PostGIS  2.1.10dev-r@@SVN_REVISION@@
cu_algorithm.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: cu_algorithm.c 14427 2015-11-25 20:12:55Z pramsey $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * http://postgis.net
6  * Copyright 2008 Paul Ramsey
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU General Public Licence. See the COPYING file.
10  *
11  **********************************************************************/
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include "CUnit/Basic.h"
17 
18 #include "liblwgeom_internal.h"
19 #include "cu_tester.h"
20 
21 /*
22 ** Global variables used by tests below
23 */
24 
25 /* Two-point objects */
26 POINTARRAY *pa21 = NULL;
27 POINTARRAY *pa22 = NULL;
28 LWLINE *l21 = NULL;
29 LWLINE *l22 = NULL;
30 /* Parsing support */
32 
33 
34 /*
35 ** The suite initialization function.
36 ** Create any re-used objects.
37 */
38 static int init_cg_suite(void)
39 {
40  pa21 = ptarray_construct(0, 0, 2);
41  pa22 = ptarray_construct(0, 0, 2);
42  l21 = lwline_construct(SRID_UNKNOWN, NULL, pa21);
43  l22 = lwline_construct(SRID_UNKNOWN, NULL, pa22);
44  return 0;
45 
46 }
47 
48 /*
49 ** The suite cleanup function.
50 ** Frees any global objects.
51 */
52 static int clean_cg_suite(void)
53 {
54  if ( l21 ) lwline_free(l21);
55  if ( l22 ) lwline_free(l22);
56  return 0;
57 }
58 
59 /*
60 ** Test left/right side.
61 */
62 static void test_lw_segment_side(void)
63 {
64  int rv = 0;
65  POINT2D p1, p2, q;
66 
67  /* Vertical line at x=0 */
68  p1.x = 0.0;
69  p1.y = 0.0;
70  p2.x = 0.0;
71  p2.y = 1.0;
72 
73  /* On the left */
74  q.x = -2.0;
75  q.y = 1.5;
76  rv = lw_segment_side(&p1, &p2, &q);
77  //printf("left %g\n",rv);
78  CU_ASSERT(rv < 0);
79 
80  /* On the right */
81  q.x = 2.0;
82  rv = lw_segment_side(&p1, &p2, &q);
83  //printf("right %g\n",rv);
84  CU_ASSERT(rv > 0);
85 
86  /* On the line */
87  q.x = 0.0;
88  rv = lw_segment_side(&p1, &p2, &q);
89  //printf("on line %g\n",rv);
90  CU_ASSERT_EQUAL(rv, 0);
91 
92 }
93 
94 static void test_lw_arc_center(void)
95 {
96 /* double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result); */
97  POINT2D c1;
98  double d1;
99  POINT2D p1, p2, p3;
100 
101  p1.x = 2047538.600;
102  p1.y = 7268770.435;
103  p2.x = 2047538.598;
104  p2.y = 7268770.435;
105  p3.x = 2047538.596;
106  p3.y = 7268770.436;
107 
108  d1 = lw_arc_center(&p1, &p2, &p3, &c1);
109 
110  CU_ASSERT_DOUBLE_EQUAL(d1, 0.0046097720751, 0.0001);
111  CU_ASSERT_DOUBLE_EQUAL(c1.x, 2047538.599, 0.001);
112  CU_ASSERT_DOUBLE_EQUAL(c1.y, 7268770.4395, 0.001);
113 
114  // printf("lw_arc_center: (%12.12g, %12.12g) %12.12g\n", c1.x, c1.y, d1);
115 }
116 
117 /*
118 ** Test crossings side.
119 */
120 static void test_lw_segment_intersects(void)
121 {
122 
123 #define setpoint(p, x1, y1) {(p).x = (x1); (p).y = (y1);}
124 
125  POINT2D p1, p2, q1, q2;
126 
127  /* P: Vertical line at x=0 */
128  setpoint(p1, 0.0, 0.0);
129  p1.x = 0.0;
130  p1.y = 0.0;
131  p2.x = 0.0;
132  p2.y = 1.0;
133 
134  /* Q: Horizontal line crossing left to right */
135  q1.x = -0.5;
136  q1.y = 0.5;
137  q2.x = 0.5;
138  q2.y = 0.5;
139  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT );
140 
141  /* Q: Horizontal line crossing right to left */
142  q1.x = 0.5;
143  q1.y = 0.5;
144  q2.x = -0.5;
145  q2.y = 0.5;
146  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );
147 
148  /* Q: Horizontal line not crossing right to left */
149  q1.x = 0.5;
150  q1.y = 1.5;
151  q2.x = -0.5;
152  q2.y = 1.5;
153  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );
154 
155  /* Q: Horizontal line crossing at second vertex right to left */
156  q1.x = 0.5;
157  q1.y = 1.0;
158  q2.x = -0.5;
159  q2.y = 1.0;
160  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );
161 
162  /* Q: Horizontal line crossing at first vertex right to left */
163  q1.x = 0.5;
164  q1.y = 0.0;
165  q2.x = -0.5;
166  q2.y = 0.0;
167  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );
168 
169  /* Q: Diagonal line with large range crossing at first vertex right to left */
170  q1.x = 0.5;
171  q1.y = 10.0;
172  q2.x = -0.5;
173  q2.y = -10.0;
174  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );
175 
176  /* Q: Diagonal line with large range crossing at second vertex right to left */
177  q1.x = 0.5;
178  q1.y = 11.0;
179  q2.x = -0.5;
180  q2.y = -9.0;
181  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );
182 
183  /* Q: Horizontal touching from left at second vertex*/
184  q1.x = -0.5;
185  q1.y = 0.5;
186  q2.x = 0.0;
187  q2.y = 0.5;
188  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );
189 
190  /* Q: Horizontal touching from right at first vertex */
191  q1.x = 0.0;
192  q1.y = 0.5;
193  q2.x = 0.5;
194  q2.y = 0.5;
195  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT );
196 
197  /* Q: Horizontal touching from left and far below on second vertex */
198  q1.x = -0.5;
199  q1.y = -10.5;
200  q2.x = 0.0;
201  q2.y = 0.5;
202  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );
203 
204  /* Q: Horizontal touching from right and far above on second vertex */
205  q1.x = 0.5;
206  q1.y = 10.5;
207  q2.x = 0.0;
208  q2.y = 0.5;
209  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );
210 
211  /* Q: Co-linear from top */
212  q1.x = 0.0;
213  q1.y = 10.0;
214  q2.x = 0.0;
215  q2.y = 0.5;
216  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );
217 
218  /* Q: Co-linear from bottom */
219  q1.x = 0.0;
220  q1.y = -10.0;
221  q2.x = 0.0;
222  q2.y = 0.5;
223  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );
224 
225  /* Q: Co-linear contained */
226  q1.x = 0.0;
227  q1.y = 0.4;
228  q2.x = 0.0;
229  q2.y = 0.5;
230  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );
231 
232  /* Q: Horizontal touching at end point from left */
233  q1.x = -0.5;
234  q1.y = 1.0;
235  q2.x = 0.0;
236  q2.y = 1.0;
237  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );
238 
239  /* Q: Horizontal touching at end point from right */
240  q1.x = 0.0;
241  q1.y = 1.0;
242  q2.x = 0.0;
243  q2.y = 0.5;
244  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );
245 
246  /* Q: Horizontal touching at start point from left */
247  q1.x = 0.0;
248  q1.y = 0.0;
249  q2.x = -0.5;
250  q2.y = 0.0;
251  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );
252 
253  /* Q: Horizontal touching at start point from right */
254  q1.x = 0.0;
255  q1.y = 0.0;
256  q2.x = 0.5;
257  q2.y = 0.0;
258  CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT );
259 
260 }
261 
263 {
264 
265  POINT4D p;
266 
267  /*
268  ** Simple test, two two-point lines
269  */
270 
271  /* Vertical line from 0,0 to 1,1 */
272  p.x = 0.0;
273  p.y = 0.0;
274  ptarray_set_point4d(pa21, 0, &p);
275  p.y = 1.0;
276  ptarray_set_point4d(pa21, 1, &p);
277 
278  /* Horizontal, crossing mid-segment */
279  p.x = -0.5;
280  p.y = 0.5;
281  ptarray_set_point4d(pa22, 0, &p);
282  p.x = 0.5;
283  ptarray_set_point4d(pa22, 1, &p);
284 
285  CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT );
286 
287  /* Horizontal, crossing at top end vertex (end crossings don't count) */
288  p.x = -0.5;
289  p.y = 1.0;
290  ptarray_set_point4d(pa22, 0, &p);
291  p.x = 0.5;
292  ptarray_set_point4d(pa22, 1, &p);
293 
294  CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS );
295 
296  /* Horizontal, crossing at bottom end vertex */
297  p.x = -0.5;
298  p.y = 0.0;
299  ptarray_set_point4d(pa22, 0, &p);
300  p.x = 0.5;
301  ptarray_set_point4d(pa22, 1, &p);
302 
303  CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT );
304 
305  /* Horizontal, no crossing */
306  p.x = -0.5;
307  p.y = 2.0;
308  ptarray_set_point4d(pa22, 0, &p);
309  p.x = 0.5;
310  ptarray_set_point4d(pa22, 1, &p);
311 
312  CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS );
313 
314  /* Vertical, no crossing */
315  p.x = -0.5;
316  p.y = 0.0;
317  ptarray_set_point4d(pa22, 0, &p);
318  p.y = 1.0;
319  ptarray_set_point4d(pa22, 1, &p);
320 
321  CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS );
322 
323 }
324 
326 {
327  LWLINE *l51;
328  LWLINE *l52;
329  /*
330  ** More complex test, longer lines and multiple crossings
331  */
332  /* Vertical line with vertices at y integers */
333  l51 = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", LW_PARSER_CHECK_NONE);
334 
335  /* Two crossings at segment midpoints */
336  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, -1 1.5, 1 3, 1 4, 1 5)", LW_PARSER_CHECK_NONE);
338  lwline_free(l52);
339 
340  /* One crossing at interior vertex */
341  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1, -1 1, -1 2, -1 3)", LW_PARSER_CHECK_NONE);
342  CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT );
343  lwline_free(l52);
344 
345  /* Two crossings at interior vertices */
346  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1, -1 1, 0 3, 1 3)", LW_PARSER_CHECK_NONE);
348  lwline_free(l52);
349 
350  /* Two crossings, one at the first vertex on at interior vertex */
351  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 0, 0 0, -1 1, 0 3, 1 3)", LW_PARSER_CHECK_NONE);
353  lwline_free(l52);
354 
355  /* Two crossings, one at the first vertex on the next interior vertex */
356  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 0, 0 0, -1 1, 0 1, 1 2)", LW_PARSER_CHECK_NONE);
358  lwline_free(l52);
359 
360  /* Three crossings, two at midpoints, one at vertex */
361  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(0.5 1, -1 0.5, 1 2, -1 2, -1 3)", LW_PARSER_CHECK_NONE);
362  CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_LEFT );
363  lwline_free(l52);
364 
365  /* One mid-point co-linear crossing */
366  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1.5, 0 2.5, -1 3, -1 4)", LW_PARSER_CHECK_NONE);
367  CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT );
368  lwline_free(l52);
369 
370  /* One on-vertices co-linear crossing */
371  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1, 0 2, -1 4, -1 4)", LW_PARSER_CHECK_NONE);
372  CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT );
373  lwline_free(l52);
374 
375  /* No crossing, but end on a co-linearity. */
376  l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 1 2, 1 3, 0 3, 0 4)", LW_PARSER_CHECK_NONE);
377  CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_NO_CROSS );
378  lwline_free(l52);
379 
380  lwline_free(l51);
381 
382 }
383 
384 
385 static void test_lwline_crossing_bugs(void)
386 {
387  LWLINE *l1;
388  LWLINE *l2;
389 
390  l1 = (LWLINE*)lwgeom_from_wkt("LINESTRING(2.99 90.16,71 74,20 140,171 154)", LW_PARSER_CHECK_NONE);
391  l2 = (LWLINE*)lwgeom_from_wkt("LINESTRING(25 169,89 114,40 70,86 43)", LW_PARSER_CHECK_NONE);
392 
394  lwline_free(l1);
395  lwline_free(l2);
396 
397 }
398 
399 static void test_lwpoint_set_ordinate(void)
400 {
401  POINT4D p;
402 
403  p.x = 0.0;
404  p.y = 0.0;
405  p.z = 0.0;
406  p.m = 0.0;
407 
408  lwpoint_set_ordinate(&p, 'X', 1.5);
409  CU_ASSERT_EQUAL( p.x, 1.5 );
410 
411  lwpoint_set_ordinate(&p, 'M', 2.5);
412  CU_ASSERT_EQUAL( p.m, 2.5 );
413 
414  lwpoint_set_ordinate(&p, 'Z', 3.5);
415  CU_ASSERT_EQUAL( p.z, 3.5 );
416 
417 }
418 
419 static void test_lwpoint_get_ordinate(void)
420 {
421  POINT4D p;
422 
423  p.x = 10.0;
424  p.y = 20.0;
425  p.z = 30.0;
426  p.m = 40.0;
427 
428  CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'X'), 10.0 );
429  CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'Y'), 20.0 );
430  CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'Z'), 30.0 );
431  CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'M'), 40.0 );
432 
433 }
434 
435 static void test_point_interpolate(void)
436 {
437  POINT4D p, q, r;
438  int rv = 0;
439 
440  p.x = 10.0;
441  p.y = 20.0;
442  p.z = 30.0;
443  p.m = 40.0;
444 
445  q.x = 20.0;
446  q.y = 30.0;
447  q.z = 40.0;
448  q.m = 50.0;
449 
450  rv = point_interpolate(&p, &q, &r, 1, 1, 'Z', 35.0);
451  CU_ASSERT_EQUAL( r.x, 15.0);
452 
453  rv = point_interpolate(&p, &q, &r, 1, 1, 'M', 41.0);
454  CU_ASSERT_EQUAL( r.y, 21.0);
455 
456  rv = point_interpolate(&p, &q, &r, 1, 1, 'M', 50.0);
457  CU_ASSERT_EQUAL( r.y, 30.0);
458 
459  rv = point_interpolate(&p, &q, &r, 1, 1, 'M', 40.0);
460  CU_ASSERT_EQUAL( r.y, 20.0);
461 
462 }
463 
464 static void test_lwline_clip(void)
465 {
466  LWCOLLECTION *c;
467  LWLINE *line = NULL;
468  LWLINE *l51 = NULL;
469  char *ewkt;
470 
471  /* Vertical line with vertices at y integers */
472  l51 = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", LW_PARSER_CHECK_NONE);
473 
474  /* Clip in the middle, mid-range. */
475  c = lwline_clip_to_ordinate_range(l51, 'Y', 1.5, 2.5);
476  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
477  //printf("c = %s\n", ewkt);
478  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
479  lwfree(ewkt);
481 
482  /* Clip off the top. */
483  c = lwline_clip_to_ordinate_range(l51, 'Y', 3.5, 5.5);
484  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
485  //printf("c = %s\n", ewkt);
486  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 3.5,0 4))");
487  lwfree(ewkt);
489 
490  /* Clip off the bottom. */
491  c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 2.5);
492  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
493  //printf("c = %s\n", ewkt);
494  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 2.5))" );
495  lwfree(ewkt);
497 
498  /* Range holds entire object. */
499  c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 5.5);
500  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
501  //printf("c = %s\n", ewkt);
502  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))" );
503  lwfree(ewkt);
505 
506  /* Clip on vertices. */
507  c = lwline_clip_to_ordinate_range(l51, 'Y', 1.0, 2.0);
508  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
509  //printf("c = %s\n", ewkt);
510  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1,0 2))" );
511  lwfree(ewkt);
513 
514  /* Clip on vertices off the bottom. */
515  c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 2.0);
516  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
517  //printf("c = %s\n", ewkt);
518  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2))" );
519  lwfree(ewkt);
521 
522  /* Clip on top. */
523  c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 0.0);
524  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
525  //printf("c = %s\n", ewkt);
526  CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0))" );
527  lwfree(ewkt);
529 
530  /* ST_LocateBetweenElevations(ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)'), 1, 2)) */
531  line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
532  c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0);
533  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
534  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
535  lwfree(ewkt);
537  lwline_free(line);
538 
539  /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 2)) */
540  line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
541  c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0);
542  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
543  //printf("a = %s\n", ewkt);
544  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
545  lwfree(ewkt);
547  lwline_free(line);
548 
549  /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 1)) */
550  line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
551  c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0);
552  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
553  //printf("b = %s\n", ewkt);
554  CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
555  lwfree(ewkt);
557  lwline_free(line);
558 
559  /* ST_LocateBetweenElevations('LINESTRING(1 1 1, 1 2 2)', 1,1) */
560  line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1 1, 1 2 2)", LW_PARSER_CHECK_NONE);
561  c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0);
562  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
563  //printf("c = %s\n", ewkt);
564  CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
565  lwfree(ewkt);
567  lwline_free(line);
568 
569  lwline_free(l51);
570 
571 }
572 
573 static void test_lwmline_clip(void)
574 {
575  LWCOLLECTION *c;
576  char *ewkt;
577  LWMLINE *mline = NULL;
578  LWLINE *line = NULL;
579 
580  /*
581  ** Set up the input line. Trivial one-member case.
582  */
583  mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
584 
585  /* Clip in the middle, mid-range. */
586  c = lwmline_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5);
587  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
588  //printf("c = %s\n", ewkt);
589  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
590  lwfree(ewkt);
592 
593  lwmline_free(mline);
594 
595  /*
596  ** Set up the input line. Two-member case.
597  */
598  mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 1,1 2,1 3,1 4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
599 
600  /* Clip off the top. */
601  c = lwmline_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5);
602  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
603  //printf("c = %s\n", ewkt);
604  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
605  lwfree(ewkt);
607 
608  lwmline_free(mline);
609 
610  /*
611  ** Set up staggered input line to create multi-type output.
612  */
613  mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 -1,1 -2,1 -3,1 -4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
614 
615  /* Clip from 0 upwards.. */
616  c = lwmline_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5);
617  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
618  //printf("c = %s\n", ewkt);
619  CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
620  lwfree(ewkt);
622 
623  lwmline_free(mline);
624 
625  /*
626  ** Set up input line from MAC
627  */
628  line = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0 0 0,1 1 1 1,2 2 2 2,3 3 3 3,4 4 4 4,3 3 3 5,2 2 2 6,1 1 1 7,0 0 0 8)", LW_PARSER_CHECK_NONE);
629 
630  /* Clip from 3 to 3.5 */
631  c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 3.5);
632  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
633  //printf("c = %s\n", ewkt);
634  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5))");
635  lwfree(ewkt);
637 
638  /* Clip from 2 to 3.5 */
639  c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.5);
640  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
641  //printf("c = %s\n", ewkt);
642  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5,2 2 2 6))");
643  lwfree(ewkt);
645 
646  /* Clip from 3 to 4 */
647  c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 4.0);
648  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
649  //printf("c = %s\n", ewkt);
650  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
651  lwfree(ewkt);
653 
654  /* Clip from 2 to 3 */
655  c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.0);
656  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
657  //printf("c = %s\n", ewkt);
658  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))");
659  lwfree(ewkt);
661 
662 
663  lwline_free(line);
664 
665 }
666 
667 
668 
669 static void test_lwline_clip_big(void)
670 {
671  POINTARRAY *pa = ptarray_construct(1, 0, 3);
672  LWLINE *line = lwline_construct(SRID_UNKNOWN, NULL, pa);
673  LWCOLLECTION *c;
674  char *ewkt;
675  POINT4D p;
676 
677  p.x = 0.0;
678  p.y = 0.0;
679  p.z = 0.0;
680  ptarray_set_point4d(pa, 0, &p);
681 
682  p.x = 1.0;
683  p.y = 1.0;
684  p.z = 1.0;
685  ptarray_set_point4d(pa, 1, &p);
686 
687  p.x = 2.0;
688  p.y = 2.0;
689  p.z = 2.0;
690  ptarray_set_point4d(pa, 2, &p);
691 
692  c = lwline_clip_to_ordinate_range(line, 'Z', 0.5, 1.5);
693  ewkt = lwgeom_to_ewkt((LWGEOM*)c);
694  //printf("c = %s\n", ewkt);
695  CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0.5 0.5 0.5,1 1 1,1.5 1.5 1.5))" );
696 
697  lwfree(ewkt);
699  lwline_free(line);
700 }
701 
702 static void test_geohash_precision(void)
703 {
704  GBOX bbox;
705  GBOX bounds;
706  int precision = 0;
707  gbox_init(&bbox);
708  gbox_init(&bounds);
709 
710  bbox.xmin = 23.0;
711  bbox.xmax = 23.0;
712  bbox.ymin = 25.2;
713  bbox.ymax = 25.2;
714  precision = lwgeom_geohash_precision(bbox, &bounds);
715  //printf("\nprecision %d\n",precision);
716  CU_ASSERT_EQUAL(precision, 20);
717 
718  bbox.xmin = 23.0;
719  bbox.ymin = 23.0;
720  bbox.xmax = 23.1;
721  bbox.ymax = 23.1;
722  precision = lwgeom_geohash_precision(bbox, &bounds);
723  //printf("precision %d\n",precision);
724  CU_ASSERT_EQUAL(precision, 3);
725 
726  bbox.xmin = 23.0;
727  bbox.ymin = 23.0;
728  bbox.xmax = 23.0001;
729  bbox.ymax = 23.0001;
730  precision = lwgeom_geohash_precision(bbox, &bounds);
731  //printf("precision %d\n",precision);
732  CU_ASSERT_EQUAL(precision, 7);
733 
734 }
735 
736 static void test_geohash_point(void)
737 {
738  char *geohash;
739 
740  geohash = geohash_point(0, 0, 16);
741  //printf("\ngeohash %s\n",geohash);
742  CU_ASSERT_STRING_EQUAL(geohash, "s000000000000000");
743  lwfree(geohash);
744 
745  geohash = geohash_point(90, 0, 16);
746  //printf("\ngeohash %s\n",geohash);
747  CU_ASSERT_STRING_EQUAL(geohash, "w000000000000000");
748  lwfree(geohash);
749 
750  geohash = geohash_point(20.012345, -20.012345, 15);
751  //printf("\ngeohash %s\n",geohash);
752  CU_ASSERT_STRING_EQUAL(geohash, "kkqnpkue9ktbpe5");
753  lwfree(geohash);
754 
755 }
756 
757 static void test_geohash(void)
758 {
759  LWPOINT *lwpoint = NULL;
760  LWLINE *lwline = NULL;
761  LWMLINE *lwmline = NULL;
762  char *geohash = NULL;
763 
764  lwpoint = (LWPOINT*)lwgeom_from_wkt("POINT(23.0 25.2)", LW_PARSER_CHECK_NONE);
765  geohash = lwgeom_geohash((LWGEOM*)lwpoint,0);
766  //printf("\ngeohash %s\n",geohash);
767  CU_ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
768  lwpoint_free(lwpoint);
769  lwfree(geohash);
770 
771  lwpoint = (LWPOINT*)lwgeom_from_wkt("POINT(23.0 25.2 2.0)", LW_PARSER_CHECK_NONE);
772  geohash = lwgeom_geohash((LWGEOM*)lwpoint,0);
773  //printf("geohash %s\n",geohash);
774  CU_ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
775  lwpoint_free(lwpoint);
776  lwfree(geohash);
777 
778  lwline = (LWLINE*)lwgeom_from_wkt("LINESTRING(23.0 23.0,23.1 23.1)", LW_PARSER_CHECK_NONE);
779  geohash = lwgeom_geohash((LWGEOM*)lwline,0);
780  //printf("geohash %s\n",geohash);
781  CU_ASSERT_STRING_EQUAL(geohash, "ss0");
782  lwline_free(lwline);
783  lwfree(geohash);
784 
785  lwline = (LWLINE*)lwgeom_from_wkt("LINESTRING(23.0 23.0,23.001 23.001)", LW_PARSER_CHECK_NONE);
786  geohash = lwgeom_geohash((LWGEOM*)lwline,0);
787  //printf("geohash %s\n",geohash);
788  CU_ASSERT_STRING_EQUAL(geohash, "ss06g7");
789  lwline_free(lwline);
790  lwfree(geohash);
791 
792  lwmline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((23.0 23.0,23.1 23.1),(23.0 23.0,23.1 23.1))", LW_PARSER_CHECK_NONE);
793  geohash = lwgeom_geohash((LWGEOM*)lwmline,0);
794  //printf("geohash %s\n",geohash);
795  CU_ASSERT_STRING_EQUAL(geohash, "ss0");
796  lwmline_free(lwmline);
797  lwfree(geohash);
798 }
799 
800 static void test_isclosed(void)
801 {
802  LWGEOM *geom;
803 
804  /* LINESTRING */
805 
806  /* Not Closed on 2D */
807  geom = lwgeom_from_wkt("LINESTRING(1 2,3 4)", LW_PARSER_CHECK_NONE);
808  CU_ASSERT(!lwline_is_closed((LWLINE *) geom));
809  lwgeom_free(geom);
810 
811  /* Closed on 2D */
812  geom = lwgeom_from_wkt("LINESTRING(1 2,3 4,1 2)", LW_PARSER_CHECK_NONE);
813  CU_ASSERT(lwline_is_closed((LWLINE *) geom));
814  lwgeom_free(geom);
815 
816  /* Not closed on 3D */
817  geom = lwgeom_from_wkt("LINESTRING(1 2 3,4 5 6)", LW_PARSER_CHECK_NONE);
818  CU_ASSERT(!lwline_is_closed((LWLINE *) geom));
819  lwgeom_free(geom);
820 
821  /* Closed on 3D */
822  geom = lwgeom_from_wkt("LINESTRING(1 2 3,4 5 6,1 2 3)", LW_PARSER_CHECK_NONE);
823  CU_ASSERT(lwline_is_closed((LWLINE *) geom));
824  lwgeom_free(geom);
825 
826  /* Closed on 4D, even if M is not the same */
827  geom = lwgeom_from_wkt("LINESTRING(1 2 3 4,5 6 7 8,1 2 3 0)", LW_PARSER_CHECK_NONE);
828  CU_ASSERT(lwline_is_closed((LWLINE *) geom));
829  lwgeom_free(geom);
830 
831 
832  /* CIRCULARSTRING */
833 
834  /* Not Closed on 2D */
835  geom = lwgeom_from_wkt("CIRCULARSTRING(1 2,3 4,5 6)", LW_PARSER_CHECK_NONE);
836  CU_ASSERT(!lwcircstring_is_closed((LWCIRCSTRING *) geom));
837  lwgeom_free(geom);
838 
839  /* Closed on 2D */
840  geom = lwgeom_from_wkt("CIRCULARSTRING(1 2,3 4,1 2)", LW_PARSER_CHECK_NONE);
841  CU_ASSERT(lwcircstring_is_closed((LWCIRCSTRING *) geom));
842  lwgeom_free(geom);
843 
844  /* Not closed on 3D */
845  geom = lwgeom_from_wkt("CIRCULARSTRING(1 2 3,4 5 6,7 8 9)", LW_PARSER_CHECK_NONE);
846  CU_ASSERT(!lwcircstring_is_closed((LWCIRCSTRING *) geom));
847  lwgeom_free(geom);
848 
849  /* Closed on 3D */
850  geom = lwgeom_from_wkt("CIRCULARSTRING(1 2 3,4 5 6,1 2 3)", LW_PARSER_CHECK_NONE);
851  CU_ASSERT(lwcircstring_is_closed((LWCIRCSTRING *) geom));
852  lwgeom_free(geom);
853 
854  /* Closed on 4D, even if M is not the same */
855  geom = lwgeom_from_wkt("CIRCULARSTRING(1 2 3 4,5 6 7 8,1 2 3 0)", LW_PARSER_CHECK_NONE);
856  CU_ASSERT(lwcircstring_is_closed((LWCIRCSTRING *) geom));
857  lwgeom_free(geom);
858 
859 
860  /* COMPOUNDCURVE */
861 
862  /* Not Closed on 2D */
863  geom = lwgeom_from_wkt("COMPOUNDCURVE(CIRCULARSTRING(1 2,3 4,1 2),(1 2,7 8,5 6))", LW_PARSER_CHECK_NONE);
864  CU_ASSERT(!lwcompound_is_closed((LWCOMPOUND *) geom));
865  lwgeom_free(geom);
866 
867  geom = lwgeom_from_wkt("COMPOUNDCURVE((1 2,3 4,1 2),CIRCULARSTRING(1 2,7 8,5 6))", LW_PARSER_CHECK_NONE);
868  CU_ASSERT(!lwcompound_is_closed((LWCOMPOUND *) geom));
869  lwgeom_free(geom);
870 
871  /* Closed on 2D */
872  geom = lwgeom_from_wkt("COMPOUNDCURVE(CIRCULARSTRING(1 2,3 4,5 6), (5 6,7 8,1 2))", LW_PARSER_CHECK_NONE);
873  CU_ASSERT(lwcompound_is_closed((LWCOMPOUND *) geom));
874  lwgeom_free(geom);
875 
876  geom = lwgeom_from_wkt("COMPOUNDCURVE((1 2,3 4,5 6),CIRCULARSTRING(5 6,7 8,1 2))", LW_PARSER_CHECK_NONE);
877  CU_ASSERT(lwcompound_is_closed((LWCOMPOUND *) geom));
878  lwgeom_free(geom);
879 
880  /* Not Closed on 3D */
881  geom = lwgeom_from_wkt("COMPOUNDCURVE(CIRCULARSTRING(1 2 3,4 5 6,1 2 3),(1 2 3,7 8 9,10 11 12))", LW_PARSER_CHECK_NONE);
882  CU_ASSERT(!lwcompound_is_closed((LWCOMPOUND *) geom));
883  lwgeom_free(geom);
884 
885  geom = lwgeom_from_wkt("COMPOUNDCURVE((1 2 3,4 5 6,1 2 3),CIRCULARSTRING(1 2 3,7 8 9,10 11 12))", LW_PARSER_CHECK_NONE);
886  CU_ASSERT(!lwcompound_is_closed((LWCOMPOUND *) geom));
887  lwgeom_free(geom);
888 
889  /* Closed on 3D */
890  geom = lwgeom_from_wkt("COMPOUNDCURVE(CIRCULARSTRING(1 2 3,4 5 6,7 8 9),(7 8 9,10 11 12,1 2 3))", LW_PARSER_CHECK_NONE);
891  CU_ASSERT(lwcompound_is_closed((LWCOMPOUND *) geom));
892  lwgeom_free(geom);
893 
894  geom = lwgeom_from_wkt("COMPOUNDCURVE((1 2 3,4 5 6,7 8 9),CIRCULARSTRING(7 8 9,10 11 12,1 2 3))", LW_PARSER_CHECK_NONE);
895  CU_ASSERT(lwcompound_is_closed((LWCOMPOUND *) geom));
896  lwgeom_free(geom);
897 
898  /* Closed on 4D, even if M is not the same */
899  geom = lwgeom_from_wkt("COMPOUNDCURVE((1 2 3 4,5 6 7 8,9 10 11 12),CIRCULARSTRING(9 10 11 12,13 14 15 16,1 2 3 0))", LW_PARSER_CHECK_NONE);
900  CU_ASSERT(lwcompound_is_closed((LWCOMPOUND *) geom));
901  lwgeom_free(geom);
902 }
903 
904 
905 static void test_geohash_point_as_int(void)
906 {
907  unsigned int gh;
908  POINT2D p;
909 
910  p.x = 50; p.y = 35;
911  gh = geohash_point_as_int(&p);
912  CU_ASSERT_EQUAL(gh, (unsigned int)3440103613);
913  p.x = 140; p.y = 45;
914  gh = geohash_point_as_int(&p);
915  CU_ASSERT_EQUAL(gh, (unsigned int)3982480893);
916  p.x = 140; p.y = 55;
917  gh = geohash_point_as_int(&p);
918  CU_ASSERT_EQUAL(gh, (unsigned int)4166944232);
919 }
920 
921 static void test_lwgeom_simplify(void)
922 {
923  LWGEOM *l;
924  LWGEOM *i;
925  char *ewkt;
926 
927  /* Not simplifiable */
928  i = lwgeom_from_wkt("LINESTRING(0 0, 50 1.00001, 100 0)", LW_PARSER_CHECK_NONE);
929  l = lwgeom_simplify(i, 1.0);
930  ewkt = lwgeom_to_ewkt(l);
931  CU_ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,50 1.00001,100 0)");
932  lwgeom_free(l);
933  lwgeom_free(i);
934  lwfree(ewkt);
935 
936  /* Simplifiable */
937  i = lwgeom_from_wkt("LINESTRING(0 0,50 0.99999,100 0)", LW_PARSER_CHECK_NONE);
938  l = lwgeom_simplify(i, 1.0);
939  ewkt = lwgeom_to_ewkt(l);
940  CU_ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,100 0)");
941  lwgeom_free(l);
942  lwgeom_free(i);
943  lwfree(ewkt);
944 }
945 
946 /*
947 ** Used by test harness to register the tests in this file.
948 */
949 void algorithms_suite_setup(void);
951 {
952  CU_pSuite suite = CU_add_suite("Computational Geometry", init_cg_suite, clean_cg_suite);
966  PG_ADD_TEST(suite,test_geohash);
968  PG_ADD_TEST(suite,test_isclosed);
971 }
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
Definition: lwgeom_api.c:501
double x
Definition: liblwgeom.h:308
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
Definition: lwalgorithm.c:228
static void test_lwline_crossing_short_lines(void)
Definition: cu_algorithm.c:262
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition: ptarray.c:49
static void test_lwline_clip_big(void)
Definition: cu_algorithm.c:669
static void test_lw_segment_side(void)
Definition: cu_algorithm.c:62
double m
Definition: liblwgeom.h:308
static void test_isclosed(void)
Definition: cu_algorithm.c:800
static void test_geohash_point_as_int(void)
Definition: cu_algorithm.c:905
char * r
Definition: cu_in_wkt.c:25
void lwmline_free(LWMLINE *mline)
Definition: lwmline.c:99
void lwfree(void *mem)
Definition: lwutil.c:190
int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2)
Given two lines, characterize how (and if) they cross each other.
Definition: lwalgorithm.c:461
POINTARRAY * pa21
Definition: cu_algorithm.c:26
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
Definition: lwgeom.c:425
double xmax
Definition: liblwgeom.h:249
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:180
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
static void test_lwmline_clip(void)
Definition: cu_algorithm.c:573
void lwline_free(LWLINE *line)
Definition: lwline.c:63
static void test_lw_segment_intersects(void)
Definition: cu_algorithm.c:120
static void test_lwpoint_get_ordinate(void)
Definition: cu_algorithm.c:419
double lwpoint_get_ordinate(const POINT4D *p, char ordinate)
Given a POINT4D and an ordinate number, return the value of the ordinate.
static void test_geohash(void)
Definition: cu_algorithm.c:757
LWLINE * l22
Definition: cu_algorithm.c:29
static void test_lwline_clip(void)
Definition: cu_algorithm.c:464
LWLINE * l21
Definition: cu_algorithm.c:28
int lwcompound_is_closed(const LWCOMPOUND *curve)
Definition: lwcompound.c:22
static int clean_cg_suite(void)
Definition: cu_algorithm.c:52
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:844
LWCOLLECTION * lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to)
Clip a line based on the from/to range of one of its ordinates.
static void test_geohash_point(void)
Definition: cu_algorithm.c:736
void algorithms_suite_setup(void)
Definition: cu_algorithm.c:950
static void test_lw_arc_center(void)
Definition: cu_algorithm.c:94
static void test_lwline_crossing_bugs(void)
Definition: cu_algorithm.c:385
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1706
double x
Definition: liblwgeom.h:284
static void test_lwline_crossing_long_lines(void)
Definition: cu_algorithm.c:325
double ymin
Definition: liblwgeom.h:250
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: g_box.c:34
double xmin
Definition: liblwgeom.h:248
static int init_cg_suite(void)
Definition: cu_algorithm.c:38
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM...
Definition: liblwgeom.h:1713
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
int point_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz, int hasm, char ordinate, double interpolation_value)
Given two points, a dimensionality, an ordinate, and an interpolation value generate a new point that...
int lwcircstring_is_closed(const LWCIRCSTRING *curve)
Definition: lwcircstring.c:255
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:154
#define PG_ADD_TEST(suite, testfunc)
LWCOLLECTION * lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
Clip a multi-line based on the from/to range of one of its ordinates.
LWGEOM_PARSER_RESULT parse_result
Definition: cu_algorithm.c:31
int lwgeom_geohash_precision(GBOX bbox, GBOX *bounds)
Definition: lwalgorithm.c:743
void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value)
Given a point, ordinate number and value, set that ordinate on the point.
double ymax
Definition: liblwgeom.h:251
double y
Definition: liblwgeom.h:284
char * geohash_point(double longitude, double latitude, int precision)
Definition: lwalgorithm.c:582
double z
Definition: liblwgeom.h:308
static void test_geohash_precision(void)
Definition: cu_algorithm.c:702
unsigned int geohash_point_as_int(POINT2D *pt)
Definition: lwalgorithm.c:648
#define setpoint(p, x1, y1)
static void test_lwpoint_set_ordinate(void)
Definition: cu_algorithm.c:399
char * lwgeom_geohash(const LWGEOM *lwgeom, int precision)
Calculate the GeoHash (http://geohash.org) string for a geometry.
Definition: lwalgorithm.c:828
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:435
static void test_point_interpolate(void)
Definition: cu_algorithm.c:435
LWGEOM * lwgeom_simplify(const LWGEOM *igeom, double dist)
Definition: lwgeom.c:1478
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:316
static void test_lwgeom_simplify(void)
Definition: cu_algorithm.c:921
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
Definition: lwalgorithm.c:62
double y
Definition: liblwgeom.h:308
POINTARRAY * pa22
Definition: cu_algorithm.c:27
int lw_segment_intersects(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
returns the kind of CG_SEGMENT_INTERSECTION_TYPE behavior of lineseg 1 (constructed from p1 and p2) a...
Definition: lwalgorithm.c:372