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::triangulateFromQuadric(unsigned nStepX, unsigned nStepY) { if (nStepX<2 || nStepY<2) return 0; //qaudric fit const PointCoordinateType* Q = getQuadric(); //Q: Z = a + b.X + c.Y + d.X^2 + e.X.Y + f.Y^2 if (!Q) return 0; const PointCoordinateType& a = Q[0]; const PointCoordinateType& b = Q[1]; const PointCoordinateType& c = Q[2]; const PointCoordinateType& d = Q[3]; const PointCoordinateType& e = Q[4]; const PointCoordinateType& f = Q[5]; const uchar X = m_quadricEquationDirections.x; const uchar Y = m_quadricEquationDirections.y; const uchar Z = m_quadricEquationDirections.z; //gravity center (should be ok if the quadric is ok) const CCVector3* G = getGravityCenter(); assert(G); //bounding box CCVector3 bbMin, bbMax; m_associatedCloud->getBoundingBox(bbMin,bbMax); CCVector3 bboxDiag = bbMax - bbMin; //Sample points on Quadric and triangulate them! PointCoordinateType spanX = bboxDiag.u[X]; PointCoordinateType spanY = bboxDiag.u[Y]; PointCoordinateType stepX = spanX/(nStepX-1); PointCoordinateType stepY = spanY/(nStepY-1); ChunkedPointCloud* vertices = new ChunkedPointCloud(); if (!vertices->reserve(nStepX*nStepY)) { delete vertices; return 0; } SimpleMesh* quadMesh = new SimpleMesh(vertices,true); if (!quadMesh->reserve((nStepX-1)*(nStepY-1)*2)) { delete quadMesh; return 0; } for (unsigned x=0; x<nStepX; ++x) { CCVector3 P; P.x = bbMin[X] + stepX * x - G->u[X]; for (unsigned y=0; y<nStepY; ++y) { P.y = bbMin[Y] + stepY * y - G->u[Y]; P.z = a+b*P.x+c*P.y+d*P.x*P.x+e*P.x*P.y+f*P.y*P.y; CCVector3 Pc; Pc.u[X] = P.x; Pc.u[Y] = P.y; Pc.u[Z] = P.z; Pc += *G; vertices->addPoint(Pc); if (x>0 && y>0) { unsigned iA = (x-1) * nStepY + y-1; unsigned iB = iA+1; unsigned iC = iA+nStepY; unsigned iD = iB+nStepY; quadMesh->addTriangle(iA,iC,iB); quadMesh->addTriangle(iB,iC,iD); } } } return quadMesh; }
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; }