4

I want to calculate the curvature value for each vertex of my mesh. All the scripts suggested here Is there a way to calculate mean curvature of a triangular mesh? don't work for me. These are the script (written by lemon) and the mesh mentioned above after running the script.

import bpy
import bmesh
from mathutils import Vector
from math import sqrt, asin

Helper function to select vertices

def select_vertices( obj, indices, end_with_mode ): bpy.ops.object.mode_set(mode = 'OBJECT') bpy.ops.object.mode_set(mode = 'EDIT') bpy.ops.mesh.select_mode(type="VERT") bpy.ops.mesh.select_all(action = 'DESELECT') bpy.ops.object.mode_set(mode = 'OBJECT') for index in indices: obj.data.vertices[index].select = True bpy.ops.object.mode_set(mode = end_with_mode)

def ensure_vertex_group( obj, group_name ): vertex_group = obj.vertex_groups.get( group_name ) if not vertex_group: vertex_group = obj.vertex_groups.new( name = group_name ) for i in range( len(obj.data.vertices) ): vertex_group.add( [i], 0, 'ADD' ) return vertex_group

def assign_to_vertex_group( obj, group_name, curvatures ): vertex_group = ensure_vertex_group( obj, group_name )

curvatures = [abs(c) for c in curvatures]

min_curvature = min( curvatures )
max_curvature = max( curvatures )
vg_fac = 1.0 / (max_curvature - min_curvature) if max_curvature != min_curvature else 1.0

for i, vert in enumerate( obj.data.vertices ):
    vertex_group.add( [vert.index], (curvatures[i] - min_curvature) * vg_fac, 'REPLACE' )

def index_of( element, sequence ): for i, e in enumerate( sequence ): if e == element: return i return -1

def search_link( value, links, position ): for l in links: if l[position] == value: return l return None

def rotate( l, n ): return l[n:] + l[:n]

Get vertices in the face order but starting from a given vert

def following_verts_of_vert( vert, face ): i0 = index_of( vert, face.verts ) i1 = (i0 + 1) % 3 i2 = (i0 + 2) % 3 return face.verts[i0], face.verts[i1], face.verts[i2]

Create the oriented ring around vert

def ring_from_vert( vert ): vertices = [] for face in vert.link_faces: i0, i1, i2 = following_verts_of_vert( vert, face ) vertices.append( [i1, i2] ) result = vertices[0]
added = True while added and len(vertices): added = False prev = search_link( result[0], vertices, 1 ) if prev: result = [prev[0]] + result vertices.remove( prev ) added = True next = search_link( result[-1], vertices, 0 ) if next and next[1] not in result: result.append( next[1] ) vertices.remove( next ) added = True return result

def curvature_along_edge( vert, other ): normal_diff = other.normal - vert.normal vert_diff = other.co - vert.co return normal_diff.dot( vert_diff ) / vert_diff.length_squared

def angle_between_edges( vert, other1, other2 ): edge1 = other1.co - vert.co edge2 = other2.co - vert.co product = edge1.cross( edge2 ) sinus = product.length / (edge1.length * edge2.length) return asin( min(1.0, sinus) )

def mean_curvature_vert( vert ): ring = ring_from_vert( vert ) ring_curvatures = [curvature_along_edge( vert, other ) for other in ring] total_angle = 0.0 curvature = 0.0 for i in range(len(ring)-1): angle = angle_between_edges( vert, ring[i], ring[i+1] ) total_angle += angle curvature += angle * (ring_curvatures[i] + ring_curvatures[i+1])

return curvature / (2.0 * total_angle)

def mean_curvature( obj, threshold ):

# Get bmesh access on the mesh
bm = bmesh.new()
bm.from_mesh( obj.data )

bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
bm.faces.ensure_lookup_table()

above_threshold = {}
curvatures = []
for vert in bm.verts:
    curvature = mean_curvature_vert( vert )
    curvatures.append( curvature )
    if abs(curvature) > threshold:
        above_threshold[vert.index] = True

return curvatures, above_threshold

print( '-------------' )

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

obj = bpy.context.active_object

threshold = 0.01 curvatures, above_threshold = mean_curvature( obj, threshold )

assign_to_vertex_group( obj, 'Curvatures', curvatures )

select_vertices( obj, above_threshold, 'OBJECT' )

cat

Davide
  • 67
  • 6
  • a bit old question/answer... but how is the mesh of the cat? If very detailed the local curvature will be very low. – lemon Nov 13 '20 at 15:03
  • 1
    ok... gave it a look. Probably your mesh is smooth and shows few curvature. Try to accentuate it in line 33. Replace the factor by a higher value: vg_fac = 4.0 / (max_curvature - min_curvature) if max_curvature != min_curvature else 1.0 – lemon Nov 13 '20 at 16:04
  • 1
    Retested it with highpoly and looks coherent: https://i.stack.imgur.com/IXZ54.jpg – lemon Nov 13 '20 at 16:09
  • @lemon Thank You for your answer! The mesh is detailed: It has about 28000 vertices! (sorry, I am new with Python and Blender). – Davide Nov 14 '20 at 10:04
  • Hello Davide. Could you upload the mesh so that I can give a look? – lemon Nov 14 '20 at 10:04
  • 1
    You can use http://blend-exchange.giantcowfilms.com/ and paste the result link here. If blend file... – lemon Nov 14 '20 at 10:16

1 Answers1

5

The script here is correct but you have few high value so this is not really visible, or they are in hidden parts.

I've added a magnify factor to compensate if wanted:

enter image description here

Updated file:

lemon
  • 60,295
  • 3
  • 66
  • 136
  • Thank you so much for your help! – Davide Nov 14 '20 at 10:46
  • Great answers.. I'm interested in finding the directions of principal curvature, for non-animated NPR.. the closest I'm getting to an approach is libigl .. any suggestions that would be prevent me from being buried, never to be seen again, would be welcome, if you happen to have looked into this yourself. – Robin Betts Nov 14 '20 at 11:21
  • 1
    @RobinBetts, posted a question about it for you in chat/RenderFarm. – lemon Nov 14 '20 at 11:26