[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3006] trunk/py/scripts/addons/ space_view3d_panel_measure.py: * Measure Panel - Version 0.8.5
Martin Buerbaum
martin.buerbaum at gmx.at
Tue Feb 21 13:12:36 CET 2012
Revision: 3006
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3006
Author: pontiac
Date: 2012-02-21 12:12:28 +0000 (Tue, 21 Feb 2012)
Log Message:
-----------
* Measure Panel - Version 0.8.5
* Calculate surface area & normals for n-gons.
* Fixed normal calculation to return saner values.
* Check prevent volume calculation for n-gons (todo: actually write code for this).
Modified Paths:
--------------
trunk/py/scripts/addons/space_view3d_panel_measure.py
Modified: trunk/py/scripts/addons/space_view3d_panel_measure.py
===================================================================
--- trunk/py/scripts/addons/space_view3d_panel_measure.py 2012-02-21 07:19:25 UTC (rev 3005)
+++ trunk/py/scripts/addons/space_view3d_panel_measure.py 2012-02-21 12:12:28 UTC (rev 3006)
@@ -27,7 +27,7 @@
"author": "Buerbaum Martin (Pontiac), TNae (Normal patch)," \
" Benjamin Lauritzen (Loonsbury; Volume code)," \
" Alessandro Sala (patch: Units in 3D View)",
- "version": (0, 8, 4),
+ "version": (0, 8, 5),
"blender": (2, 6, 0),
"location": "View3D > Properties > Measure Panel",
"description": "Measure distances between objects",
@@ -312,17 +312,63 @@
# @sa: rna_mesh.c:rna_MeshFace_area_get
# @sa: math_geom.c:area_quad_v3
# @sa: math_geom.c:area_tri_v3
-def faceAreaGlobal(face, obj):
+# @sa: math_geom.c:area_poly_v3
+# @todo Fix calculation of "n" for n-gons?
+def polyAreaGlobal(poly, obj):
area = 0.0
mesh = obj.data
mat = obj.matrix_world.copy()
+ norm = poly.normal
- if len(face.vertices) == 4:
+ if len(poly.vertices) > 4:
+ # n-Gon (5++)
+ verts = poly.vertices # vertex indices
+ nr = poly.loop_total
+
+ # first: find dominant axis: 0==X, 1==Y, 2==Z
+ # don't use 'axis_dominant_v3()' because we need max axis too
+ x = abs(norm[0])
+ y = abs(norm[1])
+ z = abs(norm[2])
+ maximum = max(x, y, z)
+
+ px = 0
+ py = 1
+ if maximum == y:
+ py = 2
+ elif maximum == x:
+ px = 1
+ py = 2
+
+ # The Trapezium Area Rule
+ idx_prev = verts[nr - 1]
+ idx_cur = verts[0]
+
+ #for (a=0; a<nr; a++):
+ for a in range(nr):
+ prev = mesh.vertices[idx_prev]
+ cur = mesh.vertices[idx_cur]
+
+ prev = mat * prev.co
+ cur = mat * cur.co
+
+ area += (cur[px] - prev[px]) * (cur[py] + prev[py])
+
+ idx_prev = verts[a]
+
+ if a == nr - 1:
+ idx_cur = verts[0]
+ else:
+ idx_cur = verts[a + 1]
+
+ area = abs(0.5 * area / maximum)
+
+ if len(poly.vertices) == 4:
# Quad
# Get vertex indices
- v1, v2, v3, v4 = face.vertices
+ v1, v2, v3, v4 = poly.vertices
# Get vertex data
v1 = mesh.vertices[v1]
@@ -350,11 +396,11 @@
area += n.length / 2.0
- elif len(face.vertices) == 3:
+ elif len(poly.vertices) == 3:
# Triangle
# Get vertex indices
- v1, v2, v3 = face.vertices
+ v1, v2, v3 = poly.vertices
# Get vertex data
v1 = mesh.vertices[v1]
@@ -373,9 +419,12 @@
area = n.length / 2.0
- return area, n
+ # Apply world matrix to normal as well.
+ norm = mat * norm
+ return area, norm
+
# Calculate the surface area of a mesh object.
# *) Set selectedOnly=1 if you only want to count selected faces.
# *) Set globalSpace=1 if you want to calculate
@@ -391,15 +440,15 @@
mesh = obj.data
# Count the area of all the faces.
- for face in mesh.faces:
- if not selectedOnly or face.select:
+ for poly in mesh.polygons:
+ if not selectedOnly or poly.select:
if globalSpace:
- a, n = faceAreaGlobal(face, obj)
+ a, n = polyAreaGlobal(poly, obj)
areaTotal += a
normTotal += n
else:
- areaTotal += face.area
- normTotal += face.normal
+ areaTotal += poly.area
+ normTotal += poly.normal
return areaTotal, normTotal
@@ -416,17 +465,21 @@
if not checkManifold(obj):
return -1
+ # Check if mesh has n-gons
+ if checkNgon(obj):
+ return -2
+
mesh = obj.data
volTot = 0
- for face in mesh.faces:
- fzn = face.normal.z
+ for poly in mesh.polygons:
+ fzn = poly.normal.z
- if len(face.vertices) == 4:
- v1, v2, v3, v4 = face.vertices
+ if len(poly.vertices) == 4:
+ v1, v2, v3, v4 = poly.vertices
else:
- v1, v2, v3 = face.vertices
+ v1, v2, v3 = poly.vertices
v1 = mesh.vertices[v1]
v2 = mesh.vertices[v2]
@@ -459,7 +512,7 @@
volume = ((z1 + z2 + z3) / 3.0) * pa
# Allowing for quads
- if len(face.vertices) == 4:
+ if len(poly.vertices) == 4:
# Get vertex data
v4 = mesh.vertices[v4]
@@ -494,7 +547,7 @@
# else:
# print obj.name, ': Object must be a mesh!' # TODO
- return -2
+ return -3
# Manifold Checks
@@ -505,8 +558,8 @@
mc = dict([(ed.key, 0) for ed in mesh.edges]) # TODO
- for f in mesh.faces:
- for ek in f.edge_keys:
+ for p in mesh.polygons:
+ for ek in p.edge_keys:
mc[ek] += 1
if mc[ek] > 2:
return 0
@@ -525,7 +578,20 @@
else:
return -1
+# Check if a mesh has n-gons (polygon with more than 4 edges).
+def checkNgon(obj):
+ if obj and obj.type == 'MESH' and obj.data:
+ mesh = obj.data
+ for p in mesh.polygons:
+ if len(p.vertices) > 4:
+ return 1
+
+ return 0
+
+ else:
+ return -1
+
# User friendly access to the "space" setting.
def measureGlobal(sce):
return (sce.measure_panel_transform == "measure_global")
@@ -748,10 +814,10 @@
if len(verts_selected) >= 3:
# Get selected faces
# @todo: Better (more efficient) way to do this?
- faces_selected = [f for f in mesh.faces
+ polys_selected = [f for f in mesh.polygons
if f.select == 1]
- if len(faces_selected) > 0:
+ if len(polys_selected) > 0:
area, normal = objectSurfaceArea(obj, True,
measureGlobal(sce))
if area >= 0.0:
@@ -1066,15 +1132,15 @@
if sce.measure_panel_calc_area:
# Get selected faces
# @todo: Better (more efficient) way to do this?
- faces_selected = [f for f in mesh.faces
- if f.select == 1]
+ polys_selected = [p for p in mesh.polygons
+ if p.select == 1]
- if len(faces_selected) > 0:
+ if len(polys_selected) > 0:
if sce.measure_panel_area1 >= 0:
box = layout.box()
row = box.row()
row.label(
- text=str(len(faces_selected)),
+ text=str(len(polys_selected)),
icon='FACESEL')
row = box.row()
@@ -1229,7 +1295,7 @@
if sce.measure_panel_calc_volume:
# Display volume of the objects.
- if sce.measure_panel_volume1 >= -1:
+ if sce.measure_panel_volume1 >= -2:
box = layout.box()
row = box.row()
row.label(text=obj1.name, icon='OBJECT_DATA')
@@ -1238,12 +1304,17 @@
row = box.row()
row.label(text="Volume")
row.prop(sce, "measure_panel_volume1")
- else: # -1
+ elif sce.measure_panel_volume1 >= -1:
row = box.row()
row.label(text="Mesh is non-manifold!",
icon='INFO')
+ else: # -2
+ row = box.row()
+ row.label(text="Mesh has n-gons (faces with " \
+ "more than 4 edges)!",
+ icon='INFO')
- if sce.measure_panel_volume2 >= -1:
+ if sce.measure_panel_volume2 >= -2:
box = layout.box()
row = box.row()
row.label(text=obj2.name, icon='OBJECT_DATA')
@@ -1252,10 +1323,15 @@
row = box.row()
row.label(text="Volume")
row.prop(sce, "measure_panel_volume2")
- else: # -1
+ elif sce.measure_panel_volume2 >= -1:
row = box.row()
row.label(text="Mesh is non-manifold!",
icon='INFO')
+ else: # -2
+ row = box.row()
+ row.label(text="Mesh has n-gons (faces with " \
+ "more than 4 edges)!",
+ icon='INFO')
elif obj:
# One object selected.
@@ -1319,7 +1395,7 @@
if sce.measure_panel_calc_volume:
# Display volume of the objects.
- if sce.measure_panel_volume1 >= -1:
+ if sce.measure_panel_volume1 >= -2:
box = layout.box()
row = box.row()
row.label(text=obj.name, icon='OBJECT_DATA')
@@ -1328,10 +1404,15 @@
row = box.row()
row.label(text="Volume")
row.prop(sce, "measure_panel_volume1")
- else: # -1
+ elif sce.measure_panel_volume1 >= -1:
row = box.row()
row.label(text="Mesh is non-manifold!",
icon='INFO')
+ else: # -2
+ row = box.row()
+ row.label(text="Mesh has n-gons (faces with " \
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list