Class: Laser::Cutter::Notching::PathGenerator

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/laser-cutter/notching/path_generator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(edge) ⇒ PathGenerator

This class generates lines that zigzag between two lines: the outside line, and the inside line of a single edge. Edge class encapsulates both of them with additional properties.



47
48
49
# File 'lib/laser-cutter/notching/path_generator.rb', line 47

def initialize(edge)
  @edge = edge
end

Instance Attribute Details

#edgeObject

Returns the value of attribute edge.



42
43
44
# File 'lib/laser-cutter/notching/path_generator.rb', line 42

def edge
  @edge
end

Instance Method Details

#add_boxes_when_in(dim_index, direction, k) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/laser-cutter/notching/path_generator.rb', line 118

def add_boxes_when_in(dim_index, direction, k)
  v1 = k * direction * shift_vector(1, dim_index)
  v2 = k * direction * shift_vector(2, dim_index)
  p1 = edge.inside.p1.plus(v1)
  coords = []
  coords[d_index_along] = edge.inside.p1[d_index_along]
  coords[d_index_across] = edge.outside.p1[d_index_across]
  p2 = Geometry::Point[*coords]
  r1 = Geometry::Rect[p1, p2]

  p1 = edge.inside.p2.plus(v2)
  coords = []
  coords[d_index_along] = edge.inside.p2[d_index_along]
  coords[d_index_across] = edge.outside.p2[d_index_across]
  p2 = Geometry::Point[*coords]
  r2 = Geometry::Rect[p1, p2]
  lines = [r1, r2].map(&:sides).flatten
  lines << Geometry::Line[edge.inside.p1.plus(v1), edge.inside.p1.clone]
  lines << Geometry::Line[edge.inside.p2.plus(v2), edge.inside.p2.clone]
  lines
end

#add_corners_when_out(dim_index, direction, k) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/laser-cutter/notching/path_generator.rb', line 140

def add_corners_when_out(dim_index, direction, k)
  v1 = direction * k * shift_vector(1, dim_index)
  v2 = direction * k * shift_vector(2, dim_index)
  p1 = edge.inside.p1.plus(v1)
  coords = []
  coords[d_index_along] = edge.outside.p1[d_index_along]
  coords[d_index_across] = edge.inside.p1[d_index_across]
  p2 = Geometry::Point[*coords]
  r1 = Geometry::Rect[p1, p2]

  p1 = edge.inside.p2.plus(v2)
  coords = []
  coords[d_index_along] = edge.outside.p2[d_index_along]
  coords[d_index_across] = edge.inside.p2[d_index_across]
  p2 = Geometry::Point[*coords]
  r2 = Geometry::Rect[p1, p2]
  lines = [r1, r2].map(&:sides).flatten
  lines << Geometry::Line[edge.inside.p1.plus(v1), edge.inside.p1.clone]
  lines << Geometry::Line[edge.inside.p2.plus(v2), edge.inside.p2.clone]
  lines
end

#adjust_for_kerf(vertices, direction) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/laser-cutter/notching/path_generator.rb', line 79

def adjust_for_kerf(vertices, direction)
  if kerf?
    point = vertices.pop
    point = corners ? point.plus(2 * direction * shift_vector(1)) : point
    vertices << point
  end
end

#corner_box_sidesObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/laser-cutter/notching/path_generator.rb', line 87

def corner_box_sides
  boxes = []
  extra_lines = []
  sides = []

  # These two boxes occupy the corners of the 3D box. They do not match
  # in width to our notches because they are usually merged with them.
  # It's just an aesthetic choice I guess.
  boxes << Geometry::Rect[edge.inside.p1.clone, edge.outside.p1.clone]
  boxes << Geometry::Rect[edge.inside.p2.clone, edge.outside.p2.clone]

  if kerf?
    if adjust_corners
      if first_notch_out?
        k = 2
        direction = -1
        dim_index = 1
        extra_lines << add_corners_when_out(dim_index, direction, k)
      else
        k = -2
        direction = 1
        dim_index = 0
        extra_lines << add_boxes_when_in(dim_index, direction, k)
      end
    end
  end
  sides = boxes.flatten.map(&:relocate!).map(&:sides)
  sides << extra_lines if !extra_lines.empty?
  sides.flatten
end

#d_index_acrossObject



179
180
181
# File 'lib/laser-cutter/notching/path_generator.rb', line 179

def d_index_across
  (d_index_along + 1) % 2
end

#d_index_alongObject

0 = X, 1 = Y



175
176
177
# File 'lib/laser-cutter/notching/path_generator.rb', line 175

def d_index_along
  (edge.inside.p1.x == edge.inside.p2.x) ? 1 : 0
end

#direction_acrossObject



187
188
189
# File 'lib/laser-cutter/notching/path_generator.rb', line 187

def direction_across
  (edge.inside.p1.coords.[](d_index_across) < edge.outside.p1.coords.[](d_index_across)) ? 1 : -1
end

#direction_alongObject



183
184
185
# File 'lib/laser-cutter/notching/path_generator.rb', line 183

def direction_along
  (edge.inside.p1.coords.[](d_index_along) < edge.inside.p2.coords.[](d_index_along)) ? 1 : -1
end

#generateObject

Calculates a notched path that flows between the outer edge of the box (outside_line) and inner (inside_line). Relative location of these lines also defines the direction and orientation of the box, and hence the notches.

We always want to create a symmetric path that has a notch in the middle (for center_out = true) or dip in the middle (center_out = false)



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/laser-cutter/notching/path_generator.rb', line 57

def generate
  shifts = define_shifts
  vertices = []
  lines = []

  if corners
    lines << corner_box_sides
  end

  point = starting_point

  vertices << point
  adjust_for_kerf(vertices,-1) if adjust_corners && !first_notch_out?
  shifts.each do |shift|
    point = shift.next_point_after point
    vertices << point
  end
  adjust_for_kerf(vertices, 1) if adjust_corners && !first_notch_out?
  lines << create_lines(vertices)
  lines.flatten
end

#shift_vector(index, dim_shift = 0) ⇒ Object



162
163
164
165
166
167
# File 'lib/laser-cutter/notching/path_generator.rb', line 162

def shift_vector(index, dim_shift = 0)
  shift = []
  shift[(d_index_across + dim_shift) % 2] = 0
  shift[(d_index_along + dim_shift) % 2] = kerf / 2.0 * edge.send("v#{index}".to_sym).[]((d_index_along + dim_shift) % 2)
  Vector.[](*shift)
end

#starting_pointObject



170
171
172
# File 'lib/laser-cutter/notching/path_generator.rb', line 170

def starting_point
  edge.inside.p1.clone # start
end