GenericIndexedMesh* Neighbourhood::triangulateOnPlane(bool duplicateVertices/*=false*/, PointCoordinateType maxEdgeLength/*=0*/) { if (m_associatedCloud->size()<CC_LOCAL_MODEL_MIN_SIZE[TRI]) { //can't compute LSF plane with less than 3 points! return 0; } //project the points on this plane GenericIndexedMesh* mesh = 0; std::vector<CCVector2> points2D; if (projectPointsOn2DPlane<CCVector2>(points2D)) { Delaunay2dMesh* dm = new Delaunay2dMesh(); //triangulate the projected points if (!dm->build(points2D,0)) { delete dm; return 0; } //change the default mesh's reference if (duplicateVertices) { ChunkedPointCloud* cloud = new ChunkedPointCloud(); unsigned count = m_associatedCloud->size(); if (!cloud->reserve(count)) { delete dm; delete cloud; return 0; } for (unsigned i=0; i<count; ++i) cloud->addPoint(*m_associatedCloud->getPoint(i)); dm->linkMeshWith(cloud,true); } else { dm->linkMeshWith(m_associatedCloud,false); } //remove triangles with too long edges if (maxEdgeLength > 0) { dm->removeTrianglesLongerThan(maxEdgeLength); if (dm->size() == 0) { //no more triangles? delete dm; dm = 0; } } mesh = static_cast<GenericIndexedMesh*>(dm); } return mesh; }
GenericIndexedMesh* Neighbourhood::triangulateOnPlane( bool duplicateVertices/*=false*/, PointCoordinateType maxEdgeLength/*=0*/, char* errorStr/*=0*/) { if (m_associatedCloud->size() < CC_LOCAL_MODEL_MIN_SIZE[TRI]) { //can't compute LSF plane with less than 3 points! if (errorStr) strcpy(errorStr,"Not enough points"); return 0; } //safety check: Triangle lib will crash if the points are all the same! if (computeLargestRadius() < ZERO_TOLERANCE) { return 0; } //project the points on this plane GenericIndexedMesh* mesh = 0; std::vector<CCVector2> points2D; if (projectPointsOn2DPlane<CCVector2>(points2D)) { Delaunay2dMesh* dm = new Delaunay2dMesh(); //triangulate the projected points if (!dm->buildMesh(points2D,0,errorStr)) { delete dm; return 0; } //change the default mesh's reference if (duplicateVertices) { ChunkedPointCloud* cloud = new ChunkedPointCloud(); unsigned count = m_associatedCloud->size(); if (!cloud->reserve(count)) { if (errorStr) strcpy(errorStr,"Not enough memory"); delete dm; delete cloud; return 0; } for (unsigned i=0; i<count; ++i) cloud->addPoint(*m_associatedCloud->getPoint(i)); dm->linkMeshWith(cloud,true); } else { dm->linkMeshWith(m_associatedCloud,false); } //remove triangles with too long edges if (maxEdgeLength > 0) { dm->removeTrianglesWithEdgesLongerThan(maxEdgeLength); if (dm->size() == 0) { //no more triangles? if (errorStr) strcpy(errorStr,"Not triangle left after pruning"); delete dm; dm = 0; } } mesh = static_cast<GenericIndexedMesh*>(dm); } return mesh; }
GenericIndexedMesh* PointProjectionTools::computeTriangulation( GenericIndexedCloudPersist* theCloud, CC_TRIANGULATION_TYPES type/*=GENERIC*/, PointCoordinateType maxEdgeLength/*=0*/, char* errorStr/*=0*/) { if (!theCloud) { if (errorStr) strcpy(errorStr, "Invalid input cloud"); return 0; } switch(type) { case GENERIC: { unsigned count = theCloud->size(); std::vector<CCVector2> the2DPoints; try { the2DPoints.resize(count); } catch (.../*const std::bad_alloc&*/) //out of memory { if (errorStr) strcpy(errorStr, "Not enough memory"); break; } theCloud->placeIteratorAtBegining(); CCVector3 P; for (unsigned i=0; i<count; ++i) { theCloud->getPoint(i,P); the2DPoints[i].x = P.x; the2DPoints[i].y = P.y; } Delaunay2dMesh* dm = new Delaunay2dMesh(); char triLibErrorStr[1024]; if (!dm->build(the2DPoints,0,false,triLibErrorStr)) { if (errorStr) strcpy(errorStr, triLibErrorStr); delete dm; return 0; } dm->linkMeshWith(theCloud,false); //remove triangles with too long edges if (maxEdgeLength > 0) { dm->removeTrianglesLongerThan(maxEdgeLength); if (dm->size() == 0) { //no more triangles? if (errorStr) strcpy(errorStr, "No triangle left after pruning"); delete dm; return 0; } } return static_cast<GenericIndexedMesh*>(dm); } break; case GENERIC_BEST_LS_PLANE: { Neighbourhood Yk(theCloud); GenericIndexedMesh* mesh = Yk.triangulateOnPlane(false,maxEdgeLength,errorStr); return mesh; } break; default: //shouldn't happen assert(false); break; } return 0; }
GenericIndexedMesh* PointProjectionTools::computeTriangulation( GenericIndexedCloudPersist* cloud, CC_TRIANGULATION_TYPES type/*=DELAUNAY_2D_AXIS_ALIGNED*/, PointCoordinateType maxEdgeLength/*=0*/, unsigned char dim/*=0*/, char* errorStr/*=0*/) { if (!cloud) { if (errorStr) strcpy(errorStr, "Invalid input cloud"); return nullptr; } switch(type) { case DELAUNAY_2D_AXIS_ALIGNED: { if (dim > 2) { if (errorStr) strcpy(errorStr, "Invalid projection dimension"); return nullptr; } const unsigned char Z = static_cast<unsigned char>(dim); const unsigned char X = Z == 2 ? 0 : Z+1; const unsigned char Y = X == 2 ? 0 : X+1; unsigned count = cloud->size(); std::vector<CCVector2> the2DPoints; try { the2DPoints.resize(count); } catch (.../*const std::bad_alloc&*/) //out of memory { if (errorStr) strcpy(errorStr, "Not enough memory"); break; } cloud->placeIteratorAtBeginning(); for (unsigned i=0; i<count; ++i) { const CCVector3* P = cloud->getPoint(i); the2DPoints[i].x = P->u[X]; the2DPoints[i].y = P->u[Y]; } Delaunay2dMesh* dm = new Delaunay2dMesh(); char triLibErrorStr[1024]; if (!dm->buildMesh(the2DPoints,0,triLibErrorStr)) { if (errorStr) strcpy(errorStr, triLibErrorStr); delete dm; return nullptr; } dm->linkMeshWith(cloud,false); //remove triangles with too long edges if (maxEdgeLength > 0) { dm->removeTrianglesWithEdgesLongerThan(maxEdgeLength); if (dm->size() == 0) { //no more triangles? if (errorStr) strcpy(errorStr, "No triangle left after pruning"); delete dm; return nullptr; } } return static_cast<GenericIndexedMesh*>(dm); } break; case DELAUNAY_2D_BEST_LS_PLANE: { Neighbourhood Yk(cloud); GenericIndexedMesh* mesh = Yk.triangulateOnPlane(false,maxEdgeLength,errorStr); return mesh; } break; default: //shouldn't happen assert(false); break; } return nullptr; }