Updating Rhino geometry via GUIDs

I’m trying to update the initially drawn curves in Rhino based on the output of a series of components that calculate new geometry. The curves are fed into Grasshopper through Geometry Pipelines to allow for users to quickly draw/edit/delete new curves on the Rhino canvas.

E.g.: the blue lines are solved positions based on the drawn black lines.

I’ve made a component that replaces the drawn curve with the corresponding new (blue) curve based on the input curve GUIDs (See below)… however, when I execute this component, the topology/positions of curves get crazy very quickly. I’ve verified that the list of GUIDs has not changed in order, and the order of the list of curves has not changed as well.

Is this something I can fix with delayed solutions/expiring solutions at the right time? I’m at a bit of a loss. Relevant code is below:

protected override void SolveInstance(IGH_DataAccess DA)
        {
            bool update = false;
            Network network = new Network();

            DA.GetData(0, ref update);
            if (!DA.GetData(1, ref network)) return;

            List <Guid> guids = network.Guids;
            var doc = RhinoDoc.ActiveDoc;

            if (update)
            {
                for (int i = 0; i < guids.Count; i++)
                {
                    Guid guid = guids[i];
                    Curve newcurve = network.Curves[i];

                    doc.Objects.Replace(guid, newcurve);
                }
            }
        }

would greatly appreciate some help!

Interestingly, this is not a problem when I simply use a curve component and manually select all curves.

However, this makes it not ideal for real-time design, where curves need to be added, deleted, moved on the fly.

But it does seem to be a problem unique to Geometry Pipelines–any ideas?

With a bit more thinking, I think my problem is a bit more clear to me, but the solution still evades me:

I’m trapped in a recursive loop where every time I update the upstream geometry, it triggers new calculations along the component chain until it reaches back to my Update component, where the order of curves start getting mixed up.

I think my problem can be solved if there is a way I can freeze all components while the update loop is still running, IE wait until all curves have been updated before notifying the rest of the components.

Is this an appropriate place to use a ScheduleSolution method? Or is there another way I can hide the curves from view until the update computation is complete?

As an update, I’ve managed an inelegant hack that works well by explicitly locking all Geometry Pipeline components before updating geometry, then unlocking:

protected override void SolveInstance(IGH_DataAccess DA)
        {
            bool update = false;
            Network network = new Network();
            //List<Guid> guids = new List<Guid>();

            DA.GetData(0, ref update);
            if (!DA.GetData(1, ref network)) return;
            //if (!DA.GetDataList(2, guids)) return;

            List <Guid> guids = network.Guids;
            var doc = RhinoDoc.ActiveDoc;

            //var ghdobjs = this.OnPingDocument().Objects;

            if (update)
            {
                //var oldcurve = doc.Objects.FindId(guids[i]);
                var ghdobjs = this.OnPingDocument().Objects;
                foreach (IGH_DocumentObject Obj in ghdobjs)
                {
                    if (Obj.NickName == "Pipeline")
                    {
                        GH_ActiveObject comp = (GH_ActiveObject)Obj;
                        comp.Locked = true;
                        comp.ExpireSolution(false);
                    }
                }
                for (int i = 0; i < guids.Count; i++)
                {
                    Guid guid = guids[i];

                    Curve newcurve = (Curve)network.Curves[i].Duplicate();

                    doc.Objects.Replace(guid, newcurve);

                }
                foreach (IGH_DocumentObject Obj in ghdobjs)
                {
                    if (Obj.NickName == "Pipeline")
                    {
                        GH_ActiveObject comp = (GH_ActiveObject)Obj;
                        comp.Locked = false;
                    }
                }

            }
        }

An error pops up saying a downstream component has expired during a solution, but ignoring the message has the update component performing flawlessly.

I’m clearly doing something sketchy, and would still love some insight on a more kosher way of doing things.

1 Like

I’m using EleFront for a similar process where I bake and overwrite geometry.