Files
blender-addons/mesh_tiny_cad/CCEN.py
Campbell Barton 9999dada60 Update for API change: scene.cursor_location -> scene.cursor.location
Note that some scripts still used the 3D view cursor which has been
removed for a while.
2019-03-01 12:51:10 +11:00

160 lines
4.4 KiB
Python

# ##### 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 #####
# <pep8 compliant>
import math
import bpy
import bmesh
import mathutils
from mathutils import geometry
from mathutils import Vector
def generate_bmesh_repr(p1, v1, axis, num_verts):
'''
p1: center of circle (local coordinates)
v1: first vertex of circle in (local coordinates)
axis: orientation matrix
origin: obj.location
'''
props = bpy.context.scene.tinycad_props
rescale = props.rescale
# generate geometry up front
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 = (mat_rot @ ((v1 - p1) * rescale))
chain.append(local_point + p1)
obj = bpy.context.edit_object
me = obj.data
bm = bmesh.from_edit_mesh(me)
# add verts
v_refs = []
for p in chain:
v = bm.verts.new(p)
v.select = False # this might be a default.. redundant?
v_refs.append(v)
# join verts, daisy chain
num_verts = len(v_refs)
for i in range(num_verts):
idx1 = i
idx2 = (i + 1) % num_verts
bm.edges.new([v_refs[idx1], v_refs[idx2]])
bmesh.update_edit_mesh(me, True)
def generate_3PT(pts, obj, nv, mode=1):
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 == 0:
pass
elif mode == 1:
generate_bmesh_repr(p1, v1, axis, nv)
else:
print('not on a circle')
def get_three_verts_from_selection(obj):
me = obj.data
bm = bmesh.from_edit_mesh(me)
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
return [v.co[:] for v in bm.verts if v.select]
def dispatch(context, mode=0):
try:
obj = context.edit_object
pts = get_three_verts_from_selection(obj)
props = context.scene.tinycad_props
generate_3PT(pts, obj, props.num_verts, mode)
except:
print('dispatch failed', mode)
class TCCallBackCCEN(bpy.types.Operator):
bl_idname = 'tinycad.reset_circlescale'
bl_label = 'CCEN circle reset'
bl_options = {'REGISTER'}
def execute(self, context):
context.scene.tinycad_props.rescale = 1
return {'FINISHED'}
class TCCircleCenter(bpy.types.Operator):
'''Recreate a Circle from 3 selected verts, move 3dcursor to its center'''
bl_idname = 'tinycad.circlecenter'
bl_label = 'CCEN circle center from selected'
bl_options = {'REGISTER', 'UNDO'}
def draw(self, context):
scn = context.scene
l = self.layout
col = l.column()
col.prop(scn.tinycad_props, 'num_verts', text='num verts')
row = col.row(align=True)
row.prop(scn.tinycad_props, 'rescale', text='rescale')
row.operator('tinycad.reset_circlescale', text="", icon="PIVOT_CURSOR")
@classmethod
def poll(cls, context):
obj = context.edit_object
return obj is not None and obj.type == 'MESH'
def execute(self, context):
dispatch(context, mode=1)
return {'FINISHED'}