Grasshopper

algorithmic modeling for Rhino

In a custom component, I need to avoid computing the entire code when a parameter changes. Is this possible?


Imagine that my code takes a long time to be computed, and I have a parameter (of points) which only affects the final phase of the code. Then I would like to change this parameter without rerun all pre and heavy code. Perhaps with a custom way to collect data parameter? or there is some method to this? or is it not possible? 

Changing the Phase property of the param I can avoid recompute the component, but in some moment I will need read that input, so it will be recomputed. I have nothing clear about the data collection cycle anyway.

Some clarification would be great.

Thanks.

Views: 1272

Replies to This Discussion

There's nothing in-build that will allow for this. You'll have to cache your own data and quickly re-assign it if you think the cache is still valid.

It is possible to read params manually using Params.Input[0].VolatileData or similar (this reads the 0th input). This then returns an IGH_Structure, giving you the slightly awkward task of deconstructing to access your data.

But this isn't the way I'd recommend, since it is up to components upstream as to whether your component gets expired and recomputes anyway. Changing the way you access the params isn't going to help you solve the problem.

As David says, I would create some class variables in your component to create a copy of your param data - the cache he said about. In your SolveInstance, use IGH_DataAccess DA to read your params into some local variables as usual. Then compare this with the data saved in your cache. Make sure your heavy calculations are wrapped inside an 'if' statement. You can use the comparison to decide whether you want to run the heavy calcs. You can then run the final phase as normal. Finally, make sure that your cache is up to date with the latest param data.

Thanks guys, I think I understand the logic. I still have not tried because I have gone another way. Now I have the same problem but with an output, I think that here the cache does not help me, no?. I'm still developing in vb script component.

I have a network of lines defined by a few points. When the script is executed, it returns in an output that network of curves in its default form. But then, arise in rhino some interactive grips (like a gumball but in a personalized way, using displayconduit), which are used to drag the position of the points (which define the curve network). So the problem is that I do not know how to get back the updated network in the output.

The role is something like:

Sub Runscript(...)

MiClase = new MyClass()

A = MiClase.Curves

end sub

'<Custom additional code> 

Dim MiClase as MyClass()

Public Class MyClass

(...)

End class

'<Custom additional code> 

So now the issue is, how I can resend data to the output? I already have the updated curves (because I can see him baking in rhino), I only need to get them out by the output.

I have to access the parameter and add the new data from within it? (addvolatiledata and this stuff) I've tried but without success.
Somehow I feel that I have no control over the execution process of the code, it's something that bothers me.


Is there any way to update the output without re-execute all?

Here is an example of the problem in a few lines of code.

Private Sub RunScript(ByVal x As Boolean, ByVal Ids As List(Of Guid), ByRef A As Object)

If x Then
BB = New BLABLA(ids)
A = BB.Curva
End If

End Sub

'<Custom additional code>

Dim BB As BlABLA


Public Class BLABLA
Public Curva As curve

Sub New(ids As list(Of guid))
Dim points As New list(Of point3d)
For Each id As guid In ids
Dim rh As rhinoobject = rhinodoc.ActiveDoc.Objects.Find(id)
Dim pt As Rhino.Geometry.Point = DirectCast(rh.Geometry, rhino.Geometry.Point)
If pt is Nothing Then Continue For
points.add(pt.Location)
Next
curva = curve.CreateInterpolatedCurve(points, 3)
End Sub

End Class

Attachments:

I meant, just update the curve output without rebuild the class. The event wich trigger the update is irrelevant here, it can be anything.

This file contains the code with an event based in timer, only to facilitate the help.

Private Sub RunScript(ByVal x As Boolean, ByVal Ids As List(Of Guid), ByRef A As Object)

If x Then
BB = New BLABLA(ids)
A = BB.Curva
Else
If BB IsNot Nothing Then BB.timer.Stop()
End If

End Sub

'<Custom additional code>

Dim BB As BlABLA


Public Class BLABLA
Public Curva As curve
Private Cache As list(Of point3d)
Private IDs As list(Of guid)

Sub New(_ids As list(Of guid))
IDs = _ids
Dim points As New list(Of point3d)
For Each id As guid In ids
Dim rh As rhinoobject = rhinodoc.ActiveDoc.Objects.Find(id)
Dim pt As Rhino.Geometry.Point = DirectCast(rh.Geometry, rhino.Geometry.Point)
If pt is Nothing Then Continue For
points.add(pt.Location)
Next
cache = points
curva = curve.CreateInterpolatedCurve(points, 3)
timer = New system.Windows.Forms.Timer
timer.Interval = 100
timer.Start()

End Sub

Public WithEvents timer As system.Windows.Forms.Timer

Private Sub Tick(sender As Object, e As System.EventArgs) Handles timer.Tick

For i As int32 = 0 To ids.count - 1
Dim rh As rhinoobject = rhinodoc.ActiveDoc.Objects.Find(ids(i))
Dim pt As Rhino.Geometry.Point = DirectCast(rh.Geometry, rhino.Geometry.Point)
If pt Is Nothing Then Continue For

If Not pt.Location.Equals(cache(i)) Then
UpdateOutput()

End If
cache(i) = pt.Location
Next
End Sub

Private Sub UpdateOutput()
'HERE I NEED UPDATE THE A OUTPUT
rhinoapp.WriteLine("Change")
End Sub

End Class

Attachments:

This seems to work..

Private Sub UpdateOutput()
rhinoapp.WriteLine("Updated")
Output.ClearData()
Output.AddVolatileDataList(New gh_path(0), curvas)
Output.CollectData()
Output.ComputeData()
Output.OnSolutionExpired(True)
End Sub

Isn't this normally done by splitting a program into separate Grasshopper script components?

Hi there,

I've tested several ways to achieve that. Mainly the "cache" solution and some "event based" solutions.

The matter with the event solution is that you need to proper register and unregister when a source is connected disconnected.  So fare I have not been able to make it work properly.

Listen to Source changes

this.Params.ParameterSourcesChanged += OnSourceChanged

Decide or not to listen to a given source

this.Params.Input[i].Sources[j].SolutionExpired

I have just remarked that when you enter SolveInstance "this.Params.Input[i].Sources[j].Phase" seems to be set to :

- "Computed" for each parameter that has changed during the recompute.

- "Collected" if it has not changed.

So that migth be a proper way to achieve this kind of behaviour. Each time you enter solve instance check for every Input Param and for every Source their Phase flag.

Lionel

Apparently this does not work the same for custom GH_Goo<T>.

Having such a flag on Input sources that would tell which inputs are part of the recompute and which are not would be very helpful.

I don't know if it makes sens for a future revision ...

Phase should be Blank if the parameter has expired, or Computed/Collected if it hasn't.

RSS

About

Translate

Search

Photos

  • Add Photos
  • View All

© 2021   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service