0
$\begingroup$

enter image description here I would like select left or right side of mesh like this and separate it from the object using script. Is it possible? Thanks in advance.

$\endgroup$
  • $\begingroup$ You want a script that could select half of the road and separate the road with one button click? Too much trouble to build a script don't you think? $\endgroup$ – hawkenfox Apr 23 '18 at 16:34
2
$\begingroup$

Bmesh version

Most edges in the middle of the road have 2 linked faces, and each edge vertex 4 linked edges. (as pointed out in other answer the non-non-manifold)

middle = [e for e in bm.edges if len(e.link_faces) == 2 
        and all(len(v.link_edges) == 4 for v in e.verts)]            

for e in bm.edges:
    e.select = e in middle

Which gives this result, the middle of the road selected without the ends.

enter image description here

Use middle edges to rip the mesh with bmesh.ops.split_edges. If there are any vertices left that have 5 link edges they are on the tip of the rip.

The two rip edges in the verts link edges will also be in the ret['edges'] list returned by the operator.

An edge vector is made from one of the rip edges. The edge to rip is chosen as the one with the smallest angle to rip edge vector. Could possibly use a mesh select operator here, feel I'm missing something as seems overly complicated

Here is a bmesh script to run in edit mode for testing. After running the road mesh will be ripped down the centre line.

import bpy
import bmesh

context = bpy.context
ob = context.object
me = ob.data
bm = bmesh.from_edit_mesh(me)

middle = [e for e in bm.edges if len(e.link_faces) == 2 
        and all(len(v.link_edges) == 4 for v in e.verts)]

ret = bmesh.ops.split_edges(bm, edges=middle)
edges = set(ret["edges"])
ends = []
for v in bm.verts:
    if len(v.link_edges) == 5:
        link_edges = set(v.link_edges)
        cut = edges.intersection(v.link_edges)
        link_edges -= cut
        e = cut.pop()
        v = e.verts[1].co - e.verts[0].co
        def angle(edge):
            return v.angle(edge.verts[1].co - edge.verts[0].co)
        ends.append(sorted(list(link_edges), key=lambda e: angle(e))[0])
if ends:
    bmesh.ops.split_edges(bm, edges=ends)

Seeing this test script is for edit mode can now run

bpy.ops.mesh.separate(type='LOOSE')

To avoid any edit mode operators (so the script can be used on multi meshes in object mode) try the get_islands(...) method.

$\endgroup$
0
$\begingroup$

Solution:

def cut_lanes(obj):
    print("cut_lanes: ", obj.name)
    obj.select = True 
    bpy.context.scene.objects.active = obj

    bpy.context.tool_settings.mesh_select_mode = (False, True, False)
    bpy.ops.mesh.select_non_manifold()
    bpy.ops.mesh.select_all(action="INVERT")

    bpy.ops.object.mode_set(mode='OBJECT')
    edges_ind = [i.index for i in obj.data.edges if i.select]

    bpy.ops.object.mode_set(mode='EDIT')
    if len(edges_ind) != 0: 

        index = edges_ind[0]
        cuts = 1

        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                override = bpy.context.copy()
                override['area'] = area
                override['region'] = area.regions[4]
                bpy.ops.mesh.loopcut(override, number_cuts=cuts, 
                                         edge_index=index)
                break  

        bpy.ops.mesh.edge_split()
        bpy.ops.mesh.separate(type="LOOSE")

    obj.select = False
$\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.