# how to find a side total length

I have this simple setup: I'd like to walk this perimeter and find the total length of every side, so as to find which side is longer: How can I do that with a python script? Thank you EDIT: added a clearer picture

Co linear Edges

below is a script that returns all co linear edges from a set of input edges. Two edges are colinear if they share a vertex and the edge vectors are parallel (dot product of normalized vectors is one)

The method edge_line_segments(...) takes as its arguments, the bmesh, a list of edges from that bmesh and a tolerance angle for how far from parallel the edges can be.

The return dictionary has a key "segments" which is a list of edges in each line segment.

import bpy
import bmesh

def tag(iterable, value):
for x in iterable:
x.tag = value

def vec(e):
v0, v1 = e.verts
return (v1.co - v0.co).normalized()

def parallel(e1, e2, tol_angle=0):
return abs(vec(e1).dot(vec(e2)) - 1) <= sin(tol_angle)

def line_select_extend(edge, v, tol_angle=0):
edges = []
while v:
segments = [e for e in v.link_edges
if not e is edge
and e.tag
and parallel(e, edge, tol_angle)]
if segments:
edge = segments
edges.extend(segments)
v = edge.other_vert(v)
else:
v = None
return edges

def select_segment(edge, tol_angle=0):
v0, v1 = edge.verts
edges = line_select_extend(edge, v0, tol_angle)
edges.reverse()
edges.append(edge)
edges.extend(line_select_extend(edge, v1, tol_angle))
return edges

def edge_line_segments(bm, edges=[], tol_angle=0):
ret = {"segments" : []}
tag(bm.edges, False)
tag(edges, True)
edges = set(edges)
while edges:
segments = select_segment(next(iter(edges)))
ret["segments"].append(segments)
edges -= set(segments)
tag(bm.edges, False)
return ret


To use.

Test script below to run in edit mode. Calls method with boundary (perimeter edges), sorts the segments by length, selects the edges of the longest segment and writes a report to system console.

context = bpy.context
ob = context.object
me = ob.data

bm = bmesh.from_edit_mesh(me)
perimeter = [e for e in bm.edges if e.is_boundary]
segments = [(sum(e.calc_length() for e in s), s)
for s in ret["segments"]]
segments.sort(key=lambda s: s)

for i, (length, edges) in enumerate(segments):
print("linked segment %d edges length %.3f" % (len(edges), length))

for e in edges:
e.select = i == len(segments) - 1
print("\t edge %d len %.2f" % (e.index, e.calc_length()))

• This puts me on the right way, thank you very much. – Kabu May 22 '18 at 8:31

With the following script you're able to find the indexnumber of the corner vertices. Just put the object in editmode and select all corner vertices. The script will print a list for the second script.

import bpy
import bmesh

obj = bpy.context.active_object

mesh = obj.data

bm = bmesh.from_edit_mesh(mesh)

bm.faces.ensure_lookup_table()
vertices = bm.faces.verts

corner_verts =[]
for v in vertices:
if v.select:
corner_verts.append(v.index)

print(corner_verts)

bm.free()
bpy.ops.object.mode_set(mode='OBJECT')


Replace the corner_verts array with the output from the first script.

import bpy
import bmesh

obj = bpy.context.active_object

mesh = obj.data

bpy.ops.object.mode_set(mode='EDIT')

bm = bmesh.from_edit_mesh(mesh)
bm.verts.ensure_lookup_table()

corner_verts = [3, 11, 10, 1, 6, 5, 0, 15, 14, 2, 13, 12]
len_corner_verts = len(corner_verts)

for i in range(0, len_corner_verts):
v1 = bm.verts[corner_verts[i % len_corner_verts]].co
v2 = bm.verts[corner_verts[(i + 1) % len_corner_verts]].co
dv = v2 -v1
print('from {0} to {1}, length: {2}'.format(v1, v2, dv.length))

print('---')

bm.free()
bpy.ops.object.mode_set(mode='OBJECT')