GeoTessCPP  2.1
Software to facilitate storage and retrieval of 3D information about the Earth.
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
GeoTessGrid.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 GEOTESSGRID_OBJECT_H
37 #define GEOTESSGRID_OBJECT_H
38 
39 // **** _SYSTEM INCLUDES_ ******************************************************
40 
41 #include <iostream>
42 #include <string>
43 #include <fstream>
44 #include <vector>
45 #include <set>
46 #include <list>
47 #include <set>
48 #include <sstream>
49 
50 // use standard library objects
51 using namespace std;
52 
53 // **** _LOCAL INCLUDES_ *******************************************************
54 
55 #include "CPPUtils.h"
56 #include "GeoTessUtils.h"
57 #include "ArrayReuse.h"
58 #include "GeoTessException.h"
60 
61 // **** _BEGIN GEOTESS NAMESPACE_ **********************************************
62 
63 namespace geotess
64 {
65 
66 // **** _FORWARD REFERENCES_ ***************************************************
67 
68 class IFStreamAscii;
69 class IFStreamBinary;
70 
71 // **** _CLASS DEFINITION_ *****************************************************
72 
98 struct Edge
99 {
103  int vj;
104 
108  int vk;
109 
110  int cornerj;
111 
115  int tLeft;
116 
120  int tRight;
121 
125  double normal[3]; //
126 
131  Edge* next; //
132 };
133 
164 {
165 protected:
166 
174  double** vertices;
175 
180 
186  int** triangles;
187 
192 
204  int** levels;
205 
209  int nLevels;
210 
225 
230 
236  void initialize();
237 
241  GeoTessGrid(const string& gid) :
242  vertices(NULL), nVertices(0),
243  triangles(NULL), nTriangles(0),
244  levels(NULL), nLevels(0),
245  tessellations(NULL), nTessellations(0),
246  descendants(NULL), gridID(gid),
247  gridInputFile("null"), gridOutputFile("null"), gridSoftwareVersion(""),
248  gridGenerationDate(""), refCount(0)
249  {
250  }
251 
252 private:
253 
261  int* descendants;
262 
280  vector<vector<Edge*> > edgeList;
281 
294  mutable vector<vector<Edge*> > spokeList;
295 
302  mutable vector<double*> circumCenters;
303 
312  string gridID;
313 
317  string gridInputFile;
318 
322  string gridOutputFile;
323 
327  string gridSoftwareVersion;
328 
333  string gridGenerationDate;
334 
338  int refCount;
339 
344  vector< vector< vector<int> > > vtxTriangles;
345 
351  mutable vector< set<int> > connectedVertices;
352 
356  GeoTessGrid* loadGridAscii(const string& inputFile);
357 
362  GeoTessGrid* loadGridAscii(IFStreamAscii& input);
363 
367  GeoTessGrid* loadGridBinary(const string& inputFile);
368 
372  virtual GeoTessGrid* loadGridBinary(IFStreamBinary& ifs);
373 
374  static void loadGridAsciiFront(IFStreamAscii& input, int& gridFileFormat,
375  string& gridSWVersion, string& fileCreationDate,
376  string& gridid, const string& grdInptFile);
377 
378  static void loadGridBinaryFront(IFStreamBinary& ifs, int& gridFileFormat,
379  string& gridSWVersion, string& fileCreationDate,
380  string& gridid, const string& grdInptFile);
381 
396  const set<int>& getVertexIndices(const int& level);
397 
398  void computeSpokeLists(const int& level) const;
399 
400 public:
401 
408  vertices(NULL), nVertices(0),
409  triangles(NULL), nTriangles(0),
410  levels(NULL), nLevels(0),
411  tessellations(NULL), nTessellations(0),
412  descendants(NULL), gridID(""),
413  gridInputFile("null"), gridOutputFile("null"), gridSoftwareVersion(""),
414  gridGenerationDate(""), refCount(0)
415  { }
416 
421  vertices(NULL), triangles(NULL), levels(NULL), tessellations(NULL),
422  descendants(NULL), gridID(""),
423  gridInputFile("null"), gridOutputFile("null"), gridSoftwareVersion(""),
424  gridGenerationDate(""), refCount(0)
425  { loadGridAscii(input); }
426 
431  vertices(NULL), triangles(NULL), levels(NULL), tessellations(NULL),
432  descendants(NULL), gridID(""),
433  gridInputFile("null"), gridOutputFile("null"), gridSoftwareVersion(""),
434  gridGenerationDate(""), refCount(0)
435  { loadGridBinary(input); }
436 
441  GeoTessGrid(GeoTessGrid &other);
442 
448  GeoTessGrid& operator= (const GeoTessGrid& other);
449 
454  LONG_INT getMemory()
455  {
456  LONG_INT memory = (LONG_INT)sizeof(GeoTessGrid);
457 
458  // double** vertices
459  memory += nVertices * (LONG_INT)sizeof(double*) + nVertices * 3 * (LONG_INT)sizeof(double);
460 
461  // int** triangles
462  memory += nTriangles * (LONG_INT)sizeof(int*) + nTriangles * 3 * (LONG_INT)sizeof(int);
463 
464  // int** levels
465  memory += nLevels * (LONG_INT)sizeof(int*) + nLevels * 2 * (LONG_INT)sizeof(int);
466 
467  // int** tessellations
468  memory += nTessellations * (LONG_INT)sizeof(int*) + nTessellations * 2 * (LONG_INT)sizeof(int);
469 
470  // int* descendants
471  memory += nTriangles * (LONG_INT)sizeof(int);
472 
473  // vector<vector<Edge*> > edgeList : nTriangles x 3 array of Edges
474  memory += (LONG_INT) (edgeList.capacity() * sizeof(vector<Edge*>)
475  + edgeList.size() * 3 * (sizeof(Edge*) + sizeof(Edge)));
476 
477  // vector<vector<Edge*> > spokeList;
478  memory += (LONG_INT) (spokeList.capacity() * sizeof(vector<Edge*>)
479  + spokeList.size() * 3 * sizeof(Edge*));
480 
481  // vector<double*> circumCenters is nTriangles x 3 array of doubles
482  memory += (LONG_INT) (circumCenters.capacity() * sizeof(double*));
483  for (int i=0; i<(int)circumCenters.size(); ++i)
484  if (circumCenters[i]) memory += 3 * (LONG_INT)sizeof(double);
485 
486  // An nLevels x nVertices x n array that stores the indices of the n
487  // triangles of which each vertex is a member.
488  // vector< vector< vector<int> > > vtxTriangles;
489  memory += (LONG_INT) (vtxTriangles.capacity() * sizeof(vector< vector<int> >));
490  for (int i=0; i<(int)vtxTriangles.size(); ++i)
491  {
492  memory += (LONG_INT) (vtxTriangles[i].capacity() * sizeof(vector<int>));
493  for (int j=0; j<(int)vtxTriangles[i].size(); ++j)
494  memory += (LONG_INT) (vtxTriangles[i][j].capacity() * sizeof(int));
495  }
496 
497  // An nLevels x n array that stores the indexes of the n vertices
498  // that are connected together by triangles on the corresponding
499  // level. Lazy evaluation is used to construct this array of sets.
500  // vector< set<int> > connectedVertices;
501  memory += (LONG_INT) (connectedVertices.capacity() * sizeof(set<int>));
502  for (int i=0; i<(int)connectedVertices.size(); ++i)
503  memory += (LONG_INT) (connectedVertices[i].size() * sizeof(int));
504 
505  // add memory requirements for all the string variables.
506  memory += (LONG_INT) (gridID.length() + gridInputFile.length() + gridOutputFile.length()
507  + gridSoftwareVersion.length() + gridGenerationDate.length());
508 
509  return memory;
510  }
511 
517  GeoTessGrid* loadGrid(const string& inputFile);
518 
525  static string getGridID(const string& fileName);
526 
533  static bool isGeoTessGrid(const string& inputFile);
534 
540  bool operator == (const GeoTessGrid& g) const
541  { return (gridID == g.gridID); }
542 
548  bool operator != (const GeoTessGrid& g) const
549  { return !(*this == g); }
550 
561  const string& getGridID() const
562  {
563  return gridID;
564  }
565 
572  void setGridSoftwareVersion(const string& swVersion) {gridSoftwareVersion = swVersion; };
573 
580  const string& getGridSoftwareVersion() const {return gridSoftwareVersion; };
581 
588  void setGridGenerationDate(const string& gridDate) {gridGenerationDate = gridDate; };
589 
596  const string& getGridGenerationDate() const {return gridGenerationDate; };
597 
602  void setGridInputFile(const string& gridFile) { gridInputFile = gridFile; }
603 
611  const string& getGridInputFile() const {return gridInputFile; }
612 
620  const string& getGridOutputFile() const { return gridOutputFile; }
621 
627  const double* getVertex(int vertex) const
628  {
629  return vertices[vertex];
630  }
631 
640  int findClosestVertex(double* unit_vector, int tessId)
641  {
642  int* t = triangles[getTriangle(getFirstTriangle(tessId, 0), unit_vector)];
643 
644  int index = 0;
645  double dot = GeoTessUtils::dot(unit_vector, vertices[t[0]]);
646 
647  double doti = GeoTessUtils::dot(unit_vector, vertices[t[1]]);
648  if (doti > dot)
649  {
650  index = 1;
651  dot = doti;
652  }
653 
654  doti = GeoTessUtils::dot(unit_vector, vertices[t[2]]);
655  if (doti > dot)
656  {
657  index = 2;
658  dot = doti;
659  }
660 
661  return t[index];
662  }
663 
672  int getVertexIndex(int triangle, int corner) const
673  { return triangles[triangle][corner]; }
674 
690  int getVertexIndex(int tessId, int level, int triangle, int corner) const
691  {
692  return triangles[levels[tessellations[tessId][0] + level][0] + triangle][corner];
693  }
694 
701  int getVertexIndex(const double* u)
702  {
703  for (int i=nTessellations-1; i>=0; --i)
704  {
705  int vid = getVertexIndex(u, i);
706  if (vid >= 0)
707  return vid;
708  }
709  return -1;
710  }
711 
720  int getVertexIndex(const double* u, int tessId)
721  {
722  int* t = triangles[getTriangle(getFirstTriangle(tessId, 0), u)];
723 
724  if (GeoTessUtils::dot(u, vertices[t[0]]) > cos(1e-7))
725  return t[0];
726  if (GeoTessUtils::dot(u, vertices[t[1]]) > cos(1e-7))
727  return t[1];
728  if (GeoTessUtils::dot(u, vertices[t[2]]) > cos(1e-7))
729  return t[2];
730  return -1;
731  }
732 
744  double* getVertex(int tessId, int level, int triangle, int corner)
745  {
746  return vertices[triangles[levels[tessellations[tessId][0] + level][0] + triangle][corner]];
747  }
748 
758  double const* const* getVertices() const { return vertices; }
759 
768  void getVerticesTopLevel(const int& tessellation, set<const double*>& vectors)
769  {
770  getVertices(tessellation, getNLevels(tessellation)-1, vectors);
771  }
772 
782  void getVertices(const int& tessellation, const int& level, set<const double*>& vectors);
783 
796  const set<int>& getVertexIndices(const int& tessId, const int& level)
797  { return getVertexIndices(getLevel(tessId, level)); }
798 
810  const set<int>& getVertexIndicesTopLevel(const int& tessId)
811  { return getVertexIndices(tessellations[tessId][1] - 1); }
812 
817  int getNVertices() const { return nVertices; }
818 
823  int getNTessellations() const { return nTessellations; }
824 
832  int getNLevels(int tessellation) const
833  { return tessellations[tessellation][1] - tessellations[tessellation][0]; }
834 
843  int getLevel(int tessellation, int i) const
844  { return tessellations[tessellation][0] + i; }
845 
861  int getLastLevel(int tessellation) const
862  { return tessellations[tessellation][1] - 1; }
863 
878  int getTopLevel(int tessellation) const
879  { return tessellations[tessellation][1] - tessellations[tessellation][0] - 1; }
880 
890  int getNTriangles(int tessellation, int level) const
891  {
892  return levels[tessellations[tessellation][0] + level][1]
893  - levels[tessellations[tessellation][0] + level][0];
894  }
895 
907  int getTriangle(int tessellation, int level, int i) const
908  { return levels[tessellations[tessellation][0] + level][0] + i; }
909 
919  int getFirstTriangle(int tessellation, int level) const
920  { return levels[tessellations[tessellation][0] + level][0]; }
921 
931  int getLastTriangle(int tessellation, int level) const
932  { return levels[tessellations[tessellation][0] + level][1]-1; }
933 
943  int const* const* getTriangles() const { return triangles; }
944 
956  const int* getTriangleVertexIndexes(int triangleIndex) const
957  { return triangles[triangleIndex]; }
958 
970  int getTriangleVertexIndex(int triangleIndex, int cornerIndex) const
971  { return triangles[triangleIndex][cornerIndex]; }
972 
984  const double* getTriangleVertex(int triangleIndex, int cornerIndex) const
985  { return vertices[triangles[triangleIndex][cornerIndex]]; }
986 
987 
996  void getTriangleVertices(int triangle, double** triVrt)
997  {
998  int* corners = triangles[triangle];
999  triVrt[0][0] = vertices[corners[0]][0];
1000  triVrt[0][1] = vertices[corners[0]][1];
1001  triVrt[0][2] = vertices[corners[0]][2];
1002  triVrt[1][0] = vertices[corners[1]][0];
1003  triVrt[1][1] = vertices[corners[1]][1];
1004  triVrt[1][2] = vertices[corners[1]][2];
1005  triVrt[2][0] = vertices[corners[2]][0];
1006  triVrt[2][1] = vertices[corners[2]][1];
1007  triVrt[2][2] = vertices[corners[2]][2];
1008  }
1009 
1014  const void computeCircumCenters()
1015  {
1016  if (circumCenters.empty()) circumCenters.resize(nTriangles, NULL);
1017 
1018  for (int triangle=0; triangle<nTriangles; ++triangle)
1019  if (circumCenters[triangle] == NULL)
1020  {
1021  int* corners = triangles[triangle];
1022  circumCenters[triangle] = GeoTessUtils::circumCenterPlus(vertices[corners[0]],
1023  vertices[corners[1]], vertices[corners[2]]);
1024  }
1025  }
1026 
1031  const void computeCircumCenters(const int& level)
1032  {
1033  if (circumCenters.empty()) circumCenters.resize(nTriangles);
1034 
1035  if (circumCenters[levels[level][0]] == NULL)
1036  {
1037  for (int triangle=levels[level][0]; triangle<levels[level][1]; ++triangle)
1038  {
1039  int* corners = triangles[triangle];
1040  circumCenters[triangle] = GeoTessUtils::circumCenterPlus(vertices[corners[0]],
1041  vertices[corners[1]], vertices[corners[2]]);
1042  }
1043  }
1044  }
1045 
1061  const double* getCircumCenter(const int& triangle) const { return circumCenters[triangle]; }
1062 
1080  void getCircumCenter(const int& triangle, double* cc) const
1081  { cc[0]=circumCenters[triangle][0]; cc[1]=circumCenters[triangle][1]; cc[2]=circumCenters[triangle][2]; }
1082 
1097  int getNeighbor(const int& triangleIndex, const int& neighborIndex) const
1098  { return neighborIndex == 3 ? descendants[triangleIndex] : edgeList[triangleIndex][neighborIndex]->tLeft; }
1099 
1124  int getNeighbor(const int& tessellation, const int& level, const int& triangle, const int& side)
1125  { return getNeighbor(getTriangle(tessellation, level, triangle), side); }
1126 
1141  void getNeighbors(int triangleIndex, vector<int>& neighbors)
1142  {
1143  neighbors.clear();
1144  vector<Edge*> edges = edgeList[triangleIndex];
1145  neighbors.push_back(edges[0]->tLeft);
1146  neighbors.push_back(edges[1]->tLeft);
1147  neighbors.push_back(edges[2]->tLeft);
1148  neighbors.push_back(descendants[triangleIndex]);
1149  }
1150 
1173  void getNeighbors(const int& tessellation, const int& level, const int& triangle, vector<int>& neighbors)
1174  { getNeighbors(getTriangle(tessellation, level, triangle), neighbors); }
1175 
1189  int getNeighborIndex(const int& tid, const int& nid)
1190  {
1191  if (edgeList[tid][0]->tLeft == nid)
1192  return 0;
1193  if (edgeList[tid][1]->tLeft == nid)
1194  return 1;
1195  if (edgeList[tid][2]->tLeft == nid)
1196  return 2;
1197  return -1;
1198  }
1199 
1200  int const* getDescendants() const { return descendants; }
1201 
1202  int getDescendant(const int& triangle) const { return descendants[triangle]; }
1203 
1204  int getDescendant(const int& tessId, const int& level, const int& triangle) const
1205  { return descendants[getTriangle(tessId, level, triangle)]; }
1206 
1210  string toString();
1211 
1219  int getTriangle(int triangleIndex, const double* vector);
1220 
1228  const vector<vector<int> >& getVertexTriangles(const int& level) const { return vtxTriangles[level]; }
1229 
1242  const vector<int>& getVertexTriangles(const int& tessId, const int& level, const int& vertex) const
1243  { return vtxTriangles[tessellations[tessId][0] + level][vertex]; }
1244 
1258  const vector<int>& getVertexTriangles(int tessId, int vertex) const
1259  { return getVertexTriangles(tessId, getNLevels(tessId)-1, vertex); }
1260 
1267  //void clearVertexTriangles();
1268 
1278  void getVertexNeighborsOrdered(const int& tessId, const int& level, const int& vertex, vector<int>& v);
1279 
1291  void getVertexNeighbors(const int& tessId, const int& level, const int& vertex, set<int>& nbrs)
1292  { getVertexNeighbors(tessId, level, vertex, 1, nbrs); }
1293 
1311  void getVertexNeighbors(const int& tessId, const int& level, const int& vertex,
1312  const int& order, set<int>& nbrs);
1313 
1314  // All methods below this point are public but are not documented in the doxygen documentation.
1315  // These are methods that typical applications will never need to call. They have to be
1316  // public because other classes in the GeoTess namespace need to access them.
1317  //
1319 
1325  GeoTessGrid(const GeoTessOptimizationType* opttype) :
1326  vertices(NULL), nVertices(0),
1327  triangles(NULL), nTriangles(0),
1328  levels(NULL), nLevels(0),
1329  tessellations(NULL), nTessellations(0),
1330  descendants(NULL), gridID(""),
1331  gridInputFile("null"), gridOutputFile("null"), gridSoftwareVersion(""),
1332  gridGenerationDate(""), refCount(0)
1333  { }
1334 
1339  GeoTessGrid(IFStreamAscii& input, const GeoTessOptimizationType* opttype) :
1340  vertices(NULL), triangles(NULL), levels(NULL), tessellations(NULL),
1341  descendants(NULL), gridID(""),
1342  gridInputFile("null"), gridOutputFile("null"), gridSoftwareVersion(""),
1343  gridGenerationDate(""), refCount(0)
1344  { loadGridAscii(input); }
1345 
1350  GeoTessGrid(IFStreamBinary& input, const GeoTessOptimizationType* opttype) :
1351  vertices(NULL), triangles(NULL), levels(NULL), tessellations(NULL),
1352  descendants(NULL), gridID(""),
1353  gridInputFile("null"), gridOutputFile("null"), gridSoftwareVersion(""),
1354  gridGenerationDate(""), refCount(0)
1355  { loadGridBinary(input); }
1356 
1361  GeoTessGrid(double** _vertices, int& _nVertices,
1362  int** _triangles, int& _nTriangles,
1363  int** _levels, int& _nLevels,
1364  int** _tessellations, int& _nTessellations,
1365  string& _gridID,
1366  string& _gridInputFile,
1367  string& _gridOutputFile,
1368  string& _gridSoftwareVersion,
1369  string& _gridGenerationDate) :
1370  vertices(_vertices), nVertices(_nVertices),
1371  triangles(_triangles), nTriangles(_nTriangles),
1372  levels(_levels), nLevels(_nLevels),
1373  tessellations(_tessellations), nTessellations(_nTessellations),
1374  descendants(NULL),
1375  gridID(_gridID),
1376  gridInputFile(_gridInputFile),
1377  gridOutputFile(_gridOutputFile),
1378  gridSoftwareVersion(_gridSoftwareVersion),
1379  gridGenerationDate(_gridGenerationDate),
1380  refCount(0)
1381  { initialize(); }
1382 
1386  virtual ~GeoTessGrid();
1387 
1391  int getReferenceCount() { return refCount; }
1392 
1396  void addReference() { ++refCount; }
1397 
1401  void removeReference()
1402  {
1403  if (isNotReferenced())
1404  {
1405  ostringstream os;
1406  os << endl << "ERROR in GeoTessGrid::removeReference" << endl
1407  << "Reference count (" << refCount << ") is already zero." << endl;
1408  throw GeoTessException(os, __FILE__, __LINE__, 2001);
1409  }
1410 
1411  --refCount;
1412  }
1413 
1417  bool isNotReferenced() { return (refCount == 0); }
1418 
1424  void writeGrid(const string& fileName);
1425 
1429  void writeGridAscii(const string& fileName);
1430 
1434  void writeGridAscii(IFStreamAscii& output);
1435 
1439  void writeGridBinary(const string& fileName);
1440 
1444  void writeGridBinary(IFStreamBinary& output);
1445 
1451  bool isSupportedFormatVersion(int frmtVrsn)
1452  { return (frmtVrsn == 2); }
1453 
1454  // deprecated. GeoTessOptimizationType is no longer used. Always optimized for speed.
1455  const GeoTessOptimizationType& getOptimizationType() const { return GeoTessOptimizationType::SPEED; }
1456 
1458 
1467  void testGrid();
1468 
1474  int getNLevels() const { return nLevels; }
1475 
1487  int const* const* getLevels() const { return levels; }
1488 
1503  int const* const* getTessellations() const { return tessellations; }
1504 
1512  int getNTriangles() const { return nTriangles; }
1513 
1514  vector<Edge*>& getSpokeList(const int& level) const
1515  { computeSpokeLists(level); return spokeList[level]; }
1516 
1517  const vector<vector<Edge*> >& getEdgeList() const { return edgeList; }
1518 
1519  const vector<Edge*>& getEdgeList(const int& triangle) const { return edgeList[triangle]; }
1520 
1527  void getCenter(const int& triangle, double* center)
1528  {
1529  vector<double*> corners;
1530  corners.push_back(vertices[triangles[triangle][0]]);
1531  corners.push_back(vertices[triangles[triangle][1]]);
1532  corners.push_back(vertices[triangles[triangle][2]]);
1533  GeoTessUtils::center(corners, center);
1534  }
1535 
1541  int delaunay();
1542 
1543 };
1544 // end class GeoTessGrid
1545 
1546 }// end namespace geotess
1547 
1548 #endif // GEOTESSGRID_OBJECT_H