def get_outer_angle(p1, p2, center, radius): xp1, yp1 = p1 xp2, yp2 = p2 xc, yc = center a = math.atan2(yp1 - yc, xp1 - xc) b = math.atan2(yp2 - yc, xp2 - xc) beta = abs((a - b) % (2 * math.pi)) mid = (xp1 + xp2) / 2, (yp1 + yp2) / 2 proj_1 = functions.euclid_dist(center, mid) alpha_a = functions.euclid_dist(mid, p2) proj_2 = alpha_a * math.tan(beta / 2) p3 = project_to_circle(mid, center, proj_1 + proj_2) return beta / 2, p3
def get_curve_length(c): l = 0 for i in range(len(c.evalpts) - 1): l += functions.euclid_dist(c.evalpts[i], c.evalpts[i + 1]) return l
def get_cm_from_interpolation_length(pts, interpolation_factor, center_circle, radius): # 0 is circ center = center_circle cm = multi.CurveContainer() cm.vis = VisMPL.VisCurve2D(axes=False, labels=False, ctrlpts=False, legend=False) circle_length = 2 * math.pi * radius tangents = [] curve_lengths = [] for i in range(len(pts)): p1 = pts[(i - 1) % len(pts)] p2 = pts[(i + 1) % len(pts)] pr = (p2[0] - p1[0], p2[1] - p1[1]) alpha = math.atan2(pr[1], pr[0]) % math.pi tangents.append(alpha) dists = [] for i in range(len(pts)): dist = functions.euclid_dist(pts[i], pts[(i + 1) % len(pts)]) d = dist * 0.25 dists.append(d) for i in range(len(pts)): c = BSpline.Curve() c.degree = 3 d = dists[i] p1, p2 = get_points_on_tangent(pts[i], tangents[i], d) if functions.euclid_dist( p1, pts[(i + 1) % len(pts)]) < functions.euclid_dist( p2, pts[(i + 1) % len(pts)]): p2, p1 = p1, p2 p3, p4 = get_points_on_tangent(pts[(i + 1) % len(pts)], tangents[(i + 1) % len(pts)], d) if functions.euclid_dist(p4, pts[i]) < functions.euclid_dist( p3, pts[i]): p4, p3 = p3, p4 c.ctrlpts = [pts[i], p2, p3, pts[(i + 1) % len(pts)]] c.knotvector = [0, 0, 0, 0, 1, 1, 1, 1] length = get_curve_length(c) curve_lengths.append(length) cm.add(c) curve_lengths.reverse() xc, yc = center_circle pts_r = list(pts) pts_r.reverse() distance_factor = circle_length / sum(curve_lengths) pts_interpolated = [] starting_point = functions.project_to_circle(pts[0], center_circle, radius) pts_interpolated.append(starting_point) starting_angle = math.atan2(starting_point[1] - yc, starting_point[0] - xc) alpha = curve_lengths[0] * distance_factor / radius xp = xc + radius * math.cos(alpha) yp = yc + radius * math.sin(alpha) angle_sum = starting_angle for i in range(len(pts) - 1): alpha = curve_lengths[i] * distance_factor / radius angle_sum += alpha xp = xc + radius * math.cos(angle_sum) yp = yc + radius * math.sin(angle_sum) pts_interpolated.append((xp, yp)) pts_interpolated.reverse() pts_interpolated.insert(0, pts_interpolated.pop()) tangents_interpolated = [] for i in range(len(pts_interpolated)): x, y = pts_interpolated[i] alpha = math.atan2(y - center_circle[1], x - center_circle[0]) alpha -= 0.5 * math.pi alpha = alpha % math.pi tangents_interpolated.append(alpha) dists_interpolated = [] for i in range(len(pts_interpolated)): x1, y1 = pts_interpolated[i] x4, y4 = pts_interpolated[(i + 1) % len(pts_interpolated)] xc, yc = center_circle axx = x1 - xc ay = y1 - yc bx = x4 - xc by = y4 - yc q1 = axx * axx + ay * ay q2 = q1 + axx * bx + ay * by k2 = 4 / 3 * (math.sqrt(2 * q1 * q2) - q2) / (axx * by - ay * bx) d = math.sqrt((k2 * ay)**2 + (k2 * axx)**2) dists_interpolated.append(d) cm = multi.CurveContainer() cm.vis = VisMPL.VisCurve2D(axes=False, labels=False, ctrlpts=False, legend=False) pts = [[ interpolation_factor * pp[0] + (1 - interpolation_factor) * pc[0], interpolation_factor * pp[1] + (1 - interpolation_factor) * pc[1] ] for (pp, pc) in zip(pts, pts_interpolated)] new_tangents = [] for tp, tc in zip(tangents, tangents_interpolated): if abs(tp - tc) > math.pi / 2: if tp < math.pi / 2: t = interpolation_factor * (tp + math.pi) + ( 1 - interpolation_factor) * tc elif tc < math.pi / 2: t = interpolation_factor * tp + (1 - interpolation_factor) * ( tc + math.pi) else: t = interpolation_factor * tp + (1 - interpolation_factor) * tc new_tangents.append(t) tangents = new_tangents dists = [ interpolation_factor * dp + (1 - interpolation_factor) * dc for (dp, dc) in zip(dists, dists_interpolated) ] angle_mapping = {} ctrlpts = [] for i in range(len(pts)): c = BSpline.Curve() c.degree = 3 d = dists[i] p1, p2 = get_points_on_tangent(pts[i], tangents[i], d) if i == 0: print(tangents[i]) if p1[1] < p2[1] and tangents[i] < math.pi: p1, p2 = p2, p1 elif p1[1] > p2[1] and tangents[i] > math.pi: p1, p2 = p2, p1 else: if math.atan2(p1[1] - center[1], p1[0] - center[0]) < math.atan2( p2[1] - center[1], p2[0] - center[0]): p1, p2 = p2, p1 if functions.euclid_dist( p1, pts[(i + 1) % len(pts)]) < functions.euclid_dist( p2, pts[(i + 1) % len(pts)]): p2, p1 = p1, p2 xp, yp = pts[i] if (xp, yp) in angle_mapping: p = angle_mapping[(xp, yp)] if p[0] > xp and p2[0] > xp or p[0] < xp and p2[0] < xp: p1, p2 = p2, p1 angle_mapping[(xp, yp)] = p2 p3, p4 = get_points_on_tangent(pts[(i + 1) % len(pts)], tangents[(i + 1) % len(pts)], d) if functions.euclid_dist(p4, pts[i]) < functions.euclid_dist( p3, pts[i]): p4, p3 = p3, p4 xp, yp = pts[(i + 1) % len(pts)] angle_mapping[(xp, yp)] = p3 c.ctrlpts = [pts[i], p2, p3, pts[(i + 1) % len(pts)]] c.knotvector = [0, 0, 0, 0, 1, 1, 1, 1] cm.add(c) return cm
def get_cm_from_interpolation_radial(pts, interpolation_factor): # 0 is circ center_circle = (200, 540) center_polygon = (223, 555) center = center_circle[0] * ( 1 - interpolation_factor ) + center_polygon[0] * interpolation_factor, center_circle[1] * ( 1 - interpolation_factor) + center_polygon[1] * interpolation_factor radius = 70 tangents = [] for i in range(len(pts)): p1 = pts[(i - 1) % len(pts)] p2 = pts[(i + 1) % len(pts)] pr = (p2[0] - p1[0], p2[1] - p1[1]) alpha = math.atan2(pr[1], pr[0]) tangents.append(alpha) dists = [] for i in range(len(pts)): dist = functions.euclid_dist(pts[i], pts[(i + 1) % len(pts)]) d = dist * 0.3 dists.append(d) pts_interpolated = [ functions.project_to_circle(p, center_circle, radius) for p in pts ] tangents_interpolated = [] for i in range(len(pts)): x, y = pts[i] alpha = math.atan2(y - center_circle[1], x - center_circle[0]) alpha -= 0.5 * math.pi alpha = alpha % math.pi tangents_interpolated.append(alpha) dists_interpolated = [] for i in range(len(pts_interpolated)): x1, y1 = pts_interpolated[i] x4, y4 = pts_interpolated[(i + 1) % len(pts_interpolated)] xc, yc = center_circle axx = x1 - xc ay = y1 - yc bx = x4 - xc by = y4 - yc q1 = axx * axx + ay * ay q2 = q1 + axx * bx + ay * by k2 = 4 / 3 * (math.sqrt(2 * q1 * q2) - q2) / (axx * by - ay * bx) d = math.sqrt((k2 * ay)**2 + (k2 * axx)**2) dists_interpolated.append(d) cm = multi.CurveContainer() cm.vis = VisMPL.VisCurve2D(axes=False, labels=False, ctrlpts=False, legend=False) pts = [[ interpolation_factor * pp[0] + (1 - interpolation_factor) * pc[0], interpolation_factor * pp[1] + (1 - interpolation_factor) * pc[1] ] for (pp, pc) in zip(pts, pts_interpolated)] new_tangents = [] for tp, tc in zip(tangents, tangents_interpolated): if abs(tp - tc) > math.pi / 2: if tp < math.pi / 2: t = interpolation_factor * (tp + math.pi) + ( 1 - interpolation_factor) * tc elif tc < math.pi / 2: t = interpolation_factor * tp + (1 - interpolation_factor) * ( tc + math.pi) else: t = interpolation_factor * tp + (1 - interpolation_factor) * tc new_tangents.append(t) tangents = new_tangents dists = [ interpolation_factor * dp + (1 - interpolation_factor) * dc for (dp, dc) in zip(dists, dists_interpolated) ] ctrlpts = [] for i in range(len(pts)): c = BSpline.Curve() c.degree = 3 d = dists[i] p1, p2 = get_points_on_tangent(pts[i], tangents[i], d) if math.atan2(p1[1] - center[1], p1[0] - center[0]) < math.atan2( p2[1] - center[1], p2[0] - center[0]): p1, p2 = p2, p1 if functions.euclid_dist( p1, pts[(i + 1) % len(pts)]) < functions.euclid_dist( p2, pts[(i + 1) % len(pts)]): p2, p1 = p1, p2 p3, p4 = get_points_on_tangent(pts[(i + 1) % len(pts)], tangents[(i + 1) % len(pts)], d) if functions.euclid_dist(p4, pts[i]) < functions.euclid_dist( p3, pts[i]): p4, p3 = p3, p4 c.ctrlpts = [pts[i], p2, p3, pts[(i + 1) % len(pts)]] c.knotvector = [0, 0, 0, 0, 1, 1, 1, 1] cm.add(c) return cm
import numpy as np from scipy import interpolate from matplotlib import pyplot as plt import functions import math CIRCLE = False #pts = [[485, 475], [387, 577]] pts = [[485, 475], [430, 366], [325, 231], [274, 438], [193, 436], [150, 525], [204, 604], [284, 612], [387, 577]] #pts = [[100, 0], [0, -100], [-100, 0], [0, 100]] center = (317, 465) radius = max([functions.euclid_dist(p, center) for p in pts]) if CIRCLE: pts = [functions.project_to_circle(p, center, radius) for p in pts] circle_pts = [[center[0] + radius, center[1]], [center[0] - radius, center[1]], [center[0], center[1] + radius], [center[0], center[1] - radius]] circle_pts_2 = [[center[0] + radius, center[1] + radius], [center[0] - radius, center[1] - radius], [center[0] - radius, center[1] + radius], [center[0] + radius, center[1] - radius]] circle_pts_2 = [ functions.project_to_circle(p, center, radius) for p in circle_pts_2 ] pts.extend(circle_pts) pts.extend(circle_pts_2)
curves_0 = [] curve.degree = 3 # order = degree + 1 curve.ctrlpts = pts_c curve.knotvector = utilities.generate_knot_vector(curve.degree, len(curve.ctrlpts), clamped=False) curve_list = operations.decompose_curve(curve) knot_vectors = [] radius = 0 for c in curve_list: knot_vectors.append(c.knotvector) curves_0.append(c) radius = max(radius, max([functions.euclid_dist(center, p) for p in c.ctrlpts])) base_pts = [(p[0], p[1]) for c in curve_list for p in c.ctrlpts] x, y, r = make_circle(base_pts) # O(n) center = (x, y) radius = r pts_pr = [] for c in curves_0: pts_pr.append(project_to_circle(c.ctrlpts[0], center, radius)) #print(project_to_circle(c.ctrlpts[0], center, radius)) #print(len(pts_pr)) pts_pr[0] = pts_pr[-1] circle_ctrl = []