From dfe65aacd4dd11d3679c8566d1b3fe3b1947a36e Mon Sep 17 00:00:00 2001 From: Gergely Koloszar Date: Sat, 18 Oct 2025 21:00:00 +0200 Subject: [PATCH 1/5] Rewrite and document latlon tool source - incorrect argument count has been fixed - The code has been split up into smaller units to be more understandable - sources were put in comments to help find resources for the algorithm - output is now in meters --- helpers/latlon.c | 96 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/helpers/latlon.c b/helpers/latlon.c index 4c1788a..ea9bc1f 100644 --- a/helpers/latlon.c +++ b/helpers/latlon.c @@ -1,36 +1,74 @@ -#include -#include +// This small program computes the distance between two points on the Earths +// surface. The algorithm used for computing is called haversine formula. +// Source for the algorithm can be found here: +// https://en.wikipedia.org/wiki/Haversine_formula + #include +#include +#include -#define R 6371 -#define TO_RAD (3.1415926536 / 180) -double dist(double th1, double ph1, double th2, double ph2) -{ - double dx, dy, dz; - ph1 -= ph2; - ph1 *= TO_RAD, th1 *= TO_RAD, th2 *= TO_RAD; +// Earths radius in meters +#define RADIUS ((12756L / 2.0L) * 1000L) - dz = sin(th1) - sin(th2); - dx = cos(ph1) * cos(th1) - cos(th2); - dy = sin(ph1) * cos(th1); - return asin(sqrt(dx * dx + dy * dy + dz * dz) / 2) * 2 * R; +// PI natural constant +#define PI 3.1415926536L + +// coordinates struct for storing points +struct Coordinate { + double latitude; + double longitude; +}; + +/** + * @brief Calculates a radian value from an angle + */ +double radian_from(const double angle) { + return (angle * PI) / 180; } -int main(int argc, const char * argv[]) -{ - if(argc < 5 || argc > 5){ - return 1; - } - float coords[4]; - for(int i=1;i<5;i++){ - if(atof(argv[i]) == 0){ - return 1; - } - coords[i] = atof(argv[i]); - } - - double d = dist(coords[1], coords[2], coords[3], coords[4]); - printf("%.1f\n", d); +/** + * @brief Calculate the haversine function from an angle in radian + */ +double haversine(const double angle) { return ((1.0L - cos(angle)) / 2); } - return 0; +/** + * @brief Calculate the distance between two coordinates + */ +double great_circle_distance(const struct Coordinate a, + const struct Coordinate b) { + + // calculate longitude and latitude differences + struct Coordinate diff_coord = { + .longitude = a.longitude - b.longitude, + .latitude = a.latitude - b.latitude, + }; + + // calculate haversine(theta) value, where theta is the angle between the + // two coordinates + double hav_theta = haversine(diff_coord.latitude) + + cos(a.latitude) * cos(b.latitude) * haversine(diff_coord.longitude); + + // calculate distance from radius, and haversine(theta) values + double distance = 2 * RADIUS * asin(sqrt(hav_theta)); + + return distance; +} + +int main(int argc, const char* argv[]) { + if (argc < 5 || argc > 5) { + return 1; + } + + const struct Coordinate a = { + .latitude = radian_from(atof(argv[1])), + .longitude = radian_from(atof(argv[2])), + }; + const struct Coordinate b = { + .latitude = radian_from(atof(argv[3])), + .longitude = radian_from(atof(argv[4])), + }; + + printf("%.1f\n", great_circle_distance(a, b)); + + return 0; } From 67b055905859213c235a750ef3800c9c76af13db Mon Sep 17 00:00:00 2001 From: Gergely Koloszar Date: Sat, 18 Oct 2025 21:13:15 +0200 Subject: [PATCH 2/5] Add makefile, and move latlon to a 'tools' directory --- helpers/tools/Makefile | 24 ++++++++++++++++++++++++ helpers/{ => tools}/latlon.c | 0 2 files changed, 24 insertions(+) create mode 100644 helpers/tools/Makefile rename helpers/{ => tools}/latlon.c (100%) diff --git a/helpers/tools/Makefile b/helpers/tools/Makefile new file mode 100644 index 0000000..38914fd --- /dev/null +++ b/helpers/tools/Makefile @@ -0,0 +1,24 @@ +bin := latlon + +CC = gcc + +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -Wpedantic +CFLAGS += -std=c23 +CFLAGS += -O3 + +LDFLAGS += -lm + +PREFIX ?= $(HOME)/.local/share/dzgui + +all: $(bin) + +install: $(bin) + install -Dm 755 $(bin) $(PREFIX) + +$(bin): latlon.c + $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + +clean: + rm -f $(bin) diff --git a/helpers/latlon.c b/helpers/tools/latlon.c similarity index 100% rename from helpers/latlon.c rename to helpers/tools/latlon.c From e73617c2f43a836724a3d0126e43f8b20299a2c3 Mon Sep 17 00:00:00 2001 From: Gergely Koloszar Date: Sat, 18 Oct 2025 21:14:39 +0200 Subject: [PATCH 3/5] Add gitignore for latlon --- helpers/tools/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 helpers/tools/.gitignore diff --git a/helpers/tools/.gitignore b/helpers/tools/.gitignore new file mode 100644 index 0000000..d8b458e --- /dev/null +++ b/helpers/tools/.gitignore @@ -0,0 +1 @@ +latlon From 21d4601e41c4af2e15bb66b1a8c7a3975216fb19 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:01:46 +0900 Subject: [PATCH 4/5] chore: add comments about pretty printing --- helpers/tools/latlon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helpers/tools/latlon.c b/helpers/tools/latlon.c index ea9bc1f..3d9492e 100644 --- a/helpers/tools/latlon.c +++ b/helpers/tools/latlon.c @@ -7,7 +7,8 @@ #include #include -// Earths radius in meters +// Earth's radius in meters. To pretty-print the result for the end-user, it is +// recommended to divide the result by 1,000 and round it. #define RADIUS ((12756L / 2.0L) * 1000L) // PI natural constant From a419aad160102359d804ff47e412703074540b0c Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:05:21 +0900 Subject: [PATCH 5/5] chore: move comments --- helpers/tools/latlon.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/helpers/tools/latlon.c b/helpers/tools/latlon.c index 3d9492e..a734f31 100644 --- a/helpers/tools/latlon.c +++ b/helpers/tools/latlon.c @@ -7,8 +7,7 @@ #include #include -// Earth's radius in meters. To pretty-print the result for the end-user, it is -// recommended to divide the result by 1,000 and round it. +// Earth's radius in meters. #define RADIUS ((12756L / 2.0L) * 1000L) // PI natural constant @@ -69,6 +68,9 @@ int main(int argc, const char* argv[]) { .longitude = radian_from(atof(argv[4])), }; + // Returns the distance in meters. + // To pretty-print the result in a consumer of this module, it is + // recommended to divide the result by 1,000 and round it. printf("%.1f\n", great_circle_distance(a, b)); return 0;