added code for generation of jigsaw puzzle piece on svg line

master
Simon Pirkelmann 2019-09-13 17:17:05 +02:00
parent d59117c101
commit 441d733935
1 changed files with 74 additions and 23 deletions

View File

@ -5,7 +5,7 @@ import operator
# scale in inkscape
# 1 unit = 0.283 mm
scale = 1000.0/282.222
svg_scale = 1000.0/282.222
def svg_circle(id, name, c, r):
# create circle object in svg notation
@ -48,12 +48,12 @@ def svg_puzzle(p, size, angle):
p4 = p - size * v1
# convert to svg units
p1 *= scale
p2 *= scale
p3 *= scale
p4 *= scale
p1 *= svg_scale
p2 *= svg_scale
p3 *= svg_scale
p4 *= svg_scale
radius_scaled = 1.25 * size * scale
radius_scaled = 1.25 * size * svg_scale
text = [' <path \n '
' id="path666" \n '
@ -63,6 +63,58 @@ def svg_puzzle(p, size, angle):
return text
def svg_line_puzzle(start, end, puzzle_scale=1.0, linewidth=0.50):
v = end - start
dist = np.linalg.norm(v)
size = dist / 10.0 * puzzle_scale
v = v / dist
angle = math.atan2(v[1], v[0])
p = np.mean([start, end], axis=0)
# compute points
"""
v1 and v2 are orthogonal vectors
construction of points (starting at p):
p3 <------ -2 v1 ------ p2
^
|
v2
|
|
p4 <-- -v1 -- p -- v1 --> p1
then between points p2 and p3 with draw an arc
"""
v1 = np.array([np.cos(angle), np.sin(angle)])
v2 = np.array([v1[1], -v1[0]])
p1 = p - size * v1
p2 = p1 + size * v2
p3 = p2 + 2.0 * size * v1
p4 = p + size * v1
# convert to svg units
p1 *= svg_scale
p2 *= svg_scale
p3 *= svg_scale
p4 *= svg_scale
start *= svg_scale
end *= svg_scale
radius_scaled = 1.25 * size * svg_scale
text = [' <path \n '
' id="path666" \n '
' style="fill:none;stroke:#000000;stroke-width:{}mm" \n'
' d="M {} {} L {} {} L {} {} A {} {} 0 1 1 {} {} L {} {} L {} {}"'
' />\n'.format(linewidth, start[0], start[1], p1[0], p1[1], p2[0], p2[1], radius_scaled, radius_scaled,
p3[0], p3[1], p4[0], p4[1], end[0], end[1])]
return text
def svg_half_circle(id, name, c, r, angle, orientation_flag=1):
# draws half a circle centered at c with radius r
# angle specifies how the half circle should be rotated
@ -74,13 +126,13 @@ def svg_half_circle(id, name, c, r, angle, orientation_flag=1):
# compute starting point
v = np.array([np.cos(angle), np.sin(angle)])
begin = c + r * v # in millimeters
begin *= scale # in svg units
begin *= svg_scale # in svg units
# compute end point
end = c - r * v # in millimeters
end *= scale # in svg units
end *= svg_scale # in svg units
radius_scaled = r * scale # radius in svg units
radius_scaled = r * svg_scale # radius in svg units
text = [' <path \n '
' id="path666" \n '
@ -92,9 +144,9 @@ def svg_half_circle(id, name, c, r, angle, orientation_flag=1):
return text
def svg_arc(p1, p2, r, large_arc, sweep):
begin = p1 * scale
end = p2 * scale
radius_scaled = r * scale
begin = p1 * svg_scale
end = p2 * svg_scale
radius_scaled = r * svg_scale
text = [' <path \n '
' id="path666" \n '
' style="fill:none;stroke:#ff0000;stroke-width:0.60000002" \n'
@ -613,14 +665,16 @@ class PlateLayout:
vunit = np.array([np.cos(a), np.sin(a)])
p1 = vunit * self.target_center_hole_radius
p2 = vunit * r1
text = svg_line(p1, p2, 0.1)
#text = svg_line(p1, p2, 0.1)
text = svg_line_puzzle(p1, p2)
f_lines = f_lines + text
r2 = np.linalg.norm(np.array(self.tube_1_coords[k])) + self.target_radius_1
p3 = vunit * r2
r3 = self.target_plate_radius - self.plate_module
p4 = vunit * r3
text = svg_line(p3, p4, 0.1)
text = svg_line_puzzle(p3, p4)
#text = svg_line(p3, p4, 0.1)
f_lines = f_lines + text
outer_point_1 = p4
@ -632,14 +686,16 @@ class PlateLayout:
vunit = np.array([np.cos(a), np.sin(a)])
p1 = vunit * self.target_center_hole_radius
p2 = vunit * r1
text = svg_line(p1, p2, 0.1)
#text = svg_line(p1, p2, 0.1)
text = svg_line_puzzle(p1, p2)
f_lines = f_lines + text
r2 = np.linalg.norm(np.array(self.tube_1_coords[k_next])) + self.target_radius_1
p3 = vunit * r2
r3 = self.target_plate_radius - self.plate_module
p4 = vunit * r3
text = svg_line(p3, p4, 0.1)
#text = svg_line(p3, p4, 0.1)
text = svg_line_puzzle(p3, p4)
f_lines = f_lines + text
outer_point_2 = p4
@ -663,8 +719,8 @@ class PlateLayout:
coordinates.append(c_running)
pass
dist_1 = [np.linalg.norm(c - outer_point_1*scale) for c in coordinates]
dist_2 = [np.linalg.norm(c - outer_point_2 * scale) for c in coordinates]
dist_1 = [np.linalg.norm(c - outer_point_1 * svg_scale) for c in coordinates]
dist_2 = [np.linalg.norm(c - outer_point_2 * svg_scale) for c in coordinates]
# find minimum distance and keep only points between the two distances
# problem: does not consider manual rotation of the plate
@ -674,11 +730,6 @@ class PlateLayout:
pass
#f_lines[k] = gear_data[0:index+1] + gear_data[-2:]
c = self.tube_1_coords[k]
angle = self.tube_1_angles[k]
text = svg_puzzle(c, 4, angle)
f_lines = f_lines + text
return f_lines
def output_whole(self, f_lines):