parent
bf85efe4b5
commit
0c682bf4d8
93
README.ipynb
93
README.ipynb
|
@ -86,7 +86,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 21,
|
"execution_count": 16,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": true
|
||||||
},
|
},
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 22,
|
"execution_count": 17,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 23,
|
"execution_count": 18,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -224,7 +224,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 24,
|
"execution_count": 19,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -265,7 +265,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 25,
|
"execution_count": 20,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -300,7 +300,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 26,
|
"execution_count": 21,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -363,7 +363,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 27,
|
"execution_count": 22,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -411,7 +411,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 28,
|
"execution_count": 23,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -466,7 +466,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 29,
|
"execution_count": 24,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -509,7 +509,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 30,
|
"execution_count": 25,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -551,7 +551,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 31,
|
"execution_count": 26,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -606,7 +606,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 32,
|
"execution_count": 27,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": false
|
"collapsed": false
|
||||||
},
|
},
|
||||||
|
@ -635,65 +635,58 @@
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"### An Advanced Application: Offsetting Bezier Curves\n",
|
"### An Advanced Application: Offsetting Paths\n",
|
||||||
"Here we'll find the [offset curve](https://en.wikipedia.org/wiki/Parallel_curve) for a few Bezier cubics."
|
"Here we'll find the [offset curve](https://en.wikipedia.org/wiki/Parallel_curve) for a few paths."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 33,
|
"execution_count": 28,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"collapsed": true
|
"collapsed": false
|
||||||
},
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def display_offset_curve(bezpath, offset_distance, steps=1000,\n",
|
"from svgpathtools import parse_path, Line, Path, wsvg\n",
|
||||||
" stripe_width=3, stripe_colors='ygb',\n",
|
"def offset_curve(path, offset_distance, steps=1000):\n",
|
||||||
" name='offsetcurves.svg', show_normal_line=True):\n",
|
" \"\"\"Takes in a Path object, `path`, and a distance,\n",
|
||||||
" \"\"\"Takes in a path of bezier curves, `bezpath`, and a distance,\n",
|
" `offset_distance`, and outputs an piecewise-linear approximation \n",
|
||||||
" `offset_distance`, and displays the 'parallel' offset curve by placing a\n",
|
" of the 'parallel' offset curve.\"\"\"\n",
|
||||||
" dot at a distance of `offset_distance` away at each step.\"\"\"\n",
|
|
||||||
" nls = []\n",
|
" nls = []\n",
|
||||||
" nodes = []\n",
|
" for seg in path:\n",
|
||||||
" line_colors = ''\n",
|
|
||||||
" node_colors = ''\n",
|
|
||||||
"\n",
|
|
||||||
" for bez in bezpath:\n",
|
|
||||||
" ct = 1\n",
|
" ct = 1\n",
|
||||||
" for k in range(steps):\n",
|
" for k in range(steps):\n",
|
||||||
" t = k / steps\n",
|
" t = k / steps\n",
|
||||||
" nl = Line(bez.point(t),\n",
|
" offset_vector = offset_distance * seg.normal(t)\n",
|
||||||
" bez.point(t) + offset_distance * bez.normal(t))\n",
|
" nl = Line(seg.point(t), seg.point(t) + offset_vector)\n",
|
||||||
" nls.append(nl)\n",
|
" nls.append(nl)\n",
|
||||||
" line_colors += stripe_colors[ct % 3]\n",
|
" connect_the_dots = [Line(nls[k].end, nls[k+1].end) for k in range(len(nls)-1)]\n",
|
||||||
" if not (k % stripe_width):\n",
|
" if path.isclosed():\n",
|
||||||
" ct += 1\n",
|
" connect_the_dots.append(Line(nls[-1].end, nls[0].end))\n",
|
||||||
" nodes.append(bez.point(t))\n",
|
" offset_path = Path(*connect_the_dots)\n",
|
||||||
" nodes.append(nl.end)\n",
|
" return offset_path\n",
|
||||||
" node_colors += 'kr'\n",
|
|
||||||
" # nls.reverse()\n",
|
|
||||||
" if show_normal_line:\n",
|
|
||||||
" wsvg([bezpath] + nls, 'k' + line_colors,\n",
|
|
||||||
" nodes=nodes, node_colors=node_colors,\n",
|
|
||||||
" filename=name)\n",
|
|
||||||
" else:\n",
|
|
||||||
" wsvg(bezpath, 'k',\n",
|
|
||||||
" nodes=nodes, node_colors=node_colors,\n",
|
|
||||||
" filename=name)\n",
|
|
||||||
"\n",
|
"\n",
|
||||||
"bez1 = parse_path(\"m 288,600 c -52,-28 -42,-61 0,-97 \")[0]\n",
|
"# Examples:\n",
|
||||||
"bez2 = parse_path(\"M 151,395 C 407,485 726.17662,160 634,339\")[0]\n",
|
"path1 = parse_path(\"m 288,600 c -52,-28 -42,-61 0,-97 \")\n",
|
||||||
"bez3 = parse_path(\"m 117,695 c 237,-7 -103,-146 457,0\")[0]\n",
|
"path2 = parse_path(\"M 151,395 C 407,485 726.17662,160 634,339\").translated(300)\n",
|
||||||
"path = Path(bez1, bez2.translated(300), bez3.translated(500+400j))\n",
|
"path3 = parse_path(\"m 117,695 c 237,-7 -103,-146 457,0\").translated(500+400j)\n",
|
||||||
|
"paths = [path1, path2, path3]\n",
|
||||||
"\n",
|
"\n",
|
||||||
"display_offset_curve(path, 500)"
|
"offset_distances = [10*k for k in range(1,51)]\n",
|
||||||
|
"offset_paths = []\n",
|
||||||
|
"for path in paths:\n",
|
||||||
|
" for distances in offset_distances:\n",
|
||||||
|
" offset_paths.append(offset_curve(path, distances))\n",
|
||||||
|
"\n",
|
||||||
|
"# Note: This will take a few moments\n",
|
||||||
|
"wsvg(paths + offset_paths, 'g'*len(paths) + 'r'*len(offset_paths), filename='offset_curves.svg')"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"![offsetcurves.svg](offsetcurves.svg)"
|
"![offset_curves.svg](offset_curves.svg)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
74
README.rst
74
README.rst
|
@ -453,7 +453,7 @@ Translations (shifts), reversing orientation, and normal vectors
|
||||||
'bgpkgp', nodes=[b.point(t), br.point(t)], filename='vectorframes.svg',
|
'bgpkgp', nodes=[b.point(t), br.point(t)], filename='vectorframes.svg',
|
||||||
text=["b's tangent", "br's tangent"], text_path=[tangent_line, tangent_line_r])
|
text=["b's tangent", "br's tangent"], text_path=[tangent_line, tangent_line_r])
|
||||||
|
|
||||||
.. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/test.svg
|
.. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/vectorframes.svg
|
||||||
:alt: vectorframes.svg
|
:alt: vectorframes.svg
|
||||||
|
|
||||||
vectorframes.svg
|
vectorframes.svg
|
||||||
|
@ -554,60 +554,52 @@ Intersections between Bezier curves
|
||||||
|
|
||||||
output\_intersections.svg
|
output\_intersections.svg
|
||||||
|
|
||||||
An Advanced Application: Offsetting Bezier Curves
|
An Advanced Application: Offsetting Paths
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Here we'll find the `offset
|
Here we'll find the `offset
|
||||||
curve <https://en.wikipedia.org/wiki/Parallel_curve>`__ for a few Bezier
|
curve <https://en.wikipedia.org/wiki/Parallel_curve>`__ for a few paths.
|
||||||
cubics.
|
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
def display_offset_curve(bezpath, offset_distance, steps=1000,
|
from svgpathtools import parse_path, Line, Path, wsvg
|
||||||
stripe_width=3, stripe_colors='ygb',
|
def offset_curve(path, offset_distance, steps=1000):
|
||||||
name='offsetcurves.svg', show_normal_line=True):
|
"""Takes in a Path object, `path`, and a distance,
|
||||||
"""Takes in a path of bezier curves, `bezpath`, and a distance,
|
`offset_distance`, and outputs an piecewise-linear approximation
|
||||||
`offset_distance`, and displays the 'parallel' offset curve by placing a
|
of the 'parallel' offset curve."""
|
||||||
dot at a distance of `offset_distance` away at each step."""
|
|
||||||
nls = []
|
nls = []
|
||||||
nodes = []
|
for seg in path:
|
||||||
line_colors = ''
|
|
||||||
node_colors = ''
|
|
||||||
|
|
||||||
for bez in bezpath:
|
|
||||||
ct = 1
|
ct = 1
|
||||||
for k in range(steps):
|
for k in range(steps):
|
||||||
t = k / steps
|
t = k / steps
|
||||||
nl = Line(bez.point(t),
|
offset_vector = offset_distance * seg.normal(t)
|
||||||
bez.point(t) + offset_distance * bez.normal(t))
|
nl = Line(seg.point(t), seg.point(t) + offset_vector)
|
||||||
nls.append(nl)
|
nls.append(nl)
|
||||||
line_colors += stripe_colors[ct % 3]
|
connect_the_dots = [Line(nls[k].end, nls[k+1].end) for k in range(len(nls)-1)]
|
||||||
if not (k % stripe_width):
|
if path.isclosed():
|
||||||
ct += 1
|
connect_the_dots.append(Line(nls[-1].end, nls[0].end))
|
||||||
nodes.append(bez.point(t))
|
offset_path = Path(*connect_the_dots)
|
||||||
nodes.append(nl.end)
|
return offset_path
|
||||||
node_colors += 'kr'
|
|
||||||
# nls.reverse()
|
|
||||||
if show_normal_line:
|
|
||||||
wsvg([bezpath] + nls, 'k' + line_colors,
|
|
||||||
nodes=nodes, node_colors=node_colors,
|
|
||||||
filename=name)
|
|
||||||
else:
|
|
||||||
wsvg(bezpath, 'k',
|
|
||||||
nodes=nodes, node_colors=node_colors,
|
|
||||||
filename=name)
|
|
||||||
|
|
||||||
bez1 = parse_path("m 288,600 c -52,-28 -42,-61 0,-97 ")[0]
|
# Examples:
|
||||||
bez2 = parse_path("M 151,395 C 407,485 726.17662,160 634,339")[0]
|
path1 = parse_path("m 288,600 c -52,-28 -42,-61 0,-97 ")
|
||||||
bez3 = parse_path("m 117,695 c 237,-7 -103,-146 457,0")[0]
|
path2 = parse_path("M 151,395 C 407,485 726.17662,160 634,339").translated(300)
|
||||||
path = Path(bez1, bez2.translated(300), bez3.translated(500+400j))
|
path3 = parse_path("m 117,695 c 237,-7 -103,-146 457,0").translated(500+400j)
|
||||||
|
paths = [path1, path2, path3]
|
||||||
|
|
||||||
display_offset_curve(path, 500)
|
offset_distances = [10*k for k in range(1,51)]
|
||||||
|
offset_paths = []
|
||||||
|
for path in paths:
|
||||||
|
for distances in offset_distances:
|
||||||
|
offset_paths.append(offset_curve(path, distances))
|
||||||
|
|
||||||
.. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/offsetcurves.svg
|
# Note: This will take a few moments
|
||||||
:alt: offsetcurves.svg
|
wsvg(paths + offset_paths, 'g'*len(paths) + 'r'*len(offset_paths), filename='offset_curves.svg')
|
||||||
|
|
||||||
offsetcurves.svg
|
.. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/offset_curves.svg
|
||||||
|
:alt: offset\_curves.svg
|
||||||
|
|
||||||
|
offset\_curves.svg
|
||||||
|
|
||||||
Compatibility Notes for users of svg.path (v2.0)
|
Compatibility Notes for users of svg.path (v2.0)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 4.3 MiB |
9005
offsetcurves.svg
9005
offsetcurves.svg
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 835 KiB |
Loading…
Reference in New Issue