/** * checks whether two Polylines are inside one another. * * XXX It's the caller's responsibility to make sure the polylines are * coplanar. * * Returns: * 1 if the first is inside the second * -1 if the second is inside the first * 0 if the two intersect at some point or one of them isn't closed */ int PolylinePolylineInternal( ON_Polyline P, ON_Polyline Q, double tol ) { int i; for (i = 0; i < P.Count(); i++) { if (!PointInPolyline(P[i], Q, tol)) { break; } } if (i == P.Count()) { return 1; } for (i = 0; i < Q.Count(); i++) { if (!PointInPolyline(Q[i], P, tol)) { break; } } if (i == Q.Count()) { return -1; } else { return 0; } }
CRhinoCommand::result CCommandSamplePolyline::RunCommand( const CRhinoCommandContext& context ) { CRhinoCommand::result rc = CRhinoCommand::nothing; ON_Polyline pline; if( context.IsInteractive() ) { // Our way... CGetPolylinePoints gp; int count = gp.GetPoints(); if( count > 1 ) { pline = gp.m_point_array; if( pline.IsValid() ) rc = CRhinoCommand::success; } } else { // The Rhino way... CArgsRhinoGetPolyline args; args.SetFirstPointPrompt( L"Start of polyline" ); args.SetSecondPointPrompt( L"Next point of polyline" ); rc = RhinoGetPolyline( args, pline ); } if( rc == CRhinoCommand::success ) { context.m_doc.AddCurveObject( pline ); context.m_doc.Redraw(); } return rc; }
CRhinoCommand::result CCommandTestCustomGrips::RunCommand( const CRhinoCommandContext& context ) { ON_3dPoint rect[5]; CArgsRhinoGetPlane args; args.SetCornerMode( CArgsRhinoGetPlane::mode_corners ); args.SetAllowRounded( FALSE ); args.SetAllowDeformable( FALSE ); CRhinoCommand::result rc = RhinoGetRectangle( args, rect ); if( rc == CRhinoCommand::success) { ON_Polyline pline; rect[4] = rect[0]; pline.Create( 3, FALSE, 5, 3, (double*)&rect ); ON_PolylineCurve* pline_curve = new ON_PolylineCurve( pline ); CRhinoRectangleObject* rect_object = new CRhinoRectangleObject(); rect_object->SetCurve( pline_curve ); if( context.m_doc.AddObject(rect_object) ) context.m_doc.Redraw(); else delete rect_object; } return CRhinoCommand::success; }
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 void ON_Intersect_MeshPlanes3(ON_SimpleArray<ON_Polyline*>* pPolylines, int i, int point_count, /*ARRAY*/ON_3dPoint* points) { if( NULL==pPolylines || i<0 || i>=pPolylines->Count() || point_count<0 || NULL==points || NULL==*points) return; ON_Polyline* polyline = (*pPolylines)[i]; if( NULL==polyline || polyline->Count()!=point_count ) return; const ON_3dPoint* source = polyline->Array(); ::memcpy(points, source, sizeof(ON_3dPoint) * point_count); }
// return number of points in a certain polyline RH_C_FUNCTION int ON_Intersect_MeshPlanes2(ON_SimpleArray<ON_Polyline*>* pPolylines, int i) { int rc = 0; if( pPolylines && i>=0 && i<pPolylines->Count() ) { ON_Polyline* polyline = (*pPolylines)[i]; if( polyline ) rc = polyline->Count(); } return rc; }
void CRhinoRectangleGrips::Draw( CRhinoDrawGripsSettings& dgs ) { UpdateRectangle(); if ( m_bDrawRectangle && dgs.m_bDrawDynamicStuff ) { const int count = m_rectangle.Count(); const ON_3dPoint* P = m_rectangle.Array(); int i; for( i = 1; i < count; i++ ) dgs.m_vp.DrawLine( P[i-1],P[i] ); } CRhinoObjectGrips::Draw(dgs); }
bool PointInPolyline( const ON_3dPoint& P, const ON_Polyline pline, double tol ) { if (!pline.IsClosed(tol)) { /* no inside to speak of */ return false; } /* First we need to find a point that's in the plane and outside the polyline */ ON_BoundingBox bbox; PolylineBBox(pline, &bbox); ON_3dPoint adder; int i; for (i = 0; i < pline.Count(); i++) { adder = P - pline[i]; if (!VNEAR_ZERO(adder, tol)) { break; } } ON_3dPoint DistantPoint = P; int multiplier = 2; do { DistantPoint += adder*multiplier; multiplier = multiplier*multiplier; } while (bbox.IsPointIn(DistantPoint, false)); bool inside = false; int rv; ON_3dPoint result[2]; for (i = 0; i < pline.Count() - 1; i++) { rv = SegmentSegmentIntersect(P, DistantPoint, pline[i], pline[i + 1], result, tol); if (rv == 1) { inside = !inside; } else if (rv == 2) { bu_exit(-1, "This is very unlikely bug in PointInPolyline which needs to be fixed\n"); } } return inside; }
int PolylineBBox( const ON_Polyline& pline, ON_BoundingBox* bbox ) { ON_3dPoint min = pline[0], max = pline[0]; for (int i = 1; i < pline.Count(); i++) { VMINMAX(min, max, pline[i]); } bbox->m_min = min; bbox->m_max = max; return 0; }
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; }
/** * uses iteration of SegmentSegmentIntersect. * * returns the number of intersections it finds */ int SegmentPolylineIntersect( const ON_3dPoint& P, const ON_3dPoint& Q, const ON_Polyline& pline, ON_SimpleArray<ON_3dPoint> out, double tol ) { int rv = 0; int my_rv = 0; /* what this function will return at the end */ ON_3dPoint result[2]; for (int i = 0; i < (pline.Count() - 1); i++) { rv = SegmentSegmentIntersect(P, Q, pline[i], pline[i+1], result, tol); if (out) { /* the output field can be made null to use the function to check for intersections but not return them */ for (int j = 0; j < rv; j++) { out.Append(result[j]); } } my_rv += rv; } return my_rv; }
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; }
void CRhinoRectangleGrips::UpdateRectangle() { if ( m_bNewLocation ) { // Update rectangle from grip locations int i; m_rectangle.Reserve(5); m_rectangle.SetCount(5); // If anything moved this time, the ones that didn't move will // be inactive for the rest of the drag for ( i = 0; i < 8; i++ ) { if ( m_rectangle_grips[i].m_bActive && m_rectangle_grips[i].GripMoved() ) { for ( i = 0; i < 8; i++ ) { if ( !m_rectangle_grips[i].GripMoved() ) m_rectangle_grips[i].m_bActive = false; } break; } } // first check corners for ( i = 0; i < 8; i += 2 ) { if ( m_rectangle_grips[i].m_bActive && m_rectangle_grips[i].GripMoved() ) { // if corner moves, middles are inactive for this drag m_rectangle_grips[(i+1)%8].m_bActive = false; m_rectangle_grips[(i+7)%8].m_bActive = false; } } // second check middles for ( i = 1; i < 8; i += 2 ) { if ( m_rectangle_grips[i].m_bActive && m_rectangle_grips[i].GripMoved() ) { // if middle moves, corners are inactive for this drag m_rectangle_grips[(i+1)%8].m_bActive = false; m_rectangle_grips[(i+7)%8].m_bActive = false; } } // double x0 = m_rectangle[0].x; if ( m_rectangle_grips[0].m_bActive && m_rectangle_grips[0].GripMoved() ) x0 = m_rectangle_grips[0].GripLocation().x; else if ( m_rectangle_grips[6].m_bActive && m_rectangle_grips[6].GripMoved() ) x0 = m_rectangle_grips[6].GripLocation().x; else if ( m_rectangle_grips[7].m_bActive && m_rectangle_grips[7].GripMoved() ) x0 = m_rectangle_grips[7].GripLocation().x; double x1 = m_rectangle[2].x; if ( m_rectangle_grips[4].m_bActive && m_rectangle_grips[4].GripMoved() ) x1 = m_rectangle_grips[4].GripLocation().x; else if ( m_rectangle_grips[2].m_bActive && m_rectangle_grips[2].GripMoved() ) x1 = m_rectangle_grips[2].GripLocation().x; else if ( m_rectangle_grips[3].m_bActive && m_rectangle_grips[3].GripMoved() ) x1 = m_rectangle_grips[3].GripLocation().x; double y0 = m_rectangle[0].y; if ( m_rectangle_grips[0].m_bActive && m_rectangle_grips[0].GripMoved() ) y0 = m_rectangle_grips[0].GripLocation().y; else if ( m_rectangle_grips[2].m_bActive && m_rectangle_grips[2].GripMoved() ) y0 = m_rectangle_grips[2].GripLocation().y; else if ( m_rectangle_grips[1].m_bActive && m_rectangle_grips[1].GripMoved() ) y0 = m_rectangle_grips[1].GripLocation().y; double y1 = m_rectangle[2].y; if ( m_rectangle_grips[4].m_bActive && m_rectangle_grips[4].GripMoved() ) y1 = m_rectangle_grips[4].GripLocation().y; else if ( m_rectangle_grips[6].m_bActive && m_rectangle_grips[6].GripMoved() ) y1 = m_rectangle_grips[6].GripLocation().y; else if ( m_rectangle_grips[5].m_bActive && m_rectangle_grips[5].GripMoved() ) y1 = m_rectangle_grips[5].GripLocation().y; m_rectangle[0].x = m_rectangle[3].x = x0; m_rectangle[1].x = m_rectangle[2].x = x1; m_rectangle[0].y = m_rectangle[1].y = y0; m_rectangle[2].y = m_rectangle[3].y = y1; m_rectangle[4] = m_rectangle[0]; // apply rectangular constraints to grip locations ON_Line L; for ( i = 0; i < 4; i++ ) { int gi = 2*i; L.from = m_rectangle[i]; L.to = m_rectangle[i+1]; m_rectangle_grips[gi].SetPoint( L.from ); m_rectangle_grips[gi+1].SetPoint( 0.5*L.from + 0.5*L.to ); } m_bDrawRectangle = true; m_bNewLocation = false; } }