Compare commits
15 Commits
Author | SHA1 | Date |
---|---|---|
Andrew Port | fcb648b9bb | |
Andrew Port | ec546a71d4 | |
Andrew Port | bc930005c2 | |
Andrew Port | ae9b79e77a | |
Andrew Port | 289ee6ecb4 | |
Andrew Port | 592fe3a525 | |
Andrew Port | 81870e1f85 | |
Andrew Port | 6015a97090 | |
Andrew Port | 788b2b43a2 | |
Andrew Port | b282094b53 | |
Andrew Port | 229773ff9d | |
Kaspar Emanuel | a16a060c27 | |
Sebastian Kuzminsky | e94483510e | |
Sebastian Kuzminsky | 6abda09d1c | |
Andrew Port | 5c73056420 |
|
@ -8,7 +8,7 @@ on:
|
|||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish to TestPyPI
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Set up Python 3
|
||||
|
@ -30,7 +30,7 @@ jobs:
|
|||
--outdir dist/
|
||||
.
|
||||
- name: Publish to Test PyPI
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
skip_existing: true
|
||||
password: ${{ secrets.TESTPYPI_API_TOKEN }}
|
||||
|
|
|
@ -8,7 +8,7 @@ on:
|
|||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish to TestPyPI and PyPI
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Set up Python 3
|
||||
|
@ -30,13 +30,13 @@ jobs:
|
|||
--outdir dist/
|
||||
.
|
||||
- name: Publish to Test PyPI
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
skip_existing: true
|
||||
password: ${{ secrets.TESTPYPI_API_TOKEN }}
|
||||
repository_url: https://test.pypi.org/legacy/
|
||||
- name: Publish to PyPI
|
||||
if: startsWith(github.ref, 'refs/tags')
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
|
|
2
setup.py
2
setup.py
|
@ -3,7 +3,7 @@ import codecs
|
|||
import os
|
||||
|
||||
|
||||
VERSION = '1.6.0'
|
||||
VERSION = '1.6.1'
|
||||
AUTHOR_NAME = 'Andy Port'
|
||||
AUTHOR_EMAIL = 'AndyAPort@gmail.com'
|
||||
GITHUB = 'https://github.com/mathandy/svgpathtools'
|
||||
|
|
|
@ -43,8 +43,8 @@ except NameError:
|
|||
COMMANDS = set('MmZzLlHhVvCcSsQqTtAa')
|
||||
UPPERCASE = set('MZLHVCSQTA')
|
||||
|
||||
COMMAND_RE = re.compile("([MmZzLlHhVvCcSsQqTtAa])")
|
||||
FLOAT_RE = re.compile("[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?")
|
||||
COMMAND_RE = re.compile(r"([MmZzLlHhVvCcSsQqTtAa])")
|
||||
FLOAT_RE = re.compile(r"[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?")
|
||||
|
||||
# Default Parameters ##########################################################
|
||||
|
||||
|
@ -338,9 +338,13 @@ def transform(curve, tf):
|
|||
|
||||
if new_radius.real == 0 or new_radius.imag == 0 :
|
||||
return Line(new_start, new_end)
|
||||
else :
|
||||
else:
|
||||
if tf[0][0] * tf[1][1] >= 0.0:
|
||||
new_sweep = curve.sweep
|
||||
else:
|
||||
new_sweep = not curve.sweep
|
||||
return Arc(new_start, radius=new_radius, rotation=curve.rotation + rot,
|
||||
large_arc=curve.large_arc, sweep=curve.sweep, end=new_end,
|
||||
large_arc=curve.large_arc, sweep=new_sweep, end=new_end,
|
||||
autoscale_radius=True)
|
||||
|
||||
else:
|
||||
|
@ -1394,7 +1398,7 @@ class CubicBezier(object):
|
|||
class Arc(object):
|
||||
def __init__(self, start, radius, rotation, large_arc, sweep, end,
|
||||
autoscale_radius=True):
|
||||
"""
|
||||
r"""
|
||||
This should be thought of as a part of an ellipse connecting two
|
||||
points on that ellipse, start and end.
|
||||
Parameters
|
||||
|
@ -2568,7 +2572,7 @@ class Path(MutableSequence):
|
|||
|
||||
# Shortcuts
|
||||
if len(self._segments) == 0:
|
||||
return None
|
||||
raise ValueError("This path contains no segments!")
|
||||
if pos == 0.0:
|
||||
return self._segments[0].point(pos)
|
||||
if pos == 1.0:
|
||||
|
@ -2585,6 +2589,7 @@ class Path(MutableSequence):
|
|||
segment_end - segment_start)
|
||||
return segment.point(segment_pos)
|
||||
segment_start = segment_end
|
||||
raise RuntimeError("Something has gone wrong. Could not compute Path.point({}) for path {}".format(pos, self))
|
||||
|
||||
def length(self, T0=0, T1=1, error=LENGTH_ERROR, min_depth=LENGTH_MIN_DEPTH):
|
||||
self._calc_lengths(error=error, min_depth=min_depth)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100mm" height="100mm" viewBox="-100 -200 500 500" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
<g id="Sketch" transform="scale(1,-1)">
|
||||
<path id="slot" d="
|
||||
M 0 10
|
||||
L 0 80
|
||||
A 30 30 0 1 0 0 140
|
||||
A 10 10 0 0 1 0 100
|
||||
L 100 100
|
||||
A 10 10 0 1 1 100 140
|
||||
A 30 30 0 0 0 100 80
|
||||
L 100 10
|
||||
A 10 10 0 0 0 90 0
|
||||
L 10 0
|
||||
A 10 10 0 0 0 0 10
|
||||
" stroke="#ff0000" stroke-width="0.35 px"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 665 B |
|
@ -5,11 +5,15 @@ $ python -m unittest test.test_groups.TestGroups.test_group_flatten
|
|||
"""
|
||||
from __future__ import division, absolute_import, print_function
|
||||
import unittest
|
||||
from svgpathtools import Document, SVG_NAMESPACE, parse_path
|
||||
from svgpathtools import Document, SVG_NAMESPACE, parse_path, Line, Arc
|
||||
from os.path import join, dirname
|
||||
import numpy as np
|
||||
|
||||
|
||||
# When an assert fails, show the full error message, don't truncate it.
|
||||
unittest.util._MAX_LENGTH = 999999999
|
||||
|
||||
|
||||
def get_desired_path(name, paths):
|
||||
return next(p for p in paths
|
||||
if p.element.get('{some://testuri}name') == name)
|
||||
|
@ -42,6 +46,22 @@ class TestGroups(unittest.TestCase):
|
|||
self.check_values(tf.dot(v_s), actual.start)
|
||||
self.check_values(tf.dot(v_e), actual.end)
|
||||
|
||||
def test_group_transform(self):
|
||||
# The input svg has a group transform of "scale(1,-1)", which
|
||||
# can mess with Arc sweeps.
|
||||
doc = Document(join(dirname(__file__), 'negative-scale.svg'))
|
||||
path = doc.paths()[0]
|
||||
self.assertEqual(path[0], Line(start=-10j, end=-80j))
|
||||
self.assertEqual(path[1], Arc(start=-80j, radius=(30+30j), rotation=0.0, large_arc=True, sweep=True, end=-140j))
|
||||
self.assertEqual(path[2], Arc(start=-140j, radius=(20+20j), rotation=0.0, large_arc=False, sweep=False, end=-100j))
|
||||
self.assertEqual(path[3], Line(start=-100j, end=(100-100j)))
|
||||
self.assertEqual(path[4], Arc(start=(100-100j), radius=(20+20j), rotation=0.0, large_arc=True, sweep=False, end=(100-140j)))
|
||||
self.assertEqual(path[5], Arc(start=(100-140j), radius=(30+30j), rotation=0.0, large_arc=False, sweep=True, end=(100-80j)))
|
||||
self.assertEqual(path[6], Line(start=(100-80j), end=(100-10j)))
|
||||
self.assertEqual(path[7], Arc(start=(100-10j), radius=(10+10j), rotation=0.0, large_arc=False, sweep=True, end=(90+0j)))
|
||||
self.assertEqual(path[8], Line(start=(90+0j), end=(10+0j)))
|
||||
self.assertEqual(path[9], Arc(start=(10+0j), radius=(10+10j), rotation=0.0, large_arc=False, sweep=True, end=-10j))
|
||||
|
||||
def test_group_flatten(self):
|
||||
# Test the Document.paths() function against the
|
||||
# groups.svg test file.
|
||||
|
|
Loading…
Reference in New Issue