Scripts: curvature.py

File curvature.py, 2.1 KB (added by goddard, 12 years ago)
Line 
1# Color selected surface pieces by mean curvature.
2#
3# Gray at the average curvature value over the surface, and blue and red
4# at +/- 3 standard deviations of curvature values across the surface.
5#
6# The curvature is estimated from the vertices and normals of the triangulated
7# surface in simple way which will show artifacts from non-isotropic meshes.
8# For each triangle edge it computes the normal vector rotation from one vertex
9# to the other divided by the edge length. The vertex mean curvature is the
10# mean of the curvatures computed for each edge.
11#
12
13def color_by_curvature(p):
14 k = vertex_mean_curvatures(p)
15 r = 1.0/k
16 print ('radius min %.4g, max %.4g, mean %.4g, std %.4g'
17 % (r.min(), r.max(), r.mean(), r.std()))
18
19 km = k.mean()
20 cval = (km - 3*k.std(), km, km + 3*k.std())
21 # Colors are red, green, blue, opacity in range 0 to 1.
22 low_color, mean_color, high_color = (0,0,1,1),(.7,.7,.7,1),(1,0,0,1) # blue, gray, red
23 colors = (low_color, mean_color, high_color)
24 above_color = below_color = (1,1,0,1)
25 import SurfaceColor
26 rgba = SurfaceColor.interpolate_colormap(k, cval, colors, low_color, high_color)
27 p.vertexColors = rgba
28
29def vertex_mean_curvatures(p):
30 va, ta = p.geometry # Vertices and triangles
31 na = p.normals
32 nv, nt = len(va), len(ta)
33 from numpy import zeros, float64
34 k = zeros((nv,), float64) # Vertex curvatures
35 c = zeros((nv,), float64) # Count of edges per vertex
36 from math import acos, sqrt
37 for t in range(nt):
38 j0, j1, j2 = ta[t]
39 for i0,i1 in ((j0,j1),(j1,j2),(j2,j0)):
40 v0,v1 = va[i0],va[i1]
41 n0,n1 = na[i0],na[i1]
42 e = v1-v0 # vector between two vertices
43 elen = sqrt((e*e).sum())
44 e /= elen # Normalize edge length.
45 da = acos((n0*e).sum()) - acos((n1*e).sum())
46 k01 = da / elen
47 k[i0] += k01
48 k[i1] += k01
49 c[i0] += 1
50 c[i1] += 1
51 k /= c
52 return k
53
54import Surface
55plist = Surface.selected_surface_pieces()
56for p in plist:
57 color_by_curvature(p)