-
Notifications
You must be signed in to change notification settings - Fork 0
/
gen_pattern.py
134 lines (120 loc) · 6.25 KB
/
gen_pattern.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python
"""gen_pattern.py
Usage example:
python gen_pattern.py -o out.svg -r 11 -c 8 -T circles -s 20.0 -R 5.0 -u mm -w 216 -h 279
-o, --output - output file (default out.svg)
-r, --rows - pattern rows (default 11)
-c, --columns - pattern columns (default 8)
-T, --type - type of pattern, circles, acircles, checkerboard (default circles)
-s, --square_size - size of squares in pattern (default 20.0)
-R, --radius_rate - circles_radius = square_size/radius_rate (default 5.0)
-u, --units - mm, inches, px, m (default mm)
-w, --page_width - page width in units (default 216)
-h, --page_height - page height in units (default 279)
-a, --page_size - page size (default A4), supersedes -h -w arguments
-H, --help - show help
"""
import argparse
from svgfig import *
class PatternMaker:
def __init__(self, cols, rows, output, units, square_size, radius_rate, page_width, page_height):
self.cols = cols
self.rows = rows
self.output = output
self.units = units
self.square_size = square_size
self.radius_rate = radius_rate
self.width = page_width
self.height = page_height
self.g = SVG("g") # the svg group container
def make_circles_pattern(self):
spacing = self.square_size
r = spacing / self.radius_rate
pattern_width = ((self.cols - 1.0) * spacing) + (2.0 * r)
pattern_height = ((self.rows - 1.0) * spacing) + (2.0 * r)
x_spacing = (self.width - pattern_width) / 2.0
y_spacing = (self.height - pattern_height) / 2.0
for x in range(0, self.cols):
for y in range(0, self.rows):
dot = SVG("circle", cx=(x * spacing) + x_spacing + r,
cy=(y * spacing) + y_spacing + r, r=r, fill="black", stroke="none")
self.g.append(dot)
def make_acircles_pattern(self):
spacing = self.square_size
r = spacing / self.radius_rate
pattern_width = ((self.cols-1.0) * 2 * spacing) + spacing + (2.0 * r)
pattern_height = ((self.rows-1.0) * spacing) + (2.0 * r)
x_spacing = (self.width - pattern_width) / 2.0
y_spacing = (self.height - pattern_height) / 2.0
for x in range(0, self.cols):
for y in range(0, self.rows):
dot = SVG("circle", cx=(2 * x * spacing) + (y % 2)*spacing + x_spacing + r,
cy=(y * spacing) + y_spacing + r, r=r, fill="black", stroke="none")
self.g.append(dot)
def make_checkerboard_pattern(self):
spacing = self.square_size
xspacing = (self.width - self.cols * self.square_size) / 2.0
yspacing = (self.height - self.rows * self.square_size) / 2.0
for x in range(0, self.cols):
for y in range(0, self.rows):
if x % 2 == y % 2:
square = SVG("rect", x=x * spacing + xspacing, y=y * spacing + yspacing, width=spacing,
height=spacing, fill="black", stroke="none")
self.g.append(square)
def save(self):
c = canvas(self.g, width="%d%s" % (self.width, self.units), height="%d%s" % (self.height, self.units),
viewBox="0 0 %d %d" % (self.width, self.height))
c.save(self.output)
def main():
# parse command line options
parser = argparse.ArgumentParser(description="generate camera-calibration pattern", add_help=False)
parser.add_argument("-H", "--help", help="show help", action="store_true", dest="show_help")
parser.add_argument("-o", "--output", help="output file", default="out.svg", action="store", dest="output")
parser.add_argument("-c", "--columns", help="pattern columns", default="8", action="store", dest="columns",
type=int)
parser.add_argument("-r", "--rows", help="pattern rows", default="11", action="store", dest="rows", type=int)
parser.add_argument("-T", "--type", help="type of pattern", default="circles", action="store", dest="p_type",
choices=["circles", "acircles", "checkerboard"])
parser.add_argument("-u", "--units", help="length unit", default="mm", action="store", dest="units",
choices=["mm", "inches", "px", "m"])
parser.add_argument("-s", "--square_size", help="size of squares in pattern", default="20.0", action="store",
dest="square_size", type=float)
parser.add_argument("-R", "--radius_rate", help="circles_radius = square_size/radius_rate", default="5.0",
action="store", dest="radius_rate", type=float)
parser.add_argument("-w", "--page_width", help="page width in units", default=argparse.SUPPRESS, action="store",
dest="page_width", type=float)
parser.add_argument("-h", "--page_height", help="page height in units", default=argparse.SUPPRESS, action="store",
dest="page_height", type=float)
parser.add_argument("-a", "--page_size", help="page size, superseded if -h and -w are set", default="A4", action="store",
dest="page_size", choices=["A0", "A1", "A2", "A3", "A4", "A5"])
args = parser.parse_args()
show_help = args.show_help
if show_help:
parser.print_help()
return
output = args.output
columns = args.columns
rows = args.rows
p_type = args.p_type
units = args.units
square_size = args.square_size
radius_rate = args.radius_rate
if 'page_width' and 'page_height' in args:
page_width = args.page_width
page_height = args.page_height
else:
page_size = args.page_size
# page size dict (ISO standard, mm) for easy lookup. format - size: [width, height]
page_sizes = {"A0": [840, 1188], "A1": [594, 840], "A2": [420, 594], "A3": [297, 420], "A4": [210, 297],
"A5": [148, 210]}
page_width = page_sizes[page_size][0]
page_height = page_sizes[page_size][1]
pm = PatternMaker(columns, rows, output, units, square_size, radius_rate, page_width, page_height)
# dict for easy lookup of pattern type
mp = {"circles": pm.make_circles_pattern, "acircles": pm.make_acircles_pattern,
"checkerboard": pm.make_checkerboard_pattern}
mp[p_type]()
# this should save pattern to output
pm.save()
if __name__ == "__main__":
main()