GeoTessCPP  2.0.0
Software to facilitate storage and retrieval of 3D information about the Earth.
 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 
120 {
121 protected:
122 
126  vector<GreatCircle*> edges;
127 
134  double* referencePoint;
135 
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_ */