1 //*****************************************************************************
2 // FILE: ossimPolygon.h
3 //
4 // License: See top level LICENSE.txt file.
5 //
6 // AUTHOR: Garrett Potts
7 //
8 //*****************************************************************************
9 // $Id: ossimGeoPolygon.cpp 23170 2015-02-25 20:59:10Z dburken $
10
11 #include <ostream>
12 #include <sstream>
13 #include <algorithm>
14 #include <ossim/base/ossimGeoPolygon.h>
15 #include <ossim/base/ossimDatumFactoryRegistry.h>
16 #include <ossim/base/ossimDatum.h>
17 #include <ossim/base/ossimKeywordlist.h>
18 #include <ossim/base/ossimKeywordNames.h>
19
20 static const char* NUMBER_VERTICES_KW = "number_vertices";
21
operator <<(std::ostream & out,const ossimGeoPolygon & poly)22 std::ostream& operator <<(std::ostream& out, const ossimGeoPolygon& poly)
23 {
24 if(poly.size())
25 {
26 if(poly.size() >1)
27 {
28 for(ossim_uint32 i = 0; i < poly.size()-1; ++i)
29 {
30 out << "P" << i << ": " << poly[i] << std::endl;
31 }
32 out << "P" << (poly.size()-1)
33 << ": " << poly[poly.size()-1] << std::endl;
34 }
35 else
36 {
37 out << "P0: " << poly[0] << std::endl;
38 }
39 }
40
41 return out;
42 }
43
ossimGeoPolygon()44 ossimGeoPolygon::ossimGeoPolygon()
45 :
46 theVertexList(),
47 theAttributeList(),
48 theHoleList(),
49 theCurrentVertex(-1),
50 theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN)
51 {
52 }
53
ossimGeoPolygon(const std::vector<ossimGpt> & points)54 ossimGeoPolygon::ossimGeoPolygon(const std::vector<ossimGpt>& points)
55 :
56 theVertexList(points),
57 theAttributeList(),
58 theHoleList(),
59 theCurrentVertex(0),
60 theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN)
61 {
62 }
63
ossimGeoPolygon(const ossimGeoPolygon & rhs)64 ossimGeoPolygon::ossimGeoPolygon(const ossimGeoPolygon& rhs)
65 :
66 theVertexList(rhs.theVertexList),
67 theAttributeList(rhs.theAttributeList),
68 theHoleList(rhs.theHoleList),
69 theCurrentVertex(rhs.theCurrentVertex),
70 theOrderingType(rhs.theOrderingType)
71 {
72 }
73
operator =(const ossimGeoPolygon & rhs)74 const ossimGeoPolygon& ossimGeoPolygon::operator=(const ossimGeoPolygon& rhs)
75 {
76 if ( this != &rhs )
77 {
78 theVertexList = rhs.theVertexList;
79 theAttributeList = rhs.theAttributeList;
80 theHoleList = rhs.theHoleList;
81 theCurrentVertex = rhs.theCurrentVertex;
82 theOrderingType = rhs.theOrderingType;
83 }
84 return *this;
85 }
86
addWmsBbox(const ossimString & wmsBbox)87 bool ossimGeoPolygon::addWmsBbox(const ossimString& wmsBbox)
88 {
89 std::vector<ossimString> splitArray = wmsBbox.split(",");
90 bool result = true;
91 if(splitArray.size()>=4)
92 {
93 double minx = splitArray[0].trim().toDouble();
94 double miny = splitArray[1].trim().toDouble();
95 double maxx = splitArray[2].trim().toDouble();
96 double maxy = splitArray[3].trim().toDouble();
97
98 addPoint(miny, minx);//lower left
99 addPoint(maxy, minx);//upper left
100 addPoint(maxy, maxx);//upper right
101 addPoint(miny, maxx);//lower right
102 }
103 else
104 {
105 // error
106 result = false;
107 }
108
109 return result;
110 }
111
hasNans() const112 bool ossimGeoPolygon::hasNans()const
113 {
114 int upper = (int)theVertexList.size();
115 int i = 0;
116
117 for(i = 0; i < upper; ++i)
118 {
119 if(theVertexList[i].hasNans())
120 {
121 return true;
122 }
123 }
124
125 return false;
126 }
127
vertex(int index,ossimGpt & v) const128 bool ossimGeoPolygon::vertex(int index, ossimGpt& v) const
129 {
130 if((index >= (int)theVertexList.size()) ||
131 (index < 0))
132 {
133 return false;
134 }
135
136 v = theVertexList[index];
137 theCurrentVertex = index;
138
139 return true;
140 }
141
nextVertex(ossimDpt & v) const142 bool ossimGeoPolygon::nextVertex(ossimDpt& v) const
143 {
144 ++theCurrentVertex;
145 if(theCurrentVertex >= (ossim_int32)theVertexList.size())
146 {
147 return false;
148 }
149 v = theVertexList[theCurrentVertex];
150
151 return true;
152 }
153
stretchOut(ossimGeoPolygon & newPolygon,double displacement)154 void ossimGeoPolygon::stretchOut(ossimGeoPolygon& newPolygon,
155 double displacement)
156 {
157 newPolygon.resize(size());
158 if(size() >= 3)
159 {
160 const ossimDatum* datum = theVertexList[0].datum();
161 checkOrdering();
162 double signMult = 1.0;
163 if(theOrderingType == OSSIM_COUNTERCLOCKWISE_ORDER)
164 {
165 signMult = -1.0;
166 }
167
168 ossimDpt prev, current, next;
169
170 ossim_uint32 prevI;
171 ossim_uint32 currentI;
172 ossim_uint32 nextI;
173 ossim_uint32 i = 0;
174 ossim_uint32 upper = size();
175
176 bool equalEndsFlag = false;
177 if(theVertexList[0] == theVertexList[theVertexList.size()-1])
178 {
179 equalEndsFlag = true;
180 prevI = 0;
181 currentI = 1;
182 nextI = 2;
183 i = 1;
184 --upper;
185 }
186 else
187 {
188 equalEndsFlag = false;
189 prevI = size()-1;
190 currentI = 0;
191 nextI = 1;
192 }
193 for(; i < upper;++i)
194 {
195 prev = theVertexList[prevI];
196 current = theVertexList[currentI];
197 next = theVertexList[nextI];
198
199 ossimDpt averageNormal;
200
201 ossimDpt diffPrev = current - prev;
202 ossimDpt diffNext = next - current;
203
204 diffPrev = diffPrev*(1.0/diffPrev.length());
205 diffNext = diffNext*(1.0/diffNext.length());
206
207 ossimDpt diffPrevNormal(-diffPrev.y,
208 diffPrev.x);
209 ossimDpt diffNextNormal(-diffNext.y,
210 diffNext.x);
211
212 averageNormal = (diffPrevNormal + diffNextNormal);
213 averageNormal = averageNormal*(signMult*(1.0/averageNormal.length()));
214 ossimDpt newPoint = ossimDpt( theVertexList[i].lond(),
215 theVertexList[i].latd()) +
216 averageNormal*displacement;
217 newPolygon[i].latd(newPoint.lat);
218 newPolygon[i].lond(newPoint.lon);
219 newPolygon[i].height(theVertexList[i].height());
220 newPolygon[i].datum(datum);
221
222 ++prevI;
223 ++currentI;
224 ++nextI;
225
226 prevI%=size();
227 nextI%=size();
228 }
229 if(equalEndsFlag)
230 {
231
232 prev = theVertexList[theVertexList.size()-2];
233 current = theVertexList[0];
234 next = theVertexList[1];
235
236 ossimDpt averageNormal;
237
238 ossimDpt diffPrev = current - prev;
239 ossimDpt diffNext = next - current;
240
241 diffPrev = diffPrev*(1.0/diffPrev.length());
242 diffNext = diffNext*(1.0/diffNext.length());
243
244 ossimDpt diffPrevNormal(-diffPrev.y,
245 diffPrev.x);
246 ossimDpt diffNextNormal(-diffNext.y,
247 diffNext.x);
248
249 averageNormal = (diffPrevNormal + diffNextNormal);
250 averageNormal = averageNormal*(signMult*(1.0/averageNormal.length()));
251 ossimDpt newPoint = ossimDpt( theVertexList[i].lond(),
252 theVertexList[i].latd()) +
253 averageNormal*displacement;
254 newPolygon[0].latd(newPoint.lat);
255 newPolygon[0].lond(newPoint.lon);
256 newPolygon[0].height(theVertexList[i].height());
257 newPolygon[0].datum(datum);
258
259 newPolygon[(int)theVertexList.size()-1] = newPolygon[0];
260 }
261 }
262 }
263
264
area() const265 double ossimGeoPolygon::area()const
266 {
267 double area = 0;
268 ossim_uint32 i=0;
269 ossim_uint32 j=0;
270 ossim_uint32 size = (ossim_uint32)theVertexList.size();
271
272 for (i=0;i<size;i++)
273 {
274 j = (i + 1) % size;
275 area += theVertexList[i].lon * theVertexList[j].lat;
276 area -= theVertexList[i].lat * theVertexList[j].lon;
277 }
278
279 area /= 2;
280
281 return area;
282 }
283
reverseOrder()284 void ossimGeoPolygon::reverseOrder()
285 {
286 std::reverse(theVertexList.begin(), theVertexList.end());
287
288 if(theOrderingType == OSSIM_COUNTERCLOCKWISE_ORDER)
289 {
290 theOrderingType = OSSIM_CLOCKWISE_ORDER;
291 }
292 else if(theOrderingType == OSSIM_CLOCKWISE_ORDER)
293 {
294 theOrderingType = OSSIM_COUNTERCLOCKWISE_ORDER;
295 }
296
297 }
298
checkOrdering() const299 void ossimGeoPolygon::checkOrdering()const
300 {
301 if(theOrderingType == OSSIM_VERTEX_ORDER_UNKNOWN)
302 {
303 double areaValue = area();
304 if(areaValue > 0)
305 {
306 theOrderingType = OSSIM_COUNTERCLOCKWISE_ORDER;
307 }
308 else if(areaValue <= 0)
309 {
310 theOrderingType = OSSIM_CLOCKWISE_ORDER;
311 }
312 }
313 }
314
computeCentroid() const315 ossimGpt ossimGeoPolygon::computeCentroid()const
316 {
317 if(!size())
318 {
319 return ossimGpt();
320 }
321 ossimDpt average(0.0,0.0);
322 double height=0.0;
323 for(ossim_uint32 i = 0; i < size(); ++i)
324 {
325 average += ossimDpt(theVertexList[i]);
326 height += theVertexList[i].height();
327 }
328
329
330 average.x /= size();
331 average.y /= size();
332 height /= size();
333
334 return ossimGpt(average.y, average.x, height, theVertexList[0].datum());
335 }
336
saveState(ossimKeywordlist & kwl,const char * prefix) const337 bool ossimGeoPolygon::saveState(ossimKeywordlist& kwl,
338 const char* prefix)const
339 {
340 int i = 0;
341
342 kwl.add(prefix,
343 ossimKeywordNames::TYPE_KW,
344 "ossimGeoPolygon",
345 true);
346 kwl.add(prefix,
347 NUMBER_VERTICES_KW,
348 static_cast<ossim_uint32>(theVertexList.size()),
349 true);
350 if(theVertexList.size())
351 {
352 kwl.add(prefix,
353 ossimKeywordNames::DATUM_KW,
354 theVertexList[0].datum()->code(),
355 true);
356 }
357 else
358 {
359 kwl.add(prefix,
360 ossimKeywordNames::DATUM_KW,
361 "WGE",
362 true);
363 }
364
365 for(i = 0; i < (int)theVertexList.size();++i)
366 {
367 ossimString vert = "v"+ossimString::toString(i);
368 ossimString value = (ossimString::toString(theVertexList[i].latd()) + " " +
369 ossimString::toString(theVertexList[i].lond()) + " " +
370 ( theVertexList[i].isHgtNan()?ossimString("nan"):ossimString::toString(theVertexList[i].height())));
371 kwl.add(prefix,
372 vert.c_str(),
373 value.c_str(),
374 true);
375 }
376
377 return true;
378 }
379
loadState(const ossimKeywordlist & kwl,const char * prefix)380 bool ossimGeoPolygon::loadState(const ossimKeywordlist& kwl,
381 const char* prefix)
382 {
383 const char* number_vertices = kwl.find(prefix, NUMBER_VERTICES_KW);
384 ossimString datumStr = kwl.find(prefix, ossimKeywordNames::DATUM_KW);
385 const ossimDatum* datum = ossimDatumFactoryRegistry::instance()->create(datumStr);
386
387 theVertexList.clear();
388 int i = 0;
389 int vertexCount = ossimString(number_vertices).toLong();
390 ossimString lat, lon, height;
391 for(i = 0; i < vertexCount; ++i)
392 {
393 ossimString v = kwl.find(prefix, (ossimString("v")+ossimString::toString(i)).c_str());
394 ossimString latString, lonString, heightString;
395 v = v.trim();
396 std::istringstream in(v);
397 in>>lat>>lon>>height;
398 theVertexList.push_back(ossimGpt(lat.toDouble(), lon.toDouble(), height.toDouble(), datum));
399 }
400
401 return true;
402 }
403