void create_subdivided_face(int sdRes, int nV, double *uvs, double *itv, int Tidx, MFloatArray &uA, MFloatArray &vA, MIntArray &uvIdx) { HDS hds; hds.V.setDims(2, nV); memcpy(&hds.V.v[0], uvs, 2*nV*sizeof(double)); hds.nFV.setDims(1, 1); hds.nFV[0] = nV; hds.tip.setDims(1, nV); for (size_t k=0; k<nV; k++) { hds.tip[k] = k; } finalize_HDS(hds); size_t nHE = hds.nHE(), nIHE = hds.nIHE();⟵ hds.T.setDims(1, nHE); hds.itv.setDims(1, nHE); memset(&hds.T.v[0], 0, nHE*sizeof(bool)); if (nV==5) hds.T[Tidx] = 1; memcpy(&hds.itv.v[0], itv, nV*sizeof(double)); // border halfedge tags for (size_t k=nIHE; k<nHE; k++) { hds.itv[k] = hds.itv[hds.twin[k]]; } TCC_MAX::linear_subdivide(hds, sdRes); int sd_nV = hds.nV(); int sd_nIHE = hds.nIHE(); uA.setLength(sd_nV); vA.setLength(sd_nV); for (int k=0; k<sd_nV; k++) { uA[k] = hds.V[2*k+0]; vA[k] = hds.V[2*k+1]; } uvIdx.setLength(sd_nIHE); for (int k=0; k<sd_nIHE; k++) { uvIdx[k]=hds.tip[k]; } }
void load_from_hds(HDS &hds, MFloatPointArray &points, MIntArray &nFV, MIntArray &F) { size_t nV = hds.nV(); size_t nF = hds.nF(); size_t nIHE = hds.nIHE(); points.setLength(nV); for (size_t k=0; k<nV; k++) { points[k](0) = hds.V[3*k+0]; points[k](1) = hds.V[3*k+1]; points[k](2) = hds.V[3*k+2]; } nFV.setLength(nF); for (size_t k=0; k<nF; k++) nFV[k] = hds.nFV[k]; F.setLength(nIHE); for (size_t k=0; k<nIHE; k++) F[k] = hds.tip[k]; }
void test_HalfedgeDS_default() { // Simple instantiation of the default halfedge data structure. typedef CGAL_HALFEDGEDS_DEFAULT<Dummy_traits_2> HDS; typedef CGAL::HalfedgeDS_decorator<HDS> Decorator; HDS hds; Decorator D(hds); D.create_loop(); assert( hds.size_of_vertices() == 1); assert( hds.size_of_halfedges() == 2); assert( hds.size_of_faces() == 2); assert( D.is_valid( false, 3)); D.make_hole( hds.halfedges_begin()->opposite()); hds.normalize_border(); assert( hds.size_of_border_halfedges() == 1); assert( hds.size_of_border_edges() == 1); assert( D.is_valid( false, 4)); D.fill_hole( hds.halfedges_begin()->opposite()); hds.normalize_border(); assert( hds.size_of_border_halfedges() == 0); assert( hds.size_of_border_edges() == 0); assert( D.is_valid( false, 4)); HDS hds2(hds); // copy constructor. Decorator D2(hds2); assert( D2.is_valid( false, 4)); hds = hds2; // assignment. assert( D.is_valid( false, 4)); typedef HDS::Halfedge_iterator Halfedge_iterator; Halfedge_iterator i = hds.halfedges_begin(); assert(!(i == hds.halfedges_end())); }
void test_HalfedgeDS_polyhedron_default() { // Simple instantiation of the default for polyhedrons. typedef CGAL_HALFEDGEDS_DEFAULT< Dummy_traits_3, CGAL::Polyhedron_items_3> HDS; typedef HDS::Vertex Vertex; typedef HDS::Halfedge Halfedge; typedef HDS::Face Face; typedef Halfedge::Base HBase; HDS hds; hds.vertices_push_back( Vertex()); hds.edges_push_back( Halfedge(), Halfedge()); hds.faces_push_back( Face()); hds.halfedges_begin()->HBase::set_face( hds.faces_begin()); assert( hds.size_of_vertices() == 1); assert( hds.size_of_halfedges() == 2); assert( hds.size_of_faces() == 1); hds.normalize_border(); assert( hds.size_of_border_halfedges() == 1); assert( hds.size_of_border_edges() == 1); typedef HDS::Halfedge_iterator Halfedge_iterator; Halfedge_iterator i = hds.halfedges_begin(); assert(!(i == hds.halfedges_end())); }
void operator()(HDS & hds) { next_index = hds.size_of_vertices(); builder = new Builder(hds, true); }
void test_HalfedgeDS_decorator() { // Simple instantiation of the default halfedge data structure. typedef CGAL_HALFEDGEDS_DEFAULT<Dummy_traits_2> HDS; typedef CGAL::HalfedgeDS_decorator<HDS> Decorator; typedef HDS::Halfedge_handle Halfedge_handle; typedef HDS::Face_handle Face_handle; HDS hds; Decorator decorator(hds); // Check create single loop. Halfedge_handle h = decorator.create_loop(); hds.normalize_border(); assert( hds.size_of_vertices() == 1); assert( hds.size_of_halfedges() == 2); assert( hds.size_of_faces() == 2); assert( decorator.is_valid( false, 4)); // Restart with open segment. hds.clear(); hds.normalize_border(); assert( decorator.is_valid( false, 4)); h = decorator.create_segment(); assert( hds.size_of_vertices() == 2); assert( hds.size_of_halfedges() == 2); assert( hds.size_of_faces() == 1); assert( decorator.is_valid( false, 4)); // Create border edge and check normalization. decorator.set_face( h->opposite(), Face_handle()); hds.normalize_border(); assert( hds.size_of_border_halfedges() == 1); assert( hds.size_of_border_edges() == 1); assert( decorator.normalized_border_is_valid()); decorator.set_face( h->opposite(), h->face()); hds.normalize_border(); assert( hds.size_of_border_halfedges() == 0); assert( hds.size_of_border_edges() == 0); assert( decorator.is_valid( false, 4)); // Extend edge to two triangles. Halfedge_handle g = decorator.split_vertex( h, h); assert( decorator.is_valid( false, 4)); assert( h != g); assert( h->next()->next() == g); assert( h == g->next()->next()); assert( h->opposite() == g->next()); assert( g->opposite() == h->next()); Halfedge_handle g2 = decorator.split_face(h->opposite(),g->opposite()); assert( decorator.is_valid( false, 4)); assert( h->opposite()->next() == g2); assert( g2->next() == g); decorator.split_vertex( g2, g->opposite()); assert( decorator.is_valid( false, 4)); assert( g->next()->next()->next()->next() == g); Halfedge_handle g3 = decorator.split_face( g2->next()->opposite(), h); assert( decorator.is_valid( false, 4)); assert( g->next()->next()->next()->next() == g); assert( h->next()->next()->next() == h); assert( g3->next()->next()->next() == g3); assert( g3->next() == g->opposite()); assert( g3->opposite()->next() == g2->opposite()); assert( g3->opposite() == h->next()); // Edge flip within the triangle. Halfedge_handle g4 = decorator.flip_edge( g3); assert( decorator.is_valid( false, 4)); assert( g4 == g3); assert( g3->next()->next() == g2->opposite()); assert( g3->opposite()->next() == h); assert( g->next()->next()->next()->next() == g); assert( h->next()->next()->next() == h); assert( g3->next()->next()->next() == g3); // Reverse face orientation. decorator.inside_out(); assert( decorator.is_valid( false, 4)); decorator.inside_out(); assert( decorator.is_valid( false, 4)); // Check hole manipulations. decorator.make_hole(g); hds.normalize_border(); assert( hds.size_of_border_halfedges() == 4); assert( hds.size_of_border_edges() == 4); assert( decorator.is_valid( false, 4)); // Reverse face orientation, deal also with the hole.. decorator.inside_out(); assert( decorator.is_valid( false, 3)); hds.normalize_border(); assert( decorator.is_valid( false, 4)); // Check add_face_to_border. hds.clear(); h = decorator.create_loop(); decorator.make_hole( h->opposite()); hds.normalize_border(); assert( decorator.is_valid( false, 4)); decorator.add_face_to_border( h->opposite(), h->opposite()); assert( hds.size_of_halfedges() == 4); assert( hds.size_of_faces() == 2); assert( decorator.is_valid( false, 3)); }
void test_HalfedgeDS_decorator3() { // Simple instantiation of the default halfedge data structure. typedef CGAL::HalfedgeDS_default<Dummy_traits_2> HDS; typedef CGAL::HalfedgeDS_decorator<HDS> Decorator; CGAL_USE_TYPE(HDS::Halfedge_handle); CGAL_USE_TYPE(HDS::Face_handle); HDS hds; Build_triangle<HDS> modifier(0,0); modifier(hds); modifier.x_=33; modifier.y_=33; modifier(hds); Decorator decorator(hds); decorator.keep_largest_connected_components(1); hds.normalize_border(); assert( hds.size_of_vertices() == 4); assert( hds.size_of_halfedges() == 10); assert( hds.size_of_faces() == 2); assert( decorator.is_valid( false, 4)); decorator.vertices_erase(hds.vertices_begin()); decorator.vertices_erase(hds.vertices_begin(), hds.vertices_end()); decorator.faces_erase(hds.faces_begin()); decorator.faces_erase(hds.faces_begin(), hds.faces_end()); assert( hds.size_of_vertices() == 0); assert( hds.size_of_halfedges() == 10); assert( hds.size_of_faces() == 0); }
MStatus TCC::createSubdividedMesh(int sdRes, int sdRefRes, MFnMesh &srcMesh, TCCData &tccData, MDataHandle outMeshHandle, float lineThickness, MStatus& stat) { HDS hds; bool shouldCreateUVs = true; size_t nV = srcMesh.numVertices(); size_t nF = srcMesh.numPolygons(); size_t nIHE = tccData.F.length(); bool consistentSizes= (tccData.pole.length()==nV) && (tccData.T.length()==nIHE) && (tccData.itv.length()==nIHE) & (tccData.corner.length()==nV); if ((nV==0)||(nF==0)||(!consistentSizes)) return MS::kFailure; MFloatArray uArray, vArray, sc_uArray, sc_vArray; MIntArray uvIdx; if (shouldCreateUVs) { createUVset(tccData, sdRes, uArray, vArray, sc_uArray, sc_vArray, uvIdx, lineThickness); } MFloatPointArray points; srcMesh.getPoints(points); store_in_hds(hds, points, tccData.nFV, tccData.F); // convert to HDS finalize_HDS(hds); size_t nHE = hds.nHE(); hds.T.setDims(1, nHE); hds.itv.setDims(1, nHE); hds.corner.setDims(1, nV); // interior halfedge tags for (size_t k=0; k<nV; k++) { hds.corner[k] = tccData.corner[k]; } // interior halfedge tags for (size_t k=0; k<nIHE; k++) { hds.T[k] = tccData.T[k]; hds.itv[k] = tccData.itv[k]; } // border halfedge tags for (size_t k=nIHE; k<nHE; k++) { hds.T[k] = false; hds.itv[k] = hds.itv[hds.twin[k]]; } TCC_MAX::subdivide(hds, sdRes); if (sdRefRes>0) { HDS hds2; copy_HDS(hds, hds2); TCC_MAX::subdivide(hds2, sdRefRes); memcpy(&hds.V[0], &hds2.V[0], hds.V.size() * sizeof(double)); } MObject outMeshObj = outMeshHandle.asMesh(); MFnMesh outMeshFn(outMeshObj); // if no topology change necessary, just update points! if ( (outMeshFn.numFaceVertices() == hds.nIHE()) && (outMeshFn.numPolygons() == hds.nF()) ) { size_t nV = hds.nV(); points.setLength(nV); for (size_t k=0; k<nV; k++) { points[k](0) = hds.V[3*k+0]; points[k](1) = hds.V[3*k+1]; points[k](2) = hds.V[3*k+2]; } stat = outMeshFn.setPoints(points); McheckErr(stat, "ERROR creating outputData"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; stat = outMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = outMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); } return MS::kSuccess; } // Have to update connectivity and geometry load_from_hds(hds, points, tccData.nFV, tccData.F); nV = points.length(); nF = tccData.nFV.length(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&stat); McheckErr(stat, "ERROR creating outputData"); MFnMesh newOutMeshFn; MObject newMesh; newMesh = newOutMeshFn.create(nV, nF, points, tccData.nFV, tccData.F, newOutputData, &stat); McheckErr(stat, "ERROR in MFnMesh.create\n"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; uvSet = newOutMeshFn.createUVSetDataMeshWithName(uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&uvSet); stat = newOutMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &uvSet); McheckErr(stat, "ERROR assigning UVs"); sc_uvSet = newOutMeshFn.createUVSetDataMeshWithName(sc_uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&sc_uvSet); stat = newOutMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &sc_uvSet); McheckErr(stat, "ERROR assigning UVs"); } if (stat == MS::kSuccess) { outMeshHandle.set(newOutputData); } return MS::kSuccess; }