Thread: [Gpsbabel-code] more sort filter options
Brought to you by:
robertl
From: Paul F. <pg...@fo...> - 2006-08-14 22:10:04
|
hello -- today i needed to sort a list of waypoints by lat/lon, and was a little surprised that gpsbabel doesn't already do this. (unless i missed it. i hope not.) this patch implements sorting by latitude major, longitude minor, or vice versa. since my reason for sorting was also to eliminated duplicate waypoints, i also implemented the effective equivalent of "sort -u" -- if the "unique" option is present along with a sort mode, then items will be made unique vis a vis that "key", after sorting. this is against 1.3.0 -- my cvs repository no longer works, and i think i recall hearing that gpsbabel has switched to svn. hopefully sort.c hasn't changed much. of course, this also means i didn't have source for the doc to update. feel free to tell me to resubmit properly, if you're so inclined... :-) paul diff -ru gpsbabel-1.3.0.orig/sort.c gpsbabel-1.3.0/sort.c --- gpsbabel-1.3.0.orig/sort.c Fri May 12 17:43:07 2006 +++ gpsbabel-1.3.0/sort.c Mon Aug 14 17:57:12 2006 @@ -28,12 +28,15 @@ sm_gcid, sm_shortname, sm_description, - sm_time + sm_time, + sm_latlon, + sm_lonlat } sort_mode_; sort_mode_ sort_mode = sm_shortname; /* How are we sorting these? */ static char *opt_sm_gcid, *opt_sm_shortname, *opt_sm_description, *opt_sm_time; +static char *opt_sm_latlon, *opt_sm_lonlat, *opt_sm_uniq; static arglist_t sort_args[] = { @@ -45,6 +48,12 @@ NULL, ARGTYPE_BOOL, ARG_NOMINMAX }, {"time", &opt_sm_time, "Sort by time", NULL, ARGTYPE_BOOL, ARG_NOMINMAX }, + {"latlon", &opt_sm_latlon, "Sort by latitude and longitude", + NULL, ARGTYPE_BOOL, ARG_NOMINMAX }, + {"lonlat", &opt_sm_lonlat, "Sort by longitude and latitude", + NULL, ARGTYPE_BOOL, ARG_NOMINMAX }, + {"unique", &opt_sm_uniq, "After sorting, eliminate duplicates", + NULL, ARGTYPE_BOOL, ARG_NOMINMAX }, ARG_TERMINATOR }; @@ -54,11 +63,31 @@ const waypoint *x1 = *(waypoint **)a; const waypoint *x2 = *(waypoint **)b; + switch (sort_mode) { - case sm_gcid: return x1->gc_data.id > x2->gc_data.id; + case sm_gcid: return x1->gc_data.id - x2->gc_data.id; case sm_shortname: return strcmp (x1->shortname, x2->shortname); case sm_description: return strcmp (x1->description, x2->description); - case sm_time: return x1->creation_time > x2->creation_time; + case sm_time: return x1->creation_time - x2->creation_time; + case sm_latlon: + if (x1->latitude == x2->latitude) { + if (x1->longitude == x2->longitude) return 0; + else if (x1->longitude < x2->longitude) return -1; + else return 1; + } + else if (x1->latitude < x2->latitude) return -1; + else return 1; + break; + + case sm_lonlat: + if (x1->longitude == x2->longitude) { + if (x1->latitude == x2->latitude) return 0; + else if (x1->latitude < x2->latitude) return -1; + else return 1; + } + else if (x1->longitude < x2->longitude) return -1; + else return 1; + break; default: abort(); return 0; /* Internal caller error. */ } } @@ -68,6 +97,7 @@ { queue * elem, * tmp; waypoint ** comp; + waypoint *wprev = 0; int i = 0, wc; wc = waypt_count(); @@ -91,6 +121,22 @@ if (comp) xfree(comp); + + if (!opt_sm_uniq) + return; + + /* find duplicate neighbors */ + QUEUE_FOR_EACH(&waypt_head, elem, tmp) { + if (!wprev) { + wprev = (waypoint *)elem; + continue; + } + if (sort_comp(&wprev, &elem) == 0) { + waypt_del((waypoint *)elem); + } else { + wprev = (waypoint *)elem; + } + } } void @@ -104,6 +150,11 @@ sort_mode = sm_description; if (opt_sm_time) sort_mode = sm_time; + if (opt_sm_latlon) + sort_mode = sm_latlon; + if (opt_sm_lonlat) + sort_mode = sm_lonlat; + } filter_vecs_t sort_vecs = { =--------------------- paul fox, pg...@fo... (arlington, ma, where it's 74.7 degrees) |
From: Robert L. <rob...@us...> - 2006-08-21 20:47:19
|
Paul Fox wrote: > today i needed to sort a list of waypoints by lat/lon, and was > a little surprised that gpsbabel doesn't already do this. (unless > i missed it. i hope not.) No, it's not there. I can't recall anyone ever asking for it. > this patch implements sorting by latitude major, longitude minor, or > vice versa. I'm unfamiliar with that term. Can you explain, please? > since my reason for sorting was also to eliminated duplicate waypoints, > i also implemented the effective equivalent of "sort -u" -- if the > "unique" option is present along with a sort mode, then items will be > made unique vis a vis that "key", after sorting. We already have filter that does that. In light of the duplicate filter (that can work by position or name) is this needed? > this is against 1.3.0 -- my cvs repository no longer works, and i > think i recall hearing that gpsbabel has switched to svn. hopefully No, we're still on CVS. I don't mind CVS; it's Sourceforge's implementation of CVS that's making me crazy. > + case sm_latlon: > + if (x1->latitude == x2->latitude) { > + if (x1->longitude == x2->longitude) return 0; > + else if (x1->longitude < x2->longitude) return -1; > + else return 1; > + } > + else if (x1->latitude < x2->latitude) return -1; > + else return 1; > + break; > + > + case sm_lonlat: > + if (x1->longitude == x2->longitude) { > + if (x1->latitude == x2->latitude) return 0; > + else if (x1->latitude < x2->latitude) return -1; > + else return 1; > + } > + else if (x1->longitude < x2->longitude) return -1; > + else return 1; > + break; How well does the above approach work if sorting by longitudes near the prime meridian where things wrap from positive to negative? Is testing numeric quality of floats in this way safe? Isn't the prevailing approach something like if abs float1 - float2 < some_crazy_small_number RJL |
From: Paul F. <pg...@fo...> - 2006-08-22 12:02:49
|
robert wrote: > Paul Fox wrote: > > > today i needed to sort a list of waypoints by lat/lon, and was > > a little surprised that gpsbabel doesn't already do this. (unless > > i missed it. i hope not.) > > No, it's not there. I can't recall anyone ever asking for it. > > > this patch implements sorting by latitude major, longitude minor, or > > vice versa. > > I'm unfamiliar with that term. Can you explain, please? i'm not sure where i got the term -- it simply means to sort first by latitude, then by longitude (for equal latitudes). > > > since my reason for sorting was also to eliminated duplicate waypoints, > > i also implemented the effective equivalent of "sort -u" -- if the > > "unique" option is present along with a sort mode, then items will be > > made unique vis a vis that "key", after sorting. > > We already have filter that does that. In light of the duplicate > filter (that can work by position or name) is this needed? i wasn't aware of the duplicate filter before -- it solves one of my immediate problems. it certainly eliminates much of my need for this patch. > > > this is against 1.3.0 -- my cvs repository no longer works, and i > > think i recall hearing that gpsbabel has switched to svn. hopefully > > No, we're still on CVS. I don't mind CVS; it's Sourceforge's > implementation of CVS that's making me crazy. must have confused it with a different project. i'll fetch a new tree, then. > > > + case sm_latlon: > > + if (x1->latitude == x2->latitude) { > > + if (x1->longitude == x2->longitude) return 0; > > + else if (x1->longitude < x2->longitude) return -1; > > + else return 1; > > + } > > + else if (x1->latitude < x2->latitude) return -1; > > + else return 1; > > + break; > > + > > + case sm_lonlat: > > + if (x1->longitude == x2->longitude) { > > + if (x1->latitude == x2->latitude) return 0; > > + else if (x1->latitude < x2->latitude) return -1; > > + else return 1; > > + } > > + else if (x1->longitude < x2->longitude) return -1; > > + else return 1; > > + break; > > How well does the above approach work if sorting by longitudes near > the prime meridian where things wrap from positive to negative? ah. you got me. it doesn't work at all, i'd guess. i'm guessing gpsbabel has some set of rules for dealing with this case, and they'd have to be applied here. my interest is road navigation, so the prime meridian doesn't come up very often. > > Is testing numeric quality of floats in this way safe? Isn't the > prevailing approach something like > > if abs float1 - float2 < some_crazy_small_number i suppose. okay, it's official. this patch is junk. actually, that's not quite true. there are still two lines of interest, i believe. in the comparison function, the gcid and time comparisons yield a boolean, rather than -1 / 0 / +1 as they should for qsort. i have trouble believing that this will always give a correct sort: switch (sort_mode) { - case sm_gcid: return x1->gc_data.id > x2->gc_data.id; + case sm_gcid: return x1->gc_data.id - x2->gc_data.id; case sm_shortname: return strcmp (x1->shortname, x2->shortname); case sm_description: return strcmp (x1->description, x2->description); - case sm_time: return x1->creation_time > x2->creation_time; + case sm_time: return x1->creation_time - x2->creation_time; paul =--------------------- paul fox, pg...@fo... (arlington, ma, where it's 58.6 degrees) |
From: Robert L. <rob...@us...> - 2006-08-22 15:39:44
|
> > How well does the above approach work if sorting by longitudes near > > the prime meridian where things wrap from positive to negative? > > ah. you got me. it doesn't work at all, i'd guess. i'm guessing That alone would probably not be a deal breaker. Heck, I'm pretty sure there are other related problem areas for us. But since the functionality you wanted is already there, I agree that doing it again here is probably bad. > have to be applied here. my interest is road navigation, so the prime > meridian doesn't come up very often. For navigators in Europe, it would be more important. :-) > actually, that's not quite true. there are still two lines of > interest, i believe. in the comparison function, the gcid and time > comparisons yield a boolean, rather than -1 / 0 / +1 as they should I'd noticed that (the dangers of unrelated fixes in a patch for review...) and agree. I've commited that. Thanx, RJL |