algorithmic modeling for Rhino
Hello everyone,
I'm looking for a VB script that does the same as the Sort Points Along Curve component.
I have written a simple sorting script:
Function sort_points_along_curve(ByVal points_list As List(Of Point3d), ByVal sorting_curve As Curve) As List(Of Point3d)
points_list.Sort(
Function(point1, point2)
Dim point1_t As Double, point2_t As Double
sorting_curve.ClosestPoint(point1, point1_t)
sorting_curve.ClosestPoint(point2, point2_t)
Return point2_t.CompareTo(point1_t)
End Function)
Return points_list
End Function
But I would also like to remember the original order of the points. The component outputs a 'point index map' which holds the original order.
How can I create such a point index map in VB?
(And I cannot compare the newly sorted points to the originals, because a lot of points are in the same location.)
Thank you for any feedback!
Tags:
Hi Fernando,
something like that?
(first number = unsorted index, second number = sorted index)
I use Linq:
Dim getT = Function(pt As Point3d)
Dim t As Double
curve.ClosestPoint(pt, t)
Return t
End Function
Dim map = points.Select(Function(pt, i) New With {.T = getT(pt), .Index = i}) _
.OrderBy(Function(p) p.T) _
.Select(Function(p, i) New With {.T = p.T, .OldIndex = p.Index, .NewIndex = i}) _
.OrderBy(Function(p) p.OldIndex) _
.Select(Function(p) p.NewIndex) _
.ToList()
Hi TJO,
Thank you so much, that is perfect!
I've never worked with Linq, but I have experience with writing sql queries, it's pretty much the same. It opens up so much possibilities for me, Grasshopper keeps getting better and better!
Just to be clear, you wrote:
map = points.Select(Function(pt, i) New With {.T = GetT(pt, curve), .Index = i}) _
.OrderBy(Function(pair) pair.T) _
.Select(Function(pair, i) New With {.OldIndex = pair.Index, .NewIndex = i}) _
.OrderBy(Function(p) p.OldIndex) _
.Select(Function(p) p.NewIndex).ToList()
instead of:
map = points.Select(Function(pt, i) New With {.T = GetT(pt, curve), .Index = i}) _
.OrderBy(Function(pair) pair.T) _
.Select(Function(p) p.Index).ToList()
because that extra part takes duplicate points into account, and makes sure that the original order is kept, right?
Thank you very much!
I'm glad I could help!
You are right! The additional lines are restoring the original order of the points. Duplicate points should not make problems anyway. They keep their relative position.
I know that TJO solved your problem in a really cool 1 line code... but it kind of flew over my head so I just wanted to add my 2 cents and show the same solution without functions and on multiple lines
Private Sub RunScript(ByVal points As List(Of Point3d), ByVal curve As Curve, ByRef map As Object)
Dim nA(points.Count-1) As int32
Dim tA(points.Count-1) As int32
For i As int32 = 0 To points.Count - 1
Dim t As New Double
curve.ClosestPoint(points(i), t)
nA(i) = i
tA(i) = t
Next
Array.Sort(tA, nA)
map = nA
Hi Andy!
Of course you can use Array.Sort(). Don't forget to sort the points back:
Dim n = points.Count()
Dim unorderedIndices(n - 1) As Integer
Dim orderedIndices(n - 1) As Integer
Dim t(n - 1) As Double
For i As Integer = 0 To n - 1
curve.ClosestPoint(points(i), t(i))
unorderedIndices(i) = i
orderedIndices(i) = i
Next
Array.Sort(t, unorderedIndices)
Array.Sort(unorderedIndices, orderedIndices)
To get the ordered position of point i you can call: orderedIndices(i)
and you can get the parameter of point i by calling t(orderedIndices(i))
Thanks Andy and TJO!
© 2021 Created by Scott Davidson. Powered by