Пример #1
0
def make_hatches_from_str(s: str,
                          font: fonts.FontFace,
                          size: float = 1.0,
                          align: str = 'LEFT',
                          length: float = 0,
                          segments: int = 4,
                          dxfattribs: Dict = None,
                          m: Matrix44 = None) -> List[Hatch]:
    """ Convert a single line string `s` into a list of virtual
    :class:`~ezdxf.entities.Hatch` entities.
    The text `size` is the height of the uppercase letter "X" (cap height).
    The paths are aligned about the insertion point at (0, 0).
    The HATCH entities are aligned to this insertion point. BASELINE means the
    bottom of the letter "X".

    Args:
         s: text to convert
         font: font face definition
         size: text size (cap height) in drawing units
         align: alignment as string, default is "LEFT"
         length: target length for the "ALIGNED" and "FIT" alignments
         segments: minimal segment count per Bézier curve
         dxfattribs: additional DXF attributes
         m: transformation :class:`~ezdxf.math.Matrix44`

    """
    font_properties, font_measurements = _get_font_data(font)
    # scale cap_height for 1 drawing unit!
    scaled_size = size / font_measurements.cap_height
    scaled_fm = font_measurements.scale_from_baseline(scaled_size)
    paths = _str_to_paths(s, font_properties, scaled_size)

    # HATCH is an OCS entity, transforming just the polyline paths
    # is not correct! The Hatch has to be created in the xy-plane!
    hatches = []
    dxfattribs = dxfattribs or dict()
    dxfattribs.setdefault('solid_fill', 1)
    dxfattribs.setdefault('pattern_name', 'SOLID')
    dxfattribs.setdefault('color', 7)

    for contour, holes in group_contour_and_holes(paths):
        hatch = Hatch.new(dxfattribs=dxfattribs)
        # Vec2 removes the z-axis, which would be interpreted as bulge value!
        hatch.paths.add_polyline_path(
            Vec2.generate(contour.flattening(1, segments=segments)), flags=1)
        for hole in holes:
            hatch.paths.add_polyline_path(
                Vec2.generate(hole.flattening(1, segments=segments)), flags=0)
        hatches.append(hatch)

    halign, valign = const.TEXT_ALIGN_FLAGS[align.upper()]
    bbox = path.bbox(paths, precise=False)
    matrix = get_alignment_transformation(scaled_fm, bbox, halign, valign)
    if m is not None:
        matrix *= m

    # Transform HATCH entities as a unit:
    return [hatch.transform(matrix) for hatch in hatches]
Пример #2
0
def make_paths_from_str(s: str,
                        font: fonts.FontFace,
                        size: float = 1.0,
                        align: str = 'LEFT',
                        length: float = 0,
                        m: Matrix44 = None) -> List[Path]:
    """ Convert a single line string `s` into a list of
    :class:`~ezdxf.render.path.Path` objects. All paths are returned in a single
    list. The text `size` is the height of the uppercase letter "X" (cap height).
    The paths are aligned about the insertion point at (0, 0).
    BASELINE means the bottom of the letter "X".

    Args:
         s: text to convert
         font: font face definition
         size: text size (cap height) in drawing units
         align: alignment as string, default is "LEFT"
         length: target length for the "ALIGNED" and "FIT" alignments
         m: transformation :class:`~ezdxf.math.Matrix44`

    """
    font_properties, font_measurements = _get_font_data(font)
    scaled_size = size / font_measurements.cap_height
    scaled_fm = font_measurements.scale_from_baseline(scaled_size)
    paths = _str_to_paths(s, font_properties, scaled_size)
    bbox = path.bbox(paths, precise=False)
    halign, valign = const.TEXT_ALIGN_FLAGS[align.upper()]
    matrix = get_alignment_transformation(scaled_fm, bbox, halign, valign)

    stretch_x = 1.0
    stretch_y = 1.0
    if align == 'ALIGNED':
        stretch_x = length / bbox.size.x
        stretch_y = stretch_x
    elif align == 'FIT':
        stretch_x = length / bbox.size.x
    if stretch_x != 1.0:
        matrix *= Matrix44.scale(stretch_x, stretch_y, 1.0)
    if m is not None:
        matrix *= m
    return list(path.transform_paths(paths, matrix))
Пример #3
0
 def test_non_uniform_stretch_paths(self, spath):
     result = fit_paths_into_box([spath], (8, 7, 6), uniform=False)
     box = bbox(result)
     assert box.size == (8, 7, 6)
Пример #4
0
 def test_project_into_xz(self, spath):
     result = fit_paths_into_box([spath], (6, 0, 6))
     box = bbox(result)
     assert box.size == (2, 0, 6), "y-axis should be ignored"
Пример #5
0
 def test_project_into_xy(self, spath):
     result = fit_paths_into_box([spath], (6, 6, 0))
     box = bbox(result)
     # Note: z-axis is also ignored by extent detection:
     # scaling factor = 3x
     assert box.size == (3, 6, 0), "z-axis should be ignored"
Пример #6
0
 def test_uniform_shrink_paths(self, spath):
     result = fit_paths_into_box([spath], (1.5, 1.5, 1.5))
     box = bbox(result)
     assert box.size == (0.5, 1, 1.5)
Пример #7
0
 def test_uniform_stretch_paths_limited_by_x(self, spath):
     result = fit_paths_into_box([spath], (1.2, 6, 6))
     box = bbox(result)
     # stretch factor: 1.2
     assert box.size == (1.2, 2.4, 3.6)
Пример #8
0
 def test_uniform_stretch_paths_limited_by_y(self, spath):
     result = fit_paths_into_box([spath], (6, 3, 6))
     box = bbox(result)
     # stretch factor: 1.5
     assert box.size == (1.5, 3, 4.5)
Пример #9
0
 def test_project_into_xz(self, spath):
     result = path.fit_paths_into_box([spath], (6, 0, 6), uniform=False)
     box = path.bbox(result)
     assert box.size == (6, 0, 6), "y-axis should be ignored"
Пример #10
0
 def test_precise_box(self, quadratic):
     result = bbox([quadratic], precise=True)
     assert result.extmax.y == pytest.approx(0.5)  # parabola
Пример #11
0
 def test_not_precise_box(self, quadratic):
     result = bbox([quadratic], precise=False)
     assert result.extmax.y == pytest.approx(1)  # control point
Пример #12
0
 def test_two_path(self):
     p1 = Path()
     p1.line_to((1, 2, 3))
     p2 = Path()
     p2.line_to((-3, -2, -1))
     assert bbox([p1, p2]).size == (4, 4, 4)
Пример #13
0
 def test_one_path(self):
     p = Path()
     p.line_to((1, 2, 3))
     assert bbox([p]).size == (1, 2, 3)
Пример #14
0
 def test_empty_paths(self):
     result = bbox([])
     assert result.has_data is False
Пример #15
0
 def test_non_uniform_shrink_paths(self, spath):
     result = fit_paths_into_box([spath], (1.5, 1.5, 1.5), uniform=False)
     box = bbox(result)
     assert box.size == (1.5, 1.5, 1.5)
Пример #16
0
 def test_uniform_stretch_paths_limited_by_z(self, spath):
     result = fit_paths_into_box([spath], (6, 6, 6))
     box = bbox(result)
     assert box.size == (2, 4, 6)
Пример #17
0
 def test_project_into_yz(self, spath):
     result = fit_paths_into_box([spath], (0, 6, 6), uniform=False)
     box = bbox(result)
     assert box.size == (0, 6, 6), "x-axis should be ignored"
Пример #18
0
 def test_project_into_yz(self, spath):
     result = path.fit_paths_into_box([spath], (0, 6, 6))
     box = path.bbox(result)
     assert box.size == (0, 4, 6), "x-axis should be ignored"