2
$\begingroup$

I'm dipping my feet at Blender SDK, and I'm trying to calculate intersection between two planes:

enter image description here

Created a default plane in center, duplicated, rotated second, scaled first, applied transforms; but I'm failing for apparently no reason. The script:

import bpy
import bmesh
import mathutils

# https://docs.blender.org/api/2.79/mathutils.geometry.html

# Get the active mesh

center1 = 0
normal1 = 0
center2 = 0
normal2 = 0

# get the selected object
# me = bpy.context.object.data

me = bpy.data.objects['Plane'].data

# for i in range(1,objs+1):

# Get a BMesh representation
bm = bmesh.new()   # create an empty BMesh
bm.from_mesh(me)   # fill it in from a Mesh

print('bmesh:', bm)
# Modify the BMesh, can do anything here...

# get obj geom
for f in bm.faces:
    print('face index:', f.index ,' and face normal:', f.normal)    

    center1 = f.calc_center_median_weighted()
    normal1 = f.normal

# Finish up, write the bmesh back to the mesh
# bm.to_mesh(me)
# free and prevent further access
bm.free()  

mz = bpy.data.objects['Plane.001'].data

# for i in range(1,objs+1):

# Get a BMesh representation
bz = bmesh.new()   # create an empty BMesh
bz.from_mesh(mz)   # fill it in from a Mesh

print('bmesh:', bz)
# Modify the BMesh, can do anything here...

# get obj geom
for f in bz.faces:
    print('face index:', f.index ,' and face normal:', f.normal)    

    center2 = f.calc_center_median_weighted()
    normal2 = f.normal

# Finish up, write the bmesh back to the mesh
# bm.to_mesh(me)
# free and prevent further access
bz.free()  

# calc

print('center1:', center1)
print('normal1:', normal1)
print('center2:', center2)
print('normal2:', normal2)

intersect_line = mathutils.geometry.intersect_plane_plane(center1, normal1, center2, normal2)

print('Point:', intersect_line[0] ,' Vector:', intersect_line[1]) 

# mathutils.geometry.intersect_plane_plane(plane_a_co, plane_a_no, plane_b_co, plane_b_no)

it should be straightforward, but clearly I'm missing something...

the blend

EDIT: console print

bmesh: <BMesh(0x10a6d6008), totvert=4, totedge=4, totface=1, totloop=4>
face index: 0  and face normal: <Vector (0.0000, 0.0000, 1.0000)>
bmesh: <BMesh(0x10a6d6008), totvert=4, totedge=4, totface=1, totloop=4>
face index: 0  and face normal: <Vector (0.9426, -0.1969, 0.2696)>
center1: <Vector (0.0000, -1.0000, 0.0000)>
normal1: <Vector (0.9426, -0.1969, 0.2696)>
center2: <Vector (0.0000, 0.0000, -0.0000)>
normal2: <Vector (0.9426, -0.1969, 0.2696)>
Point: None  Vector: None

EDIT2: better script

import bpy
import bmesh
import mathutils

# https://docs.blender.org/api/2.79/mathutils.geometry.html

# Get the active mesh

def intersect_faces () :

    center1 = mathutils.Vector([0.0,0.0,0.0])
    normal1 = mathutils.Vector([0.0,0.0,0.0])
    center2 = mathutils.Vector([0.0,0.0,0.0])
    normal2 = mathutils.Vector([0.0,0.0,0.0])

    face_pn1 = [center1,normal1]
    face_pn2 = [center2,normal2]

    face_pn = [face_pn1,face_pn2]

    me = bpy.context.selectable_objects[0].data

    # for i in range(1,objs+1):

    # Get a BMesh representation
    bm = bmesh.new()   # create an empty BMesh
    bm.from_mesh(me)   # fill it in from a Mesh

    print('Start')
    print('bmesh:', bm)
    # Modify the BMesh, can do anything here...

    # get obj geom
    for f in bm.faces:
        print('face index:', f.index ,' and face normal:', f.normal)    

        center1 = f.calc_center_median_weighted()
        normal1 = f.normal.copy()

        print('center1:', center1)
        print('normal1:', normal1)

        face_pn1[0]=center1
        face_pn1[1]=normal1

    # Finish up, write the bmesh back to the mesh
    # bm.to_mesh(me)
    # free and prevent further access
    bm.free()  

    # mz = bpy.data.objects['Plane.001'].data

    mz = bpy.context.selectable_objects[1].data

    # for i in range(1,objs+1):

    # Get a BMesh representation
    bz = bmesh.new()   # create an empty BMesh
    bz.from_mesh(mz)   # fill it in from a Mesh

    print('bmesh:', bz)
    # Modify the BMesh, can do anything here...

    # get obj geom
    for g in bz.faces:
        print('face index:', g.index ,' and face normal:', g.normal)    

        center2 = g.calc_center_median_weighted()
        normal2 = g.normal.copy()

        print('center2:', center2)
        print('normal2:', normal2)

        face_pn2[0]=center2
        face_pn2[1]=normal2

    # Finish up, write the bmesh back to the mesh
    # bm.to_mesh(me)
    # free and prevent further access
    bz.free()  

    return face_pn

# check

face_pn = intersect_faces()

center1 = face_pn[0][0]
normal1 = face_pn[0][1]
center2 = face_pn[1][0]
normal2 = face_pn[1][1]

# calc
print('final values')
print('center1:', center1)
print('normal1:', normal1)
print('center2:', center2)
print('normal2:', normal2)

intersect_line = mathutils.geometry.intersect_plane_plane(center1, normal1, center2, normal2)

print('Point:', intersect_line[0] ,' Vector:', intersect_line[1]) 

# mathutils.geometry.intersect_plane_plane(plane_a_co, plane_a_no, plane_b_co, plane_b_no)

anyway, result is strange... if you run it, say 100 times, sometimes it works and sometimes it doesn't... I start suspecting a bug.

EDIT3: script modified with normal.copy as suggested by kheetor. This solves the problem

$\endgroup$
  • $\begingroup$ How are your prints looking? The centers and normals in mesh data are in object space, which means if you rotated objects in object mode instead of edit mode the normals are identical and you can't calculate intersection. $\endgroup$ – kheetor Apr 10 '18 at 16:53
  • $\begingroup$ Normal appear correct in the first part of the script; while in the last part (after "calc") are overwritten. Maybe something "pythonesque"? $\endgroup$ – Kabu Apr 10 '18 at 20:01
  • $\begingroup$ I added .copy() in the end of normal assignments and it worked "normal1 = f.normal.copy()". Something pythonesque indeed, you were still referencing the "normal" variabled stored in the "f" iterator instead of a new Vector3 like you should. $\endgroup$ – kheetor Apr 11 '18 at 12:10
  • $\begingroup$ I have already told you what the problem is ^ $\endgroup$ – kheetor Apr 11 '18 at 15:49
  • $\begingroup$ You are right. Still I have to grasp this pythoneque thing well... Post the answer so I can accept it $\endgroup$ – Kabu Apr 11 '18 at 19:41
0
$\begingroup$

I think this is something like you need.

import bpy
import bmesh
import mathutils
from bpy_extras.object_utils import  object_data_add

def objects_return(obj):

    mat = obj.matrix_world
    v0 = mat *obj.data.vertices[0].co
    v1 = mat *obj.data.vertices[1].co
    v2 = mat *obj.data.vertices[2].co

    normal = mathutils.geometry.normal(v0,v1,v2)

    r = [v0,normal]

    return r

def new_object(verts, edges):

    mesh = bpy.data.meshes.new(name="new line")
    mesh.from_pydata(verts, [], [])
    object_data_add(bpy.context, mesh, operator=None)




print("#"*15)
p1 = bpy.data.objects['Plane']
p2 = bpy.data.objects['Plane.001']

a = objects_return(p1)
b = objects_return(p2)



c = mathutils.geometry.intersect_plane_plane(a[0], a[1], b[0], b[1])



bpy.context.scene.cursor_location = c[0]
vertices = [tuple(c[0]),tuple(c[1])]
edges = [tuple(c[0]),tuple(c[1])]

new_object(vertices, edges)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.