GeoTessCPP: include/GeoTessPolygon.h Source File

GeoTessCPP 2.1 Software to facilitate storage and retrieval of 3D information about the Earth.

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Friends Macros
GeoTessPolygon.h
Go to the documentation of this file.
1 //- ****************************************************************************
2 //-
3 //- Copyright 2009 Sandia Corporation. Under the terms of Contract
4 //- DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
5 //- retains certain rights in this software.
6 //-
7 //- BSD Open Source License.
8 //- All rights reserved.
9 //-
10 //- Redistribution and use in source and binary forms, with or without
11 //- modification, are permitted provided that the following conditions are met:
12 //-
13 //- * Redistributions of source code must retain the above copyright notice,
14 //- this list of conditions and the following disclaimer.
15 //- * Redistributions in binary form must reproduce the above copyright
16 //- notice, this list of conditions and the following disclaimer in the
17 //- documentation and/or other materials provided with the distribution.
18 //- * Neither the name of Sandia National Laboratories nor the names of its
19 //- contributors may be used to endorse or promote products derived from
20 //- this software without specific prior written permission.
21 //-
22 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //- POSSIBILITY OF SUCH DAMAGE.
33 //-
34 //- ****************************************************************************
35
36 #ifndef POLYGON_H_
37 #define POLYGON_H_
38
39 // **** _SYSTEM INCLUDES_ ******************************************************
40
41 #include <cstdio>
42 #include <iostream>
43 #include <iomanip>
44 #include <vector>
45
46 // use standard library objects
47 using namespace std;
48
49 // **** _LOCAL INCLUDES_ *******************************************************
50
51 #include "CPPUtils.h"
52 #include "GeoTessUtils.h"
53 #include "GeoTessGreatCircle.h"
54 #include "IFStreamAscii.h"
55
56 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
57
58 namespace geotess {
59
60 // **** _FORWARD REFERENCES_ ***************************************************
61
62 // **** _CLASS DEFINITION_ *****************************************************
63
111 class GEOTESS_EXP_IMP GeoTessPolygon
112 {
113 protected:
114
118 vector<GeoTessGreatCircle*> edges;
119
126 double* referencePoint;
127
131 bool referenceIn;
132
136 static double TOLERANCE;
137
142 bool global;
143
147 bool lonFirst;
148
152 void setup(vector<double*>& points);
153
154 int edgeCrossings(GeoTessGreatCircle& gcRef);
155
159 int refCount;
160
161 public:
162
163 virtual ~GeoTessPolygon();
164
169 void* attachment;
170
171 GeoTessPolygon();
172
185 GeoTessPolygon(vector<double*>& points);
186
198 GeoTessPolygon(const double* center, double radius, int nEdges);
199
208 GeoTessPolygon(string filename);
209
213 virtual string class_name() { return "Polygon"; };
214
218 void addReference() { ++refCount; }
219
223 void removeReference()
224 {
225 if (isNotReferenced())
226 {
227 ostringstream os;
228 os << endl << "ERROR in Polygon::removeReference" << endl
229 << "Reference count (" << refCount << ") is already zero." << endl;
230 throw GeoTessException(os, __FILE__, __LINE__, 10001);
231 }
232
233 --refCount;
234 }
235
239 bool isNotReferenced() { return refCount == 0; }
240
241 int getRefCount() { return refCount; }
242
250 int size()
251 {
252 return edges.size();
253 }
254
258 static double getTolerance()
259 {
260 return TOLERANCE;
261 }
262
269 const double* const getReferencePoint()
270 {
271 return referencePoint;
272 }
273
280 const void getReferencePoint(double *u)
281 {
282 u[0] = referencePoint[0];
283 u[1] = referencePoint[1];
284 u[2] = referencePoint[2];
285 }
286
291 bool getReferencePointIn()
292 {
293 return referenceIn;
294 }
295
300 void invert()
301 {
302 referenceIn = !referenceIn;
303 }
304
317 void setReferencePoint(const double* refPoint, const bool &inside)
318 {
319 if (referencePoint == NULL)
320 referencePoint = new double[3];
321
322 referencePoint[0] = refPoint[0];
323 referencePoint[1] = refPoint[1];
324 referencePoint[2] = refPoint[2];
325 referenceIn = inside;
326 }
327
337 void setReferencePoint(double lat, double lon, bool inside)
338 {
339 double r[3];
340 GeoTessUtils::getVectorDegrees(lat, lon, r);
341 setReferencePoint(r, inside);
342 }
343
352 bool containsAny(const vector<double*>& points)
353 {
354 for (int i=0; i<(int)points.size(); ++i)
355 if (contains(points[i]))
356 return true;
357 return false;
358 }
359
366 bool containsAll(const vector<double*>& positions)
367 {
368 for (int i=0; i<(int)positions.size(); ++i)
369 if (!contains(positions[i]))
370 return false;
371 return true;
372 }
373
380 bool contains(const double* x)
381 {
382 if (global || GeoTessUtils::dot(referencePoint, x) > cos(TOLERANCE))
383 return referenceIn;
384
385 GeoTessGreatCircle gcRef(referencePoint, x);
386
387 return onBoundary(gcRef) || ((edgeCrossings(gcRef) % 2 == 0) == referenceIn);
388 }
389
397 bool onBoundary(GeoTessGreatCircle& gcRef)
398 {
399 // point being evaluated is gcRef.getLast()
400 for (int i=0; i<(int)edges.size(); ++i)
401 {
402 // if point is very close to a polygon point, return true
403 if (GeoTessUtils::dot(gcRef.getLast(), edges[i]->getFirst()) >= cos(TOLERANCE))
404 return true;
405
406 // if gcRef and edge are coincident, i.e., their normals are parallel or
407 // anti-parallel, and the point being evaluated is between first and last
408 // point of the edge, then return true;
409 if (abs(GeoTessUtils::dot(gcRef.getNormal(), edges[i]->getNormal())) >= cos(TOLERANCE)
410 && edges[i]->getDistance(gcRef.getLast()) <= edges[i]->getDistance())
411 return true;
412 }
413 return false;
414 }
415
423 bool onBoundary(const double* x)
424 {
425 GeoTessGreatCircle gc(referencePoint, x);
426 return onBoundary(gc);
427 }
428
443 void getPoints(vector<double*> &points, const bool &repeatFirstPoint)
444 {
445 points.reserve(points.size()+edges.size()+1);
446
447 for (int i = 0; i < (int)edges.size(); ++i)
448 {
449 double* point = new double[3];
450 point[0] = edges[i]->getFirst()[0];
451 point[1] = edges[i]->getFirst()[1];
452 point[2] = edges[i]->getFirst()[2];
453 points.push_back(point);
454 }
455
456 if (repeatFirstPoint)
457 {
458 double* point = new double[3];
459 point[0] = edges[0]->getFirst()[0];
460 point[1] = edges[0]->getFirst()[1];
461 point[2] = edges[0]->getFirst()[2];
462 points.push_back(point);
463 }
464 }
465
481 void getPoints(vector<double*> &points, const bool &repeatFirstPoint, const double &maxSpacing)
482 {
483 points.reserve(points.size()+edges.size()+1);
484
485 int n;
486 double dx;
487 for (int i = 0; i < (int)edges.size(); ++i)
488 {
489 n = (int)ceil(edges[i]->getDistance()/maxSpacing);
490 dx = edges[i]->getDistance()/n;
491 for (int j=0; j<n; ++j)
492 points.push_back(edges[i]->getPoint(j*dx));
493 }
494
495 if (repeatFirstPoint)
496 {
497 double* point = new double[3];
498 point[0] = edges[0]->getFirst()[0];
499 point[1] = edges[0]->getFirst()[1];
500 point[2] = edges[0]->getFirst()[2];
501 points.push_back(point);
502 }
503 }
504
512 const double* getPoint(int index)
513 {
514 return edges[index]->getFirst();
515 }
516
529 double getArea()
530 {
531 double a, area = 0;
532 GeoTessGreatCircle* edge;
533 GeoTessGreatCircle* previous = edges[edges.size()-1];
534
535 for (int i=0; i<(int)edges.size(); ++i)
536 {
537 edge = edges[i];
538 a = PI - GeoTessUtils::angle(previous->getNormal(), edge->getNormal());
539
540 if (GeoTessUtils::scalarTripleProduct(previous->getNormal(), edge->getNormal(),
541 edge->getFirst()) < 0)
542 area += a;
543 else
544 area += 2*PI - a;
545
546 previous = edge;
547 }
548 area -= (edges.size()-2)*PI;
549 return area;
550 }
551
561 double getAreaSmall()
562 {
563 double area = getArea();
564 return area <= 2*PI ? area : 4*PI-area;
565 }
566
576 double getAreaLarge()
577 {
578 double area = getArea();
579 return area >= 2*PI ? area : 4*PI-area;
580 }
581
600 string str(const bool& repeatFirstPoint, const bool& latFirst,
601 const double& minLongitude = -180);
602
603 virtual void write(const string& outputFileName);
604
606
607 virtual void loadAscii(vector<string>& records);
608
610
611 }; // end class Polygon
612
613 } // end namespace geotess
614
615 #endif /* POLYGON_H_ */