Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Buerbaum <martin.buerbaum@gmx.at>2011-09-19 16:58:15 +0400
committerMartin Buerbaum <martin.buerbaum@gmx.at>2011-09-19 16:58:15 +0400
commitd64686a4e37a56f8c94fda4f818ea0ffc37b2d3d (patch)
tree9aaa947ca09a7c23ccdc8ea068f42998c1242e49 /space_view3d_panel_measure.py
parentda3fabba95dc6854915c455186d670484633573a (diff)
* Measure Panel - Version 0.8.0
* Volume calculation and mainfold check code by Benjamin Lauritzen (Loonsbury) * Updated API revision
Diffstat (limited to 'space_view3d_panel_measure.py')
-rw-r--r--space_view3d_panel_measure.py272
1 files changed, 234 insertions, 38 deletions
diff --git a/space_view3d_panel_measure.py b/space_view3d_panel_measure.py
index 6f024a0b..30809809 100644
--- a/space_view3d_panel_measure.py
+++ b/space_view3d_panel_measure.py
@@ -15,13 +15,20 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
+#
+# Uses volume calculation and manifold check code (GPL2+) from:
+# http://www.shapeways.com/forum/index.php?t=msg&goto=3639
+# Shapeways Volume Calculator by Benjamin Lauritzen (Loonsbury)
+#
+# #################################
bl_info = {
"name": "Measure Panel",
- "author": "Buerbaum Martin (Pontiac), TNae (Normal patch)",
- "version": (0, 7, 15),
+ "author": "Buerbaum Martin (Pontiac), TNae (Normal patch)," \
+ " Benjamin Lauritzen (Loonsbury; Volume code)",
+ "version": (0, 8, 0),
"blender": (2, 5, 7),
- "api": 35864,
+ "api": 40343,
"location": "View3D > Properties > Measure Panel",
"description": "Measure distances between objects",
"warning": "Script needs repairs",
@@ -58,6 +65,7 @@ It's very helpful to use one or two "Empty" objects with
"Snap during transform" enabled for fast measurement.
Version history:
+v0.8.0 - Volume calculation
v0.7.15 - Measurement of face normals by TNae + extended to cover all cases.
Grouped measured values inside boxes.
v0.7.14
@@ -432,6 +440,125 @@ def objectSurfaceArea(obj, selectedOnly, globalSpace):
return -1, Vector((0.0, 0.0, 0.0))
+# Calculate the volume of a mesh object.
+# Copyright Loonsbury (loonsbury@yahoo.com)
+def objectVolume(obj, globalSpace):
+ if (obj and obj.type == 'MESH' and obj.data):
+
+ # Check if mesh is non-manifold
+ if not checkManifold(obj):
+ return -1
+
+ mesh = obj.data
+
+ volTot = 0
+
+ for face in mesh.faces:
+ fzn = face.normal.z
+
+ if len(face.vertices) == 4:
+ v1, v2, v3, v4 = face.vertices
+ else:
+ v1, v2, v3 = face.vertices
+
+ v1 = obj.data.vertices[v1]
+ v2 = obj.data.vertices[v2]
+ v3 = obj.data.vertices[v3]
+
+ # Scaled vert coordinates with object XYZ offsets for
+ # selection extremes/sizing.
+ if globalSpace:
+ x1 = v1.co[0] * obj.scale[0] + obj.location[0]
+ y1 = v1.co[1] * obj.scale[1] + obj.location[1]
+ z1 = v1.co[2] * obj.scale[2] + obj.location[2]
+
+ x2 = v2.co[0] * obj.scale[0] + obj.location[0]
+ y2 = v2.co[1] * obj.scale[1] + obj.location[1]
+ z2 = v2.co[2] * obj.scale[2] + obj.location[2]
+
+ x3 = v3.co[0] * obj.scale[0] + obj.location[0]
+ y3 = v3.co[1] * obj.scale[1] + obj.location[1]
+ z3 = v3.co[2] * obj.scale[2] + obj.location[2]
+
+ else:
+ x1, y1, z1 = v1.co
+ x2, y2, z2 = v2.co
+ x3, y3, z3 = v3.co
+
+ pa = 0.5 * abs(
+ (x1 * (y3 - y2))
+ + (x2 * (y1 - y3))
+ + (x3 * (y2 - y1)))
+ volume = ((z1 + z2 + z3) / 3.0) * pa
+
+ # Allowing for quads
+ if len(face.vertices) == 4:
+ # Get vertex data
+ v4 = obj.data.vertices[v4]
+
+ if globalSpace:
+ x4 = v4.co[0] * obj.scale[0] + obj.location[0]
+ y4 = v4.co[1] * obj.scale[1] + obj.location[1]
+ z4 = v4.co[2] * obj.scale[2] + obj.location[2]
+
+ else:
+ x4, y4, z4 = v4.co
+
+ pa = 0.5 * abs(
+ (x1 * (y4 - y3))
+ + (x3 * (y1 - y4))
+ + (x4 * (y3 - y1)))
+
+ volume += ((z1 + z3 + z4) / 3.0) * pa
+
+ if fzn < 0:
+ fzn = -1
+
+ elif fzn > 0:
+ fzn = 1
+
+ else:
+ fzn = 0
+
+ volTot += fzn * volume
+
+ return volTot
+
+# else:
+# print obj.name, ': Object must be a mesh!' # TODO
+
+ return -2
+
+
+# Manifold Checks
+# Copyright Loonsbury (loonsbury@yahoo.com)
+def checkManifold(obj):
+ if (obj and obj.type == 'MESH' and obj.data):
+ mesh = obj.data
+
+ mc = dict([(ed.key, 0) for ed in mesh.edges]) # TODO
+
+ for f in mesh.faces:
+ for ek in f.edge_keys:
+ mc[ek] += 1
+ if mc[ek] > 2:
+ return 0
+
+ mt = [e[1] for e in mc.items()]
+ mt.sort()
+
+ if mt[0] < 2:
+ return 0
+
+ if mt[len(mt) - 1] > 2:
+ return 0
+
+ return 1
+
+ else:
+ return -1
+
+
# User friendly access to the "space" setting.
def measureGlobal(sce):
return (sce.measure_panel_transform == "measure_global")
@@ -681,10 +808,40 @@ def draw_measurements_callback(self, context):
# Calculate surface area of the object.
area, normal = objectSurfaceArea(obj, False,
measureGlobal(sce))
+
if (area >= 0):
sce.measure_panel_area1 = area
sce.measure_panel_normal1 = normal
+ if (sce.measure_panel_calc_volume):
+ obj = getSingleObject(context)
+
+ if (context.mode == 'OBJECT'):
+ # We are working in object mode.
+
+ #if len(context.selected_objects) > 2: # TODO
+
+ #el
+ if len(context.selected_objects) == 2:
+ # 2 objects selected.
+
+ obj1, obj2 = context.selected_objects
+
+ # Calculate surface area of the objects.
+ volume1 = objectVolume(obj1, measureGlobal(sce))
+ volume2 = objectVolume(obj2, measureGlobal(sce))
+
+ sce.measure_panel_volume1 = volume1
+ sce.measure_panel_volume2 = volume2
+
+ elif (obj):
+ # One object selected.
+
+ # Calculate surface area of the object.
+ volume1 = objectVolume(obj, measureGlobal(sce))
+
+ sce.measure_panel_volume1 = volume1
+
class VIEW3D_OT_display_measurements(bpy.types.Operator):
'''Display the measurements made in the 'Measure' panel'''
@@ -800,6 +957,8 @@ class VIEW3D_PT_measure(bpy.types.Panel):
# Get a single selected object (or nothing).
obj = getSingleObject(context)
+ drawTansformButtons = 1
+
if (context.mode == 'EDIT_MESH'):
obj = context.active_object
@@ -854,11 +1013,6 @@ class VIEW3D_PT_measure(bpy.types.Panel):
# " to do this manually, after you changed" \
# " the selection.")
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
elif len(verts_selected) == 1:
# One vertex selected.
# We measure the distance from the
@@ -877,11 +1031,6 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.operator("view3d.reenter_editmode",
text="Update selection & distance")
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
elif len(verts_selected) == 2:
# Two vertices selected.
# We measure the distance between the
@@ -900,11 +1049,6 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.operator("view3d.reenter_editmode",
text="Update selection & distance")
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
else:
row = layout.row()
row.prop(sce, "measure_panel_calc_area",
@@ -937,11 +1081,6 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.operator("view3d.reenter_editmode",
text="Update selection & area")
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
else:
row = layout.row()
row.label(text="Selection not supported.",
@@ -993,11 +1132,6 @@ class VIEW3D_PT_measure(bpy.types.Panel):
# row.label(text=str(round(area, PRECISION))
# + " BU^2")
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
elif len(context.selected_objects) == 2:
# 2 objects selected.
# We measure the distance between the 2 selected objects.
@@ -1019,7 +1153,7 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row = layout.row()
row.prop(sce, "measure_panel_calc_area",
- text="Surface area:")
+ text="Surface area")
if (sce.measure_panel_calc_area):
# Display surface area of the objects.
@@ -1053,10 +1187,39 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row = box.row()
row.prop(sce, "measure_panel_normal2")
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
+ row = layout.row()
+ row.prop(sce, "measure_panel_calc_volume",
+ text="Volume:")
+
+ if (sce.measure_panel_calc_volume):
+ # Display volume of the objects.
+ if (sce.measure_panel_volume1 >= -1):
+ box = layout.box()
+ row = box.row()
+ row.label(text=obj1.name, icon='OBJECT_DATA')
+
+ if (sce.measure_panel_volume1 >= 0):
+ row = box.row()
+ row.label(text="Volume")
+ row.prop(sce, "measure_panel_volume1")
+ else: # -1
+ row = box.row()
+ row.label(text="Mesh is non-manifold!",
+ icon='INFO')
+
+ if (sce.measure_panel_volume2 >= -1):
+ box = layout.box()
+ row = box.row()
+ row.label(text=obj2.name, icon='OBJECT_DATA')
+
+ if (sce.measure_panel_volume2 >= 0):
+ row = box.row()
+ row.label(text="Volume")
+ row.prop(sce, "measure_panel_volume2")
+ else: # -1
+ row = box.row()
+ row.label(text="Mesh is non-manifold!",
+ icon='INFO')
elif (obj):
# One object selected.
@@ -1076,7 +1239,7 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row = layout.row()
row.prop(sce, "measure_panel_calc_area",
- text="Surface area:")
+ text="Surface area")
if (sce.measure_panel_calc_area):
# Display surface area of the object.
@@ -1095,10 +1258,25 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row = box.row()
row.prop(sce, "measure_panel_normal1")
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
+ row = layout.row()
+ row.prop(sce, "measure_panel_calc_volume",
+ text="Volume:")
+
+ if (sce.measure_panel_calc_volume):
+ # Display volume of the objects.
+ if (sce.measure_panel_volume1 >= -1):
+ box = layout.box()
+ row = box.row()
+ row.label(text=obj.name, icon='OBJECT_DATA')
+
+ if (sce.measure_panel_volume1 >= 0):
+ row = box.row()
+ row.label(text="Volume")
+ row.prop(sce, "measure_panel_volume1")
+ else: # -1
+ row = box.row()
+ row.label(text="Mesh is non-manifold!",
+ icon='INFO')
elif not context.selected_objects:
# Nothing selected.
@@ -1118,6 +1296,12 @@ class VIEW3D_PT_measure(bpy.types.Panel):
row.label(text="Selection not supported.",
icon='INFO')
+ if drawTansformButtons:
+ row = layout.row()
+ row.prop(sce,
+ "measure_panel_transform",
+ expand=True)
+
def register():
bpy.utils.register_module(__name__)
@@ -1139,6 +1323,12 @@ def register():
bpy.types.Scene.measure_panel_normal2 = bpy.props.FloatVectorProperty(
precision=PRECISION,
subtype="XYZ")
+ bpy.types.Scene.measure_panel_volume1 = bpy.props.FloatProperty(
+ precision=PRECISION,
+ unit="VOLUME")
+ bpy.types.Scene.measure_panel_volume2 = bpy.props.FloatProperty(
+ precision=PRECISION,
+ unit="VOLUME")
TRANSFORM = [
("measure_global", "Global",
@@ -1165,6 +1355,12 @@ def register():
" usage on bigger meshes)",
default=0)
+ # Define property for the calc-volume setting.
+ bpy.types.Scene.measure_panel_calc_volume = bpy.props.BoolProperty(
+ description="Calculate mesh volume (heavy CPU" \
+ " usage on bigger meshes)",
+ default=0)
+
pass