Bugfix in search_for_outside_edge routine.
[voro++.git] / branches / 2d_boundary / Tests / build / lib.macosx-10.7-intel-2.7 / svgfig / pathdata.py
blob0bd8abd2e4f67059dba8397ddd5b444b5fd378d2
1 import defaults
3 ############################### convenient functions for making paths
5 def poly(*data, **kwds):
6 errstring = "Arguments are: poly((x1,y1), (x2,y2), ..., loop=False)"
7 loop = False
8 if "loop" in kwds:
9 loop = kwds["loop"]
10 del kwds["loop"]
11 if len(kwds) > 0: raise TypeError, errstring
13 try:
14 output = []
15 for x, y in data:
16 if output == []: output.append(("M", x, y))
17 else: output.append(("L", x, y))
18 if loop and len(data) > 0:
19 output.append(("Z",))
20 return output
21 except (TypeError, ValueError): raise TypeError, errstring
23 def bezier(*data, **kwds):
24 errstring = "Arguments are: bezier((x,y,c1x,c1y,c2x,c2y), ..., loop=False)"
25 loop = False
26 if "loop" in kwds:
27 loop = kwds["loop"]
28 del kwds["loop"]
29 if len(kwds) > 0: raise TypeError, errstring
31 try:
32 output = []
33 for x, y, c1x, c1y, c2x, c2y in data:
34 if output == []: output.append(("M", x, y))
35 else:
36 output.append(("C", c1x, c1y, c2x, c2y, x, y))
37 if loop and len(data) > 0:
38 output.append(("Z",))
39 return output
40 except (TypeError, ValueError): raise TypeError, errstring
42 def velocity(*data, **kwds):
43 errstring = "Arguments are: velocity((x,y,vx,vy), ..., loop=False)"
44 loop = False
45 if "loop" in kwds:
46 loop = kwds["loop"]
47 del kwds["loop"]
48 if len(kwds) > 0: raise TypeError, errstring
50 try:
51 output = []
52 indexes = range(len(data))
53 if loop and len(data) > 0: indexes.append(0)
55 for i in indexes:
56 if output == []: output.append(("M", data[i][0], data[i][1]))
57 else:
58 inext = (i+1) % len(data)
59 iprev = (i-1) % len(data)
61 x, y = data[i][0], data[i][1]
62 c1x, c1y = data[iprev][2]/3. + data[iprev][0], data[iprev][3]/3. + data[iprev][1]
63 c2x, c2y = data[i][2]/-3. + x, data[i][3]/-3. + y
65 output.append(("C", c1x, c1y, c2x, c2y, x, y))
67 if loop and len(data) > 0:
68 output.append(("Z",))
69 return output
70 except (TypeError, ValueError): raise TypeError, errstring
72 def foreback(*data, **kwds):
73 errstring = "Arguments are: foreback((x,y,vfx,vfy,vbx,vby), ..., loop=False)"
74 loop = False
75 if "loop" in kwds:
76 loop = kwds["loop"]
77 del kwds["loop"]
78 if len(kwds) > 0: raise TypeError, errstring
80 try:
81 output = []
82 indexes = range(len(data))
83 if loop and len(data) > 0: indexes.append(0)
85 for i in indexes:
86 if output == []: output.append(("M", data[i][0], data[i][1]))
87 else:
88 inext = (i+1) % len(data)
89 iprev = (i-1) % len(data)
91 x, y = data[i][0], data[i][1]
92 c1x, c1y = data[iprev][4]/3. + data[iprev][0], data[iprev][5]/3. + data[iprev][1]
93 c2x, c2y = data[i][2]/-3. + x, data[i][3]/-3. + y
95 output.append(("C", c1x, c1y, c2x, c2y, x, y))
97 if loop and len(data) > 0:
98 output.append(("Z",))
99 return output
100 except (TypeError, ValueError): raise TypeError, errstring
102 def smooth(*data, **kwds):
103 errstring = "Arguments are: smooth((x1,y1), (x2,y2), ..., loop=False)"
105 loop = False
106 if "loop" in kwds:
107 loop = kwds["loop"]
108 del kwds["loop"]
109 if len(kwds) > 0: raise TypeError, errstring
111 try:
112 x, y = zip(*data)
113 vx, vy = [0.]*len(data), [0.]*len(data)
114 for i in xrange(len(data)):
115 inext = (i+1) % len(data)
116 iprev = (i-1) % len(data)
118 vx[i] = (x[inext] - x[iprev])/2.
119 vy[i] = (y[inext] - y[iprev])/2.
120 if not loop and (i == 0 or i == len(data)-1):
121 vx[i], vy[i] = 0., 0.
123 return velocity(zip(x, y, vx, vy), loop)
124 except (TypeError, ValueError): raise TypeError, errstring
126 ############################### pathdata parsers
128 def parse_whitespace(index, pathdata):
129 while index < len(pathdata) and pathdata[index] in (" ", "\t", "\r", "\n", ","): index += 1
130 return index, pathdata
132 def parse_command(index, pathdata):
133 index, pathdata = parse_whitespace(index, pathdata)
135 if index >= len(pathdata): return None, index, pathdata
136 command = pathdata[index]
137 if "A" <= command <= "Z" or "a" <= command <= "z":
138 index += 1
139 return command, index, pathdata
140 else:
141 return None, index, pathdata
143 def parse_number(index, pathdata):
144 index, pathdata = parse_whitespace(index, pathdata)
146 if index >= len(pathdata): return None, index, pathdata
147 first_digit = pathdata[index]
149 if "0" <= first_digit <= "9" or first_digit in ("-", "+", "."):
150 start = index
151 while index < len(pathdata) and ("0" <= pathdata[index] <= "9" or pathdata[index] in ("-", "+", ".", "e", "E")):
152 index += 1
153 end = index
155 index = end
156 return float(pathdata[start:end]), index, pathdata
157 else:
158 return None, index, pathdata
160 def parse_boolean(index, pathdata):
161 index, pathdata = parse_whitespace(index, pathdata)
163 if index >= len(pathdata): return None, index, pathdata
164 first_digit = pathdata[index]
166 if first_digit in ("0", "1"):
167 index += 1
168 return int(first_digit), index, pathdata
169 else:
170 return None, index, pathdata
172 ############################### main parsing function (keeps defaults from getting messy)
174 def parse(pathdata):
175 if isinstance(pathdata, (list, tuple)): return pathdata
177 output = []
178 index = 0
179 while True:
180 command, index, pathdata = parse_command(index, pathdata)
181 index, pathdata = parse_whitespace(index, pathdata)
183 if command == None and index == len(pathdata): break # this is the normal way out of the loop
184 if command in ("Z", "z"):
185 output.append((command,))
187 ######################
188 elif command in ("H", "h", "V", "v"):
189 errstring = "Pathdata command \"%s\" requires a number at index %d" % (command, index)
190 num1, index, pathdata = parse_number(index, pathdata)
191 if num1 == None: raise ValueError, errstring
193 while num1 != None:
194 output.append((command, num1))
195 num1, index, pathdata = parse_number(index, pathdata)
197 ######################
198 elif command in ("M", "m", "L", "l", "T", "t"):
199 errstring = "Pathdata command \"%s\" requires an x,y pair at index %d" % (command, index)
200 num1, index, pathdata = parse_number(index, pathdata)
201 num2, index, pathdata = parse_number(index, pathdata)
203 if num1 == None: raise ValueError, errstring
205 while num1 != None:
206 if num2 == None: raise ValueError, errstring
207 output.append((command, num1, num2))
209 num1, index, pathdata = parse_number(index, pathdata)
210 num2, index, pathdata = parse_number(index, pathdata)
212 ######################
213 elif command in ("S", "s", "Q", "q"):
214 errstring = "Pathdata command \"%s\" requires a cx,cy,x,y quadruplet at index %d" % (command, index)
215 num1, index, pathdata = parse_number(index, pathdata)
216 num2, index, pathdata = parse_number(index, pathdata)
217 num3, index, pathdata = parse_number(index, pathdata)
218 num4, index, pathdata = parse_number(index, pathdata)
220 if num1 == None: raise ValueError, errstring
222 while num1 != None:
223 if num2 == None or num3 == None or num4 == None: raise ValueError, errstring
224 output.append((command, num1, num2, num3, num4))
226 num1, index, pathdata = parse_number(index, pathdata)
227 num2, index, pathdata = parse_number(index, pathdata)
228 num3, index, pathdata = parse_number(index, pathdata)
229 num4, index, pathdata = parse_number(index, pathdata)
231 ######################
232 elif command in ("C", "c"):
233 errstring = "Pathdata command \"%s\" requires a c1x,c1y,c2x,c2y,x,y sextuplet at index %d" % (command, index)
234 num1, index, pathdata = parse_number(index, pathdata)
235 num2, index, pathdata = parse_number(index, pathdata)
236 num3, index, pathdata = parse_number(index, pathdata)
237 num4, index, pathdata = parse_number(index, pathdata)
238 num5, index, pathdata = parse_number(index, pathdata)
239 num6, index, pathdata = parse_number(index, pathdata)
241 if num1 == None: raise ValueError, errstring
243 while num1 != None:
244 if num2 == None or num3 == None or num4 == None or num5 == None or num6 == None: raise ValueError, errstring
246 output.append((command, num1, num2, num3, num4, num5, num6))
248 num1, index, pathdata = parse_number(index, pathdata)
249 num2, index, pathdata = parse_number(index, pathdata)
250 num3, index, pathdata = parse_number(index, pathdata)
251 num4, index, pathdata = parse_number(index, pathdata)
252 num5, index, pathdata = parse_number(index, pathdata)
253 num6, index, pathdata = parse_number(index, pathdata)
255 ######################
256 elif command in ("A", "a"):
257 errstring = "Pathdata command \"%s\" requires a rx,ry,angle,large-arc-flag,sweep-flag,x,y septuplet at index %d" % (command, index)
258 num1, index, pathdata = parse_number(index, pathdata)
259 num2, index, pathdata = parse_number(index, pathdata)
260 num3, index, pathdata = parse_number(index, pathdata)
261 num4, index, pathdata = parse_boolean(index, pathdata)
262 num5, index, pathdata = parse_boolean(index, pathdata)
263 num6, index, pathdata = parse_number(index, pathdata)
264 num7, index, pathdata = parse_number(index, pathdata)
266 if num1 == None: raise ValueError, errstring
268 while num1 != None:
269 if num2 == None or num3 == None or num4 == None or num5 == None or num6 == None or num7 == None: raise ValueError, errstring
271 output.append((command, num1, num2, num3, num4, num5, num6, num7))
273 num1, index, pathdata = parse_number(index, pathdata)
274 num2, index, pathdata = parse_number(index, pathdata)
275 num3, index, pathdata = parse_number(index, pathdata)
276 num4, index, pathdata = parse_boolean(index, pathdata)
277 num5, index, pathdata = parse_boolean(index, pathdata)
278 num6, index, pathdata = parse_number(index, pathdata)
279 num7, index, pathdata = parse_number(index, pathdata)
281 return output
283 ############################### transformation function (keeps defaults from getting messy)
285 def transform(func, pathdata):
286 x, y, X, Y = None, None, None, None
287 output = []
288 for datum in pathdata:
289 if not isinstance(datum, (tuple, list)):
290 raise TypeError, "Pathdata elements must be lists/tuples"
292 command = datum[0]
293 args = datum[1:]
295 ######################
296 if command in ("Z", "z"):
297 x, y, X, Y = None, None, None, None
298 output.append(("Z",))
300 ######################
301 elif command in ("H", "h", "V", "v"):
302 num1 = args[0]
304 if command == "H" or (command == "h" and x == None): x = num1
305 elif command == "h": x += num1
306 elif command == "V" or (command == "v" and y == None): y = num1
307 elif command == "v": y += num1
309 X, Y = func(x, y)
310 output.append(("L", X, Y))
312 ######################
313 elif command in ("M", "m", "L", "l", "T", "t"):
314 num1, num2 = args
316 if command.isupper() or x == None or y == None:
317 x, y = num1, num2
318 else:
319 x += num1
320 y += num2
322 X, Y = func(x, y)
323 output.append((command.capitalize(), X, Y))
325 ######################
326 elif command in ("S", "s", "Q", "q"):
327 num1, num2, num3, num4 = args
329 if command.isupper() or x == None or y == None:
330 cx, cy = num1, num2
331 else:
332 cx = x + num1
333 cy = y + num2
335 if command.isupper() or x == None or y == None:
336 x, y = num3, num4
337 else:
338 x += num3
339 y += num4
341 CX, CY = func(cx, cy)
342 X, Y = func(x, y)
343 output.append((command.capitalize(), CX, CY, X, Y))
345 ######################
346 elif command in ("C", "c"):
347 num1, num2, num3, num4, num5, num6 = args
349 if command.isupper() or x == None or y == None:
350 c1x, c1y = num1, num2
351 else:
352 c1x = x + num1
353 c1y = y + num2
355 if command.isupper() or x == None or y == None:
356 c2x, c2y = num3, num4
357 else:
358 c2x = x + num3
359 c2y = y + num4
361 if command.isupper() or x == None or y == None:
362 x, y = num5, num6
363 else:
364 x += num5
365 y += num6
367 C1X, C1Y = func(c1x, c1y)
368 C2X, C2Y = func(c2x, c2y)
369 X, Y = func(x, y)
370 output.append((command.capitalize(), C1X, C1Y, C2X, C2Y, X, Y))
372 ######################
373 elif command in ("A", "a"):
374 num1, num2, angle, large_arc_flag, sweep_flag, num3, num4 = args
376 oldx, oldy = x, y
377 OLDX, OLDY = X, Y
379 if command.isupper() or x == None or y == None:
380 x, y = num3, num4
381 else:
382 x += num3
383 y += num4
384 X, Y = func(x, y)
386 if x != None and y != None:
387 centerx, centery = (x + oldx)/2., (y + oldy)/2.
388 CENTERX, CENTERY = (X + OLDX)/2., (Y + OLDY)/2.
390 rx = centerx + num1
391 ry = centery + num2
392 RX, RY = func(rx, ry)
394 output.append((command.capitalize(), RX - CENTERX, RY - CENTERY, angle, large_arc_flag, sweep_flag, X, Y))
396 return output
398 ############################### bbox function (keeps defaults from getting messy)
400 def bbox(pathdata):
401 x, y = None, None
402 output = defaults.BBox(None, None, None, None)
404 for datum in pathdata:
405 if not isinstance(datum, (tuple, list)):
406 raise TypeError, "Pathdata elements must be lists/tuples"
408 command = datum[0]
409 args = datum[1:]
411 ######################
412 if command in ("Z", "z"): pass
414 ######################
415 elif command in ("H", "h", "V", "v"):
416 num1 = args[0]
418 if command == "H" or (command == "h" and x == None): x = num1
419 elif command == "h": x += num1
420 elif command == "V" or (command == "v" and y == None): y = num1
421 elif command == "v": y += num1
423 output.insert(x, y)
425 ######################
426 elif command in ("M", "m", "L", "l", "T", "t"):
427 num1, num2 = args
429 if command.isupper() or x == None or y == None:
430 x, y = num1, num2
431 else:
432 x += num1
433 y += num2
435 output.insert(x, y)
437 ######################
438 elif command in ("S", "s", "Q", "q"):
439 num1, num2, num3, num4 = args
441 if command.isupper() or x == None or y == None:
442 cx, cy = num1, num2
443 else:
444 cx = x + num1
445 cy = y + num2
447 if command.isupper() or x == None or y == None:
448 x, y = num3, num4
449 else:
450 x += num3
451 y += num4
453 output.insert(x, y)
455 ######################
456 elif command in ("C", "c"):
457 num1, num2, num3, num4, num5, num6 = args
459 if command.isupper() or x == None or y == None:
460 c1x, c1y = num1, num2
461 else:
462 c1x = x + num1
463 c1y = y + num2
465 if command.isupper() or x == None or y == None:
466 c2x, c2y = num3, num4
467 else:
468 c2x = x + num3
469 c2y = y + num4
471 if command.isupper() or x == None or y == None:
472 x, y = num5, num6
473 else:
474 x += num5
475 y += num6
477 output.insert(x, y)
479 ######################
480 elif command in ("A", "a"):
481 num1, num2, angle, large_arc_flag, sweep_flag, num3, num4 = args
483 oldx, oldy = x, y
484 OLDX, OLDY = X, Y
486 if command.isupper() or x == None or y == None:
487 x, y = num3, num4
488 else:
489 x += num3
490 y += num4
492 if x != None and y != None:
493 centerx, centery = (x + oldx)/2., (y + oldy)/2.
494 CENTERX, CENTERY = (X + OLDX)/2., (Y + OLDY)/2.
496 output.insert(x, y)
498 return output