How to draw a collection of oriented triangles ?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to draw a collection of oriented triangles ?

Nicolas P. Rougier

I would like to draw several triangles (same size, same color) with different individual orientations.
Scatter plot does not allow to specify individual orientations and I've a hard time with PatchCollection.

What would be the easiest way ? Is there an example somewhere around by any chance ?


Nicolas
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to draw a collection of oriented triangles ?

Joshua Klein

I’ve had great success using PathPatch and AffineTransform for this purpose:

from matplotlib import pyplot as plt
from matplotlib.path import Path
from matplotlib.transforms import Affine2D
from matplotlib.patches import PathPatch

unit_triangle = Path.unit_regular_polygon(3)

def make_triangle(x, y, rot_deg, color, scale):
    path = Path(unit_triangle.vertices * scale, unit_triangle.codes)
    trans = Affine2D().translate(x, y).rotate_deg_around(x, y, rot_deg)
    t_path = path.transformed(trans)
    patch = PathPatch(t_path, facecolor=color)  
    return patch

ax = plt.gca()

for x, y, rot_deg in [(1, 1, 90), (2, 2, 45), (-1, 1, 128)]:
    patch = make_triangle(x, y, rot_deg, "blue", 1)
    ax.add_patch(patch)

# Patches don't automatically change the visible range of the axes like scatter does.
ax.autoscale()

On Sat, Nov 26, 2016 at 9:21 AM, Nicolas P. Rougier <[hidden email]> wrote:

I would like to draw several triangles (same size, same color) with different individual orientations.
Scatter plot does not allow to specify individual orientations and I've a hard time with PatchCollection.

What would be the easiest way ? Is there an example somewhere around by any chance ?


Nicolas
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to draw a collection of oriented triangles ?

Nicolas P. Rougier

Thank you Joshua, I'll start from your code. My other problem is that I also need to update rotation and position (for an animation). Hope this will work with patch collection and updating individual transform.

Nicolas

> On 26 Nov 2016, at 15:53, Joshua Klein <[hidden email]> wrote:
>
> I’ve had great success using PathPatch and AffineTransform for this purpose:
>
> from matplotlib import pyplot as
>  plt
>
> from matplotlib.path import
>  Path
>
> from matplotlib.transforms import
>  Affine2D
>
> from matplotlib.patches import
>  PathPatch
>
> unit_triangle = Path.unit_regular_polygon(
> 3
> )
>
>
> def make_triangle(x, y, rot_deg, color, scale):
>
>     path = Path(unit_triangle.vertices * scale, unit_triangle.codes)
>     trans = Affine2D().translate(x, y).rotate_deg_around(x, y, rot_deg)
>     t_path = path.transformed(trans)
>     patch = PathPatch(t_path, facecolor=color)  
>    
> return
>  patch
>
> ax = plt.gca()
>
>
> for x, y, rot_deg in [(1, 1, 90), (2, 2, 45), (-1, 1, 128
> )]:
>     patch = make_triangle(x, y, rot_deg,
> "blue", 1
> )
>     ax.add_patch(patch)
>
>
> # Patches don't automatically change the visible range of the axes like scatter does.
>
> ax.autoscale()
>
>
> On Sat, Nov 26, 2016 at 9:21 AM, Nicolas P. Rougier <[hidden email]> wrote:
>
> I would like to draw several triangles (same size, same color) with different individual orientations.
> Scatter plot does not allow to specify individual orientations and I've a hard time with PatchCollection.
>
> What would be the easiest way ? Is there an example somewhere around by any chance ?
>
>
> Nicolas
> _______________________________________________
> Matplotlib-users mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/matplotlib-users
>

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to draw a collection of oriented triangles ?

Joshua Klein

I don’t think my code ever directly works with a PatchCollection object, just individual patches which possess distinct properties. Here’s an example using animations:

import matplotlib
matplotlib.use("Tkagg")
from matplotlib import pyplot as plt
from matplotlib.path import Path
from matplotlib.transforms import Affine2D
from matplotlib.patches import PathPatch
from matplotlib import animation
import numpy as np

unit_triangle = Path.unit_regular_polygon(3)

def make_triangle(x, y, rot_deg, color, scale):
    path = Path(unit_triangle.vertices * scale, unit_triangle.codes)
    trans = Affine2D().translate(x, y).rotate_deg_around(x, y, rot_deg)
    t_path = path.transformed(trans)
    patch = PathPatch(t_path, facecolor=color)  
    return patch

triangles = [(1, 1, 90), (2, 2, 45), (-1, 1, 128)]
patches = []

def step_fn(i):
    next_step = []
    # Random walk update each triangle's position
    for tri in triangles:
        x = tri[0] + np.random.random() - 0.5
        y = tri[1] + np.random.random() - 0.5
        rot = tri[2] + (np.random.random() - 0.5) * 45
        next_step.append((x, y, rot))
    triangles[:] = next_step

    # Remove the old patches
    while patches:
        patch = patches.pop()
        patch.remove()

    # Add the new patches
    patches[:] = [make_triangle(x, y, rot_deg, "blue", 0.2) for x, y, rot_deg in triangles]
    for patch in patches:
        plt.gca().add_patch(patch)
    plt.autoscale()

fig = plt.figure()
a = animation.FuncAnimation(fig, step_fn, blit=False, interval=10)

plt.show()

On Sat, Nov 26, 2016 at 12:20 PM, Nicolas P. Rougier <[hidden email]> wrote:

Thank you Joshua, I'll start from your code. My other problem is that I also need to update rotation and position (for an animation). Hope this will work with patch collection and updating individual transform.

Nicolas

> On 26 Nov 2016, at 15:53, Joshua Klein <[hidden email]> wrote:
>
> I’ve had great success using PathPatch and AffineTransform for this purpose:
>
> from matplotlib import pyplot as
>  plt
>
> from matplotlib.path import
>  Path
>
> from matplotlib.transforms import
>  Affine2D
>
> from matplotlib.patches import
>  PathPatch
>
> unit_triangle = Path.unit_regular_polygon(
> 3
> )
>
>
> def make_triangle(x, y, rot_deg, color, scale):
>
>     path = Path(unit_triangle.vertices * scale, unit_triangle.codes)
>     trans = Affine2D().translate(x, y).rotate_deg_around(x, y, rot_deg)
>     t_path = path.transformed(trans)
>     patch = PathPatch(t_path, facecolor=color)
>
> return
>  patch
>
> ax = plt.gca()
>
>
> for x, y, rot_deg in [(1, 1, 90), (2, 2, 45), (-1, 1, 128
> )]:
>     patch = make_triangle(x, y, rot_deg,
> "blue", 1
> )
>     ax.add_patch(patch)
>
>
> # Patches don't automatically change the visible range of the axes like scatter does.
>
> ax.autoscale()
>
>
> On Sat, Nov 26, 2016 at 9:21 AM, Nicolas P. Rougier <[hidden email]> wrote:
>
> I would like to draw several triangles (same size, same color) with different individual orientations.
> Scatter plot does not allow to specify individual orientations and I've a hard time with PatchCollection.
>
> What would be the easiest way ? Is there an example somewhere around by any chance ?
>
>
> Nicolas
> _______________________________________________
> Matplotlib-users mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/matplotlib-users
>



_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to draw a collection of oriented triangles ?

Nicolas P. Rougier

Thanks. I end up using a PathCollection with a single path. The advantage is that you can split a path into several disconnected paths but the update can still be made at once (scaling, translating and rotation). This makes things relatively fast.

Code is available at: https://gist.github.com/rougier/b82fe08f1840f4277b52fb8bfbdb3cc7



Nicolas


> On 26 Nov 2016, at 21:47, Joshua Klein <[hidden email]> wrote:
>
> I don’t think my code ever directly works with a PatchCollection object, just individual patches which possess distinct properties. Here’s an example using animations:
>
> import
>  matplotlib
> matplotlib.use(
> "Tkagg"
> )
>
> from matplotlib import pyplot as
>  plt
>
> from matplotlib.path import
>  Path
>
> from matplotlib.transforms import
>  Affine2D
>
> from matplotlib.patches import
>  PathPatch
>
> from matplotlib import
>  animation
>
> import numpy as
>  np
>
> unit_triangle = Path.unit_regular_polygon(
> 3
> )
>
>
> def make_triangle(x, y, rot_deg, color, scale):
>
>     path = Path(unit_triangle.vertices * scale, unit_triangle.codes)
>     trans = Affine2D().translate(x, y).rotate_deg_around(x, y, rot_deg)
>     t_path = path.transformed(trans)
>     patch = PathPatch(t_path, facecolor=color)  
>    
> return
>  patch
>
> triangles = [(
> 1, 1, 90), (2, 2, 45), (-1, 1, 128
> )]
> patches = []
>
>
> def step_fn(i):
>
>     next_step = []
>    
> # Random walk update each triangle's position
>
>    
> for tri in
>  triangles:
>         x = tri[
> 0] + np.random.random() - 0.5
>
>         y = tri[
> 1] + np.random.random() - 0.5
>
>         rot = tri[
> 2] + (np.random.random() - 0.5) * 45
>
>         next_step.append((x, y, rot))
>     triangles[:] = next_step
>
>    
> # Remove the old patches
>
>    
> while
>  patches:
>         patch = patches.pop()
>         patch.remove()
>
>    
> # Add the new patches
>
>     patches[:] = [make_triangle(x, y, rot_deg,
> "blue", 0.2) for x, y, rot_deg in
>  triangles]
>    
> for patch in
>  patches:
>         plt.gca().add_patch(patch)
>     plt.autoscale()
>
> fig = plt.figure()
> a = animation.FuncAnimation(fig, step_fn, blit=
> False, interval=10
> )
>
> plt.show()
>
>
> On Sat, Nov 26, 2016 at 12:20 PM, Nicolas P. Rougier <[hidden email]> wrote:
>
> Thank you Joshua, I'll start from your code. My other problem is that I also need to update rotation and position (for an animation). Hope this will work with patch collection and updating individual transform.
>
> Nicolas
>
> > On 26 Nov 2016, at 15:53, Joshua Klein <[hidden email]> wrote:
> >
> > I’ve had great success using PathPatch and AffineTransform for this purpose:
> >
> > from matplotlib import pyplot as
> >  plt
> >
> > from matplotlib.path import
> >  Path
> >
> > from matplotlib.transforms import
> >  Affine2D
> >
> > from matplotlib.patches import
> >  PathPatch
> >
> > unit_triangle = Path.unit_regular_polygon(
> > 3
> > )
> >
> >
> > def make_triangle(x, y, rot_deg, color, scale):
> >
> >     path = Path(unit_triangle.vertices * scale, unit_triangle.codes)
> >     trans = Affine2D().translate(x, y).rotate_deg_around(x, y, rot_deg)
> >     t_path = path.transformed(trans)
> >     patch = PathPatch(t_path, facecolor=color)
> >
> > return
> >  patch
> >
> > ax = plt.gca()
> >
> >
> > for x, y, rot_deg in [(1, 1, 90), (2, 2, 45), (-1, 1, 128
> > )]:
> >     patch = make_triangle(x, y, rot_deg,
> > "blue", 1
> > )
> >     ax.add_patch(patch)
> >
> >
> > # Patches don't automatically change the visible range of the axes like scatter does.
> >
> > ax.autoscale()
> >
> >
> > On Sat, Nov 26, 2016 at 9:21 AM, Nicolas P. Rougier <[hidden email]> wrote:
> >
> > I would like to draw several triangles (same size, same color) with different individual orientations.
> > Scatter plot does not allow to specify individual orientations and I've a hard time with PatchCollection.
> >
> > What would be the easiest way ? Is there an example somewhere around by any chance ?
> >
> >
> > Nicolas
> > _______________________________________________
> > Matplotlib-users mailing list
> > [hidden email]
> > https://mail.python.org/mailman/listinfo/matplotlib-users
> >
>
>

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Loading...