예제 #1
0
def _virtual_polyline_entities(points, elevation: float, extrusion: Vec3,
                               dxfattribs: dict,
                               doc) -> Iterable[Union["Line", "Arc"]]:
    ocs = OCS(extrusion) if extrusion else OCS()
    prev_point = None
    prev_bulge = None

    for x, y, bulge in points:
        point = Vec3(x, y, elevation)
        if prev_point is None:
            prev_point = point
            prev_bulge = bulge
            continue

        attribs = dict(dxfattribs)
        if prev_bulge != 0:
            center, start_angle, end_angle, radius = bulge_to_arc(
                prev_point, point, prev_bulge)
            if radius > 0:
                attribs["center"] = Vec3(center.x, center.y, elevation)
                attribs["radius"] = radius
                attribs["start_angle"] = math.degrees(start_angle)
                attribs["end_angle"] = math.degrees(end_angle)
                if extrusion:
                    attribs["extrusion"] = extrusion
                yield factory.new(dxftype="ARC", dxfattribs=attribs, doc=doc)
        else:
            attribs["start"] = ocs.to_wcs(prev_point)
            attribs["end"] = ocs.to_wcs(point)
            yield factory.new(dxftype="LINE", dxfattribs=attribs, doc=doc)
        prev_point = point
        prev_bulge = bulge
예제 #2
0
파일: explode.py 프로젝트: vshu3000/ezdxf
def _virtual_polyline_entities(points, elevation: float, extrusion: Vector,
                               dxfattribs: dict,
                               doc) -> Iterable[Union['Line', 'Arc']]:
    ocs = OCS(extrusion) if extrusion else OCS()
    prev_point = None
    prev_bulge = None

    for x, y, bulge in points:
        point = Vector(x, y, elevation)
        if prev_point is None:
            prev_point = point
            prev_bulge = bulge
            continue

        attribs = dict(dxfattribs)
        if prev_bulge != 0:
            center, start_angle, end_angle, radius = bulge_to_arc(
                prev_point, point, prev_bulge)
            attribs['center'] = Vector(center.x, center.y, elevation)
            attribs['radius'] = radius
            attribs['start_angle'] = math.degrees(start_angle)
            attribs['end_angle'] = math.degrees(end_angle)
            if extrusion:
                attribs['extrusion'] = extrusion
            yield factory.new(dxftype='ARC', dxfattribs=attribs, doc=doc)
        else:
            attribs['start'] = ocs.to_wcs(prev_point)
            attribs['end'] = ocs.to_wcs(point)
            yield factory.new(dxftype='LINE', dxfattribs=attribs, doc=doc)
        prev_point = point
        prev_bulge = bulge
예제 #3
0
def test_bulge_to_arc():
    center, start_angle, end_angle, radius = bulge_to_arc(start_point=(0, 0),
                                                          end_point=(1, 0),
                                                          bulge=-1)
    assert center.isclose((.5, 0., 0.))
    assert math.isclose(start_angle, 0, abs_tol=1e-15)
    assert math.isclose(end_angle, math.pi)
    assert radius == .5
예제 #4
0
 def bulge_to(p1: Vec3, p2: Vec3, bulge: float):
     if p1.isclose(p2):
         return
     center, start_angle, end_angle, radius = bulge_to_arc(p1, p2, bulge)
     ellipse = ConstructionEllipse.from_arc(
         center, radius, Z_AXIS,
         math.degrees(start_angle),
         math.degrees(end_angle),
     )
     curves = list(cubic_bezier_from_ellipse(ellipse))
     if curves[0].control_points[0].isclose(p2):
         curves = _reverse_bezier_curves(curves)
     self.add_curves(curves)
예제 #5
0
 def bulge_to(p1: Vec3, p2: Vec3, bulge: float):
     if p1.isclose(p2, rel_tol=IS_CLOSE_TOL, abs_tol=0):
         return
     center, start_angle, end_angle, radius = bulge_to_arc(p1, p2, bulge)
     ellipse = ConstructionEllipse.from_arc(
         center, radius, Z_AXIS,
         math.degrees(start_angle),
         math.degrees(end_angle),
     )
     curves = list(cubic_bezier_from_ellipse(ellipse))
     curve0 = curves[0]
     cp0 = curve0.control_points[0]
     if cp0.isclose(p2, rel_tol=IS_CLOSE_TOL, abs_tol=0):
         curves = reverse_bezier_curves(curves)
     add_bezier4p(path, curves)
예제 #6
0
        def _edges(points) -> Iterable[Union[LineEdge, ArcEdge]]:
            prev_point = None
            prev_bulge = None
            for x, y, bulge in points:
                point = Vec3(x, y)
                if prev_point is None:
                    prev_point = point
                    prev_bulge = bulge
                    continue

                if prev_bulge != 0:
                    arc = ArcEdge()
                    # bulge_to_arc returns always counter-clockwise oriented
                    # start- and end angles:
                    (
                        arc.center,
                        start_angle,
                        end_angle,
                        arc.radius,
                    ) = bulge_to_arc(prev_point, point, prev_bulge)
                    chk_point = arc.center + Vec2.from_angle(
                        start_angle, arc.radius
                    )
                    arc.ccw = chk_point.isclose(prev_point, abs_tol=1e-9)
                    arc.start_angle = math.degrees(start_angle) % 360.0
                    arc.end_angle = math.degrees(end_angle) % 360.0
                    if math.isclose(
                        arc.start_angle, arc.end_angle
                    ) and math.isclose(arc.start_angle, 0):
                        arc.end_angle = 360.0
                    yield arc
                else:
                    line = LineEdge()
                    line.start = (prev_point.x, prev_point.y)
                    line.end = (point.x, point.y)
                    yield line

                prev_point = point
                prev_bulge = bulge
예제 #7
0
파일: trace.py 프로젝트: yanbin-ha/ezdxf
    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