GeoTessCPP
2.0.0
Software to facilitate storage and retrieval of 3D information about the Earth.
|
00001 //- **************************************************************************** 00002 //- 00003 //- Copyright 2009 Sandia Corporation. Under the terms of Contract 00004 //- DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00005 //- retains certain rights in this software. 00006 //- 00007 //- BSD Open Source License. 00008 //- All rights reserved. 00009 //- 00010 //- Redistribution and use in source and binary forms, with or without 00011 //- modification, are permitted provided that the following conditions are met: 00012 //- 00013 //- * Redistributions of source code must retain the above copyright notice, 00014 //- this list of conditions and the following disclaimer. 00015 //- * Redistributions in binary form must reproduce the above copyright 00016 //- notice, this list of conditions and the following disclaimer in the 00017 //- documentation and/or other materials provided with the distribution. 00018 //- * Neither the name of Sandia National Laboratories nor the names of its 00019 //- contributors may be used to endorse or promote products derived from 00020 //- this software without specific prior written permission. 00021 //- 00022 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00026 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00027 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00028 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00029 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00030 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00031 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 //- POSSIBILITY OF SUCH DAMAGE. 00033 //- 00034 //- **************************************************************************** 00035 00036 #ifndef POLYGON_H_ 00037 #define POLYGON_H_ 00038 00039 // **** _SYSTEM INCLUDES_ ****************************************************** 00040 00041 #include <cstdio> 00042 #include <iostream> 00043 #include <iomanip> 00044 #include <vector> 00045 00046 // use standard library objects 00047 using namespace std; 00048 00049 // **** _LOCAL INCLUDES_ ******************************************************* 00050 00051 #include "CPPUtils.h" 00052 #include "GeoTessUtils.h" 00053 #include "GeoTessGreatCircle.h" 00054 #include "IFStreamAscii.h" 00055 00056 // **** _BEGIN GEOTESS NAMESPACE_ ********************************************** 00057 00058 namespace geotess { 00059 00060 // **** _FORWARD REFERENCES_ *************************************************** 00061 00062 // **** _CLASS DEFINITION_ ***************************************************** 00063 00111 class GEOTESS_EXP_IMP GeoTessPolygon 00112 { 00113 protected: 00114 00118 vector<GeoTessGreatCircle*> edges; 00119 00126 double* referencePoint; 00127 00131 bool referenceIn; 00132 00136 static double TOLERANCE; 00137 00142 bool global; 00143 00147 bool lonFirst; 00148 00152 void setup(vector<double*>& points); 00153 00154 int edgeCrossings(GeoTessGreatCircle& gcRef); 00155 00159 int refCount; 00160 00161 public: 00162 00163 virtual ~GeoTessPolygon(); 00164 00169 void* attachment; 00170 00171 GeoTessPolygon(); 00172 00186 GeoTessPolygon(vector<double*>& points); 00187 00202 GeoTessPolygon(const double* center, double radius, int nEdges); 00203 00212 GeoTessPolygon(string filename); 00213 00217 virtual string class_name() { return "Polygon"; }; 00218 00222 void addReference() { ++refCount; } 00223 00227 void removeReference() 00228 { 00229 if (isNotReferenced()) 00230 { 00231 ostringstream os; 00232 os << endl << "ERROR in Polygon::removeReference" << endl 00233 << "Reference count (" << refCount << ") is already zero." << endl; 00234 throw GeoTessException(os, __FILE__, __LINE__, 10001); 00235 } 00236 00237 --refCount; 00238 } 00239 00243 bool isNotReferenced() { return refCount == 0; } 00244 00245 int getRefCount() { return refCount; } 00246 00254 int size() 00255 { 00256 return edges.size(); 00257 } 00258 00262 static double getTolerance() 00263 { 00264 return TOLERANCE; 00265 } 00266 00273 const double* const getReferencePoint() 00274 { 00275 return referencePoint; 00276 } 00277 00284 const void getReferencePoint(double *u) 00285 { 00286 u[0] = referencePoint[0]; 00287 u[1] = referencePoint[1]; 00288 u[2] = referencePoint[2]; 00289 } 00290 00295 bool getReferencePointIn() 00296 { 00297 return referenceIn; 00298 } 00299 00304 void invert() 00305 { 00306 referenceIn = !referenceIn; 00307 } 00308 00321 void setReferencePoint(const double* refPoint, const bool &inside) 00322 { 00323 if (referencePoint == NULL) 00324 referencePoint = new double[3]; 00325 00326 referencePoint[0] = refPoint[0]; 00327 referencePoint[1] = refPoint[1]; 00328 referencePoint[2] = refPoint[2]; 00329 referenceIn = inside; 00330 } 00331 00341 void setReferencePoint(double lat, double lon, bool inside) 00342 { 00343 double r[3]; 00344 GeoTessUtils::getVectorDegrees(lat, lon, r); 00345 setReferencePoint(r, inside); 00346 } 00347 00356 bool containsAny(const vector<double*>& points) 00357 { 00358 for (int i=0; i<(int)points.size(); ++i) 00359 if (contains(points[i])) 00360 return true; 00361 return false; 00362 } 00363 00370 bool containsAll(const vector<double*>& positions) 00371 { 00372 for (int i=0; i<(int)positions.size(); ++i) 00373 if (!contains(positions[i])) 00374 return false; 00375 return true; 00376 } 00377 00384 bool contains(const double* x) 00385 { 00386 if (global || GeoTessUtils::dot(referencePoint, x) > cos(TOLERANCE)) 00387 return referenceIn; 00388 00389 GeoTessGreatCircle gcRef(referencePoint, x); 00390 00391 return onBoundary(gcRef) || ((edgeCrossings(gcRef) % 2 == 0) == referenceIn); 00392 } 00393 00401 bool onBoundary(GeoTessGreatCircle& gcRef) 00402 { 00403 // point being evaluated is gcRef.getLast() 00404 for (int i=0; i<(int)edges.size(); ++i) 00405 { 00406 // if point is very close to a polygon point, return true 00407 if (GeoTessUtils::dot(gcRef.getLast(), edges[i]->getFirst()) >= cos(TOLERANCE)) 00408 return true; 00409 00410 // if gcRef and edge are coincident, i.e., their normals are parallel or 00411 // anti-parallel, and the point being evaluated is between first and last 00412 // point of the edge, then return true; 00413 if (abs(GeoTessUtils::dot(gcRef.getNormal(), edges[i]->getNormal())) >= cos(TOLERANCE) 00414 && edges[i]->getDistance(gcRef.getLast()) <= edges[i]->getDistance()) 00415 return true; 00416 } 00417 return false; 00418 } 00419 00427 bool onBoundary(const double* x) 00428 { 00429 GeoTessGreatCircle gc(referencePoint, x); 00430 return onBoundary(gc); 00431 } 00432 00447 void getPoints(vector<double*> &points, const bool &repeatFirstPoint) 00448 { 00449 points.reserve(points.size()+edges.size()+1); 00450 00451 for (int i = 0; i < (int)edges.size(); ++i) 00452 { 00453 double* point = new double[3]; 00454 point[0] = edges[i]->getFirst()[0]; 00455 point[1] = edges[i]->getFirst()[1]; 00456 point[2] = edges[i]->getFirst()[2]; 00457 points.push_back(point); 00458 } 00459 00460 if (repeatFirstPoint) 00461 { 00462 double* point = new double[3]; 00463 point[0] = edges[0]->getFirst()[0]; 00464 point[1] = edges[0]->getFirst()[1]; 00465 point[2] = edges[0]->getFirst()[2]; 00466 points.push_back(point); 00467 } 00468 } 00469 00485 void getPoints(vector<double*> &points, const bool &repeatFirstPoint, const double &maxSpacing) 00486 { 00487 points.reserve(points.size()+edges.size()+1); 00488 00489 int n; 00490 double dx; 00491 for (int i = 0; i < (int)edges.size(); ++i) 00492 { 00493 n = (int)ceil(edges[i]->getDistance()/maxSpacing); 00494 dx = edges[i]->getDistance()/n; 00495 for (int j=0; j<n; ++j) 00496 points.push_back(edges[i]->getPoint(j*dx)); 00497 } 00498 00499 if (repeatFirstPoint) 00500 { 00501 double* point = new double[3]; 00502 point[0] = edges[0]->getFirst()[0]; 00503 point[1] = edges[0]->getFirst()[1]; 00504 point[2] = edges[0]->getFirst()[2]; 00505 points.push_back(point); 00506 } 00507 } 00508 00516 const double* getPoint(int index) 00517 { 00518 return edges[index]->getFirst(); 00519 } 00520 00533 double getArea() 00534 { 00535 double a, area = 0; 00536 GeoTessGreatCircle* edge; 00537 GeoTessGreatCircle* previous = edges[edges.size()-1]; 00538 00539 for (int i=0; i<(int)edges.size(); ++i) 00540 { 00541 edge = edges[i]; 00542 a = PI - GeoTessUtils::angle(previous->getNormal(), edge->getNormal()); 00543 00544 if (GeoTessUtils::scalarTripleProduct(previous->getNormal(), edge->getNormal(), 00545 edge->getFirst()) < 0) 00546 area += a; 00547 else 00548 area += 2*PI - a; 00549 00550 previous = edge; 00551 } 00552 area -= (edges.size()-2)*PI; 00553 return area; 00554 } 00555 00565 double getAreaSmall() 00566 { 00567 double area = getArea(); 00568 return area <= 2*PI ? area : 4*PI-area; 00569 } 00570 00580 double getAreaLarge() 00581 { 00582 double area = getArea(); 00583 return area >= 2*PI ? area : 4*PI-area; 00584 } 00585 00604 string str(const bool& repeatFirstPoint, const bool& latFirst, 00605 const double& minLongitude = -180); 00606 00607 virtual void write(const string& outputFileName); 00608 00610 00611 virtual void loadAscii(vector<string>& records); 00612 00614 00615 }; // end class Polygon 00616 00617 } // end namespace geotess 00618 00619 #endif /* POLYGON_H_ */