[fix] fix bezier when individual handles sit on points
bonus: prevent eternal while loop
This commit is contained in:
parent
963d89daf9
commit
04229fbc31
1 changed files with 68 additions and 29 deletions
97
butils.py
97
butils.py
|
@ -215,6 +215,34 @@ def calc_bezier_length(bezier_point_1, bezier_point_2, resolution=20):
|
||||||
return length
|
return length
|
||||||
|
|
||||||
|
|
||||||
|
def get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor):
|
||||||
|
beziers = []
|
||||||
|
lengths = []
|
||||||
|
total_length = 0
|
||||||
|
n_bezier_points = len(bezier_spline_obj.bezier_points)
|
||||||
|
real_n_bezier_points = len(bezier_spline_obj.bezier_points)
|
||||||
|
if bezier_spline_obj.use_cyclic_u:
|
||||||
|
n_bezier_points += 1
|
||||||
|
for i in range(0, n_bezier_points - 1):
|
||||||
|
i_a = i % (n_bezier_points - 1)
|
||||||
|
i_b = (i_a + 1) % real_n_bezier_points
|
||||||
|
bezier = [
|
||||||
|
bezier_spline_obj.bezier_points[i_a],
|
||||||
|
bezier_spline_obj.bezier_points[i_b],
|
||||||
|
]
|
||||||
|
length = calc_bezier_length(
|
||||||
|
bezier[0],
|
||||||
|
bezier[1],
|
||||||
|
int(bezier_spline_obj.resolution_u * resolution_factor),
|
||||||
|
)
|
||||||
|
total_length += length
|
||||||
|
beziers.append(bezier)
|
||||||
|
lengths.append(length)
|
||||||
|
# if total_length > distance:
|
||||||
|
# break
|
||||||
|
return beziers, lengths, total_length
|
||||||
|
|
||||||
|
|
||||||
def calc_point_on_bezier_spline(
|
def calc_point_on_bezier_spline(
|
||||||
bezier_spline_obj, distance, output_tangent=False, resolution_factor=1.0
|
bezier_spline_obj, distance, output_tangent=False, resolution_factor=1.0
|
||||||
):
|
):
|
||||||
|
@ -241,6 +269,17 @@ def calc_point_on_bezier_spline(
|
||||||
if distance <= 0:
|
if distance <= 0:
|
||||||
p = bezier_spline_obj.bezier_points[0]
|
p = bezier_spline_obj.bezier_points[0]
|
||||||
travel = (p.co - p.handle_left).normalized() * distance
|
travel = (p.co - p.handle_left).normalized() * distance
|
||||||
|
|
||||||
|
# in case the handles sit on the points
|
||||||
|
# we interpolate the travel from points of the bezier
|
||||||
|
# if the bezier points sit on each other we have same issue
|
||||||
|
# but that is then to be fixed in the bezier
|
||||||
|
if p.handle_left == p.co and len(bezier_spline_obj.bezier_points) > 1:
|
||||||
|
beziers, lengths, total_length = get_real_beziers_and_lengths(bezier_spline_obj,
|
||||||
|
resolution_factor)
|
||||||
|
travel_point = calc_point_on_bezier(beziers[0][1], beziers[0][0], 0.001)
|
||||||
|
travel = travel_point.normalized() * distance
|
||||||
|
|
||||||
location = p.co + travel
|
location = p.co + travel
|
||||||
if output_tangent:
|
if output_tangent:
|
||||||
p2 = bezier_spline_obj.bezier_points[1]
|
p2 = bezier_spline_obj.bezier_points[1]
|
||||||
|
@ -249,30 +288,8 @@ def calc_point_on_bezier_spline(
|
||||||
else:
|
else:
|
||||||
return location
|
return location
|
||||||
|
|
||||||
beziers = []
|
beziers, lengths, total_length = get_real_beziers_and_lengths(bezier_spline_obj,
|
||||||
lengths = []
|
resolution_factor)
|
||||||
total_length = 0
|
|
||||||
n_bezier_points = len(bezier_spline_obj.bezier_points)
|
|
||||||
real_n_bezier_points = len(bezier_spline_obj.bezier_points)
|
|
||||||
if bezier_spline_obj.use_cyclic_u:
|
|
||||||
n_bezier_points += 1
|
|
||||||
for i in range(0, n_bezier_points - 1):
|
|
||||||
i_a = i % (n_bezier_points - 1)
|
|
||||||
i_b = (i_a + 1) % real_n_bezier_points
|
|
||||||
bezier = [
|
|
||||||
bezier_spline_obj.bezier_points[i_a],
|
|
||||||
bezier_spline_obj.bezier_points[i_b],
|
|
||||||
]
|
|
||||||
length = calc_bezier_length(
|
|
||||||
bezier[0],
|
|
||||||
bezier[1],
|
|
||||||
int(bezier_spline_obj.resolution_u * resolution_factor),
|
|
||||||
)
|
|
||||||
total_length += length
|
|
||||||
beziers.append(bezier)
|
|
||||||
lengths.append(length)
|
|
||||||
# if total_length > distance:
|
|
||||||
# break
|
|
||||||
|
|
||||||
iterated_distance = 0
|
iterated_distance = 0
|
||||||
for i in range(0, len(beziers)):
|
for i in range(0, len(beziers)):
|
||||||
|
@ -290,7 +307,16 @@ def calc_point_on_bezier_spline(
|
||||||
# if we are here, the point is outside the spline
|
# if we are here, the point is outside the spline
|
||||||
last_i = len(beziers) - 1
|
last_i = len(beziers) - 1
|
||||||
p = beziers[last_i][1]
|
p = beziers[last_i][1]
|
||||||
|
|
||||||
travel = (p.handle_right - p.co).normalized() * (distance - total_length)
|
travel = (p.handle_right - p.co).normalized() * (distance - total_length)
|
||||||
|
|
||||||
|
# in case the handles sit on the points
|
||||||
|
# we interpolate the travel from points of the bezier
|
||||||
|
# if the bezier points sit on each other we have same issue
|
||||||
|
# but that is then to be fixed in the bezier
|
||||||
|
if p.handle_right == p.co and len(beziers) > 0:
|
||||||
|
travel_point = calc_point_on_bezier(beziers[-1][1], beziers[-1][0], 0.001)
|
||||||
|
travel = travel_point.normalized() * (distance - total_length)
|
||||||
location = p.co + travel
|
location = p.co + travel
|
||||||
if output_tangent:
|
if output_tangent:
|
||||||
tangent = calc_tangent_on_bezier(beziers[last_i][0], p, 1)
|
tangent = calc_tangent_on_bezier(beziers[last_i][0], p, 1)
|
||||||
|
@ -580,7 +606,7 @@ def update_available_fonts():
|
||||||
f = abc3d_data.available_fonts.add()
|
f = abc3d_data.available_fonts.add()
|
||||||
f.font_name = font_name
|
f.font_name = font_name
|
||||||
f.face_name = face_name
|
f.face_name = face_name
|
||||||
print(f"{__name__} added {font_name} {face_name}")
|
print(f"{utils.prefix()}::update_available_fonts: {__name__} added {font_name} {face_name}")
|
||||||
|
|
||||||
|
|
||||||
# def update_available_texts():
|
# def update_available_texts():
|
||||||
|
@ -1474,26 +1500,39 @@ def set_text_on_curve(text_properties, reset_timeout_s=0.1, reset_depsgraph_n=4,
|
||||||
mom, advance + glyph_advance, False, True
|
mom, advance + glyph_advance, False, True
|
||||||
)
|
)
|
||||||
if psi == si:
|
if psi == si:
|
||||||
|
n_max = 100
|
||||||
|
n = 0
|
||||||
while (
|
while (
|
||||||
previous_location - new_location
|
previous_location - new_location
|
||||||
).length > glyph_advance and psi == si:
|
).length > glyph_advance and psi == si and n < n_max:
|
||||||
curve_compensation = curve_compensation - glyph_advance * 0.01
|
curve_compensation = curve_compensation - glyph_advance * 0.01
|
||||||
new_location, si = calc_point_on_bezier_curve(
|
tmp_new_location, si = calc_point_on_bezier_curve(
|
||||||
mom,
|
mom,
|
||||||
advance + glyph_advance + curve_compensation,
|
advance + glyph_advance + curve_compensation,
|
||||||
output_tangent=False,
|
output_tangent=False,
|
||||||
output_spline_index=True,
|
output_spline_index=True,
|
||||||
)
|
)
|
||||||
|
if tmp_new_location == new_location:
|
||||||
|
print(f"{utils.prefix()}::set_text_on_curve::compensate_curvature while loop overstaying welcome")
|
||||||
|
break
|
||||||
|
new_location = tmp_new_location
|
||||||
|
n += 1
|
||||||
|
n = 0
|
||||||
while (
|
while (
|
||||||
previous_location - new_location
|
previous_location - new_location
|
||||||
).length < glyph_advance and psi == si:
|
).length < glyph_advance and psi == si and n < n_max:
|
||||||
curve_compensation = curve_compensation + glyph_advance * 0.01
|
curve_compensation = curve_compensation + glyph_advance * 0.01
|
||||||
new_location, si = calc_point_on_bezier_curve(
|
tmp_new_location, si = calc_point_on_bezier_curve(
|
||||||
mom,
|
mom,
|
||||||
advance + glyph_advance + curve_compensation,
|
advance + glyph_advance + curve_compensation,
|
||||||
output_tangent=False,
|
output_tangent=False,
|
||||||
output_spline_index=True,
|
output_spline_index=True,
|
||||||
)
|
)
|
||||||
|
if tmp_new_location == new_location:
|
||||||
|
print(f"{utils.prefix()}::set_text_on_curve::compensate_curvature while loop overstaying welcome")
|
||||||
|
break
|
||||||
|
new_location = tmp_new_location
|
||||||
|
n += 1
|
||||||
|
|
||||||
advance = advance + glyph_advance + curve_compensation
|
advance = advance + glyph_advance + curve_compensation
|
||||||
glyph_index += 1
|
glyph_index += 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue