# -*- coding: utf-8 -*- # Copyright (C) 2023 Ilia Kurochkin # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. ''' DESCRIPTION. Various mesh tools for Edit Mode. ''' __version__ = '0.1' import bpy import bmesh from math import radians def select_peaks(me, peak_limit_angle=60, peak_accuracy_angle=10): ''' Select sharp vertices that stand alone. ''' bm = bmesh.from_edit_mesh(me) def is_sharp(vert, eps=radians(peak_limit_angle)): sharps = [] face_before = None for face in vert.link_faces: if face_before: face_angle = face.normal.angle(face_before.normal) if face_angle > radians(peak_accuracy_angle): angle = vert.normal.angle(face.normal) if angle > eps: sharps.append(angle) face_before = face return ( (len(sharps) + 1) == len(vert.link_faces) or (len(sharps) + 2) == len(vert.link_faces) ) def non_single(vert): for edge in vert.link_edges: if edge.other_vert(vert).select: return False return True for v in bm.verts: v.select_set( is_sharp(v) ) for v in bm.verts: if v.select: v.select_set( non_single(v) ) bmesh.update_edit_mesh(me) return me def select_zero_faces(me): ''' Select very small faces. ''' bm = bmesh.from_edit_mesh(me) [f.select_set(True) for f in bm.faces if f.calc_area() < 1e-7] bmesh.update_edit_mesh(me) return me def select_stratched_edges(me, edge_length_limit=0.002): ''' Select very stratched edges of small faces. ''' bm = bmesh.from_edit_mesh(me) faces_stratched = [f for f in bm.faces if f.calc_area() < 1e-6] for face in faces_stratched: edges_lengths = {e: e.calc_length() for e in face.edges} edge_max_length = max(edges_lengths.values()) if edge_max_length > edge_length_limit: edge_max = [k for k, v in edges_lengths.items() if v == edge_max_length][0] edge_max.select_set(True) bmesh.update_edit_mesh(me) return me def collect_less_volume_objs(objs: list, min_volume): ''' Separate selection for less volume objects. ''' less_volume_objs = [] for obj in objs: bpy.ops.object.select_all(action='DESELECT') if obj.type != 'MESH': continue # requed for bmesh obj.hide_set(False) obj.select_set(state=True) if obj.type == 'MESH': bpy.ops.object.mode_set(mode='EDIT') bm = bmesh.from_edit_mesh(obj.data) if bm.calc_volume() < min_volume: less_volume_objs.append(obj) bpy.ops.object.mode_set(mode='OBJECT') return less_volume_objs