-
Notifications
You must be signed in to change notification settings - Fork 11
/
ttt2medial.py
202 lines (177 loc) · 7.12 KB
/
ttt2medial.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import openvoronoi as ovd # https://github.com/aewallin/openvoronoi
import truetypetracer as ttt # https://github.com/aewallin/truetype-tracer
import ngc_writer # https://github.com/aewallin/linuxcnc-scripts
import math
import time
ngc_writer.clearance_height=10
ngc_writer.feed_height = 2
ngc_writer.feed = 200
ngc_writer.plunge_feed = 100
ngc_writer.metric = True # set False for inch.
def printMedial(vd, scale):
maw = ovd.MedialAxisWalk( vd.getGraph() )
toolpath = maw.walk()
for chain in toolpath:
n = 0
for move in chain:
for point in move:
if n==0: # don't draw anything on the first iteration
p = point[0]
zdepth = scale*point[1]
ngc_writer.pen_up();
ngc_writer.xy_rapid_to( scale*p.x, scale*p.y );
ngc_writer.pen_down( z= -zdepth )
else:
p = point[0]
z = point[1]
ngc_writer.line_to( scale*p.x, scale*p.y, scale*(-z) )
n=n+1
return
# this function inserts point-sites into vd
def insert_polygon_points(vd, polygon):
pts=[]
for p in polygon:
pts.append( ovd.Point( p[0], p[1] ) )
id_list = []
#print "inserting ",len(pts)," point-sites:"
m=0
for p in pts:
id_list.append( vd.addVertexSite( p ) )
#print " ",m," added vertex ", id_list[ len(id_list) -1 ]
m=m+1
return id_list
# this function inserts line-segments into vd
def insert_polygon_segments(vd,id_list):
j=0
#print "inserting ",len(id_list)," line-segments:"
for n in range(len(id_list)):
n_nxt = n+1
if n==(len(id_list)-1):
n_nxt=0
#print " ",j,"inserting segement ",id_list[n]," - ",id_list[n_nxt]
vd.addLineSite( id_list[n], id_list[n_nxt])
j=j+1
# this function takes all segments from ttt and inserts them into vd
def insert_many_polygons(vd,segs):
polygon_ids =[]
t_before = time.time()
for poly in segs:
poly_id = insert_polygon_points(vd,poly)
polygon_ids.append(poly_id)
t_after = time.time()
pt_time = t_after-t_before
t_before = time.time()
for ids in polygon_ids:
insert_polygon_segments(vd,ids)
t_after = time.time()
seg_time = t_after-t_before
return [pt_time, seg_time]
# this translates segments from ttt
def translate(segs,x,y):
out = []
for seg in segs:
seg2 = []
for p in seg:
p2 = []
p2.append(p[0] + x)
p2.append(p[1] + y)
seg2.append(p2)
out.append(seg2)
return out
# modify by deleting last point (since it is identical to the first point)
def modify_segments(segs):
segs_mod =[]
for seg in segs:
first = seg[0]
last = seg[ len(seg)-1 ]
assert( first[0]==last[0] and first[1]==last[1] )
seg.pop()
seg.reverse() # to get interior or exterior offsets. Try commenting out this and see what happens.
segs_mod.append(seg)
return segs_mod
# scale all segs so that the overall length becomes desired_length
def scale_segs(segs, current_length, desired_length):
#print " current = ",current_length
out=[]
scale = float(desired_length) / float(current_length)
#print " scale = ",scale
for seg in segs:
seg2 = []
for p in seg:
p2 = []
p2.append(p[0] * scale)
p2.append(p[1] * scale)
seg2.append(p2)
out.append(seg2)
return [out,scale]
# get segments from ttt
def ttt_segments(text):
wr = ttt.SEG_Writer()
wr.arc = False # approximate arcs with lines
wr.conic = False # approximate conic with arc/line
wr.cubic = False # approximate cubic with arc/line
wr.conic_biarc_subdivision = 10 # this has no effect?
wr.conic_line_subdivision = 50 # =10 increasesn nr of points to 366, = 5 gives 729 pts
wr.cubic_biarc_subdivision = 10 # no effect?
wr.cubic_line_subdivision = 10 # no effect?
wr.scale = 1
wr.setFont(3)
# 0 freeserif
# 1 freeserif bold
# 2 freeserif italic
# 3 freeserif bold italic
# 4 "/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf" );
# 5 "/usr/share/fonts/truetype/freefont/FreeMonoBoldOblique.ttf" );
# 6 "/usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf" )
# 7 "/usr/share/fonts/truetype/freefont/FreeSans.ttf" );
# 8 "/usr/share/fonts/truetype/freefont/FreeSansBold.ttf" );
# 9 "/usr/share/fonts/truetype/freefont/FreeSansBoldOblique.ttf" );
# 10 "/usr/share/fonts/truetype/freefont/FreeSansOblique.ttf" );
ttt.ttt(text,wr)
segs = wr.get_segments()
ext = wr.extents
return [ext, segs]
def get_scaled_segs( chars):
# generate segs with scale 1
[extents, segs] = ttt_segments( chars )
# translate so lower left corner is at (0,0)
segs = translate(segs, -extents.minx, -extents.miny )
# scale to fit within unit circle
current_length = extents.maxx-extents.minx
current_height = extents.maxy-extents.miny
[segs,scale] = scale_segs(segs, current_length, 0.6)
segs = modify_segments(segs) # removes duplicate points
return [segs, extents,scale]
if __name__ == "__main__":
vd = ovd.VoronoiDiagram(1,120) # parameters: (r,bins)
# float r = radius within which all geometry is located. it is best to use 1 (unit-circle) for now.
# int bins = number of bins for grid-search (affects performance, should not affect correctness)
vd.set_silent(True) # suppress Warnings!
mytext = "-Hello."
text_length = 123 # desired text length in user units (set mm or inch for ngc_writer at the top of this file!)
[segs, extents, scale] = get_scaled_segs( mytext )
print_scale= float(text_length)/float(0.6)
times = insert_many_polygons(vd,segs) # insert segments into vd
# count the number of segments
num_segs = 0
for s in segs:
num_segs = num_segs + len(s)
text_length = (extents.maxx-extents.minx)*scale*print_scale
text_height = (extents.maxy-extents.miny)*scale*print_scale
# print comments to g-code file
print "( ttt2medial.py - experimental v-carving script )"
print "( TTT++",ttt.version()," )"
print "( OpenVoronoi",ovd.version()," )"
print "( number of polygons: ", len(segs)," )"
print "( number of segments: ", num_segs ," )"
print "( text length: ", text_length ," )"
print "( text height: ",text_height," )"
print "( VD built in %02.3f seconds = %02f us* n*log2{n} )" % ( sum(times), 1e6*float(sum(times))/(float(num_segs)*float(math.log10(num_segs)/math.log10(2))) )
print "( VD check: ", vd.check(), " )"
pi = ovd.PolygonInterior( True ) # filter so that only polygon interior remains
vd.filter_graph(pi)
ma = ovd.MedialAxis() # filter so that only medial axis remains
vd.filter_graph(ma)
ngc_writer.preamble()
printMedial( vd , print_scale) # the actual cutting g-code
ngc_writer.postamble()