####################################################################################################
#
# Patro - A Python library to make patterns for fashion design
# Copyright (C) 2019 Salvaire Fabrice
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
####################################################################################################
####################################################################################################
import logging
import unittest
from pathlib import Path
from Patro.Common.Logging import Logging
Logging.setup_logging()
from IntervalArithmetic import Interval2D
from Patro.FileFormat.Svg import SvgFormat
from Patro.FileFormat.Svg.SvgFile import SvgFile, SvgFileInternal
from Patro.GeometryEngine.Transformation import AffineTransformation2D
from Patro.GeometryEngine.Vector import Vector2D
from PatroExample import find_data_path
####################################################################################################
_module_logger = logging.getLogger(__name__)
####################################################################################################
svg_data = """
"""
####################################################################################################
class SceneImporter(SvgFileInternal):
# Fixme: duplicated code
_logger = _module_logger.getChild('SceneImporter')
##############################################
def __init__(self, svg_path, data=None):
self._scene = {}
self._bounding_box = None
super().__init__(svg_path, data)
##############################################
def __len__(self):
return len(self._scene)
def __getitem__(self, name):
return self._scene[name]
@property
def scene(self):
return self._scene
@property
def bounding_box(self):
return self._bounding_box
##############################################
def _add_to_scene(self, name, geometry):
self._scene[name] = geometry
##############################################
def _update_bounding_box(self, item):
interval = item.bounding_box
if self._bounding_box is None:
self._bounding_box = interval
else:
self._bounding_box |= interval
##############################################
def on_svg_root(self, svg_root):
super().on_svg_root(svg_root)
self._screen_transformation = AffineTransformation2D.Screen(self._view_box.y.sup)
##############################################
def on_group(self, group):
# self._logger.info('Group: {}\n{}'.format(group.id, group))
pass
##############################################
def on_graphic_item(self, item):
state = self._dispatcher.state.clone().merge(item)
self._logger.info('Item: {}\n{}'.format(item.id, item))
# self._logger.info('Item State:\n' + str(state))
transformation = state.transform
# transformation = self._screen_transformation * state.transform
self._logger.info('Sate Transform\n' + str(transformation))
if isinstance(item, SvgFormat.Path):
path = item.path_data
if path is not None: # Fixme:
path = path.transform(transformation)
self._update_bounding_box(path)
self._add_to_scene(item.id, path)
elif isinstance(item, SvgFormat.Rect):
path = item.geometry
self._add_to_scene(item.id, path)
####################################################################################################
def count_svg_tags(svg_data):
tag_counter = {}
for line in svg_data.splitlines():
line = line.strip()
if line.startswith('<'):
position = line.find(' ')
tag = line[1:position]
if tag[0].isalpha():
tag_counter.setdefault(tag, 0)
tag_counter[tag] += 1
return tag_counter
####################################################################################################
class TestLine2D(unittest.TestCase):
##############################################
def test(self):
svg_path = find_data_path('svg', 'basic-demo-2.by-hand.svg')
#data = None
data = svg_data
scene_importer = SceneImporter(svg_path, data=data)
scene = scene_importer.scene
interval = Interval2D((20, 120), (20, 120))
self.assertEqual(scene_importer.bounding_box, interval)
tag_counter = count_svg_tags(data)
number_of_items = sum([tag_counter[x] for x in ('path', 'rect')])
self.assertEqual(len(scene_importer), number_of_items)
# for name, item in scene.items():
# print(name, item)
origin = Vector2D(20, 20)
for name in ('path-x', 'path-y', 'path-45'):
self.assertEqual(scene[name].p0, origin)
for name, p0 in (
('rect-0', (20, 20)),
('rect-x1', (40, 20)),
('rect-x2', (80, 20)),
('rect-y1', (20, 40)),
('rect-y2', (20, 80)),
('rect-bisect', (50, 50)),
#
# ('rect-45-2', (50, 50)),
# ('rect-45', (70, 70)),
# ('rect-30', (80, 80)),
# ('rect-60', (90, 90)),
):
self.assertEqual(scene[name].p0, Vector2D(p0))
####################################################################################################
if __name__ == '__main__':
unittest.main()