def __convert_to_svgpath(self): location_A = (0 + 0j) location_B = (self.xB + self.yB * self.thickness_ratio * 1j) location_C = (1 + 0j) location_D = (self.xD + (self.yB - 1.0) * self.thickness_ratio * 1j) control_1 = (0 + self.y1 * location_B.imag * 1j) control_2 = (self.x2 * location_B.real + location_B.imag * 1j) control_3 = (self.x3 * (1.0 - location_B.real) + location_B.real + location_B.imag * 1j) control_6 = (self.x6 * (1.0 - location_D.real) + location_D.real + location_D.imag * 1j) control_7 = (self.x2 * location_D.real + location_D.imag * 1j) control_8 = (0 + self.y8 * location_D.imag * 1j) y4 = location_C.imag + self.y4 * (location_B.imag - location_C.imag) x4 = location_C.real - self.x4 * (location_C.real - control_3.real) control_4 = (x4 + y4 * 1j) x5 = control_4.real - self.x5 * (control_4.real - control_6.real) y5 = control_4.imag - self.y5 * (control_4.imag - control_6.imag) control_5 = (x5 + y5 * 1j) return svg.Path( svg.CubicBezier(start=location_A, control1=control_1, control2=control_2, end=location_B), svg.CubicBezier(start=location_B, control1=control_3, control2=control_4, end=location_C), svg.CubicBezier(start=location_C, control1=control_5, control2=control_6, end=location_D), svg.CubicBezier(start=location_D, control1=control_7, control2=control_8, end=location_A))
def split_cubic(c, t): c0, c1 = svgpathtools.split_bezier(c, t) return svgpathtools.CubicBezier(c0[0], c0[1], c0[2], c0[3]), svgpathtools.CubicBezier( c1[0], c1[1], c1[2], c1[3])
p = c.end - 3 * c.control2 + 3 * c.control1 - c.start d = math.sqrt(p.real * p.real + p.imag * p.imag) * math.sqrt(3.0) / 36 t = math.pow(1.0 / d, 1.0 / 3.0) if t < 1.0: c0, c1 = split_cubic(c, 0.5) queue.append(c0) queue.append(c1) else: quadratic = cubic_to_quadratic(c) print(quadratic) add_quadratic(quadratic) num_quadratics += 1 print('num_quadratics:', num_quadratics) svgpathtools.wsvg(paths, colors=colors, stroke_widths=stroke_widths, nodes=dots, node_colors=ncols, node_radii=nradii, filename=filename) convert_and_write_svg( svgpathtools.CubicBezier(100 + 200j, 426 + 50j, 50 + 50j, 300 + 200j), 'results/curve_subdivision/subdiv_curve0.svg') convert_and_write_svg( svgpathtools.CubicBezier(100 + 200j, 427 + 50j, 50 + 50j, 300 + 200j), 'results/curve_subdivision/subdiv_curve1.svg')
def from_quadratic(cls, segment): p0, p1, p2 = segment.bpoints() return [cls(svgpathtools.CubicBezier(p0, p0 + (p1 - p0) * 2 / 3, p2 + (p1 - p2) * 2 / 3, p2))]
def __init__(self, segment): self.segment = svgpathtools.CubicBezier(*(np.round(p, INTERNAL_PRECISION) for p in segment))
def _calc_fillet_for_joint(self, p, i): seg1 = p[(i) % len(p)] seg2 = p[(i + 1) % len(p)] ori_p = svgpathtools.Path(seg1, seg2) new_p = svgpathtools.Path() # ignore the node if G1 continuity tg1 = seg1.unit_tangent(1.0) tg2 = seg2.unit_tangent(0.0) cosA = abs(tg1.real * tg2.real + tg1.imag * tg2.imag) if abs(cosA - 1.0) < 1e-6: new_p.append(seg1.cropped(self._prev_t, 1.0)) self._prev_t = 0.0 if self._very_first_t is None: self._very_first_t = 1.0 if not isclosedac(p) and i == len(p) - 2: new_p.append(seg2.cropped( 0.0, 1.0)) # add last segment if not closed else: cir = self.circle(seg1.end, self.options.radius) # new_p.extend(cir) intersects = ori_p.intersect(cir) if len(intersects) != 2: inkex.errormsg( "Some fillet or chamfer may not be drawn: %d intersections!" % len(intersects)) new_p.append(seg1.cropped(self._prev_t, 1.0)) self._prev_t = 0.0 if self._very_first_t is None: self._very_first_t = 1.0 if not isclosedac(p) and i == len(p) - 2: new_p.append(seg2.cropped( 0.0, 1.0)) # add last segment if not closed else: cb = [] segs = [] ts = [] for (T1, seg1, t1), (T2, seg2, t2) in intersects: c1 = seg1.point(t1) tg1 = seg1.unit_tangent(t1) * (self.options.radius * KAPPA) cb.extend([c1, tg1]) segs.append(seg1) ts.append(t1) # cir1 = self.circle(c1, self.options.radius * KAPPA) # new_p.extend(cir1) # new_p.append(svgpathtools.Line(c1, c1+tg1)) assert len(cb) == 4 new_p.append(segs[0].cropped(self._prev_t, ts[0])) if self.options.fillet_type == 'fillet': fillet = svgpathtools.CubicBezier(cb[0], cb[0] + cb[1], cb[2] - cb[3], cb[2]) else: fillet = svgpathtools.Line(cb[0], cb[2]) new_p.append(fillet) self._prev_t = ts[1] if self._very_first_t is None: self._very_first_t = ts[0] if isclosedac(p) and i == len(p) - 1: new_p.append(segs[1].cropped( ts[1], self._very_first_t)) # update first segment if closed elif not isclosedac(p) and i == len(p) - 2: new_p.append(segs[1].cropped( ts[1], 1.0)) # add last segment if not closed # # fix for the first segment # if p.isclosed(): # new_p[0] = p[0].cropped(ts[1], self._very_first_t) # new_p.append(segs[0].cropped(ts[0], 1.0)) # new_p.append(segs[1].cropped(0.0, ts[1])) # if self.options.fillet_type == 'fillet': # fillet = svgpathtools.CubicBezier(cb[0], cb[0]+cb[1], cb[2]-cb[3], cb[2]) # else: # fillet = svgpathtools.Line(cb[0], cb[2]) # new_p.append(fillet.reversed()) return new_p