示例#1
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
示例#2
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
示例#3
0
def get_draw_angles(start: float, end: float, extrusion: Vector):
    if extrusion.isclose(Z_AXIS):
        return start, end
    else:
        ocs = OCS(extrusion)
        s = ocs.to_wcs(Vector.from_angle(start))
        e = ocs.to_wcs(Vector.from_angle(end))
        return normalize_angle(e.angle), normalize_angle(s.angle)
示例#4
0
class OCSTransform:
    def __init__(self, extrusion: Vec3 = None, m: Matrix44 = None):
        self.m = m
        if extrusion is None:
            self.old_ocs = None
            self.scale_uniform = False
            self.new_ocs = None
        else:
            self.old_ocs = OCS(extrusion)
            new_extrusion, self.scale_uniform = transform_extrusion(extrusion, m)
            self.new_ocs = OCS(new_extrusion)

    @property
    def old_extrusion(self) -> Vec3:
        return self.old_ocs.uz

    @property
    def new_extrusion(self) -> Vec3:
        return self.new_ocs.uz

    @classmethod
    def from_ocs(cls, old: OCS, new: OCS, m: Matrix44) -> 'OCSTransform':
        ocs = cls()
        ocs.m = m
        ocs.old_ocs = old
        ocs.new_ocs = new
        return ocs

    def transform_length(self, length: 'Vertex', reflection=1.0) -> float:
        """ Returns magnitude of `length` direction vector transformed from
        old OCS into new OCS including `reflection` correction applied.
        """
        return self.m.transform_direction(self.old_ocs.to_wcs(length)).magnitude * sign(reflection)

    transform_scale_factor = transform_length

    def transform_vertex(self, vertex: 'Vertex') -> Vec3:
        """ Returns vertex transformed from old OCS into new OCS. """
        return self.new_ocs.from_wcs(self.m.transform(self.old_ocs.to_wcs(vertex)))

    def transform_2d_vertex(self, vertex: 'Vertex', elevation: float) -> Vec2:
        """ Returns 2D vertex transformed from old OCS into new OCS. """
        v = Vec3(vertex).replace(z=elevation)
        return self.new_ocs.from_wcs(self.m.transform(self.old_ocs.to_wcs(v))).vec2

    def transform_direction(self, direction: 'Vertex') -> Vec3:
        """ Returns direction transformed from old OCS into new OCS. """
        return self.new_ocs.from_wcs(self.m.transform_direction(self.old_ocs.to_wcs(direction)))

    def transform_angle(self, angle: float) -> float:
        """ Returns angle (in radians) from old OCS transformed into new OCS.
        """
        return self.transform_direction(Vec3.from_angle(angle)).angle

    def transform_deg_angle(self, angle: float) -> float:
        """ Returns angle (in degrees) from old OCS transformed into new OCS.
        """
        return math.degrees(self.transform_angle(math.radians(angle)))
示例#5
0
    def transform(self, m: Matrix44) -> 'MText':
        """ Transform the MTEXT entity by transformation matrix `m` inplace. """
        dxf = self.dxf
        old_extrusion = Vec3(dxf.extrusion)
        new_extrusion, _ = transform_extrusion(old_extrusion, m)

        if dxf.hasattr('rotation') and not dxf.hasattr('text_direction'):
            # MTEXT is not an OCS entity, but I don't know how else to convert
            # a rotation angle for an entity just defined by an extrusion vector.
            # It's correct for the most common case: extrusion=(0, 0, 1)
            ocs = OCS(old_extrusion)
            dxf.text_direction = ocs.to_wcs(Vec3.from_deg_angle(dxf.rotation))

        dxf.discard('rotation')

        old_text_direction = Vec3(dxf.text_direction)
        new_text_direction = m.transform_direction(old_text_direction)

        old_char_height_vec = old_extrusion.cross(
            old_text_direction).normalize(dxf.char_height)
        new_char_height_vec = m.transform_direction(old_char_height_vec)
        oblique = new_text_direction.angle_between(new_char_height_vec)
        dxf.char_height = new_char_height_vec.magnitude * math.sin(oblique)

        if dxf.hasattr('width'):
            width_vec = old_text_direction.normalize(dxf.width)
            dxf.width = m.transform_direction(width_vec).magnitude

        dxf.insert = m.transform(dxf.insert)
        dxf.text_direction = new_text_direction
        dxf.extrusion = new_extrusion
        return self
示例#6
0
def transform_extrusion(extrusion: 'Vertex', m: Matrix44) -> Tuple[Vec3, bool]:
    """
    Transforms the old `extrusion` vector into a new extrusion vector. Returns the new extrusion vector and a
    boolean value: ``True`` if the new OCS established by the new extrusion vector has a uniform scaled xy-plane,
    else ``False``.

    The new extrusion vector is perpendicular to plane defined by the transformed x- and y-axis.

    Args:
        extrusion: extrusion vector of the old OCS
        m: transformation matrix

    Returns:

    """
    ocs = OCS(extrusion)
    ocs_x_axis_in_wcs = ocs.to_wcs(X_AXIS)
    ocs_y_axis_in_wcs = ocs.to_wcs(Y_AXIS)
    x_axis, y_axis = m.transform_directions(
        (ocs_x_axis_in_wcs, ocs_y_axis_in_wcs))

    # Not sure if this is the correct test for a uniform scaled xy-plane
    is_uniform = math.isclose(x_axis.magnitude_square,
                              y_axis.magnitude_square,
                              abs_tol=1e-9)
    new_extrusion = x_axis.cross(y_axis).normalize()
    return new_extrusion, is_uniform
示例#7
0
 def _to_wcs(self, ocs: OCS, elevation: float):
     self._start = ocs.to_wcs(self._start.replace(z=elevation))
     for i, cmd in enumerate(self._commands):
         new_cmd = [cmd[0]]
         new_cmd.extend(
             ocs.points_to_wcs(p.replace(z=elevation) for p in cmd[1:]))
         self._commands[i] = tuple(new_cmd)
示例#8
0
def from_hatch_boundary_path(
        boundary: AbstractBoundaryPath,
        ocs: OCS = None,
        elevation: float = 0,
        offset: Vec3 = NULLVEC,  # ocs offset!
) -> "Path":
    """Returns a :class:`Path` object from a :class:`~ezdxf.entities.Hatch`
    polyline- or edge path.

    .. versionchanged:: 17.1

        Attaches the boundary state to each path as
        :class:`ezdxf.lldxf.const.BoundaryPathState`.

    """
    if isinstance(boundary, EdgePath):
        p = from_hatch_edge_path(boundary, ocs, elevation)
    elif isinstance(boundary, PolylinePath):
        p = from_hatch_polyline_path(boundary, ocs, elevation)
    else:
        raise TypeError(type(boundary))

    if offset and ocs is not None:  # only for MPOLYGON
        # assume offset is in OCS
        offset = ocs.to_wcs(offset.replace(z=elevation))
        p = p.transform(Matrix44.translate(offset.x, offset.y, offset.z))

    # attach path type information
    p.user_data = const.BoundaryPathState.from_flags(boundary.path_type_flags)
    return p
示例#9
0
    def from_arc(
        cls,
        center: "Vertex" = NULLVEC,
        radius: float = 1,
        extrusion: "Vertex" = Z_AXIS,
        start_angle: float = 0,
        end_angle: float = 360,
        ccw: bool = True,
    ) -> "ConstructionEllipse":
        """Returns :class:`ConstructionEllipse` from arc or circle.

        Arc and Circle parameters defined in OCS.

        Args:
             center: center in OCS
             radius: arc or circle radius
             extrusion: OCS extrusion vector
             start_angle: start angle in degrees
             end_angle: end angle in degrees
             ccw: arc curve goes counter clockwise from start to end if ``True``
        """
        radius = abs(radius)
        if NULLVEC.isclose(extrusion):
            raise ValueError(f"Invalid extrusion: {str(extrusion)}")
        ratio = 1.0
        ocs = OCS(extrusion)
        center = ocs.to_wcs(center)
        # Major axis along the OCS x-axis.
        major_axis = ocs.to_wcs(Vec3(radius, 0, 0))
        # No further adjustment of start- and end angle required.
        start_param = math.radians(start_angle)
        end_param = math.radians(end_angle)
        return cls(
            center,
            major_axis,
            extrusion,
            ratio,
            start_param,
            end_param,
            bool(ccw),
        )
示例#10
0
def test_ocs_to_wcs():
    ocs = OCS(EXTRUSION)
    wcs = ocs.to_wcs((9.41378764657076, 13.15481838975576, 0.8689258932616031))
    assert is_close_points(
        wcs,
        (-9.56460754, 8.44764172, 9.97894327),
        places=6,
    )
    assert is_close_points(
        ocs.to_wcs((9.41378764657076, 1.745643639268379, 0.8689258932616031)),
        (-1.60085321, 9.29648008, 1.85322122),
        places=6,
    )
    assert is_close_points(
        ocs.to_wcs((9.41378764657076, 4.552784531093068, 0.8689258932616031)),
        (-3.56027455, 9.08762984, 3.85249348),
        places=6,
    )
    assert is_close_points(
        ocs.to_wcs((9.41378764657076, 7.386888158025531, 0.8689258932616031)),
        (-5.53851623, 8.87677359, 5.87096886),
        places=6,
    )
示例#11
0
def test_circle_user_ocs():
    center = (2, 3, 4)
    extrusion = (0, 1, 0)

    circle = Circle.new(
        dxfattribs={'center': center, 'extrusion': extrusion, 'thickness': 2})
    ocs = OCS(extrusion)
    v = ocs.to_wcs(center)  # (-2, 4, 3)
    v = Vector(v.x * 2, v.y * 4, v.z * 2)
    v += (1, 1, 1)
    # and back to OCS, extrusion is unchanged
    result = ocs.from_wcs(v)

    m = Matrix44.chain(Matrix44.scale(2, 4, 2), Matrix44.translate(1, 1, 1))
    circle.transform(m)
    assert circle.dxf.center == result
    assert circle.dxf.extrusion == (0, 1, 0)
    assert circle.dxf.thickness == 8  # in WCS y-axis
示例#12
0
文件: path.py 项目: Sean-Spark/ezdxf
 def to_wcs(self, ocs: OCS, elevation: float):
     """ Transform path from given `ocs` to WCS coordinates inplace. """
     self._start = ocs.to_wcs(self._start.replace(z=elevation))
     for i, cmd in enumerate(self._commands):
         self._commands[i] = cmd.to_wcs(ocs, elevation)
示例#13
0
 def to_wcs(self, ocs: OCS, elevation: float):
     return CurveTo(
         end=ocs.to_wcs(self.end.replace(z=elevation)),
         ctrl1=ocs.to_wcs(self.ctrl1.replace(z=elevation)),
         ctrl2=ocs.to_wcs(self.ctrl2.replace(z=elevation)),
     )
示例#14
0
 def to_wcs(self, ocs: OCS, elevation: float):
     return LineTo(end=ocs.to_wcs(self.end.replace(z=elevation)))
示例#15
0
 def _to_wcs(self, ocs: OCS, elevation: float):
     self._start = ocs.to_wcs(self._start.replace(z=elevation))
     for i, cmd in enumerate(self._commands):
         self._commands[i] = cmd.to_wcs(ocs, elevation)
示例#16
0
 def to_wcs(self, ocs: OCS, elevation: float) -> None:
     """Transform path from given `ocs` to WCS coordinates inplace."""
     self._vertices = list(
         ocs.to_wcs(v.replace(z=elevation)) for v in self._vertices)