[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2332] trunk/py/scripts/addons/ space_view3d_panel_measure.py: * Measure Panel - Version 0.8.0

Martin Buerbaum martin.buerbaum at gmx.at
Mon Sep 19 14:58:16 CEST 2011


Revision: 2332
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2332
Author:   pontiac
Date:     2011-09-19 12:58:15 +0000 (Mon, 19 Sep 2011)
Log Message:
-----------
* Measure Panel - Version 0.8.0
* Volume calculation and mainfold check code by Benjamin Lauritzen (Loonsbury)
* Updated API revision

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	2011-09-19 09:52:40 UTC (rev 2331)
+++ trunk/py/scripts/addons/space_view3d_panel_measure.py	2011-09-19 12:58:15 UTC (rev 2332)
@@ -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 @@
 "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 @@
     return -1, Vector((0.0, 0.0, 0.0))
 
 
+# Calculate the volume of a mesh object.
+# Copyright Loonsbury (loonsbury at 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 at 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,11 +808,41 @@
                 # 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'''
     bl_idname = "view3d.display_measurements"
@@ -800,6 +957,8 @@
         # 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 @@
 #                            " 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 @@
                     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 @@
                     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 @@
                                 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 @@
 #                                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 @@
 
                 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,11 +1187,40 @@
                             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!",

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list