GeoTessCPP  2.2
Software to facilitate storage and retrieval of 3D information about the Earth.
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 
112 {
113 protected:
114 
118  vector<GeoTessGreatCircle*> edges;
119 
126  double* referencePoint;
127 
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 
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 
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 
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_ */
bool isNotReferenced()
Returns true if reference count is zero.
Definition: GeoTessPolygon.h:239
void addReference()
Add reference count;.
Definition: GeoTessPolygon.h:218
An ordered list of points on the surface of a unit sphere that define a closed polygon.
Definition: GeoTessPolygon.h:111
int size()
Returns the number of edges that define the polygon.
Definition: GeoTessPolygon.h:250
void setReferencePoint(double lat, double lon, bool inside)
Specify the reference point for this polygon and whether or not the specified point is inside or outs...
Definition: GeoTessPolygon.h:337
static double TOLERANCE
Tolerance value in radians used when comparing locations of two points.
Definition: GeoTessPolygon.h:136
const double * getPoint(int index)
Retrieve a reference to one point on the polygon boundary.
Definition: GeoTessPolygon.h:512
Definition: ArrayReuse.h:55
const double *const getReferencePoint()
Retrieve a reference to the referencePoint.
Definition: GeoTessPolygon.h:269
void setReferencePoint(const double *refPoint, const bool &inside)
Specify the reference point for this polygon and whether or not the specified point is inside or outs...
Definition: GeoTessPolygon.h:317
void * attachment
Some unspecified information that applications can attach to this polygon.
Definition: GeoTessPolygon.h:169
vector< GeoTessGreatCircle * > edges
A GreatCircle object for each edge of the polygon.
Definition: GeoTessPolygon.h:118
double * getFirst()
Retrieve a reference to the first unit vector on this GreatCircle.
Definition: GeoTessGreatCircle.h:482
int getRefCount()
Definition: GeoTessPolygon.h:241
double getAreaLarge()
Retrieve the area of this polygon.
Definition: GeoTessPolygon.h:576
const void getReferencePoint(double *u)
Retrieve a copy to the referencePoint.
Definition: GeoTessPolygon.h:280
static double getTolerance()
Retrieve the tolerance value in radians used when comparing locations of two points.
Definition: GeoTessPolygon.h:258
double * referencePoint
A point on the surface of the unit sphere that is used as a reference point.
Definition: GeoTessPolygon.h:126
Manages information about a great circle path that extends from one point to another point...
Definition: GeoTessGreatCircle.h:168
bool contains(const double *x)
return true if point x is located inside the polygon
Definition: GeoTessPolygon.h:380
bool onBoundary(const double *x)
Return true if evaluation point is very close to being on the boundary of the polygon.
Definition: GeoTessPolygon.h:423
void getPoints(vector< double * > &points, const bool &repeatFirstPoint)
Retrieve a deep copy of the points on the polygon.
Definition: GeoTessPolygon.h:443
bool referenceIn
true if the referencePoint is inside the polygon.
Definition: GeoTessPolygon.h:131
An exception class for all GeoTess objects.
Definition: GeoTessException.h:65
bool onBoundary(GeoTessGreatCircle &gcRef)
Return true if evaluation point is very close to being on the boundary of the polygon.
Definition: GeoTessPolygon.h:397
int refCount
Reference count.
Definition: GeoTessPolygon.h:159
double getArea()
Retrieve the area of this polygon.
Definition: GeoTessPolygon.h:529
bool containsAll(const vector< double * > &positions)
Returns true if this Polygon contains all of the supplied unit vectors.
Definition: GeoTessPolygon.h:366
bool containsAny(const vector< double * > &points)
Returns true if this Polygon contains any of the supplied unit vectors.
Definition: GeoTessPolygon.h:352
bool global
If global is true this polygon encompasses the entire Earth and method contains() will always return ...
Definition: GeoTessPolygon.h:142
const double * getNormal()
Retrieve a reference to the unit vector that is normal to the plane of this great circle (firstPoint ...
Definition: GeoTessGreatCircle.h:508
void invert()
Invert the current polygon.
Definition: GeoTessPolygon.h:300
bool getReferencePointIn()
Retrieve the value of referenceIn which indicates whether or not the referencePoint is inside or outs...
Definition: GeoTessPolygon.h:291
double getAreaSmall()
Retrieve the area of this polygon.
Definition: GeoTessPolygon.h:561
double * getLast()
Retrieve a reference to the last unit vector on this GreatCircle.
Definition: GeoTessGreatCircle.h:494
#define GEOTESS_EXP_IMP
Definition: CPPGlobals.h:71
bool lonFirst
When reading/writing lat,lon data, should order be lat,lon or lon,lat.
Definition: GeoTessPolygon.h:147
virtual string class_name()
Returns the class name.
Definition: GeoTessPolygon.h:213
void getPoints(vector< double * > &points, const bool &repeatFirstPoint, const double &maxSpacing)
Retrieve a deep copy of the points on the polygon.
Definition: GeoTessPolygon.h:481
void removeReference()
Remove reference count;.
Definition: GeoTessPolygon.h:223