|
|
1 | /** |
|
|
2 | * ZANavi, Zoff Android Navigation system. |
|
|
3 | * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc> |
|
|
4 | * |
|
|
5 | * This program is free software; you can redistribute it and/or |
|
|
6 | * modify it under the terms of the GNU General Public License |
|
|
7 | * version 2 as published by the Free Software Foundation. |
|
|
8 | * |
|
|
9 | * This program is distributed in the hope that it will be useful, |
|
|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
12 | * GNU General Public License for more details. |
|
|
13 | * |
|
|
14 | * You should have received a copy of the GNU General Public License |
|
|
15 | * along with this program; if not, write to the |
|
|
16 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
|
17 | * Boston, MA 02110-1301, USA. |
|
|
18 | */ |
|
|
19 | |
1 | /** |
20 | /** |
2 | * Navit, a modular navigation system. |
21 | * Navit, a modular navigation system. |
3 | * Copyright (C) 2005-2008 Navit Team |
22 | * Copyright (C) 2005-2008 Navit Team |
4 | * |
23 | * |
5 | * This program is free software; you can redistribute it and/or |
24 | * This program is free software; you can redistribute it and/or |
… | |
… | |
30 | #include "item.h" |
49 | #include "item.h" |
31 | #include "map.h" |
50 | #include "map.h" |
32 | #include "transform.h" |
51 | #include "transform.h" |
33 | #include "projection.h" |
52 | #include "projection.h" |
34 | #include "point.h" |
53 | #include "point.h" |
|
|
54 | #include "navit.h" |
35 | |
55 | |
36 | #define POST_SHIFT 8 |
56 | #define POST_SHIFT 8 |
37 | |
|
|
38 | |
57 | |
39 | #ifdef ENABLE_ROLL |
58 | #ifdef ENABLE_ROLL |
40 | #define HOG(t) ((t).hog) |
59 | #define HOG(t) ((t).hog) |
41 | #else |
60 | #else |
42 | #define HOG(t) 0 |
61 | #define HOG(t) 0 |
43 | #endif |
62 | #endif |
44 | |
63 | |
45 | static void |
|
|
46 | transform_set_screen_dist(struct transformation *t, int dist) |
64 | static void transform_set_screen_dist(struct transformation *t, int dist) |
47 | { |
65 | { |
48 | t->screen_dist=dist; |
66 | t->screen_dist = dist; |
49 | t->xscale3d=dist; |
67 | t->xscale3d = dist; |
50 | t->yscale3d=dist; |
68 | t->yscale3d = dist; |
51 | t->wscale3d=dist << POST_SHIFT; |
69 | t->wscale3d = dist << POST_SHIFT; |
52 | } |
70 | } |
53 | |
71 | |
54 | static void |
|
|
55 | transform_setup_matrix(struct transformation *t) |
72 | static void transform_setup_matrix(struct transformation *t) |
56 | { |
73 | { |
57 | navit_float det; |
74 | navit_float det; |
58 | navit_float fac; |
75 | navit_float fac; |
59 | navit_float yawc=navit_cos(-M_PI*t->yaw/180); |
76 | navit_float yawc = navit_cos(-M_PI * t->yaw / 180); |
60 | navit_float yaws=navit_sin(-M_PI*t->yaw/180); |
77 | navit_float yaws = navit_sin(-M_PI * t->yaw / 180); |
61 | navit_float pitchc=navit_cos(-M_PI*t->pitch/180); |
78 | navit_float pitchc = navit_cos(-M_PI * t->pitch / 180); |
62 | navit_float pitchs=navit_sin(-M_PI*t->pitch/180); |
79 | navit_float pitchs = navit_sin(-M_PI * t->pitch / 180); |
63 | #ifdef ENABLE_ROLL |
80 | #ifdef ENABLE_ROLL |
64 | navit_float rollc=navit_cos(M_PI*t->roll/180); |
81 | navit_float rollc=navit_cos(M_PI*t->roll/180); |
65 | navit_float rolls=navit_sin(M_PI*t->roll/180); |
82 | navit_float rolls=navit_sin(M_PI*t->roll/180); |
66 | #else |
83 | #else |
67 | navit_float rollc=1; |
84 | navit_float rollc = 1; |
68 | navit_float rolls=0; |
85 | navit_float rolls = 0; |
69 | #endif |
86 | #endif |
70 | |
87 | |
71 | int scale=t->scale; |
88 | int scale = t->scale; |
72 | int order_dir=-1; |
89 | int order_dir = -1; |
73 | |
90 | |
74 | //dbg(1,"yaw=%d pitch=%d center=0x%x,0x%x\n", t->yaw, t->pitch, t->map_center.x, t->map_center.y); |
91 | //dbg(1,"yaw=%d pitch=%d center=0x%x,0x%x\n", t->yaw, t->pitch, t->map_center.x, t->map_center.y); |
75 | t->znear=1 << POST_SHIFT; |
92 | t->znear = 1 << POST_SHIFT; |
76 | t->zfar=300*t->znear; |
93 | t->zfar = 300 * t->znear; |
77 | t->scale_shift=0; |
94 | t->scale_shift = 0; |
78 | t->order=t->order_base; |
95 | t->order = t->order_base; |
|
|
96 | |
79 | if (t->scale >= 1) { |
97 | if (t->scale >= 1) |
|
|
98 | { |
80 | scale=t->scale; |
99 | scale = t->scale; |
81 | } else { |
100 | } |
|
|
101 | else |
|
|
102 | { |
82 | scale=1.0/t->scale; |
103 | scale = 1.0 / t->scale; |
83 | order_dir=1; |
104 | order_dir = 1; |
84 | } |
105 | } |
|
|
106 | |
85 | while (scale > 1) { |
107 | while (scale > 1) |
|
|
108 | { |
86 | if (order_dir < 0) |
109 | if (order_dir < 0) |
87 | t->scale_shift++; |
110 | t->scale_shift++; |
88 | t->order+=order_dir; |
111 | t->order += order_dir; |
89 | scale >>= 1; |
112 | scale >>= 1; |
90 | } |
113 | } |
|
|
114 | |
91 | fac=(1 << POST_SHIFT) * (1 << t->scale_shift) / t->scale; |
115 | fac = (1 << POST_SHIFT) * (1 << t->scale_shift) / t->scale; |
92 | //dbg(1,"scale_shift=%d order=%d scale=%f fac=%f\n", t->scale_shift, t->order,t->scale,fac); |
116 | //dbg(1,"scale_shift=%d order=%d scale=%f fac=%f\n", t->scale_shift, t->order,t->scale,fac); |
93 | |
117 | |
94 | t->m00=rollc*yawc*fac; |
118 | t->m00 = rollc * yawc * fac; |
95 | t->m01=rollc*yaws*fac; |
119 | t->m01 = rollc * yaws * fac; |
96 | t->m02=-rolls*fac; |
120 | t->m02 = -rolls * fac; |
97 | t->m10=(pitchs*rolls*yawc-pitchc*yaws)*(-fac); |
121 | t->m10 = (pitchs * rolls * yawc - pitchc * yaws) * (-fac); |
98 | t->m11=(pitchs*rolls*yaws+pitchc*yawc)*(-fac); |
122 | t->m11 = (pitchs * rolls * yaws + pitchc * yawc) * (-fac); |
99 | t->m12=pitchs*rollc*(-fac); |
123 | t->m12 = pitchs * rollc * (-fac); |
100 | t->m20=(pitchc*rolls*yawc+pitchs*yaws)*fac; |
124 | t->m20 = (pitchc * rolls * yawc + pitchs * yaws) * fac; |
101 | t->m21=(pitchc*rolls*yaws-pitchs*yawc)*fac; |
125 | t->m21 = (pitchc * rolls * yaws - pitchs * yawc) * fac; |
102 | t->m22=pitchc*rollc*fac; |
126 | t->m22 = pitchc * rollc * fac; |
103 | |
127 | |
104 | t->offx=t->screen_center.x; |
128 | t->offx = t->screen_center.x; |
105 | t->offy=t->screen_center.y; |
129 | t->offy = t->screen_center.y; |
106 | if (t->pitch) |
130 | if (t->pitch) |
107 | { |
131 | { |
108 | t->ddd=1; |
132 | t->ddd = 1; |
109 | t->offz=t->screen_dist; |
133 | t->offz = t->screen_dist; |
110 | //dbg(1,"near %d far %d\n",t->znear,t->zfar); |
134 | //dbg(1,"near %d far %d\n",t->znear,t->zfar); |
111 | t->xscale=t->xscale3d; |
135 | t->xscale = t->xscale3d; |
112 | t->yscale=t->yscale3d; |
136 | t->yscale = t->yscale3d; |
113 | t->wscale=t->wscale3d; |
137 | t->wscale = t->wscale3d; |
114 | } else { |
138 | } |
|
|
139 | else |
|
|
140 | { |
115 | t->ddd=0; |
141 | t->ddd = 0; |
116 | t->offz=0; |
142 | t->offz = 0; |
117 | t->xscale=1; |
143 | t->xscale = 1; |
118 | t->yscale=1; |
144 | t->yscale = 1; |
119 | t->wscale=1; |
145 | t->wscale = 1; |
120 | } |
146 | } |
121 | det=(navit_float)t->m00*(navit_float)t->m11*(navit_float)t->m22+ |
147 | det = (navit_float) t->m00 * (navit_float) t->m11 * (navit_float) t->m22 + (navit_float) t->m01 * (navit_float) t->m12 * (navit_float) t->m20 + (navit_float) t->m02 * (navit_float) t->m10 * (navit_float) t->m21 - (navit_float) t->m02 * (navit_float) t->m11 * (navit_float) t->m20 - (navit_float) t->m01 * (navit_float) t->m10 * (navit_float) t->m22 - (navit_float) t->m00 * (navit_float) t->m12 * (navit_float) t->m21; |
122 | (navit_float)t->m01*(navit_float)t->m12*(navit_float)t->m20+ |
|
|
123 | (navit_float)t->m02*(navit_float)t->m10*(navit_float)t->m21- |
|
|
124 | (navit_float)t->m02*(navit_float)t->m11*(navit_float)t->m20- |
|
|
125 | (navit_float)t->m01*(navit_float)t->m10*(navit_float)t->m22- |
|
|
126 | (navit_float)t->m00*(navit_float)t->m12*(navit_float)t->m21; |
|
|
127 | |
148 | |
128 | t->im00=(t->m11*t->m22-t->m12*t->m21)/det; |
149 | t->im00 = (t->m11 * t->m22 - t->m12 * t->m21) / det; |
129 | t->im01=(t->m02*t->m21-t->m01*t->m22)/det; |
150 | t->im01 = (t->m02 * t->m21 - t->m01 * t->m22) / det; |
130 | t->im02=(t->m01*t->m12-t->m02*t->m11)/det; |
151 | t->im02 = (t->m01 * t->m12 - t->m02 * t->m11) / det; |
131 | t->im10=(t->m12*t->m20-t->m10*t->m22)/det; |
152 | t->im10 = (t->m12 * t->m20 - t->m10 * t->m22) / det; |
132 | t->im11=(t->m00*t->m22-t->m02*t->m20)/det; |
153 | t->im11 = (t->m00 * t->m22 - t->m02 * t->m20) / det; |
133 | t->im12=(t->m02*t->m10-t->m00*t->m12)/det; |
154 | t->im12 = (t->m02 * t->m10 - t->m00 * t->m12) / det; |
134 | t->im20=(t->m10*t->m21-t->m11*t->m20)/det; |
155 | t->im20 = (t->m10 * t->m21 - t->m11 * t->m20) / det; |
135 | t->im21=(t->m01*t->m20-t->m00*t->m21)/det; |
156 | t->im21 = (t->m01 * t->m20 - t->m00 * t->m21) / det; |
136 | t->im22=(t->m00*t->m11-t->m01*t->m10)/det; |
157 | t->im22 = (t->m00 * t->m11 - t->m01 * t->m10) / det; |
137 | } |
158 | } |
138 | |
159 | |
139 | struct transformation * |
160 | struct transformation * |
140 | transform_new(void) |
161 | transform_new(void) |
141 | { |
162 | { |
142 | struct transformation *this_; |
163 | struct transformation *this_; |
143 | |
164 | |
144 | this_=g_new0(struct transformation, 1); |
165 | this_=g_new0(struct transformation, 1); |
145 | transform_set_screen_dist(this_, 100); |
166 | transform_set_screen_dist(this_, 100); |
146 | this_->order_base=14; |
167 | this_->order_base = 14; |
147 | #if 0 |
168 | #if 0 |
148 | this_->pitch=20; |
169 | this_->pitch=20; |
149 | #endif |
170 | #endif |
150 | #if 0 |
171 | #if 0 |
151 | this_->roll=30; |
172 | this_->roll=30; |
… | |
… | |
153 | #endif |
174 | #endif |
154 | transform_setup_matrix(this_); |
175 | transform_setup_matrix(this_); |
155 | return this_; |
176 | return this_; |
156 | } |
177 | } |
157 | |
178 | |
158 | int |
|
|
159 | transform_get_hog(struct transformation *this_) |
179 | int transform_get_hog(struct transformation *this_) |
160 | { |
180 | { |
161 | return HOG(*this_); |
181 | return HOG(*this_); |
162 | } |
182 | } |
163 | |
183 | |
164 | void |
|
|
165 | transform_set_hog(struct transformation *this_, int hog) |
184 | void transform_set_hog(struct transformation *this_, int hog) |
166 | { |
185 | { |
167 | #ifdef ENABLE_ROLL |
186 | #ifdef ENABLE_ROLL |
168 | this_->hog=hog; |
187 | this_->hog=hog; |
169 | #else |
188 | #else |
170 | dbg(0,"not supported\n"); |
189 | dbg(0, "not supported\n"); |
171 | #endif |
190 | #endif |
172 | |
191 | |
173 | } |
192 | } |
174 | |
193 | |
175 | int |
|
|
176 | transform_get_attr(struct transformation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter) |
194 | int transform_get_attr(struct transformation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter) |
177 | { |
195 | { |
178 | switch (type) { |
196 | switch (type) |
|
|
197 | { |
179 | #ifdef ENABLE_ROLL |
198 | #ifdef ENABLE_ROLL |
180 | case attr_hog: |
199 | case attr_hog: |
181 | attr->u.num=this_->hog; |
200 | attr->u.num=this_->hog; |
182 | break; |
201 | break; |
183 | #endif |
202 | #endif |
184 | default: |
203 | default: |
185 | return 0; |
204 | return 0; |
186 | } |
205 | } |
187 | attr->type=type; |
206 | attr->type = type; |
188 | return 1; |
207 | return 1; |
189 | } |
208 | } |
190 | |
209 | |
191 | int |
|
|
192 | transform_set_attr(struct transformation *this_, struct attr *attr) |
210 | int transform_set_attr(struct transformation *this_, struct attr *attr) |
193 | { |
211 | { |
194 | switch (attr->type) { |
212 | switch (attr->type) |
|
|
213 | { |
195 | #ifdef ENABLE_ROLL |
214 | #ifdef ENABLE_ROLL |
196 | case attr_hog: |
215 | case attr_hog: |
197 | this_->hog=attr->u.num; |
216 | this_->hog=attr->u.num; |
198 | return 1; |
217 | return 1; |
199 | #endif |
218 | #endif |
200 | default: |
219 | default: |
201 | return 0; |
220 | return 0; |
202 | } |
221 | } |
203 | } |
222 | } |
204 | |
223 | |
205 | int |
|
|
206 | transformation_get_order_base(struct transformation *this_) |
224 | int transformation_get_order_base(struct transformation *this_) |
207 | { |
225 | { |
208 | return this_->order_base; |
226 | return this_->order_base; |
209 | } |
227 | } |
210 | |
228 | |
211 | void |
|
|
212 | transform_set_order_base(struct transformation *this_, int order_base) |
229 | void transform_set_order_base(struct transformation *this_, int order_base) |
213 | { |
230 | { |
214 | this_->order_base=order_base; |
231 | this_->order_base = order_base; |
215 | } |
232 | } |
216 | |
|
|
217 | |
233 | |
218 | struct transformation * |
234 | struct transformation * |
219 | transform_dup(struct transformation *t) |
235 | transform_dup(struct transformation *t) |
220 | { |
236 | { |
221 | struct transformation *ret=g_new0(struct transformation, 1); |
237 | struct transformation *ret=g_new0(struct transformation, 1); |
222 | *ret=*t; |
238 | *ret = *t; |
223 | return ret; |
239 | return ret; |
224 | } |
240 | } |
225 | |
241 | |
226 | static const navit_float gar2geo_units = 360.0/(1<<24); |
242 | static const navit_float gar2geo_units = 360.0 / (1 << 24); |
227 | static const navit_float geo2gar_units = 1/(360.0/(1<<24)); |
243 | static const navit_float geo2gar_units = 1 / (360.0 / (1 << 24)); |
228 | |
244 | |
229 | void |
|
|
230 | transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g) |
245 | void transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g) |
231 | { |
246 | { |
|
|
247 | // dbg(0,"enter\n"); |
|
|
248 | |
232 | int x,y,northern,zone; |
249 | int x, y, northern, zone; |
|
|
250 | |
|
|
251 | #if 0 |
|
|
252 | int hash_id; |
|
|
253 | int s; |
|
|
254 | struct hash_entry_transform *v = NULL; |
|
|
255 | #endif |
|
|
256 | |
233 | switch (pro) { |
257 | switch (pro) |
|
|
258 | { |
234 | case projection_mg: |
259 | case projection_mg: |
|
|
260 | |
|
|
261 | #if 0 |
|
|
262 | hash_id = (long)(c->x) << 16 | (int)(c->y); |
|
|
263 | dbg(0,"h=%d\n", hash_id); |
|
|
264 | |
|
|
265 | if (global_transform_hash2) |
|
|
266 | { |
|
|
267 | s=g_hash_table_size(global_transform_hash2); |
|
|
268 | dbg(0,"size=%d\n",s); |
|
|
269 | if (s > 30000) |
|
|
270 | { |
|
|
271 | g_hash_table_remove_all(global_transform_hash2); |
|
|
272 | } |
|
|
273 | v = g_hash_table_lookup(global_transform_hash2, &hash_id); |
|
|
274 | } |
|
|
275 | |
|
|
276 | if (v != NULL) |
|
|
277 | { |
|
|
278 | if ((v->x == c->x)&&(v->y == c->y)) |
|
|
279 | { |
|
|
280 | g->lng = v->lng; |
|
|
281 | g->lat = v->lat; |
|
|
282 | } |
|
|
283 | else |
|
|
284 | { |
|
|
285 | // g->lng=c->x/6371000.0/M_PI*180; |
|
|
286 | g->lng = c->x * 0.00000899322; // simpler |
|
|
287 | g->lat = navit_atan(exp(c->y / 6371000.0)) / M_PI * 360 - 90; |
|
|
288 | |
|
|
289 | if (global_transform_hash2) |
|
|
290 | { |
|
|
291 | v = g_new0(struct hash_entry_transform,1); |
|
|
292 | v->id=hash_id; |
|
|
293 | v->x=c->x; |
|
|
294 | v->y=c->y; |
|
|
295 | v->lat=g->lat; |
|
|
296 | v->lng=g->lng; |
|
|
297 | g_hash_table_insert(global_transform_hash2, &v->id, v); |
|
|
298 | } |
|
|
299 | } |
|
|
300 | } |
|
|
301 | else |
|
|
302 | { |
|
|
303 | // g->lng=c->x/6371000.0/M_PI*180; |
|
|
304 | g->lng = c->x * 0.00000899322; // simpler |
|
|
305 | g->lat = navit_atan(exp(c->y / 6371000.0)) / M_PI * 360 - 90; |
|
|
306 | |
|
|
307 | if (global_transform_hash2) |
|
|
308 | { |
|
|
309 | v = g_new0(struct hash_entry_transform,1); |
|
|
310 | v->id=hash_id; |
|
|
311 | v->x=c->x; |
|
|
312 | v->y=c->y; |
|
|
313 | v->lat=g->lat; |
|
|
314 | v->lng=g->lng; |
|
|
315 | g_hash_table_insert(global_transform_hash2, &v->id, v); |
|
|
316 | } |
|
|
317 | } |
|
|
318 | #endif |
235 | // g->lng=c->x/6371000.0/M_PI*180; |
319 | // g->lng=c->x/6371000.0/M_PI*180; |
236 | g->lng=c->x*0.00000899322; // simpler |
320 | g->lng = c->x * 0.00000899322; // simpler |
237 | g->lat=navit_atan(exp(c->y/6371000.0))/M_PI*360-90; |
321 | g->lat = navit_atan(exp(c->y / 6371000.0)) / M_PI * 360 - 90; |
|
|
322 | |
238 | break; |
323 | break; |
239 | case projection_garmin: |
324 | case projection_garmin: |
240 | g->lng=c->x*gar2geo_units; |
325 | g->lng = c->x * gar2geo_units; |
241 | g->lat=c->y*gar2geo_units; |
326 | g->lat = c->y * gar2geo_units; |
242 | break; |
327 | break; |
243 | case projection_utm: |
328 | case projection_utm: |
244 | x=c->x; |
329 | x = c->x; |
245 | y=c->y; |
330 | y = c->y; |
246 | northern=y >= 0; |
331 | northern = y >= 0; |
247 | if (!northern) |
332 | if (!northern) |
248 | { |
333 | { |
249 | y+=10000000; |
334 | y += 10000000; |
250 | } |
335 | } |
251 | zone=(x/1000000); |
336 | zone = (x / 1000000); |
252 | x=x%1000000; |
337 | x = x % 1000000; |
253 | transform_utm_to_geo(x, y, zone, northern, g); |
338 | transform_utm_to_geo(x, y, zone, northern, g); |
254 | break; |
339 | break; |
255 | default: |
340 | default: |
256 | break; |
341 | break; |
257 | } |
342 | } |
258 | } |
343 | } |
259 | |
344 | |
260 | void |
|
|
261 | transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c) |
345 | void transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c) |
262 | { |
346 | { |
|
|
347 | // dbg(0,"enter\n"); |
|
|
348 | |
|
|
349 | #if 0 |
|
|
350 | int hash_id; |
|
|
351 | int s; |
|
|
352 | struct hash_entry_transform *v = NULL; |
|
|
353 | #endif |
|
|
354 | |
263 | switch (pro) { |
355 | switch (pro) |
|
|
356 | { |
264 | case projection_mg: |
357 | case projection_mg: |
|
|
358 | #if 0 |
|
|
359 | // check if value already in hash |
|
|
360 | hash_id = (long)(g->lat*1000000) << 16 | (int)(g->lng*1000000); |
|
|
361 | dbg(0,"h=%d\n", hash_id); |
|
|
362 | |
|
|
363 | //dbg(0,"tt 001 %f %d %f %d %lu %d\n", g->lat, (int)g->lat, g->lng, (int)g->lng, hash_id, (int)hash_id); |
|
|
364 | //dbg(0,"%lu %d\n",(long)(g->lat*1000000) << 16, (int)(g->lng*1000000)); |
|
|
365 | if (global_transform_hash) |
|
|
366 | { |
|
|
367 | //dbg(0,"tt 001.1\n"); |
|
|
368 | s=g_hash_table_size(global_transform_hash); |
|
|
369 | dbg(0,"size=%d\n",s); |
|
|
370 | if (s > 30000) |
|
|
371 | { |
|
|
372 | g_hash_table_remove_all(global_transform_hash); |
|
|
373 | } |
|
|
374 | v = g_hash_table_lookup(global_transform_hash, &hash_id); |
|
|
375 | } |
|
|
376 | |
|
|
377 | if (v != NULL) |
|
|
378 | { |
|
|
379 | if ((v->lat == g->lat)&&(v->lng == g->lng)) |
|
|
380 | { |
|
|
381 | c->x = v->x; |
|
|
382 | c->y = v->y; |
|
|
383 | } |
|
|
384 | else |
|
|
385 | { |
|
|
386 | // c->x=g->lng*6371000.0*M_PI/180; |
|
|
387 | c->x = g->lng * 111194.9266445587373; // already calced (6371000.0*M_PI/180) |
|
|
388 | // c->y=log(navit_tan(M_PI_4+g->lat*M_PI/360))*6371000.0; |
|
|
389 | c->y = log(navit_tan(M_PI_4 + g->lat * 0.008726646259971647884618)) * 6371000.0; // already calced (M_PI/360) |
|
|
390 | |
|
|
391 | if (global_transform_hash) |
|
|
392 | { |
|
|
393 | v = g_new0(struct hash_entry_transform,1); |
|
|
394 | v->id=hash_id; |
|
|
395 | v->x=c->x; |
|
|
396 | v->y=c->y; |
|
|
397 | v->lat=g->lat; |
|
|
398 | v->lng=g->lng; |
|
|
399 | g_hash_table_insert(global_transform_hash, &v->id, v); |
|
|
400 | } |
|
|
401 | } |
|
|
402 | } |
|
|
403 | else |
|
|
404 | { |
|
|
405 | // c->x=g->lng*6371000.0*M_PI/180; |
|
|
406 | c->x = g->lng * 111194.9266445587373; // already calced (6371000.0*M_PI/180) |
|
|
407 | // c->y=log(navit_tan(M_PI_4+g->lat*M_PI/360))*6371000.0; |
|
|
408 | c->y = log(navit_tan(M_PI_4 + g->lat * 0.008726646259971647884618)) * 6371000.0; // already calced (M_PI/360) |
|
|
409 | |
|
|
410 | if (global_transform_hash) |
|
|
411 | { |
|
|
412 | v = g_new0(struct hash_entry_transform,1); |
|
|
413 | v->id=hash_id; |
|
|
414 | v->x=c->x; |
|
|
415 | v->y=c->y; |
|
|
416 | v->lat=g->lat; |
|
|
417 | v->lng=g->lng; |
|
|
418 | g_hash_table_insert(global_transform_hash, &v->id, v); |
|
|
419 | } |
|
|
420 | } |
|
|
421 | #endif |
265 | // c->x=g->lng*6371000.0*M_PI/180; |
422 | // c->x=g->lng*6371000.0*M_PI/180; |
266 | c->x=g->lng*111194.9266445587373; // already calced (6371000.0*M_PI/180) |
423 | c->x = g->lng * 111194.9266445587373; // already calced (6371000.0*M_PI/180) |
267 | // c->y=log(navit_tan(M_PI_4+g->lat*M_PI/360))*6371000.0; |
424 | // c->y=log(navit_tan(M_PI_4+g->lat*M_PI/360))*6371000.0; |
268 | c->y=log(navit_tan(M_PI_4+g->lat*0.008726646259971647884618))*6371000.0; // already calced (M_PI/360) |
425 | c->y = log(navit_tan(M_PI_4 + g->lat * 0.008726646259971647884618)) * 6371000.0; // already calced (M_PI/360) |
|
|
426 | |
269 | break; |
427 | break; |
270 | case projection_garmin: |
428 | case projection_garmin: |
271 | c->x=g->lng*geo2gar_units; |
429 | c->x = g->lng * geo2gar_units; |
272 | c->y=g->lat*geo2gar_units; |
430 | c->y = g->lat * geo2gar_units; |
273 | break; |
431 | break; |
274 | default: |
432 | default: |
275 | break; |
433 | break; |
276 | } |
434 | } |
277 | } |
435 | } |
278 | |
436 | |
279 | void |
|
|
280 | transform_from_to_count(struct coord *cfrom, enum projection from, struct coord *cto, enum projection to, int count) |
437 | void transform_from_to_count(struct coord *cfrom, enum projection from, struct coord *cto, enum projection to, int count) |
281 | { |
438 | { |
282 | struct coord_geo g; |
439 | struct coord_geo g; |
283 | int i; |
440 | int i; |
284 | |
441 | |
285 | for (i = 0 ; i < count ; i++) { |
442 | for (i = 0; i < count; i++) |
|
|
443 | { |
286 | transform_to_geo(from, cfrom, &g); |
444 | transform_to_geo(from, cfrom, &g); |
287 | transform_from_geo(to, &g, cto); |
445 | transform_from_geo(to, &g, cto); |
288 | cfrom++; |
446 | cfrom++; |
289 | cto++; |
447 | cto++; |
290 | } |
448 | } |
291 | } |
449 | } |
292 | |
450 | |
293 | void |
|
|
294 | transform_from_to(struct coord *cfrom, enum projection from, struct coord *cto, enum projection to) |
451 | void transform_from_to(struct coord *cfrom, enum projection from, struct coord *cto, enum projection to) |
295 | { |
452 | { |
296 | struct coord_geo g; |
453 | struct coord_geo g; |
|
|
454 | |
297 | transform_to_geo(from, cfrom, &g); |
455 | transform_to_geo(from, cfrom, &g); |
298 | transform_from_geo(to, &g, cto); |
456 | transform_from_geo(to, &g, cto); |
299 | } |
457 | } |
300 | |
458 | |
301 | void |
|
|
302 | transform_geo_to_cart(struct coord_geo *geo, navit_float a, navit_float b, struct coord_geo_cart *cart) |
459 | void transform_geo_to_cart(struct coord_geo *geo, navit_float a, navit_float b, struct coord_geo_cart *cart) |
303 | { |
460 | { |
304 | navit_float n,ee=1-b*b/(a*a); |
461 | navit_float n, ee = 1 - b * b / (a * a); |
305 | n = a/sqrtf(1-ee*navit_sin(geo->lat)*navit_sin(geo->lat)); |
462 | n = a / sqrtf(1 - ee * navit_sin(geo->lat) * navit_sin(geo->lat)); |
306 | cart->x=n*navit_cos(geo->lat)*navit_cos(geo->lng); |
463 | cart->x = n * navit_cos(geo->lat) * navit_cos(geo->lng); |
307 | cart->y=n*navit_cos(geo->lat)*navit_sin(geo->lng); |
464 | cart->y = n * navit_cos(geo->lat) * navit_sin(geo->lng); |
308 | cart->z=n*(1-ee)*navit_sin(geo->lat); |
465 | cart->z = n * (1 - ee) * navit_sin(geo->lat); |
309 | } |
466 | } |
310 | |
467 | |
311 | void |
|
|
312 | transform_cart_to_geo(struct coord_geo_cart *cart, navit_float a, navit_float b, struct coord_geo *geo) |
468 | void transform_cart_to_geo(struct coord_geo_cart *cart, navit_float a, navit_float b, struct coord_geo *geo) |
313 | { |
469 | { |
314 | navit_float lat,lati,n,ee=1-b*b/(a*a), lng = navit_tan(cart->y/cart->x); |
470 | navit_float lat, lati, n, ee = 1 - b * b / (a * a), lng = navit_tan(cart->y / cart->x); |
315 | |
471 | |
316 | lat = navit_tan(cart->z / navit_sqrt((cart->x * cart->x) + (cart->y * cart->y))); |
472 | lat = navit_tan(cart->z / navit_sqrt((cart->x * cart->x) + (cart->y * cart->y))); |
317 | do |
473 | do |
318 | { |
474 | { |
319 | lati = lat; |
475 | lati = lat; |
320 | |
476 | |
321 | n = a / navit_sqrt(1-ee*navit_sin(lat)*navit_sin(lat)); |
477 | n = a / navit_sqrt(1 - ee * navit_sin(lat) * navit_sin(lat)); |
322 | lat = navit_atan((cart->z + ee * n * navit_sin(lat)) / navit_sqrt(cart->x * cart->x + cart->y * cart->y)); |
478 | lat = navit_atan((cart->z + ee * n * navit_sin(lat)) / navit_sqrt(cart->x * cart->x + cart->y * cart->y)); |
323 | } |
479 | } |
324 | while (fabs(lat - lati) >= 0.000000000000001); |
480 | while (fabs(lat - lati) >= 0.000000000000001); |
325 | |
481 | |
326 | geo->lng=lng/M_PI*180; |
482 | geo->lng = lng / M_PI * 180; |
327 | geo->lat=lat/M_PI*180; |
483 | geo->lat = lat / M_PI * 180; |
328 | } |
484 | } |
329 | |
485 | |
330 | |
|
|
331 | void |
|
|
332 | transform_utm_to_geo(const double UTMEasting, const double UTMNorthing, int ZoneNumber, int NorthernHemisphere, struct coord_geo *geo) |
486 | void transform_utm_to_geo(const double UTMEasting, const double UTMNorthing, int ZoneNumber, int NorthernHemisphere, struct coord_geo *geo) |
333 | { |
487 | { |
334 | //converts UTM coords to lat/long. Equations from USGS Bulletin 1532 |
488 | //converts UTM coords to lat/long. Equations from USGS Bulletin 1532 |
335 | //East Longitudes are positive, West longitudes are negative. |
489 | //East Longitudes are positive, West longitudes are negative. |
336 | //North latitudes are positive, South latitudes are negative |
490 | //North latitudes are positive, South latitudes are negative |
337 | //Lat and Long are in decimal degrees. |
491 | //Lat and Long are in decimal degrees. |
338 | //Written by Chuck Gantz- chuck.gantz@globalstar.com |
492 | //Written by Chuck Gantz- chuck.gantz@globalstar.com |
339 | |
493 | |
340 | double Lat, Long; |
494 | double Lat, Long; |
341 | double k0 = 0.99960000000000004; |
495 | double k0 = 0.99960000000000004; |
342 | double a = 6378137; |
496 | double a = 6378137; |
343 | double eccSquared = 0.0066943799999999998; |
497 | double eccSquared = 0.0066943799999999998; |
344 | double eccPrimeSquared; |
498 | double eccPrimeSquared; |
345 | double e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared)); |
499 | double e1 = (1 - sqrt(1 - eccSquared)) / (1 + sqrt(1 - eccSquared)); |
346 | double N1, T1, C1, R1, D, M; |
500 | double N1, T1, C1, R1, D, M; |
347 | double LongOrigin; |
501 | double LongOrigin; |
348 | double mu, phi1, phi1Rad; |
502 | double mu, phi1, phi1Rad; |
349 | double x, y; |
503 | double x, y; |
350 | double rad2deg = 180/M_PI; |
504 | double rad2deg = 180 / M_PI; |
351 | |
505 | |
352 | x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude |
506 | x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude |
353 | y = UTMNorthing; |
507 | y = UTMNorthing; |
354 | |
508 | |
355 | if (!NorthernHemisphere) { |
509 | if (!NorthernHemisphere) |
|
|
510 | { |
356 | y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere |
511 | y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere |
357 | } |
512 | } |
358 | |
513 | |
359 | LongOrigin = (ZoneNumber - 1)*6 - 180 + 3; //+3 puts origin in middle of zone |
514 | LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin in middle of zone |
360 | |
515 | |
361 | eccPrimeSquared = (eccSquared)/(1-eccSquared); |
516 | eccPrimeSquared = (eccSquared) / (1 - eccSquared); |
362 | |
517 | |
363 | M = y / k0; |
518 | M = y / k0; |
364 | mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256)); |
519 | mu = M / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256)); |
365 | phi1Rad = mu + (3*e1/2-27*e1*e1*e1/32)*sin(2*mu) |
520 | phi1Rad = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * sin(6 * mu); |
366 | + (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu) |
|
|
367 | +(151*e1*e1*e1/96)*sin(6*mu); |
|
|
368 | phi1 = phi1Rad*rad2deg; |
521 | phi1 = phi1Rad * rad2deg; |
369 | |
522 | |
370 | N1 = a/sqrt(1-eccSquared*sin(phi1Rad)*sin(phi1Rad)); |
523 | N1 = a / sqrt(1 - eccSquared * sin(phi1Rad) * sin(phi1Rad)); |
371 | T1 = tan(phi1Rad)*tan(phi1Rad); |
524 | T1 = tan(phi1Rad) * tan(phi1Rad); |
372 | C1 = eccPrimeSquared*cos(phi1Rad)*cos(phi1Rad); |
525 | C1 = eccPrimeSquared * cos(phi1Rad) * cos(phi1Rad); |
373 | R1 = a*(1-eccSquared)/pow(1-eccSquared*sin(phi1Rad)*sin(phi1Rad), 1.5); |
526 | R1 = a * (1 - eccSquared) / pow(1 - eccSquared * sin(phi1Rad) * sin(phi1Rad), 1.5); |
374 | D = x/(N1*k0); |
527 | D = x / (N1 * k0); |
375 | |
528 | |
376 | Lat = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24 |
529 | Lat = phi1Rad - (N1 * tan(phi1Rad) / R1) * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24 + (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) * D * D * D * D * D * D / 720); |
377 | +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720); |
|
|
378 | Lat = Lat * rad2deg; |
530 | Lat = Lat * rad2deg; |
379 | |
531 | |
380 | Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1) |
532 | Long = (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1) * D * D * D * D * D / 120) / cos(phi1Rad); |
381 | *D*D*D*D*D/120)/cos(phi1Rad); |
|
|
382 | Long = LongOrigin + Long * rad2deg; |
533 | Long = LongOrigin + Long * rad2deg; |
383 | |
534 | |
384 | geo->lat=Lat; |
535 | geo->lat = Lat; |
385 | geo->lng=Long; |
536 | geo->lng = Long; |
386 | } |
537 | } |
387 | |
538 | |
388 | void |
|
|
389 | transform_datum(struct coord_geo *from, enum map_datum from_datum, struct coord_geo *to, enum map_datum to_datum) |
539 | void transform_datum(struct coord_geo *from, enum map_datum from_datum, struct coord_geo *to, enum map_datum to_datum) |
390 | { |
540 | { |
391 | } |
541 | } |
392 | |
542 | |
393 | int |
|
|
394 | transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int mindist, int width, int *width_return) |
543 | int transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int mindist, int width, int *width_return) |
395 | { |
544 | { |
396 | struct coord c1; |
545 | struct coord c1; |
397 | int xcn, ycn; |
546 | int xcn, ycn; |
398 | struct coord_geo g; |
547 | struct coord_geo g; |
399 | int xc, yc, zc=0, xco=0, yco=0, zco=0; |
548 | int xc, yc, zc = 0, xco = 0, yco = 0, zco = 0; |
400 | int xm,ym,zct; |
549 | int xm, ym, zct; |
401 | int zlimit=t->znear; |
550 | int zlimit = t->znear; |
402 | int visible, visibleo=-1; |
551 | int visible, visibleo = -1; |
403 | int i,j = 0,k=0; |
552 | int i, j = 0, k = 0; |
|
|
553 | |
404 | //dbg(1,"count=%d\n", count); |
554 | //dbg(0,"count=%d\n", count); |
405 | for (i=0; i < count; i++) |
555 | for (i = 0; i < count; i++) |
406 | { |
556 | { |
407 | if (pro == t->pro) |
557 | if (pro == t->pro) |
408 | { |
558 | { |
409 | xc=c[i].x; |
559 | xc = c[i].x; |
410 | yc=c[i].y; |
560 | yc = c[i].y; |
411 | } |
561 | } |
412 | else |
562 | else |
413 | { |
563 | { |
|
|
564 | //dbg(0,"to from geo\n"); |
414 | transform_to_geo(pro, &c[i], &g); |
565 | transform_to_geo(pro, &c[i], &g); |
415 | transform_from_geo(t->pro, &g, &c1); |
566 | transform_from_geo(t->pro, &g, &c1); |
416 | xc=c1.x; |
567 | xc = c1.x; |
417 | yc=c1.y; |
568 | yc = c1.y; |
418 | } |
569 | } |
419 | |
570 | |
420 | if (i != 0 && i != count-1 && mindist) |
571 | if (i != 0 && i != count - 1 && mindist) |
421 | { |
572 | { |
422 | if (xc > c[k].x-mindist && xc < c[k].x+mindist && yc > c[k].y-mindist && yc < c[k].y+mindist && |
573 | if (xc > c[k].x - mindist && xc < c[k].x + mindist && yc > c[k].y - mindist && yc < c[k].y + mindist && (c[i + 1].x != c[0].x || c[i + 1].y != c[0].y)) |
423 | (c[i+1].x != c[0].x || c[i+1].y != c[0].y)) |
574 | { |
424 | continue; |
575 | continue; |
|
|
576 | } |
425 | k=i; |
577 | k = i; |
426 | } |
578 | } |
427 | xm=xc; |
579 | xm = xc; |
428 | ym=yc; |
580 | ym = yc; |
429 | // dbg(2,"0x%x, 0x%x - 0x%x,0x%x contains 0x%x,0x%x\n", t->r.lu.x, t->r.lu.y, t->r.rl.x, t->r.rl.y, c->x, c->y); |
581 | // dbg(2,"0x%x, 0x%x - 0x%x,0x%x contains 0x%x,0x%x\n", t->r.lu.x, t->r.lu.y, t->r.rl.x, t->r.rl.y, c->x, c->y); |
430 | // ret=coord_rect_contains(&t->r, c); |
582 | // ret=coord_rect_contains(&t->r, c); |
431 | xc-=t->map_center.x; |
583 | xc -= t->map_center.x; |
432 | yc-=t->map_center.y; |
584 | yc -= t->map_center.y; |
433 | xc >>= t->scale_shift; |
585 | xc >>= t->scale_shift; |
434 | yc >>= t->scale_shift; |
586 | yc >>= t->scale_shift; |
435 | xm=xc; |
587 | xm = xc; |
436 | ym=yc; |
588 | ym = yc; |
437 | |
589 | |
438 | xcn=xc*t->m00+yc*t->m01+HOG(*t)*t->m02; |
590 | xcn = xc * t->m00 + yc * t->m01 + HOG(*t) * t->m02; |
439 | ycn=xc*t->m10+yc*t->m11+HOG(*t)*t->m12; |
591 | ycn = xc * t->m10 + yc * t->m11 + HOG(*t) * t->m12; |
440 | |
592 | |
441 | if (t->ddd) |
593 | if (t->ddd) |
442 | { |
594 | { |
443 | zc=(xc*t->m20+yc*t->m21+HOG(*t)*t->m22); |
595 | zc = (xc * t->m20 + yc * t->m21 + HOG(*t) * t->m22); |
444 | zct=zc; |
596 | zct = zc; |
445 | zc+=t->offz << POST_SHIFT; |
597 | zc += t->offz << POST_SHIFT; |
446 | //dbg(1,"zc=%d\n", zc); |
598 | //dbg(1,"zc=%d\n", zc); |
447 | //dbg(1,"zc(%d)=xc(%d)*m20(%d)+yc(%d)*m21(%d)\n", (xc*t->m20+yc*t->m21), xc, t->m20, yc, t->m21); |
599 | //dbg(1,"zc(%d)=xc(%d)*m20(%d)+yc(%d)*m21(%d)\n", (xc*t->m20+yc*t->m21), xc, t->m20, yc, t->m21); |
448 | /* visibility */ |
600 | /* visibility */ |
449 | visible=(zc < zlimit ? 0:1); |
601 | visible = (zc < zlimit ? 0 : 1); |
450 | //dbg(1,"visible=%d old %d\n", visible, visibleo); |
602 | //dbg(1,"visible=%d old %d\n", visible, visibleo); |
451 | if (visible != visibleo && visibleo != -1) |
603 | if (visible != visibleo && visibleo != -1) |
452 | { |
604 | { |
453 | //dbg(1,"clipping (%d,%d,%d)-(%d,%d,%d) (%d,%d,%d)\n", xcn, ycn, zc, xco, yco, zco, xco-xcn, yco-ycn, zco-zc); |
605 | //dbg(1,"clipping (%d,%d,%d)-(%d,%d,%d) (%d,%d,%d)\n", xcn, ycn, zc, xco, yco, zco, xco-xcn, yco-ycn, zco-zc); |
454 | if (zco != zc) |
606 | if (zco != zc) |
455 | { |
607 | { |
456 | xcn=xcn+(long long)(xco-xcn)*(zlimit-zc)/(zco-zc); |
608 | xcn = xcn + (long long) (xco - xcn) * (zlimit - zc) / (zco - zc); |
457 | ycn=ycn+(long long)(yco-ycn)*(zlimit-zc)/(zco-zc); |
609 | ycn = ycn + (long long) (yco - ycn) * (zlimit - zc) / (zco - zc); |
458 | } |
610 | } |
459 | //dbg(1,"result (%d,%d,%d) * %d / %d\n", xcn,ycn,zc,zlimit-zc,zco-zc); |
611 | //dbg(1,"result (%d,%d,%d) * %d / %d\n", xcn,ycn,zc,zlimit-zc,zco-zc); |
460 | zc=zlimit; |
612 | zc = zlimit; |
461 | xco=xcn; |
613 | xco = xcn; |
462 | yco=ycn; |
614 | yco = ycn; |
463 | zco=zc; |
615 | zco = zc; |
464 | if (visible) |
616 | if (visible) |
465 | { |
617 | { |
466 | i--; |
618 | i--; |
467 | } |
619 | } |
468 | visibleo=visible; |
620 | visibleo = visible; |
469 | } |
621 | } |
470 | else |
622 | else |
471 | { |
623 | { |
472 | xco=xcn; |
624 | xco = xcn; |
473 | yco=ycn; |
625 | yco = ycn; |
474 | zco=zc; |
626 | zco = zc; |
475 | visibleo=visible; |
627 | visibleo = visible; |
476 | |
628 | |
477 | if (! visible) |
629 | if (!visible) |
478 | { |
630 | { |
479 | continue; |
631 | continue; |
480 | } |
632 | } |
481 | } |
633 | } |
482 | //dbg(1,"zc=%d\n", zc); |
634 | //dbg(1,"zc=%d\n", zc); |
483 | //dbg(1,"xcn %d ycn %d\n", xcn, ycn); |
635 | //dbg(1,"xcn %d ycn %d\n", xcn, ycn); |
484 | //dbg(1,"%d,%d %d\n",xc,yc,zc); |
636 | //dbg(1,"%d,%d %d\n",xc,yc,zc); |
485 | #if 0 |
637 | //#if 0 |
486 | dbg(0,"%d/%d=%d %d/%d=%d\n",xcn,xc,xcn/xc,ycn,yc,ycn/yc); |
638 | // dbg(0,"%d/%d=%d %d/%d=%d\n",xcn,xc,xcn/xc,ycn,yc,ycn/yc); |
487 | #endif |
639 | //#endif |
|
|
640 | |
488 | #if 1 |
641 | //#if 1 |
489 | xc=(long long)xcn*t->xscale/zc; |
642 | xc = (long long) xcn * t->xscale / zc; |
490 | yc=(long long)ycn*t->yscale/zc; |
643 | yc = (long long) ycn * t->yscale / zc; |
491 | #else |
644 | //#else |
492 | xc=xcn/(1000+zc); |
645 | // xc=xcn/(1000+zc); |
493 | yc=ycn/(1000+zc); |
646 | // yc=ycn/(1000+zc); |
494 | #endif |
647 | //#endif |
|
|
648 | |
|
|
649 | |
495 | #if 0 |
650 | //#if 0 |
496 | dbg(1,"%d,%d %d\n",xc,yc,zc); |
651 | // dbg(1,"%d,%d %d\n",xc,yc,zc); |
497 | #endif |
652 | //#endif |
498 | } |
653 | } |
499 | else |
654 | else |
500 | { |
655 | { |
501 | xc=xcn; |
656 | xc = xcn; |
502 | yc=ycn; |
657 | yc = ycn; |
503 | xc>>=POST_SHIFT; |
658 | xc >>= POST_SHIFT; |
504 | yc>>=POST_SHIFT; |
659 | yc >>= POST_SHIFT; |
505 | } |
660 | } |
506 | |
661 | |
507 | xc+=t->offx; |
662 | xc += t->offx; |
508 | yc+=t->offy; |
663 | yc += t->offy; |
509 | p[j].x=xc; |
664 | p[j].x = xc; |
510 | p[j].y=yc; |
665 | p[j].y = yc; |
511 | |
666 | |
512 | if (width_return) |
667 | if (width_return) |
513 | { |
668 | { |
514 | if (t->ddd) |
669 | if (t->ddd) |
515 | { |
670 | { |
516 | width_return[j]=width*t->wscale/zc; |
671 | width_return[j] = width * t->wscale / zc; |
517 | } |
672 | } |
518 | else |
673 | else |
519 | { |
674 | { |
520 | width_return[j]=width; |
675 | width_return[j] = width; |
521 | } |
676 | } |
522 | } |
677 | } |
523 | j++; |
678 | j++; |
524 | } |
679 | } // ------- END for loop ---------- |
|
|
680 | |
525 | return j; |
681 | return j; |
526 | } |
682 | } |
527 | |
683 | |
528 | static void |
|
|
529 | transform_apply_inverse_matrix(struct transformation *t, struct coord_geo_cart *in, struct coord_geo_cart *out) |
684 | static void transform_apply_inverse_matrix(struct transformation *t, struct coord_geo_cart *in, struct coord_geo_cart *out) |
530 | { |
685 | { |
531 | out->x=in->x*t->im00+in->y*t->im01+in->z*t->im02; |
686 | out->x = in->x * t->im00 + in->y * t->im01 + in->z * t->im02; |
532 | out->y=in->x*t->im10+in->y*t->im11+in->z*t->im12; |
687 | out->y = in->x * t->im10 + in->y * t->im11 + in->z * t->im12; |
533 | out->z=in->x*t->im20+in->y*t->im21+in->z*t->im22; |
688 | out->z = in->x * t->im20 + in->y * t->im21 + in->z * t->im22; |
534 | } |
689 | } |
535 | |
690 | |
536 | static int |
|
|
537 | transform_zplane_intersection(struct coord_geo_cart *p1, struct coord_geo_cart *p2, navit_float z, struct coord_geo_cart *result) |
691 | static int transform_zplane_intersection(struct coord_geo_cart *p1, struct coord_geo_cart *p2, navit_float z, struct coord_geo_cart *result) |
538 | { |
692 | { |
539 | navit_float dividend=z-p1->z; |
693 | navit_float dividend = z - p1->z; |
540 | navit_float divisor=p2->z-p1->z; |
694 | navit_float divisor = p2->z - p1->z; |
541 | navit_float q; |
695 | navit_float q; |
542 | if (!divisor) { |
696 | if (!divisor) |
|
|
697 | { |
543 | if (dividend) |
698 | if (dividend) |
544 | return 0; /* no intersection */ |
699 | return 0; /* no intersection */ |
545 | else |
700 | else |
546 | return 3; /* identical planes */ |
701 | return 3; /* identical planes */ |
547 | } |
702 | } |
548 | q=dividend/divisor; |
703 | q = dividend / divisor; |
549 | result->x=p1->x+q*(p2->x-p1->x); |
704 | result->x = p1->x + q * (p2->x - p1->x); |
550 | result->y=p1->y+q*(p2->y-p1->y); |
705 | result->y = p1->y + q * (p2->y - p1->y); |
551 | result->z=z; |
706 | result->z = z; |
552 | if (q >= 0 && q <= 1) |
707 | if (q >= 0 && q <= 1) |
553 | return 1; /* intersection within [p1,p2] */ |
708 | return 1; /* intersection within [p1,p2] */ |
554 | return 2; /* intersection without [p1,p2] */ |
709 | return 2; /* intersection without [p1,p2] */ |
555 | } |
710 | } |
556 | |
711 | |
557 | static void |
|
|
558 | transform_screen_to_3d(struct transformation *t, struct point *p, navit_float z, struct coord_geo_cart *cg) |
712 | static void transform_screen_to_3d(struct transformation *t, struct point *p, navit_float z, struct coord_geo_cart *cg) |
559 | { |
713 | { |
560 | double xc,yc; |
714 | double xc, yc; |
561 | double offz=t->offz << POST_SHIFT; |
715 | double offz = t->offz << POST_SHIFT; |
562 | xc=p->x - t->offx; |
716 | xc = p->x - t->offx; |
563 | yc=p->y - t->offy; |
717 | yc = p->y - t->offy; |
564 | cg->x=xc*z/t->xscale; |
718 | cg->x = xc * z / t->xscale; |
565 | cg->y=yc*z/t->yscale; |
719 | cg->y = yc * z / t->yscale; |
566 | cg->z=z-offz; |
720 | cg->z = z - offz; |
567 | } |
721 | } |
568 | |
722 | |
569 | static int |
|
|
570 | transform_reverse_near_far(struct transformation *t, struct point *p, struct coord *c, int near, int far) |
723 | static int transform_reverse_near_far(struct transformation *t, struct point *p, struct coord *c, int near, int far) |
571 | { |
724 | { |
572 | double xc,yc; |
725 | double xc, yc; |
573 | |
726 | |
574 | //dbg(1,"%d,%d\n",p->x,p->y); |
727 | //dbg(1,"%d,%d\n",p->x,p->y); |
575 | |
728 | |
576 | if (t->ddd) |
729 | if (t->ddd) |
577 | { |
730 | { |
578 | struct coord_geo_cart nearc,farc,nears,fars,intersection; |
731 | struct coord_geo_cart nearc, farc, nears, fars, intersection; |
579 | transform_screen_to_3d(t, p, near, &nearc); |
732 | transform_screen_to_3d(t, p, near, &nearc); |
580 | transform_screen_to_3d(t, p, far, &farc); |
733 | transform_screen_to_3d(t, p, far, &farc); |
581 | transform_apply_inverse_matrix(t, &nearc, &nears); |
734 | transform_apply_inverse_matrix(t, &nearc, &nears); |
582 | transform_apply_inverse_matrix(t, &farc, &fars); |
735 | transform_apply_inverse_matrix(t, &farc, &fars); |
583 | if (transform_zplane_intersection(&nears, &fars, HOG(*t), &intersection) != 1) |
736 | if (transform_zplane_intersection(&nears, &fars, HOG(*t), &intersection) != 1) |
584 | { |
737 | { |
585 | return 0; |
738 | return 0; |
586 | } |
739 | } |
587 | xc=intersection.x; |
740 | xc = intersection.x; |
588 | yc=intersection.y; |
741 | yc = intersection.y; |
589 | } |
742 | } |
590 | else |
743 | else |
591 | { |
744 | { |
592 | double xcn,ycn; |
745 | double xcn, ycn; |
593 | xcn=p->x - t->offx; |
746 | xcn = p->x - t->offx; |
594 | ycn=p->y - t->offy; |
747 | ycn = p->y - t->offy; |
595 | xc=(xcn*t->im00+ycn*t->im01)*(1 << POST_SHIFT); |
748 | xc = (xcn * t->im00 + ycn * t->im01) * (1 << POST_SHIFT); |
596 | yc=(xcn*t->im10+ycn*t->im11)*(1 << POST_SHIFT); |
749 | yc = (xcn * t->im10 + ycn * t->im11) * (1 << POST_SHIFT); |
597 | } |
750 | } |
598 | |
751 | |
599 | c->x=xc*(1 << t->scale_shift)+t->map_center.x; |
752 | c->x = xc * (1 << t->scale_shift) + t->map_center.x; |
600 | c->y=yc*(1 << t->scale_shift)+t->map_center.y; |
753 | c->y = yc * (1 << t->scale_shift) + t->map_center.y; |
601 | |
754 | |
602 | return 1; |
755 | return 1; |
603 | } |
756 | } |
604 | |
757 | |
605 | int |
|
|
606 | transform_reverse(struct transformation *t, struct point *p, struct coord *c) |
758 | int transform_reverse(struct transformation *t, struct point *p, struct coord *c) |
607 | { |
759 | { |
608 | return transform_reverse_near_far(t, p, c, t->znear, t->zfar); |
760 | return transform_reverse_near_far(t, p, c, t->znear, t->zfar); |
609 | } |
761 | } |
610 | |
762 | |
611 | enum projection |
|
|
612 | transform_get_projection(struct transformation *this_) |
763 | enum projection transform_get_projection(struct transformation *this_) |
613 | { |
764 | { |
614 | return this_->pro; |
765 | return this_->pro; |
615 | } |
766 | } |
616 | |
767 | |
617 | void |
|
|
618 | transform_set_projection(struct transformation *this_, enum projection pro) |
768 | void transform_set_projection(struct transformation *this_, enum projection pro) |
619 | { |
769 | { |
620 | this_->pro=pro; |
770 | this_->pro = pro; |
621 | } |
771 | } |
622 | |
772 | |
623 | static int |
|
|
624 | min4(int v1,int v2, int v3, int v4) |
773 | static int min4(int v1, int v2, int v3, int v4) |
625 | { |
774 | { |
626 | int res=v1; |
775 | int res = v1; |
627 | if (v2 < res) |
776 | if (v2 < res) |
628 | res=v2; |
777 | res = v2; |
629 | if (v3 < res) |
778 | if (v3 < res) |
630 | res=v3; |
779 | res = v3; |
631 | if (v4 < res) |
780 | if (v4 < res) |
632 | res=v4; |
781 | res = v4; |
633 | return res; |
782 | return res; |
634 | } |
783 | } |
635 | |
784 | |
636 | static int |
|
|
637 | max4(int v1,int v2, int v3, int v4) |
785 | static int max4(int v1, int v2, int v3, int v4) |
638 | { |
786 | { |
639 | int res=v1; |
787 | int res = v1; |
640 | if (v2 > res) |
788 | if (v2 > res) |
641 | res=v2; |
789 | res = v2; |
642 | if (v3 > res) |
790 | if (v3 > res) |
643 | res=v3; |
791 | res = v3; |
644 | if (v4 > res) |
792 | if (v4 > res) |
645 | res=v4; |
793 | res = v4; |
646 | return res; |
794 | return res; |
647 | } |
795 | } |
648 | |
796 | |
649 | struct map_selection * |
797 | struct map_selection * |
650 | transform_get_selection(struct transformation *this_, enum projection pro, int order) |
798 | transform_get_selection(struct transformation *this_, enum projection pro, int order) |
651 | { |
799 | { |
652 | |
800 | |
653 | struct map_selection *ret,*curri,*curro; |
801 | struct map_selection *ret, *curri, *curro; |
654 | struct coord_geo g; |
802 | struct coord_geo g; |
655 | |
803 | |
656 | ret=map_selection_dup(this_->map_sel); |
804 | ret = map_selection_dup(this_->map_sel); |
657 | curri=this_->map_sel; |
805 | curri = this_->map_sel; |
658 | curro=ret; |
806 | curro = ret; |
659 | while (curri) { |
807 | while (curri) |
|
|
808 | { |
660 | if (this_->pro != pro) { |
809 | if (this_->pro != pro) |
|
|
810 | { |
661 | transform_to_geo(this_->pro, &curri->u.c_rect.lu, &g); |
811 | transform_to_geo(this_->pro, &curri->u.c_rect.lu, &g); |
662 | transform_from_geo(pro, &g, &curro->u.c_rect.lu); |
812 | transform_from_geo(pro, &g, &curro->u.c_rect.lu); |
663 | // dbg(1,"%f,%f", g.lat, g.lng); |
813 | // dbg(1,"%f,%f", g.lat, g.lng); |
664 | transform_to_geo(this_->pro, &curri->u.c_rect.rl, &g); |
814 | transform_to_geo(this_->pro, &curri->u.c_rect.rl, &g); |
665 | transform_from_geo(pro, &g, &curro->u.c_rect.rl); |
815 | transform_from_geo(pro, &g, &curro->u.c_rect.rl); |
666 | // dbg(1,": - %f,%f\n", g.lat, g.lng); |
816 | // dbg(1,": - %f,%f\n", g.lat, g.lng); |
667 | } |
817 | } |
668 | // dbg(1,"transform rect for %d is %d,%d - %d,%d\n", pro, curro->u.c_rect.lu.x, curro->u.c_rect.lu.y, curro->u.c_rect.rl.x, curro->u.c_rect.rl.y); |
818 | // dbg(1,"transform rect for %d is %d,%d - %d,%d\n", pro, curro->u.c_rect.lu.x, curro->u.c_rect.lu.y, curro->u.c_rect.rl.x, curro->u.c_rect.rl.y); |
669 | curro->order+=order; |
819 | curro->order += order; |
670 | #if 0 |
820 | #if 0 |
671 | curro->u.c_rect.lu.x-=500; |
821 | curro->u.c_rect.lu.x-=500; |
672 | curro->u.c_rect.lu.y+=500; |
822 | curro->u.c_rect.lu.y+=500; |
673 | curro->u.c_rect.rl.x+=500; |
823 | curro->u.c_rect.rl.x+=500; |
674 | curro->u.c_rect.rl.y-=500; |
824 | curro->u.c_rect.rl.y-=500; |
675 | #endif |
825 | #endif |
676 | curro->range=item_range_all; |
826 | curro->range = item_range_all; |
677 | curri=curri->next; |
827 | curri = curri->next; |
678 | curro=curro->next; |
828 | curro = curro->next; |
679 | } |
829 | } |
680 | return ret; |
830 | return ret; |
681 | } |
831 | } |
682 | |
832 | |
683 | struct coord * |
833 | struct coord * |
… | |
… | |
690 | transform_get_center(struct transformation *this_) |
840 | transform_get_center(struct transformation *this_) |
691 | { |
841 | { |
692 | return &this_->map_center; |
842 | return &this_->map_center; |
693 | } |
843 | } |
694 | |
844 | |
695 | void |
|
|
696 | transform_set_center(struct transformation *this_, struct coord *c) |
845 | void transform_set_center(struct transformation *this_, struct coord *c) |
697 | { |
846 | { |
698 | this_->map_center=*c; |
847 | this_->map_center = *c; |
699 | } |
848 | } |
700 | |
849 | |
701 | |
|
|
702 | void |
|
|
703 | transform_set_yaw(struct transformation *t,int yaw) |
850 | void transform_set_yaw(struct transformation *t, int yaw) |
704 | { |
851 | { |
705 | t->yaw=yaw; |
852 | t->yaw = yaw; |
706 | transform_setup_matrix(t); |
853 | transform_setup_matrix(t); |
707 | } |
854 | } |
708 | |
855 | |
709 | int |
|
|
710 | transform_get_yaw(struct transformation *this_) |
856 | int transform_get_yaw(struct transformation *this_) |
711 | { |
857 | { |
712 | return this_->yaw; |
858 | return this_->yaw; |
713 | } |
859 | } |
714 | |
860 | |
715 | void |
|
|
716 | transform_set_pitch(struct transformation *this_,int pitch) |
861 | void transform_set_pitch(struct transformation *this_, int pitch) |
717 | { |
862 | { |
718 | this_->pitch=pitch; |
863 | this_->pitch = pitch; |
719 | transform_setup_matrix(this_); |
864 | transform_setup_matrix(this_); |
720 | } |
865 | } |
721 | int |
|
|
722 | transform_get_pitch(struct transformation *this_) |
866 | int transform_get_pitch(struct transformation *this_) |
723 | { |
867 | { |
724 | return this_->pitch; |
868 | return this_->pitch; |
725 | } |
869 | } |
726 | |
870 | |
727 | void |
|
|
728 | transform_set_roll(struct transformation *this_,int roll) |
871 | void transform_set_roll(struct transformation *this_, int roll) |
729 | { |
872 | { |
730 | #ifdef ENABLE_ROLL |
873 | #ifdef ENABLE_ROLL |
731 | this_->roll=roll; |
874 | this_->roll=roll; |
732 | transform_setup_matrix(this_); |
875 | transform_setup_matrix(this_); |
733 | #else |
876 | #else |
734 | dbg(0,"not supported\n"); |
877 | //dbg(0, "not supported\n"); |
735 | #endif |
878 | #endif |
736 | } |
879 | } |
737 | |
880 | |
738 | int |
|
|
739 | transform_get_roll(struct transformation *this_) |
881 | int transform_get_roll(struct transformation *this_) |
740 | { |
882 | { |
741 | #ifdef ENABLE_ROLL |
883 | #ifdef ENABLE_ROLL |
742 | return this_->roll; |
884 | return this_->roll; |
743 | #else |
885 | #else |
744 | return 0; |
886 | return 0; |
745 | #endif |
887 | #endif |
746 | } |
888 | } |
747 | |
889 | |
748 | void |
|
|
749 | transform_set_distance(struct transformation *this_,int distance) |
890 | void transform_set_distance(struct transformation *this_, int distance) |
750 | { |
891 | { |
751 | transform_set_screen_dist(this_, distance); |
892 | transform_set_screen_dist(this_, distance); |
752 | transform_setup_matrix(this_); |
893 | transform_setup_matrix(this_); |
753 | } |
894 | } |
754 | |
895 | |
755 | int |
|
|
756 | transform_get_distance(struct transformation *this_) |
896 | int transform_get_distance(struct transformation *this_) |
757 | { |
897 | { |
758 | return this_->screen_dist; |
898 | return this_->screen_dist; |
759 | } |
899 | } |
760 | |
900 | |
761 | void |
|
|
762 | transform_set_scales(struct transformation *this_, int xscale, int yscale, int wscale) |
901 | void transform_set_scales(struct transformation *this_, int xscale, int yscale, int wscale) |
763 | { |
902 | { |
764 | this_->xscale3d=xscale; |
903 | this_->xscale3d = xscale; |
765 | this_->yscale3d=yscale; |
904 | this_->yscale3d = yscale; |
766 | this_->wscale3d=wscale; |
905 | this_->wscale3d = wscale; |
767 | } |
906 | } |
768 | |
907 | |
769 | void |
|
|
770 | transform_set_screen_selection(struct transformation *t, struct map_selection *sel) |
908 | void transform_set_screen_selection(struct transformation *t, struct map_selection *sel) |
771 | { |
909 | { |
772 | map_selection_destroy(t->screen_sel); |
910 | map_selection_destroy(t->screen_sel); |
773 | t->screen_sel=map_selection_dup(sel); |
911 | t->screen_sel = map_selection_dup(sel); |
774 | if (sel) { |
912 | if (sel) |
|
|
913 | { |
775 | t->screen_center.x=(sel->u.p_rect.rl.x-sel->u.p_rect.lu.x)/2; |
914 | t->screen_center.x = (sel->u.p_rect.rl.x - sel->u.p_rect.lu.x) / 2; |
776 | t->screen_center.y=(sel->u.p_rect.rl.y-sel->u.p_rect.lu.y)/2; |
915 | t->screen_center.y = (sel->u.p_rect.rl.y - sel->u.p_rect.lu.y) / 2; |
777 | transform_setup_matrix(t); |
916 | transform_setup_matrix(t); |
778 | } |
917 | } |
779 | } |
918 | } |
780 | |
919 | |
781 | void |
|
|
782 | transform_set_screen_center(struct transformation *t, struct point *p) |
920 | void transform_set_screen_center(struct transformation *t, struct point *p) |
783 | { |
921 | { |
784 | t->screen_center=*p; |
922 | t->screen_center = *p; |
785 | } |
923 | } |
786 | |
924 | |
787 | #if 0 |
925 | #if 0 |
788 | void |
926 | void |
789 | transform_set_size(struct transformation *t, int width, int height) |
927 | transform_set_size(struct transformation *t, int width, int height) |
… | |
… | |
791 | t->width=width; |
929 | t->width=width; |
792 | t->height=height; |
930 | t->height=height; |
793 | } |
931 | } |
794 | #endif |
932 | #endif |
795 | |
933 | |
796 | void |
|
|
797 | transform_get_size(struct transformation *t, int *width, int *height) |
934 | void transform_get_size(struct transformation *t, int *width, int *height) |
798 | { |
935 | { |
799 | struct point_rect *r; |
936 | struct point_rect *r; |
800 | if (t->screen_sel) { |
937 | if (t->screen_sel) |
|
|
938 | { |
801 | r=&t->screen_sel->u.p_rect; |
939 | r = &t->screen_sel->u.p_rect; |
802 | *width=r->rl.x-r->lu.x; |
940 | *width = r->rl.x - r->lu.x; |
803 | *height=r->rl.y-r->lu.y; |
941 | *height = r->rl.y - r->lu.y; |
804 | } |
942 | } |
805 | } |
943 | } |
806 | |
944 | |
807 | void |
|
|
808 | transform_setup(struct transformation *t, struct pcoord *c, int scale, int yaw) |
945 | void transform_setup(struct transformation *t, struct pcoord *c, int scale, int yaw) |
809 | { |
946 | { |
810 | t->pro=c->pro; |
947 | t->pro = c->pro; |
811 | t->map_center.x=c->x; |
948 | t->map_center.x = c->x; |
812 | t->map_center.y=c->y; |
949 | t->map_center.y = c->y; |
813 | t->scale=scale/16.0; |
950 | t->scale = scale / 16.0; |
814 | transform_set_yaw(t, yaw); |
951 | transform_set_yaw(t, yaw); |
815 | } |
952 | } |
816 | |
953 | |
817 | #if 0 |
954 | #if 0 |
818 | |
955 | |
… | |
… | |
827 | t->r.rl.y=center->y-limit; |
964 | t->r.rl.y=center->y-limit; |
828 | t->r.lu.y=center->y+limit; |
965 | t->r.lu.y=center->y+limit; |
829 | } |
966 | } |
830 | #endif |
967 | #endif |
831 | |
968 | |
832 | void |
|
|
833 | transform_setup_source_rect(struct transformation *t) |
969 | void transform_setup_source_rect(struct transformation *t) |
834 | { |
970 | { |
835 | int i; |
971 | int i; |
836 | struct coord screen[4]; |
972 | struct coord screen[4]; |
837 | struct point screen_pnt[4]; |
973 | struct point screen_pnt[4]; |
838 | struct point_rect *pr; |
974 | struct point_rect *pr; |
839 | struct map_selection *ms,*msm,*next,**msm_last; |
975 | struct map_selection *ms, *msm, *next, **msm_last; |
840 | ms=t->map_sel; |
976 | ms = t->map_sel; |
841 | while (ms) { |
977 | while (ms) |
|
|
978 | { |
842 | next=ms->next; |
979 | next = ms->next; |
843 | g_free(ms); |
980 | g_free(ms); |
844 | ms=next; |
981 | ms = next; |
845 | } |
982 | } |
846 | t->map_sel=NULL; |
983 | t->map_sel = NULL; |
847 | msm_last=&t->map_sel; |
984 | msm_last = &t->map_sel; |
848 | ms=t->screen_sel; |
985 | ms = t->screen_sel; |
849 | while (ms) { |
986 | while (ms) |
|
|
987 | { |
850 | msm=g_new0(struct map_selection, 1); |
988 | msm=g_new0(struct map_selection, 1); |
851 | *msm=*ms; |
989 | *msm = *ms; |
852 | pr=&ms->u.p_rect; |
990 | pr = &ms->u.p_rect; |
853 | screen_pnt[0].x=pr->lu.x; /* left upper */ |
991 | screen_pnt[0].x = pr->lu.x; /* left upper */ |
854 | screen_pnt[0].y=pr->lu.y; |
992 | screen_pnt[0].y = pr->lu.y; |
855 | screen_pnt[1].x=pr->rl.x; /* right upper */ |
993 | screen_pnt[1].x = pr->rl.x; /* right upper */ |
856 | screen_pnt[1].y=pr->lu.y; |
994 | screen_pnt[1].y = pr->lu.y; |
857 | screen_pnt[2].x=pr->rl.x; /* right lower */ |
995 | screen_pnt[2].x = pr->rl.x; /* right lower */ |
858 | screen_pnt[2].y=pr->rl.y; |
996 | screen_pnt[2].y = pr->rl.y; |
859 | screen_pnt[3].x=pr->lu.x; /* left lower */ |
997 | screen_pnt[3].x = pr->lu.x; /* left lower */ |
860 | screen_pnt[3].y=pr->rl.y; |
998 | screen_pnt[3].y = pr->rl.y; |
861 | if (t->ddd) { |
999 | if (t->ddd) |
|
|
1000 | { |
862 | struct coord_geo_cart tmp,cg[8]; |
1001 | struct coord_geo_cart tmp, cg[8]; |
863 | struct coord c; |
1002 | struct coord c; |
864 | int valid=0; |
1003 | int valid = 0; |
865 | unsigned char edgenodes[]={ |
1004 | unsigned char edgenodes[] = { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 }; |
866 | 0,1, |
|
|
867 | 1,2, |
|
|
868 | 2,3, |
|
|
869 | 3,0, |
|
|
870 | 4,5, |
|
|
871 | 5,6, |
|
|
872 | 6,7, |
|
|
873 | 7,4, |
|
|
874 | 0,4, |
|
|
875 | 1,5, |
|
|
876 | 2,6, |
|
|
877 | 3,7}; |
|
|
878 | for (i = 0 ; i < 8 ; i++) { |
1005 | for (i = 0; i < 8; i++) |
|
|
1006 | { |
879 | transform_screen_to_3d(t, &screen_pnt[i%4], (i >= 4 ? t->zfar:t->znear), &tmp); |
1007 | transform_screen_to_3d(t, &screen_pnt[i % 4], (i >= 4 ? t->zfar : t->znear), &tmp); |
880 | transform_apply_inverse_matrix(t, &tmp, &cg[i]); |
1008 | transform_apply_inverse_matrix(t, &tmp, &cg[i]); |
881 | } |
1009 | } |
882 | msm->u.c_rect.lu.x=0; |
1010 | msm->u.c_rect.lu.x = 0; |
883 | msm->u.c_rect.lu.y=0; |
1011 | msm->u.c_rect.lu.y = 0; |
884 | msm->u.c_rect.rl.x=0; |
1012 | msm->u.c_rect.rl.x = 0; |
885 | msm->u.c_rect.rl.y=0; |
1013 | msm->u.c_rect.rl.y = 0; |
886 | for (i = 0 ; i < 12 ; i++) { |
1014 | for (i = 0; i < 12; i++) |
|
|
1015 | { |
887 | if (transform_zplane_intersection(&cg[edgenodes[i*2]], &cg[edgenodes[i*2+1]], HOG(*t), &tmp) == 1) { |
1016 | if (transform_zplane_intersection(&cg[edgenodes[i * 2]], &cg[edgenodes[i * 2 + 1]], HOG(*t), &tmp) == 1) |
|
|
1017 | { |
888 | c.x=tmp.x*(1 << t->scale_shift)+t->map_center.x; |
1018 | c.x = tmp.x * (1 << t->scale_shift) + t->map_center.x; |
889 | c.y=tmp.y*(1 << t->scale_shift)+t->map_center.y; |
1019 | c.y = tmp.y * (1 << t->scale_shift) + t->map_center.y; |
890 | //dbg(1,"intersection with edge %d at 0x%x,0x%x\n",i,c.x,c.y); |
1020 | //dbg(1,"intersection with edge %d at 0x%x,0x%x\n",i,c.x,c.y); |
891 | if (valid) |
1021 | if (valid) |
892 | coord_rect_extend(&msm->u.c_rect, &c); |
1022 | coord_rect_extend(&msm->u.c_rect, &c); |
893 | else { |
1023 | else |
|
|
1024 | { |
894 | msm->u.c_rect.lu=c; |
1025 | msm->u.c_rect.lu = c; |
895 | msm->u.c_rect.rl=c; |
1026 | msm->u.c_rect.rl = c; |
896 | valid=1; |
1027 | valid = 1; |
897 | } |
1028 | } |
898 | //dbg(1,"rect 0x%x,0x%x - 0x%x,0x%x\n",msm->u.c_rect.lu.x,msm->u.c_rect.lu.y,msm->u.c_rect.rl.x,msm->u.c_rect.rl.y); |
1029 | //dbg(1,"rect 0x%x,0x%x - 0x%x,0x%x\n",msm->u.c_rect.lu.x,msm->u.c_rect.lu.y,msm->u.c_rect.rl.x,msm->u.c_rect.rl.y); |
899 | } |
1030 | } |
900 | } |
1031 | } |
|
|
1032 | } |
901 | } else { |
1033 | else |
|
|
1034 | { |
902 | for (i = 0 ; i < 4 ; i++) { |
1035 | for (i = 0; i < 4; i++) |
|
|
1036 | { |
903 | transform_reverse(t, &screen_pnt[i], &screen[i]); |
1037 | transform_reverse(t, &screen_pnt[i], &screen[i]); |
904 | //dbg(1,"map(%d) %d,%d=0x%x,0x%x\n", i,screen_pnt[i].x, screen_pnt[i].y, screen[i].x, screen[i].y); |
1038 | //dbg(1,"map(%d) %d,%d=0x%x,0x%x\n", i,screen_pnt[i].x, screen_pnt[i].y, screen[i].x, screen[i].y); |
905 | } |
1039 | } |
906 | msm->u.c_rect.lu.x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); |
1040 | msm->u.c_rect.lu.x = min4(screen[0].x, screen[1].x, screen[2].x, screen[3].x); |
907 | msm->u.c_rect.rl.x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); |
1041 | msm->u.c_rect.rl.x = max4(screen[0].x, screen[1].x, screen[2].x, screen[3].x); |
908 | msm->u.c_rect.rl.y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); |
1042 | msm->u.c_rect.rl.y = min4(screen[0].y, screen[1].y, screen[2].y, screen[3].y); |
909 | msm->u.c_rect.lu.y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); |
1043 | msm->u.c_rect.lu.y = max4(screen[0].y, screen[1].y, screen[2].y, screen[3].y); |
910 | } |
1044 | } |
911 | //dbg(1,"%dx%d\n", msm->u.c_rect.rl.x-msm->u.c_rect.lu.x, |
1045 | //dbg(1,"%dx%d\n", msm->u.c_rect.rl.x-msm->u.c_rect.lu.x, |
912 | // msm->u.c_rect.lu.y-msm->u.c_rect.rl.y); |
1046 | // msm->u.c_rect.lu.y-msm->u.c_rect.rl.y); |
913 | *msm_last=msm; |
1047 | *msm_last = msm; |
914 | msm_last=&msm->next; |
1048 | msm_last = &msm->next; |
915 | ms=ms->next; |
1049 | ms = ms->next; |
916 | } |
1050 | } |
917 | } |
1051 | } |
918 | |
1052 | |
919 | long |
|
|
920 | transform_get_scale(struct transformation *t) |
1053 | long transform_get_scale(struct transformation *t) |
921 | { |
1054 | { |
922 | return (int)(t->scale*16); |
1055 | return (int) (t->scale * 16); |
923 | } |
1056 | } |
924 | |
1057 | |
925 | void |
|
|
926 | transform_set_scale(struct transformation *t, long scale) |
1058 | void transform_set_scale(struct transformation *t, long scale) |
927 | { |
1059 | { |
928 | t->scale=scale/16.0; |
1060 | t->scale = scale / 16.0; |
929 | transform_setup_matrix(t); |
1061 | transform_setup_matrix(t); |
930 | } |
1062 | } |
931 | |
1063 | |
932 | |
|
|
933 | int |
|
|
934 | transform_get_order(struct transformation *t) |
1064 | int transform_get_order(struct transformation *t) |
935 | { |
1065 | { |
936 | //dbg(1,"order %d\n", t->order); |
1066 | //dbg(1,"order %d\n", t->order); |
937 | return t->order; |
1067 | return t->order; |
938 | } |
1068 | } |
939 | |
|
|
940 | |
|
|
941 | |
1069 | |
942 | #define TWOPI (M_PI*2) |
1070 | #define TWOPI (M_PI*2) |
943 | #define GC2RAD(c) ((c) * TWOPI/(1<<24)) |
1071 | #define GC2RAD(c) ((c) * TWOPI/(1<<24)) |
944 | #define minf(a,b) ((a) < (b) ? (a) : (b)) |
1072 | #define minf(a,b) ((a) < (b) ? (a) : (b)) |
945 | |
1073 | |
946 | static double |
|
|
947 | transform_distance_garmin(struct coord *c1, struct coord *c2) |
1074 | static double transform_distance_garmin(struct coord *c1, struct coord *c2) |
948 | { |
1075 | { |
949 | #ifdef USE_HALVESINE |
1076 | #ifdef USE_HALVESINE |
950 | static const int earth_radius = 6371*1000; //m change accordingly |
1077 | static const int earth_radius = 6371*1000; //m change accordingly |
951 | // static const int earth_radius = 3960; //miles |
1078 | // static const int earth_radius = 3960; //miles |
952 | |
1079 | |
953 | //Point 1 cords |
1080 | //Point 1 cords |
954 | navit_float lat1 = GC2RAD(c1->y); |
1081 | navit_float lat1 = GC2RAD(c1->y); |
955 | navit_float long1 = GC2RAD(c1->x); |
1082 | navit_float long1 = GC2RAD(c1->x); |
956 | |
1083 | |
957 | //Point 2 cords |
1084 | //Point 2 cords |
958 | navit_float lat2 = GC2RAD(c2->y); |
1085 | navit_float lat2 = GC2RAD(c2->y); |
959 | navit_float long2 = GC2RAD(c2->x); |
1086 | navit_float long2 = GC2RAD(c2->x); |
960 | |
1087 | |
961 | //Haversine Formula |
1088 | //Haversine Formula |
962 | navit_float dlong = long2-long1; |
1089 | navit_float dlong = long2-long1; |
963 | navit_float dlat = lat2-lat1; |
1090 | navit_float dlat = lat2-lat1; |
964 | |
1091 | |
965 | navit_float sinlat = navit_sin(dlat/2); |
1092 | navit_float sinlat = navit_sin(dlat/2); |
966 | navit_float sinlong = navit_sin(dlong/2); |
1093 | navit_float sinlong = navit_sin(dlong/2); |
967 | |
1094 | |
968 | navit_float a=(sinlat*sinlat)+navit_cos(lat1)*navit_cos(lat2)*(sinlong*sinlong); |
1095 | navit_float a=(sinlat*sinlat)+navit_cos(lat1)*navit_cos(lat2)*(sinlong*sinlong); |
969 | navit_float c=2*navit_asin(minf(1,navit_sqrt(a))); |
1096 | navit_float c=2*navit_asin(minf(1,navit_sqrt(a))); |
970 | #ifdef AVOID_FLOAT |
1097 | #ifdef AVOID_FLOAT |
971 | return round(earth_radius*c); |
1098 | return round(earth_radius*c); |
972 | #else |
1099 | #else |
973 | return earth_radius*c; |
1100 | return earth_radius*c; |
974 | #endif |
1101 | #endif |
975 | #else |
1102 | #else |
976 | #define GMETER 2.3887499999999999 |
1103 | #define GMETER 2.3887499999999999 |
977 | navit_float dx,dy; |
1104 | navit_float dx, dy; |
978 | dx=c1->x-c2->x; |
1105 | dx = c1->x - c2->x; |
979 | dy=c1->y-c2->y; |
1106 | dy = c1->y - c2->y; |
980 | return navit_sqrt(dx*dx+dy*dy)*GMETER; |
1107 | return navit_sqrt(dx * dx + dy * dy) * GMETER; |
981 | #undef GMETER |
1108 | #undef GMETER |
982 | #endif |
1109 | #endif |
983 | } |
1110 | } |
984 | |
1111 | |
985 | double |
|
|
986 | transform_scale(int y) |
1112 | double transform_scale(int y) |
987 | { |
1113 | { |
988 | struct coord c; |
1114 | struct coord c; |
989 | struct coord_geo g; |
1115 | struct coord_geo g; |
990 | c.x=0; |
1116 | c.x = 0; |
991 | c.y=y; |
1117 | c.y = y; |
992 | transform_to_geo(projection_mg, &c, &g); |
1118 | transform_to_geo(projection_mg, &c, &g); |
993 | return 1/navit_cos(g.lat/180*M_PI); |
1119 | return 1 / navit_cos(g.lat / 180 * M_PI); |
994 | } |
1120 | } |
995 | |
1121 | |
996 | #ifdef AVOID_FLOAT |
1122 | #ifdef AVOID_FLOAT |
997 | static int |
1123 | static int |
|
|
1124 | tab_sqrt[]= |
998 | tab_sqrt[]={14142,13379,12806,12364,12018,11741,11517,11333,11180,11051,10943,10850,10770,10701,10640,10587,10540,10499,10462,10429,10400,10373,10349,10327,10307,10289,10273,10257,10243,10231,10219,10208}; |
1125 | { 14142,13379,12806,12364,12018,11741,11517,11333,11180,11051,10943,10850,10770,10701,10640,10587,10540,10499,10462,10429,10400,10373,10349,10327,10307,10289,10273,10257,10243,10231,10219,10208}; |
999 | |
1126 | |
1000 | static int tab_int_step = 0x20000; |
1127 | static int tab_int_step = 0x20000; |
|
|
1128 | static int tab_int_scale[]= |
1001 | static int tab_int_scale[]={10000,10002,10008,10019,10033,10052,10076,10103,10135,10171,10212,10257,10306,10359,10417,10479,10546,10617,10693,10773,10858,10947,11041,11140,11243,11352,11465,11582,11705,11833,11965,12103,12246,12394,12547,12706,12870,13039,13214,13395,13581,13773,13971,14174,14384,14600,14822,15050,15285,15526,15774,16028,16289,16557,16832,17114,17404,17700,18005,18316,18636,18964,19299,19643,19995,20355,20724,21102,21489,21885,22290,22705,23129,23563,24007,24461,24926,25401,25886,26383,26891}; |
1129 | { 10000,10002,10008,10019,10033,10052,10076,10103,10135,10171,10212,10257,10306,10359,10417,10479,10546,10617,10693,10773,10858,10947,11041,11140,11243,11352,11465,11582,11705,11833,11965,12103,12246,12394,12547,12706,12870,13039,13214,13395,13581,13773,13971,14174,14384,14600,14822,15050,15285,15526,15774,16028,16289,16557,16832,17114,17404,17700,18005,18316,18636,18964,19299,19643,19995,20355,20724,21102,21489,21885,22290,22705,23129,23563,24007,24461,24926,25401,25886,26383,26891}; |
1002 | |
1130 | |
1003 | int transform_int_scale(int y) |
1131 | int transform_int_scale(int y) |
1004 | { |
1132 | { |
1005 | int i,size = sizeof(tab_int_scale)/sizeof(int); |
1133 | int i,size = sizeof(tab_int_scale)/sizeof(int); |
1006 | if (y < 0) |
1134 | if (y < 0) |
1007 | y=-y; |
1135 | y=-y; |
1008 | i=y/tab_int_step; |
1136 | i=y/tab_int_step; |
1009 | if (i < size-1) |
1137 | if (i < size-1) |
1010 | return tab_int_scale[i]+((tab_int_scale[i+1]-tab_int_scale[i])*(y-i*tab_int_step))/tab_int_step; |
1138 | return tab_int_scale[i]+((tab_int_scale[i+1]-tab_int_scale[i])*(y-i*tab_int_step))/tab_int_step; |
1011 | return tab_int_scale[size-1]; |
1139 | return tab_int_scale[size-1]; |
1012 | } |
1140 | } |
1013 | #endif |
1141 | #endif |
1014 | |
1142 | |
1015 | double |
|
|
1016 | transform_distance(enum projection pro, struct coord *c1, struct coord *c2) |
1143 | double transform_distance(enum projection pro, struct coord *c1, struct coord *c2) |
1017 | { |
1144 | { |
1018 | if (pro == projection_mg) { |
1145 | if (pro == projection_mg) |
|
|
1146 | { |
1019 | #ifndef AVOID_FLOAT |
1147 | #ifndef AVOID_FLOAT |
1020 | double dx,dy,scale=transform_scale((c1->y+c2->y)/2); |
1148 | double dx, dy, scale = transform_scale((c1->y + c2->y) / 2); |
1021 | dx=c1->x-c2->x; |
1149 | dx = c1->x - c2->x; |
1022 | dy=c1->y-c2->y; |
1150 | dy = c1->y - c2->y; |
1023 | return sqrt(dx*dx+dy*dy)/scale; |
1151 | return sqrt(dx * dx + dy * dy) / scale; |
1024 | #else |
1152 | #else |
1025 | int dx,dy,f,scale=transform_int_scale((c1->y+c2->y)/2); |
1153 | int dx,dy,f,scale=transform_int_scale((c1->y+c2->y)/2); |
1026 | dx=c1->x-c2->x; |
1154 | dx=c1->x-c2->x; |
1027 | dy=c1->y-c2->y; |
1155 | dy=c1->y-c2->y; |
1028 | if (dx < 0) |
1156 | if (dx < 0) |
1029 | dx=-dx; |
1157 | dx=-dx; |
1030 | if (dy < 0) |
1158 | if (dy < 0) |
1031 | dy=-dy; |
1159 | dy=-dy; |
1032 | while (dx > 20000 || dy > 20000) { |
1160 | while (dx > 20000 || dy > 20000) |
|
|
1161 | { |
1033 | dx/=10; |
1162 | dx/=10; |
1034 | dy/=10; |
1163 | dy/=10; |
1035 | scale/=10; |
1164 | scale/=10; |
1036 | } |
1165 | } |
1037 | if (! dy) |
1166 | if (! dy) |
1038 | return dx*10000/scale; |
1167 | return dx*10000/scale; |
1039 | if (! dx) |
1168 | if (! dx) |
1040 | return dy*10000/scale; |
1169 | return dy*10000/scale; |
1041 | if (dx > dy) { |
1170 | if (dx > dy) |
|
|
1171 | { |
1042 | f=dx*8/dy-8; |
1172 | f=dx*8/dy-8; |
1043 | if (f >= 32) |
1173 | if (f >= 32) |
1044 | return dx*10000/scale; |
1174 | return dx*10000/scale; |
1045 | return dx*tab_sqrt[f]/scale; |
1175 | return dx*tab_sqrt[f]/scale; |
1046 | } else { |
1176 | } |
|
|
1177 | else |
|
|
1178 | { |
1047 | f=dy*8/dx-8; |
1179 | f=dy*8/dx-8; |
1048 | if (f >= 32) |
1180 | if (f >= 32) |
1049 | return dy*10000/scale; |
1181 | return dy*10000/scale; |
1050 | return dy*tab_sqrt[f]/scale; |
1182 | return dy*tab_sqrt[f]/scale; |
1051 | } |
1183 | } |
1052 | #endif |
1184 | #endif |
|
|
1185 | } |
1053 | } else if (pro == projection_garmin) { |
1186 | else if (pro == projection_garmin) |
|
|
1187 | { |
1054 | return transform_distance_garmin(c1, c2); |
1188 | return transform_distance_garmin(c1, c2); |
1055 | } else { |
1189 | } |
|
|
1190 | else |
|
|
1191 | { |
1056 | dbg(0,"Unknown projection: %d\n", pro); |
1192 | dbg(0, "Unknown projection: %d\n", pro); |
1057 | return 0; |
1193 | return 0; |
1058 | } |
1194 | } |
1059 | } |
1195 | } |
1060 | |
1196 | |
1061 | void |
|
|
1062 | transform_project(enum projection pro, struct coord *c, int distance, int angle, struct coord *res) |
1197 | void transform_project(enum projection pro, struct coord *c, int distance, int angle, struct coord *res) |
1063 | { |
1198 | { |
1064 | double scale; |
1199 | double scale; |
1065 | switch (pro) { |
1200 | switch (pro) |
|
|
1201 | { |
1066 | case projection_mg: |
1202 | case projection_mg: |
1067 | scale=transform_scale(c->y); |
1203 | scale = transform_scale(c->y); |
1068 | res->x=c->x+distance*sin(angle*M_PI/180)*scale; |
1204 | res->x = c->x + distance * sin(angle * M_PI / 180) * scale; |
1069 | res->y=c->y+distance*cos(angle*M_PI/180)*scale; |
1205 | res->y = c->y + distance * cos(angle * M_PI / 180) * scale; |
1070 | break; |
1206 | break; |
1071 | default: |
1207 | default: |
1072 | dbg(0,"Unsupported projection: %d\n", pro); |
1208 | dbg(0, "Unsupported projection: %d\n", pro); |
1073 | return; |
1209 | return; |
1074 | } |
1210 | } |
1075 | |
|
|
1076 | } |
|
|
1077 | |
1211 | |
|
|
1212 | } |
1078 | |
1213 | |
1079 | double |
|
|
1080 | transform_polyline_length(enum projection pro, struct coord *c, int count) |
1214 | double transform_polyline_length(enum projection pro, struct coord *c, int count) |
1081 | { |
1215 | { |
1082 | double ret=0; |
1216 | double ret = 0; |
1083 | int i; |
1217 | int i; |
1084 | |
1218 | |
1085 | for (i = 0 ; i < count-1 ; i++) |
1219 | for (i = 0; i < count - 1; i++) |
1086 | ret+=transform_distance(pro, &c[i], &c[i+1]); |
1220 | ret += transform_distance(pro, &c[i], &c[i + 1]); |
1087 | return ret; |
1221 | return ret; |
1088 | } |
1222 | } |
1089 | |
|
|
1090 | |
1223 | |
1091 | // calc the distance (squared) of a point (p) to a line segment (l1 .. l2) |
1224 | // calc the distance (squared) of a point (p) to a line segment (l1 .. l2) |
1092 | // return (int) distance squared |
1225 | // return (int) distance squared |
1093 | int transform_distance_point2line_sq(struct coord *p, struct coord *l1, struct coord *l2) |
1226 | int transform_distance_point2line_sq(struct coord *p, struct coord *l1, struct coord *l2) |
1094 | { |
1227 | { |
1095 | int A = p->x - l1->x; |
1228 | int A = p->x - l1->x; |
1096 | int B = p->y - l1->y; |
1229 | int B = p->y - l1->y; |
1097 | float C = l2->x - l1->x; |
1230 | float C = l2->x - l1->x; |
1098 | float D = l2->y - l1->y; |
1231 | float D = l2->y - l1->y; |
1099 | |
1232 | |
1100 | int dot = A * C + B * D; |
1233 | int dot = A * C + B * D; |
1101 | int len_sq = C * C + D * D; |
1234 | int len_sq = C * C + D * D; |
1102 | float param = (float)dot / (float)len_sq; |
1235 | float param = (float) dot / (float) len_sq; |
1103 | |
1236 | |
1104 | int xx, yy; |
1237 | int xx, yy; |
1105 | |
1238 | |
1106 | if (param < 0 || (l1->x == l2->x && l1->y == l2->y)) |
1239 | if (param < 0 || (l1->x == l2->x && l1->y == l2->y)) |
1107 | { |
1240 | { |
1108 | xx = l1->x; |
1241 | xx = l1->x; |
1109 | yy = l1->y; |
1242 | yy = l1->y; |
1110 | } |
1243 | } |
1111 | else if (param > 1) |
1244 | else if (param > 1) |
1112 | { |
1245 | { |
1113 | xx = l2->x; |
1246 | xx = l2->x; |
1114 | yy = l2->y; |
1247 | yy = l2->y; |
1115 | } |
1248 | } |
1116 | else |
1249 | else |
1117 | { |
1250 | { |
1118 | xx = l1->x + param * C; |
1251 | xx = l1->x + param * C; |
1119 | yy = l1->y + param * D; |
1252 | yy = l1->y + param * D; |
1120 | } |
1253 | } |
1121 | |
1254 | |
1122 | int dx = p->x - xx; |
1255 | int dx = p->x - xx; |
1123 | int dy = p->y - yy; |
1256 | int dy = p->y - yy; |
1124 | |
1257 | |
1125 | if (dx > 32767 || dy > 32767 || dx < -32767 || dy < -32767) |
1258 | if (dx > 32767 || dy > 32767 || dx < -32767 || dy < -32767) |
1126 | { |
1259 | { |
1127 | return INT_MAX; |
1260 | return INT_MAX; |
1128 | } |
1261 | } |
1129 | |
1262 | |
1130 | return (dx * dx + dy * dy); |
1263 | return (dx * dx + dy * dy); |
1131 | |
1264 | |
1132 | } |
1265 | } |
1133 | |
1266 | |
1134 | int |
|
|
1135 | transform_distance_sq(struct coord *c1, struct coord *c2) |
1267 | int transform_distance_sq(struct coord *c1, struct coord *c2) |
1136 | { |
1268 | { |
1137 | int dx=c1->x-c2->x; |
1269 | int dx = c1->x - c2->x; |
1138 | int dy=c1->y-c2->y; |
1270 | int dy = c1->y - c2->y; |
1139 | |
1271 | |
1140 | if (dx > 32767 || dy > 32767 || dx < -32767 || dy < -32767) |
1272 | if (dx > 32767 || dy > 32767 || dx < -32767 || dy < -32767) |
1141 | return INT_MAX; |
1273 | return INT_MAX; |
1142 | else |
1274 | else |
1143 | return dx*dx+dy*dy; |
1275 | return dx * dx + dy * dy; |
1144 | } |
1276 | } |
1145 | |
1277 | |
1146 | navit_float |
|
|
1147 | transform_distance_sq_float(struct coord *c1, struct coord *c2) |
1278 | navit_float transform_distance_sq_float(struct coord *c1, struct coord *c2) |
1148 | { |
1279 | { |
1149 | int dx=c1->x-c2->x; |
1280 | int dx = c1->x - c2->x; |
1150 | int dy=c1->y-c2->y; |
1281 | int dy = c1->y - c2->y; |
1151 | return (navit_float)dx*dx+dy*dy; |
1282 | return (navit_float) dx * dx + dy * dy; |
1152 | } |
1283 | } |
1153 | |
1284 | |
1154 | int |
|
|
1155 | transform_distance_sq_pc(struct pcoord *c1, struct pcoord *c2) |
1285 | int transform_distance_sq_pc(struct pcoord *c1, struct pcoord *c2) |
1156 | { |
1286 | { |
1157 | struct coord p1,p2; |
1287 | struct coord p1, p2; |
1158 | p1.x = c1->x; p1.y = c1->y; |
1288 | p1.x = c1->x; |
1159 | p2.x = c2->x; p2.y = c2->y; |
1289 | p1.y = c1->y; |
|
|
1290 | p2.x = c2->x; |
|
|
1291 | p2.y = c2->y; |
1160 | return transform_distance_sq(&p1, &p2); |
1292 | return transform_distance_sq(&p1, &p2); |
1161 | } |
1293 | } |
1162 | |
1294 | |
1163 | int |
|
|
1164 | transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt) |
1295 | int transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt) |
1165 | { |
1296 | { |
1166 | int vx,vy,wx,wy; |
1297 | int vx, vy, wx, wy; |
1167 | int c1,c2; |
1298 | int c1, c2; |
1168 | int climit=1000000; |
1299 | int climit = 1000000; |
1169 | struct coord l; |
1300 | struct coord l; |
1170 | |
1301 | |
1171 | vx=l1->x-l0->x; |
1302 | vx = l1->x - l0->x; |
1172 | vy=l1->y-l0->y; |
1303 | vy = l1->y - l0->y; |
1173 | wx=ref->x-l0->x; |
1304 | wx = ref->x - l0->x; |
1174 | wy=ref->y-l0->y; |
1305 | wy = ref->y - l0->y; |
1175 | |
1306 | |
1176 | c1=vx*wx+vy*wy; |
1307 | c1 = vx * wx + vy * wy; |
1177 | if ( c1 <= 0 ) { |
1308 | if (c1 <= 0) |
|
|
1309 | { |
1178 | if (lpnt) |
1310 | if (lpnt) |
1179 | *lpnt=*l0; |
1311 | *lpnt = *l0; |
1180 | return transform_distance_sq(l0, ref); |
1312 | return transform_distance_sq(l0, ref); |
1181 | } |
1313 | } |
1182 | c2=vx*vx+vy*vy; |
1314 | c2 = vx * vx + vy * vy; |
1183 | if ( c2 <= c1 ) { |
1315 | if (c2 <= c1) |
|
|
1316 | { |
1184 | if (lpnt) |
1317 | if (lpnt) |
1185 | *lpnt=*l1; |
1318 | *lpnt = *l1; |
1186 | return transform_distance_sq(l1, ref); |
1319 | return transform_distance_sq(l1, ref); |
1187 | } |
1320 | } |
1188 | while (c1 > climit || c2 > climit) { |
1321 | while (c1 > climit || c2 > climit) |
|
|
1322 | { |
1189 | c1/=256; |
1323 | c1 /= 256; |
1190 | c2/=256; |
1324 | c2 /= 256; |
1191 | } |
1325 | } |
1192 | l.x=l0->x+vx*c1/c2; |
1326 | l.x = l0->x + vx * c1 / c2; |
1193 | l.y=l0->y+vy*c1/c2; |
1327 | l.y = l0->y + vy * c1 / c2; |
1194 | if (lpnt) |
1328 | if (lpnt) |
1195 | *lpnt=l; |
1329 | *lpnt = l; |
1196 | return transform_distance_sq(&l, ref); |
1330 | return transform_distance_sq(&l, ref); |
1197 | } |
1331 | } |
1198 | |
1332 | |
1199 | navit_float |
|
|
1200 | transform_distance_line_sq_float(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt) |
1333 | navit_float transform_distance_line_sq_float(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt) |
1201 | { |
1334 | { |
1202 | navit_float vx,vy,wx,wy; |
1335 | navit_float vx, vy, wx, wy; |
1203 | navit_float c1,c2; |
1336 | navit_float c1, c2; |
1204 | struct coord l; |
1337 | struct coord l; |
1205 | |
1338 | |
1206 | vx=l1->x-l0->x; |
1339 | vx = l1->x - l0->x; |
1207 | vy=l1->y-l0->y; |
1340 | vy = l1->y - l0->y; |
1208 | wx=ref->x-l0->x; |
1341 | wx = ref->x - l0->x; |
1209 | wy=ref->y-l0->y; |
1342 | wy = ref->y - l0->y; |
1210 | |
1343 | |
1211 | c1=vx*wx+vy*wy; |
1344 | c1 = vx * wx + vy * wy; |
1212 | if ( c1 <= 0 ) { |
1345 | if (c1 <= 0) |
|
|
1346 | { |
1213 | if (lpnt) |
1347 | if (lpnt) |
1214 | *lpnt=*l0; |
1348 | *lpnt = *l0; |
1215 | return transform_distance_sq_float(l0, ref); |
1349 | return transform_distance_sq_float(l0, ref); |
1216 | } |
1350 | } |
1217 | c2=vx*vx+vy*vy; |
1351 | c2 = vx * vx + vy * vy; |
1218 | if ( c2 <= c1 ) { |
1352 | if (c2 <= c1) |
|
|
1353 | { |
1219 | if (lpnt) |
1354 | if (lpnt) |
1220 | *lpnt=*l1; |
1355 | *lpnt = *l1; |
1221 | return transform_distance_sq_float(l1, ref); |
1356 | return transform_distance_sq_float(l1, ref); |
1222 | } |
1357 | } |
1223 | l.x=l0->x+vx*c1/c2; |
1358 | l.x = l0->x + vx * c1 / c2; |
1224 | l.y=l0->y+vy*c1/c2; |
1359 | l.y = l0->y + vy * c1 / c2; |
1225 | if (lpnt) |
1360 | if (lpnt) |
1226 | *lpnt=l; |
1361 | *lpnt = l; |
1227 | return transform_distance_sq_float(&l, ref); |
1362 | return transform_distance_sq_float(&l, ref); |
1228 | } |
1363 | } |
1229 | |
1364 | |
1230 | |
|
|
1231 | int |
|
|
1232 | transform_distance_polyline_sq__v2(struct coord *c, int count, struct coord *ref) |
1365 | int transform_distance_polyline_sq__v2(struct coord *c, int count, struct coord *ref) |
1233 | { |
1366 | { |
1234 | int i,dist,distn; |
1367 | int i, dist, distn; |
1235 | |
1368 | |
1236 | if (count < 2) |
1369 | if (count < 2) |
1237 | { |
1370 | { |
1238 | int d; |
1371 | int d; |
1239 | d = transform_distance_sq(&c[0], ref); |
1372 | d = transform_distance_sq(&c[0], ref); |
1240 | //dbg(0,"d=%d\n", d); |
1373 | //dbg(0,"d=%d\n", d); |
1241 | return d; |
1374 | return d; |
1242 | } |
1375 | } |
1243 | |
1376 | |
1244 | dist=transform_distance_point2line_sq(ref, &c[0], &c[1]); |
1377 | dist = transform_distance_point2line_sq(ref, &c[0], &c[1]); |
1245 | //dbg(0,"dist1:%d\n", dist); |
1378 | //dbg(0,"dist1:%d\n", dist); |
1246 | |
1379 | |
1247 | for (i = 2; i < count; i++) |
1380 | for (i = 2; i < count; i++) |
1248 | { |
1381 | { |
1249 | distn=transform_distance_point2line_sq(ref, &c[i-1], &c[i]); |
1382 | distn = transform_distance_point2line_sq(ref, &c[i - 1], &c[i]); |
1250 | //dbg(0,"dist2:%d\n", dist); |
1383 | //dbg(0,"dist2:%d\n", dist); |
1251 | if (distn < dist) |
1384 | if (distn < dist) |
1252 | { |
1385 | { |
1253 | dist=distn; |
1386 | dist = distn; |
1254 | } |
1387 | } |
1255 | } |
1388 | } |
1256 | //dbg(0,"dist final:%d\n", dist); |
1389 | //dbg(0,"dist final:%d\n", dist); |
1257 | return dist; |
1390 | return dist; |
1258 | } |
1391 | } |
1259 | |
1392 | |
1260 | |
|
|
1261 | |
|
|
1262 | int |
|
|
1263 | transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos) |
1393 | int transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos) |
1264 | { |
1394 | { |
1265 | int i,dist,distn; |
1395 | int i, dist, distn; |
1266 | struct coord lp; |
1396 | struct coord lp; |
1267 | if (count < 2) |
1397 | if (count < 2) |
1268 | { |
1398 | { |
1269 | // dbg(0,"1\n"); |
1399 | // dbg(0,"1\n"); |
1270 | return INT_MAX; |
1400 | return INT_MAX; |
1271 | } |
1401 | } |
1272 | if (pos) |
1402 | if (pos) |
1273 | { |
1403 | { |
1274 | *pos=0; |
1404 | *pos = 0; |
1275 | } |
1405 | } |
1276 | |
1406 | |
1277 | dist=transform_distance_line_sq(&c[0], &c[1], ref, lpnt); |
1407 | dist = transform_distance_line_sq(&c[0], &c[1], ref, lpnt); |
1278 | // dbg(0,"dist:%d\n", dist); |
1408 | // dbg(0,"dist:%d\n", dist); |
1279 | |
1409 | |
1280 | for (i = 2; i < count; i++) |
1410 | for (i = 2; i < count; i++) |
1281 | { |
1411 | { |
1282 | distn=transform_distance_line_sq(&c[i-1], &c[i], ref, &lp); |
1412 | distn = transform_distance_line_sq(&c[i - 1], &c[i], ref, &lp); |
1283 | if (distn < dist) |
1413 | if (distn < dist) |
1284 | { |
1414 | { |
1285 | dist=distn; |
1415 | dist = distn; |
1286 | if (lpnt) |
1416 | if (lpnt) |
1287 | { |
1417 | { |
1288 | *lpnt=lp; |
1418 | *lpnt = lp; |
1289 | } |
1419 | } |
1290 | if (pos) |
1420 | if (pos) |
1291 | { |
1421 | { |
1292 | *pos=i-1; |
1422 | *pos = i - 1; |
1293 | } |
1423 | } |
1294 | } |
1424 | } |
1295 | } |
1425 | } |
1296 | return dist; |
1426 | return dist; |
1297 | } |
1427 | } |
1298 | |
1428 | |
1299 | int |
|
|
1300 | transform_douglas_peucker(struct coord *in, int count, int dist_sq, struct coord *out) |
1429 | int transform_douglas_peucker(struct coord *in, int count, int dist_sq, struct coord *out) |
1301 | { |
1430 | { |
1302 | int ret=0; |
1431 | int ret = 0; |
1303 | int i,d,dmax=0, idx=0; |
1432 | int i, d, dmax = 0, idx = 0; |
1304 | for (i = 1; i < count-2 ; i++) { |
1433 | for (i = 1; i < count - 2; i++) |
|
|
1434 | { |
1305 | d=transform_distance_line_sq(&in[0], &in[count-1], &in[i], NULL); |
1435 | d = transform_distance_line_sq(&in[0], &in[count - 1], &in[i], NULL); |
1306 | if (d > dmax) { |
1436 | if (d > dmax) |
|
|
1437 | { |
1307 | idx=i; |
1438 | idx = i; |
1308 | dmax=d; |
1439 | dmax = d; |
1309 | } |
1440 | } |
1310 | } |
1441 | } |
1311 | if (dmax > dist_sq) { |
1442 | if (dmax > dist_sq) |
|
|
1443 | { |
1312 | ret=transform_douglas_peucker(in, idx, dist_sq, out)-1; |
1444 | ret = transform_douglas_peucker(in, idx, dist_sq, out) - 1; |
1313 | ret+=transform_douglas_peucker(in+idx, count-idx, dist_sq, out+ret); |
1445 | ret += transform_douglas_peucker(in + idx, count - idx, dist_sq, out + ret); |
1314 | } else { |
1446 | } |
|
|
1447 | else |
|
|
1448 | { |
1315 | if (count > 0) |
1449 | if (count > 0) |
1316 | out[ret++]=in[0]; |
1450 | out[ret++] = in[0]; |
1317 | if (count > 1) |
1451 | if (count > 1) |
1318 | out[ret++]=in[count-1]; |
1452 | out[ret++] = in[count - 1]; |
1319 | } |
1453 | } |
1320 | return ret; |
1454 | return ret; |
1321 | } |
1455 | } |
1322 | |
1456 | |
1323 | int |
|
|
1324 | transform_douglas_peucker_float(struct coord *in, int count, navit_float dist_sq, struct coord *out) |
1457 | int transform_douglas_peucker_float(struct coord *in, int count, navit_float dist_sq, struct coord *out) |
1325 | { |
1458 | { |
1326 | int ret=0; |
1459 | int ret = 0; |
1327 | int i,idx=0; |
1460 | int i, idx = 0; |
1328 | navit_float d,dmax=0; |
1461 | navit_float d, dmax = 0; |
1329 | for (i = 1; i < count-2 ; i++) { |
1462 | for (i = 1; i < count - 2; i++) |
|
|
1463 | { |
1330 | d=transform_distance_line_sq_float(&in[0], &in[count-1], &in[i], NULL); |
1464 | d = transform_distance_line_sq_float(&in[0], &in[count - 1], &in[i], NULL); |
1331 | if (d > dmax) { |
1465 | if (d > dmax) |
|
|
1466 | { |
1332 | idx=i; |
1467 | idx = i; |
1333 | dmax=d; |
1468 | dmax = d; |
1334 | } |
1469 | } |
1335 | } |
1470 | } |
1336 | if (dmax > dist_sq) { |
1471 | if (dmax > dist_sq) |
|
|
1472 | { |
1337 | ret=transform_douglas_peucker_float(in, idx, dist_sq, out)-1; |
1473 | ret = transform_douglas_peucker_float(in, idx, dist_sq, out) - 1; |
1338 | ret+=transform_douglas_peucker_float(in+idx, count-idx, dist_sq, out+ret); |
1474 | ret += transform_douglas_peucker_float(in + idx, count - idx, dist_sq, out + ret); |
1339 | } else { |
1475 | } |
|
|
1476 | else |
|
|
1477 | { |
1340 | if (count > 0) |
1478 | if (count > 0) |
1341 | out[ret++]=in[0]; |
1479 | out[ret++] = in[0]; |
1342 | if (count > 1) |
1480 | if (count > 1) |
1343 | out[ret++]=in[count-1]; |
1481 | out[ret++] = in[count - 1]; |
1344 | } |
1482 | } |
1345 | return ret; |
1483 | return ret; |
1346 | } |
1484 | } |
1347 | |
1485 | |
1348 | |
|
|
1349 | void |
|
|
1350 | transform_print_deg(double deg) |
1486 | void transform_print_deg(double deg) |
1351 | { |
1487 | { |
1352 | printf("%2.0f:%2.0f:%2.4f", floor(deg), fmod(deg*60,60), fmod(deg*3600,60)); |
1488 | printf("%2.0f:%2.0f:%2.4f", floor(deg), fmod(deg * 60, 60), fmod(deg * 3600, 60)); |
1353 | } |
1489 | } |
1354 | |
1490 | |
1355 | #ifdef AVOID_FLOAT |
1491 | #ifdef AVOID_FLOAT |
|
|
1492 | static int tab_atan[]= |
1356 | static int tab_atan[]={0,262,524,787,1051,1317,1584,1853,2126,2401,2679,2962,3249,3541,3839,4142,4452,4770,5095,5430,5774,6128,6494,6873,7265,7673,8098,8541,9004,9490,10000,10538}; |
1493 | { 0,262,524,787,1051,1317,1584,1853,2126,2401,2679,2962,3249,3541,3839,4142,4452,4770,5095,5430,5774,6128,6494,6873,7265,7673,8098,8541,9004,9490,10000,10538}; |
1357 | |
1494 | |
1358 | static int |
1495 | static int |
1359 | atan2_int_lookup(int val) |
1496 | atan2_int_lookup(int val) |
1360 | { |
1497 | { |
1361 | int len=sizeof(tab_atan)/sizeof(int); |
1498 | int len=sizeof(tab_atan)/sizeof(int); |
1362 | int i=len/2; |
1499 | int i=len/2; |
1363 | int p=i-1; |
1500 | int p=i-1; |
1364 | for (;;) { |
1501 | for (;;) |
|
|
1502 | { |
1365 | i>>=1; |
1503 | i>>=1; |
1366 | if (val < tab_atan[p]) |
1504 | if (val < tab_atan[p]) |
1367 | p-=i; |
1505 | p-=i; |
1368 | else |
1506 | else |
1369 | if (val < tab_atan[p+1]) |
1507 | if (val < tab_atan[p+1]) |
1370 | return p+(p>>1); |
1508 | return p+(p>>1); |
1371 | else |
1509 | else |
1372 | p+=i; |
1510 | p+=i; |
1373 | } |
1511 | } |
1374 | } |
1512 | } |
1375 | |
1513 | |
1376 | static int |
1514 | static int |
1377 | atan2_int(int dx, int dy) |
1515 | atan2_int(int dx, int dy) |
1378 | { |
1516 | { |
1379 | int mul=1,add=0,ret; |
1517 | int mul=1,add=0,ret; |
1380 | if (! dx) { |
1518 | if (! dx) |
|
|
1519 | { |
1381 | return dy < 0 ? 180 : 0; |
1520 | return dy < 0 ? 180 : 0; |
1382 | } |
1521 | } |
1383 | if (! dy) { |
1522 | if (! dy) |
|
|
1523 | { |
1384 | return dx < 0 ? -90 : 90; |
1524 | return dx < 0 ? -90 : 90; |
1385 | } |
1525 | } |
1386 | if (dx < 0) { |
1526 | if (dx < 0) |
|
|
1527 | { |
1387 | dx=-dx; |
1528 | dx=-dx; |
1388 | mul=-1; |
1529 | mul=-1; |
1389 | } |
1530 | } |
1390 | if (dy < 0) { |
1531 | if (dy < 0) |
|
|
1532 | { |
1391 | dy=-dy; |
1533 | dy=-dy; |
1392 | add=180*mul; |
1534 | add=180*mul; |
1393 | mul*=-1; |
1535 | mul*=-1; |
1394 | } |
1536 | } |
1395 | while (dx > 20000 || dy > 20000) { |
1537 | while (dx > 20000 || dy > 20000) |
|
|
1538 | { |
1396 | dx/=10; |
1539 | dx/=10; |
1397 | dy/=10; |
1540 | dy/=10; |
1398 | } |
1541 | } |
1399 | if (dx > dy) { |
1542 | if (dx > dy) |
|
|
1543 | { |
1400 | ret=90-atan2_int_lookup(dy*10000/dx); |
1544 | ret=90-atan2_int_lookup(dy*10000/dx); |
1401 | } else { |
1545 | } |
|
|
1546 | else |
|
|
1547 | { |
1402 | ret=atan2_int_lookup(dx*10000/dy); |
1548 | ret=atan2_int_lookup(dx*10000/dy); |
1403 | } |
1549 | } |
1404 | return ret*mul+add; |
1550 | return ret*mul+add; |
1405 | } |
1551 | } |
1406 | #endif |
1552 | #endif |
1407 | |
1553 | |
1408 | int |
|
|
1409 | transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir) |
1554 | int transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir) |
1410 | { |
1555 | { |
1411 | int dx=c2->x-c1->x; |
1556 | int dx = c2->x - c1->x; |
1412 | int dy=c2->y-c1->y; |
1557 | int dy = c2->y - c1->y; |
1413 | #ifndef AVOID_FLOAT |
1558 | #ifndef AVOID_FLOAT |
1414 | double angle; |
1559 | double angle; |
1415 | angle=atan2(dx,dy); |
1560 | angle = atan2(dx, dy); |
1416 | angle*=180/M_PI; |
1561 | angle *= 180 / M_PI; |
1417 | #else |
1562 | #else |
1418 | int angle; |
1563 | int angle; |
1419 | angle=atan2_int(dx,dy); |
1564 | angle=atan2_int(dx,dy); |
1420 | #endif |
1565 | #endif |
1421 | if (dir == -1) |
1566 | if (dir == -1) |
1422 | angle=angle-180; |
1567 | angle = angle - 180; |
1423 | if (angle < 0) |
1568 | if (angle < 0) |
1424 | angle+=360; |
1569 | angle += 360; |
1425 | return angle; |
1570 | return angle; |
1426 | } |
1571 | } |
1427 | |
1572 | |
1428 | int |
|
|
1429 | transform_within_border(struct transformation *this_, struct point *p, int border) |
1573 | int transform_within_border(struct transformation *this_, struct point *p, int border) |
1430 | { |
1574 | { |
1431 | struct map_selection *ms=this_->screen_sel; |
1575 | struct map_selection *ms = this_->screen_sel; |
1432 | while (ms) { |
1576 | while (ms) |
|
|
1577 | { |
1433 | struct point_rect *r=&ms->u.p_rect; |
1578 | struct point_rect *r = &ms->u.p_rect; |
1434 | if (p->x >= r->lu.x+border && p->x <= r->rl.x-border && |
1579 | if (p->x >= r->lu.x + border && p->x <= r->rl.x - border && p->y >= r->lu.y + border && p->y <= r->rl.y - border) |
1435 | p->y >= r->lu.y+border && p->y <= r->rl.y-border) |
|
|
1436 | return 1; |
1580 | return 1; |
1437 | ms=ms->next; |
1581 | ms = ms->next; |
1438 | } |
1582 | } |
1439 | return 0; |
1583 | return 0; |
1440 | } |
1584 | } |
1441 | |
1585 | |
1442 | int |
|
|
1443 | transform_within_dist_point(struct coord *ref, struct coord *c, int dist) |
1586 | int transform_within_dist_point(struct coord *ref, struct coord *c, int dist) |
1444 | { |
1587 | { |
1445 | if (c->x-dist > ref->x) |
1588 | if (c->x - dist > ref->x) |
1446 | return 0; |
1589 | return 0; |
1447 | if (c->x+dist < ref->x) |
1590 | if (c->x + dist < ref->x) |
1448 | return 0; |
1591 | return 0; |
1449 | if (c->y-dist > ref->y) |
1592 | if (c->y - dist > ref->y) |
1450 | return 0; |
1593 | return 0; |
1451 | if (c->y+dist < ref->y) |
1594 | if (c->y + dist < ref->y) |
1452 | return 0; |
1595 | return 0; |
1453 | if ((c->x-ref->x)*(c->x-ref->x) + (c->y-ref->y)*(c->y-ref->y) <= dist*dist) |
1596 | if ((c->x - ref->x) * (c->x - ref->x) + (c->y - ref->y) * (c->y - ref->y) <= dist * dist) |
1454 | return 1; |
1597 | return 1; |
1455 | return 0; |
1598 | return 0; |
1456 | } |
1599 | } |
1457 | |
1600 | |
1458 | int |
|
|
1459 | transform_within_dist_line(struct coord *ref, struct coord *c0, struct coord *c1, int dist) |
1601 | int transform_within_dist_line(struct coord *ref, struct coord *c0, struct coord *c1, int dist) |
1460 | { |
1602 | { |
1461 | int vx,vy,wx,wy; |
1603 | int vx, vy, wx, wy; |
1462 | int n1,n2; |
1604 | int n1, n2; |
1463 | struct coord lc; |
1605 | struct coord lc; |
1464 | |
1606 | |
1465 | if (c0->x < c1->x) { |
1607 | if (c0->x < c1->x) |
|
|
1608 | { |
1466 | if (c0->x-dist > ref->x) |
1609 | if (c0->x - dist > ref->x) |
1467 | return 0; |
1610 | return 0; |
1468 | if (c1->x+dist < ref->x) |
1611 | if (c1->x + dist < ref->x) |
1469 | return 0; |
1612 | return 0; |
1470 | } else { |
1613 | } |
|
|
1614 | else |
|
|
1615 | { |
1471 | if (c1->x-dist > ref->x) |
1616 | if (c1->x - dist > ref->x) |
1472 | return 0; |
1617 | return 0; |
1473 | if (c0->x+dist < ref->x) |
1618 | if (c0->x + dist < ref->x) |
1474 | return 0; |
1619 | return 0; |
1475 | } |
1620 | } |
1476 | if (c0->y < c1->y) { |
1621 | if (c0->y < c1->y) |
|
|
1622 | { |
1477 | if (c0->y-dist > ref->y) |
1623 | if (c0->y - dist > ref->y) |
1478 | return 0; |
1624 | return 0; |
1479 | if (c1->y+dist < ref->y) |
1625 | if (c1->y + dist < ref->y) |
1480 | return 0; |
1626 | return 0; |
1481 | } else { |
1627 | } |
|
|
1628 | else |
|
|
1629 | { |
1482 | if (c1->y-dist > ref->y) |
1630 | if (c1->y - dist > ref->y) |
1483 | return 0; |
1631 | return 0; |
1484 | if (c0->y+dist < ref->y) |
1632 | if (c0->y + dist < ref->y) |
1485 | return 0; |
1633 | return 0; |
1486 | } |
1634 | } |
1487 | vx=c1->x-c0->x; |
1635 | vx = c1->x - c0->x; |
1488 | vy=c1->y-c0->y; |
1636 | vy = c1->y - c0->y; |
1489 | wx=ref->x-c0->x; |
1637 | wx = ref->x - c0->x; |
1490 | wy=ref->y-c0->y; |
1638 | wy = ref->y - c0->y; |
1491 | |
1639 | |
1492 | n1=vx*wx+vy*wy; |
1640 | n1 = vx * wx + vy * wy; |
1493 | if ( n1 <= 0 ) |
1641 | if (n1 <= 0) |
1494 | return transform_within_dist_point(ref, c0, dist); |
1642 | return transform_within_dist_point(ref, c0, dist); |
1495 | n2=vx*vx+vy*vy; |
1643 | n2 = vx * vx + vy * vy; |
1496 | if ( n2 <= n1 ) |
1644 | if (n2 <= n1) |
1497 | return transform_within_dist_point(ref, c1, dist); |
1645 | return transform_within_dist_point(ref, c1, dist); |
1498 | |
1646 | |
1499 | lc.x=c0->x+vx*n1/n2; |
1647 | lc.x = c0->x + vx * n1 / n2; |
1500 | lc.y=c0->y+vy*n1/n2; |
1648 | lc.y = c0->y + vy * n1 / n2; |
1501 | return transform_within_dist_point(ref, &lc, dist); |
1649 | return transform_within_dist_point(ref, &lc, dist); |
1502 | } |
1650 | } |
1503 | |
1651 | |
1504 | int |
|
|
1505 | transform_within_dist_polyline(struct coord *ref, struct coord *c, int count, int close, int dist) |
1652 | int transform_within_dist_polyline(struct coord *ref, struct coord *c, int count, int close, int dist) |
1506 | { |
1653 | { |
1507 | int i; |
1654 | int i; |
1508 | for (i = 0 ; i < count-1 ; i++) { |
1655 | for (i = 0; i < count - 1; i++) |
|
|
1656 | { |
1509 | if (transform_within_dist_line(ref,c+i,c+i+1,dist)) { |
1657 | if (transform_within_dist_line(ref, c + i, c + i + 1, dist)) |
|
|
1658 | { |
1510 | return 1; |
1659 | return 1; |
1511 | } |
1660 | } |
1512 | } |
1661 | } |
1513 | if (close) |
1662 | if (close) |
1514 | return (transform_within_dist_line(ref,c,c+count-1,dist)); |
1663 | return (transform_within_dist_line(ref, c, c + count - 1, dist)); |
1515 | return 0; |
1664 | return 0; |
1516 | } |
1665 | } |
1517 | |
1666 | |
1518 | int |
|
|
1519 | transform_within_dist_polygon(struct coord *ref, struct coord *c, int count, int dist) |
1667 | int transform_within_dist_polygon(struct coord *ref, struct coord *c, int count, int dist) |
1520 | { |
1668 | { |
1521 | int i, j, ci = 0; |
1669 | int i, j, ci = 0; |
1522 | for (i = 0, j = count-1; i < count; j = i++) { |
1670 | for (i = 0, j = count - 1; i < count; j = i++) |
1523 | if ((((c[i].y <= ref->y) && ( ref->y < c[j].y )) || |
1671 | { |
1524 | ((c[j].y <= ref->y) && ( ref->y < c[i].y))) && |
1672 | if ((((c[i].y <= ref->y) && (ref->y < c[j].y)) || ((c[j].y <= ref->y) && (ref->y < c[i].y))) && (ref->x < (c[j].x - c[i].x) * (ref->y - c[i].y) / (c[j].y - c[i].y) + c[i].x)) |
1525 | (ref->x < (c[j].x - c[i].x) * (ref->y - c[i].y) / (c[j].y - c[i].y) + c[i].x)) |
|
|
1526 | ci = !ci; |
1673 | ci = !ci; |
1527 | } |
1674 | } |
1528 | if (! ci) { |
1675 | if (!ci) |
|
|
1676 | { |
1529 | if (dist) |
1677 | if (dist) |
1530 | return transform_within_dist_polyline(ref, c, count, dist, 1); |
1678 | return transform_within_dist_polyline(ref, c, count, dist, 1); |
1531 | else |
1679 | else |
1532 | return 0; |
1680 | return 0; |
1533 | } |
1681 | } |
1534 | return 1; |
1682 | return 1; |
1535 | } |
1683 | } |
1536 | |
1684 | |
1537 | int |
|
|
1538 | transform_within_dist_item(struct coord *ref, enum item_type type, struct coord *c, int count, int dist) |
1685 | int transform_within_dist_item(struct coord *ref, enum item_type type, struct coord *c, int count, int dist) |
1539 | { |
1686 | { |
1540 | if (type < type_line) |
1687 | if (type < type_line) |
1541 | return transform_within_dist_point(ref, c, dist); |
1688 | return transform_within_dist_point(ref, c, dist); |
1542 | if (type < type_area) |
1689 | if (type < type_area) |
1543 | return transform_within_dist_polyline(ref, c, count, 0, dist); |
1690 | return transform_within_dist_polyline(ref, c, count, 0, dist); |
1544 | return transform_within_dist_polygon(ref, c, count, dist); |
1691 | return transform_within_dist_polygon(ref, c, count, dist); |
1545 | } |
1692 | } |
1546 | |
1693 | |
1547 | void |
|
|
1548 | transform_copy(struct transformation *src, struct transformation *dst) |
1694 | void transform_copy(struct transformation *src, struct transformation *dst) |
1549 | { |
1695 | { |
1550 | memcpy(dst, src, sizeof(*src)); |
1696 | memcpy(dst, src, sizeof(*src)); |
1551 | } |
1697 | } |
1552 | |
1698 | |
1553 | void |
|
|
1554 | transform_destroy(struct transformation *t) |
1699 | void transform_destroy(struct transformation *t) |
1555 | { |
1700 | { |
1556 | g_free(t); |
1701 | g_free(t); |
1557 | } |
1702 | } |
1558 | |
1703 | |
1559 | |
|
|
1560 | /* |
1704 | /* |
1561 | Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent. |
1705 | Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent. |
1562 | |
1706 | |
1563 | L = latitude in radians (positive north) |
1707 | L = latitude in radians (positive north) |
1564 | Lo = longitude in radians (positive east) |
1708 | Lo = longitude in radians (positive east) |
1565 | E = easting (meters) |
1709 | E = easting (meters) |
1566 | N = northing (meters) |
1710 | N = northing (meters) |
1567 | |
1711 | |
1568 | For the sphere |
1712 | For the sphere |
1569 | |
1713 | |
1570 | E = r Lo |
1714 | E = r Lo |
1571 | N = r ln [ tan (pi/4 + L/2) ] |
1715 | N = r ln [ tan (pi/4 + L/2) ] |
1572 | |
1716 | |
1573 | where |
1717 | where |
1574 | |
1718 | |
1575 | r = radius of the sphere (meters) |
1719 | r = radius of the sphere (meters) |
1576 | ln() is the natural logarithm |
1720 | ln() is the natural logarithm |
1577 | |
1721 | |
1578 | For the ellipsoid |
1722 | For the ellipsoid |
1579 | |
1723 | |
1580 | E = a Lo |
1724 | E = a Lo |
1581 | N = a * ln ( tan (pi/4 + L/2) * ( (1 - e * sin (L)) / (1 + e * sin (L))) ** (e/2) ) |
1725 | N = a * ln ( tan (pi/4 + L/2) * ( (1 - e * sin (L)) / (1 + e * sin (L))) ** (e/2) ) |
1582 | |
1726 | |
1583 | |
1727 | |
1584 | e |
1728 | e |
1585 | - |
1729 | - |
1586 | pi L 1 - e sin(L) 2 |
1730 | pi L 1 - e sin(L) 2 |
1587 | = a ln( tan( ---- + ---) (--------------) ) |
1731 | = a ln( tan( ---- + ---) (--------------) ) |
1588 | 4 2 1 + e sin(L) |
1732 | 4 2 1 + e sin(L) |
1589 | |
1733 | |
1590 | |
1734 | |
1591 | where |
1735 | where |
1592 | |
1736 | |
1593 | a = the length of the semi-major axis of the ellipsoid (meters) |
1737 | a = the length of the semi-major axis of the ellipsoid (meters) |
1594 | e = the first eccentricity of the ellipsoid |
1738 | e = the first eccentricity of the ellipsoid |
1595 | |
1739 | |
1596 | |
1740 | |
1597 | */ |
1741 | */ |
1598 | |
1742 | |
|
|
1743 | void transform_init(void) |
|
|
1744 | { |
|
|
1745 | #if 0 |
|
|
1746 | if (global_transform_hash == NULL) |
|
|
1747 | { |
|
|
1748 | dbg(0,"enter\n"); |
|
|
1749 | global_transform_hash=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, g_free_func); |
|
|
1750 | dbg(0,"leave\n"); |
|
|
1751 | } |
|
|
1752 | if (global_transform_hash2 == NULL) |
|
|
1753 | { |
|
|
1754 | dbg(0,"enter\n"); |
|
|
1755 | global_transform_hash2=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, g_free_func); |
|
|
1756 | dbg(0,"leave\n"); |
|
|
1757 | } |
|
|
1758 | #endif |
|
|
1759 | } |
1599 | |
1760 | |