forked from blender/blender-addons
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
1,231 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# ##### 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 bpy | ||
import bmesh | ||
from . import cad_module as cm | ||
|
||
|
||
def add_line_to_bisection(self): | ||
|
||
obj = bpy.context.object | ||
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() | ||
|
||
edges = [e for e in bm.edges if e.select and not e.hide] | ||
|
||
if not len(edges) == 2: | ||
msg = "select two coplanar non parallel edges" | ||
self.report({"WARNING"}, msg) | ||
return | ||
|
||
[[v1, v2], [v3, v4]] = [[v.co for v in e.verts] for e in edges] | ||
print('vectors found:\n', v1, '\n', v2, '\n', v3, '\n', v4) | ||
|
||
dist1 = (v1 - v2).length | ||
dist2 = (v3 - v4).length | ||
bdist = min([dist1, dist2]) | ||
edge1 = (v1, v2) | ||
edge2 = (v3, v4) | ||
|
||
if not cm.test_coplanar(edge1, edge2): | ||
msg = "edges must be coplanar non parallel edges" | ||
self.report({"WARNING"}, msg) | ||
return | ||
|
||
# get pt and pick fartest vertex from (projected) intersections | ||
pt = cm.get_intersection(edge1, edge2) | ||
far1 = v2 if (v1 - pt).length < (v2 - pt).length else v1 | ||
far2 = v4 if (v3 - pt).length < (v4 - pt).length else v3 | ||
# print('intersection: ', pt) | ||
|
||
dex1 = far1 - pt | ||
dex2 = far2 - pt | ||
dex1 = dex1 * (bdist / dex1.length) | ||
dex2 = dex2 * (bdist / dex2.length) | ||
pt2 = pt + (dex1).lerp(dex2, 0.5) | ||
# print('bisector point:', pt2) | ||
|
||
pt3 = pt2.lerp(pt, 2.0) | ||
|
||
vec1 = bm.verts.new(pt2) | ||
vec2 = bm.verts.new(pt) | ||
vec3 = bm.verts.new(pt3) | ||
bm.edges.new((vec1, vec2)) | ||
bm.edges.new((vec2, vec3)) | ||
bmesh.update_edit_mesh(me) | ||
# print("done") | ||
|
||
|
||
class TCLineOnBisection(bpy.types.Operator): | ||
'''Generate the bisector of two selected edges''' | ||
bl_idname = 'tinycad.linetobisect' | ||
bl_label = 'BIX line to bisector' | ||
bl_options = {'REGISTER', 'UNDO'} | ||
|
||
@classmethod | ||
def poll(cls, context): | ||
obj = context.active_object | ||
return all([obj is not None, obj.type == 'MESH', obj.mode == 'EDIT']) | ||
|
||
def execute(self, context): | ||
add_line_to_bisection(self) | ||
return {'FINISHED'} | ||
|
||
|
||
def register(): | ||
bpy.utils.register_module(__name__) | ||
|
||
|
||
def unregister(): | ||
bpy.utils.unregister_module(__name__) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
# ##### 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 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="LINK") | ||
|
||
@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'} | ||
|
||
|
||
def register(): | ||
bpy.utils.register_module(__name__) | ||
|
||
|
||
def unregister(): | ||
bpy.utils.unregister_module(__name__) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# ##### 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 os | ||
import bpy | ||
|
||
ICONS = 'BIX CCEN V2X VTX XALL E2F'.split(' ') | ||
icon_collection = {} | ||
|
||
|
||
class TinyCADProperties(bpy.types.PropertyGroup): | ||
|
||
num_verts = bpy.props.IntProperty( | ||
min=3, max=60, default=12) | ||
|
||
rescale = bpy.props.FloatProperty( | ||
default=1.0, | ||
precision=4, | ||
min=0.0001) | ||
|
||
|
||
class VIEW3D_MT_edit_mesh_tinycad(bpy.types.Menu): | ||
bl_label = "TinyCAD" | ||
|
||
@classmethod | ||
def poll(cls, context): | ||
return bool(context.object) | ||
|
||
def draw(self, context): | ||
|
||
pcoll = icon_collection["main"] | ||
|
||
def cicon(name): | ||
return pcoll[name].icon_id | ||
|
||
op = self.layout.operator | ||
op('tinycad.autovtx', text='VTX | AUTO', icon_value=cicon('VTX')) | ||
op('tinycad.vertintersect', text='V2X | Vertex at intersection', icon_value=cicon('V2X')) | ||
op('tinycad.intersectall', text='XALL | Intersect selected edges', icon_value=cicon('XALL')) | ||
op('tinycad.linetobisect', text='BIX | Bisector of 2 planar edges', icon_value=cicon('BIX')) | ||
op('tinycad.circlecenter', text='CCEN | Resurrect circle center', icon_value=cicon('CCEN')) | ||
op('tinycad.edge_to_face', text='E2F | Extend Edge to Face', icon_value=cicon('E2F')) | ||
|
||
|
||
def register_icons(): | ||
import bpy.utils.previews | ||
pcoll = bpy.utils.previews.new() | ||
icons_dir = os.path.join(os.path.dirname(__file__), "icons") | ||
for icon_name in ICONS: | ||
pcoll.load(icon_name, os.path.join(icons_dir, icon_name + '.png'), 'IMAGE') | ||
|
||
icon_collection["main"] = pcoll | ||
|
||
|
||
def unregister_icons(): | ||
for pcoll in icon_collection.values(): | ||
bpy.utils.previews.remove(pcoll) | ||
icon_collection.clear() | ||
|
||
|
||
def register(): | ||
bpy.utils.register_module(__name__) | ||
|
||
|
||
def unregister(): | ||
bpy.utils.unregister_module(__name__) |
Oops, something went wrong.