From 6002d409143a6726899a4de15c3a6b279a6b1d71 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 27 Sep 2019 10:07:38 +0200 Subject: Directory reorg: Put renderer into its own subdir --- support/pogojig/inkscape/effect.py | 279 ------------------------------------- 1 file changed, 279 deletions(-) delete mode 100644 support/pogojig/inkscape/effect.py (limited to 'support/pogojig/inkscape/effect.py') diff --git a/support/pogojig/inkscape/effect.py b/support/pogojig/inkscape/effect.py deleted file mode 100644 index 89824e9..0000000 --- a/support/pogojig/inkscape/effect.py +++ /dev/null @@ -1,279 +0,0 @@ -""" -Based on code from Aaron Spike. See -http://www.bobcookdev.com/inkscape/inkscape-dxf.html -""" - -import collections -import itertools -import os -import pkgutil -import re -from lxml import etree - -from . import inkex, simpletransform, cubicsuperpath, cspsubdiv, inkscape - - -def _get_unit_factors_map(): - # Fluctuates somewhat between Inkscape releases _and_ between SVG version. - pixels_per_inch = 96. - pixels_per_mm = pixels_per_inch / 25.4 - - return { - 'px': 1.0, - 'mm': pixels_per_mm, - 'cm': pixels_per_mm * 10, - 'm': pixels_per_mm * 1e3, - 'km': pixels_per_mm * 1e6, - 'pt': pixels_per_inch / 72, - 'pc': pixels_per_inch / 6, - 'in': pixels_per_inch, - 'ft': pixels_per_inch * 12, - 'yd': pixels_per_inch * 36} - - -class ExportEffect(inkex.Effect): - _unit_factors = _get_unit_factors_map() - _asymptote_all_paths_name = 'all' - - def __init__(self): - inkex.Effect.__init__(self) - - self._flatness = float(os.environ.get('INKSCAPE_DXF_FLATNESS', 0.1)) - - self._layers = None - self._paths = None - - def _get_document_scale(self): - """ - Return scaling factor applied to the document because of a viewBox - setting. This currently ignores any setting of a preserveAspectRatio - attribute (like Inkscape). - """ - document_height = self._get_height() - view_box = self._get_view_box() - - if view_box is None or document_height is None: - return 1 - else: - _, _, _, view_box_height = view_box - - return document_height / view_box_height - - def _get_document_height(self): - """ - Get the height of the document in pixels in the document coordinate - system as it is interpreted by Inkscape. - """ - view_box = self._get_view_box() - document_height = self._get_height() - - if view_box is not None: - _, _, _, view_box_height = view_box - - return view_box_height - elif document_height is not None: - return document_height - else: - return 0 - - def _get_height(self): - height_attr = self.document.getroot().get('height') - - if height_attr is None: - return None - else: - return self._measure_to_pixels(height_attr) - - def _get_view_box(self): - view_box_attr = self.document.getroot().get('viewBox') - - if view_box_attr is None: - return None - else: - return [float(i) for i in view_box_attr.split()] - - def _get_shape_paths(self, node, transform): - shape = cubicsuperpath.parsePath(node.get('d')) - - transform = simpletransform.composeTransform( - transform, - simpletransform.composeParents(node, [[1, 0, 0], [0, 1, 0]])) - - simpletransform.applyTransformToPath(transform, shape) - - def iter_paths(): - for path in shape: - cspsubdiv.subdiv(path, self._flatness) - - # path contains two control point coordinates and the actual - # coordinates per point. - yield [i for _, i, _ in path] - - return list(iter_paths()) - - def effect(self): - document_height = self._get_document_height() - document_scale = self._get_document_scale() - - transform = simpletransform.composeTransform( - [[document_scale, 0, 0], [0, document_scale, 0]], - [[1, 0, 0], [0, -1, document_height]]) - - layers = inkscape.get_inkscape_layers(self.svg_file) - layers_by_inkscape_name = {i.inkscape_name: i for i in layers} - - def iter_paths(): - for node in self.document.getroot().xpath('//svg:path', namespaces=inkex.NSS): - layer = layers_by_inkscape_name.get(self._get_inkscape_layer_name(node)) - - for path in self._get_shape_paths(node, transform): - yield layer, path - - self._layers = layers - self._paths = list(iter_paths()) - - def write_dxf(self, file): - # Scales pixels to millimeters. This is the predominant unit in CAD. - unit_factor = self._unit_factors['mm'] - - layer_indices = {l: i for i, l in enumerate(self._layers)} - - file.write(pkgutil.get_data(__name__, 'dxf_header.txt').decode('ASCII')) - - def write_instruction(code, value): - print(code, file=file) - print(value, file=file) - - handle_iter = itertools.count(256) - - for layer, path in self._paths: - for (x1, y1), (x2, y2) in zip(path, path[1:]): - write_instruction(0, 'LINE') - - if layer is not None: - write_instruction(8, layer.export_name) - write_instruction(62, layer_indices.get(layer, 0)) - - write_instruction(5, '{:x}'.format(next(handle_iter))) - write_instruction(100, 'AcDbEntity') - write_instruction(100, 'AcDbLine') - write_instruction(10, repr(x1 / unit_factor)) - write_instruction(20, repr(y1 / unit_factor)) - write_instruction(30, 0.0) - write_instruction(11, repr(x2 / unit_factor)) - write_instruction(21, repr(y2 / unit_factor)) - write_instruction(31, 0.0) - - file.write(pkgutil.get_data(__name__, 'dxf_footer.txt').decode('ASCII')) - - def write_asy(self, file): - def write_line(format, *args): - print >> file, format.format(*args) + ';' - - # Scales pixels to points. Asymptote uses PostScript points (1 / 72 - # inch) by default. - unit_factor = self._unit_factors['pt'] - - paths_by_layer = collections.defaultdict(list) - variable_names = [] - - for layer, path in self._paths: - paths_by_layer[layer].append(path) - - for layer in self._layers + [None]: - paths = paths_by_layer[layer] - variable_name = self._asymptote_identifier_from_layer(layer) - write_line('path[] {}', variable_name) - - variable_names.append(variable_name) - - for path in paths: - point_strs = ['({}, {})'.format(x / unit_factor, y / unit_factor) for x, y in path] - - # Hack. We should determine this from whether Z or z was used - # to close the path in the SVG document. - if path[0] == path[-1]: - point_strs[-1] = 'cycle' - - write_line('{}.push({})', variable_name, ' -- '.join(point_strs)) - - if self._asymptote_all_paths_name not in variable_names: - write_line('path[] {}', self._asymptote_all_paths_name) - - for i in variable_names: - write_line('{}.append({})', self._asymptote_all_paths_name, i) - - @classmethod - def _parse_measure(cls, string): - value_match = re.match(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)', string) - unit_match = re.search('(%s)$' % '|'.join(cls._unit_factors.keys()), string) - - value = float(string[value_match.start():value_match.end()]) - - if unit_match: - unit = string[unit_match.start():unit_match.end()] - else: - unit = None - - return value, unit - - @classmethod - def _measure_to_pixels(cls, string): - """ - Parse a string containing a measure and return it's value converted - to pixels. - """ - value, unit = cls._parse_measure(string) - - return value * cls._get_unit_factor(unit) - - @classmethod - def _get_inkscape_layer_name(cls, node): - while node is not None: - layer = node.get(inkex.addNS('label', 'inkscape')) - - if layer is not None: - return layer - - node = node.getparent() - - return None - - @classmethod - def _get_unit_factor(cls, unit): - if unit is None: - return 1 - else: - return cls._unit_factors[unit] - - @classmethod - def _asymptote_identifier_from_layer(cls, layer): - if layer is None: - return '_' - else: - return re.sub('[^a-zA-Z0-9]', '_', layer.export_name) - - @classmethod - def check_document_units(cls, path): - with open(path, 'r') as file: - p = etree.XMLParser(huge_tree = True) - document = etree.parse(file, parser = p) - - height_attr = document.getroot().get('height') - - if height_attr is None: - raise ValueError( - 'SVG document has no height attribute. See ' - 'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements') - - _, height_unit = cls._parse_measure(height_attr) - - if height_unit is None or height_unit == 'px': - raise ValueError( - 'Height of SVG document is not an absolute measure. See ' - 'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements') - - if document.getroot().get('viewBox') is None: - raise ValueError( - 'SVG document has no viewBox attribute. See ' - 'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements') -- cgit