From f3070e7ed17bb2afa6037f259e853df9eb394101 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 6 Oct 2011 00:05:27 +0000 Subject: removng curve utils, Id like to keep working on this but currently its not used anywhere. --- modules/curve_utils.py | 994 ------------------------------------------------- 1 file changed, 994 deletions(-) delete mode 100644 modules/curve_utils.py (limited to 'modules') diff --git a/modules/curve_utils.py b/modules/curve_utils.py deleted file mode 100644 index 529ddd0c..00000000 --- a/modules/curve_utils.py +++ /dev/null @@ -1,994 +0,0 @@ -# ##### 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 ##### - -# - -import bpy - - -def vis_curve_object(): - scene = bpy.data.scenes[0] # weak! - cu = bpy.data.curves.new(name="Line", type='CURVE') - ob = bpy.data.objects.new(name="Test", object_data=cu) - ob.layers = [True] * 20 - base = scene.objects.link(ob) - return ob - - -def vis_curve_spline(p1, h1, p2, h2): - ob = vis_curve_object() - spline = ob.data.splines.new(type='BEZIER') - spline.bezier_points.add(1) - spline.bezier_points[0].co = p1.to_3d() - spline.bezier_points[1].co = p2.to_3d() - - spline.bezier_points[0].handle_right = h1.to_3d() - spline.bezier_points[1].handle_left = h2.to_3d() - - -def vis_circle_object(co, rad=1.0): - import math - scene = bpy.data.scenes[0] # weak! - ob = bpy.data.objects.new(name="Circle", object_data=None) - ob.rotation_euler.x = math.pi / 2 - ob.location = co.to_3d() - ob.empty_draw_size = rad - ob.layers = [True] * 20 - base = scene.objects.link(ob) - return ob - - -def visualize_line(p1, p2, p3=None, rad=None): - pair = p1.to_3d(), p2.to_3d() - - ob = vis_curve_object() - spline = ob.data.splines.new(type='POLY') - spline.points.add(1) - for co, v in zip((pair), spline.points): - v.co.xyz = co - - if p3: - spline = ob.data.splines.new(type='POLY') - spline.points[0].co.xyz = p3.to_3d() - if rad is not None: - vis_circle_object(p3, rad) - - -def treat_points(points, - double_limit=0.0001, - ): - - # first remove doubles - tot_len = 0.0 - if double_limit != 0.0: - i = len(points) - 1 - while i > 0: - length = (points[i] - points[i - 1]).length - if length < double_limit: - del points[i] - if i >= len(points): - i -= 1 - else: - tot_len += length - i -= 1 - return tot_len - - -def solve_curvature(p1, p2, n1, n2, fac, fallback): - """ Add a nice circular curvature on - """ - from mathutils.geometry import (intersect_line_line, - ) - - p1_a = p1 + n1 - p2_a = p2 - n2 - - isect = intersect_line_line(p1, - p1_a, - p2, - p2_a, - ) - - if isect: - corner = isect[0].lerp(isect[1], 0.5) - else: - corner = None - - if corner: - p1_first_order = p1.lerp(corner, fac) - p2_first_order = corner.lerp(p2, fac) - co = p1_first_order.lerp(p2_first_order, fac) - - return co - else: - # cant interpolate. just return interpolated value - return fallback.copy() # p1.lerp(p2, fac) - - -def points_to_bezier(points_orig, - double_limit=0.0001, - kink_tolerance=0.25, - bezier_tolerance=0.05, # error distance, scale dependant - subdiv=8, - angle_span=0.95, # 1.0 tries to evaluate splines of 180d - ): - - import math - from mathutils import Vector - - class Point(object): - __slots__ = ("co", - "angle", - "no", - "is_joint", - "next", - "prev", - ) - - def __init__(self, co): - self.co = co - self.is_joint = False - - def calc_angle(self): - if self.prev is None or self.next is None: - self.angle = 0.0 - else: - va = self.co - self.prev.co - vb = self.next.co - self.co - self.angle = va.angle(vb, 0.0) - - def angle_diff(self): - """ use for detecting joints, detect difference in angle from - surrounding points. - """ - if self.prev is None or self.next is None: - return 0.0 - else: - if (self.angle > self.prev.angle and - self.angle > self.next.angle): - return abs(self.angle - self.prev.angle) / math.pi - else: - return 0.0 - - def calc_normal(self): - v1 = v2 = None - if self.prev and not self.prev.is_joint: - v1 = (self.co - self.prev.co).normalized() - if self.next and not self.next.is_joint: - v2 = (self.next.co - self.co).normalized() - - if v1 and v2: - self.no = (v1 + v2).normalized() - elif v1: - self.no = v1 - elif v2: - self.no = v2 - else: - print("Warning, assigning dummy normal") - self.no = Vector((0.0, 1, 0.0)) - - class Spline(object): - __slots__ = ("points", - "handle_left", - "handle_right", - "next", - "prev", - ) - - def __init__(self, points): - self.points = points - - def link_points(self): - - if hasattr(self.points[0], "prev"): - raise Exception("already linked") - - p_prev = None - for p in self.points: - p.prev = p_prev - p_prev = p - - p_prev = None - for p in reversed(self.points): - p.next = p_prev - p_prev = p - - def split(self, i, is_joint=False): - prev = self.prev - next = self.next - - if is_joint: - self.points[i].is_joint = True - - # share a point - spline_a = Spline(self.points[:i + 1]) - spline_b = Spline(self.points[i:]) - - # invalidate self, dont reuse! - self.points = None - - spline_a.next = spline_b - spline_b.prev = spline_a - - spline_a.prev = prev - spline_b.next = next - if prev: - prev.next = spline_a - if next: - next.prev = spline_b - - return spline_a, spline_b - - def calc_angle(self): - for p in self.points: - p.calc_angle() - - def calc_normal(self): - for p in self.points: - p.calc_normal() - - def calc_all(self): - self.link_points() - self.calc_angle() - self.calc_normal() - - #~ def total_angle(self): - #~ return abs(sum((p.angle for p in self.points))) - - def redistribute(self, segment_length, smooth=False): - if len(self.points) == 1: - return - - from mathutils.geometry import intersect_line_sphere - - p_line = p = self.points[0] - points = [(p.co.copy(), p.co.copy())] - p = p.next - - def point_add(co, p=None): - co = co.copy() - co_smooth = co.copy() - - if smooth: - if p is None: - pass # works ok but no smoothing - elif (p.prev.no - p.no).length < 0.001: - pass # normals are too similar, paralelle - elif (p.angle > 0.0) != (p.prev.angle > 0.0): - pass - else: - # visualize_line(p.co, p.co + p.no) - - # this assumes co is on the line - fac = ((p.prev.co - co).length / - (p.prev.co - p.co).length) - - assert(fac >= 0.0 and fac <= 1.0) - - co_smooth = solve_curvature(p.prev.co, - p.co, - p.prev.no, - p.no, - fac, - co, - ) - - points.append((co, co_smooth)) - - def point_step(p): - if p.is_joint or p.next is None: - point_add(p.co) - return None - else: - return p.next - - print("START") - while p: - # we want the first pont past the segment size - - #if p.is_joint: - # vis_circle_object(p.co) - - length = (points[-1][0] - p.co).length - - if abs(length - segment_length) < 0.00001: - # close enough to be considered on the circle bounds - point_add(p.co) - p_line = p - p = point_step(p) - elif length < segment_length: - p = point_step(p) - else: - # the point is further then the segment width - p_start = points[-1][0] if p.prev is p_line else p.prev.co - - if (p_start - points[-1][0]).length > segment_length: - raise Exception("eek2") - if (p.co - points[-1][0]).length < segment_length: - raise Exception("eek3") - - # print(p_start, p.co, points[-1][0], segment_length) - i1, i2 = intersect_line_sphere(p_start, - p.co, - points[-1][0], - segment_length, - ) - # print() - # print(i1, i2) - # assert(i1 is not None) - if i1 is not None: - point_add(i1, p) - p_line = p.prev - elif i2: - raise Exception("err") - - elif i1 is None and i2 is None: - visualize_line(p_start, - p.co, - points[-1][0], - segment_length, - ) - - # XXX FIXME - # raise Exception("BAD!s") - point_add(p.co) - p_line = p - p = point_step(p) - - joint = self.points[0].is_joint, self.points[-1].is_joint - - self.points = [Point(p[1]) for p in points] - - self.points[0].is_joint, self.points[-1].is_joint = joint - - self.calc_all() - # raise Exception("END") - - def intersect_line(self, l1, l2, reverse=False): - """ Spectial kind of intersection, works in 3d on the plane - defimed by the points normal and the line. - """ - - from mathutils.geometry import (intersect_point_line, - ) - - if reverse: - p_first = self.points[-1] - no = -self.points[-1].no - point_iter = reversed(self.points[:-1]) - else: - p_first = self.points[0] - no = self.points[0].no - point_iter = self.points[1:] - - # calculate the line right angles to the line - bi_no = (no - no.project(l2 - l1)).normalized() - - bi_l1 = p_first.co - bi_l2 = p_first.co + bi_no - - for p_apex in point_iter: - ix, fac = intersect_point_line(p_apex.co, bi_l1, bi_l2) - - if fac < 0.0001: - - if reverse: - p_apex_other = p_apex.next - else: - p_apex_other = p_apex.prev - - # find the exact point on the line between the apex and - # the middle - p_test_1 = intersect_point_line(p_apex.co, - l1, - l2)[0] - p_test_2 = intersect_point_line(p_apex_other.co, - l1, - l2)[0] - - w1 = (p_test_1 - p_apex.co).length - w2 = (p_test_2 - p_apex_other.co).length - - #assert(w1 + w2 != 0) - try: - fac = w1 / (w1 + w2) - except ZeroDivisionError: - fac = 0.5 - assert(fac >= 0.0 and fac <= 1.0) - - p_apex_co = p_apex.co.lerp(p_apex_other.co, fac) - p_apex_no = p_apex.no.lerp(p_apex_other.no, fac) - p_apex_no.normalize() - - # visualize_line(p_mid.to_3d(), corner.to_3d()) - # visualize_line(p_apex.co.to_3d(), p_apex_co.to_3d()) - - return p_apex_co, p_apex_no, p_apex - - # intersection not found - return None, None, None - - - @staticmethod - def bez_solve(p0, p1, p2, p3, u, v): - 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 - - 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 = p1 - (ui_p3 * p0 + u_p3 * p3) - q2 = p2 - (vi_p3 * p0 + v_p3 * p3) - - return ((d * q1 - b * q2) / det, - (-c * q1 + a * q2) / det - ) - - def bezier_solve__math1(self): - """ Calculate bezier handles, - assume the splines have been broken up. - - http://polymathprogrammer.com/ - """ - - def get(f, min=0.0, max=1.0): - f = (f * (max - min) + min) - return self.points[int((len(self.points) - 1) * f)].co - - - p1 = get(0.0) - p2 = get(1.0) - i1 = get(1/3) - i2 = get(2/3) - - pos = __class__.bez_solve(p1, i1, i2, p2, 1.0 / 3.0, 2.0 / 3.0) - self.handle_left = self.points[0].co + (pos[0] - self.points[0].co) - self.handle_right = self.points[-1].co + (pos[1] - self.points[-1].co) - - def bezier_solve__math2(self): - - def get(f, min=0.0, max=1.0): - f = (f * (max - min) + min) - return self.points[int((len(self.points) - 1) * f)].co - - p1 = get(0.0, min=0.0, max=0.5) - p2 = get(1.0, min=0.0, max=0.5) - i1 = get(1/3, min=0.0, max=0.5) - i2 = get(2/3, min=0.0, max=0.5) - - pos_a = __class__.bez_solve(p1, i1, i2, p2, 1.0 / 3.0, 2.0 / 3.0) - - p1 = get(0.0, min=0.5, max=1.0) - p2 = get(1.0, min=0.5, max=1.0) - i1 = get(1/3, min=0.5, max=1.0) - i2 = get(2/3, min=0.5, max=1.0) - - pos_b = __class__.bez_solve(p1, i1, i2, p2, 1.0 / 3.0, 2.0 / 3.0) - - self.handle_left = self.points[0].co + (pos_a[0] - self.points[0].co) * 2 - self.handle_right = self.points[-1].co + (pos_b[1] - self.points[-1].co) * 2 - - def bezier_solve__inkscape(self): - - # static void - # estimate_bi(Point bezier[4], unsigned const ei, - # Point const data[], double const u[], unsigned const len) - def estimate_bi(bezier, ei, data, u): - - def B0(u): return ( ( 1.0 - u ) * ( 1.0 - u ) * ( 1.0 - u ) ) - def B1(u): return ( 3 * u * ( 1.0 - u ) * ( 1.0 - u ) ) - def B2(u): return ( 3 * u * u * ( 1.0 - u ) ) - def B3(u): return ( u * u * u ) - - # assert( not (1 <= ei and ei <= 2)) - oi = 3 - ei - num = [0.0, 0.0, 0.0] - den = 0.0 - - for i in range(len(data)): - ui = u[i]; - b = [ - B0(ui), - B1(ui), - B2(ui), - B3(ui) - ] - - for d in range(3): - num[d] += (b[ei] * (b[0] * bezier[0][d] + - b[oi] * bezier[oi][d] + - b[3] * bezier[3][d] + - - data[i][d])) - - den -= b[ei] * b[ei] - - if den: - for d in range(3): - bezier[ei][d] = num[d] / den - else: - bezier[ei] = (oi * bezier[0] + ei * bezier[3]) / 3.0 - bezier = [ - self.points[0].co, - self.points[0].co.lerp(self.points[-1].co, 1/3), - self.points[0].co.lerp(self.points[-1].co, 2/3), - self.points[-1].co, - ] - data = [p.co for p in self.points] - u = [i / len(self.points) for i in range(len(self.points))] - estimate_bi(bezier, 1, data, u) - estimate_bi(bezier, 2, data, u) - estimate_bi(bezier, 1, data, u) - estimate_bi(bezier, 2, data, u) - estimate_bi(bezier, 1, data, u) - estimate_bi(bezier, 2, data, u) - estimate_bi(bezier, 1, data, u) - estimate_bi(bezier, 2, data, u) - - self.handle_left = bezier[1] - self.handle_right = bezier[2] - - def bezier_solve_ideasman42(self): - from mathutils.geometry import (intersect_point_line, - intersect_line_line, - ) - - # get a line - p1 = self.points[0] - p2 = self.points[-1] - - # ------ - # take 2 - p_vec = (p2.co - p1.co).normalized() - - # vector between line and point directions - l1_no = (p1.no + p_vec).normalized() - l2_no = ((-p2.no) - p_vec).normalized() - - l1_co = p1.co + l1_no - l2_co = p2.co + l2_no - - # visualize_line(p1.co, l1_co) - # visualize_line(p2.co, l2_co) - - line_ix_p1_co, line_ix_p1_no, line_ix_p1 = \ - self.intersect_line(p1.co, - l1_co, - ) - line_ix_p2_co, line_ix_p2_no, line_ix_p2 = \ - self.intersect_line(p2.co, - l2_co, - reverse=True, - ) - if line_ix_p1_co is None: - line_ix_p1_co, line_ix_p1_no, line_ix_p1 = \ - p1.next.co, p1.next.no, p1.next - if line_ix_p2_co is None: - 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() - 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 - # the tangent. - - # first need to reflect the second normal for angle comparison - # first fist need the reflection normal - - # angle between - 0 - 1 - from math import pi - no_ref = p_vec.cross(p2.no).cross(p_vec).normalized() - l2_no_ref = p2.no.reflect(no_ref).normalized() - no_angle = p1.no.angle(l2_no_ref) / pi - del no_ref - - # This could be tweaked but seems to work well - - # fac_fac = 1.0 - - print("angle", "%.6f" % no_angle) - - fac_1 = intersect_point_line(p2_apex_co, - p1.co, - p1.co + l1_tan * (p1.co - p1_apex_co).length, - )[1] * (1.0 + no_angle) - fac_2 = intersect_point_line(p1_apex_co, - p2.co, - p2.co + l2_tan * (p2.co - p2_apex_co).length, - )[1] * (1.0 + no_angle) - - h1_fac = abs(fac_1) - h2_fac = abs(fac_2) - - h1 = p1.co + (p1.no * h1_fac) - h2 = p2.co - (p2.no * h2_fac) - - self.handle_left = h1 - self.handle_right = h2 - - ''' - visualize_line(p1.co, p1_apex_co) - visualize_line(p1_apex_co, p2_apex_co) - visualize_line(p2.co, p2_apex_co) - visualize_line(p1.co, p2.co) - ''' - - def bezier_solve(self): - return self.bezier_solve__inkscape() - - def bezier_error(self, error_max=-1.0, test_count=8): - from mathutils.geometry import interpolate_bezier - - test_points = interpolate_bezier(self.points[0].co, - self.handle_left, - self.handle_right, - self.points[-1].co, - test_count, - ) - - from mathutils.geometry import intersect_point_line - - error = 0.0 - - # this is a rough method measuring the error but should be ok - # TODO. dont test against every single point. - for co in test_points: - # initial values - co_best = self.points[0].co - - length_best = (co - co_best).length - for p in self.points[1:]: - # dist to point - length = (co - p.co).length - if length < length_best: - length_best = length - co_best = p.co - - p_ix, fac = intersect_point_line(co, p.co, p.prev.co) - p_ix = p_ix - if fac >= 0.0 and fac <= 1.0: - length = (co - p_ix).length - if length < length_best: - length_best = length - co_best = p_ix - - error += length_best / test_count - - if error_max != -1.0 and error > error_max: - return True - - if error_max != -1.0: - return False - else: - return error - - class Curve(object): - __slots__ = ("splines", - ) - - def __init__(self, splines): - self.splines = splines - - def link_splines(self): - s_prev = None - for s in self.splines: - s.prev = s_prev - s_perv = s - - s_prev = None - for s in reversed(self.splines): - s.next = s_prev - s_perv = s - - def calc_data(self): - for s in self.splines: - s.calc_all() - - self.link_splines() - - def split_func_map_point(self, func, is_joint=False): - """ func takes a point and returns true on split - - return True if any splits are made. - """ - s_index = 0 - s = self.splines[s_index] - while s: - assert(self.splines[s_index] == s) - - for i, p in enumerate(s.points): - - if i == 0 or i >= len(s.points) - 1: - continue - - if func(p): - split_pair = s.split(i, is_joint=is_joint) - # keep list in sync - self.splines[s_index:s_index + 1] = split_pair - - # advance on main while loop - s = split_pair[0] - assert(self.splines[s_index] == s) - break - - s = s.next - s_index += 1 - - def split_func_spline(self, func, is_joint=False, recursive=False): - """ func takes a spline and returns the point index on split or -1 - - return True if any splits are made. - """ - s_index = 0 - s = self.splines[s_index] - while s: - assert(self.splines[s_index] == s) - - i = func(s) - - if i != -1: - split_pair = s.split(i, is_joint=is_joint) - # keep list in sync - self.splines[s_index:s_index + 1] = split_pair - - # advance on main while loop - s = split_pair[0] - assert(self.splines[s_index] == s) - - if recursive: - continue - - s = s.next - s_index += 1 - - def validate(self): - s_prev = None - iii = 0 - for s in self.splines: - assert(s.prev == s_prev) - if s_prev: - assert(s_prev.next == s) - s_prev = s - iii += 1 - - def redistribute(self, segment_length, smooth=False): - for s in self.splines: - s.redistribute(segment_length, smooth) - - def to_blend_data(self): - """ Points to blender data, debugging only - """ - scene = bpy.data.scenes[0] # weak! - for base in scene.object_bases: - base.select = False - cu = bpy.data.curves.new(name="Test", type='CURVE') - for s in self.splines: - spline = cu.splines.new(type='POLY') - spline.points.add(len(s.points) - 1) - for p, v in zip(s.points, spline.points): - v.co.xyz = p.co - - ob = bpy.data.objects.new(name="Test", object_data=cu) - ob.layers = [True] * 20 - base = scene.objects.link(ob) - scene.objects.active = ob - base.select = True - # base.layers = [True] * 20 - print(ob, "Done") - - def to_blend_curve(self, cu=None, cu_matrix=None): - """ return new bezier spline datablock or add to an existing - """ - if not cu: - cu = bpy.data.curves.new(name="Curve", type='CURVE') - - spline = cu.splines.new(type='BEZIER') - spline.bezier_points.add(len(self.splines)) - - s_prev = None - for i, bp in enumerate(spline.bezier_points): - if i < len(self.splines): - s = self.splines[i] - else: - s = None - - if s_prev and s: - pt = s.points[0] - hl = s_prev.handle_right - hr = s.handle_left - elif s: - pt = s.points[0] - hr = s.handle_left - hl = (pt.co + (pt.co - hr)) - elif s_prev: - pt = s_prev.points[-1] - hl = s_prev.handle_right - hr = (pt.co + (pt.co - hl)) - else: - assert(0) - - bp.co.xyz = pt.co - bp.handle_left.xyz = hl - bp.handle_right.xyz = hr - - handle_type = 'FREE' - - if pt.is_joint == False or (s_prev and s) == False: - - # XXX, this should not happen, but since it can - # at least dont allow allignment to break the curve output - if (pt.co - hl).angle(hr - pt.co, 0.0) < 0.1: - - handle_type = 'ALIGNED' - - bp.handle_left_type = bp.handle_right_type = handle_type - s_prev = s - - scene = bpy.data.scenes[0] # weak! - ob = bpy.data.objects.new(name="Test", object_data=cu) - ob.layers = [True] * 20 - base = scene.objects.link(ob) - scene.objects.active = ob - base.select = True - - return cu - - points = list(points_orig) - - # remove doubles - tot_length = treat_points(points) - - # calculate segment spacing - segment_length = (tot_length / len(points)) / subdiv - - curve = Curve([Spline([Point(p) for p in points])]) - - curve.calc_data() - - if kink_tolerance != 0.0: - pass - - curve.split_func_map_point(lambda p: p.angle_diff() > kink_tolerance, - is_joint=True, - ) - - # return - # curve.validate() - - # higher quality but not really needed - ''' - curve.redistribute(segment_length / 4.0, smooth=True) - curve.redistribute(segment_length, smooth=False) - ''' - curve.redistribute(segment_length, smooth=True) - - # debug only! - # to test how good the bezier spline fitting is without corrections - - ''' - for s in curve.splines: - s.bezier_solve() - ''' - - ''' - def angle_point(s): - a = 0.0 - a_best = len(s.points) // 2 - i = 1 - for p in s.points[2:-2]: - if p.angle > a: - a = p.angle - a_best = i - i += 1 - return a_best - ''' - - # or recursively subdivide... - curve.split_func_spline(lambda s: - len(s.points) // 2 # angle_point(s) - if ((s.bezier_solve(), - s.bezier_error(bezier_tolerance))[1] - and (len(s.points))) - else -1, - recursive=True, - ) - - - error = 0.0 - for s in curve.splines: - error += s.bezier_error() - print("%d :: %.6f" % (len(curve.splines), error)) - - # VISUALIZE - # curve.to_blend_data() - curve.to_blend_curve() - - -if __name__ == "__main__": - if 0: - bpy.ops.wm.open_mainfile(filepath="/root/curve_test3.blend") - - for c in "Curve Curve.001 Curve.002 Curve.003 Curve.004 Curve.005".split(): - print("---", c) - ob = bpy.data.objects[c] - points = [p.co.xyz for s in ob.data.splines for p in s.points] - - print("points_to_bezier 1") - points_to_bezier(points) - print("points_to_bezier 2") - else: - bpy.ops.wm.open_mainfile(filepath="/root/curve_test2.blend") - - ob = bpy.data.objects['Curve'] - points = [p.co.xyz for s in ob.data.splines for p in s.points] - - print("points_to_bezier 1") - points_to_bezier(points) - print("points_to_bezier 2") - - bpy.ops.wm.save_as_mainfile(filepath="/root/curve_test_edit.blend", - copy=True) - print("done!") -- cgit v1.2.3