Scale of Mesh

I want to scale a mesh before drawing it, how do I scale it by a specified number?

What should be defined before this code?
The Scale method can only take one argument, what if I want to take more than one?

mesh.scale(width);
mesh.scale(length);
mesh.scale(depth);
doc.Objects.AddMesh(mesh);

I would like to 3D scale around the origin.

I can only get one return value, what should I do if I want to get more than one?

width,length,depth
These are all double values.

Hi

Apply a transform with

GeometryBase.Transform Method

creating a transform with

Does that help?

Hi Willem

I also referred to that Method, but I will try again.

This code would fill the entire screen.
It will not be the number that is set by default.

Plane plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
Transform scale3d = new Transform();
scale3d = Transform.Scale(plane, length, width, depth);
meshAll_2.Transform(scale3d);
doc.Objects.AddMesh(meshAll_2);

Hi @jack3, note that the 3 values used in Transform.Scale are scale factors not real dimensional units. To scale to a specific dimension you would need to measure the current dimension eg. using the bounding box and then compute the desired scale factors yourself in order to use them.

_
c.

Hi @clement

Thanks for the advice.
If you don’t mind, do you have any examples?

Hi @jack3, sure, to test below, create a box, in the world xy plane:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def DoSomething():
    
    obj_id = rs.GetObject("Select the box", rs.filter.polysurface, True, False)
    if not obj_id: return
    
    rh_obj = rs.coercerhinoobject(obj_id, True, True)
    plane = Rhino.Geometry.Plane.WorldXY
    bbox = rh_obj.Geometry.GetBoundingBox(plane)
    
    length, width, height = 24, 12, 18
    
    x_factor = length / bbox.Min.DistanceTo(bbox.PointAt(1,0,0))
    y_factor = width  / bbox.Min.DistanceTo(bbox.PointAt(0,1,0))
    z_factor = height / bbox.Min.DistanceTo(bbox.PointAt(0,0,1))

    xform = Rhino.Geometry.Transform.Scale(plane, x_factor, y_factor, z_factor)
    rh_obj.Geometry.Transform(xform)
    rh_obj.CommitChanges()
    scriptcontext.doc.Views.Redraw()
    
DoSomething()

_
c.

Hi @clement

Thank you for providing us with a sample.
But I am building in C#…

Hi @jack3,

sorry i am using python only. You should be able to transfer above into C# if you understand the concept, i’ll try:

Plane plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
BoundingBox bbox = meshAll_2.GetBoundingBox(plane);
double x_factor = length / bbox.Min.DistanceTo(bbox.PointAt(1,0,0));
double y_factor = width / bbox.Min.DistanceTo(bbox.PointAt(0,1,0));
double z_factor = height / bbox.Min.DistanceTo(bbox.PointAt(0,0,1));
Transform scale3d = new Transform();
scale3d = Transform.Scale(plane, x_factor, y_factor, z_factor);
meshAll_2.Transform(scale3d);
doc.Objects.AddMesh(meshAll_2);
...

above asumes that you have length, width and height somewhere in your code.

_
c.

Hi @clement

It is an adequate sample.
Thank you very much.

private void ComputeMesh()
Is there a wrong way to define Scale in this Method?

    internal class DisplayTestConduit : DisplayConduit
    {
        private readonly Mesh m_mesh = null;
        private Mesh m_mesh0 = null;
        private readonly Color m_color = Rhino.ApplicationSettings.AppearanceSettings.FeedbackColor;

        public double Length
        {
            get => m_length;
            set
            {
                if (value > 0.001)
                {
                    m_length = value;
                    ComputeMesh();
                }
            }
        }
        private double m_length = 10.38;

        public double Width
        {
            get => m_width;
            set
            {
                if (value > 0.001)
                {
                    m_width = value;
                    ComputeMesh();
                }
            }
        }
        private double m_width = 5.19;

        public double Depth
        {
            get => m_depth;
            set
            {
                if (value > 0.001)
                {
                    m_depth = value;
                    ComputeMesh();
                }
            }
        }
        private double m_depth = 3.17;

        private void ComputeMesh()
        {
            m_mesh0 = m_mesh.DuplicateMesh();
            m_mesh0.Scale(Length);
            m_mesh0.Scale(Width);
            m_mesh0.Scale(Depth);
        }

Hi @jack3,

according to your initial question i would say yes. According to the documentation for GeometryBase.Scale the number you put for scaleFactor is not a distance but a uniform factor, it works for all 3 dimensions (x,y,z). So if you would like to scale some geometry to double its size you would use:

m_mesh0.Scale(2.0)

and to scale it to half it’s size you would use

m_mesh0.Scale(0.5)

looking at your recent code you would scale all 3 axes 3 times with different values. I am not sure this is desired. Are you trying to scale your geometry to a specific size ?

_
c.

Hi @clement

I am trying to output a number specified by double.

I define it this way in RunCommad.

            var conduit = new DisplayTestConduit(meshAll_2)
            {
                Length = length,
                Width = width,
                Depth = depth,
                Enabled = true
            };
            doc.Views.Redraw();

It seems that the Scale Method is not used to scale each of Length, Width, and Depth by 1D, but what should I do if I want to scale each item by 1D?

Hi @jack3, to scale only in one direction, set all other factors to 1.0. For example below scales only the height by a factor of 2.0:

scale1d = Transform.Scale(plane, 1.0, 1.0, 2.0);
meshAll_2.Transform(scale1d);

_
c.

How can I define the ComputeMesh() Method so that the Length, Width, and Depth are each 1DScale in the ComputeMesh() Method?

Hi @jack3, Transform.Scale method creates a non uniform scaling transform along 3 axes. To get all 3 at once you would use something close to this:

private void ComputeMesh()
        {
            m_mesh0 = m_mesh.DuplicateMesh();
			Plane plane = Plane.WorldXY; 
			Transform xform = new Transform();
			xform = Transform.Scale(plane, length, width, depth);
			m_mesh0.Transform(xform);
        }

If you want a mesh for each singular axis, you would create 3 transforms and set the scale factors to 1.0 where you do not want a scaling to happen. See my previous reply in case you want to scale only in one direction.

_
c.

1 Like