Duplicate, Untrim and Extend sub-object surface from GetObject

I’m using Rhino.Input.Custom.GetObject() with a filter for Surface and with sub objects allowed, and it seems to work.

However, the results from the Objects() seems to be either Surface or PlaneSurface in my use cases, and both of those have Duplicate and Extend (but not Untrim?)… in either case, I don’t understand how to run those methods regardless of the object type:

	go = Rhino.Input.Custom.GetObject()
	go.SetCommandPrompt("Select two surfaces")
	go.AlreadySelectedObjectSelect = True
	go.SubObjectSelect = True
	go.GeometryFilter = Rhino.DocObjects.ObjectType.Surface
	go.GetMultiple(2, 2) # Ensure the user selects two objects

	if go.CommandResult() != Rhino.Commands.Result.Success:
		print("Command result was unsuccessful")
		return

	s1 = go.Objects()[0]
	s2 = go.Objects()[1]

	d1 = s1.Duplicate()
	d2 = s2.Duplicate()

What am I missing and why is there no Untrim?

You are missing several things

The s1 and s2 are not surfaces - They are Type ObjectRef

ObjectRef is a reference to an object. To get the object you need:
s1=go.Objects()[0].Object()

That should give you a BrepObject (you may want to do a type check to make sure).

To get the underlying Brep you need call the brepobject’s BrepGeometry. That will give you the Brep which should have just one face. To get down to the BrepFace you need to do something like this.

brepface= s1.BrepGeometry.Faces[0]

The brepface is a surface with trimming. To get the untrimmed surface you will need:

surface=brepface.UnderlyingSurface()

1 Like

Right, so that’s why I was trying to avoid adding .Surface() or .PlaneSurface() since they could be either (I’m very much not a coder). :sweat_smile:

Oh, wow, thank you! I didn’t know it went that deep! :pray:

So, now I tried this (which I checked apparently results in a NurbsSurface):

	s1 = go.Objects()[0].Object().BrepGeometry.Faces[0].UnderlyingSurface().Duplicate()
	s2 = go.Objects()[1].Object().BrepGeometry.Faces[0].UnderlyingSurface().Duplicate()

	c1 = s1.PointAt(0.5,0.5)
	c2 = s2.PointAt(0.5,0.5)


	print("{}".format(c1))
	print("{}".format(c2))

And I get no errors, but also no duplicates. Yet I do get seemingly correct center points.

Again, if someone please could let me know what I’m missing?

I’m not following what you are trying to accomplish with duplicates.

It looks to me like you do have the duplicates that the script made (s1 and s2). What you don’t have is the originals, but technically speaking, the originals would also be duplicates of 2 surfaces in the document. You should be able to get the same points c1 and c2 if you just delete the call to .Duplicate().

Well, unfortunately not only do I not know the syntax, but also apparently not the terminology.

I thought .Duplicate() would leave me with a copy in the 3D viewport, like what you do with the DupEdge command (or copy & paste).

Since I want to try to do .Extend() on them as well, I wanted to make sure that I didn’t do it on the original surfaces but rather duplicates of them (also, I’d like to see what the heck I’m doing). :laughing:

EDIT: Just noticed that even this sometimes still yields a PlaneSurface and not always a NurbsSurface as I thought… can this line be altered in a way to force it to always be a NurbsSurface? Would make the script easier…

s1 = go.Objects()[0].Object().BrepGeometry.Faces[0].UnderlyingSurface()

EDIT: Oh, also the above line is WRONG in that it doesn’t not access the sub-object I thought I’d selected, but whatever the first sub-object in the polysurface I happened to make the sub-object selection from! How can I get the actual single surface I selected in my viewport, regardless if it was a sub-object or not, and regardless if it’s a PlaneSurface or a NurbsSurface?

EDIT: This might be more accurate?

	s1 = go.Objects()[0].Surface().UnderlyingSurface().ToNurbsSurface()

No but how would one know? Its not as if the documentation tells you exactly what it does.

You already have a duplicate no need to create one. To do what you want the surface has to be made into a Brep and then the Brep added to the document through the ObjectTable. Seeing what you are doing in real time is complicated. It involves creating a display pipeline. I’ve never done that but I expect you can search the forum and find examples.

Extending is likely to be complicated also. First you will need to get the edge the user wants to extend.

Yup sorry, I misled you. When you query the ObjRef you should not call
go.Objects()[0].Object(). That gives you the top level object. Instead call go.Objects()[0].Face() that gives you just the face you want.

This code should add an untrimmed version of the face to the document

from __future__ import print_function
import Rhino
import Rhino.Geometry as rg

def get():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select two surfaces")
    go.AlreadySelectedObjectSelect = True
    go.SubObjectSelect = True
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Surface
    go.GetMultiple(2, 2) # Ensure the user selects two objects
    
    if go.CommandResult() != Rhino.Commands.Result.Success:
    	print("Command result was unsuccessful")
    	return
    
    brepface1 = go.Objects()[0].Face()
    brepface2 = go.Objects()[1].Face()

    surface1=brepface1.UnderlyingSurface()
    surface2=brepface2.UnderlyingSurface()
    
    id1=do.AddBrep(surface1.ToBrep())
    id2=do.AddBrep(surface2.ToBrep())
    
    
AD=Rhino.RhinoDoc.ActiveDoc;  do= AD.Objects    
get()
1 Like