Commit d038d858 authored by lambrechts's avatar lambrechts
Browse files

dg : svg2geo.py suppor all svg path command except Aa (ellipse)

git-svn-id: https://geuz.org/svn/gmsh/trunk@16294 59c8cabf-10d6-4a28-b43f-3936b85956c4
parent 58458f74
......@@ -4,6 +4,7 @@
import math
import xml.sax.handler
import svgpathparser
R = 6.371e6
......@@ -86,49 +87,36 @@ class SVGHandler(xml.sax.handler.ContentHandler):
self.connectingNodes.append([node[0], node[1], node[2], self.ip])
self.writeNode(node)
return self.ip - 1
def writePath(self, path):
nodes = path.split()
closed = (nodes[-1] == "z" or nodes[-1] == "Z")
relative = (nodes[0] == "m")
relativeFirst = True
nodesonly = []
for snode in nodes :
if (len(snode.split(",")) == 2) :
coords = snode.split(",")
u = float(coords[0])
v = float(coords[1])
if (relative):
if(relativeFirst):
relativeFirst = False
else:
u = lastU + u
v = lastV + v
lastU = u
lastV = v
nodesonly.append(inputCoordinates(u, v))
if len(nodesonly) < 2 :
return
if not closed :
beginp = self.getConnectingNode(nodesonly[0])
endp = self.getConnectingNode(nodesonly[-1])
nodesonly.pop(0)
nodesonly.pop(-1)
def addLine(self, ltype, points) :
beginp = self.getConnectingNode(points[0])
endp = self.getConnectingNode(points[-1])
points.pop(0)
points.pop(-1)
firstp = self.ip
for node in nodesonly:
for node in points:
self.writeNode(node)
if len(nodesonly) > 2:
if closed :
ofile.write("BSpline(IL + %i) = {IP + %i : IP + %i, IP + %i};\n" % (self.il, firstp, self.ip - 1, firstp))
else:
ofile.write("BSpline(IL + %i) = {IP + %i, IP + %i : IP + %i, IP + %i};\n" % (self.il, beginp, firstp, self.ip - 1, endp))
if len(points) > 2:
ofile.write("%s(IL + %i) = {IP + %i, IP + %i : IP + %i, IP + %i};\n" % (ltype, self.il, beginp, firstp, self.ip - 1, endp))
else:
ofile.write("Line(IL + %i) = {IP + %i, IP + %i};\n" % (self.il, beginp, endp))
ofile.write("%s(IL + %i) = {IP + %i, IP + %i};\n" % (ltype, self.il, beginp, endp))
if (self.title != ""):
if (self.title in self.physicalLines):
self.physicalLines[self.title].append(self.il)
else:
self.physicalLines[self.title] = [self.il]
self.il = self.il + 1;
def writePath(self, path):
lines = svgpathparser.parse_path(path)
i = 0
while i < len(lines) :
ltype = lines[i][0]
points = []
points += lines[i][1]
i += 1
while (i < len(lines) and ltype == lines[i][0]) :
points += lines[i][1][1:]
i += 1
self.addLine(ltype, [inputCoordinates(p.real, p.imag) for p in points])
def endDocument(self):
for tag, lines in self.physicalLines.items():
self.ofile.write("Physical Line (\"%s\") = {IL + %i" % (tag, lines[0]));
......
#minor modifications to Lenart Regebro work (https://github.com/regebro/svg.path) [CC0 1.0 Universal]
COMMANDS = 'MmZzLlHhVvCcSsQqTtAa'
UPPERCASE = 'MZLHVCSQTA'
def _tokenize_path(pathdef):
# Commas and minus-signs are separators, just like spaces.
pathdef = pathdef.replace(',', ' ').replace('-', ' -')
# Commands are allowed without spaces around. Let's insert spaces so it's
# easier to split later.
for c in COMMANDS:
pathdef = pathdef.replace(c, ' %s ' % c)
# Split the path into elements and reverse, for easy use of .pop()
return pathdef.split()
def parse_path(pathdef, current_pos=0j):
# In the SVG specs, initial movetos are absolute, even if
# specified as 'm'. This is the default behavior here as well.
# But if you pass in a current_pos variable, the initial moveto
# will be relative to that current_pos. This is useful.
elements = _tokenize_path(pathdef)
elements.reverse()
segments = []
start_pos = None
command = None
while elements:
if elements[-1] in COMMANDS:
# New command.
last_command = command # Used by S and T
command = elements.pop()
absolute = command in UPPERCASE
command = command.upper()
else:
# If this element starts with numbers, it is an implicit command
# and we don't change the command. Check that it's allowed:
if command is None:
raise ValueError("Unallowed implicit command in %s, position %s" % (
pathdef, len(pathdef.split()) - len(elements)))
if command == 'M':
# Moveto command.
x = elements.pop()
y = elements.pop()
pos = float(x) + float(y) * 1j
if absolute:
current_pos = pos
else:
current_pos += pos
if start_pos is None:
start_pos = current_pos
# Implicit moveto commands are treated as lineto commands.
# So we set command to lineto here, in case there are
# further implicit commands after this moveto.
command = 'L'
elif command == 'Z':
# Close path
segments.append(("Line", (current_pos, start_pos)))
current_pos = start_pos
start_pos = None
elif command == 'L':
x = elements.pop()
y = elements.pop()
pos = float(x) + float(y) * 1j
if not absolute:
pos += current_pos
segments.append(("Line", (current_pos, pos)))
current_pos = pos
elif command == 'H':
x = elements.pop()
pos = float(x) + current_pos.imag * 1j
if not absolute:
pos += current_pos.real
segments.append(("Line", (current_pos, pos)))
current_pos = pos
elif command == 'V':
y = elements.pop()
pos = current_pos.real + float(y) * 1j
if not absolute:
pos += current_pos.imag * 1j
segments.append(("Line", (current_pos, pos)))
current_pos = pos
elif command == 'C':
control1 = float(elements.pop()) + float(elements.pop()) * 1j
control2 = float(elements.pop()) + float(elements.pop()) * 1j
end = float(elements.pop()) + float(elements.pop()) * 1j
if not absolute:
control1 += current_pos
control2 += current_pos
end += current_pos
segments.append(("Bezier", (current_pos, control1, control2, end)))
current_pos = end
elif command == 'S':
# Smooth curve. First control point is the "reflection" of
# the second control point in the previous path.
if last_command not in 'CS':
# If there is no previous command or if the previous command
# was not an C, c, S or s, assume the first control point is
# coincident with the current point.
control1 = current_pos
else:
# The first control point is assumed to be the reflection of
# the second control point on the previous command relative
# to the current point.
control1 = current_pos + current_pos - segments[-1].control2
control2 = float(elements.pop()) + float(elements.pop()) * 1j
end = float(elements.pop()) + float(elements.pop()) * 1j
if not absolute:
control2 += current_pos
end += current_pos
segments.append(("Bezier", (current_pos, control1, control2, end)))
current_pos = end
elif command == 'Q':
control = float(elements.pop()) + float(elements.pop()) * 1j
end = float(elements.pop()) + float(elements.pop()) * 1j
if not absolute:
control += current_pos
end += current_pos
segments.append(("Bezier", (current_pos, current_pos * 1./3 + 2./3 * control, end * 1./3 + 2./3 * control, end)))
current_pos = end
elif command == 'T':
# Smooth curve. Control point is the "reflection" of
# the second control point in the previous path.
if last_command not in 'QT':
# If there is no previous command or if the previous command
# was not an Q, q, T or t, assume the first control point is
# coincident with the current point.
control = current_pos
else:
# The control point is assumed to be the reflection of
# the control point on the previous command relative
# to the current point.
control = current_pos + current_pos - segments[-1].control2
end = float(elements.pop()) + float(elements.pop()) * 1j
if not absolute:
control += current_pos
end += current_pos
segments.append(("Bezier", (current_pos, current_pos * 1./3 + 2./3 * control, end * 1./3 + 2./3 * control, end)))
current_pos = end
elif command == 'A':
radius = float(elements.pop()) + float(elements.pop()) * 1j
rotation = float(elements.pop())
arc = float(elements.pop())
sweep = float(elements.pop())
end = float(elements.pop()) + float(elements.pop()) * 1j
if not absolute:
end += current_pos
segments.append(("arc", (current_pos, radius, rotation, arc, sweep, end)))
current_pos = end
return segments
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment