2 by Yann Bertrand, january 2014.
4 BEGIN GPL LICENSE BLOCK
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 "name": "Curve Outline",
25 "description": "creates an Outline",
26 "author": "Yann Bertrand (jimflim), Vladimir Spivak (cwolf3d)",
28 "blender": (2, 69, 0),
33 from mathutils
import Vector
34 from mathutils
.geometry
import intersect_line_line
39 def createOutline(curve
, outline
):
41 for spline
in curve
.data
.splines
[:]:
42 if spline
.type == 'BEZIER':
43 p
= spline
.bezier_points
48 n
= ((p
[0].handle_right
- p
[0].co
).normalized() - (p
[0].handle_left
- p
[0].co
).normalized()).normalized()
49 n
= Vector((-n
[1], n
[0], n
[2]))
50 o
= p
[0].co
+ outline
* n
53 for i
in range(1,len(p
)-1):
54 n
= ((p
[i
].handle_right
- p
[i
].co
).normalized() - (p
[i
].handle_left
- p
[i
].co
).normalized()).normalized()
55 n
= Vector((-n
[1], n
[0], n
[2]))
56 o
= intersect_line_line(out
[-1], (out
[-1]+p
[i
].co
- p
[i
-1].co
), p
[i
].co
, p
[i
].co
+ n
)[0]
59 n
= ((p
[-1].handle_right
- p
[-1].co
).normalized() - (p
[-1].handle_left
- p
[-1].co
).normalized()).normalized()
60 n
= Vector((-n
[1], n
[0], n
[2]))
61 o
= p
[-1].co
+ outline
* n
64 curve
.data
.splines
.new(spline
.type)
65 if spline
.use_cyclic_u
:
66 curve
.data
.splines
[-1].use_cyclic_u
= True
67 p_out
= curve
.data
.splines
[-1].bezier_points
70 for i
in range(len(out
)):
71 p_out
[i
].handle_left_type
= 'FREE'
72 p_out
[i
].handle_right_type
= 'FREE'
77 l
= (p
[i
+ 1].co
- p
[i
].co
).length
78 l2
= (out
[i
] - out
[i
+ 1]).length
81 p_out
[i
].handle_left
= out
[i
] + ((p
[i
].handle_left
- p
[i
].co
) * l2
/l
)
83 p_out
[i
+ 1].handle_left
= out
[i
+ 1] + ((p
[i
+ 1].handle_left
- p
[i
+ 1].co
) * l2
/l
)
84 p_out
[i
].handle_right
= out
[i
] + ((p
[i
].handle_right
- p
[i
].co
) * l2
/l
)
86 for i
in range(len(p
)):
87 p_out
[i
].handle_left_type
= p
[i
].handle_left_type
88 p_out
[i
].handle_right_type
= p
[i
].handle_right_type
91 if len(spline
.points
) < 2:
94 for point
in spline
.points
:
95 v
= Vector((point
.co
[0], point
.co
[1], point
.co
[2]))
99 n
= ((p
[1] - p
[0]).normalized() - (p
[-1] - p
[0]).normalized()).normalized()
100 n
= Vector((-n
[1], n
[0], n
[2]))
101 o
= p
[0] + outline
* n
104 for i
in range(1,len(p
)-1):
105 n
= ((p
[i
+1] - p
[i
]).normalized() - (p
[i
-1] - p
[i
]).normalized()).normalized()
106 n
= Vector((-n
[1], n
[0], n
[2]))
107 o
= intersect_line_line(out
[-1], (out
[-1]+p
[i
] - p
[i
-1]), p
[i
], p
[i
] + n
)[0]
110 n
= ((p
[0] - p
[-1]).normalized() - (p
[-2] - p
[-1]).normalized()).normalized()
111 n
= Vector((-n
[1], n
[0], n
[2]))
112 o
= p
[-1] + outline
* n
115 curve
.data
.splines
.new(spline
.type)
116 if spline
.use_cyclic_u
:
117 curve
.data
.splines
[-1].use_cyclic_u
= True
118 p_out
= curve
.data
.splines
[-1].points
119 p_out
.add(len(out
)-1)
121 for i
in range(len(out
)):
122 p_out
[i
].co
= (out
[i
][0], out
[i
][1], out
[i
][2], 0.0)
127 class CurveOutline(bpy
.types
.Operator
):
129 bl_idname
= "curvetools.outline"
130 bl_label
= "Create Outline"
131 bl_options
= {'REGISTER', 'UNDO'}
132 outline
: bpy
.props
.FloatProperty(name
="Amount", default
=0.1)
135 def poll(cls
, context
):
136 return util
.Selected1OrMoreCurves()
138 def execute(self
, context
):
139 createOutline(context
.object, self
.outline
)
142 def invoke(self
, context
, event
):
143 return context
.window_manager
.invoke_props_popup(self
, event
)
145 def menu_func(self
, context
):
146 self
.layout
.operator(CurveOutline
.bl_idname
)
150 bpy
.utils
.register_class(operators
)
154 bpy
.utils
.unregister_class(operators
)
156 if __name__
== "__main__":
159 operators
= [CurveOutline
]