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