Ejemplo n.º 1
0
    def translate(self, dx: float, dy: float, dz: float) -> 'Text':
        """ Optimized TEXT/ATTRIB/ATTDEF translation about `dx` in x-axis, `dy` in y-axis and `dz` in z-axis,
        returns `self` (floating interface).

        .. versionadded:: 0.13

        """
        ocs = self.ocs()
        dxf = self.dxf
        vec = Vector(dx, dy, dz)

        dxf.insert = ocs.from_wcs(vec + ocs.to_wcs(dxf.insert))
        if dxf.hasattr('align_point'):
            dxf.align_point = ocs.from_wcs(vec + ocs.to_wcs(dxf.align_point))
        return self
Ejemplo n.º 2
0
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, 330)
    assert isclose(dxf_arc.dxf.end_angle, 210)
    assert dxf_arc.dxf.extrusion.isclose((0.57735027, 0.57735027, 0.57735027),
                                         abs_tol=1e-9)
Ejemplo n.º 3
0
    def vertices(self, angles: Iterable[float]) -> Iterable[Vector]:
        """
        Yields vertices of the circle for iterable `angles` in WCS. This method takes into account a local OCS.

        Args:
            angles: iterable of angles in OCS as degrees, angle goes counter clockwise around the extrusion vector,
                    ocs x-axis = 0 deg.

        .. versionadded:: 0.11

        """
        ocs = self.ocs()
        for angle in angles:
            v = Vector.from_deg_angle(angle, self.dxf.radius) + self.dxf.center
            yield ocs.to_wcs(v)
Ejemplo n.º 4
0
    def draw_viewport_entity(self, entity: DXFGraphic) -> None:
        assert entity.dxftype() == 'VIEWPORT'
        dxf = entity.dxf
        view_vector: Vector = dxf.view_direction_vector
        mag = view_vector.magnitude
        if math.isclose(mag, 0.0):
            print('warning: viewport with null view vector')
            return
        view_vector /= mag
        if not math.isclose(view_vector.dot(Vector(0, 0, 1)), 1.0):
            print(
                f'cannot render viewport with non-perpendicular view direction: {dxf.view_direction_vector}'
            )
            return

        cx, cy = dxf.center.x, dxf.center.y
        dx = dxf.width / 2
        dy = dxf.height / 2
        minx, miny = cx - dx, cy - dy
        maxx, maxy = cx + dx, cy + dy
        points = [(minx, miny), (maxx, miny), (maxx, maxy), (minx, maxy),
                  (minx, miny)]
        self.out.draw_filled_polygon([Vector(x, y, 0) for x, y in points],
                                     VIEWPORT_COLOR)
Ejemplo n.º 5
0
def test_edge_path_transform_interface(hatch, m44):
    path = hatch.paths.add_edge_path()
    path.add_line((0, 0), (10, 0))
    path.add_arc((10, 5), radius=5, start_angle=270, end_angle=450, ccw=1)
    path.add_ellipse((5, 10),
                     major_axis=(5, 0),
                     ratio=0.2,
                     start_angle=0,
                     end_angle=180)
    spline = path.add_spline([(1, 1), (2, 2), (3, 3), (4, 4)],
                             degree=3,
                             periodic=1)
    # the following values do not represent a mathematically valid spline
    spline.control_points = [(1, 1), (2, 2), (3, 3), (4, 4)]
    spline.knot_values = [1, 2, 3, 4, 5, 6]
    spline.weights = [4, 3, 2, 1]
    spline.start_tangent = (10, 1)
    spline.end_tangent = (2, 20)

    chk = list(
        m44.transform_vertices([
            Vector(0, 0),
            Vector(10, 0),
            Vector(10, 5),
            Vector(5, 10),
            Vector(1, 1),
            Vector(2, 2),
            Vector(3, 3),
            Vector(4, 4),
        ]))

    hatch.transform(m44)
    line = path.edges[0]
    assert chk[0].isclose(line.start)
    assert chk[1].isclose(line.end)
    arc = path.edges[1]
    assert chk[2].isclose(arc.center)
    ellipse = path.edges[2]
    assert chk[3].isclose(ellipse.center)
    spline = path.edges[3]
    for c, v in zip(chk[4:], spline.control_points):
        assert c.isclose(v)
    for c, v in zip(chk[4:], spline.fit_points):
        assert c.isclose(v)
    assert m44.transform_direction((10, 1, 0)).isclose(spline.start_tangent)
    assert m44.transform_direction((2, 20, 0)).isclose(spline.end_tangent)
Ejemplo n.º 6
0
def cubic_bezier_arc_parameters(start_angle: float,
                                end_angle: float,
                                segments: int = 1) -> Sequence[Vector]:
    """
    Yields cubic Bézier-curve parameters for a circular 2D arc with center at (0, 0) and a radius of 1
    in the form of [start point, 1. control point, 2. control point, end point].

    Args:
        start_angle: start angle in radians
        end_angle: end angle in radians (end_angle > start_angle!)
        segments: count of Bèzier-curve segments, at least one segment for each quarter (pi/2)

    """
    if segments < 1:
        raise ValueError('Invalid argument segments (>= 1).')
    delta_angle = end_angle - start_angle
    if delta_angle > 0:
        arc_count = max(math.ceil(delta_angle / math.pi * 2.0), segments)
    else:
        raise ValueError('Delta angle from start- to end angle has to be > 0.')

    segment_angle = delta_angle / arc_count
    tangent_length = TANGENT_FACTOR * math.tan(segment_angle / 4.0)

    angle = start_angle
    end_point = None
    for _ in range(arc_count):
        start_point = Vector.from_angle(
            angle) if end_point is None else end_point
        angle += segment_angle
        end_point = Vector.from_angle(angle)
        control_point_1 = start_point + (-start_point.y * tangent_length,
                                         start_point.x * tangent_length)
        control_point_2 = end_point + (end_point.y * tangent_length,
                                       -end_point.x * tangent_length)
        yield start_point, control_point_1, control_point_2, end_point
Ejemplo n.º 7
0
 def build():
     arc = Arc.new(
         dxfattribs={
             'start_angle': random.uniform(0, 360),
             'end_angle': random.uniform(0, 360),
         })
     vertices = list(arc.vertices(arc.angles(vertex_count)))
     m = Matrix44.chain(
         Matrix44.axis_rotate(axis=Vector.random(),
                              angle=random.uniform(0, math.tau)),
         Matrix44.translate(dx=random.uniform(-2, 2),
                            dy=random.uniform(-2, 2),
                            dz=random.uniform(-2, 2)),
     )
     return synced_transformation(arc, vertices, m)
Ejemplo n.º 8
0
    def draw_line_entity(self, entity: DXFGraphic) -> None:
        d, dxftype = entity.dxf, entity.dxftype()
        properties = self._resolve_properties(entity)
        if dxftype == 'LINE':
            self.out.draw_line(d.start, d.end, properties)

        elif dxftype in ('XLINE', 'RAY'):
            start = d.start
            delta = Vector(d.unit_vector.x, d.unit_vector.y, 0) * INFINITE_LINE_LENGTH
            if dxftype == 'XLINE':
                self.out.draw_line(start - delta / 2, start + delta / 2, properties)
            elif dxftype == 'RAY':
                self.out.draw_line(start, start + delta, properties)
        else:
            raise TypeError(dxftype)
Ejemplo n.º 9
0
 def text2(self, data: bytes):
     bs = ByteStream(data)
     start_point = Vector(bs.read_vertex())
     normal = Vector(bs.read_vertex())
     text_direction = Vector(bs.read_vertex())
     text = bs.read_padded_string()
     ignore_length_of_string, raw = bs.read_struct('<2l')
     height, width_factor, oblique_angle, tracking_percentage = bs.read_struct(
         '<4d')
     is_backwards, is_upside_down, is_vertical, is_underline, is_overline = bs.read_struct(
         '<5L')
     font_filename = bs.read_padded_string()
     big_font_filename = bs.read_padded_string()
     attribs = self._build_dxf_attribs()
     attribs['insert'] = start_point
     attribs['text'] = text
     attribs['height'] = height
     attribs['width'] = width_factor
     attribs['rotation'] = text_direction.angle_deg
     attribs['oblique'] = math.degrees(oblique_angle)
     attribs['style'] = self._get_style(font_filename, big_font_filename)
     attribs['text_generation_flag'] = 2 * is_backwards + 4 * is_upside_down
     attribs['extrusion'] = normal
     return self._factory('TEXT', dxfattribs=attribs)
Ejemplo n.º 10
0
def test_get_start_and_end_vertex():
    ellipse = Ellipse.new(handle='ABBA',
                          owner='0',
                          dxfattribs={
                              'center': (1, 2, 3),
                              'major_axis': (4, 3, 0),
                              'ratio': .7,
                              'start_param': math.pi / 2,
                              'end_param': math.pi,
                              'extrusion': (0, 0, -1),
                          })

    start, end = list(
        ellipse.vertices([
            ellipse.dxf.start_param,
            ellipse.dxf.end_param,
        ]))
    # test values from BricsCAD
    assert start.isclose(Vector(3.1, -0.8, 3), abs_tol=1e-6)
    assert end.isclose(Vector(-3, -1, 3), abs_tol=1e-6)

    # for convenience, but Ellipse.vertices is much more efficient:
    assert ellipse.start_point.isclose(Vector(3.1, -0.8, 3), abs_tol=1e-6)
    assert ellipse.end_point.isclose(Vector(-3, -1, 3), abs_tol=1e-6)
Ejemplo n.º 11
0
    def set_location(self,
                     insert: 'Vertex',
                     rotation: float = None,
                     attachment_point: int = None) -> 'MText':
        """ Set attributes :attr:`dxf.insert`, :attr:`dxf.rotation` and
        :attr:`dxf.attachment_point`, ``None`` for :attr:`dxf.rotation` or
        :attr:`dxf.attachment_point` preserves the existing value.

        """
        self.dxf.insert = Vector(insert)
        if rotation is not None:
            self.set_rotation(rotation)
        if attachment_point is not None:
            self.dxf.attachment_point = attachment_point
        return self  # fluent interface
Ejemplo n.º 12
0
def test_transformation():
    axis = Vector.random()
    angle = 1.5
    ucs = UCS(origin=(3, 4, 5))
    m = Matrix44.axis_rotate(axis, angle)
    expected_origin = m.transform(ucs.origin)
    expected_ux = m.transform(ucs.ux)
    expected_uy = m.transform(ucs.uy)
    expected_uz = m.transform(ucs.uz)
    new = ucs.transform(m)

    assert new.origin.isclose(expected_origin)
    assert new.ux.isclose(expected_ux)
    assert new.uy.isclose(expected_uy)
    assert new.uz.isclose(expected_uz)
Ejemplo n.º 13
0
    def transform(self, m: Matrix44) -> 'Bezier4P':
        """ General transformation interface, returns a new :class:`Bezier4p` curve and it is always a 3D curve.

        Args:
             m: 4x4 transformation matrix (:class:`ezdxf.math.Matrix44`)

        .. versionadded:: 0.14

        """
        if len(self._control_points[0]) == 2:
            defpoints = Vector.generate(self._control_points)
        else:
            defpoints = self._control_points

        defpoints = tuple(m.transform_vertices(defpoints))
        return Bezier4P(defpoints)
Ejemplo n.º 14
0
    def extend(self, vertices: Iterable['Vertex']) -> None:
        """ Append multiple vertices to the reference line.

        It is possible to work with 3D vertices, but all vertices have to be in
        the same plane and the normal vector of this plan is stored as
        extrusion vector in the MLINE entity.

        """
        vertices = Vector.list(vertices)
        if not vertices:
            return
        all_vertices = []
        if len(self):
            all_vertices.extend(self.get_locations())
        all_vertices.extend(vertices)
        self.generate_geometry(all_vertices)
Ejemplo n.º 15
0
def spline_insert_knot():
    doc = ezdxf.new('R2000', setup=True)
    msp = doc.modelspace()

    def add_spline(control_points, color=3, knots=None):
        msp.add_polyline2d(control_points, dxfattribs={'color': color, 'linetype': 'DASHED'})
        msp.add_open_spline(control_points, degree=3, knots=knots, dxfattribs={'color': color})

    control_points = Vector.list([(0, 0), (10, 20), (30, 10), (40, 10), (50, 0), (60, 20), (70, 50), (80, 70)])
    add_spline(control_points, color=3, knots=None)

    bspline = BSpline(control_points, order=4)
    bspline.insert_knot(bspline.max_t/2)
    add_spline(bspline.control_points, color=4, knots=bspline.knots())

    doc.saveas("Spline_R2000_spline_insert_knot.dxf")
Ejemplo n.º 16
0
def translate(
    vertices: Iterable['Vertex'],
    vec: 'Vertex' = (0, 0, 1)) -> Iterable[Vector]:
    """
    Translate `vertices` along `vec`, faster than a Matrix44 transformation.

    Args:
        vertices: iterable of vertices
        vec: translation vector

    Returns: yields transformed vertices

    """
    vec = Vector(vec)
    for p in vertices:
        yield vec + p
Ejemplo n.º 17
0
def diameter_3d(dxfversion='R2000', delta=10):
    doc = ezdxf.new(dxfversion, setup=True)
    msp = doc.modelspace()

    for x, y in multiple_locations(delta=delta):
        ucs = UCS(origin=(x, y, 0)).rotate_local_x(math.radians(45))
        angle = Vector(x, y).angle_deg
        msp.add_circle((0, 0), radius=3).transform(ucs.matrix)
        dim = msp.add_diameter_dim(center=(0, 0),
                                   radius=3,
                                   angle=angle,
                                   dimstyle='EZ_RADIUS')
        dim.render(discard=BRICSCAD, ucs=ucs)

    doc.set_modelspace_vport(height=3 * delta)
    doc.saveas(OUTDIR / f'dim_diameter_{dxfversion}_3d.dxf')
Ejemplo n.º 18
0
    def point(self, t: float) -> Vector:
        """
        Get point at distance `t` as Vector().

        """

        def term(length_power, curvature_power, const):
            return t ** length_power / (const * self.curvature_powers[curvature_power])

        if t not in self._cache:
            y = term(3, 2, 6.) - term(7, 6, 336.) + term(11, 10, 42240.) - \
                term(15, 14, 9676800.) + term(19, 18, 3530096640.)
            x = t - term(5, 4, 40.) + term(9, 8, 3456.) - term(13, 12, 599040.) + \
                term(17, 16, 175472640.)
            self._cache[t] = Vector(x, y)
        return self._cache[t]
Ejemplo n.º 19
0
 def bulge_to(p1: Vector, p2: Vector, 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)
Ejemplo n.º 20
0
def ngon(count: int,
         length: float = None,
         radius: float = None,
         rotation: float = 0.,
         elevation: float = 0.,
         close: bool = False) -> Iterable[Vector]:
    """
    Returns the corner vertices of a `regular polygon <https://en.wikipedia.org/wiki/Regular_polygon>`_.
    The polygon size is determined by the edge `length` or the circum `radius` argument.
    If both are given `length` has higher priority.

    Args:
        count: count of polygon corners >= ``3``
        length: length of polygon side
        radius: circum radius
        rotation: rotation angle in radians
        elevation: z-axis for all vertices
        close: yields first vertex also as last vertex if ``True``.

    Returns:
        vertices as :class:`~ezdxf.math.Vector` objects

    """
    if count < 3:
        raise ValueError('Argument `count` has to be greater than 2.')
    if length is not None:
        if length <= 0.:
            raise ValueError('Argument `length` has to be greater than 0.')
        radius = length / 2. / sin(pi / count)
    elif radius is not None:
        if radius <= 0.:
            raise ValueError('Argument `radius` has to be greater than 0.')
    else:
        raise ValueError('Argument `length` or `radius` required.')

    delta = 2. * pi / count
    angle = rotation
    first = None
    for _ in range(count):
        v = Vector(radius * cos(angle), radius * sin(angle), elevation)
        if first is None:
            first = v
        yield v
        angle += delta

    if close:
        yield first
Ejemplo n.º 21
0
def radius_default_inside_horizontal(dxfversion='R2000', delta=10, dimtmove=0):
    doc = ezdxf.new(dxfversion, setup=True)
    style = doc.dimstyles.get('EZ_RADIUS_INSIDE')
    style.dxf.dimtmove = dimtmove

    msp = doc.modelspace()
    for x, y in multiple_locations(delta=delta):
        angle = Vector(x, y).angle_deg
        msp.add_circle((x, y), radius=3)

        dim = msp.add_radius_dim(center=(x, y), radius=3, angle=angle, dimstyle='EZ_RADIUS_INSIDE',
                                 override={
                                     'dimtih': 1,  # force text inside horizontal
                                 })
        dim.render(discard=BRICSCAD)
    doc.set_modelspace_vport(height=3 * delta)
    doc.saveas(OUTDIR / f'dim_radius_{dxfversion}_default_inside_horizontal_dimtmove_{dimtmove}.dxf')
def test_from_ezdxf_bspline_to_nurbs_python_curve_rational():
    bspline = rational_spline_from_arc(center=Vector(0, 0), radius=2, start_angle=0, end_angle=90)

    # to NURBS-Python
    curve = bspline.to_nurbs_python_curve()
    assert curve.degree == 2
    assert len(curve.ctrlpts) == 3
    assert len(curve.knotvector) == 6  # count + order
    assert curve.rational is True
    assert curve.weights == [1.0, 0.7071067811865476, 1.0]

    # and back to ezdxf
    spline = BSpline.from_nurbs_python_curve(curve)
    assert spline.degree == 2
    assert len(spline.control_points) == 3
    assert len(spline.knots()) == 6  # count + order
    assert spline.weights() == [1.0, 0.7071067811865476, 1.0]
Ejemplo n.º 23
0
    def user_text_free(dimstyle, x=0, y=0, leader=False):
        """
        User defined dimension text placing.

        Args:
            dimstyle: dimstyle to use
            x: start point x
            y: start point y
            leader: use leader line if True

        """
        override = {
            'dimdle': 0.,
            'dimexe': .5,  # length of extension line above dimension line
            'dimexo': .5,  # extension line offset
            'dimtfill': 2,  # custom text fill
            'dimtfillclr': 4  # cyan
        }

        base = (x, y + 2)
        dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + 3, y), dimstyle=dimstyle,
                                 override=override)  # type: DimStyleOverride
        location = Vector(x + 3, y + 3, 0)
        dim.set_location(location, leader=leader)
        dim.render(ucs=ucs, discard=BRICSCAD)
        add_text([f'usr absolute={location}', f'leader={leader}'], insert=Vector(x, y))

        x += 4
        dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + 3, y), dimstyle=dimstyle,
                                 override=override)  # type: DimStyleOverride
        relative = Vector(-1, +1)  # relative to dimline center
        dim.set_location(relative, leader=leader, relative=True)
        dim.render(ucs=ucs, discard=BRICSCAD)
        add_text([f'usr relative={relative}', f'leader={leader}'], insert=Vector(x, y))

        x += 4
        dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + 3, y), dimstyle=dimstyle,
                                 override=override)  # type: DimStyleOverride
        dh = -.7
        dv = 1.5
        dim.shift_text(dh, dv)
        dim.render(ucs=ucs, discard=BRICSCAD)
        add_text([f'shift text=({dh}, {dv})', ], insert=Vector(x, y))

        override['dimtix'] = 1  # force text inside
        x += 4
        dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + .3, y), dimstyle=dimstyle,
                                 override=override)  # type: DimStyleOverride
        dh = 0
        dv = 1
        dim.shift_text(dh, dv)
        dim.render(ucs=ucs, discard=BRICSCAD)
        add_text([f'shift text=({dh}, {dv})', ], insert=Vector(x, y))
Ejemplo n.º 24
0
def test_intersection_ray_ray_3d():
    ray1 = (Vector(0, 0, 0), Vector(1, 0, 0))
    ray2 = (Vector(0, 0, 0), Vector(0, 0, 1))

    # parallel rays return a 0-tuple
    result = intersection_ray_ray_3d(ray1, ray1)
    assert len(result) == 0
    assert bool(result) is False

    # intersecting rays return a 1-tuple
    result = intersection_ray_ray_3d(ray1, ray2)
    assert len(result) == 1
    assert bool(result) is True
    assert result == (Vector(0, 0, 0), )

    # not intersecting and not parallel rays return a 2-tuple
    line3 = (Vector(0, 0, 1), Vector(0, 1, 1))
    result = intersection_ray_ray_3d(ray1, line3)
    assert len(result) == 2
    assert bool(result) is True
    # returns points of closest approach on each ray
    assert Vector(0, 0, 1) in result
    assert Vector(0, 0, 0) in result
def test_basis_vector_N_ip():
    degree = 3
    fit_points = Vector.list(POINTS2)  # data points D
    n = len(fit_points) - 1
    t_vector = list(uniform_t_vector(fit_points))
    knots = list(control_frame_knots(n, degree, t_vector))
    should_count = len(fit_points) - 2  # target control point count
    h = should_count - 1
    spline = Basis(knots, order=degree + 1, count=len(fit_points))
    matrix_N = [spline.basis(t) for t in t_vector]

    for k in range(1, n):
        basis_vector = bspline_basis_vector(u=t_vector[k],
                                            count=len(fit_points),
                                            degree=degree,
                                            knots=knots)
        for i in range(1, h):
            assert isclose(matrix_N[k][i], basis_vector[i])
Ejemplo n.º 26
0
def ellipse(major_axis=(1, 0),
            ratio: float = 0.5,
            start: float = 0,
            end: float = math.tau,
            count: int = 8):
    major_axis = Vector(major_axis).replace(z=0)
    ellipse_ = Ellipse.new(dxfattribs={
        'center': (0, 0, 0),
        'major_axis': major_axis,
        'ratio': min(max(ratio, 1e-6), 1),
        'start_param': start,
        'end_param': end
    },
                           doc=doc)
    control_vertices = list(ellipse_.vertices(ellipse_.params(count)))
    axis_vertices = list(
        ellipse_.vertices([0, math.pi / 2, math.pi, math.pi * 1.5]))
    return ellipse_, control_vertices, axis_vertices
Ejemplo n.º 27
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
Ejemplo n.º 28
0
Archivo: mesh.py Proyecto: hh-wu/ezdxf
    def add_vertices(self, vertices: Iterable['Vertex']) -> Sequence[int]:
        """
        Add new vertices to the mesh, each vertex is a ``(x, y, z)`` tuple or a :class:`~ezdxf.math.Vector` object,
        returns the indices of the `vertices` added to the :attr:`vertices` list.

        e.g. adding 4 vertices to an empty mesh, returns the indices ``(0, 1, 2, 3)``, adding additional 4 vertices
        returns the indices ``(4, 5, 6, 7)``.

        Args:
            vertices: list of vertices, vertex as ``(x, y, z)`` tuple or :class:`~ezdxf.math.Vector` objects

        Returns:
            tuple: indices of the `vertices` added to the :attr:`vertices` list

        """
        start_index = len(self.vertices)
        self.vertices.extend(Vector.generate(vertices))
        return tuple(range(start_index, len(self.vertices)))
Ejemplo n.º 29
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)
Ejemplo n.º 30
0
    def add_measurement_text(self, dim_text: str, pos: Vec2,
                             rotation: float) -> None:
        """
        Add measurement text to dimension BLOCK.

        Args:
            dim_text: dimension text
            pos: text location
            rotation: text rotation in degrees

        """
        attribs = {
            'color': self.text_color,
        }
        self.add_text(dim_text,
                      pos=Vector(pos),
                      rotation=rotation,
                      dxfattribs=attribs)