2
$\begingroup$

I'm working with multiple objects that are planes, such as an actual plane, an image imported as a plane, or text. At any time, I could be working with 2 or more of these objects and they could all be the same type or any of the ones I've listed.

I'm not talking about putting objects on an actual, existing mesh plane. I want them to be in the same plane, but that doesn't mean on the same face of an object or plane object.

I know how to match the rotation of two objects to make sure they have the same orientation. I want to go one step farther and make the objects coplanar. This plane will usually not line up with an axis or be even parallel to an axis. (For instance, X rotation might be 32.5°, Y rotation could be 12° and Z rotation could be 75.13°.)

I think it might be easiest to move the 3D cursor to a point on the plane and then moving the object center to the 3D cursor.

I'll be defining a plane with 4 coordinates for corners, but I'll be keeping those as variables and not using them to create an object. How can I pick a point in that plane or check when a point is in that plane?

While I'll be doing this in a script, I don't need actual code, I can work that out, but either a formula that can check if a point is in a plane or code to do it is welcome.

$\endgroup$

1 Answer 1

6
$\begingroup$

Define a plane by a point on the plane and its normal.

For example sake using 4 coordinates of plane as 4 points that make up the plane.

>>> ob = C.object
>>> ob
bpy.data.objects['Plane']

>>> mw = ob.matrix_world
>>> points = [mw @ v.co for v in ob.data.vertices]

Only need 3 points, $(a, b, c)$ to define a plane. All of these distinct points is on the plane. The normal is the cross product of any two non parallel vectors on the plane (b - a).cross(c - a)

The global plane coordinate and normal of example plane.

>>> plane_co = points[0]
>>> v1 = points[1] - plane_co
>>> v2 = points[2] - plane_co
>>> plane_no = (v1.cross(v2)).normalized()

Hence to make any plane aligned with another plane can align their two normals. To get the quaternion rotation required to rotate one vector to align with another.

>>> q = plane_no.rotation_difference(plane_no_2)

Matrix math to translate, rotate, scale with respect to a pivot point in Object mode

Finally there is a helper method mathutils.geometry.distance_point_to_plane

>>> geometry.distance_point_to_plane(
distance_point_to_plane(pt, plane_co, plane_no)
.. function:: distance_point_to_plane(pt, plane_co, plane_no)
Returns the signed distance between a point and a plane    (negative when below the normal).
:arg pt: Point
:type pt: :class:`mathutils.Vector`
:arg plane_co: A point on the plane
:type plane_co: :class:`mathutils.Vector`
:arg plane_no: The direction the plane is facing
:type plane_no: :class:`mathutils.Vector`
:rtype: float

which will give how far along the plane normal a point on another plane is to current plane.

Have used this in determining coplanar faces here https://blender.stackexchange.com/a/53976/15543.

$\endgroup$
1
  • 1
    $\begingroup$ I've had to read this answer multiple times to make sure I get everything in it - and I'm still re-reading it! I mentioned using 4 coordinates for the plane because, in my script, I need a rectangular area to keep everything within. So I can always just pick any 3 of those 4 points to define the plane. Your answer and the info in it is also helping me see an easier and quicker way to do what I want to do. Thank you! (Always love seeing your name at the end of an answer. You're thorough and detailed and always on target!) $\endgroup$
    – Tango
    Commented May 23, 2021 at 17:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .