Grasshopper

algorithmic modeling for Rhino

Is there a VB equivalent to Sort Points Along Curve with point index map?

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!

Views: 865

Replies to This Discussion

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()

Attachments:

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()

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!

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!

• View All