SVG Line, polygon and polyline.
This commit is contained in:
98
svgparse.py
98
svgparse.py
@@ -9,6 +9,10 @@
|
|||||||
# * Groups #
|
# * Groups #
|
||||||
# * Rectangles #
|
# * Rectangles #
|
||||||
# * Circles #
|
# * Circles #
|
||||||
|
# * Ellipses #
|
||||||
|
# * Polygons #
|
||||||
|
# * Polylines #
|
||||||
|
# * Lines #
|
||||||
# * Paths #
|
# * Paths #
|
||||||
# * All transformations #
|
# * All transformations #
|
||||||
# #
|
# #
|
||||||
@@ -22,6 +26,9 @@ from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, parse_path
|
|||||||
from shapely.geometry import LinearRing, LineString, Point
|
from shapely.geometry import LinearRing, LineString, Point
|
||||||
from shapely.affinity import translate, rotate, scale, skew, affine_transform
|
from shapely.affinity import translate, rotate, scale, skew, affine_transform
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import logging
|
||||||
|
|
||||||
|
log = logging.getLogger('base2')
|
||||||
|
|
||||||
|
|
||||||
def svgparselength(lengthstr):
|
def svgparselength(lengthstr):
|
||||||
@@ -83,7 +90,7 @@ def path2shapely(path, res=1.0):
|
|||||||
points.append((end.real, end.imag))
|
points.append((end.real, end.imag))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print "I don't know what this is:", component
|
log.warning("I don't know what this is:", component)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if path.closed:
|
if path.closed:
|
||||||
@@ -156,6 +163,32 @@ def svgellipse2shapely(ellipse, n_points=32):
|
|||||||
return LinearRing(pts)
|
return LinearRing(pts)
|
||||||
|
|
||||||
|
|
||||||
|
def svgline2shapely(line):
|
||||||
|
|
||||||
|
x1 = svgparselength(line.get('x1'))
|
||||||
|
y1 = svgparselength(line.get('y1'))
|
||||||
|
x2 = svgparselength(line.get('x2'))
|
||||||
|
y2 = svgparselength(line.get('y2'))
|
||||||
|
|
||||||
|
return LineString([(x1, y1), (x2, y2)])
|
||||||
|
|
||||||
|
|
||||||
|
def svgpolyline2shapely(polyline):
|
||||||
|
|
||||||
|
ptliststr = polyline.get('points')
|
||||||
|
points = parse_svg_point_list(ptliststr)
|
||||||
|
|
||||||
|
return LineString(points)
|
||||||
|
|
||||||
|
|
||||||
|
def svgpolygon2shapely(polygon):
|
||||||
|
|
||||||
|
ptliststr = polygon.get('points')
|
||||||
|
points = parse_svg_point_list(ptliststr)
|
||||||
|
|
||||||
|
return LinearRing(points)
|
||||||
|
|
||||||
|
|
||||||
def getsvggeo(node):
|
def getsvggeo(node):
|
||||||
"""
|
"""
|
||||||
Extracts and flattens all geometry from an SVG node
|
Extracts and flattens all geometry from an SVG node
|
||||||
@@ -176,35 +209,50 @@ def getsvggeo(node):
|
|||||||
|
|
||||||
# Parse
|
# Parse
|
||||||
elif kind == 'path':
|
elif kind == 'path':
|
||||||
print "***PATH***"
|
log.debug("***PATH***")
|
||||||
P = parse_path(node.get('d'))
|
P = parse_path(node.get('d'))
|
||||||
P = path2shapely(P)
|
P = path2shapely(P)
|
||||||
geo = [P]
|
geo = [P]
|
||||||
|
|
||||||
elif kind == 'rect':
|
elif kind == 'rect':
|
||||||
print "***RECT***"
|
log.debug("***RECT***")
|
||||||
R = svgrect2shapely(node)
|
R = svgrect2shapely(node)
|
||||||
geo = [R]
|
geo = [R]
|
||||||
|
|
||||||
elif kind == 'circle':
|
elif kind == 'circle':
|
||||||
print "***CIRCLE***"
|
log.debug("***CIRCLE***")
|
||||||
C = svgcircle2shapely(node)
|
C = svgcircle2shapely(node)
|
||||||
geo = [C]
|
geo = [C]
|
||||||
|
|
||||||
elif kind == 'ellipse':
|
elif kind == 'ellipse':
|
||||||
print "***ELLIPSE***"
|
log.debug("***ELLIPSE***")
|
||||||
E = svgellipse2shapely(node)
|
E = svgellipse2shapely(node)
|
||||||
geo = [E]
|
geo = [E]
|
||||||
|
|
||||||
|
elif kind == 'polygon':
|
||||||
|
log.debug("***POLYGON***")
|
||||||
|
poly = svgpolygon2shapely(node)
|
||||||
|
geo = [poly]
|
||||||
|
|
||||||
|
elif kind == 'line':
|
||||||
|
log.debug("***LINE***")
|
||||||
|
line = svgline2shapely(node)
|
||||||
|
geo = [line]
|
||||||
|
|
||||||
|
elif kind == 'polyline':
|
||||||
|
log.debug("***POLYLINE***")
|
||||||
|
pline = svgpolyline2shapely(node)
|
||||||
|
geo = [pline]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print "Unknown kind:", kind
|
log.warning("Unknown kind: " + kind)
|
||||||
geo = None
|
geo = None
|
||||||
|
|
||||||
# Transformations
|
# Transformations
|
||||||
if 'transform' in node.attrib:
|
if 'transform' in node.attrib:
|
||||||
trstr = node.get('transform')
|
trstr = node.get('transform')
|
||||||
trlist = parse_svg_transform(trstr)
|
trlist = parse_svg_transform(trstr)
|
||||||
print trlist
|
#log.debug(trlist)
|
||||||
|
|
||||||
# Transformations are applied in reverse order
|
# Transformations are applied in reverse order
|
||||||
for tr in trlist[::-1]:
|
for tr in trlist[::-1]:
|
||||||
@@ -227,6 +275,42 @@ def getsvggeo(node):
|
|||||||
return geo
|
return geo
|
||||||
|
|
||||||
|
|
||||||
|
def parse_svg_point_list(ptliststr):
|
||||||
|
"""
|
||||||
|
Returns a list of coordinate pairs extracted from the "points"
|
||||||
|
attribute in SVG polygons and polylines.
|
||||||
|
|
||||||
|
:param ptliststr: "points" attribute string in polygon or polyline.
|
||||||
|
:return: List of tuples with coordinates.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pairs = []
|
||||||
|
last = None
|
||||||
|
pos = 0
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
for match in re.finditer(r'(\s*,\s*)|(\s+)', ptliststr):
|
||||||
|
|
||||||
|
val = float(ptliststr[pos:match.start()])
|
||||||
|
|
||||||
|
if i % 2 == 1:
|
||||||
|
pairs.append((last, val))
|
||||||
|
else:
|
||||||
|
last = val
|
||||||
|
|
||||||
|
pos = match.end()
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
# Check for last element
|
||||||
|
val = float(ptliststr[pos:])
|
||||||
|
if i % 2 == 1:
|
||||||
|
pairs.append((last, val))
|
||||||
|
else:
|
||||||
|
log.warning("Incomplete coordinates.")
|
||||||
|
|
||||||
|
return pairs
|
||||||
|
|
||||||
|
|
||||||
def parse_svg_transform(trstr):
|
def parse_svg_transform(trstr):
|
||||||
"""
|
"""
|
||||||
Parses an SVG transform string into a list
|
Parses an SVG transform string into a list
|
||||||
|
|||||||
Reference in New Issue
Block a user