[python] Can't scale breps non-uniformly?

I was unable to scale a brep. And I can’t tell if it is a bug or by design. It was very unexpected, though. The code below did NOT work.

#! python 2
import Rhino.Geometry as rg
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc

pln = rg.Plane.WorldXY
ob = rg.Sphere(pln, 10).ToBrep()

xform = rg.Transform.Scale(pln, 1, 2, 1)
ob.Transform(xform)

sc.doc.Objects.AddBrep(ob)

I was pulling my hair out. But fortunately I somehow found the answer here.

So based on that, I was able to scale the sphere by converting it to a NurbsSurface and then converting it to a brep after the scaling operation. But, like I said, it was very unexpected that I couldn’t do a NU scale on a brep directly. And no errors thrown, either…it just refused to scale. In fact, iirc, at some point in time, I recorded the result of ob.Transform(xform) and got True back!

(working code below)

#! python 2
import Rhino.Geometry as rg
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc

pln = rg.Plane.WorldXY
ob = rg.Sphere(pln, 10).ToNurbsSurface()

xform = rg.Transform.Scale(pln, 1, 2, 1)
ob.Transform(xform)

ob = ob.ToBrep()

sc.doc.Objects.AddBrep(ob)

A sphere in Rhinocommon is not a BREP. It is it’s own structure, based on a plane and a radius. In order to do anything with it you will need to convert it to a BREP or some other kind of surface object. The same kind of thing is true with cylinder objects as well as line, polyline, arc, circle objects etc.

A sphere in Rhinocommon is not a BREP. It is it’s own structure, based on a plane and a radius.

Ok. I didn’t know that, but it makes sense, and that explains why the sphere object itself could not be scaled either, which I think I did try at some point. So, it’s helpful to know that for future coding.

But, keep in mind, in my example, I converted the sphere to a brep before attempting to scale it, and I couldn’t scale it. I had to convert it to a NurbsSurface as an intermediate step, scale it, and then convert it to a brep. (How would a polysurface be scaled? Are they broken into a group of surfaces, scaled and put back together?)

The truly confusing part was that when I called Brep.Transform(xform), it returned True as though it had successfully scaled it.

I’m really amazed that breps can’t be NU scaled directly (in code). Or, have I misunderstood something fundamental?

Hi @webdunce
since you’ve imported rhinoscriptsyntax easiest would be

    xform = rs.XformScale( (3.0,2.0,1.0) )
    rs.TransformObjects( objs, xform, True)

Yes, if you set a breakpoint on rs.TransformObjects and dig into Object.py you can check it out.

Jess

I guess I could have. In my actual code, I’m working with DrawOverlay and so I’ve generally avoided using rhinoscriptsyntax, but perhaps as long as I don’t use any of the AddWhatever() functions, maybe I could use it more than I do (in this project).

Basically, I’m trying to convert some of my grasshopper scripts to Eto forms with sliders (and it’s going surprisingly well, actually, at least with some of the simpler tools)

I agree, this is a bit of an oddity. sphere.ToBrep() does create a brep that can be scaled, but apparently not non-uniformly. If I run this:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

wxy=Rhino.Geometry.Plane.WorldXY
sph=Rhino.Geometry.Sphere(wxy,10.0)
sph_brep=sph.ToBrep()
sc.doc.Objects.AddBrep(sph_brep)
xform=Rhino.Geometry.Transform.Scale(wxy,2.0,1.0,1.0)
sph_brep.Transform(xform)
sc.doc.Objects.AddBrep(sph_brep)

I get two spheres, one with a radius of 10mm as created and the second (transformed) with a radius of 14.14 - i.e. uniformly scaled by the square root of 2 - instead of an ellipsoid that is 20mm on the X-axis and 10mm on the other two. Both of them are listed as surfaces of revolution in What. Funny, I can scale the original sphere in Rhino that way no problem, it is then automatically transformed into a NURBS surface.

The same happens if I use
xform=Rhino.Geometry.Transform.Scale(wxy,2.0,2.0,1.0)

If I put in all three numbers the same,
xform=Rhino.Geometry.Transform.Scale(wxy,2.0,2.0,2.0)
then it scales by 2, a sphere with a 20mm radius

Even more surprising - if i run this:
xform=Rhino.Geometry.Transform.Scale(wxy,2.0,1.0,2.0)
it also scales uniformly by 2.

I don’t understand why it works this way, makes no sense to me.

1 Like

Hi @webdunce ,

Look into using GeometryBase.IsDeformable and GeometryBase.MakeDeformable.

https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.geometrybase

— Dale

4 Likes

Thanks, Dale. Worked like a charm.

#! python 2
import Rhino.Geometry as rg
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc

pln = rg.Plane.WorldXY
ob = rg.Sphere(pln, 10).ToBrep()
r = ob.MakeDeformable()

if r:
    xform = rg.Transform.Scale(pln, 1, 2, 1)
    ob.Transform(xform)

    sc.doc.Objects.AddBrep(ob)
else:
    Rhino.RhinoApp.WriteLine("Nope! LOL!")

Thanks Dale!