bool TriangulatorAdaptor::triangulate(int *triangleIndexes) { int XX, YY; from3DTo2D(XX, YY); map<pair<double, double> , int> coorToPosMap; // coordinate to position map for (int i = 0; i < polygon.size(); i++) { coorToPosMap.insert( pair<pair<double, double> , int>( pair<double, double>(polygon[i][XX], polygon[i][YY]), i)); } TPPLPoly poly; poly.Init(polygon.size()); for (int i = 0; i < polygon.size(); i++) { poly[i].x = polygon[i][XX]; poly[i].y = polygon[i][YY]; } if (poly.GetOrientation() == TPPL_CW) { isClockwise = true; poly.Invert(); // polygon has to be counter-clockwise } else if(poly.GetOrientation() == TPPL_CCW) { isClockwise = false; } else { return false; } list<TPPLPoly> triangles; TPPLPartition triangulator; // see http://code.google.com/p/polypartition/ int success = triangulator.Triangulate_OPT(&poly, &triangles); if (success != 1) { cout << "Error: polygon cannot be triangulated!" << endl; cout << "Polygon:" << endl; for (int i=0; i<polygon.size(); i++) { cout << polygon[i][0] << " " << polygon[i][1] << " " << polygon[i][2] << endl; } return false; } //assert(success == 1); assert(triangles.size() +2 == polygon.size()); int count = 0; for (list<TPPLPoly>::iterator it = triangles.begin(); it != triangles.end(); it++) { if (!isClockwise) { for (int j = 0; j < 3; j++) { triangleIndexes[count * 3 + j] = coorToPosMap[pair<double, double>((*it)[j].x, (*it)[j].y)]; } } else { for (int j = 0; j < 3; j++) { triangleIndexes[count * 3 + 2 - j] = coorToPosMap[pair<double, double>((*it)[j].x, (*it)[j].y)]; } } count++; } assert(count == triangles.size()); return true; }
// Initialize polypartition TPPLPoly from a list of indices and vertices // // verts - 3D polygon vertex vectors // xind,yind - Indices of 3D vectors to extract as x and y coordinates for 2D // triangulation computation. // inds,size - Array of indices into the `verts` list // isHole - Value for the hole flag, and to determine the orientation static void initTPPLPoly(TPPLPoly& poly, const std::vector<float>& verts, int xind, int yind, const GLuint* inds, int size, bool isHole) { // Check for explicitly closed polygons (last and first vertices equal) and // discard the last vertex in these cases. This is a pretty stupid // convention, but the OGC have blessed it and now we've got a bunch of // geospatial formats (kml, WKT, GeoJSON) which require it. Sigh. // http://gis.stackexchange.com/questions/10308/why-do-valid-polygons-repeat-the-same-start-and-end-point/10309#10309 if (inds[0] == inds[size-1] || (verts[3*inds[0]+0] == verts[3*inds[size-1]+0] && verts[3*inds[0]+1] == verts[3*inds[size-1]+1] && verts[3*inds[0]+2] == verts[3*inds[size-1]+2])) { g_logger.warning_limited("Ignoring duplicate final vertex in explicitly closed polygon"); size -= 1; } // Copy into polypartition data structure poly.Init(size); for (int i = 0; i < size; ++i) { poly[i].x = verts[3*inds[i]+xind]; poly[i].y = verts[3*inds[i]+yind]; poly[i].id = inds[i]; } int orientation = poly.GetOrientation(); // Invert so that outer = ccw, holes = cw if ((orientation == TPPL_CW) ^ isHole) poly.Invert(); poly.SetHole(isHole); }
void make_poly(float* buf, int pnt_sz, TPPLPoly& poly) { poly.Init(pnt_sz); for (int k(0); k < pnt_sz; k++) { poly[k].x = buf[2 * k]; poly[k].y = buf[2 * k + 1]; } if (poly.GetOrientation() == TPPL_CW) { poly.SetHole(true); } }