Geometry.Scale in Python

Hello Dynamo Friends :slight_smile:

I want to scale a solid (Dynamo solid and Revit Solid) in python.

There are so many methods and nodes in dynamo:

But i can´t find anything on RevitApiDocs or google on how to use such methods in python.
Is it possible to use these in python?

Happy about any advice :slight_smile:

Assuming you have loaded the Dynamo geometry library into Python (the standard Python template in Dynamo for Revit will do this for you), and you have defined your geometryVariable, xAmount, yAmount, and zAmount you can use this line to scale Dynamo geometry:
scaledUp = Geometry.Scale(geometryVariable, xAmount, yAmount, zAmount)

Revit geometry scaling is a bit more complex, as it requires the use of a transform, which can be created via this method: ScaleBasis Method

Once you have created the transform object, you can then utilize it on the REvit geometry object. I believe this method should work for that: GetTransformed Method

Note that this will not manipulate existing elements; You’ll have a LOT more to do if that’s what you’re after.

4 Likes

Oh it´s that easy, that works!

for l in List:
	scaledUp = Geometry.Scale(l, 2, 2, 2)

Will look into that transform method, this will keep me busy some time for sure.

Thanks Jacob!

Edit:

Scaling with basepoint/plane also works fine:

for l in List:
	scaledUp = Geometry.Scale(l, plane, 2, 2, 2)
1 Like

This is one of the reasons I like the “nodes > design script > python” progression. The class.method(override1,override2) syntactic which is present in Design Script and the Dynamo node library is directly related to how you write it in Python. If you’re not sure of the DesignScript method, you can utilize node to code as well to really help facilitate the progression. :slight_smile:

Because of this you need not worry so much about the constructors/methods/properties, and can instead focus on learning the context specific stuff in Python (ie: your for loop, or list comprehension which would be scaledUp = [Geometry.Scale(l, plane, 2,2,2) for l in geometryList]).

2 Likes

Hello,
surely it is still too early for me to access python but how to manage a double for to have 5 scaled spheres not changing place

In the idea I wanted to put Planes[s] but does not work

# Charger les bibliothèques DesignScript et Standard Python
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Les entrées effectuées dans ce noeud sont stockées sous forme de liste dans les variables IN.
Solides=IN[0]
Planes=IN[1]
r=[]

# Placer votre code au-dessous de cette ligne
z=len(Solides)
for s in Solides:
	r.append(Geometry.Scale(s,Planes[0],0.5,0.5,0.5))

# Affectez la sortie Ă  la variable OUT.
OUT = r,z

# Charger les bibliothèques DesignScript et Standard Python
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Les entrées effectuées dans ce noeud sont stockées sous forme de liste dans les variables IN.
Solides=IN[0]
Planes=IN[1]
r=[]

# Placer votre code au-dessous de cette ligne
z=len(Solides)
for s in Solides:
	for t in Planes:
		r.append(Geometry.Scale(s,t,0.5,0.5,0.5))

# Affectez la sortie Ă  la variable OUT.
OUT = r,z

thanks in advance
Cordially
christian.stan

I´m nearly there to transform my Revit.DB.Solids but out of ideas.
Creating Transform seems to work, but i can´t apply it…

transf = Transform.Identity
transf.Origin = center
transf = transf.ScaleBasis(2)

scaled= Geometry.GetTransformed(x,transf)

→ object has no attribute “GetTransformed”

transf = Transform.Identity
transf.Origin = center
transf = transf.ScaleBasis(2)

scaled= x.GetTransformed(transf)

→ object has no attribute “GetTransformed”

Lists of equal length can be zip´ed together.

Spheres=IN[0]
Centers=IN[1]
outlist=[]

for Sphere, Center in zip(Spheres,Centers):
	scaledsphere = Geometry.Scale(Sphere,Center,0.5,0.5,0.5)
	outlist.append(scaledsphere)
	
OUT = outlist

Using the Python zip() Function for Parallel Iteration – Real Python

1 Like

Thanks for the additional explanation.
:wink:

cordially
christian.stan

You can use SolidUtils.CreateTransformed(solid, transform)

1 Like

Yes i can! :smiley: Thank you viktor!

Still one issue with my method because the scaled solid is landing far away from the original one, but basically it works.

center = UnwrapElement(IN[1])

transf = Transform.Identity
transf.Origin = center
transf = transf.ScaleBasis(2)

scaled = SolidUtils.CreateTransformed(x, transf)

OUT = scaled

happy to help :slight_smile:
You can try getting your original solid’s centroid and set the Transform’s origin to it before creating the transformed version.
edit: Now I saw that you have done that

1 Like

I can´t get it to work :confused:
It seems like this transforming is happening in a different coordinatesystem, because when i use the transform.origin method the new solid is landing far away.

The transform basis property says:

Defines the basis of the old coordinate system in the new coordinate system."

So maybe i dont have to only set the origin but also the coordinatesystem basis?

I tried my luck, but dont understand whats this index is about:

image

t = Transform.Identity
t = t.Basis(0, center)
t = t.ScaleBasis(2)

scaled = SolidUtils.CreateTransformed(x, t)

I also tried the scale.BasisAndOrigin Method but that didn´t help.

Any ideas what i can try?

hmm, the whole thing does´nt work, see how the position of the origin is also “scaled”.

Using 0,0,0 as origin.

[video-to-gif output image]

By making a second transform and creating another copy of my solid i managed to set an origin and now the solid won´t jump around anymore. But it is placed at 0,0,0 and i can´t get it to the position of the original solid…

[video-to-gif output image]

x = UnwrapElement(IN[0])
t = Transform.Identity
t = t.ScaleBasis(4)

scale = SolidUtils.CreateTransformed(x, t)
y=scale.ComputeCentroid()

xvalue = -y.X
yvalue = -y.Y
zvalue = -y.Z

z = Transform.Identity
z.Origin = XYZ(xvalue,yvalue,zvalue)
scale2 = SolidUtils.CreateTransformed(scale, z)
OUT = scale2

There might be a better way, but you can move the solid back:

originalBoxCenter = originalBox.ComputeCentroid()
t1 = Transform.Identity
t1 = t1.ScaleBasis(4)

scaledBox = SolidUtils.CreateTransformed(originalBox, t1)
scaledBoxCenter = scaledBox.ComputeCentroid()
t2 = Transform.Identity
t2.Origin = (scaledBoxCenter - originalBoxCenter).Negate()
movedBox = SolidUtils.CreateTransformed(scaledBox, t2)
OUT = originalBox.Convert() , movedBox.Convert()
1 Like

Perfect that works :smiley:

Solid = UnwrapElement(IN[0])
SolidCenter = Solid.ComputeCentroid()
t1 = Transform.Identity
t1 = t1.ScaleBasis(1.1)

scaledSolid = SolidUtils.CreateTransformed(Solid, t1)
scaledSolidCenter=scaledSolid.ComputeCentroid()

t2 = Transform.Identity
t2.Origin = (scaledSolidCenter - SolidCenter).Negate()
movedSolid = SolidUtils.CreateTransformed(scaledSolid, t2)
OUT = movedSolid

Thanks again Viktor :slight_smile:

1 Like