PostGIS  2.1.10dev-r@@SVN_REVISION@@
cu_tree.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Copyright 2011 Sandro Santilli <strk@keybit.net>
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 "lwgeodetic.h"
20 #include "lwgeodetic_tree.h"
21 #include "cu_tester.h"
22 
23 
24 static void test_tree_circ_create(void)
25 {
26  LWLINE *g;
27  CIRC_NODE *c;
28  /* Line with 4 edges */
29  g = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(0 88,0 89,0 90,180 89,180 88)", LW_PARSER_CHECK_NONE));
30  c = circ_tree_new(g->points);
31  //circ_tree_print(c, 0);
32 
33  if ( CIRC_NODE_SIZE > 4 )
34  {
35  CU_ASSERT(c->num_nodes == 4);
36  }
37  else
38  {
39  CU_ASSERT(c->num_nodes == ( 4 % CIRC_NODE_SIZE ? 1 : 0 ) + 4 / CIRC_NODE_SIZE);
40  }
41 
42  circ_tree_free(c);
43  lwline_free(g);
44 }
45 
46 
47 static void test_tree_circ_pip(void)
48 {
49  LWLINE *g;
50  CIRC_NODE *c;
51  POINT2D pt, pt_outside;
52  int rv, on_boundary;
53 
54  pt.x = 0.0;
55  pt.y = 0.0;
56  pt_outside.x = -2.0;
57  pt_outside.y = 0.0;
58 
59  /* Point in square */
60  g = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(-1 -1,1 -1,1 1,-1 1,-1 -1)", LW_PARSER_CHECK_NONE));
61  c = circ_tree_new(g->points);
62  rv = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
63  CU_ASSERT_EQUAL(rv, 1);
64 
65  /* Point on other side of square */
66  pt.x = 2.0;
67  pt.y = 0.0;
68  rv = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
69  CU_ASSERT_EQUAL(rv, 0);
70 
71  /* Clean and do new shape */
72  circ_tree_free(c);
73  lwline_free(g);
74 
75  /* Point in square, stab passing through vertex */
76  pt.x = 0.0;
77  pt.y = 0.0;
78  g = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(-1 -1,0 -1,1 -1,1 0,1 1,0 1,-1 1,-1 0,-1 -1)", LW_PARSER_CHECK_NONE));
79  c = circ_tree_new(g->points);
80  //circ_tree_print(c, 0);
81  rv = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
82  CU_ASSERT_EQUAL(rv, 1);
83 
84  /* Point on other side of square, stab passing through vertex */
85  pt.x = 2.0;
86  pt.y = 0.0;
87  rv = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
88  CU_ASSERT_EQUAL(rv, 0);
89 
90  /* Clean and do new shape */
91  circ_tree_free(c);
92  lwline_free(g);
93 
94  /* Point outside "w" thing, stab passing through vertexes and grazing pointy thing */
95  pt.x = 2.0;
96  pt.y = 0.0;
97  g = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(-1 -1,0 -1,1 -1,1 0,1 1,0 0,-1 1,-1 0,-1 -1)", LW_PARSER_CHECK_NONE));
98  c = circ_tree_new(g->points);
99  //circ_tree_print(c, 0);
100  rv = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
101  //printf("rv %d\n", rv);
102  CU_ASSERT_EQUAL(rv, 0);
103 
104  /* Point inside "w" thing, stab passing through vertexes and grazing pointy thing */
105  pt.x = 0.8;
106  pt.y = 0.0;
107  rv = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
108  //printf("rv %d\n", rv);
109  CU_ASSERT_EQUAL(rv, 1);
110 
111  /* Clean and do new shape */
112  circ_tree_free(c);
113  lwline_free(g);
114 
115 }
116 
117 static void test_tree_circ_pip2(void)
118 {
119  LWGEOM* g;
120  LWPOLY* p;
121  LWPOINT* lwpt;
122  int rv_classic, rv_tree, on_boundary;
123  POINT2D pt, pt_outside;
124  GBOX gbox;
125  CIRC_NODE *c;
126 
127  g = lwgeom_from_wkt("POLYGON((0 0,0 1,1 1,1 0,0 0))", LW_PARSER_CHECK_NONE);
128  p = lwgeom_as_lwpoly(g);
129 
130  pt.x = 0.2;
131  pt.y = 0.1;
133  gbox_pt_outside(&gbox, &pt_outside);
134  c = circ_tree_new(p->rings[0]);
135  //circ_tree_print(c, 0);
136  rv_classic = lwpoly_covers_point2d(p, &pt);
137  rv_tree = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
138  CU_ASSERT_EQUAL(rv_tree, rv_classic);
139  circ_tree_free(c);
140  lwgeom_free(g);
141 
142  g = lwgeom_from_hexwkb("0103000020E6100000010000004700000000000000621119C000000040C70C4B40000000E0CC6C18C0000000A026FF4A4000000040438519C000000000E8F44A40000000000F5318C00000004024C84A4000000060F9E518C0000000A027AD4A40000000805E0D18C0000000C0F5784A4000000040539718C000000080815E4A40000000C026FE19C0000000C0502D4A4000000060127019C000000040EA164A40000000003BFD1BC0000000609E234A4000000080D9011CC000000060B9114A4000000040C8501EC0000000C0D50C4A40000000C05F2C20C000000040C9E749400000006008D820C000000080D6F0494000000080139F20C000000060F3DE4940000000A0B16421C0000000C059C94940000000808FA223C0000000C007B949400000000041E722C000000080C3DC4940000000808F4224C0000000405DCE494000000060752923C000000040A9EF4940000000005CAD24C0000000C036E4494000000040F88624C00000008078FE494000000060558523C00000006025134A40000000403AED24C00000000011174A40000000A05E7D23C0000000E0A41F4A4000000040F0AD23C0000000809A304A4000000040A64E23C000000040C9474A40000000C0FCA221C0000000C030554A40000000805EDD23C0000000E010474A4000000040BFF822C00000008078664A4000000080C98F22C000000040E2914A40000000C036E021C00000002024924A4000000080D9E121C000000000D0A14A4000000040533723C000000040B99D4A40000000204B1E23C0000000C0CCB04A4000000000625A24C0000000A071B44A40000000004A5F24C0000000806FC64A40000000E0DD6523C00000006088CC4A400000004012D023C0000000001AE14A40000000806E1F23C0000000400BEE4A40000000E0A2E123C0000000C017EF4A4000000060449423C00000004003F94A40000000C0DC0624C0000000A0ED1B4B40000000A0803F24C0000000005D0C4B4000000040753924C000000080701D4B400000002021F320C00000000001234B4000000000C65221C000000080792D4B40000000406D6020C0000000001A514B4000000040BF9821C0000000A00E594B400000000031B520C0000000C0726B4B400000002019EA20C000000020977F4B400000000002ED1FC0000000E0B49B4B400000000084CC1EC0000000602D8C4B4000000020BB2A1FC000000060239B4B4000000040AE871EC0000000A0FDA14B400000008077771EC0000000C0E5864B40000000C0AABA1EC000000000B7794B40000000C03EC91DC0000000E020874B4000000000A4301EC0000000C0C49B4B4000000000B5811DC0000000A0A3B04B400000004095BD1BC000000020869E4B400000004091021DC00000004009894B40000000409D361EC000000080A2614B40000000809FB41FC0000000A0AB594B40000000C046021FC0000000C0164C4B40000000C0EC5020C0000000E05A384B4000000040DF3C1EC0000000803F104B4000000000B4221DC0000000C0CD0F4B40000000C0261E1CC00000006067354B4000000080E17A1AC000000080C3044B4000000000621119C000000040C70C4B40", LW_PARSER_CHECK_NONE);
143  p = lwgeom_as_lwpoly(g);
144  lwpt = (LWPOINT*)lwgeom_from_hexwkb("0101000020E610000057B89C28FEB320C09C8102CB3B2B4A40", LW_PARSER_CHECK_NONE);
145  lwpoint_getPoint2d_p(lwpt, &pt);
147  gbox_pt_outside(&gbox, &pt_outside);
148  //printf("OUTSIDE POINT(%g %g)\n", pt_outside.x, pt_outside.y);
149  c = circ_tree_new(p->rings[0]);
150  rv_classic = lwpoly_covers_point2d(p, &pt);
151  rv_tree = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
152  CU_ASSERT_EQUAL(rv_tree, rv_classic);
153  circ_tree_free(c);
154  lwpoint_free(lwpt);
155  lwgeom_free(g);
156 
157  g = lwgeom_from_hexwkb("0103000020E610000001000000CF0100000000000000004EC03943F5FFFF7F56400000000000003E403943F5FFFF7F56400000000000003E401842CEFBFF7F56400000000000003E402F849CF7FF7F56400000000000003E4047C66AF3FF7F56400000000000003E405F0839EFFF7F56400000000000003E40774A07EBFF7F56400000000000003E408F8CD5E6FF7F56400000000000003E40A6CEA3E2FF7F56400000000000003E40D65240DAFF7F56400000000000003E4006D7DCD1FF7F56400000000000003E40355B79C9FF7F56400000000000003E407D21E4BCFF7F56400000000000003E40DC291DACFF7F56400000000000003E403B32569BFF7F56400000000000003E40CABE2B82FF7F56400000000000003E40594B0169FF7F56400000000000003E40309E4143FF7F56400000000000003E401E335019FF7F56400000000000003E403C4CFBE6FE7F56400000000000003E40B96DDFA3FE7F56400000000000003E407E552E54FE7F56400000000000003E40A245B6F3FD7F56400000000000003E403D80457EFD7F56400000000000003E407E8978EBFC7F56400000000000003E407FA31D37FC7F56400000000000003E405510035DFB7F56400000000000003E404A969350FA7F56400000000000003E40BC3D0801F97F56400000000000003E40C3482F6AF77F56400000000000003E40D5011077F57F56400000000000003E406CB3B112F37F56400000000000003E402C2CB81FF07F56400000000000003E40A4F8F884EC7F56400000000000003E40C5AD8218E87F56400000000000003E40C1A6CEA3E27F56400000000000003E40A1BAB9F8DB7F56400000000000003E40401361C3D37F56400000000000003E40639813B4C97F56400000000000003E408D429259BD7F56400000000000003E40B854A52DAE7F56400000000000003E406F9EEA909B7F56400000000000003E403FC6DCB5847F56400000000000003E408FC536A9687F56400000000000003E402975C938467F56400000000000003E403F8D7BF31B7F56400000000000003E40F4311F10E87E56400000000000003E40C1FBAA5CA87E56400000000000003E40D2FF722D5A7E56400000000000003E4009A7052FFA7D56400000000000003E403332C85D847D56400000000000003E40B35F77BAF37C56400000000000003E40253ACB2C427C56400000000000003E40FA7B293C687B56400000000000003E407D3D5FB35C7A56400000000000003E40E3A25A44147956400000000000003E40A0504F1F817756400000000000003E4062855B3E927556400000000000003E40B62BF4C1327356400000000000003E40280D350A497056400000000000003E4061DC0DA2B56C56400000000000003E40B81E85EB516856400000000000003E403237DF88EE6256400000000000003E4041EE224C515C56400000000000003E409EE925C6325456400000000000003E400B2593533B4A56400000000000003E4089CF9D60FF3D56400000000000003E40F04A92E7FA2E56400000000000003E40AC3594DA8B1C56400000000000003E40C9022670EB0556400000000000003E4069A510C825EA55400000000000003E4033DC80CF0FC855400000000000003E40FF907EFB3A9E55400000000000003E404203B16CE66A55400000000000003E40DA39CD02ED2B55400000000000003E4070404B57B0DE54400000000000003E4000000000008054403333333333B33D4000000000008054406666666666663D4000000000008054409999999999193D400000000000805440CCCCCCCCCCCC3C4000000000008054400000000000803C4000000000008054403333333333333C4000000000008054406666666666E63B4000000000008054409999999999993B400000000000805440CCCCCCCCCC4C3B4000000000008054400000000000003B4000000000008054403333333333B33A4000000000008054406666666666663A4000000000008054409999999999193A400000000000805440CCCCCCCCCCCC3940000000000080544000000000008039400000000000805440333333333333394000000000008054406666666666E63840000000000080544099999999999938400000000000805440CCCCCCCCCC4C38400000000000805440000000000000384000000000008054403333333333B3374000000000008054406666666666663740000000000080544099999999991937400000000000805440CDCCCCCCCCCC3640000000000080544000000000008036400000000000805440333333333333364000000000008054406666666666E63540000000000080544099999999999935400000000000805440CDCCCCCCCC4C35400000000000805440000000000000354000000000008054403333333333B3344000000000008054406666666666663440000000000080544099999999991934400000000000805440CDCCCCCCCCCC3340000000000080544000000000008033400000000000805440333333333333334000000000008054406666666666E63240000000000080544099999999999932400000000000805440CDCCCCCCCC4C32400000000000805440000000000000324000000000008054403333333333B3314000000000008054406666666666663140000000000080544099999999991931400000000000805440CDCCCCCCCCCC304000000000008054400000000000803040000000000080544033333333333330400000000000805440CCCCCCCCCCCC2F4000000000008054403333333333332F4000000000008054409999999999992E4000000000008054400000000000002E4000000000008054406666666666662D400000000000805440CCCCCCCCCCCC2C4000000000008054403333333333332C4000000000008054409999999999992B4000000000008054400000000000002B4000000000008054406666666666662A400000000000805440CCCCCCCCCCCC2940000000000080544033333333333329400000000000805440999999999999284000000000008054400000000000002840000000000080544066666666666627400000000000805440CDCCCCCCCCCC2640000000000080544033333333333326400000000000805440999999999999254000000000008054400000000000002540000000000080544066666666666624400000000000805440CDCCCCCCCCCC2340000000000080544033333333333323400000000000805440999999999999224000000000008054400000000000002240000000000080544066666666666621400000000000805440CDCCCCCCCCCC20400000000000805440333333333333204000000000008054403333333333331F4000000000008054400000000000001E400000000000805440CCCCCCCCCCCC1C4000000000008054409999999999991B4000000000008054406666666666661A4000000000008054403333333333331940000000000080544000000000000018400000000000805440CDCCCCCCCCCC1640000000000080544099999999999915400000000000805440666666666666144000000000008054403333333333331340000000000080544000000000000012400000000000805440CDCCCCCCCCCC104000000000008054403333333333330F400000000000805440CCCCCCCCCCCC0C4000000000008054406666666666660A400000000000805440000000000000084000000000008054409999999999990540000000000080544033333333333303400000000000805440CDCCCCCCCCCC00400000000000805440CCCCCCCCCCCCFC3F0000000000805440000000000000F83F0000000000805440333333333333F33F0000000000805440CCCCCCCCCCCCEC3F0000000000805440333333333333E33F0000000000805440333333333333D33F00000000008054400000000000000000000000000080544000000000000000002174D0251C7C54400000000000000000F96871C6307854400000000000000000E6E61BD13D745440000000000000000019726C3D437054400000000000000000F0129CFA406C54400000000000000000CCD1E3F7366854400000000000000000F374AE28256454400000000000000000ACC266800B6054400000000000000000700514EAE95B544000000000000000006EC1525DC057544000000000000000001C412AC58E5354400000000000000000AB083719554F5440000000000000000091628044134B544000000000000000001615713AC94654400000000000000000992842EA7642544000000000000000007AA52C431C3E5440000000000000000000529B38B939544000000000000000008B36C7B94D3554400000000000000000795BE9B5D9305440000000000000000029C93A1C5D2C54400000000000000000E54526E0D72754400000000000000000211CB3EC49235440000000000000000027124C35B31E5440000000000000000055302AA9131A544000000000000000000A7F86376B1554400000000000000000BE4868CBB91054400000000000000000A1116C5CFF0B54400000000000000000406667D13B0754400000000000000000E50CC51D6F0254400000000000000000ED0DBE3099FD53400000000000000000D0B359F5B9F853400000000000000000D6C4025FD1F353400000000000000000768BC058DFEE534000000000000000000E10CCD1E3E953400000000000000000FF5A5EB9DEE453400000000000000000A774B0FECFDF534000000000000000006665FB90B7DA53400000000000000000CBB9145795D55340000000000000000005F6984869D053400000000000000000BCE82B4833CB534000000000000000001E166A4DF3C553400000000000000000A3C85A43A9C053400000000000000000DA8CD31055BB53400000000000000000F3E670ADF6B5534000000000000000007C6308008EB053400000000000000000EC4CA1F31AAB534000000000000000008B69A67B9DA553400000000000000000E945ED7E15A0534000000000000000004CA8E0F0829A53400000000000000000431D56B8E5945340000000000000000045EF54C03D8F534000000000000000009BE447FC8A8953400000000000000000D2890453CD83534000000000000000004BE7C3B3047E5340000000000000000093895B053178534000000000000000000B79043752725340000000000000000012BEF737686C5340000000000000000036E50AEF726653400000000000000000EF3845477260534000000000000000009CC1DF2F665A53400000000000000000CC0BB08F4E5453400000000000000000DE1FEF552B4E53400000000000000000618A7269FC4753400000000000000000B45373B9C141534000000000000000006708C72C7B3B53400000000000000000D9B0A6B228355340000000000000000098D9E731CA2E53400000000000000000340F60915F2853400000000000000000F4177AC4E821534000000000000000007EC2D9AD651B534000000000000000003317B83CD61453400000000000000000A0A2EA573A0E5340000000000000000056F146E6910753400000000000000000B20B06D7DC0053400000000000000000457EFD101BFA524000000000000000008593347F4CF352400000000000000000191A4F0471EC5240000000000000000049D8B79388E552400000000000000000BA9C121093DE52400000000000000000E6B1666490D75240000000000000000059A4897780D0524000000000000000008CBE823463C9524000000000000000000D8D278238C2524000000000000000006B9C4D4700BB524000000000000000001D37FC6EBAB352400000000000000000B3E908E066AC52400000000000000000A4FE7A8505A5524000000000000000009544F641969D52400000000000000000FF05820019965240000000000000000070CFF3A78D8E52400000000000000000772D211FF486524000000000000000008B6A11514C7F52400000000000000000545568209677524000000000000000005F7AFB73D16F524000000000000000002424D236FE675240000000000000000033DFC14F1C6052400000000000000000317A6EA12B5852400000000000000000963FDF162C505240000000000000000008FEB7921D48524000000000000000000000000000405240999999999999C9BF0000000000405240999999999999D9BF0000000000405240333333333333E3BF0000000000405240999999999999E9BF0000000000405240000000000000F0BF0000000000405240333333333333F3BF0000000000405240666666666666F6BF0000000000405240999999999999F9BF0000000000405240CCCCCCCCCCCCFCBF000000000040524000000000000000C0000000000040524099999999999901C0000000000040524033333333333303C00000000000405240CDCCCCCCCCCC04C0000000000040524066666666666606C0000000000040524000000000000008C0000000000040524099999999999909C000000000004052403333333333330BC00000000000405240CCCCCCCCCCCC0CC000000000004052406666666666660EC0000000000040524000000000000010C00000000000405240CDCCCCCCCCCC10C0000000000040524099999999999911C0000000000040524066666666666612C0000000000040524033333333333313C0000000000040524000000000000014C00000000000405240CDCCCCCCCCCC14C0000000000040524099999999999915C0000000000040524066666666666616C0000000000040524033333333333317C0000000000040524000000000000018C00000000000405240CCCCCCCCCCCC18C0000000000040524099999999999919C000000000004052406666666666661AC000000000004052403333333333331BC000000000004052400000000000001CC00000000000405240CCCCCCCCCCCC1CC000000000004052409999999999991DC000000000004052406666666666661EC000000000004052403333333333331FC0000000000040524000000000000020C0000000000040524066666666666620C00000000000405240CDCCCCCCCCCC20C0000000000040524033333333333321C0000000000040524099999999999921C0000000000040524000000000000022C0000000000040524066666666666622C00000000000405240CDCCCCCCCCCC22C0000000000040524033333333333323C0000000000040524099999999999923C0000000000040524000000000000024C0000000000040524066666666666624C00000000000405240CDCCCCCCCCCC24C0000000000040524033333333333325C0000000000040524099999999999925C0000000000040524000000000000026C0000000000040524066666666666626C00000000000405240CDCCCCCCCCCC26C0000000000040524033333333333327C0000000000040524099999999999927C0000000000040524000000000000028C0000000000040524066666666666628C00000000000405240CCCCCCCCCCCC28C0000000000040524033333333333329C0000000000040524099999999999929C000000000004052400000000000002AC000000000004052406666666666662AC00000000000405240CCCCCCCCCCCC2AC000000000004052403333333333332BC000000000004052409999999999992BC000000000004052400000000000002CC000000000004052406666666666662CC00000000000405240CCCCCCCCCCCC2CC000000000004052403333333333332DC000000000004052409999999999992DC000000000004052400000000000002EC000000000004052406666666666662EC00000000000405240CCCCCCCCCCCC2EC000000000004052403333333333332FC000000000004052409999999999992FC0000000000040524000000000000030C0000000000040524033333333333330C0000000000040524066666666666630C0000000000040524099999999999930C00000000000405240CDCCCCCCCCCC30C0000000000040524000000000000031C0000000000040524033333333333331C0000000000040524066666666666631C0000000000040524099999999999931C00000000000405240CDCCCCCCCCCC31C0000000000040524000000000000032C0000000000040524033333333333332C0000000000040524066666666666632C0000000000040524099999999999932C00000000000405240CDCCCCCCCCCC32C0000000000040524000000000000033C0000000000040524033333333333333C0000000000040524066666666666633C0000000000040524099999999999933C00000000000405240CDCCCCCCCCCC33C0000000000040524000000000000034C0000000000040524000000000000034C0000000000080514000000000008043C00000000000C04F4000000000008045C00000000000404D4030116F9D7F8B45C00000000000404D408FA67A32FF9645C00000000000404D40BFB7E9CF7EA245C00000000000404D401E4DF564FEAD45C00000000000404D404E5E64027EB945C00000000000404D40AEF36F97FDC445C00000000000404D40DD04DF347DD045C00000000000404D403D9AEAC9FCDB45C00000000000404D406DAB59677CE745C00000000000404D40CC4065FCFBF245C00000000000404D40FC51D4997BFE45C00000000000404D405BE7DF2EFB0946C00000000000404D408BF84ECC7A1546C00000000000404D40EB8D5A61FA2046C00000000000404D401B9FC9FE792C46C00000000000404D407A34D593F93746C00000000000404D40AA454431794346C00000000000404D40DA56B3CEF84E46C00000000000404D4039ECBE63785A46C00000000000404D4069FD2D01F86546C00000000000404D40C8923996777146C00000000000404D40F8A3A833F77C46C00000000000404D405839B4C8768846C00000000000404D40884A2366F69346C00000000000404D40E7DF2EFB759F46C00000000000404D4017F19D98F5AA46C00000000000404D407686A92D75B646C00000000000404D40A69718CBF4C146C00000000000404D40062D246074CD46C00000000000404D40353E93FDF3D846C00000000000404D4095D39E9273E446C00000000000404D40C5E40D30F3EF46C00000000000404D40247A19C572FB46C00000000000404D40548B8862F20647C00000000000404D40B42094F7711247C00000000000404D40E3310395F11D47C00000000000404D4013437232712947C00000000000404D4073D87DC7F03447C00000000000404D40A2E9EC64704047C00000000000404D40027FF8F9EF4B47C00000000000404D40329067976F5747C00000000000404D409125732CEF6247C00000000000404D40C136E2C96E6E47C00000000000404D4021CCED5EEE7947C00000000000404D4050DD5CFC6D8547C00000000000404D40B0726891ED9047C00000000000404D40E083D72E6D9C47C00000000000404D403F19E3C3ECA747C00000000000404D406F2A52616CB347C00000000000404D40CEBF5DF6EBBE47C00000000000404D40FED0CC936BCA47C00000000000404D405E66D828EBD547C00000000000404D408E7747C66AE147C00000000000404D40BD88B663EAEC47C00000000000404D401D1EC2F869F847C00000000000404D404D2F3196E90348C00000000000404D40ACC43C2B690F48C00000000000404D40DCD5ABC8E81A48C00000000000404D403B6BB75D682648C00000000000404D406B7C26FBE73148C00000000000404D40CB113290673D48C00000000000404D40FB22A12DE74848C00000000000404D405AB8ACC2665448C00000000000404D408AC91B60E65F48C00000000000404D40E95E27F5656B48C00000000000404D4019709692E57648C00000000000404D407905A227658248C00000000000404D40A81611C5E48D48C00000000000404D4008AC1C5A649948C00000000000404D4038BD8BF7E3A448C00000000000404D4068CEFA9463B048C00000000000404D40C763062AE3BB48C00000000000404D40F77475C762C748C00000000000404D40560A815CE2D248C00000000000404D40861BF0F961DE48C00000000000404D40E6B0FB8EE1E948C00000000000404D4015C26A2C61F548C00000000000404D4000000000000049C00000000000404D400000000000E04CC0000000000040504000000000000053C000000000000053400000000000C052C000000000008053400000000000004EC000000000008054400000000000004EC03943F5FFFF7F5640", LW_PARSER_CHECK_NONE);
158  p = lwgeom_as_lwpoly(g);
159  lwpt = (LWPOINT*)lwgeom_from_hexwkb("0101000020E610000031B1F9B836A046C03C889D2974124E40", LW_PARSER_CHECK_NONE);
160  lwpoint_getPoint2d_p(lwpt, &pt);
162  gbox_pt_outside(&gbox, &pt_outside);
163  //printf("OUTSIDE POINT(%g %g)\n", pt_outside.x, pt_outside.y);
164  c = circ_tree_new(p->rings[0]);
165  rv_classic = lwpoly_covers_point2d(p, &pt);
166  rv_tree = circ_tree_contains_point(c, &pt, &pt_outside, &on_boundary);
167  CU_ASSERT_EQUAL(rv_tree, rv_classic);
168  circ_tree_free(c);
169  lwpoint_free(lwpt);
170  lwgeom_free(g);
171 
172 }
173 
174 
175 static void test_tree_circ_distance(void)
176 {
177  LWGEOM *lwg1, *lwg2;
178  CIRC_NODE *c1, *c2;
179  SPHEROID s;
180  double d1, d2;
181  double threshold = 0.0;
182 
183  spheroid_init(&s, 1.0, 1.0);
184 
185  /* Ticket #1958 */
186  lwg1 = lwgeom_from_wkt("LINESTRING(22.88333 41.96667,21.32667 42.13667)", LW_PARSER_CHECK_NONE);
187  lwg2 = lwgeom_from_wkt("POLYGON((22.94472 41.34667,22.87528 41.99028,22.87389 41.98472,22.87472 41.98333,22.94472 41.34667))", LW_PARSER_CHECK_NONE);
188  c1 = lwgeom_calculate_circ_tree(lwg1);
189  c2 = lwgeom_calculate_circ_tree(lwg2);
190  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
191  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
192 // printf("d1 = %g d2 = %g\n", d1 * WGS84_RADIUS, d2 * WGS84_RADIUS);
193 // printf("line\n");
194 // circ_tree_print(c1, 0);
195 // printf("poly\n");
196 // circ_tree_print(c2, 0);
197  circ_tree_free(c1);
198  circ_tree_free(c2);
199  lwgeom_free(lwg1);
200  lwgeom_free(lwg2);
201  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.0000001);
202 
203  /* Ticket #1951 */
204  lwg1 = lwgeom_from_wkt("LINESTRING(0 0, 0 0)", LW_PARSER_CHECK_NONE);
205  lwg2 = lwgeom_from_wkt("POINT(0.1 0.1)", LW_PARSER_CHECK_NONE);
206  c1 = lwgeom_calculate_circ_tree(lwg1);
207  c2 = lwgeom_calculate_circ_tree(lwg2);
208  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
209  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
210  circ_tree_free(c1);
211  circ_tree_free(c2);
212  lwgeom_free(lwg1);
213  lwgeom_free(lwg2);
214  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.00001);
215 
216  lwg1 = lwgeom_from_wkt("LINESTRING(-1 -1,0 -1,1 -1,1 0,1 1,0 0,-1 1,-1 0,-1 -1)", LW_PARSER_CHECK_NONE);
217  lwg2 = lwgeom_from_wkt("POINT(-2 0)", LW_PARSER_CHECK_NONE);
218  c1 = lwgeom_calculate_circ_tree(lwg1);
219  c2 = lwgeom_calculate_circ_tree(lwg2);
220  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
221  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
222  circ_tree_free(c1);
223  circ_tree_free(c2);
224  lwgeom_free(lwg1);
225  lwgeom_free(lwg2);
226  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.00001);
227 
228  lwg1 = lwgeom_from_wkt("LINESTRING(-1 -1,0 -1,1 -1,1 0,1 1,0 0,-1 1,-1 0,-1 -1)", LW_PARSER_CHECK_NONE);
229  lwg2 = lwgeom_from_wkt("POINT(2 2)", LW_PARSER_CHECK_NONE);
230  c1 = lwgeom_calculate_circ_tree(lwg1);
231  c2 = lwgeom_calculate_circ_tree(lwg2);
232  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
233  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
234  circ_tree_free(c1);
235  circ_tree_free(c2);
236  lwgeom_free(lwg1);
237  lwgeom_free(lwg2);
238  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.00001);
239 
240  lwg1 = lwgeom_from_wkt("LINESTRING(-1 -1,0 -1,1 -1,1 0,1 1,0 0,-1 1,-1 0,-1 -1)", LW_PARSER_CHECK_NONE);
241  lwg2 = lwgeom_from_wkt("POINT(1 1)", LW_PARSER_CHECK_NONE);
242  c1 = lwgeom_calculate_circ_tree(lwg1);
243  c2 = lwgeom_calculate_circ_tree(lwg2);
244  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
245  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
246  circ_tree_free(c1);
247  circ_tree_free(c2);
248  lwgeom_free(lwg1);
249  lwgeom_free(lwg2);
250  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.00001);
251 
252  lwg1 = lwgeom_from_wkt("LINESTRING(-1 -1,0 -1,1 -1,1 0,1 1,0 0,-1 1,-1 0,-1 -1)", LW_PARSER_CHECK_NONE);
253  lwg2 = lwgeom_from_wkt("POINT(1 0.5)", LW_PARSER_CHECK_NONE);
254  c1 = lwgeom_calculate_circ_tree(lwg1);
255  c2 = lwgeom_calculate_circ_tree(lwg2);
256  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
257  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
258 // printf("distance_tree %g\n", distance_tree);
259 // printf("distance_geom %g\n", distance_geom);
260 // circ_tree_print(cline, 0);
261 // circ_tree_print(cpoint, 0);
262  circ_tree_free(c1);
263  circ_tree_free(c2);
264  lwgeom_free(lwg1);
265  lwgeom_free(lwg2);
266  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.00001);
267 
268 
269  /* Ticket #2351 */
270  lwg1 = lwgeom_from_wkt("LINESTRING(149.386990599235 -26.3567415843982,149.386990599247 -26.3567415843965)", LW_PARSER_CHECK_NONE);
271  lwg2 = lwgeom_from_wkt("POINT(149.386990599235 -26.3567415843982)", LW_PARSER_CHECK_NONE);
272  c1 = lwgeom_calculate_circ_tree(lwg1);
273  c2 = lwgeom_calculate_circ_tree(lwg2);
274  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
275  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
276  // printf("d1 = %g d2 = %g\n", d1 * WGS84_RADIUS, d2 * WGS84_RADIUS);
277  // printf("line\n");
278  // circ_tree_print(c1, 0);
279  // printf("point\n");
280  // circ_tree_print(c2, 0);
281  circ_tree_free(c1);
282  circ_tree_free(c2);
283  lwgeom_free(lwg1);
284  lwgeom_free(lwg2);
285  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.0000001);
286 
287  /* Ticket #2634 */
288  lwg1 = lwgeom_from_wkt("MULTIPOINT (-10 40,-10 65,10 40,10 65,30 40,30 65,50 40,50 65)", LW_PARSER_CHECK_NONE);
289  lwg2 = lwgeom_from_wkt("POLYGON((-9.1111111 40,-9.14954053919354 39.6098193559677,-9.26335203497743 39.2346331352698,-9.4481718753949138.8888595339608,-9.6968975376269 38.5857864376269,-9.99997063396079 38.3370607753949,-10.3457442352698 38.1522409349774,-10.7209304559677 38.0384294391935,-11.1111111 38,-11.5012917440323 38.0384294391935,-11.8764779647302 38.1522409349774,-12.2222515660392 38.3370607753949,-12.5253246623731 38.5857864376269,-12.7740503246051 38.8888595339608,-12.9588701650226 39.2346331352698,-13.0726816608065 39.6098193559677,-13.1111111 40,-13.0726816608065 40.3901806440322,-12.9588701650226 40.7653668647302,-12.7740503246051 41.1111404660392,-12.5253246623731 41.4142135623731,-12.2222515660392 41.6629392246051,-11.8764779647302 41.8477590650226,-11.5012917440323 41.9615705608065,-11.1111111 42,-10.7209304559678 41.9615705608065,-10.3457442352698 41.8477590650226,-9.9999706339608 41.6629392246051,-9.69689753762691 41.4142135623731,-9.44817187539491 41.1111404660392,-9.26335203497743 40.7653668647302,-9.14954053919354 40.3901806440323,-9.1111111 40))", LW_PARSER_CHECK_NONE);
290  c1 = lwgeom_calculate_circ_tree(lwg1);
291  c2 = lwgeom_calculate_circ_tree(lwg2);
292  d1 = circ_tree_distance_tree(c1, c2, &s, threshold);
293  d2 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
294  // printf("d1 = %g d2 = %g\n", d1 * WGS84_RADIUS, d2 * WGS84_RADIUS);
295  // printf("multipoint\n");
296  // circ_tree_print(c1, 0);
297  // printf("polygon\n");
298  // circ_tree_print(c2, 0);
299  circ_tree_free(c1);
300  circ_tree_free(c2);
301  lwgeom_free(lwg1);
302  lwgeom_free(lwg2);
303  CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.0000001);
304 }
305 
306 
307 
308 /*
309 ** Used by test harness to register the tests in this file.
310 */
311 void tree_suite_setup(void);
313 {
314  CU_pSuite suite = CU_add_suite("Internal Spatial Trees", NULL, NULL);
319 }
int lwgeom_calculate_gbox_geodetic(const LWGEOM *geom, GBOX *gbox)
Calculate the geodetic bounding box for an LWGEOM.
Definition: lwgeodetic.c:2612
#define CIRC_NODE_SIZE
Note that p1 and p2 are pointers into an independent POINTARRAY, do not free them.
void spheroid_init(SPHEROID *s, double a, double b)
Initialize a spheroid object for use in geodetic functions.
Definition: lwspheroid.c:20
int lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out)
Definition: lwpoint.c:25
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:180
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
void lwline_free(LWLINE *line)
Definition: lwline.c:63
static void test_tree_circ_distance(void)
Definition: cu_tree.c:175
static void test_tree_circ_pip(void)
Definition: cu_tree.c:47
double circ_tree_distance_tree(const CIRC_NODE *n1, const CIRC_NODE *n2, const SPHEROID *spheroid, double threshold)
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:125
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:844
CIRC_NODE * lwgeom_calculate_circ_tree(const LWGEOM *lwgeom)
void tree_suite_setup(void)
Definition: cu_tree.c:312
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1706
double x
Definition: liblwgeom.h:284
CIRC_NODE * circ_tree_new(const POINTARRAY *pa)
Build a tree of nodes from a point array, one node per edge.
static void test_tree_circ_pip2(void)
Definition: cu_tree.c:117
#define PG_ADD_TEST(suite, testfunc)
int circ_tree_contains_point(const CIRC_NODE *node, const POINT2D *pt, const POINT2D *pt_outside, int *on_boundary)
Walk the tree and count intersections between the stab line and the edges.
POINTARRAY ** rings
Definition: liblwgeom.h:413
char * s
Definition: cu_in_wkt.c:24
double y
Definition: liblwgeom.h:284
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:753
void circ_tree_free(CIRC_NODE *node)
Recurse from top of node tree and free all children.
void gbox_pt_outside(const GBOX *gbox, POINT2D *pt_outside)
Calculate a spherical point that falls outside the geocentric gbox.
Definition: lwgeodetic.c:1443
static void test_tree_circ_create(void)
Definition: cu_tree.c:24
double lwgeom_distance_spheroid(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2, const SPHEROID *spheroid, double tolerance)
Calculate the geodetic distance from lwgeom1 to lwgeom2 on the spheroid.
Definition: lwgeodetic.c:2078
int lwpoly_covers_point2d(const LWPOLY *poly, const POINT2D *pt_to_test)
Given a polygon (lon/lat decimal degrees) and point (lon/lat decimal degrees) and a guaranteed outsid...
Definition: lwgeodetic.c:2384
POINTARRAY * points
Definition: liblwgeom.h:378