예제 #1
0
    def generate_path_tree(self):
        """ Specialized path generation for Waterbomb tesselation pattern
        """
        unit_factor = self.calc_unit_factor()
        length = self.options.length * unit_factor
        vertex_radius = self.options.vertex_radius * unit_factor
        cols = self.options.columns
        lines = self.options.lines
        phase_shift = self.options.phase_shift
        pattern_first_line = self.options.pattern_first_line
        pattern_last_line = self.options.pattern_last_line

        # create vertices
        vertex_line_types = [[
            Path(((i / 2.) * length, 0), style='p', radius=vertex_radius)
            for i in range(2 * cols + 1)
        ],
                             [
                                 Path((i * length, 0),
                                      style='p',
                                      radius=vertex_radius)
                                 for i in range(cols + 1)
                             ],
                             [
                                 Path(((i + 0.5) * length, 0),
                                      style='p',
                                      radius=vertex_radius)
                                 for i in range(cols)
                             ]]

        vertices = []
        for i in range(2 * lines + 1):
            if i % 2 == 0 or (pattern_first_line == 'magic_ball'
                              and i == 1) or (pattern_last_line == 'magic_ball'
                                              and i == 2 * lines - 1):
                type = 0
            elif (i / 2 + phase_shift) % 2 == 0:
                type = 1
            else:
                type = 2
            vertices = vertices + Path.list_add(vertex_line_types[type],
                                                (0, 0.5 * i * length))

        # create a list for the horizontal creases and another for the vertical creases
        # alternate strokes to minimize laser cutter path
        corr_fist_line = length / 2 if pattern_first_line == 'magic_ball' else 0
        corr_last_line = length / 2 if pattern_last_line == 'magic_ball' else 0
        grid = [
            Path.generate_hgrid([0, length * cols], [0, length * lines], lines,
                                'm'),
            Path.generate_vgrid(
                [0, length * cols],
                [corr_fist_line, length * lines - corr_last_line], 2 * cols,
                'm')
        ]

        vgrid_a = Path.generate_vgrid([0, length * cols], [0, length / 2],
                                      2 * cols, 'v')
        vgrid_b = Path.list_add(vgrid_a, (0, (lines - 0.5) * length))
        if pattern_first_line == 'magic_ball' and pattern_last_line == 'magic_ball':
            grid[1] = [[vgrid_a[i], grid[1][i], vgrid_b[i]] if i %
                       2 == 0 else [vgrid_b[i], grid[1][i], vgrid_a[i]]
                       for i in range(len(grid[1]))]
        elif pattern_first_line == 'magic_ball':
            grid[1] = [[vgrid_a[i], grid[1][i]] if i %
                       2 == 0 else [grid[1][i], vgrid_a[i]]
                       for i in range(len(grid[1]))]
        elif pattern_last_line == 'magic_ball':
            grid[1] = [[grid[1][i], vgrid_b[i]] if i %
                       2 == 0 else [vgrid_b[i], grid[1][i]]
                       for i in range(len(grid[1]))]

        # create generic valley Path lines, one pointing up and other pointing down
        valley_types = [
            Path([(i * length / 2, (1 - i % 2) * length / 2)
                  for i in range(2 * cols + 1)], 'v'),
            Path([(i * length / 2, (i % 2) * length / 2)
                  for i in range(2 * cols + 1)], 'v')
        ]

        # define which lines must be of which type, according to parity and options
        senses = np.array(
            [bool((i % 2 + i) / 2 % 2) for i in range(2 * lines)])
        senses = 1 * senses  # converts bool array to 0's and 1's
        if phase_shift:
            senses = np.invert(senses)
        if pattern_first_line == "magic_ball":
            senses[0] = ~senses[0]
        if pattern_last_line == "magic_ball":
            senses[-1] = ~senses[-1]
        valleys = [
            valley_types[senses[i]] + (0, i * length / 2)
            for i in range(2 * lines)
        ]

        # convert first and last lines to mountains if magic_ball
        if pattern_first_line == "magic_ball":
            valleys[0].style = 'm'
        if pattern_last_line == "magic_ball":
            valleys[-1].style = 'm'

        # invert every two lines to minimize laser cutter movements
        for i in range(1, 2 * lines, 2):
            valleys[i].invert()

        self.edge_points = [
            (0 * length * cols, 0 * length * lines),  # top left
            (1 * length * cols, 0 * length * lines),  # top right
            (1 * length * cols, 1 * length * lines),  # bottom right
            (0 * length * cols, 1 * length * lines)
        ]  # bottom left

        self.path_tree = [grid, valleys, vertices]
예제 #2
0
    def generate_path_tree(self):
        """ Specialized path generation for Waterbomb tesselation pattern
        """
        unit_factor = self.calc_unit_factor()
        vertex_radius = self.options.vertex_radius * unit_factor
        lines = self.options.lines
        sides = self.options.sides
        radius = self.options.radius * unit_factor
        angle_ratio = self.options.angle_ratio
        mirror_cells = self.options.mirror_cells

        theta = (pi / 2.) * (1 - 2. / sides)
        l = 2. * radius * cos(theta * (1. - angle_ratio))
        a = 2. * radius * sin(pi / sides)
        # b = sqrt(a*a + l*l - 2*a*l*cos(angle_ratio*theta))
        # phi = abs(acos((l*l + b*b - a*a)/(2*l*b)))
        # gamma = pi/2 - angle_ratio*theta - phi
        # dy = b*cos(gamma)
        # dx = b*sin(gamma)
        dy = l * sin(theta * angle_ratio)
        dx = l * cos(theta * angle_ratio) - a

        add_attachment = self.options.add_attachment
        attachment_percentage = self.options.attachment_percentage / 100.
        attachment_height = a * (attachment_percentage - 1) * tan(
            angle_ratio * theta)

        vertices = []
        for i in range(sides + 1):
            for j in range(lines + 1):
                if mirror_cells:
                    vertices.append(
                        Path((dx * ((lines - j) % 2) + a * i, dy * j),
                             style='p',
                             radius=vertex_radius))
                else:
                    vertices.append(
                        Path((dx * (lines - j) + a * i, dy * j),
                             style='p',
                             radius=vertex_radius))

        # create a horizontal grid, then offset each line according to angle
        grid_h = Path.generate_hgrid([0, a * sides], [0, dy * lines], lines,
                                     'm')

        if not mirror_cells:
            # shift every mountain line of the grid to the right by increasing amounts
            grid_h = Path.list_add(grid_h, [(i * dx, 0)
                                            for i in range(lines - 1, 0, -1)])
        else:
            # shift every OTHER mountain line of the grid a bit to the right
            grid_h = Path.list_add(grid_h, [((i % 2) * dx, 0)
                                            for i in range(lines - 1, 0, -1)])
            if add_attachment:
                for i in range(lines % 2, lines - 1, 2):
                    # hacky solution, changes length of every other mountain line
                    grid_h[i].points[1 -
                                     i % 2] = (grid_h[i].points[1 - i % 2][0] +
                                               a * attachment_percentage,
                                               grid_h[i].points[1 - i % 2][1])

        # create MV zigzag for Kresling pattern
        zigzag = Kresling.generate_kresling_zigzag(sides, radius, angle_ratio,
                                                   add_attachment)
        zigzags = []

        # duplicate zigzag pattern for desired number of cells
        if not mirror_cells:
            for i in range(lines):
                zigzags.append(
                    Path.list_add(zigzag, (i * dx, (lines - i) * dy)))
        else:
            zigzag_mirror = Path.list_reflect(zigzag, (0, lines * dy / 2),
                                              (dx, lines * dy / 2))
            for i in range(lines):
                if i % 2 == 1:
                    zigzags.append(
                        Path.list_add(zigzag_mirror,
                                      (0, -(lines - i +
                                            (lines - 1) % 2) * dy)))
                else:
                    zigzags.append(Path.list_add(zigzag,
                                                 (0, (lines - i) * dy)))

        # create edge strokes
        if not mirror_cells:
            self.edge_points = [
                (a * sides, dy * lines),  # bottom right
                (0, dy * lines),  # bottom left
                (dx * lines, 0),  # top left
                (dx * lines + a * sides, 0)
            ]  # top right

            if add_attachment:
                for i in range(lines):
                    x = dx * (lines - i) + a * (sides + attachment_percentage)
                    self.edge_points.append((x, dy * i))
                    self.edge_points.append((x, dy * i - attachment_height))
                    if i != lines - 1:
                        self.edge_points.append(
                            (x - dx - a * attachment_percentage, dy * (i + 1)))
                        pass

        else:
            self.edge_points = [(a * sides + (lines % 2) * dx, 0)]

            for i in range(lines + 1):
                self.edge_points.append([((lines + i) % 2) * dx, dy * i])

            self.edge_points.append(
                [a * sides + ((lines + i) % 2) * dx, lines * dy])

            if add_attachment:
                for i in range(lines + 1):

                    if not i % 2 == 0:
                        self.edge_points.append([
                            a * sides + (i % 2) *
                            (dx + a * attachment_percentage),
                            dy * (lines - i) - (i % 2) * attachment_height
                        ])
                        self.edge_points.append([
                            a * sides + (i % 2) *
                            (dx + a * attachment_percentage), dy * (lines - i)
                        ])
                        if (i != lines):
                            self.edge_points.append([
                                a * sides + (i % 2) *
                                (dx + a * attachment_percentage),
                                dy * (lines - i) + (i % 2) * attachment_height
                            ])
                    else:
                        self.edge_points.append([
                            a * sides + (i % 2) *
                            (dx + a * attachment_percentage), dy * (lines - i)
                        ])
            else:
                for i in range(lines + 1):
                    self.edge_points.append(
                        [a * sides + (i % 2) * dx, dy * (lines - i)])

        self.path_tree = [grid_h, zigzags, vertices]