GeoTessCPP: include/Polygon.h Source File

GeoTessCPP 2.0.0 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
Polygon.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 "GreatCircle.h"
54 #include "IFStreamAscii.h"
55
56 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
57
58 namespace geotess {
59
60 // **** _FORWARD REFERENCES_ ***************************************************
61
62 // **** _CLASS DEFINITION_ *****************************************************
63
119 class GEOTESS_EXP_IMP Polygon
120 {
121 protected:
122
126 vector<GreatCircle*> edges;
127
134 double* referencePoint;
135
139 bool referenceIn;
140
144 static double TOLERANCE;
145
150 bool global;
151
155 bool lonFirst;
156
160 void setup(vector<double*>& points);
161
162 int edgeCrossings(GreatCircle& gcRef);
163
167 int refCount;
168
169 public:
170
171 virtual ~Polygon();
172
177 void* attachment;
178
179 Polygon();
180
194 Polygon(vector<double*>& points);
195
210 Polygon(const double* center, double radius, int nEdges);
211
220 Polygon(string filename);
221
225 virtual string class_name() { return "Polygon"; };
226
230 void addReference() { ++refCount; }
231
235 void removeReference()
236 {
237 if (isNotReferenced())
238 {
239 ostringstream os;
240 os << endl << "ERROR in Polygon::removeReference" << endl
241 << "Reference count (" << refCount << ") is already zero." << endl;
242 throw GeoTessException(os, __FILE__, __LINE__, 10001);
243 }
244
245 --refCount;
246 }
247
251 bool isNotReferenced() { return refCount == 0; }
252
260 int size()
261 {
262 return edges.size();
263 }
264
268 static double getTolerance()
269 {
270 return TOLERANCE;
271 }
272
279 const double* const getReferencePoint()
280 {
281 return referencePoint;
282 }
283
290 const void getReferencePoint(double *u)
291 {
292 u[0] = referencePoint[0];
293 u[1] = referencePoint[1];
294 u[2] = referencePoint[2];
295 }
296
301 bool getReferencePointIn()
302 {
303 return referenceIn;
304 }
305
310 void invert()
311 {
312 referenceIn = !referenceIn;
313 }
314
327 void setReferencePoint(const double* refPoint, const bool &inside)
328 {
329 if (referencePoint == NULL)
330 referencePoint = new double[3];
331
332 referencePoint[0] = refPoint[0];
333 referencePoint[1] = refPoint[1];
334 referencePoint[2] = refPoint[2];
335 referenceIn = inside;
336 }
337
347 void setReferencePoint(double lat, double lon, bool inside)
348 {
349 double r[3];
350 GeoTessUtils::getVectorDegrees(lat, lon, r);
351 setReferencePoint(r, inside);
352 }
353
362 bool containsAny(const vector<double*>& points)
363 {
364 for (int i=0; i<(int)points.size(); ++i)
365 if (contains(points[i]))
366 return true;
367 return false;
368 }
369
376 bool containsAll(const vector<double*>& positions)
377 {
378 for (int i=0; i<(int)positions.size(); ++i)
379 if (!contains(positions[i]))
380 return false;
381 return true;
382 }
383
390 bool contains(const double* x)
391 {
392 if (global || GeoTessUtils::dot(referencePoint, x) > cos(TOLERANCE))
393 return referenceIn;
394
395 GreatCircle gcRef(referencePoint, x);
396
397 return onBoundary(gcRef) || ((edgeCrossings(gcRef) % 2 == 0) == referenceIn);
398 }
399
407 bool onBoundary(GreatCircle& gcRef)
408 {
409 // point being evaluated is gcRef.getLast()
410 for (int i=0; i<(int)edges.size(); ++i)
411 {
412 // if point is very close to a polygon point, return true
413 if (GeoTessUtils::dot(gcRef.getLast(), edges[i]->getFirst()) >= cos(TOLERANCE))
414 return true;
415
416 // if gcRef and edge are coincident, i.e., their normals are parallel or
417 // anti-parallel, and the point being evaluated is between first and last
418 // point of the edge, then return true;
419 if (abs(GeoTessUtils::dot(gcRef.getNormal(), edges[i]->getNormal())) >= cos(TOLERANCE)
420 && edges[i]->getDistance(gcRef.getLast()) <= edges[i]->getDistance())
421 return true;
422 }
423 return false;
424 }
425
433 bool onBoundary(const double* x)
434 {
435 GreatCircle gc(referencePoint, x);
436 return onBoundary(gc);
437 }
438
453 void getPoints(vector<double*> &points, const bool &repeatFirstPoint)
454 {
455 points.reserve(points.size()+edges.size()+1);
456
457 for (int i = 0; i < (int)edges.size(); ++i)
458 {
459 double* point = new double[3];
460 point[0] = edges[i]->getFirst()[0];
461 point[1] = edges[i]->getFirst()[1];
462 point[2] = edges[i]->getFirst()[2];
463 points.push_back(point);
464 }
465
466 if (repeatFirstPoint)
467 {
468 double* point = new double[3];
469 point[0] = edges[0]->getFirst()[0];
470 point[1] = edges[0]->getFirst()[1];
471 point[2] = edges[0]->getFirst()[2];
472 points.push_back(point);
473 }
474 }
475
491 void getPoints(vector<double*> &points, const bool &repeatFirstPoint, const double &maxSpacing)
492 {
493 points.reserve(points.size()+edges.size()+1);
494
495 int n;
496 double dx;
497 for (int i = 0; i < (int)edges.size(); ++i)
498 {
499 n = (int)ceil(edges[i]->getDistance()/maxSpacing);
500 dx = edges[i]->getDistance()/n;
501 for (int j=0; j<n; ++j)
502 points.push_back(edges[i]->getPoint(j*dx));
503 }
504
505 if (repeatFirstPoint)
506 {
507 double* point = new double[3];
508 point[0] = edges[0]->getFirst()[0];
509 point[1] = edges[0]->getFirst()[1];
510 point[2] = edges[0]->getFirst()[2];
511 points.push_back(point);
512 }
513 }
514
522 const double* getPoint(int index)
523 {
524 return edges[index]->getFirst();
525 }
526
539 double getArea()
540 {
541 double a, area = 0;
542 GreatCircle* edge;
543 GreatCircle* previous = edges[edges.size()-1];
544
545 for (int i=0; i<(int)edges.size(); ++i)
546 {
547 edge = edges[i];
548 a = PI - GeoTessUtils::angle(previous->getNormal(), edge->getNormal());
549
550 if (GeoTessUtils::scalarTripleProduct(previous->getNormal(), edge->getNormal(),
551 edge->getFirst()) < 0)
552 area += a;
553 else
554 area += 2*PI - a;
555
556 previous = edge;
557 }
558 area -= (edges.size()-2)*PI;
559 return area;
560 }
561
571 double getAreaSmall()
572 {
573 double area = getArea();
574 return area <= 2*PI ? area : 4*PI-area;
575 }
576
586 double getAreaLarge()
587 {
588 double area = getArea();
589 return area >= 2*PI ? area : 4*PI-area;
590 }
591
610 string str(const bool& repeatFirstPoint, const bool& latFirst,
611 const double& minLongitude = -180);
612
613 virtual void write(const string& outputFileName);
614
616
617 virtual void loadAscii(IFStreamAscii& input);
618
620
621 }; // end class Polygon
622
623 } // end namespace geotess
624
625 #endif /* POLYGON_H_ */