CRhinoCommand::result CCommandSampleTriangulatePolygon::RunCommand( const CRhinoCommandContext& context ) { CRhinoGetObject go; go.SetCommandPrompt( L"Select closed planar polygon to triangulate" ); go.SetGeometryFilter( CRhinoGetObject::curve_object ); go.SetGeometryFilter( CRhinoGetObject::closed_curve ); go.EnableSubObjectSelect( FALSE ); go.GetObjects( 1, 1 ); if( go.CommandResult() != CRhinoCommand::success ) return go.CommandResult(); const CRhinoObjRef& ref = go.Object(0); ON_3dPointArray vertices; const ON_PolylineCurve* pc = ON_PolylineCurve::Cast( ref.Curve() ); if( pc ) { vertices = pc->m_pline; } else { const ON_NurbsCurve* nc = ON_NurbsCurve::Cast( ref.Curve() ); if( nc ) nc->IsPolyline( &vertices ); } if( vertices.Count() < 5 ) { RhinoApp().Print( L"Curve not polygon with at least four sides.\n" ); return CRhinoCommand::nothing; } int* triangles = (int*)onmalloc( (vertices.Count()-3) * sizeof(int) * 3 ); if( 0 == triangles ) return CRhinoCommand::failure; // out of memory memset( triangles, 0, (vertices.Count()-3) * sizeof(int) * 3 ); int rc = RhinoTriangulate3dPolygon( vertices.Count()-1, 3, (const double*)vertices.Array(), 3, triangles); if( 0 == rc ) { int i; for( i = 0; i < vertices.Count()-3; i++ ) { ON_Polyline pline; pline.Append( vertices[triangles[i * 3]] ); pline.Append( vertices[triangles[i * 3 + 1]] ); pline.Append( vertices[triangles[i * 3 + 2]] ); pline.Append( pline[0] ); context.m_doc.AddCurveObject( pline ); } context.m_doc.Redraw(); } onfree( triangles ); return CRhinoCommand::success; }
RH_C_FUNCTION ON_SimpleArray<ON_Polyline*>* ON_Intersect_MeshMesh1(const ON_Mesh* pConstMeshA, const ON_Mesh* pConstMeshB, int* polyline_count, double tolerance) { ON_SimpleArray<ON_Polyline*>* rc = NULL; if( polyline_count ) *polyline_count = 0; if( pConstMeshA && pConstMeshB && polyline_count ) { ON_ClassArray<ON_MMX_Polyline> plines; ON_ClassArray<ON_MMX_Polyline> overlapplines; if(::ON_MeshMeshIntersect(pConstMeshA, pConstMeshB, plines, overlapplines, tolerance, tolerance)) { rc = new ON_SimpleArray<ON_Polyline*>(); for( int i=0; i<plines.Count(); i++ ) { ON_Polyline* pl = new ON_Polyline(); const ON_MMX_Polyline& mmxpoly = plines[i]; int c = mmxpoly.Count(); for( int j=0; j<c; j++ ) pl->Append(mmxpoly[j].m_A.m_P); pl->Clean(ON_ZERO_TOLERANCE); if( !pl->IsValid() ) { delete pl; continue; } rc->Append(pl); } for( int i=0; i<overlapplines.Count(); i++ ) { ON_Polyline* pl = new ON_Polyline(); const ON_MMX_Polyline& mmxpoly = overlapplines[i]; int c = mmxpoly.Count(); for( int j=0; i<c; i++ ) pl->Append(mmxpoly[j].m_A.m_P); pl->Clean(ON_ZERO_TOLERANCE); if( !pl->IsValid() ) { delete pl; continue; } rc->Append(pl); } *polyline_count = rc->Count(); } } return rc; }
int TriIntersections::Faces( ON_ClassArray<ON_3dPoint[3]> UNUSED(faces) ) { if (intersections.Count() == 0) { return 0; } /* first we get an array of all the segments we can use to make * our faces. */ ON_SimpleArray<ON_Line> segments; /*the segments we have to make faces */ ON_SimpleArray<bool> flippable; /* whether or not the segment has direction */ ON_SimpleArray<bool> segexternal; /* whether or not the segment is from the edge */ for (int i = 0; i < intersections.Count(); i++) { segments.Append(intersections[i]); segments.Append(intersections[i]); flippable.Append(false); flippable.Append(false); segexternal.Append(false); segexternal.Append(false); } for (int i = 0; i < 3; i++) { if (edges[i].Count() == 2) { /* the edge was never intersected */ segments.Append(ON_Line(edges[i][0], edges[i][0])); flippable.Append(true); segexternal.Append(true); } else { for (int j = 0; j < (edges[i].Count() - 1); j++) { if (dir[i][j] == dir[i][j + 1]) { /* this indicates an error in the intersection data */ return -1; } else if (dir[i][j] == 0 || dir[i][j+1] == 1) { segments.Append(ON_Line(edges[i][j], edges[i][j+1])); flippable.Append(false); segexternal.Append(true); } else { segments.Append(ON_Line(edges[i][j+1], edges[i][j])); flippable.Append(false); segexternal.Append(true); } } } } /* Now that the segments are all set up it's time to make them * into faces. */ ON_ClassArray<ON_Polyline> outlines; ON_SimpleArray<bool> line_external; /* stores whether each polyline is internal */ ON_Polyline outline; while (segments.Count() != 0) { outline.Append(segments[0].from); outline.Append(segments[0].to); segments.Remove(0); int i = 0; bool ext = false; /* keeps track of the ternality of the path we're assembling */ while (!outline.IsClosed(tol)) { if (i >= segments.Count()) { return -1; } else if (VNEAR_EQUAL(segments[i].from, outline[outline.Count() - 1], tol)) { outline.Append(segments[i].to); } else if (VNEAR_EQUAL(segments[i].to, outline[0], tol)) { outline.Insert(0, segments[i].from); } else if (VNEAR_EQUAL(segments[i].from, outline[0], tol) && flippable[i]) { outline.Insert(0, segments[i].to); } else if (VNEAR_EQUAL(segments[i].to, outline[outline.Count() - 1], tol) && flippable[i]) { outline.Append(segments[i].from); } else { i++; continue; } /* only executed when we append edge i */ segments.Remove(i); flippable.Remove(i); ext &= segexternal[i]; segexternal.Remove(i); i = 0; } outlines.Append(outline); line_external.Append(ext); } /* XXX - now we need to setup the ternality tree for the paths */ return 0; }