[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [1934] trunk/py/scripts/addons/ mesh_inset: moving Inset script to trunk/py/scripts/addons/mesh_inset

Brendon Murphy meta.androcto1 at gmail.com
Mon May 16 12:52:49 CEST 2011


Revision: 1934
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=1934
Author:   meta-androcto
Date:     2011-05-16 10:52:48 +0000 (Mon, 16 May 2011)
Log Message:
-----------
moving Inset script to trunk/py/scripts/addons/mesh_inset
thanks to howardt for this great addition.

Added Paths:
-----------
    trunk/py/scripts/addons/mesh_inset/
    trunk/py/scripts/addons/mesh_inset/__init__.py
    trunk/py/scripts/addons/mesh_inset/geom.py
    trunk/py/scripts/addons/mesh_inset/model.py
    trunk/py/scripts/addons/mesh_inset/offset.py
    trunk/py/scripts/addons/mesh_inset/triquad.py

Removed Paths:
-------------
    contrib/py/scripts/addons/mesh_inset/

Added: trunk/py/scripts/addons/mesh_inset/__init__.py
===================================================================
--- trunk/py/scripts/addons/mesh_inset/__init__.py	                        (rev 0)
+++ trunk/py/scripts/addons/mesh_inset/__init__.py	2011-05-16 10:52:48 UTC (rev 1934)
@@ -0,0 +1,177 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  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 2
+#  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, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+bl_info = {
+  "name": "Inset Polygon",
+  "author": "Howard Trickey",
+  "version": (0, 2),
+  "blender": (2, 5, 7),
+  "api": 36147,
+  "location": "View3D > Tools",
+  "description": "Make an inset polygon inside selection.",
+  "warning": "",
+  "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Modeling/Inset-Polygon",
+  "tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=27290&group_id=153&atid=468",
+  "category": "Mesh"}
+
+if "bpy" in locals():
+  import imp
+else:
+  from . import geom
+  from . import model
+  from . import offset
+  from . import triquad
+
+import math
+import bpy
+import mathutils
+from bpy.props import *
+
+
+class Inset(bpy.types.Operator):
+  bl_idname = "mesh.inset"
+  bl_label = "Inset"
+  bl_description = "Make an inset polygon inside selection"
+  bl_options = {'REGISTER', 'UNDO'}
+
+  inset_amount = FloatProperty(name="Amount",
+    description="Distance of inset edges from outer ones",
+    default = 0.05,
+    min = 0.0,
+    max = 1000.0,
+    soft_min = 0.0,
+    soft_max = 1.0,
+    unit = 'LENGTH')
+  inset_height = FloatProperty(name="Height",
+    description="Distance to raise inset faces",
+    default = 0.0,
+    min = -1000.0,
+    max = 1000.0,
+    soft_min = -1.0,
+    soft_max = 1.0,
+    unit = 'LENGTH')
+  region = BoolProperty(name="Region",
+    description="Inset selection as one region?",
+    default = True)
+
+  @classmethod
+  def poll(cls, context):
+    obj = context.active_object
+    return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+  def draw(self, context):
+    layout= self.layout
+    box = layout.box()
+    box.label("Inset Options")
+    box.prop(self, "inset_amount")
+    box.prop(self, "inset_height")
+    box.prop(self, "region")
+
+  def invoke(self, context, event):
+    self.action(context)
+    return {'FINISHED'}
+
+  def execute(self, context):
+    self.action(context)
+    return {'FINISHED'}
+
+  def action(self, context):
+    save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+    bpy.context.user_preferences.edit.use_global_undo = False
+    bpy.ops.object.mode_set(mode='OBJECT')
+    obj = bpy.context.active_object
+    mesh = obj.data
+    do_inset(mesh, self.inset_amount, self.inset_height, self.region)
+    bpy.ops.object.mode_set(mode='EDIT')
+    bpy.context.user_preferences.edit.use_global_undo = save_global_undo
+
+
+def do_inset(mesh, amount, height, region):
+  if amount <= 0.0:
+    return
+  pitch = math.atan(height / amount)
+  selfaces = []
+  selface_indices = []
+  for face in mesh.faces:
+    if face.select and not face.hide:
+      selfaces.append(face)
+      selface_indices.append(face.index)
+  m = geom.Model()
+  # if add all mesh.vertices, coord indices will line up
+  # Note: not using Points.AddPoint which does dup elim
+  # because then would have to map vertices in and out
+  m.points.pos = [ v.co.to_tuple() for v in mesh.vertices ]
+  for f in selfaces:
+    m.faces.append(list(f.vertices))
+  orig_numv = len(m.points.pos)
+  orig_numf = len(m.faces)
+  model.BevelSelectionInModel(m, m.faces, amount, pitch, True, region)
+  if len(m.faces) == orig_numf:
+    # something went wrong with Bevel - just treat as no-op
+    return
+  # blender_faces: newfaces but all 4-tuples and no 0
+  # in 4th position if a 4-sided poly
+  blender_faces = []
+  for i in range(orig_numf, len(m.faces)):
+    f = m.faces[i]
+    if len(f) == 3:
+      blender_faces.append(list(f) + [0])
+    elif len(f) == 4:
+      if f[3] == 0:
+        blender_faces.append([f[3], f[0], f[1], f[2]])
+      else:
+        blender_faces.append(f)
+  num_new_vertices = len(m.points.pos) - orig_numv
+  mesh.vertices.add(num_new_vertices)
+  for i in range(orig_numv, len(m.points.pos)):
+    mesh.vertices[i].co = mathutils.Vector(m.points.pos[i])
+  start_faces = len(mesh.faces)
+  mesh.faces.add(len(blender_faces))
+  for i, newf in enumerate(blender_faces):
+    mesh.faces[start_faces + i].vertices_raw = newf
+  mesh.update(calc_edges = True)
+  # remove original faces
+  bpy.ops.object.mode_set(mode='EDIT')
+  save_select_mode = bpy.context.tool_settings.mesh_select_mode
+  bpy.context.tool_settings.mesh_select_mode = [False, False, True]
+  bpy.ops.mesh.select_all(action = 'DESELECT')
+  bpy.ops.object.mode_set(mode = 'OBJECT')
+  for fi in selface_indices:
+    mesh.faces[fi].select = True
+  bpy.ops.object.mode_set(mode = 'EDIT')
+  bpy.ops.mesh.delete(type = 'FACE')
+  bpy.context.tool_settings.mesh_select_mode = save_select_mode
+
+
+def panel_func(self, context):
+  self.layout.label(text="Inset:")
+  self.layout.operator("mesh.inset", text="Inset")
+
+
+def register():
+  bpy.utils.register_class(Inset)
+  bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+
+def unregister():
+  bpy.utils.unregister_class(Inset)
+  bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+  register()

Added: trunk/py/scripts/addons/mesh_inset/geom.py
===================================================================
--- trunk/py/scripts/addons/mesh_inset/geom.py	                        (rev 0)
+++ trunk/py/scripts/addons/mesh_inset/geom.py	2011-05-16 10:52:48 UTC (rev 1934)
@@ -0,0 +1,696 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  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 2
+#  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, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+"""Geometry classes and operations.
+Also, vector file representation (Art).
+"""
+
+__author__ = "howard.trickey at gmail.com"
+
+import math
+
+# distances less than about DISTTOL will be considered
+# essentially zero
+DISTTOL = 1e-3
+INVDISTTOL = 1e3
+
+
+class Points(object):
+  """Container of points without duplication, each mapped to an int.
+
+  Points are either have dimension at least 2, maybe more.
+
+  Implementation:
+  In order to efficiently find duplicates, we quantize the points
+  to triples of ints and map from quantized triples to vertex
+  index.
+
+  Attributes:
+    pos: list of tuple of float - coordinates indexed by
+        vertex number
+    invmap: dict of (int, int, int) to int - quantized coordinates
+        to vertex number map
+  """
+
+  def __init__(self, initlist = []):
+    self.pos = []
+    self.invmap = dict()
+    for p in initlist:
+      self.AddPoint(p)
+
+  @staticmethod
+  def Quantize(p):
+    """Quantize the float tuple into an int tuple.
+
+    Args:
+      p: tuple of float
+    Returns:
+      tuple of int - scaled by INVDISTTOL and rounded p
+    """
+
+    return tuple([int(round(v*INVDISTTOL)) for v in p])
+
+  def AddPoint(self, p):
+    """Add point p to the Points set and return vertex number.
+
+    If there is an existing point which quantizes the same,,
+    don't add a new one but instead return existing index.
+
+    Args:
+      p: tuple of float - coordinates (2-tuple or 3-tuple)
+    Returns:
+      int - the vertex number of added (or existing) point
+    """
+
+    qp = Points.Quantize(p)
+    if qp in self.invmap:
+      return self.invmap[qp]
+    else:
+      self.invmap[qp] = len(self.pos)
+      self.pos.append(p)
+      return len(self.pos)-1
+
+  def AddPoints(self, points):
+    """Add another set of points to this set.
+
+    We need to return a mapping from indices
+    in the argument points space into indices
+    in this point space.
+
+    Args:
+      points: Points - to union into this set
+    Returns:
+      list of int: maps added indices to new ones
+    """
+
+    vmap = [ 0 ] * len(points.pos)
+    for i in range(len(points.pos)):
+      vmap[i] = self.AddPoint(points.pos[i])
+    return vmap
+
+  def AddZCoord(self, z):
+    """Change this in place to have a z coordinate, with value z.
+
+    Assumes the coordinates are currently 2d.
+
+    Args:
+      z: the value of the z coordinate to add
+    Side Effect:
+      self now has a z-coordinate added
+    """
+
+    assert(len(self.pos) == 0 or len(self.pos[0]) == 2)
+    newinvmap = dict()
+    for i, (x,y) in enumerate(self.pos):
+      newp = (x, y, z)
+      self.pos[i] = newp
+      newinvmap[self.Quantize(newp)] = i
+    self.invmap = newinvmap
+
+  def AddToZCoord(self, i, delta):
+    """Change the z-coordinate of point with index i to add delta.
+
+    Assumes the coordinates are currently 3d.
+
+    Args:
+      i: int - index of a point
+      delta: float - value to add to z-coord
+    """
+
+    (x, y, z) = self.pos[i]
+    self.pos[i] = (x, y, z + delta)
+
+
+class PolyArea(object):
+  """Contains a Polygonal Area (polygon with possible holes).
+
+  A polygon is a list of vertex ids, each an index given by
+  a Points object. The list represents a CCW-oriented
+  outer boundary (implicitly closed).

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list