From d35a1dd4bbede46718a012bbdb5bc707d44e0644 Mon Sep 17 00:00:00 2001 From: "kujiu (@rincevent)" Date: Tue, 2 Nov 2021 01:47:43 +0100 Subject: [PATCH] Lasercutting version --- README.md | 15 +- lasercut/goban-lasercut.py | 383 +++++ lasercut/goban19x19-300x300-base.svg | 380 +++++ lasercut/goban19x19-300x300-recto.svg | 2139 +++++++++++++++++++++++++ lasercut/goban19x19-300x300-verso.svg | 368 +++++ lasercut/requirements.txt | 1 + 6 files changed, 3285 insertions(+), 1 deletion(-) create mode 100644 lasercut/goban-lasercut.py create mode 100644 lasercut/goban19x19-300x300-base.svg create mode 100644 lasercut/goban19x19-300x300-recto.svg create mode 100644 lasercut/goban19x19-300x300-verso.svg create mode 100644 lasercut/requirements.txt diff --git a/README.md b/README.md index 88c48bd..ed58553 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ # goban -Parametric goban and stones for blind players \ No newline at end of file +Parametric goban and stones for blind players + +- One version for 3D printing + CNC +- One version for laser-cutting + +## Laser-cutting version + +- Engrave then cut one base. +- Engrave verso of upper sheet. +- Engrave then cut recto of upper sheet. +- Stick upper sheet on base. + +Hint : create three goban, each in an other color. +Reorder your stones to have good colors for each set. diff --git a/lasercut/goban-lasercut.py b/lasercut/goban-lasercut.py new file mode 100644 index 0000000..37be681 --- /dev/null +++ b/lasercut/goban-lasercut.py @@ -0,0 +1,383 @@ +#!/usr/bin/env python3 + +import argparse +import math +import drawSvg as draw + + +def is_hoshi(pos, size): + """ + Is this position a hoshi ? + """ + for axis in (0, 1): + if size[axis] > 10: + if pos[axis] not in (3, round(size[axis]/2)-1, size[axis]-4): + return False + elif pos[axis] not in (2, round(size[axis]/2)-1, size[axis]-3): + return False + + return True + + +class GobanDraw: + """ + Drawing a goban and its stones. + + @param config: Config from argparse + """ + def __init__(self, config) -> None: + self.config = config + self.scale = config.resolution + self.total_size = ( + ((config.size[0]-1)*config.cellsize[0]+ + config.borders[1]+config.borders[3]+ + 2*config.stone_radius+2*config.stone_margin)*self.scale, + ((config.size[1]-1)*config.cellsize[1]+ + config.borders[0]+config.borders[2]+ + 2*config.stone_radius+2*config.stone_margin)*self.scale) + + print("Total size: %dx%d" % self.total_size) + + self.recto_drawing = draw.Drawing(*self.total_size) + self.verso_drawing = draw.Drawing(*self.total_size) + self.base_drawing = draw.Drawing(*self.total_size) + + def drawEngraving(self) -> None: + """ + Draw engraving of stones and goban + """ + if not self.config.engrave: + return + + engraved_stones = 0 + borders = [b*self.scale for b in self.config.borders] + cellsize = [s*self.scale for s in self.config.cellsize] + radius = self.config.stone_radius * self.scale + margin = self.config.stone_margin * self.scale + thickness = self.config.thickness * self.scale + mark_thickness = self.config.mark_thickness * self.scale + color = self.config.engrave_color + for x in range(self.config.size[0]): + for y in range(self.config.size[1]): + # pos(recto_x, recto_y, verso_x, verso_y) + pos = ( + borders[3]+x*cellsize[0]+radius+margin, + borders[0]+y*cellsize[1]+radius+margin, + self.total_size[0]-borders[3]-x*cellsize[0]-radius-margin, + borders[0]+y*cellsize[1]+radius+margin + ) + # Draw grid on recto + if x > 0: + self.recto_drawing.append( + draw.Line( + pos[0]-radius-margin, + pos[1], + pos[0]-cellsize[0]+radius+margin, + pos[1], + stroke=color, + stroke_width=thickness + ) + ) + if y > 0: + self.recto_drawing.append( + draw.Line( + pos[0], + pos[1]-radius-margin, + pos[0], + pos[1]-cellsize[1]+radius+margin, + stroke=color, + stroke_width=thickness + ) + ) + # Draw engraving on stones (recto and verso) + if engraved_stones < self.config.engraved_stones: + engraved_radius = mark_thickness + while engraved_radius < radius: + self.recto_drawing.append( + draw.Circle( + pos[0], + pos[1], + engraved_radius - mark_thickness/2, + fill='none', + stroke=color, + stroke_width=mark_thickness + ) + ) + self.verso_drawing.append( + draw.Circle( + pos[2], + pos[3], + engraved_radius - mark_thickness/2, + fill='none', + stroke=color, + stroke_width=mark_thickness + ) + ) + engraved_radius += 2*mark_thickness + engraved_stones += 1 + + # Draw Hoshi on base + if is_hoshi((x, y), self.config.size): + self.base_drawing.append( + draw.Circle( + pos[0], + pos[1], + radius/3, + fill='none', + stroke=color, + stroke_width=thickness + ) + ) + + def drawCutting(self) -> None: + """ + Draw cutting of stones and goban + """ + if not self.config.cut: + return + + borders = [b*self.scale for b in self.config.borders] + cellsize = [s*self.scale for s in self.config.cellsize] + radius = self.config.stone_radius * self.scale + margin = self.config.stone_margin * self.scale + corner_radius = min(borders) / 2 + thickness = self.config.cut_thickness * self.scale + color = self.config.cut_color + + # Cut corners on recto and base + if self.config.round_corners: + self.recto_drawing.append( + draw.Arc( + corner_radius, + corner_radius, + corner_radius, + 180, + 270, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + self.base_drawing.append( + draw.Arc( + corner_radius, + corner_radius, + corner_radius, + 180, + 270, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + self.recto_drawing.append( + draw.Arc( + self.total_size[0]-corner_radius, + corner_radius, + corner_radius, + 270, + 0, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + self.base_drawing.append( + draw.Arc( + self.total_size[0]-corner_radius, + corner_radius, + corner_radius, + 270, + 0, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + self.recto_drawing.append( + draw.Arc( + corner_radius, + self.total_size[1]-corner_radius, + corner_radius, + 90, + 180, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + self.base_drawing.append( + draw.Arc( + corner_radius, + self.total_size[1]-corner_radius, + corner_radius, + 90, + 180, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + self.recto_drawing.append( + draw.Arc( + self.total_size[0]-corner_radius, + self.total_size[1]-corner_radius, + corner_radius, + 0, + 90, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + self.base_drawing.append( + draw.Arc( + self.total_size[0]-corner_radius, + self.total_size[1]-corner_radius, + corner_radius, + 0, + 90, + stroke=color, + stroke_width=thickness, + fill='none' + ) + ) + + # Cut stones on recto and holes on base + for x in range(self.config.size[0]): + for y in range(self.config.size[1]): + # pos(recto_x, recto_y) + pos = ( + borders[3]+x*cellsize[0]+radius+margin, + borders[0]+y*cellsize[1]+radius+margin, + ) + + self.recto_drawing.append( + draw.Circle( + pos[0], + pos[1], + radius+margin, + fill='none', + stroke=color, + stroke_width=thickness + ) + ) + self.recto_drawing.append( + draw.Arc( + pos[0], + pos[1], + radius, + 90+math.acos(0.75)*360/(2*math.pi), + 90-math.acos(0.75)*360/(2*math.pi), + fill='none', + stroke=color, + stroke_width=thickness + ) + ) + self.recto_drawing.append( + draw.Arc( + pos[0], + pos[1]+3*radius/2, + radius, + 270-math.acos(0.75)*360/(2*math.pi), + 270+math.acos(0.75)*360/(2*math.pi), + fill='none', + stroke=color, + stroke_width=thickness + ) + ) + self.base_drawing.append( + draw.Circle( + pos[0], + pos[1], + radius/4, + fill='none', + stroke=color, + stroke_width=thickness + ) + ) + + def save(self) -> None: + """ + Save drawing. + """ + self.recto_drawing.saveSvg(self.config.prefix+'recto.svg') + self.verso_drawing.saveSvg(self.config.prefix+'verso.svg') + self.base_drawing.saveSvg(self.config.prefix+'base.svg') + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Create goban and stones for lasercut" + ) + parser.add_argument( + '--size', type=int, nargs=2, default=(19, 19), + help="Size of goban (number of stones)", metavar=('X', 'Y') + ) + parser.add_argument( + '--cellsize', type=int, nargs=2, default=(15, 15), + help="Size of one cell in mm", metavar=('X', 'Y') + ) + parser.add_argument( + '--stone-radius', type=int, default=5.5, + help="Radius of stone in mm" + ) + parser.add_argument( + '--stone-margin', type=int, default=1, + help="Margin of stone in mm" + ) + parser.add_argument( + '--borders', type=int, nargs=4, default=(5, 5, 5, 5), + help="Borders of goban in mm", + metavar=('UP', 'RIGHT', 'BOTTOM', 'LEFT') + ) + parser.add_argument( + '--thickness', type=float, default=2.0, + help="Thickness of grid in mm" + ) + parser.add_argument( + '--mark-thickness', type=float, default=1.5, + help="Thickness of mark on stone in mm" + ) + parser.add_argument( + '--cut-thickness', type=float, default=0.2, + help="Thickness of cut stroke in mm" + ) + parser.add_argument( + '--engrave', default=False, action='store_true', + help='Enable engraving' + ) + parser.add_argument( + '--cut', default=False, action='store_true', + help='Enable cutting' + ) + parser.add_argument( + '--round-corners', default=False, action='store_true', + help='Round corners for goban' + ) + parser.add_argument( + '--engrave-color', type=str, default='#0000ff', + help="Engrave color in web format #000000 to #ffffff" + ) + parser.add_argument( + '--cut-color', type=str, default='#ff0000', + help="Cut color in web format #000000 to #ffffff" + ) + parser.add_argument( + '--engraved-stones', type=int, default=181, + help="Number of engraved (black) stones" + ) + parser.add_argument( + '--prefix', default='', + help='Prefix for filenames, ' + + 'create three files named prefixrecto.svg, prefixverso.svg and '+ + 'prefixbase.svg' + ) + parser.add_argument( + '--resolution', type=int, default=100, + help="Resolution in pixels/mm" + ) + conf = parser.parse_args() + goban = GobanDraw(conf) + goban.drawEngraving() + goban.drawCutting() + goban.save() diff --git a/lasercut/goban19x19-300x300-base.svg b/lasercut/goban19x19-300x300-base.svg new file mode 100644 index 0000000..c7b69a9 --- /dev/null +++ b/lasercut/goban19x19-300x300-base.svg @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lasercut/goban19x19-300x300-recto.svg b/lasercut/goban19x19-300x300-recto.svg new file mode 100644 index 0000000..4e551e4 --- /dev/null +++ b/lasercut/goban19x19-300x300-recto.svg @@ -0,0 +1,2139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lasercut/goban19x19-300x300-verso.svg b/lasercut/goban19x19-300x300-verso.svg new file mode 100644 index 0000000..6186fa1 --- /dev/null +++ b/lasercut/goban19x19-300x300-verso.svg @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lasercut/requirements.txt b/lasercut/requirements.txt new file mode 100644 index 0000000..2c09f11 --- /dev/null +++ b/lasercut/requirements.txt @@ -0,0 +1 @@ +drawSvg