Transforming a Plane

Is it possible to apply a transform to a plane?

@Plane1_trans = @Plane1.transform(total_transformation)

When I try this I get:

Error: #<ArgumentError: wrong number of values in array>

I’m assuming its because I used the fit_plane_to_points method which returned an array of four numbers for the plane in question.

You can apply a transformation to a point or a vector so it stands to reason you should be able to do the same thing to a line or a plane.

A plane consists of a point and a vector - EITHER as an array of four floats OR an array of a point and a vector.
If the plane relates to a face you can easily get a point on the face [e.g. face.vertices[0].position] and a suitable vector [e.g. face.normal]
Transform those two parts separately and reform a new plane using the plane = [point,vector] method


I had to back up a bit and figure out the normal and a point on the plane but once I have that it works great.

# Create transformed Splitting Plane
pt_trans = @Vertices1[0].transform(tot_trans)
vec_trans = @Normal1.transform(tot_trans)
@Plane1_trans = [pt_trans, vec_trans]

Lines and Planes are no first-class Geom objects, but defined by convention as list of point and vector (and plane has an alternative convention with four plane equation parameters; actually both could be classes with factory methods for initializing from point and vector or four numbers).

Be aware that vectors are transformed by the inverse of the transformation matrix (normal matrix). Since this never was an issue in SketchUp, I guess SketchUp’s Vector class takes care of that.

Best refactor the code so that it tells a reader what you do, like:

plane = [@Vertices1[0].position, @Normal1]
@Plane1_trans = transform_plane(plane)

If @Vertices1 contains points, not vertices, it’s better named @Points1.

I think that the early designers of SketchUp concluded that, unlike Point3d and Vector3d, lines and planes were not essential for capturing any Entities within the model database. That is, you can define an Edge using its start and end Point3d’s, and you can define a Face using a collection of Edges and a normal Vector3d. You don’t need to store lines or planes to describe Edges and Faces, even if they are useful concepts while creating Edges and Faces. Further, you can reconstruct lines and planes from the “real” geometry when necessary without storing them explicitly. Evidently, in keeping with this philosophy, although they could have implemented helper methods to transform lines and planes, they felt you should transform the defining Point3d and Vector3d parameters instead, as @TIG showed and you also figured out. It really doesn’t take much code!

As a side note, the Ruby API is quite flexible about accepting either an Array of [Point3d, Vector3d] or an Array of four floats as the representation of a plane for input to API methods. But, most likely because it as noted above it is calculated on the fly rather than stored, the API is somewhat erratic about which representation is returned from API methods. If you plan to manipulate a plane explicitly (as opposed to just passing it on to other methods), you have to test to confirm which representation you got. Unless you study the math of plane equations and understand clearly what the four-value representation means, it is much harder to work with it than with the [Point3d, Vector3d] representation.

The API’s modification to the Array class (by adding transform methods) works only on 3 element arrays that are mimicking points or vectors. Also the output may convert the type to [ Length, Length, Length ].
(Not very clear in the docs!)

1 Like