subD control Points in Grasshopper

I’m new in rhino and I have to design a fish-like robot… I just develop the shape of the body fish in rhino with subD object and now i would like to optimize the shape with grasshopper by moving control points of the subD.
Is there any command that allows to perform this task?

1 Like

Hi @Nicolas5 ,

I think you’ll find the answers you are looking for in this previous thread:

Thanks Pierre. I try to implement the code in my grasshopper file, but it doesnt’t allow me to pick the subD. Is there any way to solve the task without passing through Python? My idea is to introduce some sliders in order to move control Points, so that I can use optimization tools such as Galapagos.

I managed to get the program to run, but I don’t quite understand how to select a specific vertex. Can you help me?

Hi @Nicolas5

Python is going to be a lot easier here, Grasshopper does not have the required components to set SubD or meshes vertices locations.

Here is a file with 4 different ways to set vertices in a SubD, using Python or just Grasshopper components. If you will be changing all control net points in your SubD, the first row will be the fastest; if you are only modifying some of them the second row might have be faster.

DI-142349.gh (47.6 KB)

The rows 3 and 4 try to do this using as little Python as possible, and it gets huge really quickly. The SubD needs to be turned into a mesh, the mesh is edited, SubD reconstructed from the mesh and vertices and edges tags are set again. Highly recommend you go the Python route.

Grasshopper does not have references to subobject, so you need to find another so track them. You could either use the vertex indices if you know them, or find the vertex indices for the closest vertices to a list of points that are tracked in GH.

If you do the latter, note that SubD vertex indices are not guaranteed to be in order 1, 2, 3, 4, etc… So in GH, you need to find the closest vertex to a point, get the list index of that vertex in the SubD vertex list, and get the vertex index in the SubD vertex index list at the same list index. The 4th option in my example file above does that.

Hope this helps,
Pierre

4 Likes

Hi. That’s a nice Python solution. Is it possible to use similar approach but for “edit points” instead of “control polygon points”? I noticed that there’s it’s possible to do so in Rhino, but not sure how to use that using Python. Any hint appreciated, thanks!

Hi @PetrVacek ,

There is a C# sample available to modify edit points in a SubD:

A Python version could use all the same RhinoCommon methods.

The caveat is that it will interpolate all limit surface points of the SubD at the same time, without any control on fixed control points. RhinoCommon access to an interpolator with more granular control is work that we plan to do during the Rhino 8 release cycle and tracked here: RH-59542 Allow for getting and setting SubD “edit” points using RhinoCommon.

1 Like

Sharing for anyone to use and improve:

File:
230718_SubD_CS_Manipulator.gh (21.9 KB)

Component to get “Surface Points” (“Edit Points”, but for SubD):

IGH_Param output = this.Component.Params.Output[1];
IGH_PreviewObject param = output as IGH_PreviewObject;
param.Hidden = true;

List < Point3d > editPoints = new List<Point3d>();
List < Point3d > controlPoints = new List<Point3d>();
List < uint > ids = new List< uint >();
SubDVertex vert = S.Vertices.First;

for(int i = 0;i < S.Vertices.Count;i++)
{
  editPoints.Add(vert.SurfacePoint());
  controlPoints.Add(vert.ControlNetPoint);
  ids.Add(vert.Id);
  vert = vert.Next;
}

E = editPoints;
C = controlPoints;
I = ids;

Component to manipulate existing SubD using “Surface Points” rather than “Control Points”:

if (!(I.Count == V.Count))
{
  throw new IndexOutOfRangeException("Vectors and indexes count differs.");
}
else
{
  if (S is SubD)
  {
    SubD newSubD = S.Duplicate() as SubD;

    if (newSubD != null)
    {
      List<Point3d> surfacePts = new List<Point3d>();
      List<uint> subdVertIds = new List<uint>();

      SubDVertex vertex = S.Vertices.First;
      for(int i = 0; i < S.Vertices.Count; i++)
      {
        int vertexId = Convert.ToInt32(vertex.Id);
        if(I.Contains(vertexId))
        {
          int itemId = I.IndexOf(vertexId);
          surfacePts.Add(vertex.SurfacePoint() + V[itemId]);
        }
        else
        {
          surfacePts.Add(vertex.SurfacePoint());
        }
        vertex = vertex.Next;
      }

      if (newSubD.InterpolateSurfacePoints(surfacePts.ToArray()))
      {
        R = newSubD;
      }
    }
  }

RH-76637 is fixed in the latest WIP