Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2011-10-06 04:05:27 +0400
committerCampbell Barton <ideasman42@gmail.com>2011-10-06 04:05:27 +0400
commitf3070e7ed17bb2afa6037f259e853df9eb394101 (patch)
treeb440c13f15f8e71445cc7ae75ddf9d05b9554679 /modules
parentf25c170bb8adb49bafb73f2414835325d98031d4 (diff)
removng curve utils, Id like to keep working on this but currently its not used anywhere.
Diffstat (limited to 'modules')
-rw-r--r--modules/curve_utils.py994
1 files changed, 0 insertions, 994 deletions
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 #####
-
-# <pep8 compliant>
-
-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!")