Ejemplo n.º 1
0
    def test_cubic_cubic(self):
        # q1 = Bezier(10,100, 90,30, 40,140, 220,220)
        # q2 = Bezier(5,150, 180,20, 80,250, 210,190)
        # console.log(q1.intersects(q2))
        q1 = CubicBezier(Point(10, 100), Point(90, 30), Point(40, 140),
                         Point(220, 220))
        q2 = CubicBezier(Point(5, 150), Point(180, 20), Point(80, 250),
                         Point(210, 190))
        i = q1.intersections(q2)
        # self.assertEqual(len(i),3)
        # self.assertAlmostEqual(i[0].point.x,81.7904225873)
        # self.assertAlmostEqual(i[0].point.y,109.899396337)
        # self.assertAlmostEqual(i[1].point.x,133.186831292)
        # self.assertAlmostEqual(i[1].point.y,167.148173322)
        # self.assertAlmostEqual(i[2].point.x,179.869157678)
        # self.assertAlmostEqual(i[2].point.y,199.661989162)
        import matplotlib.pyplot as plt
        fig, ax = plt.subplots()

        path = BezierPath()
        path.closed = False
        path.activeRepresentation = SegmentRepresentation(path, [q1])
        path.plot(ax)
        path.activeRepresentation = SegmentRepresentation(path, [q2])
        path.plot(ax)

        for n in i:
            circle = plt.Circle((n.point.x, n.point.y),
                                2,
                                fill=True,
                                color="red")
            ax.add_artist(circle)
Ejemplo n.º 2
0
  def test_loop(self):
    q = CubicBezier(
      Point(171,272), Point(388,249), Point(167,444), Point(388,176)
    )
    self.assertTrue(not q.hasLoop)

    q = CubicBezier(
      Point(171,272), Point(595,249), Point(167,444), Point(388,176)
    )
    roots = q.hasLoop
    p1 = q.pointAtTime(roots[0])
    p2 = q.pointAtTime(roots[1])
    self.assertTrue(q.hasLoop)
    self.assertEqual(p1,p2)
Ejemplo n.º 3
0
def cubic_beziers_from_arc(r, phi, flagA, flagS, p1, p2):
    #========================================================
    r_abs = tuple2(abs(r.x), abs(r.y))
    d = tuple2((p1.x - p2.x), (p1.y - p2.y))
    p = tuple2(
        math.cos(phi) * d.x / 2 + math.sin(phi) * d.y / 2,
        -math.sin(phi) * d.x / 2 + math.cos(phi) * d.y / 2)
    p_sq = tuple2(p.x**2, p.y**2)
    r_sq = tuple2(r_abs.x**2, r_abs.y**2)

    ratio = p_sq.x / r_sq.x + p_sq.y / r_sq.y
    if ratio > 1:
        scale = math.sqrt(ratio)
        r_abs = tuple2(scale * r_abs.x, scale * r_abs.y)
        r_sq = tuple2(r_abs.x**2, r_abs.y**2)

    dq = r_sq.x * p_sq.y + r_sq.y * p_sq.x
    pq = (r_sq.x * r_sq.y - dq) / dq
    q = math.sqrt(max(0, pq))
    if flagA == flagS:
        q = -q

    cp = tuple2(q * r_abs.x * p.y / r_abs.y, -q * r_abs.y * p.x / r_abs.x)
    c = tuple2(
        cp.x * math.cos(phi) - cp.y * math.sin(phi) + (p1.x + p2.x) / 2.0,
        cp.x * math.sin(phi) + cp.y * math.cos(phi) + (p1.y + p2.y) / 2.0)

    lambda1 = svg_angle(tuple2(1, 0),
                        tuple2((p.x - cp.x) / r_abs.x, (p.y - cp.y) / r_abs.y))
    delta = svg_angle(tuple2((p.x - cp.x) / r_abs.x, (p.y - cp.y) / r_abs.y),
                      tuple2((-p.x - cp.x) / r_abs.x, (-p.y - cp.y) / r_abs.y))
    delta = delta - 2 * math.pi * math.floor(delta / (2 * math.pi))
    if not flagS:
        delta -= 2 * math.pi
    lambda2 = lambda1 + delta

    t = lambda1
    dt = math.pi / 4
    curves = []
    while (t + dt) < lambda2:
        control_points = (BezierPoint(
            *cp) for cp in cubic_bezier_control_points(c, r_abs, phi, t, t +
                                                       dt))
        curves.append(CubicBezier(*control_points))
        t += dt
    control_points = (BezierPoint(
        *cp) for cp in cubic_bezier_control_points(c, r_abs, phi, t, lambda2))
    curves.append(CubicBezier(*(tuple(control_points)[:3]), BezierPoint(*p2)))
    return curves
 def test_cubic_cubic(self):
     # q1 = Bezier(10,100, 90,30, 40,140, 220,220)
     # q2 = Bezier(5,150, 180,20, 80,250, 210,190)
     # console.log(q1.intersects(q2))
     q1 = CubicBezier(Point(10, 100), Point(90, 30), Point(40, 140),
                      Point(220, 220))
     q2 = CubicBezier(Point(5, 150), Point(180, 20), Point(80, 250),
                      Point(210, 190))
     i = q1.intersections(q2)
     self.assertEqual(len(i), 3)
     self.assertAlmostEqual(i[0].point.x, 81.7904225873)
     self.assertAlmostEqual(i[0].point.y, 109.899396337)
     self.assertAlmostEqual(i[1].point.x, 133.186831292)
     self.assertAlmostEqual(i[1].point.y, 167.148173322)
     self.assertAlmostEqual(i[2].point.x, 179.869157678)
     self.assertAlmostEqual(i[2].point.y, 199.661989162)
Ejemplo n.º 5
0
def join_beziers_in_region(last_bezier, join_region, next_bezier):
    #=================================================================
    last_bezier = trim_bezier_to_region_edge(last_bezier.asSegments()[-1],
                                             join_region,
                                             start=False)
    next_bezier = trim_bezier_to_region_edge(next_bezier.asSegments()[0],
                                             join_region,
                                             start=True)

    # now want intersection of derivative lines
    intersection = line_intersection(last_bezier.points[2:4],
                                     next_bezier.points[0:2])
    intersection = BezierPoint(*intersection)
    #join_bezier = CubicBezier(last_bezier.points[3], intersection, intersection, next_bezier.points[0])

    ## What if intersection is outside of join_region? Or even not near the region's centre??
    region_centre = BezierPoint(*join_region.centroid.coords[0])
    join_bezier = CubicBezier(last_bezier.points[3], region_centre,
                              region_centre, next_bezier.points[0])

    ## Adjust derivatives at end/start of last/next bezier to have same magnitudes
    ## as join_bezier's start/end derivative (slope will already match so simply set as
    ## last_bezier.points[2] = (last_bezier.points[3] - (intersection - last_bezier.points[3]))
    ## etc...

    return (last_bezier, join_bezier, next_bezier)
Ejemplo n.º 6
0
 def appendSegment(self, seg):
     seg = [Point(n[0], n[1]) for n in seg]
     if len(seg) == 2:
         self.segments.append(Line(*seg))
     elif len(seg) == 3:
         self.segments.append(QuadraticBezier(*seg))
     elif len(seg) == 4:
         self.segments.append(CubicBezier(*seg))
     else:
         raise ValueError("Unknown segment type")
Ejemplo n.º 7
0
def Ellipse(x_radius, y_radius, origin=None, superness=CIRCULAR_SUPERNESS):
    """Returns a path representing an ellipse of given x and y radii.
  You can specify the `origin` as a Point and the `superness` of the ellipse."""
    if not origin:
        origin = Point(0, 0)
    w = origin + west * x_radius
    e = origin + east * x_radius
    n = origin + north * y_radius
    s = origin + south * y_radius

    w_n = CubicBezier(w, w + north * y_radius * superness,
                      n + west * x_radius * superness, n)
    n_e = CubicBezier(n, n + east * x_radius * superness,
                      e + north * y_radius * superness, e)
    e_s = CubicBezier(e, e + south * y_radius * superness,
                      s + east * x_radius * superness, s)
    s_w = CubicBezier(s, s + west * x_radius * superness,
                      w + south * y_radius * superness, w)
    return BezierPath.fromSegments([w_n, n_e, e_s, s_w])
 def test_cubic_line(self):
     q = CubicBezier(Point(100, 240), Point(30, 60), Point(210, 230),
                     Point(160, 30))
     l = Line(Point(25, 260), Point(230, 20))
     path = BezierPath()
     path.closed = False
     path.activeRepresentation = SegmentRepresentation(path, [q])
     i = q.intersections(l)
     self.assertEqual(len(i), 3)
     self.assertEqual(i[0].point, q.pointAtTime(0.117517031451))
     self.assertEqual(i[1].point, q.pointAtTime(0.518591792307))
     self.assertEqual(i[2].point, q.pointAtTime(0.867886610031))
Ejemplo n.º 9
0
 def test_addextremes(self):
     q = CubicBezier(Point(42, 135), Point(129, 242), Point(167, 77),
                     Point(65, 59))
     ex = q.findExtremes()
     self.assertEqual(len(ex), 2)
     path = BezierPath()
     path.closed = False
     path.activeRepresentation = SegmentRepresentation(path, [q])
     path.addExtremes()
     path.balance()
     segs = path.asSegments()
     self.assertEqual(len(segs), 3)
Ejemplo n.º 10
0
 def test_extremes(self):
   q = CubicBezier(
     Point(65,59), Point(194,90), Point(220,260), Point(70,261)
   )
   # console.log(Bezier(65,59, 194,90, 220,260, 70,261).extrema())
   r = q.findExtremes()
   self.assertEqual(len(r), 1)
   self.assertAlmostEqual(r[0], 0.5275787707261016)
   r = q.findExtremes(inflections = True)
   self.assertEqual(len(r), 2)
   self.assertAlmostEqual(r[0], 0.4512987012987013)
   self.assertAlmostEqual(r[1], 0.5275787707261016)
Ejemplo n.º 11
0
def bezier_paths_from_arc_endpoints(r, phi, flagA, flagS, p1, p2, T):
    #====================================================================
    arc = arc_endpoints_to_centre(r, phi, flagA, flagS, p1, p2)
    end_theta = arc.theta + arc.delta_theta
    t = arc.theta
    dt = math.pi / 4
    segments = []
    while (t + dt) < end_theta:
        control_points = (BezierPoint(*T.transform_point(cp))
                          for cp in cubic_bezier_control_points(
                              arc.centre, arc.radii, phi, t, t + dt))
        segments.append(CubicBezier(*control_points))
        t += dt
    control_points = (BezierPoint(*T.transform_point(cp))
                      for cp in cubic_bezier_control_points(
                          arc.centre, arc.radii, phi, t, end_theta))
    segments.append(
        CubicBezier(*(tuple(control_points)[:3]),
                    BezierPoint(*T.transform_point(p2))))
    path = BezierPath.fromSegments(segments)
    path.closed = False
    return path
Ejemplo n.º 12
0
 def test_align(self):
   q = CubicBezier(
     Point(120,160), Point(35,200), Point(220,260), Point(220,40)
   )
   s = q.aligned()
   self.assertAlmostEqual(s[0].x,0.0)
   self.assertAlmostEqual(s[0].y,0.0)
   self.assertAlmostEqual(s[1].x,-85.14452515537582)
   self.assertAlmostEqual(s[1].y,-39.69143277919774)
   self.assertAlmostEqual(s[2].x,-12.803687993289572)
   self.assertAlmostEqual(s[2].y,140.84056792618557)
   self.assertAlmostEqual(s[3].x,156.2049935181331)
   self.assertAlmostEqual(s[3].y,0.0)
Ejemplo n.º 13
0
    def fitLine(self, data, tHat1, tHat2):
        p0, p3 = data[0], data[-1]
        dist = p0.distanceFrom(p3) / 3.0

        if tHat1:
            p1 = p0 + tHat1 * dist
        else:
            p1 = ((p0 * 2.0) + p3) / 3.0
        if tHat2:
            p2 = p3 + tHat2 * dist
        else:
            p2 = ((p3 * 2.0) + p0) / 3.0

        return CubicBezier(p0, p1, p2, p3)
Ejemplo n.º 14
0
  def estimateLengths(self, data, u, tHat1, tHat2):
    C = [ [ 0.0, 0.0], [ 0.0, 0.0 ]]
    X = [ 0.0, 0.0 ]
    # bez = SCBezier()
    for (coeff,datum) in zip(u, data):
      (b0,b1,b2,b3) = (B0(coeff), B1(coeff), B2(coeff), B3(coeff))
      (a1, a2) = (tHat1 * b1, tHat2 * b2)
      C[0][0] += a1.__matmul__(a1)
      C[0][1] += a1.__matmul__(a2)
      C[1][0] = C[0][1]
      C[1][1] += a2.__matmul__(a2)
      s1 = data[0] * (b0+b1)
      shortfall = datum - s1
      shortfall = shortfall - (data[-1] * (b2+b3))
      X[0] += a1.__matmul__(shortfall)
      X[1] += a2.__matmul__(shortfall)

    det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1]
    if det_C0_C1 != 0.0:
      det_C0_X  = C[0][0] * X[1]    - C[0][1] * X[0]
      det_X_C1  = X[0]    * C[1][1] - X[1]    * C[0][1]
      alpha_l = det_X_C1 / det_C0_C1
      alpha_r = det_C0_X / det_C0_C1
    else:
      c0 = C[0][0] + C[0][1]
      if c0 != 0:
        alpha_l = X[0] / c0
        alpha_r = X[0] / c0
      else:
        alpha_l = 0.0
        alpha_r = 0.0
    if alpha_l < 1.0e-6 or alpha_r < 1.0e-6:
      alpha_l = data[-1].distanceFrom(data[0]) / 3.0
      alpha_r = alpha_l

    return CubicBezier(data[0],
                    tHat1 * alpha_l + data[0],
                    tHat2 * alpha_r + data[-1],
                    data[-1])
Ejemplo n.º 15
0
    def process_shape(self, shape, transform):
        feature = {'type': 'Feature', 'id': shape.shape_id, 'properties': {}}
        if shape.name_id != '':
            feature['properties']['id'] = '{}/{}'.format(
                self.layer_id, shape.name_id)
            feature['properties']['selectable'] = True
        if len(shape.name_attributes):
            feature['properties']['type'] = shape.name_attributes[0]
        geometry = {}
        coordinates = []

        pptx_geometry = Geometry(shape)
        for path in pptx_geometry.path_list:
            bbox = (shape.width, shape.height) if path.w is None else (path.w,
                                                                       path.h)
            T = transform * Transform(shape, bbox).matrix()

            moved = False
            first_point = None
            current_point = None
            closed = False

            for c in path.getchildren():
                if c.tag == DML('arcTo'):
                    wR = pptx_geometry.attrib_value(c, 'wR')
                    hR = pptx_geometry.attrib_value(c, 'hR')
                    stAng = radians(pptx_geometry.attrib_value(c, 'stAng'))
                    swAng = radians(pptx_geometry.attrib_value(c, 'swAng'))
                    p1 = ellipse_point(wR, hR, stAng)
                    p2 = ellipse_point(wR, hR, stAng + swAng)
                    pt = (current_point[0] - p1[0] + p2[0],
                          current_point[1] - p1[1] + p2[1])
                    large_arc_flag = 1 if swAng >= math.pi else 0
                    beziers = cubic_beziers_from_arc(tuple2(wR, hR), 0,
                                                     large_arc_flag, 1,
                                                     tuple2(*current_point),
                                                     tuple2(*pt))
                    for bz in beziers:
                        coordinates.extend(transform_bezier_samples(T, bz))
                    current_point = pt

                elif c.tag == DML('close'):
                    if first_point is not None and current_point != first_point:
                        coordinates.append(transform_point(T, first_point))
                    closed = True
                    first_point = None
                    # Close current pptx_geometry and start a new one...

                elif c.tag == DML('cubicBezTo'):
                    coords = [BezierPoint(*current_point)]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*pt))
                        current_point = pt
                    bz = CubicBezier(*coords)
                    coordinates.extend(transform_bezier_samples(T, bz))

                elif c.tag == DML('lnTo'):
                    pt = pptx_geometry.point(c.pt)
                    if moved:
                        coordinates.append(transform_point(T, current_point))
                        moved = False
                    coordinates.append(transform_point(T, pt))
                    current_point = pt

                elif c.tag == DML('moveTo'):
                    pt = pptx_geometry.point(c.pt)
                    if first_point is None:
                        first_point = pt
                    current_point = pt
                    moved = True

                elif c.tag == DML('quadBezTo'):
                    coords = [BezierPoint(*current_point)]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*pt))
                        current_point = pt
                    bz = QuadraticBezier(*coords)
                    coordinates.extend(transform_bezier_samples(T, bz))

                else:
                    print('Unknown path element: {}'.format(c.tag))

            lat_lon = points_to_lon_lat(coordinates)
            if closed:
                geometry['type'] = 'Polygon'
                geometry['coordinates'] = [lat_lon]
            else:
                geometry['type'] = 'LineString'
                geometry['coordinates'] = lat_lon

            feature['geometry'] = geometry
            self._features.append(feature)
Ejemplo n.º 16
0
    def __get_geometry(self, element, properties, transform):
    #=======================================================
    ##
    ## Returns path element as a `shapely` object.
    ##
        coordinates = []
        bezier_segments = []
        moved = False
        first_point = None
        current_point = None
        closed = False
        path_tokens = []

        T = transform@SVGTransform(element.attrib.get('transform'))
        if element.tag == SVG_NS('path'):
            path_tokens = list(parse_svg_path(element.attrib.get('d', '')))

        elif element.tag == SVG_NS('rect'):
            x = length_as_pixels(element.attrib.get('x', 0))
            y = length_as_pixels(element.attrib.get('y', 0))
            width = length_as_pixels(element.attrib.get('width', 0))
            height = length_as_pixels(element.attrib.get('height', 0))
            rx = length_as_pixels(element.attrib.get('rx'))
            ry = length_as_pixels(element.attrib.get('ry'))
            if width == 0 or height == 0: return None

            if rx is None and ry is None:
                rx = ry = 0
            elif ry is None:
                ry = rx
            elif rx is None:
                rx = ry
            rx = min(rx, width/2)
            ry = min(ry, height/2)
            if rx == 0 and ry == 0:
                path_tokens = ['M', x, y,
                               'H', x+width,
                               'V', y+height,
                               'H', x,
                               'V', y,
                               'Z']
            else:
                path_tokens = ['M', x+rx, y,
                               'H', x+width-rx,
                               'A', rx, ry, 0, 0, 1, x+width, y+ry,
                               'V', y+height-ry,
                               'A', rx, ry, 0, 0, 1, x+width-rx, y+height,
                               'H', x+rx,
                               'A', rx, ry, 0, 0, 1, x, y+height-ry,
                               'V', y+ry,
                               'A', rx, ry, 0, 0, 1, x+rx, y,
                               'Z']

        elif element.tag == SVG_NS('line'):
            x1 = length_as_pixels(element.attrib.get('x1', 0))
            y1 = length_as_pixels(element.attrib.get('y1', 0))
            x2 = length_as_pixels(element.attrib.get('x2', 0))
            y2 = length_as_pixels(element.attrib.get('y2', 0))
            path_tokens = ['M', x1, y1, x2, y2]

        elif element.tag == SVG_NS('polyline'):
            points = element.attrib.get('points', '').replace(',', ' ').split()
            path_tokens = ['M'] + points

        elif element.tag == SVG_NS('polygon'):
            points = element.attrib.get('points', '').replace(',', ' ').split()
            path_tokens = ['M'] + points + ['Z']

        elif element.tag == SVG_NS('circle'):
            cx = length_as_pixels(element.attrib.get('cx', 0))
            cy = length_as_pixels(element.attrib.get('cy', 0))
            r = length_as_pixels(element.attrib.get('r', 0))
            if r == 0: return None
            path_tokens = ['M', cx+r, cy,
                           'A', r, r, 0, 0, 0, cx, cy-r,
                           'A', r, r, 0, 0, 0, cx-r, cy,
                           'A', r, r, 0, 0, 0, cx, cy+r,
                           'A', r, r, 0, 0, 0, cx+r, cy,
                           'Z']

        elif element.tag == SVG_NS('ellipse'):
            cx = length_as_pixels(element.attrib.get('cx', 0))
            cy = length_as_pixels(element.attrib.get('cy', 0))
            rx = length_as_pixels(element.attrib.get('rx', 0))
            ry = length_as_pixels(element.attrib.get('ry', 0))
            if rx == 0 or ry == 0: return None
            path_tokens = ['M', cx+rx, cy,
                           'A', rx, ry, 0, 0, 0, cx, cy-ry,
                           'A', rx, ry, 0, 0, 0, cx-rx, cy,
                           'A', rx, ry, 0, 0, 0, cx, cy+ry,
                           'A', rx, ry, 0, 0, 0, cx+rx, cy,
                           'Z']

        elif element.tag == SVG_NS('image'):
            if 'id' in properties or 'class' in properties:
                width = length_as_pixels(element.attrib.get('width', 0))
                height = length_as_pixels(element.attrib.get('height', 0))
                path_tokens = ['M', 0, 0,
                               'H', width,
                               'V', height,
                               'H', 0,
                               'V', 0,
                               'Z']

        pos = 0
        while pos < len(path_tokens):
            if isinstance(path_tokens[pos], str) and path_tokens[pos].isalpha():
                cmd = path_tokens[pos]
                pos += 1
            # Else repeat previous command with new coordinates
            # with `moveTo` becoming `lineTo`
            elif cmd == 'M':
                cmd = 'L'
            elif cmd == 'm':
                cmd = 'l'

            if cmd not in ['s', 'S']:
                second_cubic_control = None
            if cmd not in ['t', 'T']:
                second_quad_control = None

            if cmd in ['a', 'A']:
                params = [float(x) for x in path_tokens[pos:pos+7]]
                pos += 7
                pt = params[5:7]
                if cmd == 'a':
                    pt[0] += current_point[0]
                    pt[1] += current_point[1]
                phi = radians(params[2])
                path = bezier_path_from_arc_endpoints(tuple2(*params[0:2]), phi, *params[3:5],
                                                        tuple2(*current_point), tuple2(*pt), T)
                bezier_segments.extend(path.asSegments())
                coordinates.extend(bezier_sample(path))
                current_point = pt

            elif cmd in ['c', 'C', 's', 'S']:
                coords = [BezierPoint(*T.transform_point(current_point))]
                if cmd in ['c', 'C']:
                    n_params = 6
                else:
                    n_params = 4
                    if second_cubic_control is None:
                        coords.append(BezierPoint(*T.transform_point(current_point)))
                    else:
                        coords.append(BezierPoint(*T.transform_point(
                            reflect_point(second_cubic_control, current_point))))
                params = [float(x) for x in path_tokens[pos:pos+n_params]]
                pos += n_params
                for n in range(0, n_params, 2):
                    pt = params[n:n+2]
                    if cmd.islower():
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                    if n == (n_params - 4):
                        second_cubic_control = pt
                    coords.append(BezierPoint(*T.transform_point(pt)))
                bz = CubicBezier(*coords)
                bezier_segments.append(bz)
                coordinates.extend(bezier_sample(bz))
                current_point = pt

            elif cmd in ['l', 'L', 'h', 'H', 'v', 'V']:
                if cmd in ['l', 'L']:
                    params = [float(x) for x in path_tokens[pos:pos+2]]
                    pos += 2
                    pt = params[0:2]
                    if cmd == 'l':
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                else:
                    param = float(path_tokens[pos])
                    pos += 1
                    if cmd == 'h':
                        param += current_point[0]
                    elif cmd == 'v':
                        param += current_point[1]
                    if cmd in ['h', 'H']:
                        pt = [param, current_point[1]]
                    else:
                        pt = [current_point[0], param]
                if moved:
                    coordinates.append(T.transform_point(current_point))
                    moved = False
                coordinates.append(T.transform_point(pt))
                current_point = pt

            elif cmd in ['m', 'M']:
                params = [float(x) for x in path_tokens[pos:pos+2]]
                pos += 2
                pt = params[0:2]
                if first_point is None:
                    # First `m` in a path is treated as `M`
                    first_point = pt
                else:
                    if cmd == 'm':
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                current_point = pt
                moved = True

            elif cmd in ['q', 'Q', 't', 'T']:
                coords = [BezierPoint(*T.transform_point(current_point))]
                if cmd in ['q', 'Q']:
                    n_params = 4
                else:
                    n_params = 2
                    if second_quad_control is None:
                        coords.append(BezierPoint(*T.transform_point(current_point)))
                    else:
                        coords.append(BezierPoint(*T.transform_point(
                            reflect_point(second_quad_control, current_point))))
                params = [float(x) for x in path_tokens[pos:pos+n_params]]
                pos += n_params
                for n in range(0, n_params, 2):
                    pt = params[n:n+2]
                    if cmd.islower():
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                    if n == (n_params - 4):
                        second_quad_control = pt
                    coords.append(BezierPoint(*T.transform_point(pt)))
                bz = QuadraticBezier(*coords)
                bezier_segments.append(bz)
                coordinates.extend(bezier_sample(bz))
                current_point = pt

            elif cmd in ['z', 'Z']:
                if first_point is not None and current_point != first_point:
                    coordinates.append(T.transform_point(first_point))
                closed = True
                first_point = None

            else:
                log.warn('Unknown path command: {}'.format(cmd))

        if len(bezier_segments) > 0:
            properties['bezier-path'] = BezierPath.fromSegments(bezier_segments)

        if closed and len(coordinates) >= 3:
            geometry = shapely.geometry.Polygon(coordinates)
        elif properties.get('closed', False) and len(coordinates) >= 3:
            # Return a polygon if flagged as `closed`
            coordinates.append(coordinates[0])
            geometry = shapely.geometry.Polygon(coordinates)
        elif len(coordinates) >= 2:
            geometry = shapely.geometry.LineString(coordinates)
        else:
            geometry = None
        return geometry
Ejemplo n.º 17
0
        # Subdivision
        r1 = self.minDist(uinterval=(umin, newuMid), vinterval=(vmin, newvMid))
        r2 = self.minDist(uinterval=(umin, newuMid), vinterval=(newvMid, vmax))
        r3 = self.minDist(uinterval=(newuMid, umax), vinterval=(vmin, newvMid))
        r4 = self.minDist(uinterval=(newuMid, umax), vinterval=(newvMid, vmax))
        results = min([r1, r2, r3, r4], key=lambda x: x[0])
        return results


def curveDistance(bez1, bez2):
    """Find the distance between two curves."""
    c = MinimumCurveDistanceFinder(bez1, bez2)
    dist, t1, t2 = c.minDist()
    return math.sqrt(dist), t1, t2


if __name__ == "__main__":
    bez1 = CubicBezier(Point(129, 139), Point(190, 139), Point(201, 364),
                       Point(90, 364))
    bez2 = CubicBezier(Point(309, 159), Point(178, 159), Point(215, 408),
                       Point(309, 408))
    bez3 = Line(Point(309, 159), Point(309, 408))

    c = MinimumCurveDistanceFinder(bez1, bez3)
    dist, t1, t2 = c.minDist()
    print(bez1.pointAtTime(t1))
    print(bez3.pointAtTime(t2))
    print(math.sqrt(dist))
    print(c.iterations)
Ejemplo n.º 18
0
    def process_shape(self, shape, properties, transform):
        #=====================================================
        ##
        ## Returns shape's geometry as `shapely` object.
        ##
        coordinates = []
        pptx_geometry = Geometry(shape)
        for path in pptx_geometry.path_list:
            bbox = (shape.width,
                    shape.height) if path.w is None or path.h is None else (
                        path.w, path.h)
            T = transform @ Transform(shape, bbox).matrix()

            moved = False
            first_point = None
            current_point = None
            closed = False

            for c in path.getchildren():
                if c.tag == DML('arcTo'):
                    wR = pptx_geometry.attrib_value(c, 'wR')
                    hR = pptx_geometry.attrib_value(c, 'hR')
                    stAng = radians(pptx_geometry.attrib_value(c, 'stAng'))
                    swAng = radians(pptx_geometry.attrib_value(c, 'swAng'))
                    p1 = ellipse_point(wR, hR, stAng)
                    p2 = ellipse_point(wR, hR, stAng + swAng)
                    pt = (current_point[0] - p1[0] + p2[0],
                          current_point[1] - p1[1] + p2[1])
                    large_arc_flag = 1 if swAng >= math.pi else 0
                    beziers = cubic_beziers_from_arc(tuple2(wR, hR), 0,
                                                     large_arc_flag, 1,
                                                     tuple2(*current_point),
                                                     tuple2(*pt))
                    for bz in beziers:
                        coordinates.extend(transform_bezier_samples(T, bz))
                    current_point = pt

                elif c.tag == DML('close'):
                    if first_point is not None and current_point != first_point:
                        coordinates.append(transform_point(T, first_point))
                    closed = True
                    first_point = None
                    # Close current pptx_geometry and start a new one...

                elif c.tag == DML('cubicBezTo'):
                    coords = [BezierPoint(*current_point)]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*pt))
                        current_point = pt
                    bz = CubicBezier(*coords)
                    coordinates.extend(transform_bezier_samples(T, bz))

                elif c.tag == DML('lnTo'):
                    pt = pptx_geometry.point(c.pt)
                    if moved:
                        coordinates.append(transform_point(T, current_point))
                        moved = False
                    coordinates.append(transform_point(T, pt))
                    current_point = pt

                elif c.tag == DML('moveTo'):
                    pt = pptx_geometry.point(c.pt)
                    if first_point is None:
                        first_point = pt
                    current_point = pt
                    moved = True

                elif c.tag == DML('quadBezTo'):
                    coords = [BezierPoint(*current_point)]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*pt))
                        current_point = pt
                    bz = QuadraticBezier(*coords)
                    coordinates.extend(transform_bezier_samples(T, bz))

                else:
                    print('Unknown path element: {}'.format(c.tag))

        if closed:
            geometry = shapely.geometry.Polygon(coordinates)
        else:
            geometry = shapely.geometry.LineString(coordinates)
            if properties.get('closed', False):
                # Return a polygon if flagged as `closed`
                coordinates.append(coordinates[0])
                return shapely.geometry.Polygon(coordinates)
        return geometry
Ejemplo n.º 19
0
 def test_curvature(self):
   q = CubicBezier(
     Point(122,102), Point(35,200), Point(228,145), Point(190,46)
   )
   self.assertAlmostEqual(q.curvatureAtTime(0.5),-103450.5)
Ejemplo n.º 20
0
 def test_cubicLength(self):
     b1 = CubicBezier(Point(100, 25), Point(10, 90), Point(110, 100),
                      Point(132, 192))
     self.assertAlmostEqual(b1.length, 202.20118972656385)
Ejemplo n.º 21
0
    def __get_geometry(self, shape, properties, transform):
        #======================================================
        ##
        ## Returns shape's geometry as `shapely` object.
        ##
        coordinates = []
        bezier_segments = []
        pptx_geometry = Geometry(shape)
        for path in pptx_geometry.path_list:
            bbox = (shape.width,
                    shape.height) if path.w is None or path.h is None else (
                        path.w, path.h)
            T = transform @ DrawMLTransform(shape, bbox)

            moved = False
            first_point = None
            current_point = None
            closed = False

            for c in path.getchildren():
                if c.tag == DML('arcTo'):
                    (wR, hR) = ((pptx_geometry.attrib_value(c, 'wR'),
                                 pptx_geometry.attrib_value(c, 'hR')))
                    stAng = radians(pptx_geometry.attrib_value(c, 'stAng'))
                    swAng = radians(pptx_geometry.attrib_value(c, 'swAng'))
                    p1 = ellipse_point(wR, hR, stAng)
                    p2 = ellipse_point(wR, hR, stAng + swAng)
                    pt = (current_point[0] - p1[0] + p2[0],
                          current_point[1] - p1[1] + p2[1])
                    large_arc_flag = 1 if swAng >= math.pi else 0
                    paths = bezier_paths_from_arc_endpoints(
                        tuple2(wR, hR), 0, large_arc_flag, 1,
                        tuple2(*current_point), tuple2(*pt), T)
                    bezier_segments.extend(paths.asSegments())
                    coordinates.extend(bezier_sample(paths))
                    current_point = pt

                elif c.tag == DML('close'):
                    if first_point is not None and current_point != first_point:
                        coordinates.append(T.transform_point(first_point))
                    closed = True
                    first_point = None
                    # Close current pptx_geometry and start a new one...

                elif c.tag == DML('cubicBezTo'):
                    coords = [BezierPoint(*T.transform_point(current_point))]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*T.transform_point(pt)))
                        current_point = pt
                    bz = CubicBezier(*coords)
                    bezier_segments.append(bz)
                    coordinates.extend(bezier_sample(bz))

                elif c.tag == DML('lnTo'):
                    pt = pptx_geometry.point(c.pt)
                    if moved:
                        coordinates.append(T.transform_point(current_point))
                        moved = False
                    coordinates.append(T.transform_point(pt))
                    current_point = pt

                elif c.tag == DML('moveTo'):
                    pt = pptx_geometry.point(c.pt)
                    if first_point is None:
                        first_point = pt
                    current_point = pt
                    moved = True

                elif c.tag == DML('quadBezTo'):
                    coords = [BezierPoint(*T.transform_point(current_point))]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*T.transform_point(pt)))
                        current_point = pt
                    bz = QuadraticBezier(*coords)
                    bezier_segments.append(bz)
                    coordinates.extend(bezier_sample(bz))

                else:
                    print('Unknown path element: {}'.format(c.tag))

        if settings.get('saveBeziers', False) and len(bezier_segments) > 0:
            properties['bezier-segments'] = [
                repr(bz) for bz in bezier_segments
            ]

        if closed:
            geometry = shapely.geometry.Polygon(coordinates)
        else:
            geometry = shapely.geometry.LineString(coordinates)
            if properties.get('closed', False):
                # Return a polygon if flagged as `closed`
                coordinates.append(coordinates[0])
                return shapely.geometry.Polygon(coordinates)
        return geometry
Ejemplo n.º 22
0
 def toCubicBezier(self):
     """Converts the quadratic bezier to a CubicBezier"""
     from beziers.cubicbezier import CubicBezier
     return CubicBezier(self[0], self[0] * (1 / 3.) + self[1] * (2 / 3.),
                        self[1] * (2 / 3.) + self[2] * (1 / 3.), self[2])
Ejemplo n.º 23
0
 def test_length(self):
   q = CubicBezier(
     Point(120,160), Point(35,200), Point(220,260), Point(220,40)
   )
   self.assertAlmostEqual(q.length,272.87003168)