Esempio n. 1
0
def add_ellipse(dwg: svgwrite.Drawing,
                container: BaseElement,
                center,
                beta: float,
                rotation,
                size: int = 100,
                color: str = "blue",
                marker_size: int = 20,
                width: int = 1,
                ell_scale=0.8):
    """
    Add ellipse to svg files with two arrows at outline
    :return group with arcs of ellipse
    :param dwg a Drawing class object
    :param container some object of subclass BasElement
    :param center of ellipse in pixel  (2d tuple)
    :param size length of side square what restricted the ellipse
    :param beta angle of ellipticity. beta = tg(e)
    :param rotation contre clock wise rotation in radian
    :param color color of outline and arrow
    :param marker_size in pixels. It define side of the square where will be an arrow.
    :param width width of the outlines
    :param ell_scale coefficient of scale the size of ellipse
    """
    # if abs(rotation) < 4*np.finfo(float).eps:
    #     g = Group(transform=f"translate({center[0]},{center[1]})")
    # else:
    if abs(beta) < properties.EPS_D:
        radii = (0, 0)
        ell_point_x = size / 2  # - marker_size // 4
    else:
        radii = (abs(math.cos(beta)), abs(math.sin(beta)))
        radii = np.multiply(radii, size / (2 * max(radii[0], radii[1])))
        ell_point_x = radii[0]
    # print(radii)
    g = Group(
        transform=
        f"translate({center[0]},{center[1]}) scale(1,-1) rotate({np.rad2deg(rotation)})"
    )
    arrow_marker: Marker = dwg.marker(refX=marker_size // 2 *
                                      (-1 if beta > 0 else 1),
                                      refY=marker_size // 2,
                                      markerUnits="strokeWidth",
                                      markerWidth=int(0.4 * marker_size),
                                      markerHeight=int(0.3 * marker_size),
                                      orient="auto")
    # Marker()
    arrow_marker.viewbox(minx=0, miny=0, width=marker_size, height=marker_size)
    ms = marker_size
    ms_2 = marker_size // 2
    str_path = f"M -{ms_2}, 0 L {ms_2} {ms_2} L -{ms_2} {ms}" if beta > 0 else \
        f"M {ms_2}, 0 L -{ms_2} {ms_2} L {ms_2} {ms}"
    arrow_head: svgwrite.path.Path = arrow_marker.add(dwg.path(d=str_path))
    # beta > 0 - right cw beta < 0 - left ccw
    arrow_head.fill("none")
    arrow_head.stroke(color, 2 * width)
    dwg.defs.add(arrow_marker)
    radii = np.asarray(radii)
    radii = radii * ell_scale
    ell_point_x = ell_point_x * ell_scale

    # just axes
    g.add(
        dwg.path(d=f"M 50,50 l -100,0 l 0,-100 l 100,0 l 0,100",
                 transform=f"rotate({-np.rad2deg(rotation)})"))
    point = g.add(dwg.path(d=f"M 0,0 L 5,0 M 0,0 L 0,3")
                  )  # if abs(beta) > properties.EPS_D else None
    arc1 = g.add(
        dwg.path(
            d=f"M {ell_point_x},0 a{radii[0]},{radii[1]} 0 0,0 -{2 * ell_point_x},0"
        ))
    arc2 = g.add(
        dwg.path(
            d=f"M -{ell_point_x},0 a{radii[0]},{radii[1]} 0 0,0 {2 * ell_point_x},0"
        ))
    arc1.set_markers(
        (None, None, arrow_marker
         ))  # set the end marker. start and middle markers is empty.
    arc2.set_markers((None, None, arrow_marker))
    g.fill("none")
    g.stroke(color)
    g.stroke(color, width)
    return container.add(g)