1 /******************************************************************************
2 * Copyright (c) 2016, Howard Butler <howard@hobu.co>
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following
8 * conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
17 * names of its contributors may be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 * OF SUCH DAMAGE.
33 ****************************************************************************/
34
35 #include <pdal/pdal_test_main.hpp>
36
37 #include <pdal/PointView.hpp>
38 #include <pdal/Options.hpp>
39 #include <pdal/Polygon.hpp>
40 #include <pdal/util/Algorithm.hpp>
41 #include <pdal/util/FileUtils.hpp>
42
43 #include "Support.hpp"
44
45 namespace pdal
46 {
47
getWKT()48 std::string getWKT()
49 {
50 return FileUtils::readFileIntoString(
51 Support::datapath("autzen/autzen-selection.wkt"));
52 }
53
getJSON()54 std::string getJSON()
55 {
56 return FileUtils::readFileIntoString(
57 Support::datapath("autzen/autzen-selection.json"));
58 }
59
TEST(PolygonTest,test_wkt_in)60 TEST(PolygonTest, test_wkt_in)
61 {
62 std::string wkt(getWKT());
63
64 Polygon p(wkt);
65 }
66
TEST(PolygonTest,test_json_in)67 TEST(PolygonTest, test_json_in)
68 {
69 std::string json(getJSON());
70
71 Polygon p(json);
72 }
73
TEST(PolygonTest,test_wkt_out)74 TEST(PolygonTest, test_wkt_out)
75 {
76
77 Polygon p(getWKT());
78 std::string expected("POLYGON ((636889.412951239 851528.512293259 422.7001953125,636899.142334239 851475.000686757 422.4697265625,636899.142334239 851475.000686757 422.4697265625,636928.33048324 851494.459452758 422.5400390625,636928.33048324 851494.459452758 422.5400390625,636928.33048324 851494.459452758 422.5400390625,636976.977398242 851513.918218758 424.150390625,636976.977398242 851513.918218758 424.150390625,637069.406536744 851475.000686757 438.7099609375,637132.647526246 851445.812537756 425.9501953125,637132.647526246 851445.812537756 425.9501953125,637336.964569251 851411.759697255 425.8203125,637336.964569251 851411.759697255 425.8203125,637473.175931255 851158.795739249 435.6298828125,637589.928527258 850711.244121237 420.509765625,637244.535430749 850511.791769731 420.7998046875,636758.066280736 850667.461897735 434.609375,636539.15516323 851056.637217746 422.6396484375,636889.412951239 851528.512293259 422.7001953125))");
79
80 std::string w = p.wkt();
81 EXPECT_EQ(expected, w);
82
83 }
84
TEST(PolygonTest,simplify)85 TEST(PolygonTest, simplify)
86 {
87 std::string s =
88
89 R"( MULTIPOLYGON ( ( (0 0, 0 6, 6 6, 6 1, 6 .9, 6 .8, 6 .7, 6 .5, 6 0, 0 0), (.5 1, 1.5 1, 1 2, .5 1), (.5 3, 1.5 3, 1 4, .5 3), (2 1, 5 1, 5 4, 2 4, 2 1)), ( (3 2, 3 3, 4 3, 4 2, 3 2), (3.2 2.2, 3.7 2.2, 3.7 2.7, 3.2 2.7, 3.2 2.2))))";
90 //GDAL doesn't currently handle newlines in WKT
91 /**
92 R"( MULTIPOLYGON ( ( (0 0, 6 0, 6 .5, 6 .7, 6 .8, 6 .9, 6 1, 6 6, 0 6, 0 0), (.5 1, 1.5 1, 1 2, .5 1), (.5 3, 1.5 3, 1 4, .5 3), (2 1, 5 1, 5 4, 2 4, 2 1)), ( (3 2, 4 2, 4 3, 3 3, 3 2), (3.2 2.2, 3.7 2.2, 3.7 2.7, 3.2 2.7, 3.2 2.2))))";
93 MULTIPOLYGON (
94 (
95 (0 0, 6 0, 6 .5, 6 .7, 6 .8, 6 .9, 6 1, 6 6, 0 6, 0 0),
96 (0 0, 0 6, 6 6, 6 1, 6 .9, 6 .8, 6 .7, 6 .5, 6 0, 0 0),
97 (.5 1, 1.5 1, 1 2, .5 1),
98 (.5 3, 1.5 3, 1 4, .5 3),
99 (2 1, 5 1, 5 4, 2 4, 2 1)
100 ),
101 (
102 (3 2, 3 3, 4 3, 4 2, 3 2),
103 (3.2 2.2, 3.7 2.2, 3.7 2.7, 3.2 2.7, 3.2 2.2)
104 )
105 )
106 **/
107 Polygon p(s);
108
109 p.simplify(1, 1, true);
110 s = p.wkt();
111 Utils::remove(s, ' ');
112 EXPECT_EQ(s, "MULTIPOLYGON(((00,06,66,60,00),(21,51,54,24,21)))");
113 }
114
TEST(PolygonTest,test_json_out)115 TEST(PolygonTest, test_json_out)
116 {
117 Polygon p(getJSON());
118 std::string j = p.json(5);
119 std::string expected("{ \"type\": \"Polygon\", \"coordinates\": [ [ [ 636889.41295, 851528.51229, 422.7002 ], [ 636899.14233, 851475.00069, 422.46973 ], [ 636899.14233, 851475.00069, 422.46973 ], [ 636928.33048, 851494.45945, 422.54004 ], [ 636928.33048, 851494.45945, 422.54004 ], [ 636928.33048, 851494.45945, 422.54004 ], [ 636976.9774, 851513.91822, 424.15039 ], [ 636976.9774, 851513.91822, 424.15039 ], [ 637069.40654, 851475.00069, 438.70996 ], [ 637132.64753, 851445.81254, 425.9502 ], [ 637132.64753, 851445.81254, 425.9502 ], [ 637336.96457, 851411.7597, 425.82031 ], [ 637336.96457, 851411.7597, 425.82031 ], [ 637473.17593, 851158.79574, 435.62988 ], [ 637589.92853, 850711.24412, 420.50977 ], [ 637244.53543, 850511.79177, 420.7998 ], [ 636758.06628, 850667.4619, 434.60938 ], [ 636539.15516, 851056.63722, 422.63965 ], [ 636889.41295, 851528.51229, 422.7002 ] ] ] }");
120 EXPECT_EQ(j, expected);
121 }
122
TEST(PolygonTest,smooth)123 TEST(PolygonTest, smooth)
124 {
125 Polygon p(getJSON());
126 Polygon p2 = p;
127
128 p2.simplify(100000.0, 0.0);
129 EXPECT_FLOAT_EQ(static_cast<float>(p.area()), 703744.56f);
130 EXPECT_FLOAT_EQ(static_cast<float>(p2.area()), 492958.44f);
131 }
132
133
134
TEST(PolygonTest,covers)135 TEST(PolygonTest, covers)
136 {
137 using namespace pdal::Dimension;
138
139 pdal::Polygon p(getWKT());
140
141 PointTable table;
142 PointLayoutPtr layout(table.layout());
143 layout->registerDim(Dimension::Id::X);
144 layout->registerDim(Dimension::Id::Y);
145
146
147 // Check if the very first point in the polygon is
148 // covered by the polyg. Should be true
149 //
150 PointViewPtr view(new PointView(table));
151 view->setField(Id::X, 0, 636889.412951239268295 );
152 view->setField(Id::Y, 0, 851528.512293258565478);
153
154 PointRef ref(*view, 0);
155 bool covered = p.covers(ref);
156 EXPECT_EQ(covered, true);
157 }
158
TEST(PolygonTest,valid)159 TEST(PolygonTest, valid)
160 {
161 pdal::Polygon p(getWKT());
162 EXPECT_EQ(p.valid(), true);
163 }
164
TEST(PolygonTest,bounds)165 TEST(PolygonTest, bounds)
166 {
167 pdal::Polygon p(getWKT());
168 BOX3D b = p.bounds();
169 EXPECT_NEAR(b.minx, 636539.1, .1);
170 EXPECT_NEAR(b.miny, 850511.8, .1);
171 EXPECT_NEAR(b.minz, 420.50977, .00001);
172 EXPECT_NEAR(b.maxx, 637589.9, .1);
173 EXPECT_NEAR(b.maxy, 851528.5, .1);
174 EXPECT_NEAR(b.maxz, 438.70996, .00001);
175 }
176
TEST(PolygonTest,bounds2d)177 TEST(PolygonTest, bounds2d)
178 {
179 BOX2D box(636539.12, 850511.81, 637589.94, 851528.5);
180 pdal::Polygon p(box);
181
182 BOX3D b = p.bounds();
183 EXPECT_NEAR(b.minx, 636539.12, .01);
184 EXPECT_NEAR(b.miny, 850511.81, .01);
185 EXPECT_NEAR(b.minz, 0.0, .1);
186 EXPECT_NEAR(b.maxx, 637589.94, .01);
187 EXPECT_NEAR(b.maxy, 851528.5, .1);
188 EXPECT_NEAR(b.maxz, 0.0, .1);
189 }
190
TEST(PolygonTest,bounds3d)191 TEST(PolygonTest, bounds3d)
192 {
193 BOX3D box(636539.12, 850511.81, 420.50977, 637589.94, 851528.5, 438.70996);
194 pdal::Polygon p(box);
195
196 BOX3D b = p.bounds();
197 EXPECT_NEAR(b.minx, 636539.12, .01);
198 EXPECT_NEAR(b.miny, 850511.81, .01);
199 EXPECT_NEAR(b.minz, 420.5097, .0001);
200 EXPECT_NEAR(b.maxx, 637589.94, .01);
201 EXPECT_NEAR(b.maxy, 851528.5, .1);
202 EXPECT_NEAR(b.maxz, 438.70996, .00001);
203 }
204
205
TEST(PolygonTest,streams)206 TEST(PolygonTest, streams)
207 {
208 pdal::Polygon p(getWKT());
209
210 std::stringstream ss(std::stringstream::in | std::stringstream::out);
211
212 ss << p;
213
214 pdal::Polygon p2;
215 ss >> p2;
216
217 EXPECT_TRUE(p == p2);
218
219 }
220
221 } // namespace pdal
222