Skip to content

Commit

Permalink
improved README curve offsetting example
Browse files Browse the repository at this point in the history
  • Loading branch information
mathandy committed Jul 11, 2016
1 parent bf85efe commit 0c682bf
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 9,102 deletions.
97 changes: 45 additions & 52 deletions README.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 16,
"metadata": {
"collapsed": true
},
Expand All @@ -97,7 +97,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 17,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -147,7 +147,7 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 18,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -224,7 +224,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 19,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -265,7 +265,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 20,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -300,7 +300,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 21,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -363,7 +363,7 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 22,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -411,7 +411,7 @@
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 23,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -466,7 +466,7 @@
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 24,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -509,7 +509,7 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 25,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -551,7 +551,7 @@
},
{
"cell_type": "code",
"execution_count": 31,
"execution_count": 26,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -606,7 +606,7 @@
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": 27,
"metadata": {
"collapsed": false
},
Expand Down Expand Up @@ -635,65 +635,58 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### An Advanced Application: Offsetting Bezier Curves\n",
"Here we'll find the [offset curve](https://en.wikipedia.org/wiki/Parallel_curve) for a few Bezier cubics."
"### An Advanced Application: Offsetting Paths\n",
"Here we'll find the [offset curve](https://en.wikipedia.org/wiki/Parallel_curve) for a few paths."
]
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": 28,
"metadata": {
"collapsed": true
"collapsed": false
},
"outputs": [],
"source": [
"def display_offset_curve(bezpath, offset_distance, steps=1000,\n",
" stripe_width=3, stripe_colors='ygb',\n",
" name='offsetcurves.svg', show_normal_line=True):\n",
" \"\"\"Takes in a path of bezier curves, `bezpath`, and a distance,\n",
" `offset_distance`, and displays the 'parallel' offset curve by placing a\n",
" dot at a distance of `offset_distance` away at each step.\"\"\"\n",
"from svgpathtools import parse_path, Line, Path, wsvg\n",
"def offset_curve(path, offset_distance, steps=1000):\n",
" \"\"\"Takes in a Path object, `path`, and a distance,\n",
" `offset_distance`, and outputs an piecewise-linear approximation \n",
" of the 'parallel' offset curve.\"\"\"\n",
" nls = []\n",
" nodes = []\n",
" line_colors = ''\n",
" node_colors = ''\n",
"\n",
" for bez in bezpath:\n",
" for seg in path:\n",
" ct = 1\n",
" for k in range(steps):\n",
" t = k / steps\n",
" nl = Line(bez.point(t),\n",
" bez.point(t) + offset_distance * bez.normal(t))\n",
" offset_vector = offset_distance * seg.normal(t)\n",
" nl = Line(seg.point(t), seg.point(t) + offset_vector)\n",
" nls.append(nl)\n",
" line_colors += stripe_colors[ct % 3]\n",
" if not (k % stripe_width):\n",
" ct += 1\n",
" nodes.append(bez.point(t))\n",
" nodes.append(nl.end)\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",
"bez1 = parse_path(\"m 288,600 c -52,-28 -42,-61 0,-97 \")[0]\n",
"bez2 = parse_path(\"M 151,395 C 407,485 726.17662,160 634,339\")[0]\n",
"bez3 = parse_path(\"m 117,695 c 237,-7 -103,-146 457,0\")[0]\n",
"path = Path(bez1, bez2.translated(300), bez3.translated(500+400j))\n",
"\n",
"display_offset_curve(path, 500)"
" connect_the_dots = [Line(nls[k].end, nls[k+1].end) for k in range(len(nls)-1)]\n",
" if path.isclosed():\n",
" connect_the_dots.append(Line(nls[-1].end, nls[0].end))\n",
" offset_path = Path(*connect_the_dots)\n",
" return offset_path\n",
"\n",
"# Examples:\n",
"path1 = parse_path(\"m 288,600 c -52,-28 -42,-61 0,-97 \")\n",
"path2 = parse_path(\"M 151,395 C 407,485 726.17662,160 634,339\").translated(300)\n",
"path3 = parse_path(\"m 117,695 c 237,-7 -103,-146 457,0\").translated(500+400j)\n",
"paths = [path1, path2, path3]\n",
"\n",
"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",
"metadata": {},
"source": [
"![offsetcurves.svg](offsetcurves.svg)"
"![offset_curves.svg](offset_curves.svg)"
]
},
{
Expand Down
82 changes: 37 additions & 45 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ Translations (shifts), reversing orientation, and normal vectors
'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])
.. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/test.svg
.. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/vectorframes.svg
:alt: vectorframes.svg

vectorframes.svg
Expand Down Expand Up @@ -554,60 +554,52 @@ Intersections between Bezier curves

output\_intersections.svg

An Advanced Application: Offsetting Bezier Curves
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An Advanced Application: Offsetting Paths
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Here we'll find the `offset
curve <https://en.wikipedia.org/wiki/Parallel_curve>`__ for a few Bezier
cubics.
curve <https://en.wikipedia.org/wiki/Parallel_curve>`__ for a few paths.

.. code:: python
def display_offset_curve(bezpath, offset_distance, steps=1000,
stripe_width=3, stripe_colors='ygb',
name='offsetcurves.svg', show_normal_line=True):
"""Takes in a path of bezier curves, `bezpath`, and a distance,
`offset_distance`, and displays the 'parallel' offset curve by placing a
dot at a distance of `offset_distance` away at each step."""
from svgpathtools import parse_path, Line, Path, wsvg
def offset_curve(path, offset_distance, steps=1000):
"""Takes in a Path object, `path`, and a distance,
`offset_distance`, and outputs an piecewise-linear approximation
of the 'parallel' offset curve."""
nls = []
nodes = []
line_colors = ''
node_colors = ''
for bez in bezpath:
for seg in path:
ct = 1
for k in range(steps):
t = k / steps
nl = Line(bez.point(t),
bez.point(t) + offset_distance * bez.normal(t))
offset_vector = offset_distance * seg.normal(t)
nl = Line(seg.point(t), seg.point(t) + offset_vector)
nls.append(nl)
line_colors += stripe_colors[ct % 3]
if not (k % stripe_width):
ct += 1
nodes.append(bez.point(t))
nodes.append(nl.end)
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]
bez2 = parse_path("M 151,395 C 407,485 726.17662,160 634,339")[0]
bez3 = parse_path("m 117,695 c 237,-7 -103,-146 457,0")[0]
path = Path(bez1, bez2.translated(300), bez3.translated(500+400j))
display_offset_curve(path, 500)
.. figure:: https://cdn.rawgit.com/mathandy/svgpathtools/master/offsetcurves.svg
:alt: offsetcurves.svg

offsetcurves.svg
connect_the_dots = [Line(nls[k].end, nls[k+1].end) for k in range(len(nls)-1)]
if path.isclosed():
connect_the_dots.append(Line(nls[-1].end, nls[0].end))
offset_path = Path(*connect_the_dots)
return offset_path
# Examples:
path1 = parse_path("m 288,600 c -52,-28 -42,-61 0,-97 ")
path2 = parse_path("M 151,395 C 407,485 726.17662,160 634,339").translated(300)
path3 = parse_path("m 117,695 c 237,-7 -103,-146 457,0").translated(500+400j)
paths = [path1, path2, path3]
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))
# Note: This will take a few moments
wsvg(paths + offset_paths, 'g'*len(paths) + 'r'*len(offset_paths), filename='offset_curves.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)
------------------------------------------------
Expand Down
157 changes: 157 additions & 0 deletions offset_curves.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0c682bf

Please sign in to comment.