3
$\begingroup$

I have an arbitrary oriented plane and an object "above" it.
I would like to calculate the distance from the plane for each vertex in that object.

Hopefully this screenshot illustrates the idea (the purple line would be the distance of one of the vertices):
enter image description here

I suppose some kind of a transformation of vertex global coordinates to the local orientation of the plane would be the way to go, however, I'm too new to Blender to know even what to search for (I did try searching for mentioned keywords but didn't find something I could figure out, unfortunately).

I know how to iterate trough vertices of an object and get global coordinates, no problems with that.

Edit:
As Chebhou suggested I tried using the mathutils.geometry.distance_point_to_plane(pt, plane_co, plane_no) but cannot get it to work.
For testing I'm using a 2x2x2 cube at (0,0,1) and 6x6x6 plane at (0,0,0): enter image description here
The code is this (shortened for clarity):

point_location = thecube.location

planepoint_location_w = theplane.matrix_world * theplane.data.vertices[0].co

plane_normal = theplane.matrix_world * theplane.data.polygons[0].normal

distance = geometry.distance_point_to_plane(point_location, planepoint_location_w, plane_normal)
print("point_location = ", point_location)
print("planepoint_location_w = ", planepoint_location_w)
print("distance = ", distance)

The result for the cube and plane location as in the pic is OK (the point is 1 unit above the plane):

point_location =  <Vector (0.0000, 0.0000, 1.0000)>  
planepoint_location_w =  <Vector (-3.0000, -3.0000, 0.0000)>  
distance =  1.0

However, if I move the plane on Y axis to (0,1,0) the result is this (but should be the same as before):

point_location =  <Vector (0.0000, 0.0000, 1.0000)>
planepoint_location_w =  <Vector (-3.0000, -2.0000, 0.0000)>
distance =  2.1213202476501465

Obviously I'm doing something wrong - but what?

$\endgroup$
8
  • 1
    $\begingroup$ blender.org/api/blender_python_api_current/… $\endgroup$
    – Chebhou
    Commented May 4, 2016 at 17:47
  • 1
    $\begingroup$ when you solve the problem write an answer, and if you need help just ask $\endgroup$
    – Chebhou
    Commented May 4, 2016 at 17:51
  • 1
    $\begingroup$ Thanks @Chebhou! It never occurred to me that there could be something like distance_point_to_plane! I'm looking into it ... $\endgroup$
    – spacer
    Commented May 4, 2016 at 21:08
  • 1
    $\begingroup$ @Chebhou, OK, I'm converting it to global with theplane.matrix_world * theplane.data.vertices[0].co but it still does not work right. What about the plane_no (direction the plane is facing) parameter - is that supposed to be converted to global too? I'm doing it but no go. I'll edit the question and add the test code ... $\endgroup$
    – spacer
    Commented May 4, 2016 at 22:31
  • 1
    $\begingroup$ @Chebhou, I am doing that - I updated the question to show the test code. $\endgroup$
    – spacer
    Commented May 4, 2016 at 22:58

2 Answers 2

3
$\begingroup$

You can use the dedicated function :mathutils.geometry.distance_point_to_plane(pt, plane_co, plane_no) were you supply the plane normal and one point from it, and the point you want to calculate the distance to as in the following example :

import bpy
import mathutils

plane = bpy.context.scene.objects['Plane']
p1 = plane.matrix_world*plane.data.vertices[0].co
p2 = plane.matrix_world*plane.data.vertices[1].co
p3 = plane.matrix_world*plane.data.vertices[2].co
plane_no = mathutils.geometry.normal([p1, p2, p3])

obj = bpy.context.object
mat = obj.matrix_world

for v in obj.data.vertices:
    pt = mat*v.co
    d = mathutils.geometry.distance_point_to_plane(pt, p1, plane_no)
    print(round(d, 4))
$\endgroup$
11
  • $\begingroup$ Thanks but this does not produce correct result - run it on the test example from my edit (cube at (0,0,1) and plane at (0,1,0) and it should give distance of 0 for four bottom vertexes, but it does not ... $\endgroup$
    – spacer
    Commented May 4, 2016 at 23:16
  • $\begingroup$ it seems that the converting to global is the problem $\endgroup$
    – Chebhou
    Commented May 4, 2016 at 23:18
  • $\begingroup$ Yes, I just run a test that uses all 8 possible combinations of local & global parameters and none of them gives correct result! $\endgroup$
    – spacer
    Commented May 4, 2016 at 23:19
  • $\begingroup$ see if this helps ? $\endgroup$
    – Chebhou
    Commented May 4, 2016 at 23:21
  • 1
    $\begingroup$ The edit works. Just replace print(round(d, 4)) and it will show zeros correctly. $\endgroup$
    – spacer
    Commented May 4, 2016 at 23:34
0
$\begingroup$

I have found why my attempt to convert plane's normal by using plane_normal = theplane.matrix_world * theplane.data.polygons[0].normal failed - it is because matrix_world gives 4x4 matrix and the normal is 1x3 vector.

Instead I should have used matrix_world.to_3x3():

plane_normal = theplane.matrix_world.to_3x3() * theplane.data.polygons[0].normal

and it would have worked.

$\endgroup$
1
  • $\begingroup$ See here Above will work correctly only when the origin is on the poly. $\endgroup$
    – batFINGER
    Commented Oct 23, 2018 at 10:05

You must log in to answer this question.

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