0
$\begingroup$

The eventual purpose of this script will be to try to stitch two halves of two different, sliced-open objects, together. This is to be done by individually moving each of the verts on the open non-manifold sliced edge of one of the objects, to the nearest point on the non-manifold edge on the other object.

For now, I am just trying to find & print the index of the closest edge on object B, for each non-manifold vertex on object A. Later I'll add more code for the moving of the verts on object A.

I'm a bit stuck as I'm new to python in Blender.

I'm getting the following error for line 44: AttributeError: 'BMVert' object has no attribute 'location'

Code:

    import bpy, bmesh
from mathutils import Vector
from mathutils.bvhtree import BVHTree

o = bpy.context.scene.objects
# Get the object and its mesh
obj = o["Cube"]
obj1 = o["Cube.001"]

mesh = obj.data
mesh1 = obj1.data

# Set up the selection of non-manifold verts on obj1
# Select object 1
obj1.select_set(True)

bpy.ops.object.editmode_toggle()

#me1 = obj1.data

# Create bmesh from edit mesh data (obj1)
bm1 = bmesh.from_edit_mesh(mesh1)

# Select non-manifold vertices in obj1
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.mesh.select_non_manifold()


# Loop through the selection of non-manifold vertices on obj1
for v in bm1.verts:
    
    if v.select:
        
        # For each non-manifold vertex on obj1, find the closest edge on the other object ('obj')
        # Get vertices locations
        vertices = [v.co for v in mesh.vertices]
        # Construct polygons from edges
        polygons = [(e.vertices[0], e.vertices[1], e.vertices[0]) for e in mesh.edges]

        # Create a BVH Tree from it
        tree = BVHTree.FromPolygons( vertices, polygons, all_triangles = True )

        # Search for a location
        location = v.location

        # Query the tree
        found_location, normal, index, distance = tree.find_nearest( location )

        print( index )

Would be grateful for any help. Apologies if I've done anything extremely stupid here, am feeling my way bit by bit.

$\endgroup$
7
  • $\begingroup$ Hello, this looks like it is extremely inefficient, you're recreating the BVH tree for each selected vertex, which doesn't really make sense because it shouldn't be different after each loop. And you're recreating the polygons one by one, and assuming they are all triangles when N Gons are supported in Blender which is error-prone. Note you can directly create a BVHTree from a bmesh : BVHTree.FromBMesh(bm). Have you used AI to create this script ? If so you should disclose it in your question as per the rules of this site. Cheers $\endgroup$
    – Gorgious
    Commented Jun 26 at 8:27
  • $\begingroup$ Wait no, polygons = [(e.vertices[0], e.vertices[1], e.vertices[0]) for e in mesh.edges] will create zero-area triangles if I'm not mistaken ? I'm really struggling to understand the logic :) $\endgroup$
    – Gorgious
    Commented Jun 26 at 8:31
  • $\begingroup$ Hiya, yep I've already moved the BVH tree creation out of that loop, up to earlier in the script. Yes, zero-area triangles are created so that then find_nearest can be used, so far as I understand. I got the whole BVHTree part from another thread here on StackExchange. I think the triangles need to be created because there is no way to find the nearest point on an edge - so you have to find the nearest point on a flat triangle? Could be wrong though. I would appreciate your insight! $\endgroup$
    – El Grillo
    Commented Jun 26 at 10:00
  • $\begingroup$ Here's the latest iteration of the code: pastebin.com/MxMuPvCZ The current problem I'm trying to deal with is that the found_location_world = obj.matrix_world @ found_location line is throwing a compile error 'TypeError: Matrix multiplication: not supported between 'Matrix' and 'NoneType' types`. This seems to be because I've now converted 'obj' to a bmesh... not sure how to get around this. edit: to answer your question no I haven't used AI, I've been building this using bits from various different threads here on SE. $\endgroup$
    – El Grillo
    Commented Jun 26 at 10:05
  • $\begingroup$ Doing a bit of wider reading it seems to me I would actually want to be using the mathutil closest_point_on_tri docs.blender.org/api/current/… Not sure yet however, whether I could use that mathutil function in a BVHTree on the generated polygons in the script as it currently stands. $\endgroup$
    – El Grillo
    Commented Jun 26 at 10:30

1 Answer 1

2
$\begingroup$

Here is the corrected code for line 44:

location = v.co

This is because BMesh/BMVert does not use the location attribute. It uses co, which stands for coordinates.

$\endgroup$
6
  • $\begingroup$ Brilliant - thank you! I don't suppose you have any idea why when I print {location} and {found_location} at the end of the script the coords are currently identical... $\endgroup$
    – El Grillo
    Commented Jun 25 at 22:26
  • $\begingroup$ Further to the above - appears that the reason is that both location and found_location are local coords, not world coords. Now to figure out how to convert them into world coords.. $\endgroup$
    – El Grillo
    Commented Jun 25 at 23:44
  • $\begingroup$ You can convert Local Coordinates into World Coordinates with the following code: location_world = obj1.matrix_world @ location found_location_world = obj.matrix_world @ found_location $\endgroup$
    – Dgc
    Commented Jun 26 at 0:04
  • $\begingroup$ Brilliant, many thanks. The conversion lines you posted there worked great - until recently where the second one (found_location_world = obj.matrix_world @ found_location) is now throwing a compile error 'TypeError: Matrix multiplication: not supported between 'Matrix' and 'NoneType' types'. Am struggling to figure out why. Latest version of the code if of any interest: pastebin.com/MxMuPvCZ $\endgroup$
    – El Grillo
    Commented Jun 26 at 10:09
  • 1
    $\begingroup$ If you're interested, I managed to get it to work - not perfectly, some verts get sent wildly out of place for some reason. And also somehow the 'target' mesh (as I thought it was) is actually the mesh that's being edited, and vice versa. Lol. But here's the code anyway: pastebin.com/ChyLviHw Thanks so much for your help! $\endgroup$
    – El Grillo
    Commented Jun 26 at 19:39

You must log in to answer this question.

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