GeoTessCPP  2.6.1
Software to facilitate storage and retrieval of 3D information about the Earth.
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 
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 
155 
159  int refCount;
160 
161  public:
162 
163  virtual ~GeoTessPolygon();
164 
169  void* attachment;
170 
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_ */
#define GEOTESS_EXP_IMP
Definition: CPPGlobals.h:71
An exception class for all GeoTess objects.
Manages information about a great circle path that extends from one point to another point,...
An ordered list of points on the surface of a unit sphere that define a closed polygon.
const double * getPoint(int index)
void setReferencePoint(const double *refPoint, const bool &inside)
const void getReferencePoint(double *u)
void getPoints(vector< double * > &points, const bool &repeatFirstPoint)
vector< GeoTessGreatCircle * > edges
static double getTolerance()
GeoTessPolygon(vector< double * > &points)
GeoTessPolygon(const double *center, double radius, int nEdges)
const double *const getReferencePoint()
void getPoints(vector< double * > &points, const bool &repeatFirstPoint, const double &maxSpacing)
virtual string class_name()
void setReferencePoint(double lat, double lon, bool inside)
string str(const bool &repeatFirstPoint, const bool &latFirst, const double &minLongitude=-180)
bool contains(const double *x)
bool containsAll(const vector< double * > &positions)
int edgeCrossings(GeoTessGreatCircle &gcRef)
GeoTessPolygon(string filename)
bool onBoundary(const double *x)
bool containsAny(const vector< double * > &points)
void setup(vector< double * > &points)
virtual void write(const string &outputFileName)
bool onBoundary(GeoTessGreatCircle &gcRef)