Esempio n. 1
0
 def render(self, text, origin=None, skew=0, line_spacing=1.0, pitch=1.0,
         align=None):
     result = ContourModel()
     if origin is None:
         origin = Point(0, 0, 0)
     if align is None:
         align = TEXT_ALIGN_LEFT
     base = origin
     letter_spacing = self.letterspacing * pitch
     word_spacing = self.wordspacing * pitch
     line_factor = self.default_linespacing * self.linespacingfactor \
             * line_spacing
     for line in text.splitlines():
         current_line = ContourModel()
         line_height = self.default_height
         for character in line:
             if character == " ":
                 base = base.add(Point(word_spacing, 0, 0))
             elif character in self.letters.keys():
                 charset_letter = self.letters[character]
                 new_model = ContourModel()
                 for line in charset_letter.get_positioned_lines(base,
                         skew=skew):
                     new_model.append(line, allow_reverse=True)
                 for polygon in new_model.get_polygons():
                     # add polygons instead of lines -> more efficient
                     current_line.append(polygon)
                 # update line height
                 line_height = max(line_height, charset_letter.maxy())
                 # shift the base position
                 base = base.add(Point(
                         charset_letter.maxx() + letter_spacing, 0, 0))
             else:
                 # unknown character - add a small whitespace
                 base = base.add(Point(letter_spacing, 0, 0))
         # go to the next line
         base = Point(origin.x, base.y - line_height * line_factor, origin.z)
         if not current_line.maxx is None:
             if align == TEXT_ALIGN_CENTER:
                 current_line.shift(-current_line.maxx / 2, 0, 0)
             elif align == TEXT_ALIGN_RIGHT:
                 current_line.shift(-current_line.maxx, 0, 0)
             else:
                 # left align
                 if current_line.minx != 0:
                     current_line.shift(-current_line.minx, 0, 0)
         for polygon in current_line.get_polygons():
             result.append(polygon)
     # the text should be just above the x axis
     if result.miny:
         # don't shift, if result.miny is None (e.g.: no content) or zero
         result.shift(0, -result.miny, 0)
     return result
Esempio n. 2
0
    def union(self, other):
        """ This "union" of two polygons only works for polygons without
        shared edges. TODO: fix the issues of shared edges!
        """
        # don't import earlier to avoid circular imports
        from pycam.Geometry.Model import ContourModel
        # check if one of the polygons is completely inside of the other
        if self.is_polygon_inside(other):
            return [self]
        if other.is_polygon_inside(self):
            return [other]
        # check if there is any overlap at all
        if not self.is_overlap(other):
            # no changes
            return [self, other]
        contour = ContourModel(self.plane)

        def get_outside_lines(poly1, poly2):
            result = []
            for line in poly1.get_lines():
                collisions = []
                for o_line in poly2.get_lines():
                    cp, dist = o_line.get_intersection(line)
                    if (cp is not None) and (0 < dist < 1):
                        collisions.append((cp, dist))
                # sort the collisions according to the distance
                collisions.append((line.p1, 0))
                collisions.append((line.p2, 1))
                collisions.sort(key=lambda collision: collision[1])
                for index in range(len(collisions) - 1):
                    p1 = collisions[index][0]
                    p2 = collisions[index + 1][0]
                    if pdist(p1, p2) < epsilon:
                        # ignore zero-length lines
                        continue
                    # Use the middle between p1 and p2 to check the
                    # inner/outer state.
                    p_middle = pdiv(padd(p1, p2), 2)
                    p_inside = (poly2.is_point_inside(p_middle)
                                and not poly2.is_point_on_outline(p_middle))
                    if not p_inside:
                        result.append(Line(p1, p2))
            return result

        outside_lines = []
        outside_lines.extend(get_outside_lines(self, other))
        outside_lines.extend(get_outside_lines(other, self))
        for line in outside_lines:
            contour.append(line)
        # fix potential overlapping at the beginning and end of each polygon
        result = []
        for poly in contour.get_polygons():
            if not poly.is_closed:
                lines = poly.get_lines()
                line1 = lines[-1]
                line2 = lines[0]
                if (line1.dir == line2.dir) \
                        and (line1.is_point_inside(line2.p1)):
                    # remove the last point and define the polygon as closed
                    poly._points.pop(-1)
                    poly.is_closed = True
            result.append(poly)
        return result
Esempio n. 3
0
 def render(self,
            text,
            origin=None,
            skew=0,
            line_spacing=1.0,
            pitch=1.0,
            align=None):
     result = ContourModel()
     if origin is None:
         origin = Point(0, 0, 0)
     if align is None:
         align = TEXT_ALIGN_LEFT
     base = origin
     letter_spacing = self.letterspacing * pitch
     word_spacing = self.wordspacing * pitch
     line_factor = self.default_linespacing * self.linespacingfactor \
             * line_spacing
     for line in text.splitlines():
         current_line = ContourModel()
         line_height = self.default_height
         for character in line:
             if character == " ":
                 base = base.add(Point(word_spacing, 0, 0))
             elif character in self.letters.keys():
                 charset_letter = self.letters[character]
                 new_model = ContourModel()
                 for line in charset_letter.get_positioned_lines(base,
                                                                 skew=skew):
                     new_model.append(line, allow_reverse=True)
                 for polygon in new_model.get_polygons():
                     # add polygons instead of lines -> more efficient
                     current_line.append(polygon)
                 # update line height
                 line_height = max(line_height, charset_letter.maxy())
                 # shift the base position
                 base = base.add(
                     Point(charset_letter.maxx() + letter_spacing, 0, 0))
             else:
                 # unknown character - add a small whitespace
                 base = base.add(Point(letter_spacing, 0, 0))
         # go to the next line
         base = Point(origin.x, base.y - line_height * line_factor,
                      origin.z)
         if not current_line.maxx is None:
             if align == TEXT_ALIGN_CENTER:
                 current_line.shift(-current_line.maxx / 2, 0, 0)
             elif align == TEXT_ALIGN_RIGHT:
                 current_line.shift(-current_line.maxx, 0, 0)
             else:
                 # left align
                 if current_line.minx != 0:
                     current_line.shift(-current_line.minx, 0, 0)
         for polygon in current_line.get_polygons():
             result.append(polygon)
     # the text should be just above the x axis
     if result.miny:
         # don't shift, if result.miny is None (e.g.: no content) or zero
         result.shift(0, -result.miny, 0)
     return result