Implementing a depth-first flattening of groups
parent
8a4801bcde
commit
70f6a78288
|
@ -51,19 +51,22 @@ A Big Problem:
|
||||||
# External dependencies
|
# External dependencies
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
import os
|
import os
|
||||||
|
import collections
|
||||||
import xml.etree.cElementTree as etree
|
import xml.etree.cElementTree as etree
|
||||||
import xml.etree.ElementTree.Element as Element
|
import xml.etree.ElementTree.Element as Element
|
||||||
import xml.etree.ElementTree.SubElement as SubElement
|
import xml.etree.ElementTree.SubElement as SubElement
|
||||||
|
|
||||||
# Internal dependencies
|
# Internal dependencies
|
||||||
from .parser import parse_path
|
from .parser import parse_path
|
||||||
from .svg2paths import (ellipse2pathd, line2pathd, polyline2pathd,
|
from .parser import parse_transform
|
||||||
|
from .svg2paths import (path2pathd, ellipse2pathd, line2pathd, polyline2pathd,
|
||||||
polygon2pathd, rect2pathd)
|
polygon2pathd, rect2pathd)
|
||||||
from .misctools import open_in_browser
|
from .misctools import open_in_browser
|
||||||
from .path import *
|
from .path import *
|
||||||
|
|
||||||
# THESE MUST BE WRAPPED TO OUPUT ElementTree.element objects
|
# THESE MUST BE WRAPPED TO OUTPUT ElementTree.element objects
|
||||||
CONVERSIONS = {'circle': ellipse2pathd,
|
CONVERSIONS = {'path': path2pathd,
|
||||||
|
'circle': ellipse2pathd,
|
||||||
'ellipse': ellipse2pathd,
|
'ellipse': ellipse2pathd,
|
||||||
'line': line2pathd,
|
'line': line2pathd,
|
||||||
'polyline': polyline2pathd,
|
'polyline': polyline2pathd,
|
||||||
|
@ -71,11 +74,44 @@ CONVERSIONS = {'circle': ellipse2pathd,
|
||||||
'rect': rect2pathd}
|
'rect': rect2pathd}
|
||||||
|
|
||||||
|
|
||||||
def flatten_group_transforms(group):
|
def flatten_paths(group, return_attribs = False, group_filter = lambda x: True, path_filter = lambda x: True,
|
||||||
"""Returns a 3x3 matrix which can transform points on a path from a group frame to the root frame"""
|
path_conversions = CONVERSIONS):
|
||||||
|
"""Returns the paths inside a group (recursively), expressing the paths in the root coordinates
|
||||||
|
|
||||||
|
@param group is an Element"""
|
||||||
if not isinstance(group, Element):
|
if not isinstance(group, Element):
|
||||||
raise TypeError('Must provide an xml.etree.Element object')
|
raise TypeError('Must provide an xml.etree.Element object')
|
||||||
|
|
||||||
|
# Stop right away if the group_selector rejects this group
|
||||||
|
if not group_filter(group):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_relevant_children(parent):
|
||||||
|
return filter(group_filter, parent.findall('g'))
|
||||||
|
|
||||||
|
# To handle the transforms efficiently, we'll traverse the tree of groups depth-first using a stack of tuples.
|
||||||
|
# The first entry in the tuple is the group element, the second entry is its transform, the third is its
|
||||||
|
# list of child elements, and the fourth is the index of the next child to traverse for that element.
|
||||||
|
StackElement = collections.namedtuple('StackElement', ['group', 'transform', 'children', 'next_child_index'])
|
||||||
|
|
||||||
|
def new_stack_element(element):
|
||||||
|
return StackElement(element, parse_transform(element.get('transform')), get_relevant_children(element), 0)
|
||||||
|
|
||||||
|
stack = [new_stack_element(group)]
|
||||||
|
|
||||||
|
paths = []
|
||||||
|
if return_attribs: path_attribs = []
|
||||||
|
|
||||||
|
while stack:
|
||||||
|
top = stack[-1]
|
||||||
|
|
||||||
|
for key in path_conversions:
|
||||||
|
for path_elem in filter(path_filter, top.group.iterfind(key)):
|
||||||
|
pass # TODO: Finish this
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ import xml.etree.cElementTree as etree
|
||||||
# Internal dependencies
|
# Internal dependencies
|
||||||
from .parser import parse_path
|
from .parser import parse_path
|
||||||
|
|
||||||
|
def path2pathd(path):
|
||||||
|
return path.get('d', None)
|
||||||
|
|
||||||
def ellipse2pathd(ellipse):
|
def ellipse2pathd(ellipse):
|
||||||
"""converts the parameters from an ellipse or a circle to a string
|
"""converts the parameters from an ellipse or a circle to a string
|
||||||
|
|
Loading…
Reference in New Issue