CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
List of all members | Public Member Functions | Public Attributes | Static Public Attributes
svgfig.Path Class Reference

Public Member Functions

def __init__
 
def __repr__
 
def parse
 
def parse_boolean
 
def parse_command
 
def parse_number
 
def parse_whitespace
 
def SVG
 

Public Attributes

 attr
 
 d
 

Static Public Attributes

dictionary defaults = {}
 

Detailed Description

Path represents an SVG path, an arbitrary set of curves and
straight segments. Unlike SVG("path", d="..."), Path stores
coordinates as a list of numbers, rather than a string, so that it is
transformable in a Fig.

Path(d, attribute=value)

d                       required        path data
attribute=value pairs   keyword list    SVG attributes

See http://www.w3.org/TR/SVG/paths.html for specification of paths
from text.

Internally, Path data is a list of tuples with these definitions:

    * ("Z/z",): close the current path
    * ("H/h", x) or ("V/v", y): a horizontal or vertical line
      segment to x or y
    * ("M/m/L/l/T/t", x, y, global): moveto, lineto, or smooth
      quadratic curveto point (x, y). If global=True, (x, y) should
      not be transformed.
    * ("S/sQ/q", cx, cy, cglobal, x, y, global): polybezier or
      smooth quadratic curveto point (x, y) using (cx, cy) as a
      control point. If cglobal or global=True, (cx, cy) or (x, y)
      should not be transformed.
    * ("C/c", c1x, c1y, c1global, c2x, c2y, c2global, x, y, global):
      cubic curveto point (x, y) using (c1x, c1y) and (c2x, c2y) as
      control points. If c1global, c2global, or global=True, (c1x, c1y),
      (c2x, c2y), or (x, y) should not be transformed.
    * ("A/a", rx, ry, rglobal, x-axis-rotation, angle, large-arc-flag,
      sweep-flag, x, y, global): arcto point (x, y) using the
      aforementioned parameters.
    * (",/.", rx, ry, rglobal, angle, x, y, global): an ellipse at
      point (x, y) with radii (rx, ry). If angle is 0, the whole
      ellipse is drawn; otherwise, a partial ellipse is drawn.

Definition at line 1021 of file svgfig.py.

Constructor & Destructor Documentation

def svgfig.Path.__init__ (   self,
  d = [],
  attr 
)

Definition at line 1063 of file svgfig.py.

1064  def __init__(self, d=[], **attr):
1065  if isinstance(d, str): self.d = self.parse(d)
1066  else: self.d = list(d)
1068  self.attr = dict(self.defaults)
1069  self.attr.update(attr)
dictionary defaults
Definition: svgfig.py:1058
def parse
Definition: svgfig.py:1118
def __init__
Definition: svgfig.py:1063

Member Function Documentation

def svgfig.Path.__repr__ (   self)

Definition at line 1060 of file svgfig.py.

References svgfig.SVG.attr, svgfig.Path.attr, svgfig.Fig.d, svgfig.Plot.d, svgfig.Frame.d, and svgfig.Path.d.

Referenced by data_sources.json_file.__str__().

1061  def __repr__(self):
1062  return "<Path (%d nodes) %s>" % (len(self.d), self.attr)
def __repr__
Definition: svgfig.py:1060
def svgfig.Path.parse (   self,
  pathdata 
)
Parses text-commands, converting them into a list of tuples.
Called by the constructor.

Definition at line 1118 of file svgfig.py.

References svgfig.Path.parse_boolean(), svgfig.Path.parse_command(), svgfig.Path.parse_number(), and svgfig.Path.parse_whitespace().

1119  def parse(self, pathdata):
1120  """Parses text-commands, converting them into a list of tuples.
1121  Called by the constructor."""
1122  output = []
1123  index = 0
1124  while True:
1125  command, index, pathdata = self.parse_command(index, pathdata)
1126  index, pathdata = self.parse_whitespace(index, pathdata)
1127 
1128  if command == None and index == len(pathdata): break # this is the normal way out of the loop
1129  if command in ("Z", "z"):
1130  output.append((command,))
1131 
1132  ######################
1133  elif command in ("H", "h", "V", "v"):
1134  errstring = "Path command \"%s\" requires a number at index %d" % (command, index)
1135  num1, index, pathdata = self.parse_number(index, pathdata)
1136  if num1 == None: raise ValueError(errstring)
1137 
1138  while num1 != None:
1139  output.append((command, num1))
1140  num1, index, pathdata = self.parse_number(index, pathdata)
1141 
1142  ######################
1143  elif command in ("M", "m", "L", "l", "T", "t"):
1144  errstring = "Path command \"%s\" requires an x,y pair at index %d" % (command, index)
1145  num1, index, pathdata = self.parse_number(index, pathdata)
1146  num2, index, pathdata = self.parse_number(index, pathdata)
1147 
1148  if num1 == None: raise ValueError(errstring)
1149 
1150  while num1 != None:
1151  if num2 == None: raise ValueError(errstring)
1152  output.append((command, num1, num2, False))
1153 
1154  num1, index, pathdata = self.parse_number(index, pathdata)
1155  num2, index, pathdata = self.parse_number(index, pathdata)
1156 
1157  ######################
1158  elif command in ("S", "s", "Q", "q"):
1159  errstring = "Path command \"%s\" requires a cx,cy,x,y quadruplet at index %d" % (command, index)
1160  num1, index, pathdata = self.parse_number(index, pathdata)
1161  num2, index, pathdata = self.parse_number(index, pathdata)
1162  num3, index, pathdata = self.parse_number(index, pathdata)
1163  num4, index, pathdata = self.parse_number(index, pathdata)
1164 
1165  if num1 == None: raise ValueError(errstring)
1166 
1167  while num1 != None:
1168  if num2 == None or num3 == None or num4 == None: raise ValueError(errstring)
1169  output.append((command, num1, num2, False, num3, num4, False))
1170 
1171  num1, index, pathdata = self.parse_number(index, pathdata)
1172  num2, index, pathdata = self.parse_number(index, pathdata)
1173  num3, index, pathdata = self.parse_number(index, pathdata)
1174  num4, index, pathdata = self.parse_number(index, pathdata)
1175 
1176  ######################
1177  elif command in ("C", "c"):
1178  errstring = "Path command \"%s\" requires a c1x,c1y,c2x,c2y,x,y sextuplet at index %d" % (command, index)
1179  num1, index, pathdata = self.parse_number(index, pathdata)
1180  num2, index, pathdata = self.parse_number(index, pathdata)
1181  num3, index, pathdata = self.parse_number(index, pathdata)
1182  num4, index, pathdata = self.parse_number(index, pathdata)
1183  num5, index, pathdata = self.parse_number(index, pathdata)
1184  num6, index, pathdata = self.parse_number(index, pathdata)
1185 
1186  if num1 == None: raise ValueError(errstring)
1187 
1188  while num1 != None:
1189  if num2 == None or num3 == None or num4 == None or num5 == None or num6 == None: raise ValueError(errstring)
1190 
1191  output.append((command, num1, num2, False, num3, num4, False, num5, num6, False))
1192 
1193  num1, index, pathdata = self.parse_number(index, pathdata)
1194  num2, index, pathdata = self.parse_number(index, pathdata)
1195  num3, index, pathdata = self.parse_number(index, pathdata)
1196  num4, index, pathdata = self.parse_number(index, pathdata)
1197  num5, index, pathdata = self.parse_number(index, pathdata)
1198  num6, index, pathdata = self.parse_number(index, pathdata)
1199 
1200  ######################
1201  elif command in ("A", "a"):
1202  errstring = "Path command \"%s\" requires a rx,ry,angle,large-arc-flag,sweep-flag,x,y septuplet at index %d" % (command, index)
1203  num1, index, pathdata = self.parse_number(index, pathdata)
1204  num2, index, pathdata = self.parse_number(index, pathdata)
1205  num3, index, pathdata = self.parse_number(index, pathdata)
1206  num4, index, pathdata = self.parse_boolean(index, pathdata)
1207  num5, index, pathdata = self.parse_boolean(index, pathdata)
1208  num6, index, pathdata = self.parse_number(index, pathdata)
1209  num7, index, pathdata = self.parse_number(index, pathdata)
1210 
1211  if num1 == None: raise ValueError(errstring)
1212 
1213  while num1 != None:
1214  if num2 == None or num3 == None or num4 == None or num5 == None or num6 == None or num7 == None: raise ValueError(errstring)
1215 
1216  output.append((command, num1, num2, False, num3, num4, num5, num6, num7, False))
1217 
1218  num1, index, pathdata = self.parse_number(index, pathdata)
1219  num2, index, pathdata = self.parse_number(index, pathdata)
1220  num3, index, pathdata = self.parse_number(index, pathdata)
1221  num4, index, pathdata = self.parse_boolean(index, pathdata)
1222  num5, index, pathdata = self.parse_boolean(index, pathdata)
1223  num6, index, pathdata = self.parse_number(index, pathdata)
1224  num7, index, pathdata = self.parse_number(index, pathdata)
1225 
1226  return output
def parse
Definition: svgfig.py:1118
def parse_whitespace
Definition: svgfig.py:1070
def parse_command
Definition: svgfig.py:1075
def parse_boolean
Definition: svgfig.py:1105
def parse_number
Definition: svgfig.py:1087
def svgfig.Path.parse_boolean (   self,
  index,
  pathdata 
)
Part of Path's text-command parsing algorithm; used internally.

Definition at line 1105 of file svgfig.py.

References svgfig.Path.parse_whitespace().

Referenced by svgfig.Path.parse().

1106  def parse_boolean(self, index, pathdata):
1107  """Part of Path's text-command parsing algorithm; used internally."""
1108  index, pathdata = self.parse_whitespace(index, pathdata)
1109 
1110  if index >= len(pathdata): return None, index, pathdata
1111  first_digit = pathdata[index]
1112 
1113  if first_digit in ("0", "1"):
1114  index += 1
1115  return int(first_digit), index, pathdata
1116  else:
1117  return None, index, pathdata
def parse_whitespace
Definition: svgfig.py:1070
def parse_boolean
Definition: svgfig.py:1105
def svgfig.Path.parse_command (   self,
  index,
  pathdata 
)
Part of Path's text-command parsing algorithm; used internally.

Definition at line 1075 of file svgfig.py.

References svgfig.Path.parse_whitespace().

Referenced by svgfig.Path.parse().

1076  def parse_command(self, index, pathdata):
1077  """Part of Path's text-command parsing algorithm; used internally."""
1078  index, pathdata = self.parse_whitespace(index, pathdata)
1079 
1080  if index >= len(pathdata): return None, index, pathdata
1081  command = pathdata[index]
1082  if "A" <= command <= "Z" or "a" <= command <= "z":
1083  index += 1
1084  return command, index, pathdata
1085  else:
1086  return None, index, pathdata
def parse_whitespace
Definition: svgfig.py:1070
def parse_command
Definition: svgfig.py:1075
def svgfig.Path.parse_number (   self,
  index,
  pathdata 
)
Part of Path's text-command parsing algorithm; used internally.

Definition at line 1087 of file svgfig.py.

References svgfig.Path.parse_whitespace().

Referenced by svgfig.Path.parse().

1088  def parse_number(self, index, pathdata):
1089  """Part of Path's text-command parsing algorithm; used internally."""
1090  index, pathdata = self.parse_whitespace(index, pathdata)
1091 
1092  if index >= len(pathdata): return None, index, pathdata
1093  first_digit = pathdata[index]
1094 
1095  if "0" <= first_digit <= "9" or first_digit in ("-", "+", "."):
1096  start = index
1097  while index < len(pathdata) and ("0" <= pathdata[index] <= "9" or pathdata[index] in ("-", "+", ".", "e", "E")):
1098  index += 1
1099  end = index
1100 
1101  index = end
1102  return float(pathdata[start:end]), index, pathdata
1103  else:
1104  return None, index, pathdata
def parse_whitespace
Definition: svgfig.py:1070
def parse_number
Definition: svgfig.py:1087
def svgfig.Path.parse_whitespace (   self,
  index,
  pathdata 
)
Part of Path's text-command parsing algorithm; used internally.

Definition at line 1070 of file svgfig.py.

Referenced by svgfig.Path.parse(), svgfig.Path.parse_boolean(), svgfig.Path.parse_command(), and svgfig.Path.parse_number().

1071  def parse_whitespace(self, index, pathdata):
1072  """Part of Path's text-command parsing algorithm; used internally."""
1073  while index < len(pathdata) and pathdata[index] in (" ", "\t", "\r", "\n", ","): index += 1
1074  return index, pathdata
def parse_whitespace
Definition: svgfig.py:1070
def svgfig.Path.SVG (   self,
  trans = None 
)
Apply the transformation "trans" and return an SVG object.

Definition at line 1227 of file svgfig.py.

References svgfig.SVG.attr, svgfig.Path.attr, svgfig.Fig.d, svgfig.Plot.d, svgfig.Frame.d, svgfig.Path.d, join(), and svgfig.totrans().

1228  def SVG(self, trans=None):
1229  """Apply the transformation "trans" and return an SVG object."""
1230  if isinstance(trans, str): trans = totrans(trans)
1231 
1232  x, y, X, Y = None, None, None, None
1233  output = []
1234  for datum in self.d:
1235  if not isinstance(datum, (tuple, list)):
1236  raise TypeError("pathdata elements must be tuples/lists")
1237 
1238  command = datum[0]
1239 
1240  ######################
1241  if command in ("Z", "z"):
1242  x, y, X, Y = None, None, None, None
1243  output.append("Z")
1244 
1245  ######################
1246  elif command in ("H", "h", "V", "v"):
1247  command, num1 = datum
1248 
1249  if command == "H" or (command == "h" and x == None): x = num1
1250  elif command == "h": x += num1
1251  elif command == "V" or (command == "v" and y == None): y = num1
1252  elif command == "v": y += num1
1253 
1254  if trans == None: X, Y = x, y
1255  else: X, Y = trans(x, y)
1256 
1257  output.append("L%g %g" % (X, Y))
1258 
1259  ######################
1260  elif command in ("M", "m", "L", "l", "T", "t"):
1261  command, num1, num2, isglobal12 = datum
1262 
1263  if trans == None or isglobal12:
1264  if command.isupper() or X == None or Y == None:
1265  X, Y = num1, num2
1266  else:
1267  X += num1
1268  Y += num2
1269  x, y = X, Y
1270 
1271  else:
1272  if command.isupper() or x == None or y == None:
1273  x, y = num1, num2
1274  else:
1275  x += num1
1276  y += num2
1277  X, Y = trans(x, y)
1278 
1279  COMMAND = command.capitalize()
1280  output.append("%s%g %g" % (COMMAND, X, Y))
1281 
1282  ######################
1283  elif command in ("S", "s", "Q", "q"):
1284  command, num1, num2, isglobal12, num3, num4, isglobal34 = datum
1285 
1286  if trans == None or isglobal12:
1287  if command.isupper() or X == None or Y == None:
1288  CX, CY = num1, num2
1289  else:
1290  CX = X + num1
1291  CY = Y + num2
1292 
1293  else:
1294  if command.isupper() or x == None or y == None:
1295  cx, cy = num1, num2
1296  else:
1297  cx = x + num1
1298  cy = y + num2
1299  CX, CY = trans(cx, cy)
1300 
1301  if trans == None or isglobal34:
1302  if command.isupper() or X == None or Y == None:
1303  X, Y = num3, num4
1304  else:
1305  X += num3
1306  Y += num4
1307  x, y = X, Y
1308 
1309  else:
1310  if command.isupper() or x == None or y == None:
1311  x, y = num3, num4
1312  else:
1313  x += num3
1314  y += num4
1315  X, Y = trans(x, y)
1316 
1317  COMMAND = command.capitalize()
1318  output.append("%s%g %g %g %g" % (COMMAND, CX, CY, X, Y))
1319 
1320  ######################
1321  elif command in ("C", "c"):
1322  command, num1, num2, isglobal12, num3, num4, isglobal34, num5, num6, isglobal56 = datum
1323 
1324  if trans == None or isglobal12:
1325  if command.isupper() or X == None or Y == None:
1326  C1X, C1Y = num1, num2
1327  else:
1328  C1X = X + num1
1329  C1Y = Y + num2
1330 
1331  else:
1332  if command.isupper() or x == None or y == None:
1333  c1x, c1y = num1, num2
1334  else:
1335  c1x = x + num1
1336  c1y = y + num2
1337  C1X, C1Y = trans(c1x, c1y)
1338 
1339  if trans == None or isglobal34:
1340  if command.isupper() or X == None or Y == None:
1341  C2X, C2Y = num3, num4
1342  else:
1343  C2X = X + num3
1344  C2Y = Y + num4
1345 
1346  else:
1347  if command.isupper() or x == None or y == None:
1348  c2x, c2y = num3, num4
1349  else:
1350  c2x = x + num3
1351  c2y = y + num4
1352  C2X, C2Y = trans(c2x, c2y)
1353 
1354  if trans == None or isglobal56:
1355  if command.isupper() or X == None or Y == None:
1356  X, Y = num5, num6
1357  else:
1358  X += num5
1359  Y += num6
1360  x, y = X, Y
1361 
1362  else:
1363  if command.isupper() or x == None or y == None:
1364  x, y = num5, num6
1365  else:
1366  x += num5
1367  y += num6
1368  X, Y = trans(x, y)
1369 
1370  COMMAND = command.capitalize()
1371  output.append("%s%g %g %g %g %g %g" % (COMMAND, C1X, C1Y, C2X, C2Y, X, Y))
1372 
1373  ######################
1374  elif command in ("A", "a"):
1375  command, num1, num2, isglobal12, angle, large_arc_flag, sweep_flag, num3, num4, isglobal34 = datum
1376 
1377  oldx, oldy = x, y
1378  OLDX, OLDY = X, Y
1379 
1380  if trans == None or isglobal34:
1381  if command.isupper() or X == None or Y == None:
1382  X, Y = num3, num4
1383  else:
1384  X += num3
1385  Y += num4
1386  x, y = X, Y
1387 
1388  else:
1389  if command.isupper() or x == None or y == None:
1390  x, y = num3, num4
1391  else:
1392  x += num3
1393  y += num4
1394  X, Y = trans(x, y)
1395 
1396  if x != None and y != None:
1397  centerx, centery = (x + oldx)/2., (y + oldy)/2.
1398  CENTERX, CENTERY = (X + OLDX)/2., (Y + OLDY)/2.
1399 
1400  if trans == None or isglobal12:
1401  RX = CENTERX + num1
1402  RY = CENTERY + num2
1403 
1404  else:
1405  rx = centerx + num1
1406  ry = centery + num2
1407  RX, RY = trans(rx, ry)
1408 
1409  COMMAND = command.capitalize()
1410  output.append("%s%g %g %g %d %d %g %g" % (COMMAND, RX - CENTERX, RY - CENTERY, angle, large_arc_flag, sweep_flag, X, Y))
1411 
1412  elif command in (",", "."):
1413  command, num1, num2, isglobal12, angle, num3, num4, isglobal34 = datum
1414  if trans == None or isglobal34:
1415  if command == "." or X == None or Y == None:
1416  X, Y = num3, num4
1417  else:
1418  X += num3
1419  Y += num4
1420  x, y = None, None
1421 
1422  else:
1423  if command == "." or x == None or y == None:
1424  x, y = num3, num4
1425  else:
1426  x += num3
1427  y += num4
1428  X, Y = trans(x, y)
1429 
1430  if trans == None or isglobal12:
1431  RX = X + num1
1432  RY = Y + num2
1433 
1434  else:
1435  rx = x + num1
1436  ry = y + num2
1437  RX, RY = trans(rx, ry)
1438 
1439  RX, RY = RX - X, RY - Y
1440 
1441  X1, Y1 = X + RX * math.cos(angle*math.pi/180.), Y + RX * math.sin(angle*math.pi/180.)
1442  X2, Y2 = X + RY * math.sin(angle*math.pi/180.), Y - RY * math.cos(angle*math.pi/180.)
1443  X3, Y3 = X - RX * math.cos(angle*math.pi/180.), Y - RX * math.sin(angle*math.pi/180.)
1444  X4, Y4 = X - RY * math.sin(angle*math.pi/180.), Y + RY * math.cos(angle*math.pi/180.)
1445 
1446  output.append("M%g %gA%g %g %g 0 0 %g %gA%g %g %g 0 0 %g %gA%g %g %g 0 0 %g %gA%g %g %g 0 0 %g %g" \
1447  % (X1, Y1, RX, RY, angle, X2, Y2, RX, RY, angle, X3, Y3, RX, RY, angle, X4, Y4, RX, RY, angle, X1, Y1))
1448 
1449  return SVG("path", d="".join(output), **self.attr)
def totrans
Definition: svgfig.py:598
static std::string join(char **cmd)
Definition: RemoteFile.cc:19

Member Data Documentation

svgfig.Path.attr

Definition at line 1067 of file svgfig.py.

Referenced by svgfig.Path.__repr__(), svgfig.Curve.__repr__(), svgfig.Poly.__repr__(), svgfig.Text.__repr__(), svgfig.TextGlobal.__repr__(), svgfig.Dots.__repr__(), svgfig.Line.__repr__(), svgfig.LineGlobal.__repr__(), svgfig.VLine.__repr__(), svgfig.HLine.__repr__(), svgfig.Rect.__repr__(), svgfig.Ellipse.__repr__(), svgfig.Ticks.__repr__(), svgfig.CurveAxis.__repr__(), svgfig.LineAxis.__repr__(), svgfig.XAxis.__repr__(), svgfig.YAxis.__repr__(), svgfig.Axes.__repr__(), svgfig.HGrid.__repr__(), svgfig.VGrid.__repr__(), svgfig.Grid.__repr__(), svgfig.Curve.Path(), svgfig.Poly.Path(), svgfig.Rect.Path(), svgfig.Path.SVG(), svgfig.Text.SVG(), svgfig.TextGlobal.SVG(), svgfig.LineGlobal.SVG(), svgfig.Axes.SVG(), svgfig.XErrorBars.SVG(), and svgfig.YErrorBars.SVG().

svgfig.Path.d

Definition at line 1064 of file svgfig.py.

Referenced by svgfig.Path.__repr__(), svgfig.Poly.__repr__(), svgfig.Text.__repr__(), svgfig.TextGlobal.__repr__(), svgfig.Dots.__repr__(), svgfig.XErrorBars.__repr__(), svgfig.YErrorBars.__repr__(), svgfig.Poly.Path(), svgfig.Path.SVG(), svgfig.Text.SVG(), svgfig.TextGlobal.SVG(), svgfig.Dots.SVG(), svgfig.XErrorBars.SVG(), and svgfig.YErrorBars.SVG().

dictionary svgfig.Path.defaults = {}
static

Definition at line 1058 of file svgfig.py.

Referenced by tree.Tree.reset(), and tree.Tree.var().