Hello,
I am trying to use Rhino Python (Version 7) to access and translate brep vertices. It seems like there is a RhinoCommon command to access the vertex list that returns BrepVertex objects. These objects have a Translate and Transform method. That is encouraging - it seems like the functionality is there.
But I am missing some piece of knowledge that will let me use these functions/methods on an existing brep surface. Could somebody please enlighten me on how I am supposed to use these methods in Python?
Hello,
That definitely changed the surface - but not the way I was hoping for. I think that I confused control points and vertices - I am out of my bubble on this project. Iām sorry about that. I didnāt intend to waste your time.
Using the RhinoScriptSyntax, I was able to access the rs.SurfacePoints of the surface (800+ in my case). These are the same control points I am used to seeing when pressing F10/F11. So far, so good. Then the script figured out a displacement for each control point. I have a list of displacements (and a list of surface normals if needed). But I cannot find any documentation on how to move the control points.
I think the brep.TransformComponent was doing something way more profound. It also creates many more control points and ābend neighbors to matchā which blows up the individual displacements.
Do you have any suggestions for moving the control points?
Sorry again for mixing up control points and vertices.
Some additional informationā¦ the āobject descriptionā of the surface displays this:
Geometry:
Valid surface.
trimmed surface.
NURBS Surface"U": degree =3 CV count = 23 (-82.2027 <= U <= 702.172)
āVā: degree =3 CV count = 36 (0 <= V <= 567.079)
Edge Tally:
6 boundary edges
Edge Tolerances: 0 to 0.0001
median = 0 average = 3.33333e-05
Vertex Tolerances: all 0
Render mesh: 1 mesh 1916 vertices 1933 polygons
Created with fast meshing parameters.
Analysis mesh: none present
I suspect the answer is in Rhino Common someplace, but I have close to zero luck finding examples or understanding the documentation. I see Rhino.Geometry.Collections.NurbsSurfacePointList that has methods that ~might~ move control points but no idea how to use that with an existing surface. A little frustrating.
Thank you Dale! I was able to move your code around a bit and make it work for my needs. Most examples here seem to use the interactive way of selecting objects and I have to find a way to make it non-interactive.
I pasted some code that worked for me and maybe will help somebody searching for this. Also look at the example scripts in the previous comment. One interesting thing is that the Add method of the TransformObjectList wanted an object reference instead of a GUID. Well, that is interesting for me because I though GUID was enough. Note that some methods return a list and I just wanted an object, so there are some [0] hiding here and there.
# For testing, just get direct references to the mesh and surface
TargetSurface = rs.ObjectsByName('upper')[0]
# Deselect everything and turn the grips on
rs.UnselectAllObjects()
rs.EnableObjectGrips(TargetSurface)
# The number of grips = rs.SurfacePointCount()
GripCount = rs.ObjectGripCount(TargetSurface)
# Return the GUID of grip number 10 (for example)
rs.SelectObjectGrip(TargetSurface, 10)
SelectedGrip = rs.SelectedObjects(False, True)
# To add the grip to the TransformObjectList, it needs an ObjRef not GUID
GripReference = Rhino.DocObjects.ObjRef(SelectedGrip[0])
ObjectList = Rhino.Collections.TransformObjectList()
ObjectList.Add(GripReference)
# Transformation +20mm in Z direction
Direction = Rhino.Geometry.Vector3d(0.0, 0.0, 20.0)
Transform = Rhino.Geometry.Transform.Translation(Direction)
# Move the grip
TheGrip = ObjectList.GripArray()[0]
TheGrip.Move(Transform)
# Let the owner of the grip (surface?) know it was moved
GripOwner = ObjectList.GripOwnerArray()[0]
sc.doc.Objects.GripUpdate(GripOwner, True)
# May be needed, maybe not
sc.doc.Views.Redraw()
If you stumble on this post looking for a solution, there is another post below that looks promising. I could not figure out how to get a Rhino.Geometry.NurbsSurface object from an existing NURBS surface. If you find a way (without using an interactive dialog box) please post it. Thank you! However, the code above should also work.
I already have a existing surface, and I get the GUID of that surface using this: TargetSurface = rs.ObjectsByName('upper')[0]
In practice, there will be a better method of selecting the surface but this works for testing.
In the other post, the person used this command: Control_Points = Rebuilt_Surface.Points
where RebuiltSurface is a Rhino.Geometry.NurbsSurface object. So to follow his example I need one of those type of objects. Admittedly, the Rhino Common documentation is not intended for me as an amature Python programmer. I couldnāt find a way to create NurbsSurface object from my existing nurbs surface. That sounds silly when you read it, but I hope it is clear. There is no constructor that accepts a GUID from a nurbs surface.
I think this is a problem of crossing the bridge from the rs module to the Rhino module. There is some skill to go across that bridge and I donāt have it mastered.
All rs methods work with object ids. To access things in RhinoCommon, itās best to work with Rhino objects, from them you can access the Id, ObjectAttributes or the Geometry. Having an Id, you might use one of the rs.coerce... methods to directly access what you need.
Well, the history behind this is that originally these methods were intended as internal-use utility tools - which are actually called by many other rhinoscriptsyntax methods. But then they became more or less public and people outside McNeel started using them.
Basically any ācoerceā¦ā method tries to convert one of several possible input data types into the desired output type. If it succeeds, the correct object type is output, it it fails, you get None or a slightly more descriptive error message if the āraiseā flag is set to True.
If you know how to read Python/RhinoCommon code, you can look them up here and see what they are actually doing. C:\Users\<username>\AppData\Roaming\McNeel\Rhinoceros\(7.0 or 8.0)\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rhinoscript\utility.py
It is possible to do without the coerce functions, one simply has to first determine the data input type (GUID, string, etc.) and then use the appropriate method to get the RhinoCommon object. For example in the case of a GUID of an object that is in the document, one can use
obj=scriptcontext.doc.Objects.FindId(GUID)
The advantage of using the coerceā¦ methods is that one does not need to figure out what the input data type is in advance.
Yes, I can appreciate the issues of allowing the public to flood in and see RhinoCommon interfaces. Instead of an audience of professional developers, now there are people like me looking around.
Iāve been able to piece together the bits and pieces that I neededā¦ but the pieces are scattered around various forum posts. Including the obj=scriptcontext.doc.Objects.FindId(GUID) that you mentioned above.
I do think that enough time has passed that a proper guide should be written. It would have helped me a lot and would probably help other people using the software.