[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3388] contrib/py/scripts/addons/ mesh_edgetools.py: EdgeTools: http://projects.blender.org/tracker/index.php ?func=detail&aid=31566

Paul Marshall portsidepaul at hotmail.com
Wed May 23 06:17:42 CEST 2012


Revision: 3388
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3388
Author:   brikbot
Date:     2012-05-23 04:17:42 +0000 (Wed, 23 May 2012)
Log Message:
-----------
EdgeTools: http://projects.blender.org/tracker/index.php?func=detail&aid=31566

Added Paths:
-----------
    contrib/py/scripts/addons/mesh_edgetools.py

Added: contrib/py/scripts/addons/mesh_edgetools.py
===================================================================
--- contrib/py/scripts/addons/mesh_edgetools.py	                        (rev 0)
+++ contrib/py/scripts/addons/mesh_edgetools.py	2012-05-23 04:17:42 UTC (rev 3388)
@@ -0,0 +1,1596 @@
+# Blender EdgeTools
+#
+# This is a toolkit for edge manipulation based on several of mesh manipulation
+# abilities of several CAD/CAE packages, notably CATIA's Geometric Workbench
+# from which most of these tools have a functional basis based on the paradims
+# that platform enables.  These tools are a collection of scripts that I needed
+# at some point, and so I will probably add and improve these as I continue to
+# use and model with them.
+#
+# It might be good to eventually merge the tinyCAD VTX tools for unification
+# purposes, and as these are edge-based tools, it would make sense.  Or maybe
+# merge this with tinyCAD instead?
+#
+# The GUI and Blender add-on structure shamelessly coded in imitation of the
+# LoopTools addon.
+#
+# Examples:
+#   - "Ortho" inspired from CATIA's line creation tool which creates a line of a
+#       user specified length at a user specified angle to a curve at a chosen
+#       point.  The user then selects the plane the line is to be created in.
+#   - "Shaft" is inspired from CATIA's tool of the same name.  However, instead
+#       of a curve around an axis, this will instead shaft a line, a point, or
+#       a fixed radius about the selected axis.
+#   - "Slice" is from CATIA's ability to split a curve on a plane.  When
+#       completed this be a Python equivalent with all the same basic
+#       functionality, though it will sadly be a little clumsier to use due
+#       to Blender's selection limitations.
+#
+# Tasks:
+#   - Figure out how to do a GUI for "Shaft", especially for controlling radius.
+#
+# Paul "BrikBot" Marshall
+# Created: January 28, 2012
+# Last Modified: May 11, 2012
+# Homepage (blog): http://post.darkarsenic.com/
+#                       //blog.darkarsenic.com/
+#
+# Coded in IDLE, tested in Blender 2.63.
+# Search for "@todo" to quickly find sections that need work.
+#
+# Remeber -
+#   Functional code comes before fast code.  Once it works, then worry about
+#   making it faster/more efficient.
+#
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  The Blender Edgetools is to bring CAD tools to Blender.
+#  Copyright (C) 2012  Paul Marshall
+#
+#  This program is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+# ^^ Maybe. . . . :P
+
+bl_info = {
+    'name': "EdgeTools",
+    'author': "Paul Marshall",
+    'version': (0, 8),
+    'blender': (2, 6, 3),
+    'location': "View3D > Toolbar and View3D > Specials (W-key)",
+    'warning': "",
+    'description': "CAD style edge manipulation tools",
+    'wiki_url': "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Modeling/EdgeTools",
+    'tracker_url': "https://blenderpython.svn.sourceforge.net/svnroot/blenderpython/scripts_library/scripts/addons_extern/mesh_edgetools.py",
+    'category': 'Mesh'}
+
+import bpy, bmesh, mathutils
+from math import pi, radians, sin, sqrt, tan
+from mathutils import Matrix, Vector
+from mathutils.geometry import (distance_point_to_plane,
+                                interpolate_bezier,
+                                intersect_point_line,
+                                intersect_line_line,
+                                intersect_line_plane)
+from bpy.props import (BoolProperty,
+                       BoolVectorProperty,
+                       IntProperty,
+                       FloatProperty,
+                       EnumProperty)
+
+# Quick an dirty method for getting the sign of a number:
+def sign(number):
+    return (number > 0) - (number < 0)
+
+
+# is_parallel
+#
+# Checks to see if two lines are parallel
+def is_parallel(v1, v2, v3, v4):
+    result = intersect_line_line(v1, v2, v3, v4) 
+    return result == None
+
+
+# is_axial
+#
+# This is for the special case where the edge is parallel to an axis.  In this
+# the projection onto the XY plane will fail so it will have to be handled
+# differently.  This tells us if and how:
+def is_axial(v1, v2, error = 0.000002):
+    vector = v2 - v1
+    # Don't need to store, but is easier to read:
+    vec0 = vector[0] > -error and vector[0] < error
+    vec1 = vector[1] > -error and vector[1] < error
+    vec2 = vector[2] > -error and vector[2] < error
+    if (vec0 or vec1) and vec2:
+        return 'Z'
+    elif vec0 and vec1:
+        return 'Y'
+    return None
+
+
+# is_same_co
+#
+# For some reason "Vector = Vector" does not seem to look at the actual
+# coordinates.  This provides a way to do so.
+def is_same_co(v1, v2):
+    if len(v1) != len(v2):
+        return False
+    else:
+        for co1, co2 in zip(v1, v2):
+            if co1 != co2:
+                return False
+    return True
+
+
+# other_joined_edges
+#
+# Starts with an edge.  Then scans for linked, selected edges and builds a
+# list with them in "order", starting at one end and moving towards the other.
+def order_joined_edges(edge, edges = [], direction = 1):
+    if len(edges) == 0:
+        edges.append(edge)
+        edges[0] = edge
+
+##    if bpy.app.debug:
+##        print(edge, end = ", ")
+##        print(edges, end = ", ")
+##        print(direction, end = "; ")
+
+    newList = []
+    for e in edge.verts[0].link_edges:
+        if e.select and edges.count(e) == 0:
+            if direction > 0:
+                edges.insert(0, e)
+                newList.extend(order_joined_edges(e, edges, direction + 1))
+                newList.extend(edges)
+            else:
+                edges.append(e)
+                newList.extend(edges)
+                newList.extend(order_joined_edges(e, edges, direction - 1))
+
+    # This will only matter at the first level:
+    direction = direction - 1
+
+    for e in edge.verts[1].link_edges:
+        if e.select and edges.count(e) == 0:
+            if direction > 0:
+                edges.insert(0, e)
+                newList.extend(order_joined_edges(e, edges, direction + 2))
+                newList.extend(edges)
+            else:
+                edges.append(e)
+                newList.extend(edges)
+                newList.extend(order_joined_edges(e, edges, direction))
+
+##    if bpy.app.debug:
+##        print(newList, end = ", ")
+##        print(direction)
+
+    return newList
+
+
+# --------------- GEOMETRY CALCULATION METHODS --------------
+
+# distance_point_line
+#
+# I don't know why the mathutils.geometry API does not already have this, but
+# it is trivial to code using the structures already in place.  Instead of
+# returning a float, I also want to know the direction vector defining the
+# distance.  Distance can be found with "Vector.length".
+def distance_point_line(pt, line_p1, line_p2):
+    int_co = intersect_point_line(pt, line_p1, line_p2)
+    distance_vector = int_co[0] - pt
+    return distance_vector
+
+
+# interpolate_line_line
+#
+# This is an experiment into a cubic Hermite spline (c-spline) for connecting
+# two edges with edges that obey the general equation.
+# This will return a set of point coordinates (Vectors).
+#
+# A good, easy to read background on the mathematics can be found at:
+# http://cubic.org/docs/hermite.htm
+#
+# Right now this is . . . less than functional :P
+# @todo
+#   - C-Spline and Bezier curves do not end on p2_co as they are supposed to.
+#   - B-Spline just fails.  Epically.
+#   - Add more methods as I come across them.  Who said flexibility was bad?
+def interpolate_line_line(p1_co, p1_dir, p2_co, p2_dir, segments, tension = 1,
+                          typ = 'BEZIER', include_ends = False):
+    pieces = []
+    fraction = 1 / segments
+    # Form: p1, tangent 1, p2, tangent 2
+    if typ == 'HERMITE':
+        poly = [[2, -3, 0, 1], [1, -2, 1, 0],
+                [-2, 3, 0, 0], [1, -1, 0, 0]]
+    elif typ == 'BEZIER':
+        poly = [[-1, 3, -3, 1], [3, -6, 3, 0],
+                [1, 0, 0, 0], [-3, 3, 0, 0]]
+        p1_dir = p1_dir + p1_co
+        p2_dir = -p2_dir + p2_co
+    elif typ == 'BSPLINE':
+##        Supposed poly matrix for a cubic b-spline:
+##        poly = [[-1, 3, -3, 1], [3, -6, 3, 0],
+##                [-3, 0, 3, 0], [1, 4, 1, 0]]
+        # My own invention to try to get something that somewhat acts right.
+        # This is semi-quadratic rather than fully cubic:
+        poly = [[0, -1, 0, 1], [1, -2, 1, 0],
+                [0, -1, 2, 0], [1, -1, 0, 0]]
+    if include_ends:
+        pieces.append(p1_co)
+    # Generate each point:
+    for i in range(segments - 1):
+        t = fraction * (i + 1)
+        if bpy.app.debug:
+            print(t)
+        s = [t ** 3, t ** 2, t, 1]
+        h00 = (poly[0][0] * s[0]) + (poly[0][1] * s[1]) + (poly[0][2] * s[2]) + (poly[0][3] * s[3])
+        h01 = (poly[1][0] * s[0]) + (poly[1][1] * s[1]) + (poly[1][2] * s[2]) + (poly[1][3] * s[3])
+        h10 = (poly[2][0] * s[0]) + (poly[2][1] * s[1]) + (poly[2][2] * s[2]) + (poly[2][3] * s[3])
+        h11 = (poly[3][0] * s[0]) + (poly[3][1] * s[1]) + (poly[3][2] * s[2]) + (poly[3][3] * s[3])
+        pieces.append((h00 * p1_co) + (h01 * p1_dir) + (h10 * p2_co) + (h11 * p2_dir))
+    if include_ends:
+        pieces.append(p2_co)
+    # Return:
+    if len(pieces) == 0:
+        return None
+    else:
+        if bpy.app.debug:
+            print(pieces)
+        return pieces
+
+
+# intersect_line_face
+#
+# Calculates the coordinate of intersection of a line with a face.  It returns
+# the coordinate if one exists, otherwise None.  It can only deal with tris or
+# quads for a face.  A quad does NOT have to be planar. Thus the following.
+#
+# Quad math and theory:

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list