CMS 3D CMS Logo

List of all members | Public Member Functions | Public Attributes | Static Public Attributes
svgfig.Path Class Reference

Public Member Functions

def __init__ (self, d=[], **attr)
 
def __repr__ (self)
 
def parse (self, pathdata)
 
def parse_boolean (self, index, pathdata)
 
def parse_command (self, index, pathdata)
 
def parse_number (self, index, pathdata)
 
def parse_whitespace (self, index, pathdata)
 
def SVG (self, trans=None)
 

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

◆ __init__()

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

Definition at line 1063 of file svgfig.py.

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

Member Function Documentation

◆ __repr__()

def svgfig.Path.__repr__ (   self)

Definition at line 1060 of file svgfig.py.

1060  def __repr__(self):
1061  return "<Path (%d nodes) %s>" % (len(self.d), self.attr)
1062 

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__().

◆ parse()

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.

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

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

◆ parse_boolean()

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.

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

References createfilelist.int, and svgfig.Path.parse_whitespace().

Referenced by svgfig.Path.parse().

◆ parse_command()

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.

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

References svgfig.Path.parse_whitespace().

Referenced by svgfig.Path.parse().

◆ parse_number()

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.

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

References dqmMemoryStats.float, and svgfig.Path.parse_whitespace().

Referenced by svgfig.Path.parse().

◆ parse_whitespace()

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.

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

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

◆ SVG()

def svgfig.Path.SVG (   self,
  trans = None 
)
Apply the transformation "trans" and return an SVG object.

Definition at line 1227 of file svgfig.py.

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

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

Member Data Documentation

◆ attr

svgfig.Path.attr

◆ d

svgfig.Path.d

◆ defaults

dictionary svgfig.Path.defaults = {}
static

Definition at line 1058 of file svgfig.py.

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

dqmMemoryStats.float
float
Definition: dqmMemoryStats.py:127
join
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
dumpparser.parse
def parse(path, config)
Definition: dumpparser.py:13
svgfig.totrans
def totrans(expr, vars=("x", "y"), globals=None, locals=None)
Definition: svgfig.py:598
createfilelist.int
int
Definition: createfilelist.py:10
update
#define update(a, b)
Definition: TrackClassifier.cc:10