def test_vertices():
    angles = [0, 45, 90, 135, -45, -90, -135, 180]
    arc = ConstructionArc(center=(1, 1))
    vertices = list(arc.vertices(angles))
    for v, a in zip(vertices, angles):
        a = math.radians(a)
        assert v.isclose(Vec2((1 + math.cos(a), 1 + math.sin(a))))
Esempio n. 2
0
    def from_arc(cls,
                 arc: ConstructionArc,
                 start_width: float,
                 end_width: float,
                 segments: int = 64) -> 'CurvedTrace':
        """
        Create curved trace from an arc.

        Args:
            arc: :class:`~ezdxf.math.ConstructionArc` object
            start_width: start width
            end_width: end width
            segments: count of segments for full circle (360 degree) approximation, partial arcs have proportional
                      less segments, but at least 3

        Raises:
            ValueError: if arc.radius <= 0

        """
        if arc.radius <= 0:
            raise ValueError(f'Invalid radius: {arc.radius}.')
        curve_trace = cls()
        count = max(math.ceil(arc.angle_span / 360.0 * segments), 3) + 1
        center = Vec2(arc.center)
        for point, width in zip(arc.vertices(arc.angles(count)),
                                linspace(start_width, end_width, count)):
            curve_trace._append(point, point - center, width)
        return curve_trace
def test_point_is_not_in_arc_range(p):
    """
    Test if the angle defined by arc.center and point "p" is NOT in the range
    arc.start_angle to arc.end_angle:
    """
    arc = ConstructionArc((0, 0), 1, -90, 90)
    assert arc._is_point_in_arc_range(Vec2(p)) is False
Esempio n. 4
0
def test_angle_span():
    assert ConstructionArc(start_angle=30, end_angle=270).angle_span == 240
    # crossing 0-degree:
    assert ConstructionArc(start_angle=30, end_angle=270,
                           is_counter_clockwise=False).angle_span == 120
    # crossing 0-degree:
    assert ConstructionArc(start_angle=300, end_angle=60).angle_span == 120
    assert ConstructionArc(start_angle=300, end_angle=60,
                           is_counter_clockwise=False).angle_span == 240
def test_tangents():
    angles = [0, 45, 90, 135, -45, -90, -135, 180]
    sin45 = math.sin(math.pi / 4)
    result = [(0, 1), (-sin45, sin45), (-1, 0), (-sin45, -sin45),
              (sin45, sin45), (1, 0), (sin45, -sin45), (0, -1)]
    arc = ConstructionArc(center=(1, 1))
    vertices = list(arc.tangents(angles))
    for v, r in zip(vertices, result):
        assert v.isclose(Vec2(r))
Esempio n. 6
0
def test_bounding_box():
    bbox = ConstructionArc(center=(0, 0), radius=1, start_angle=0,
                           end_angle=90).bounding_box
    assert bbox.extmin == (0, 0)
    assert bbox.extmax == (1, 1)

    bbox = ConstructionArc(center=(0, 0), radius=1, start_angle=0,
                           end_angle=180).bounding_box
    assert bbox.extmin == (-1, 0)
    assert bbox.extmax == (1, 1)

    bbox = ConstructionArc(center=(0, 0), radius=1, start_angle=270,
                           end_angle=90).bounding_box
    assert bbox.extmin == (0, -1)
    assert bbox.extmax == (1, 1)
def test_spatial_arc_from_3p():
    start_point_wcs = Vector(0, 1, 0)
    end_point_wcs = Vector(1, 0, 0)
    def_point_wcs = Vector(0, 0, 1)

    ucs = UCS.from_x_axis_and_point_in_xy(origin=def_point_wcs,
                                          axis=end_point_wcs - def_point_wcs,
                                          point=start_point_wcs)
    start_point_ucs = ucs.from_wcs(start_point_wcs)
    end_point_ucs = ucs.from_wcs(end_point_wcs)
    def_point_ucs = Vector(0, 0)

    arc = ConstructionArc.from_3p(start_point_ucs, end_point_ucs,
                                  def_point_ucs)
    dwg = ezdxf.new('R12')
    msp = dwg.modelspace()

    dxf_arc = arc.add_to_layout(msp, ucs)
    assert dxf_arc.dxftype() == 'ARC'
    assert isclose(dxf_arc.dxf.radius, 0.81649658, abs_tol=1e-9)
    assert isclose(dxf_arc.dxf.start_angle, -30)  # ???
    assert isclose(dxf_arc.dxf.end_angle, -150)  # ???
    assert is_close_points(dxf_arc.dxf.extrusion,
                           (0.57735027, 0.57735027, 0.57735027),
                           abs_tol=1e-9)
Esempio n. 8
0
def test_rational_spline_from_circular_arc_has_same_end_points():
    arc = ConstructionArc(
        start_angle=30, end_angle=330)
    spline = rational_bspline_from_arc(
        start_angle=arc.start_angle, end_angle=arc.end_angle)
    assert arc.start_point.isclose(spline.control_points[0])
    assert arc.end_point.isclose(spline.control_points[-1])
def test_arc_from_3p():
    p1 = (-15.73335, 10.98719)
    p2 = (-12.67722, 8.76554)
    p3 = (-8.00817, 12.79635)
    arc = ConstructionArc.from_3p(start_point=p1, end_point=p2, def_point=p3)

    arc_result = ConstructionArc(
        center=(-12.08260, 12.79635),
        radius=4.07443,
        start_angle=-153.638906,
        end_angle=-98.391676,
    )

    assert arc.center.isclose(arc_result.center, abs_tol=1e-5)
    assert isclose(arc.radius, arc_result.radius, abs_tol=1e-5)
    assert isclose(arc.start_angle, arc_result.start_angle, abs_tol=1e-4)
    assert isclose(arc.end_angle, arc_result.end_angle, abs_tol=1e-4)
Esempio n. 10
0
 def construction_tool(self) -> ConstructionArc:
     """Returns ConstructionArc() for the OCS representation."""
     return ConstructionArc(
         center=self.center,
         radius=self.radius,
         start_angle=self.start_angle,
         end_angle=self.end_angle,
     )
Esempio n. 11
0
def test_angles():
    arc = ConstructionArc(radius=1, start_angle=30, end_angle=60)
    assert tuple(arc.angles(2)) == (30, 60)
    assert tuple(arc.angles(3)) == (30, 45, 60)

    arc.start_angle = 180
    arc.end_angle = 0
    assert tuple(arc.angles(2)) == (180, 0)
    assert tuple(arc.angles(3)) == (180, 270, 0)

    arc.start_angle = -90
    arc.end_angle = -180
    assert tuple(arc.angles(2)) == (270, 180)
    assert tuple(arc.angles(4)) == (270, 0, 90, 180)
Esempio n. 12
0
def test_arc_from_2p_radius():
    p1 = (2, 1)
    p2 = (0, 3)
    radius = 2

    arc = ConstructionArc.from_2p_radius(start_point=p1, end_point=p2,
                                         radius=radius)
    assert arc.center == (0, 1)
    assert isclose(arc.radius, radius)
    assert isclose(arc.start_angle, 0)
    assert isclose(arc.end_angle, 90)

    arc = ConstructionArc.from_2p_radius(start_point=p2, end_point=p1,
                                         radius=radius)
    assert arc.center == Vector(2, 3)
    assert isclose(arc.radius, radius)
    assert isclose(arc.start_angle, 180)
    assert isclose(arc.end_angle, -90)
Esempio n. 13
0
def test_arc_from_2p_angle_simple():
    p1 = (2, 1)
    p2 = (0, 3)
    angle = 90

    arc = ConstructionArc.from_2p_angle(start_point=p1, end_point=p2,
                                        angle=angle)
    assert arc.center == (0, 1)
    assert isclose(arc.radius, 2)
    assert isclose(arc.start_angle, 0, abs_tol=1e-12)
    assert isclose(arc.end_angle, 90)

    arc = ConstructionArc.from_2p_angle(start_point=p2, end_point=p1,
                                        angle=angle)
    assert arc.center == (2, 3)
    assert isclose(arc.radius, 2)
    assert isclose(arc.start_angle, 180)
    assert isclose(arc.end_angle, -90)
Esempio n. 14
0
def test_arc_from_2p_angle_complex():
    p1 = (-15.73335, 10.98719)
    p2 = (-12.67722, 8.76554)
    angle = 55.247230
    arc = ConstructionArc.from_2p_angle(start_point=p1, end_point=p2,
                                        angle=angle)

    arc_result = ConstructionArc(
        center=(-12.08260, 12.79635),
        radius=4.07443,
        start_angle=-153.638906,
        end_angle=-98.391676,
    )

    assert arc.center.isclose(arc_result.center, abs_tol=1e-5)
    assert isclose(arc.radius, arc_result.radius, abs_tol=1e-5)
    assert isclose(arc.start_angle, arc_result.start_angle, abs_tol=1e-4)
    assert isclose(arc.end_angle, arc_result.end_angle, abs_tol=1e-4)
Esempio n. 15
0
def test_rational_spline_curve_points_by_nurbs_python():
    arc = ConstructionArc(end_angle=90)
    spline = rational_bspline_from_arc(end_angle=arc.end_angle)
    curve = spline.to_nurbs_python_curve()

    t = list(linspace(0, 1, 10))
    points = list(spline.points(t))
    expected = list(curve.evaluate_list(t))
    for p, e in zip(points, expected):
        assert p.isclose(e)
Esempio n. 16
0
def test_rational_spline_derivatives_by_nurbs_python():
    arc = ConstructionArc(end_angle=90)
    spline = rational_bspline_from_arc(end_angle=arc.end_angle)
    curve = spline.to_nurbs_python_curve()

    t = list(linspace(0, 1, 10))
    derivatives = list(spline.derivatives(t, n=1))
    expected = [curve.derivatives(u, 1) for u in t]
    for (p, d1), (e, ed1) in zip(derivatives, expected):
        assert p.isclose(e)
        assert d1.isclose(ed1)
Esempio n. 17
0
    def construction_tool(self) -> ConstructionArc:
        """ Returns 2D construction tool :class:`ezdxf.math.ConstructionArc`,
        ignoring the extrusion vector.

        """
        dxf = self.dxf
        return ConstructionArc(
            dxf.center,
            dxf.radius,
            dxf.start_angle,
            dxf.end_angle,
        )
Esempio n. 18
0
 def circular_arc_3p(self, data: bytes):
     bs = ByteStream(data)
     attribs = self._build_dxf_attribs()
     p1 = Vec3(bs.read_vertex())
     p2 = Vec3(bs.read_vertex())
     p3 = Vec3(bs.read_vertex())
     arc_type = bs.read_struct('L')[0]
     arc = ConstructionArc.from_3p(p1, p3, p2)
     attribs['center'] = arc.center
     attribs['radius'] = arc.radius
     attribs['start_angle'] = arc.start_angle
     attribs['end_angle'] = arc.end_angle
     return self._factory('ARC', dxfattribs=attribs)
Esempio n. 19
0
def dim_arc_3d():
    doc = ezdxf.new(DXFVERSION, setup=True)
    msp = doc.modelspace()

    for center, radius, sa, ea, distance in [[Vec3(0, 0), 5, 60, 90, 2]]:
        arc = ConstructionArc(center, radius, sa, ea)
        ucs = UCS(origin=center + (5, 5)).rotate_local_x(math.radians(45))
        msp.add_line(arc.center, arc.start_point).transform(ucs.matrix)
        msp.add_line(arc.center, arc.end_point).transform(ucs.matrix)

        dim = msp.add_arc_dim_arc(arc=arc,
                                  distance=distance,
                                  dimstyle="EZ_CURVED")
        dim.render(discard=BRICSCAD, ucs=ucs)

    doc.set_modelspace_vport(height=30)
    doc.saveas(OUTDIR / f"dim_arc_3d_{DXFVERSION}.dxf")
Esempio n. 20
0
def test_rational_spline_from_circular_arc_has_expected_parameters():
    arc = ConstructionArc(end_angle=90)
    spline = rational_bspline_from_arc(end_angle=arc.end_angle)
    assert spline.degree == 2

    cpoints = spline.control_points
    assert len(cpoints) == 3
    assert cpoints[0].isclose((1, 0, 0))
    assert cpoints[1].isclose((1, 1, 0))
    assert cpoints[2].isclose((0, 1, 0))

    weights = spline.weights()
    assert len(weights) == 3
    assert weights[0] == 1.0
    assert weights[1] == math.cos(math.pi / 4)
    assert weights[2] == 1.0

    # as BSpline constructor()
    s2 = BSpline.from_arc(arc)
    assert spline.control_points == s2.control_points
Esempio n. 21
0
def cut_dxf(dxf_file: Drawing, center: Vector, side: Vector):
    """
    切割dxf文件.

    Args:
        dxf_file: dxf文件路径, R12格式推荐.
        center: 切割线起点
        side: 切割线终点

    Returns:
        (float, Vector) : 交点至起点距离, 交点坐标. 如无交点则返回 None,None.

    """
    cutLine = ConstructionLine(center, side)
    pts = []
    # doc = ezdxf.readfile(dxf_file)
    doc = dxf_file
    msp = doc.modelspace()
    for e in msp:
        if e.dxftype() == 'LINE':
            # byLine = ConstructionLine(e.dxf.start, e.dxf.end)
            coord = intersection_seg_seg(list(e.dxf.start), list(e.dxf.end),
                                         list(cutLine.start),
                                         list(cutLine.end))
            # pt = cutLine.intersect(byLine)
            if coord != None and len(coord) != 0:
                pt = Vec2(*coord)
                pts.append(pt)
        elif e.dxftype() == 'ARC':
            byArc = ConstructionArc(e.dxf.center, e.dxf.radius,
                                    e.dxf.start_angle, e.dxf.end_angle)
            coord = intersection(cutLine, byArc)
            if coord != None and len(coord) != 0:
                pt = Vec2(*coord)
                pts.append(pt)

    if len(pts) != 0:
        pts.sort(key=lambda x: x.distance(center))
        return pts[0].distance(center), pts[0]
    else:
        return None, None
Esempio n. 22
0
    def from_polyline(cls,
                      polyline: 'DXFGraphic',
                      segments: int = 64) -> 'TraceBuilder':
        """
        Create a complete trace from a LWPOLYLINE or a 2D POLYLINE entity, the trace
        consist of multiple sub-traces if :term:`bulge` values are present.

        Args:
            polyline: :class:`~ezdxf.entities.LWPolyline` or 2D :class:`~ezdxf.entities.Polyline`
            segments: count of segments for bulge approximation, given count is for a full circle,
                      partial arcs have proportional less segments, but at least 3

        """
        dxftype = polyline.dxftype()
        if dxftype == 'LWPOLYLINE':
            polyline = cast('LWPOLYLINE', polyline)
            const_width = polyline.dxf.const_width
            points = []
            for x, y, start_width, end_width, bulge in polyline.lwpoints:
                location = Vec2(x, y)
                if const_width:
                    # This is AutoCAD behavior, BricsCAD uses const width
                    # only for missing width values.
                    start_width = const_width
                    end_width = const_width
                points.append((location, start_width, end_width, bulge))
            closed = polyline.closed
        elif dxftype == 'POLYLINE':
            polyline = cast('POLYLINE', polyline)
            if not polyline.is_2d_polyline:
                raise TypeError('2D POLYLINE required')
            closed = polyline.is_closed
            default_start_width = polyline.dxf.default_start_width
            default_end_width = polyline.dxf.default_end_width
            points = []
            for vertex in polyline.vertices:
                location = Vec2(vertex.dxf.location)
                if vertex.dxf.hasattr('start_width'):
                    start_width = vertex.dxf.start_width
                else:
                    start_width = default_start_width
                if vertex.dxf.hasattr('end_width'):
                    end_width = vertex.dxf.end_width
                else:
                    end_width = default_end_width
                bulge = vertex.dxf.bulge
                points.append((location, start_width, end_width, bulge))
        else:
            raise TypeError(f'Invalid DXF type {dxftype}')

        if closed and not points[0][0].isclose(points[-1][0]):
            # close polyline explicit
            points.append(points[0])

        trace = cls()
        store_bulge = None
        store_start_width = None
        store_end_width = None
        store_point = None

        linear_trace = LinearTrace()
        for point, start_width, end_width, bulge in points:
            if store_bulge:
                center, start_angle, end_angle, radius = bulge_to_arc(
                    store_point, point, store_bulge)
                if radius > 0:
                    arc = ConstructionArc(
                        center,
                        radius,
                        math.degrees(start_angle),
                        math.degrees(end_angle),
                        is_counter_clockwise=True,
                    )
                    if arc.start_point.isclose(point):
                        sw = store_end_width
                        ew = store_start_width
                    else:
                        ew = store_end_width
                        sw = store_start_width
                    trace.append(CurvedTrace.from_arc(arc, sw, ew, segments))
                store_bulge = None

            if bulge != 0:  # arc from prev_point to point
                if linear_trace.is_started:
                    linear_trace.add_station(point, start_width, end_width)
                    trace.append(linear_trace)
                    linear_trace = LinearTrace()
                store_bulge = bulge
                store_start_width = start_width
                store_end_width = end_width
                store_point = point
                continue

            linear_trace.add_station(point, start_width, end_width)
        if linear_trace.is_started:
            trace.append(linear_trace)

        if closed and len(trace) > 1:
            # This is required for traces with multiple paths to create the correct
            # miter at the closing point. (only linear to linear trace).
            trace.close()
        return trace
def test_arc_does_not_intersect_arc(c, r, s, e):
    arc = ConstructionArc((0, 0), 1, -90, 90)
    assert len(arc.intersect_arc(ConstructionArc(c, r, s, e))) == 0
def test_flattening(r, s, e, sagitta, count):
    arc = ConstructionArc((0, 0), r, s, e)
    assert len(list(arc.flattening(sagitta))) == count
def test_arc_intersect_circle_in_two_points(c, r):
    arc = ConstructionArc((0, 0), 1, -90, 90)
    assert len(arc.intersect_circle(ConstructionCircle(c, r))) == 2
def test_arc_does_not_intersect_line(s, e):
    arc = ConstructionArc((0, 0), 1, 0, 90)
    assert len(arc.intersect_line(ConstructionLine(s, e))) == 0
def test_arc_does_not_intersect_circle(c, r):
    arc = ConstructionArc((0, 0), 1, -90, 90)
    assert len(arc.intersect_circle(ConstructionCircle(c, r))) == 0
def test_arc_intersect_arc_in_two_points(c, r, s, e):
    arc = ConstructionArc((0, 0), 1, -90, 90)
    assert len(arc.intersect_arc(ConstructionArc(c, r, s, e))) == 2
Esempio n. 29
0
spline.apply_construction_tool(bspline)

# Recreate ARC from SPLINE, if you ASSUME or KNOW it is an ARC:
# for spline in msp.query("SPLINE):
#     ...
# 1. get the B-spline construction tool from the SPLINE entity
bspline = spline.construction_tool()
max_t = bspline.max_t

# calculate 3 significant points and 2 check points of the SPLINE:
start, chk1, middle, chk2, end = bspline.points([
    0, max_t * 0.25, max_t * 0.5, max_t * 0.75, max_t
])

# create an arc from 3 points:
arc_tool = ConstructionArc.from_3p(start, end, middle)
arc_tool.add_to_layout(msp, dxfattribs={
    "layer": "recreated arc",
    "color": ezdxf.const.MAGENTA,
})

# This only works for flat B-splines in the xy-plane, a.k.a. 2D splines!

# Check the assumption:
center = arc_tool.center
radius = arc_tool.radius
err = max(abs(radius - p.distance(center)) for p in (chk1, chk2))
print(f"max error: {err:.6f}")

# Warning: this does not proof that the assumption was correct, it is always
# possible to create a diverging B-spline which matches the check points:
Esempio n. 30
0
# create a 3D arc from 3 points in WCS
start_point_wcs = Vec3(3, 0, 0)
end_point_wcs = Vec3(0, 3, 0)
def_point_wcs = Vec3(0, 0, 3)

# create UCS
ucs = UCS.from_x_axis_and_point_in_xy(origin=def_point_wcs,
                                      axis=start_point_wcs - def_point_wcs,
                                      point=end_point_wcs)
start_point_ucs = ucs.from_wcs(start_point_wcs)
end_point_ucs = ucs.from_wcs(end_point_wcs)
def_point_ucs = Vec3(0, 0)  # origin of UCS

# create arc in the xy-plane of the UCS
arc = ConstructionArc.from_3p(start_point_ucs, end_point_ucs, def_point_ucs)
arc.add_to_layout(modelspace, ucs, dxfattribs={'color': 1})  # red arc

arc = ConstructionArc.from_3p(end_point_ucs, start_point_ucs, def_point_ucs)
arc.add_to_layout(modelspace, ucs, dxfattribs={'color': 2})  # yellow arc

p1 = Vec3(0, -18)
p2 = Vec3(0, +18)
arc = ConstructionArc.from_2p_angle(p1, p2, 90)
arc.add_to_layout(modelspace, dxfattribs={'color': 1})

arc = ConstructionArc.from_2p_angle(p1, p2, 90, ccw=False)
arc.add_to_layout(modelspace, dxfattribs={'color': 2})

p1 = Vec3(20, -18)
p2 = Vec3(20, +18)