1 /*
2 Distance Between Points Filter(s)
3
4 Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
19
20 */
21 #include "defs.h"
22 #include "filterdefs.h"
23 #include "grtcirc.h"
24
25 #if FILTERS_ENABLED
26
27 #ifndef M_PI
28 # define M_PI 3.14159265358979323846
29 #endif
30
31 static route_head *cur_rte = NULL;
32
33 static double pos_dist;
34 static double max_diff_time;
35 static char *distopt = NULL;
36 static char *timeopt = NULL;
37 static char *purge_duplicates = NULL;
38 static int check_time;
39
40 typedef struct {
41 double distance;
42 } extra_data;
43
44 static
45 arglist_t position_args[] = {
46 {
47 "distance", &distopt, "Maximum positional distance",
48 NULL, ARGTYPE_FLOAT | ARGTYPE_REQUIRED, ARG_NOMINMAX
49 },
50 {
51 "all", &purge_duplicates,
52 "Suppress all points close to other points",
53 NULL, ARGTYPE_BOOL, ARG_NOMINMAX
54 },
55 {
56 "time", &timeopt, "Maximum time in seconds beetween two points",
57 NULL, ARGTYPE_FLOAT | ARGTYPE_REQUIRED, ARG_NOMINMAX
58 },
59 ARG_TERMINATOR
60 };
61
62 static double
gc_distance(double lat1,double lon1,double lat2,double lon2)63 gc_distance(double lat1, double lon1, double lat2, double lon2)
64 {
65 return gcdist(
66 RAD(lat1),
67 RAD(lon1),
68 RAD(lat2),
69 RAD(lon2)
70 );
71 }
72
73 /* tear through a waypoint queue, processing points by distance */
74 static void
position_runqueue(queue * q,int nelems,int qtype)75 position_runqueue(queue *q, int nelems, int qtype)
76 {
77 queue * elem, * tmp;
78 waypoint ** comp;
79 int * qlist;
80 double dist, diff_time;
81 int i = 0, j, anyitem;
82
83 comp = (waypoint **) xcalloc(nelems, sizeof(*comp));
84 qlist = (int *) xcalloc(nelems, sizeof(*qlist));
85
86 QUEUE_FOR_EACH(q, elem, tmp) {
87 comp[i] = (waypoint *)elem;
88 qlist[i] = 0;
89 i++;
90 }
91
92 for (i = 0 ; i < nelems ; i++) {
93 anyitem = 0;
94
95 if (!qlist[i]) {
96 for (j = i + 1 ; j < nelems ; j++) {
97 if (!qlist[j]) {
98 dist = gc_distance(comp[j]->latitude,
99 comp[j]->longitude,
100 comp[i]->latitude,
101 comp[i]->longitude);
102
103 /* convert radians to integer feet */
104 dist = (int)(5280*radtomiles(dist));
105 diff_time = fabs(waypt_time(comp[i]) - waypt_time(comp[j]));
106
107 if (dist <= pos_dist) {
108 if (check_time && diff_time >= max_diff_time) {
109 continue;
110 }
111
112 qlist[j] = 1;
113 switch (qtype) {
114 case wptdata:
115 waypt_del(comp[j]);
116 waypt_free(comp[j]);
117 break;
118 case trkdata:
119 track_del_wpt(cur_rte, comp[j]);
120 break;
121 case rtedata:
122 route_del_wpt(cur_rte, comp[j]);
123 break;
124 default:
125 break;
126 }
127 anyitem = 1;
128 }
129 }
130 }
131
132 if (anyitem && !!purge_duplicates) {
133 switch (qtype) {
134 case wptdata:
135 waypt_del(comp[i]);
136 break;
137 case trkdata:
138 track_del_wpt(cur_rte, comp[i]);
139 break;
140 case rtedata:
141 route_del_wpt(cur_rte, comp[i]);
142 break;
143 default:
144 break;
145 }
146 waypt_free(comp[i]);
147 }
148 }
149 }
150
151 if (comp) {
152 xfree(comp);
153 }
154
155 if (qlist) {
156 xfree(qlist);
157 }
158 }
159
160 static void
position_process_route(const route_head * rh)161 position_process_route(const route_head * rh)
162 {
163 int i = rh->rte_waypt_ct;
164
165 if (i) {
166 cur_rte = (route_head *)rh;
167 position_runqueue((queue *)&rh->waypoint_list, i, rtedata);
168 cur_rte = NULL;
169 }
170
171 }
172
173 static void
position_noop_w(const waypoint * w)174 position_noop_w(const waypoint *w)
175 {
176 }
177
178 static void
position_noop_t(const route_head * h)179 position_noop_t(const route_head *h)
180 {
181 }
182
position_process(void)183 void position_process(void)
184 {
185 int i = waypt_count();
186
187 if (i) {
188 position_runqueue(&waypt_head, i, wptdata);
189 }
190
191 route_disp_all(position_process_route, position_noop_t, position_noop_w);
192 track_disp_all(position_process_route, position_noop_t, position_noop_w);
193 }
194
195 void
position_init(const char * args)196 position_init(const char *args)
197 {
198 char *fm;
199
200 pos_dist = 0;
201 max_diff_time = 0;
202 check_time = 0;
203
204 if (distopt) {
205 pos_dist = strtod(distopt, &fm);
206
207 if ((*fm == 'm') || (*fm == 'M')) {
208 /* distance is meters */
209 pos_dist *= 3.2802;
210 }
211 }
212
213 if (timeopt) {
214 check_time = 1;
215 max_diff_time = strtod(timeopt, &fm);
216 }
217 }
218
219 void
position_deinit(void)220 position_deinit(void)
221 {
222 }
223
224 filter_vecs_t position_vecs = {
225 position_init,
226 position_process,
227 position_deinit,
228 NULL,
229 position_args
230 };
231
232 #endif // FILTERS_ENABLED
233