Skip to content

Instantly share code, notes, and snippets.

@zeffii
Forked from anonymous/CCEN.py
Created January 3, 2015 17:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeffii/5d0d3a56966a1486968c to your computer and use it in GitHub Desktop.
Save zeffii/5d0d3a56966a1486968c to your computer and use it in GitHub Desktop.
CCEN EXTRA
'''
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
END GPL LICENCE BLOCK
'''
bl_info = {
"name": "tinyCAD Mesh tools",
"author": "zeffii (aka Dealga McArdle)",
"version": (1, 0, 7),
"blender": (2, 7, 3),
"category": "Mesh",
"location": "View3D > EditMode > (w) Specials",
"wiki_url": "",
"tracker_url": ""
}
## implemented lookup table for bmesh changes in 2.73
if "bpy" in locals():
import imp
import bpy
from mesh_tinyCAD.VTX import AutoVTX
from mesh_tinyCAD.V2X import Vert2Intersection
# from mesh_tinyCAD.EXM import ExtendEdgesMulti
from mesh_tinyCAD.XALL import IntersectAllEdges
from mesh_tinyCAD.BIX import LineOnBisection
from mesh_tinyCAD.PERP import CutOnPerpendicular
from mesh_tinyCAD.CCEN import CircleCenter
vtx_classes = (
[AutoVTX, "tinyCAD autoVTX"],
[Vert2Intersection, "tinyCAD V2X"],
[IntersectAllEdges, "tinyCAD XALL"],
# [ExtendEdgesMulti, "tinyCAD EXM"], # this is buggy
[LineOnBisection, "tinyCAD BIX"],
[CutOnPerpendicular, "tinyCAD PERP CUT"],
[CircleCenter, "tC Circle Center"]
)
class VIEW3D_MT_edit_mesh_tinycad(bpy.types.Menu):
bl_label = "TinyCAD"
def draw(self, context):
for i, text in vtx_classes:
self.layout.operator(i.bl_idname, text=text)
class TcInfoDict(bpy.types.PropertyGroup):
# collection property used to store the minimum info to
# generate world space grease pencil circles
num_verts = bpy.props.IntProperty()
p1 = bpy.props.FloatVectorProperty(subtype='XYZ', size=3)
v1 = bpy.props.FloatVectorProperty(subtype='XYZ', size=3)
axis = bpy.props.FloatVectorProperty(subtype='XYZ', size=3)
origin = bpy.props.FloatVectorProperty(subtype='XYZ', size=3)
mw = bpy.props.FloatVectorProperty(subtype='MATRIX', size=16)
def menu_func(self, context):
self.layout.menu("VIEW3D_MT_edit_mesh_tinycad")
self.layout.separator()
def register():
bpy.utils.register_class(TcInfoDict)
bpy.types.Scene.infodict = bpy.props.CollectionProperty(type=TcInfoDict)
for i, _ in vtx_classes:
bpy.utils.register_class(i)
bpy.utils.register_class(VIEW3D_MT_edit_mesh_tinycad)
bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func)
def unregister():
for i, _ in vtx_classes:
bpy.utils.unregister_class(i)
bpy.utils.unregister_class(VIEW3D_MT_edit_mesh_tinycad)
bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func)
del bpy.types.Scene.infodict
bpy.utils.unregister_class(TcInfoDict)
'''
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
END GPL LICENCE BLOCK
'''
import math
import bpy
import bmesh
import mathutils
from mathutils import geometry
from mathutils import Vector, Matrix
def flatten_matrix(m):
"""
can't FloatVectorProperty(subtype='MATRIX', size=16)
figure this out?!
"""
tk = []
for v in m:
for c in v[:]:
tk.append(c)
return tk
# def reshape_matrix(mf):
# print('bullshit,', mf)
# mw = Matrix()
# for j, i in enumerate(range(0, 16, 4)):
# mw[j] = mf[i:i+4]
# return mw
def draw_onto_layer(layer, scn):
# chances are it exists, let's nix it.
layer.frames[0].clear()
idc = scn.infodict[0]
num_verts = idc.num_verts
p1 = idc.p1
v1 = idc.v1
origin = idc.origin
axis = idc.axis
mw = idc.mw
layer.show_points = True
layer.color = (0.2, 0.90, .2)
s = layer.frames[0].strokes.new()
s.draw_mode = '3DSPACE'
chain = []
gamma = 2 * math.pi / num_verts
for i in range(num_verts+1):
theta = gamma * i
mat_rot = mathutils.Matrix.Rotation(theta, 4, axis)
local_point = mw * (mat_rot * (v1 - p1))
world_point = local_point - (origin - (mw*p1))
chain.append(world_point)
s.points.add(len(chain))
for idx, p in enumerate(chain):
s.points[idx].co = p
def generate_gp3d_stroke(p1, v1, axis, mw, origin, scn):
'''
p1: center of circle (local coordinates)
v1: first vertex of circle in (local coordinates)
axis: orientation matrix
mw: obj.matrix_world
origin: obj.location
'''
# get grease pencil data
# hella clunky for testing.
grease_pencil_name = 'tc_circle_000'
layer_name = "TinyCad Layer"
grease_data = bpy.data.grease_pencil
if grease_pencil_name not in grease_data:
gp = grease_data.new(grease_pencil_name)
else:
gp = grease_data[grease_pencil_name]
# get grease pencil layer
if not (layer_name in gp.layers):
layer = gp.layers.new(layer_name)
layer.frames.new(1)
layer.line_width = 1
else:
layer = gp.layers[layer_name]
idc = scn.infodict.add()
idc.num_verts = 20
idc.p1 = p1
idc.v1 = v1
idc.origin = origin
idc.axis = axis
idc.mw = flatten_matrix(mw)
draw_onto_layer(layer, scn)
def generate_3PT_mode_1(pts, obj, scn):
origin = obj.location
mw = obj.matrix_world
V = Vector
# construction
v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2])
edge1_mid = v1.lerp(v2, 0.5)
edge2_mid = v3.lerp(v4, 0.5)
axis = geometry.normal(v1, v2, v4)
mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis)
# triangle edges
v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid
v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid
v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid
v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid
r = geometry.intersect_line_line(v1_, v2_, v3_, v4_)
if r:
p1, _ = r
cp = mw * p1
bpy.context.scene.cursor_location = cp
generate_gp3d_stroke(p1, v1, axis, mw, origin, scn)
else:
print('not on a circle')
def get_three_verts_from_selection(obj):
me = obj.data
bm = bmesh.from_edit_mesh(me)
if hasattr(bm.verts, "ensure_lookup_table"):
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
return [v.co[:] for v in bm.verts if v.select]
class CircleCenter(bpy.types.Operator):
bl_idname = 'mesh.circlecenter'
bl_label = 'circle center from selected'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(self, context):
obj = context.active_object
return obj is not None and obj.type == 'MESH' and obj.mode == 'EDIT'
def execute(self, context):
obj = bpy.context.object
pts = get_three_verts_from_selection(obj)
generate_3PT_mode_1(pts, obj, context.scene)
return {'FINISHED'}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment