Created
January 4, 2015 15:45
-
-
Save zeffii/1a19c06eca26930d19dd to your computer and use it in GitHub Desktop.
ccen2_derived
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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.XALL import IntersectAllEdges | |
from mesh_tinyCAD.BIX import LineOnBisection | |
from mesh_tinyCAD.PERP import CutOnPerpendicular | |
from mesh_tinyCAD.CCEN import CircleCenter | |
from mesh_tinyCAD.CCEN import CirclePanel | |
vtx_classes = ( | |
[AutoVTX, "tinyCAD autoVTX"], | |
[Vert2Intersection, "tinyCAD V2X"], | |
[IntersectAllEdges, "tinyCAD XALL"], | |
[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) | |
def menu_func(self, context): | |
self.layout.menu("VIEW3D_MT_edit_mesh_tinycad") | |
self.layout.separator() | |
def register(): | |
for i, _ in vtx_classes: | |
bpy.utils.register_class(i) | |
bpy.types.Scene.tc_numverts = bpy.props.IntProperty(default=12) | |
bpy.utils.register_class(VIEW3D_MT_edit_mesh_tinycad) | |
bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func) | |
bpy.utils.register_class(CirclePanel) | |
def unregister(): | |
for i, _ in vtx_classes: | |
bpy.utils.unregister_class(i) | |
bpy.utils.unregister_class(CirclePanel) | |
bpy.utils.unregister_class(VIEW3D_MT_edit_mesh_tinycad) | |
bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func) | |
del bpy.types.Scene.tc_numverts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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 | |
def get_layer(): | |
''' | |
this always returns a new empty layer ready for drawing to | |
''' | |
# get grease pencil data | |
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] | |
layer.frames[0].clear() | |
return layer | |
def generate_gp3d_stroke(layer, p1, v1, axis, mw, origin, nv): | |
''' | |
p1: center of circle (local coordinates) | |
v1: first vertex of circle in (local coordinates) | |
axis: orientation matrix | |
mw: obj.matrix_world | |
origin: obj.location | |
nv: numverts | |
''' | |
layer.show_points = True | |
layer.color = (0.2, 0.90, .2) | |
s = layer.frames[0].strokes.new() | |
s.draw_mode = '3DSPACE' | |
chain = [] | |
num_verts = nv | |
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)) # + origin | |
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_geometry3d(obj, p1, v1, axis, mw, origin, nv): | |
''' | |
p1: center of circle (local coordinates) | |
v1: first vertex of circle in (local coordinates) | |
axis: orientation matrix | |
mw: obj.matrix_world | |
origin: obj.location | |
nv: numverts | |
''' | |
oe = obj.data.edges | |
ov = obj.data.vertices | |
vert_count = len(ov) | |
edge_count = len(oe) | |
point_list = [] | |
num_verts = nv | |
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 = (mat_rot * (v1 - p1)) | |
point_list.append(local_point) | |
num_points = len(point_list) | |
num_edges_to_add = num_points-1 | |
for i in range(num_edges_to_add): | |
oe.add(1) | |
ov.add(2) | |
ov[vert_count].co = point_list[i] | |
ov[vert_count+1].co = point_list[i+1] | |
oe[edge_count].vertices = [vert_count, vert_count+1] | |
vert_count = len(ov) | |
edge_count = len(oe) | |
def generate_3PT_mode_1(pts, obj, nv, mode): | |
origin = obj.location | |
mw = obj.matrix_world | |
V = Vector | |
nv = max(3, nv) | |
# 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 | |
if mode == 'FAKE': | |
layer = get_layer() | |
generate_gp3d_stroke(layer, p1, v1, axis, mw, origin, nv) | |
else: | |
generate_geometry3d(obj, p1, v1, axis, mw, origin, nv) | |
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'} | |
nv = bpy.props.IntProperty(default=12) | |
mode = bpy.props.StringProperty(default='FAKE') | |
@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, self.nv, self.mode) | |
return {'FINISHED'} | |
class CirclePanel(bpy.types.Panel): | |
bl_label = "tinyCAD circle" | |
bl_space_type = "VIEW_3D" | |
bl_region_type = "UI" | |
@classmethod | |
def poll(self, context): | |
obj = context.active_object | |
if not obj: | |
return | |
if (obj.type == 'MESH' and obj.mode == 'EDIT'): | |
return obj.data.total_vert_sel >= 3 | |
def draw(self, context): | |
layout = self.layout | |
col = layout.col() | |
col.prop(context.scene, "tc_numverts") | |
s1 = col.operator("mesh.circlecenter", text='Update Circle') | |
s1.nv = context.scene.tc_numverts | |
s1.mode = 'FAKE' | |
s2 = col.operator("mesh.circlecenter", text='Generate Geometry') | |
s2.nv = context.scene.tc_numverts | |
s2.mode = 'REAL' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment