algorithmic modeling for Rhino
This might be an incredibly simple one.
Im looking to find all the perpendicular points on a curve from a given test point in a vb component.
Essentially, looking for the same result you would get from curve.closestpoint, but for all perpendicular conditions.
Is there a built in method for this?
Thanks,
David
Tags:
There's no out-of-the-box method for this. It is reasonably easy for polylines as you can approach it in a per-segment basis, but even there you need some conditional logic to reject segments without any perpendicular point. For curved curves it becomes quite a bit harder.
--
David Rutten
david@mcneel.com
Thanks David,
Good to know. The solution I'm looking for would be for both non linear curves and polylines. I didnt know if the method that Rhino's perp osnap uses was something accessible through Rhino Common. Looks like an interesting problem to dig deeper into on the weekend.
I think subdividing the curve into smaller elements and testing for perpendicularity is the way to go. You could first divide your curve into polylines using the curve.topolylines method with to determine where there are significant differences in curvature, and subdivide your curve at the kinks. Then do closest points for each segment, and if the vector to the center is perpendicular to the tangent along the curve, include it.
This won't capture all moments, I'm sure (arcs have the potential for infinite perp points), but it should help simplify the problem and focus the sampling on parts of the curve with the greatest variety.
Maybe like this...
Private Sub RunScript(ByVal P As Point3d, ByVal C As Curve, ByVal R As Double, ByRef PP As Object, ByRef PC As Object)
C.Domain = New Interval(0, 1)
Dim Pl As PolylineCurve = C.ToPolyline(0, 1, R, C.GetLength, 5, 0, 0, C.GetLength, True)
Dim t As New List(Of Double)
Dim SubSegs() As Curve = Pl.DuplicateSegments
Dim TestCrvs As New List(Of NurbsCurve)
Dim PerpPts As New List(Of Point3d)
For Each SubSeg As Curve In SubSegs
Dim ts, te As Double
C.ClosestPoint(SubSeg.PointAtStart, ts)
C.ClosestPoint(SubSeg.PointAtEnd, te)
If ts > te Then
TestCrvs.Add(C.ToNurbsCurve(New Interval(ts, 1)))
TestCrvs.Add(C.ToNurbsCurve(New Interval(0, te)))
Else
TestCrvs.Add(C.ToNurbsCurve(New Interval(ts, te)))
End If
Next
For Each TestC As NurbsCurve In TestCrvs
If TestC IsNot Nothing Then
Dim tt As Double
TestC.ClosestPoint(P, tt)
Dim TestP As Point3d = C.PointAt(tt)
If TestC.TangentAt(tt).IsPerpendicularTo(New Vector3d(TestP - P)) Then PerpPts.Add(TestP)
End If
Next
PP = PerpPts
PC = Pl
End Sub
It would be better to test the curve using the SpanCount and the Domain. Basically, you cut the curve domain into -say- 5*spancount subdomains and test each of those for closest-point, you have a sampling that is adaptive to the complexity of the curve.
--
David Rutten
david@mcneel.com
Ah. I am totally unfamiliar with spancount. I was thinking that by breaking the curve up by the tightest angles I'd isolate more bits that had a chance of being perpendicular. I'll look into spancount...sounds interesting.
Well that's easier:
Private Sub RunScript(ByVal P As Point3d, ByVal C As Curve, ByVal At As Double, ByRef PP As Object, ByRef PC As Object)
C.Domain = New Interval(0, 1)
Dim PerpPts As New List(Of Point3d)
Dim TestCrvs As New List(Of NurbsCurve)
At = At * (Math.PI / 180) 'angle tolerance
For SC As Int32 = 0 To C.SpanCount - 1
TestCrvs.Add(C.ToNurbsCurve(C.SpanDomain(SC)))
Next
For Each TestC As NurbsCurve In TestCrvs
If TestC IsNot Nothing Then
Dim tt As Double
TestC.ClosestPoint(P, tt)
Dim TestP As Point3d = C.PointAt(tt)
If TestC.TangentAt(tt).IsPerpendicularTo(New Vector3d(TestP - P), At) Then PerpPts.Add(TestP)
End If
Next
PP = PerpPts
PC = TestCrvs
End Sub
...although I see your point that the spans should probably then also be subdivided
The higher the degree of the curve, the more 'wiggles' a single span can have. The more wiggles, the more potential perpendicular or tangent solutions.
It's probably best to divide all spans into degree+2 or [degree*2] or something pieces.
Another approach is just to sample the curve at many intervals and only take an accurate look at a segment (irrespective of spans) if the sampling indicates a potential solution. That would probably be somewhat faster, but harder to code.
--
David Rutten
david@mcneel.com
Welcome to
Grasshopper
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
© 2024 Created by Scott Davidson. Powered by