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: 1029

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

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!

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service