source: branches/1.4/liblwgeom/cunit/cu_algorithm.c @ 4787

Last change on this file since 4787 was 4787, checked in by pramsey, 7 years ago

Simplify code and improve consistency of linecrossing results (#272)

  • Property svn:keywords set to Author Date Id Revision
File size: 21.8 KB
Line 
1/**********************************************************************
2 * $Id: cu_algorithm.c 4787 2009-11-11 19:02:49Z pramsey $
3 *
4 * PostGIS - Spatial Types for PostgreSQL
5 * http://postgis.refractions.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 "cu_algorithm.h"
14
15/*
16** Called from test harness to register the tests in this file.
17*/
18CU_pSuite register_cg_suite(void)
19{
20        CU_pSuite pSuite;
21        pSuite = CU_add_suite("PostGIS Computational Geometry Suite", init_cg_suite, clean_cg_suite);
22        if (NULL == pSuite)
23        {
24                CU_cleanup_registry();
25                return NULL;
26        }
27
28        if (
29            (NULL == CU_add_test(pSuite, "test_lw_segment_side()", test_lw_segment_side)) ||
30            (NULL == CU_add_test(pSuite, "test_lw_segment_intersects()", test_lw_segment_intersects)) ||
31            (NULL == CU_add_test(pSuite, "test_lwline_crossing_short_lines()", test_lwline_crossing_short_lines)) ||
32            (NULL == CU_add_test(pSuite, "test_lwline_crossing_long_lines()", test_lwline_crossing_long_lines)) || 
33            (NULL == CU_add_test(pSuite, "test_lwline_crossing_bugs()", test_lwline_crossing_bugs)) ||
34            (NULL == CU_add_test(pSuite, "test_lwpoint_set_ordinate()", test_lwpoint_set_ordinate)) ||
35            (NULL == CU_add_test(pSuite, "test_lwpoint_get_ordinate()", test_lwpoint_get_ordinate)) ||
36            (NULL == CU_add_test(pSuite, "test_lwpoint_interpolate()", test_lwpoint_interpolate)) ||
37            (NULL == CU_add_test(pSuite, "test_lwline_clip()", test_lwline_clip)) ||
38            (NULL == CU_add_test(pSuite, "test_lwline_clip_big()", test_lwline_clip_big)) ||
39            (NULL == CU_add_test(pSuite, "test_lwmline_clip()", test_lwmline_clip)) ||
40            (NULL == CU_add_test(pSuite, "test_geohash_point()", test_geohash_point)) ||
41            (NULL == CU_add_test(pSuite, "test_geohash_precision()", test_geohash_precision)) ||
42            (NULL == CU_add_test(pSuite, "test_geohash()", test_geohash)) 
43        )
44        {
45                CU_cleanup_registry();
46                return NULL;
47        }
48        return pSuite;
49}
50
51
52/*
53** Global variables used by tests below
54*/
55
56/* Two-point objects */
57POINTARRAY *pa21 = NULL;
58POINTARRAY *pa22 = NULL;
59LWLINE *l21 = NULL;
60LWLINE *l22 = NULL;
61/* Parsing support */
62LWGEOM_PARSER_RESULT parse_result;
63
64
65/*
66** The suite initialization function.
67** Create any re-used objects.
68*/
69int init_cg_suite(void)
70{
71        pa21 = ptarray_construct(0, 0, 2);
72        pa22 = ptarray_construct(0, 0, 2);
73        l21 = lwline_construct(-1, NULL, pa21);
74        l22 = lwline_construct(-1, NULL, pa22);
75        return 0;
76
77}
78
79/*
80** The suite cleanup function.
81** Frees any global objects.
82*/
83int clean_cg_suite(void)
84{
85        if ( l21 ) lwline_free(l21);
86        if ( l22 ) lwline_free(l22);
87        return 0;
88}
89
90/*
91** Test left/right side.
92*/
93void test_lw_segment_side(void)
94{
95        double rv = 0.0;
96        POINT2D p1, p2, q;
97
98        /* Vertical line at x=0 */
99        p1.x = 0.0;
100        p1.y = 0.0;
101        p2.x = 0.0;
102        p2.y = 1.0;
103
104        /* On the left */
105        q.x = -2.0;
106        q.y = 1.5;
107        rv = lw_segment_side(p1, p2, q);
108        //printf("left %g\n",rv);
109        CU_ASSERT(rv < 0.0);
110
111        /* On the right */
112        q.x = 2.0;
113        rv = lw_segment_side(p1, p2, q);
114        //printf("right %g\n",rv);
115        CU_ASSERT(rv > 0.0);
116
117        /* On the line */
118        q.x = 0.0;
119        rv = lw_segment_side(p1, p2, q);
120        //printf("on line %g\n",rv);
121        CU_ASSERT_EQUAL(rv, 0.0);
122
123}
124
125/*
126** Test crossings side.
127*/
128void test_lw_segment_intersects(void)
129{
130
131#define setpoint(p, x1, y1) {(p).x = (x1); (p).y = (y1);}
132
133        POINT2D p1, p2, q1, q2;
134       
135        /* P: Vertical line at x=0 */
136        setpoint(p1, 0.0, 0.0);
137        p1.x = 0.0;
138        p1.y = 0.0;
139        p2.x = 0.0;
140        p2.y = 1.0;
141
142        /* Q: Horizontal line crossing left to right */
143        q1.x = -0.5;
144        q1.y = 0.5;
145        q2.x = 0.5;
146        q2.y = 0.5;
147        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_RIGHT );
148
149        /* Q: Horizontal line crossing right to left */
150        q1.x = 0.5;
151        q1.y = 0.5;
152        q2.x = -0.5;
153        q2.y = 0.5;
154        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT );
155
156        /* Q: Horizontal line not crossing right to left */
157        q1.x = 0.5;
158        q1.y = 1.5;
159        q2.x = -0.5;
160        q2.y = 1.5;
161        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION );
162
163        /* Q: Horizontal line crossing at second vertex right to left */
164        q1.x = 0.5;
165        q1.y = 1.0;
166        q2.x = -0.5;
167        q2.y = 1.0;
168        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION );
169
170        /* Q: Horizontal line crossing at first vertex right to left */
171        q1.x = 0.5;
172        q1.y = 0.0;
173        q2.x = -0.5;
174        q2.y = 0.0;
175        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT );
176
177        /* Q: Diagonal line with large range crossing at first vertex right to left */
178        q1.x = 0.5;
179        q1.y = 10.0;
180        q2.x = -0.5;
181        q2.y = -10.0;
182        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT );
183
184        /* Q: Diagonal line with large range crossing at second vertex right to left */
185        q1.x = 0.5;
186        q1.y = 11.0;
187        q2.x = -0.5;
188        q2.y = -9.0;
189        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION );
190
191        /* Q: Horizontal touching from left at second vertex*/
192        q1.x = -0.5;
193        q1.y = 0.5;
194        q2.x = 0.0;
195        q2.y = 0.5;
196        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION );
197
198        /* Q: Horizontal touching from right at first vertex */
199        q1.x = 0.0;
200        q1.y = 0.5;
201        q2.x = 0.5;
202        q2.y = 0.5;
203        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_RIGHT );
204
205        /* Q: Horizontal touching from left and far below on second vertex */
206        q1.x = -0.5;
207        q1.y = -10.5;
208        q2.x = 0.0;
209        q2.y = 0.5;
210        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION );
211
212        /* Q: Horizontal touching from right and far above on second vertex */
213        q1.x = 0.5;
214        q1.y = 10.5;
215        q2.x = 0.0;
216        q2.y = 0.5;
217        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION );
218
219        /* Q: Co-linear from top */
220        q1.x = 0.0;
221        q1.y = 10.0;
222        q2.x = 0.0;
223        q2.y = 0.5;
224        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR );
225
226        /* Q: Co-linear from bottom */
227        q1.x = 0.0;
228        q1.y = -10.0;
229        q2.x = 0.0;
230        q2.y = 0.5;
231        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR );
232
233        /* Q: Co-linear contained */
234        q1.x = 0.0;
235        q1.y = 0.4;
236        q2.x = 0.0;
237        q2.y = 0.5;
238        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR );
239
240        /* Q: Horizontal touching at end point from left */
241        q1.x = -0.5;
242        q1.y = 1.0;
243        q2.x = 0.0;
244        q2.y = 1.0;
245        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION );
246
247        /* Q: Horizontal touching at end point from right */
248        q1.x = 0.0;
249        q1.y = 1.0;
250        q2.x = 0.0;
251        q2.y = 0.5;
252        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR );
253
254        /* Q: Horizontal touching at start point from left */
255        q1.x = 0.0;
256        q1.y = 0.0;
257        q2.x = -0.5;
258        q2.y = 0.0;
259        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT );
260
261        /* Q: Horizontal touching at start point from right */
262        q1.x = 0.0;
263        q1.y = 0.0;
264        q2.x = 0.5;
265        q2.y = 0.0;
266        CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_RIGHT );
267
268}
269
270void test_lwline_crossing_short_lines(void)
271{
272
273        POINT4D p;
274       
275        /*
276        ** Simple test, two two-point lines
277        */
278
279        /* Vertical line from 0,0 to 1,1 */
280        p.x = 0.0;
281        p.y = 0.0;
282        setPoint4d(pa21, 0, &p);
283        p.y = 1.0;
284        setPoint4d(pa21, 1, &p);
285
286        /* Horizontal, crossing mid-segment */
287        p.x = -0.5;
288        p.y = 0.5;
289        setPoint4d(pa22, 0, &p);
290        p.x = 0.5;
291        setPoint4d(pa22, 1, &p);
292
293        CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT );
294
295        /* Horizontal, crossing at top end vertex (end crossings don't count) */
296        p.x = -0.5;
297        p.y = 1.0;
298        setPoint4d(pa22, 0, &p);
299        p.x = 0.5;
300        setPoint4d(pa22, 1, &p);
301
302        CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS );
303
304        /* Horizontal, crossing at bottom end vertex */
305        p.x = -0.5;
306        p.y = 0.0;
307        setPoint4d(pa22, 0, &p);
308        p.x = 0.5;
309        setPoint4d(pa22, 1, &p);
310
311        CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT );
312
313        /* Horizontal, no crossing */
314        p.x = -0.5;
315        p.y = 2.0;
316        setPoint4d(pa22, 0, &p);
317        p.x = 0.5;
318        setPoint4d(pa22, 1, &p);
319
320        CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS );
321
322        /* Vertical, no crossing */
323        p.x = -0.5;
324        p.y = 0.0;
325        setPoint4d(pa22, 0, &p);
326        p.y = 1.0;
327        setPoint4d(pa22, 1, &p);
328
329        CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS );
330
331}
332
333void test_lwline_crossing_long_lines(void)
334{
335        LWLINE *l51;
336        LWLINE *l52;
337        /*
338        ** More complex test, longer lines and multiple crossings
339        */
340        /* Vertical line with vertices at y integers */
341        l51 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", PARSER_CHECK_NONE);
342
343        /* Two crossings at segment midpoints */
344        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 1, -1 1.5, 1 3, 1 4, 1 5)", PARSER_CHECK_NONE);
345        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT );
346        lwline_free(l52);
347
348        /* One crossing at interior vertex */
349        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 1, 0 1, -1 1, -1 2, -1 3)", PARSER_CHECK_NONE);
350        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT );
351        lwline_free(l52);
352
353        /* Two crossings at interior vertices */
354        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 1, 0 1, -1 1, 0 3, 1 3)", PARSER_CHECK_NONE);
355        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT );
356        lwline_free(l52);
357
358        /* Two crossings, one at the first vertex on at interior vertex */
359        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 0, 0 0, -1 1, 0 3, 1 3)", PARSER_CHECK_NONE);
360        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT );
361        lwline_free(l52);
362
363        /* Two crossings, one at the first vertex on the next interior vertex */
364        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 0, 0 0, -1 1, 0 1, 1 2)", PARSER_CHECK_NONE);
365        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT );
366        lwline_free(l52);
367
368        /* Three crossings, two at midpoints, one at vertex */
369        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(0.5 1, -1 0.5, 1 2, -1 2, -1 3)", PARSER_CHECK_NONE);
370        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_LEFT );
371        lwline_free(l52);
372
373        /* One mid-point co-linear crossing */
374        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 1, 0 1.5, 0 2.5, -1 3, -1 4)", PARSER_CHECK_NONE);
375        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT );
376        lwline_free(l52);
377
378        /* One on-vertices co-linear crossing */
379        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 1, 0 1, 0 2, -1 4, -1 4)", PARSER_CHECK_NONE);
380        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT );
381        lwline_free(l52);
382
383        /* No crossing, but end on a co-linearity. */
384        l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 1, 1 2, 1 3, 0 3, 0 4)", PARSER_CHECK_NONE);
385        CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_NO_CROSS );
386        lwline_free(l52);
387
388        lwline_free(l51);
389
390}
391
392
393void test_lwline_crossing_bugs(void)
394{
395        LWLINE *l1;
396        LWLINE *l2;
397       
398        l1 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(2.99 90.16,71 74,20 140,171 154)", PARSER_CHECK_NONE);
399        l2 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(25 169,89 114,40 70,86 43)", PARSER_CHECK_NONE);
400
401        CU_ASSERT( lwline_crossing_direction(l1, l2) == LINE_MULTICROSS_END_RIGHT );
402        lwline_free(l1);
403        lwline_free(l2);
404       
405}
406
407void test_lwpoint_set_ordinate(void)
408{
409        POINT4D p;
410
411        p.x = 0.0;
412        p.y = 0.0;
413        p.z = 0.0;
414        p.m = 0.0;
415
416        lwpoint_set_ordinate(&p, 0, 1.5);
417        CU_ASSERT_EQUAL( p.x, 1.5 );
418
419        lwpoint_set_ordinate(&p, 3, 2.5);
420        CU_ASSERT_EQUAL( p.m, 2.5 );
421
422        lwpoint_set_ordinate(&p, 2, 3.5);
423        CU_ASSERT_EQUAL( p.z, 3.5 );
424
425}
426
427void test_lwpoint_get_ordinate(void)
428{
429        POINT4D p;
430
431        p.x = 10.0;
432        p.y = 20.0;
433        p.z = 30.0;
434        p.m = 40.0;
435
436        CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 0), 10.0 );
437        CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 1), 20.0 );
438        CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 2), 30.0 );
439        CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 3), 40.0 );
440
441}
442
443void test_lwpoint_interpolate(void)
444{
445        POINT4D p, q, r;
446        int rv = 0;
447
448        p.x = 10.0;
449        p.y = 20.0;
450        p.z = 30.0;
451        p.m = 40.0;
452       
453        q.x = 20.0;
454        q.y = 30.0;
455        q.z = 40.0;
456        q.m = 50.0;
457
458        rv = lwpoint_interpolate(&p, &q, &r, 4, 2, 35.0);
459        CU_ASSERT_EQUAL( r.x, 15.0);
460
461        rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 41.0);
462        CU_ASSERT_EQUAL( r.y, 21.0);
463
464        rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 50.0);
465        CU_ASSERT_EQUAL( r.y, 30.0);
466
467        rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 40.0);
468        CU_ASSERT_EQUAL( r.y, 20.0);
469
470}
471
472void test_lwline_clip(void)
473{
474        LWCOLLECTION *c;
475        LWLINE *line = NULL;
476        LWLINE *l51 = NULL;
477        char *ewkt;
478
479        /* Vertical line with vertices at y integers */
480        l51 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", PARSER_CHECK_NONE);
481
482        /* Clip in the middle, mid-range. */
483        c = lwline_clip_to_ordinate_range(l51, 1, 1.5, 2.5);
484        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
485        //printf("c = %s\n", ewkt);
486        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
487        lwfree(ewkt);
488        lwcollection_free(c);
489
490        /* Clip off the top. */
491        c = lwline_clip_to_ordinate_range(l51, 1, 3.5, 5.5);
492        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
493        //printf("c = %s\n", ewkt);
494        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 3.5,0 4))");
495        lwfree(ewkt);
496        lwcollection_free(c);
497
498        /* Clip off the bottom. */
499        c = lwline_clip_to_ordinate_range(l51, 1, -1.5, 2.5);
500        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
501        //printf("c = %s\n", ewkt);
502        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 2.5))" );
503        lwfree(ewkt);
504        lwcollection_free(c);
505
506        /* Range holds entire object. */
507        c = lwline_clip_to_ordinate_range(l51, 1, -1.5, 5.5);
508        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
509        //printf("c = %s\n", ewkt);
510        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))" );
511        lwfree(ewkt);
512        lwcollection_free(c);
513
514        /* Clip on vertices. */
515        c = lwline_clip_to_ordinate_range(l51, 1, 1.0, 2.0);
516        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
517        //printf("c = %s\n", ewkt);
518        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1,0 2))" );
519        lwfree(ewkt);
520        lwcollection_free(c);
521
522        /* Clip on vertices off the bottom. */
523        c = lwline_clip_to_ordinate_range(l51, 1, -1.0, 2.0);
524        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
525        //printf("c = %s\n", ewkt);
526        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2))" );
527        lwfree(ewkt);
528        lwcollection_free(c);
529
530        /* Clip on top. */
531        c = lwline_clip_to_ordinate_range(l51, 1, -1.0, 0.0);
532        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
533        //printf("c = %s\n", ewkt);
534        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0))" );
535        lwfree(ewkt);
536        lwcollection_free(c);
537
538        /* ST_LocateBetweenElevations(ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)'), 1, 2)) */
539        line = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", PARSER_CHECK_NONE);
540        c = lwline_clip_to_ordinate_range(line, 2, 1.0, 2.0);
541        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
542        //printf("a = %s\n", ewkt);
543        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
544        lwfree(ewkt);
545        lwcollection_free(c);
546        lwline_free(line);
547
548        /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 2)) */
549        line = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", PARSER_CHECK_NONE);
550        c = lwline_clip_to_ordinate_range(line, 2, 1.0, 2.0);
551        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
552        //printf("a = %s\n", ewkt);
553        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
554        lwfree(ewkt);
555        lwcollection_free(c);
556        lwline_free(line);
557
558        /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 1)) */
559        line = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", PARSER_CHECK_NONE);
560        c = lwline_clip_to_ordinate_range(line, 2, 1.0, 1.0);
561        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
562        //printf("b = %s\n", ewkt);
563        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
564        lwfree(ewkt);
565        lwcollection_free(c);
566        lwline_free(line);
567
568        /* ST_LocateBetweenElevations('LINESTRING(1 1 1, 1 2 2)', 1,1) */
569        line = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 1 1, 1 2 2)", PARSER_CHECK_NONE);
570        c = lwline_clip_to_ordinate_range(line, 2, 1.0, 1.0);
571        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
572        //printf("c = %s\n", ewkt);
573        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
574        lwfree(ewkt);
575        lwcollection_free(c);
576        lwline_free(line);
577
578        lwline_free(l51);
579
580}
581
582void test_lwmline_clip(void)
583{
584        LWCOLLECTION *c;
585        char *ewkt;
586        LWMLINE *mline = NULL;
587        LWLINE *line = NULL;
588
589        /*
590        ** Set up the input line. Trivial one-member case.
591        */
592        mline = (LWMLINE*)lwgeom_from_ewkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", PARSER_CHECK_NONE);
593
594        /* Clip in the middle, mid-range. */
595        c = lwmline_clip_to_ordinate_range(mline, 1, 1.5, 2.5);
596        ewkt = lwgeom_to_ewkt((LWGEOM*)c,0);
597        //printf("c = %s\n", ewkt);
598        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
599        lwfree(ewkt);
600        lwcollection_free(c);
601
602        lwmline_free(mline);
603
604        /*
605        ** Set up the input line. Two-member case.
606        */
607        mline = (LWMLINE*)lwgeom_from_ewkt("MULTILINESTRING((1 0,1 1,1 2,1 3,1 4), (0 0,0 1,0 2,0 3,0 4))", PARSER_CHECK_NONE);
608
609        /* Clip off the top. */
610        c = lwmline_clip_to_ordinate_range(mline, 1, 3.5, 5.5);
611        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
612        //printf("c = %s\n", ewkt);
613        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
614        lwfree(ewkt);
615        lwcollection_free(c);
616
617        lwmline_free(mline);
618
619        /*
620        ** Set up staggered input line to create multi-type output.
621        */
622        mline = (LWMLINE*)lwgeom_from_ewkt("MULTILINESTRING((1 0,1 -1,1 -2,1 -3,1 -4), (0 0,0 1,0 2,0 3,0 4))", PARSER_CHECK_NONE);
623
624        /* Clip from 0 upwards.. */
625        c = lwmline_clip_to_ordinate_range(mline, 1, 0.0, 2.5);
626        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
627        //printf("c = %s\n", ewkt);
628        CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
629        lwfree(ewkt);
630        lwcollection_free(c);
631
632        lwmline_free(mline);
633
634        /*
635        ** Set up input line from MAC
636        */
637        line = (LWLINE*)lwgeom_from_ewkt("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)", PARSER_CHECK_NONE);
638
639        /* Clip from 3 to 3.5 */
640        c = lwline_clip_to_ordinate_range(line, 2, 3.0, 3.5);
641        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
642        //printf("c = %s\n", ewkt);
643        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))");
644        lwfree(ewkt);
645        lwcollection_free(c);
646
647        /* Clip from 2 to 3.5 */
648        c = lwline_clip_to_ordinate_range(line, 2, 2.0, 3.5);
649        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
650        //printf("c = %s\n", ewkt);
651        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))");
652        lwfree(ewkt);
653        lwcollection_free(c);
654
655        /* Clip from 3 to 4 */
656        c = lwline_clip_to_ordinate_range(line, 2, 3.0, 4.0);
657        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
658        //printf("c = %s\n", ewkt);
659        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
660        lwfree(ewkt);
661        lwcollection_free(c);
662
663        /* Clip from 2 to 3 */
664        c = lwline_clip_to_ordinate_range(line, 2, 2.0, 3.0);
665        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
666        //printf("c = %s\n", ewkt);
667        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))");
668        lwfree(ewkt);
669        lwcollection_free(c);
670
671
672        lwline_free(line);
673
674}
675
676
677
678void test_lwline_clip_big(void)
679{
680        POINTARRAY *pa = ptarray_construct(1, 0, 3);
681        LWLINE *line = lwline_construct(-1, NULL, pa);
682        LWCOLLECTION *c;
683        char *ewkt;
684        POINT4D p;
685
686        p.x = 0.0;
687        p.y = 0.0;
688        p.z = 0.0;
689        setPoint4d(pa, 0, &p);
690
691        p.x = 1.0;
692        p.y = 1.0;
693        p.z = 1.0;
694        setPoint4d(pa, 1, &p);
695
696        p.x = 2.0;
697        p.y = 2.0;
698        p.z = 2.0;
699        setPoint4d(pa, 2, &p);
700
701        c = lwline_clip_to_ordinate_range(line, 2, 0.5, 1.5);
702        ewkt = lwgeom_to_ewkt((LWGEOM*)c, PARSER_CHECK_NONE);
703        //printf("c = %s\n", ewkt);
704        CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0.5 0.5 0.5,1 1 1,1.5 1.5 1.5))" );
705
706        lwfree(ewkt);
707        lwcollection_free(c);
708        lwline_free(line);
709}
710
711void test_geohash_precision(void)
712{
713        BOX3D bbox;
714        BOX3D bounds;
715        int precision = 0;
716
717        bbox.xmin = 23.0;
718        bbox.xmax = 23.0;
719        bbox.ymin = 25.2;
720        bbox.ymax = 25.2;
721        precision = lwgeom_geohash_precision(bbox, &bounds);
722        //printf("\nprecision %d\n",precision);
723        CU_ASSERT_EQUAL(precision, 20);
724
725        bbox.xmin = 23.0;
726        bbox.ymin = 23.0;
727        bbox.xmax = 23.1;
728        bbox.ymax = 23.1;
729        precision = lwgeom_geohash_precision(bbox, &bounds);
730        //printf("precision %d\n",precision);
731        CU_ASSERT_EQUAL(precision, 3);
732
733        bbox.xmin = 23.0;
734        bbox.ymin = 23.0;
735        bbox.xmax = 23.0001;
736        bbox.ymax = 23.0001;
737        precision = lwgeom_geohash_precision(bbox, &bounds);
738        //printf("precision %d\n",precision);
739        CU_ASSERT_EQUAL(precision, 7);
740
741}
742
743void test_geohash_point(void)
744{
745        char *geohash;
746
747        geohash = geohash_point(0, 0, 16);
748        //printf("\ngeohash %s\n",geohash);
749        CU_ASSERT_STRING_EQUAL(geohash, "7zzzzzzzzzzzzzzz");
750        lwfree(geohash);
751
752        geohash = geohash_point(90, 0, 16);
753        //printf("\ngeohash %s\n",geohash);
754        CU_ASSERT_STRING_EQUAL(geohash, "mzzzzzzzzzzzzzzz");
755        lwfree(geohash);
756
757        geohash = geohash_point(20.012345, -20.012345, 15);
758        //printf("\ngeohash %s\n",geohash);
759        CU_ASSERT_STRING_EQUAL(geohash, "kkqnpkue9ktbpe5");
760        lwfree(geohash);
761
762}
763
764void test_geohash(void)
765{
766        LWPOINT *lwpoint = NULL;
767        LWLINE *lwline = NULL;
768        LWMLINE *lwmline = NULL;
769        char *geohash = NULL;
770
771        lwpoint = (LWPOINT*)lwgeom_from_ewkt("POINT(23.0 25.2)", PARSER_CHECK_NONE);
772        geohash = lwgeom_geohash((LWGEOM*)lwpoint,0);
773        //printf("\ngeohash %s\n",geohash);
774        CU_ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
775        lwfree(lwpoint);
776        lwfree(geohash);
777
778        lwpoint = (LWPOINT*)lwgeom_from_ewkt("POINT(23.0 25.2 2.0)", PARSER_CHECK_NONE);
779        geohash = lwgeom_geohash((LWGEOM*)lwpoint,0);
780        //printf("geohash %s\n",geohash);
781        CU_ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
782        lwfree(lwpoint);
783        lwfree(geohash);
784
785        lwline = (LWLINE*)lwgeom_from_ewkt("LINESTRING(23.0 23.0,23.1 23.1)", PARSER_CHECK_NONE);
786        geohash = lwgeom_geohash((LWGEOM*)lwline,0);
787        //printf("geohash %s\n",geohash);
788        CU_ASSERT_STRING_EQUAL(geohash, "ss0");
789        lwfree(lwline);
790        lwfree(geohash);
791
792        lwline = (LWLINE*)lwgeom_from_ewkt("LINESTRING(23.0 23.0,23.001 23.001)", PARSER_CHECK_NONE);
793        geohash = lwgeom_geohash((LWGEOM*)lwline,0);
794        //printf("geohash %s\n",geohash);
795        CU_ASSERT_STRING_EQUAL(geohash, "ss06g7");
796        lwfree(lwline);
797        lwfree(geohash);
798
799        lwmline = (LWMLINE*)lwgeom_from_ewkt("MULTILINESTRING((23.0 23.0,23.1 23.1),(23.0 23.0,23.1 23.1))", PARSER_CHECK_NONE);
800        geohash = lwgeom_geohash((LWGEOM*)lwmline,0);
801        //printf("geohash %s\n",geohash);
802        CU_ASSERT_STRING_EQUAL(geohash, "ss0");
803        lwfree(lwmline);
804        lwfree(geohash);
805}
806
807
Note: See TracBrowser for help on using the repository browser.