Skip to content
Snippets Groups Projects
Commit 02d5067f authored by Campbell Barton's avatar Campbell Barton
Browse files

add a second experimental method of solving bezier splines, by Vincent Tan.

parent 67bc2ad7
No related branches found
No related tags found
No related merge requests found
...@@ -361,13 +361,72 @@ def points_to_bezier(points_orig, ...@@ -361,13 +361,72 @@ def points_to_bezier(points_orig,
self.calc_all() self.calc_all()
def bezier_solve(self): def bezier_solve_(self):
""" Calculate bezier handles, """ Calculate bezier handles,
assume the splines have been broken up. assume the splines have been broken up.
http://polymathprogrammer.com/
""" """
p1 = self.points[0]
p2 = self.points[-1]
line_ix_p1 = self.points[len(self.points) // 3]
line_ix_p2 = self.points[int((len(self.points) / 3) * 2)]
u = 1 / 3
v = 2 / 3
p0x, p0y, p0z = p1.co
p1x, p1y, p1z = line_ix_p1.co
p2x, p2y, p2z = line_ix_p2.co
p3x, p3y, p3z = p2.co
ui = 1.0 - u
vi = 1.0 - v
u_p3 = u * u * u
v_p3 = v * v * v
ui_p3 = ui * ui * ui
vi_p3 = vi * vi * vi
# --- snip
q1 = Vector()
q2 = Vector()
pos = Vector(), Vector(), Vector(), Vector()
a = 3.0 * ui * ui * u
b = 3.0 * ui * u * u
c = 3.0 * vi * vi * v
d = 3.0 * vi * v * v
det = a * d - b * c
if det == 0.0:
assert(0)
return 0
q1.x = p1x - (ui_p3 * p0x + u_p3 * p3x)
q1.y = p1y - (ui_p3 * p0y + u_p3 * p3y)
q1.z = p1z - (ui_p3 * p0z + u_p3 * p3z)
q2.x = p2x - (vi_p3 * p0x + v_p3 * p3x)
q2.y = p2y - (vi_p3 * p0y + v_p3 * p3y)
q2.z = p2z - (vi_p3 * p0z + v_p3 * p3z)
pos[1].x = (d * q1.x - b * q2.x) / det
pos[1].y = (d * q1.y - b * q2.y) / det
pos[1].z = (d * q1.z - b * q2.z) / det
pos[2].x = ((-c) * q1.x + a * q2.x) / det
pos[2].y = ((-c) * q1.y + a * q2.y) / det
pos[2].z = ((-c) * q1.z + a * q2.z) / det
self.handle_left = pos[1]
self.handle_right = pos[2]
def bezier_solve(self):
from mathutils.geometry import (intersect_point_line, from mathutils.geometry import (intersect_point_line,
intersect_line_line, intersect_line_line,
) )
...@@ -391,58 +450,19 @@ def points_to_bezier(points_orig, ...@@ -391,58 +450,19 @@ def points_to_bezier(points_orig,
# visualize_line(p2.co, l2_co) # visualize_line(p2.co, l2_co)
# picking 1/2 and 2/3'rds works best # picking 1/2 and 2/3'rds works best
line_ix_p1 = self.points[len(self.points) // 3] line_ix_p1 = self.points[int(len(self.points) * (1.0 / 3.0))]
line_ix_p1_co, line_ix_p1_no = line_ix_p1.co, line_ix_p1.no line_ix_p1_co, line_ix_p1_no = line_ix_p1.co, line_ix_p1.no
line_ix_p2 = self.points[int((len(self.points) / 3) * 2)] line_ix_p2 = self.points[int(len(self.points) * (2.0 / 3.0))]
line_ix_p2_co, line_ix_p2_no = line_ix_p2.co, line_ix_p2.no line_ix_p2_co, line_ix_p2_no = line_ix_p2.co, line_ix_p2.no
if line_ix_p1_co is None: # used to seek for the upper most point but this gives mostly
line_ix_p1_co, line_ix_p1_no, line_ix_p1 = \ # as good results
p1.next.co, p1.next.no, p1.next p1_apex_co = self.points[int(len(self.points) * (1.0 / 3.0) * 0.75)].co
if line_ix_p2_co is None: p2_apex_co = self.points[int(len(self.points) * (1.0 - (1.0 / 3.0) * 0.75))].co
line_ix_p2_co, line_ix_p2_no, line_ix_p2 = \
p2.prev.co, p2.prev.no, p2.prev
# vis_circle_object(line_ix_p1_co)
# vis_circle_object(line_ix_p2_co)
l1_max = 0.0
p1_apex_co = None
p = self.points[1]
while p and (not p.is_joint) and p != line_ix_p1:
ix = intersect_point_line(p.co, p1.co, l1_co)[0]
length = (ix - p.co).length
if length > l1_max:
l1_max = length
p1_apex_co = p.co
p = p.next
l2_max = 0.0
p2_apex_co = None
p = self.points[-2]
while p and (not p.is_joint) and p != line_ix_p2:
ix = intersect_point_line(p.co, p2.co, l2_co)[0]
length = (ix - p.co).length
if length > l2_max:
l2_max = length
p2_apex_co = p.co
p = p.prev
if p1_apex_co is None:
p1_apex_co = p1.next.co
if p2_apex_co is None:
p2_apex_co = p2.prev.co
l1_tan = (p1.no - p1.no.project(l1_no)).normalized() l1_tan = (p1.no - p1.no.project(l1_no)).normalized()
l2_tan = -(p2.no - p2.no.project(l2_no)).normalized() l2_tan = -(p2.no - p2.no.project(l2_no)).normalized()
# values are good!
#~ visualize_line(p1.co, p1.co + l1_tan)
#~ visualize_line(p2.co, p2.co + l2_tan)
#~ visualize_line(p1.co, p1.co + l1_no)
#~ visualize_line(p2.co, p2.co + l2_no)
# calculate bias based on the position of the other point allong # calculate bias based on the position of the other point allong
# the tangent. # the tangent.
...@@ -454,7 +474,7 @@ def points_to_bezier(points_orig, ...@@ -454,7 +474,7 @@ def points_to_bezier(points_orig,
from math import pi from math import pi
# This could be tweaked but seems to work well # This could be tweaked but seems to work well
fac_fac = (p1.co - p2.co).length * p1.no.angle(l2_no_ref) / pi fac_fac = (p1.co - p2.co).length * p1.no.angle(l2_no_ref) / (pi * 1.0)
fac_1 = intersect_point_line(p2_apex_co, fac_1 = intersect_point_line(p2_apex_co,
p1.co, p1.co,
...@@ -474,14 +494,14 @@ def points_to_bezier(points_orig, ...@@ -474,14 +494,14 @@ def points_to_bezier(points_orig,
self.handle_left = h1 self.handle_left = h1
self.handle_right = h2 self.handle_right = h2
''' """
visualize_line(p1.co, p1_apex_co) visualize_line(p1.co, p1_apex_co)
visualize_line(p1_apex_co, p2_apex_co) visualize_line(p1_apex_co, p2_apex_co)
visualize_line(p2.co, p2_apex_co) visualize_line(p2.co, p2_apex_co)
visualize_line(p1.co, p2.co) visualize_line(p1.co, p2.co)
''' """
def bezier_error(self, error_max=-1.0, test_count=8): def bezier_error(self, error_max=-1.0, test_count=16):
from mathutils.geometry import interpolate_bezier from mathutils.geometry import interpolate_bezier
test_points = interpolate_bezier(self.points[0].co, test_points = interpolate_bezier(self.points[0].co,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment