removing paths inside polygon

Hi

I’d like to be able to clip a line so that the portion of it lying outside of a given polygon remains visible and the part that lies inside of the polygon is not visible. What I want is basically the opposite of:

line.set_clip_path(polygon)

which leaves only the part of the line inside the polygon visible. Is this possible?

I know I can just fill the polygon with the background color or something but this gets messy when there are other lines on the plot that don’t need to be clipped.

Thanks,

Andrew

You could just use paths which have holes in them, making the exterior so broad that you wouldn’t notice the edge of the clipping. I’ve put together an example of doing just that:

import matplotlib.pyplot as plt
import matplotlib.path as mpath

import matplotlib.collections as mcol
import numpy as np

import copy

exterior = mpath.Path.unit_rectangle()

exterior = mpath.Path(copy.deepcopy(exterior.vertices),
copy.deepcopy(exterior.codes[:]))

exterior.vertices *= 4
exterior.vertices -= 2

interior = mpath.Path.unit_circle()
interior.vertices = interior.vertices[::-1]

clip_path = mpath.Path(vertices=np.concatenate([exterior.vertices, interior.vertices]),
codes=np.concatenate([exterior.codes, interior.codes]))

star = mpath.Path.unit_regular_star(6)
star.vertices *= 2.6

ax = plt.subplot(321)
col = mcol.PathCollection([clip_path], facecolor=‘yellow’)

ax.add_collection(col)
ax.set_title(‘Clip path’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

ax = plt.subplot(322)
col = mcol.PathCollection([star], facecolor=‘red’)

ax.add_collection(col)
ax.set_title(‘Target polygon’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

ax = plt.subplot2grid((3, 2), (1, 0), colspan=2, rowspan=2)

col = mcol.PathCollection([star])
col.set_clip_path(clip_path, ax.transData)

ax.add_collection(col)

ax.set_title(‘Target polygon clipped by clip_path’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

plt.tight_layout()

plt.show()

clipped.png

There are other options if this doesn’t cut the mustard.

HTH,

···

On 12 March 2013 15:37, Andrew Dawson <dawson@…4308…> wrote:

Hi

I’d like to be able to clip a line so that the portion of it lying outside of a given polygon remains visible and the part that lies inside of the polygon is not visible. What I want is basically the opposite of:

line.set_clip_path(polygon)

which leaves only the part of the line inside the polygon visible. Is this possible?

I know I can just fill the polygon with the background color or something but this gets messy when there are other lines on the plot that don’t need to be clipped.

Thanks,

Andrew


Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester

Wave™: Endpoint Security, Q1 2013 and “remains a good choice” in the

endpoint security space. For insight on selecting the right partner to

tackle endpoint security challenges, access the full report.

http://p.sf.net/sfu/symantec-dev2dev


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

I tried this and although it sort-of works, it doesn’t really do what I need. I tried using this:

import matplotlib.pyplot as plt

import matplotlib.path as mpath

import numpy as np

import copy

create figure and axes

fig = plt.figure(figsize=(6, 6))

ax = fig.add_axes([.1, .1, .8, .8])

ax.set_xlim([-3, 3])

ax.set_ylim([-3, 3])

a circle at the origin with radius 1

circle = plt.Circle((0, 0), 1, transform=ax.transData,

                edgecolor='k', facecolor='none')

from Phil’s example

exterior = mpath.Path.unit_rectangle()

interior = circle.get_path()

exterior = mpath.Path(copy.deepcopy(exterior.vertices),

                  copy.deepcopy(exterior.codes[:]))

interior.vertices = interior.vertices[::-1]

exterior.vertices *= 6

exterior.vertices -= 3

clip_path = mpath.Path(vertices=np.concatenate([exterior.vertices, interior.vertices]),

                   codes=np.concatenate([exterior.codes, interior.codes]))

lines from the origin dividing the axes into 8 sectors

end_coords = [(3, 0), (3, 3), (0, 3), (-3, 3),

          (-3, 0), (-3, -3), (0, -3), (3, -3)]

for x, y in end_coords:

line, = ax.plot((x, 0), (y, 0), color='k')

line.set_clip_path(clip_path, ax.transData)

ax.add_artist(circle)

plt.show()

and the result is the attached image with_clipping.png. You should see that the circle is no longer circular, and also there are weird line width issues. What I want it basically exactly like the attached without_clipping.png but with paths inside the circle removed.

Thanks

clipped.png

with_clipping.png

without_clipping.png

···

On 12 March 2013 16:43, Phil Elson <pelson.pub@…287…> wrote:

You could just use paths which have holes in them, making the exterior so broad that you wouldn’t notice the edge of the clipping. I’ve put together an example of doing just that:

import matplotlib.pyplot as plt
import matplotlib.path as mpath

import matplotlib.collections as mcol
import numpy as np

import copy

exterior = mpath.Path.unit_rectangle()

exterior = mpath.Path(copy.deepcopy(exterior.vertices),
copy.deepcopy(exterior.codes[:]))

exterior.vertices *= 4
exterior.vertices -= 2

interior = mpath.Path.unit_circle()
interior.vertices = interior.vertices[::-1]

clip_path = mpath.Path(vertices=np.concatenate([exterior.vertices, interior.vertices]),
codes=np.concatenate([exterior.codes, interior.codes]))

star = mpath.Path.unit_regular_star(6)
star.vertices *= 2.6

ax = plt.subplot(321)
col = mcol.PathCollection([clip_path], facecolor=‘yellow’)

ax.add_collection(col)
ax.set_title(‘Clip path’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

ax = plt.subplot(322)
col = mcol.PathCollection([star], facecolor=‘red’)

ax.add_collection(col)
ax.set_title(‘Target polygon’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

ax = plt.subplot2grid((3, 2), (1, 0), colspan=2, rowspan=2)

col = mcol.PathCollection([star])
col.set_clip_path(clip_path, ax.transData)

ax.add_collection(col)

ax.set_title(‘Target polygon clipped by clip_path’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

plt.tight_layout()

plt.show()

There are other options if this doesn’t cut the mustard.

HTH,


Dr Andrew Dawson
Atmospheric, Oceanic & Planetary Physics
Clarendon Laboratory
Parks Road
Oxford OX1 3PU, UK
Tel: +44 (0)1865 282438
Email: dawson@…4239…
Web Site: http://www2.physics.ox.ac.uk/contacts/people/dawson

On 12 March 2013 15:37, Andrew Dawson <dawson@…4239…> wrote:

Hi

I’d like to be able to clip a line so that the portion of it lying outside of a given polygon remains visible and the part that lies inside of the polygon is not visible. What I want is basically the opposite of:

line.set_clip_path(polygon)

which leaves only the part of the line inside the polygon visible. Is this possible?

I know I can just fill the polygon with the background color or something but this gets messy when there are other lines on the plot that don’t need to be clipped.

Thanks,

Andrew


Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester

Wave™: Endpoint Security, Q1 2013 and “remains a good choice” in the

endpoint security space. For insight on selecting the right partner to

tackle endpoint security challenges, access the full report.

http://p.sf.net/sfu/symantec-dev2dev


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

That’s really weird. @mdboom, do you have any idea what the difference is when drawing a Path which has a clip path? (I’ve looked at anti-aliasing & snapping without success)

clipped.png

···

On 12 March 2013 17:17, Andrew Dawson <dawson@…4239…> wrote:

I tried this and although it sort-of works, it doesn’t really do what I need. I tried using this:

import matplotlib.pyplot as plt

import matplotlib.path as mpath

import numpy as np

import copy

create figure and axes

fig = plt.figure(figsize=(6, 6))

ax = fig.add_axes([.1, .1, .8, .8])

ax.set_xlim([-3, 3])

ax.set_ylim([-3, 3])

a circle at the origin with radius 1

circle = plt.Circle((0, 0), 1, transform=ax.transData,

                edgecolor='k', facecolor='none')

from Phil’s example

exterior = mpath.Path.unit_rectangle()

interior = circle.get_path()

exterior = mpath.Path(copy.deepcopy(exterior.vertices),

                  copy.deepcopy(exterior.codes[:]))

interior.vertices = interior.vertices[::-1]

exterior.vertices *= 6

exterior.vertices -= 3

clip_path = mpath.Path(vertices=np.concatenate([exterior.vertices, interior.vertices]),

                   codes=np.concatenate([exterior.codes, interior.codes]))

lines from the origin dividing the axes into 8 sectors

end_coords = [(3, 0), (3, 3), (0, 3), (-3, 3),

          (-3, 0), (-3, -3), (0, -3), (3, -3)]

for x, y in end_coords:

line, = ax.plot((x, 0), (y, 0), color='k')
line.set_clip_path(clip_path, ax.transData)

ax.add_artist(circle)

plt.show()

and the result is the attached image with_clipping.png. You should see that the circle is no longer circular, and also there are weird line width issues. What I want it basically exactly like the attached without_clipping.png but with paths inside the circle removed.

Thanks

On 12 March 2013 16:43, Phil Elson <pelson.pub@…287…> wrote:

You could just use paths which have holes in them, making the exterior so broad that you wouldn’t notice the edge of the clipping. I’ve put together an example of doing just that:

import matplotlib.pyplot as plt
import matplotlib.path as mpath

import matplotlib.collections as mcol
import numpy as np

import copy

exterior = mpath.Path.unit_rectangle()

exterior = mpath.Path(copy.deepcopy(exterior.vertices),
copy.deepcopy(exterior.codes[:]))

exterior.vertices *= 4
exterior.vertices -= 2

interior = mpath.Path.unit_circle()
interior.vertices = interior.vertices[::-1]

clip_path = mpath.Path(vertices=np.concatenate([exterior.vertices, interior.vertices]),
codes=np.concatenate([exterior.codes, interior.codes]))

star = mpath.Path.unit_regular_star(6)
star.vertices *= 2.6

ax = plt.subplot(321)
col = mcol.PathCollection([clip_path], facecolor=‘yellow’)

ax.add_collection(col)
ax.set_title(‘Clip path’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

ax = plt.subplot(322)
col = mcol.PathCollection([star], facecolor=‘red’)

ax.add_collection(col)
ax.set_title(‘Target polygon’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

ax = plt.subplot2grid((3, 2), (1, 0), colspan=2, rowspan=2)

col = mcol.PathCollection([star])
col.set_clip_path(clip_path, ax.transData)

ax.add_collection(col)

ax.set_title(‘Target polygon clipped by clip_path’)

ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

plt.tight_layout()

plt.show()

There are other options if this doesn’t cut the mustard.

HTH,

Web Site: http://www2.physics.ox.ac.uk/contacts/people/dawson


Dr Andrew Dawson
Atmospheric, Oceanic & Planetary Physics
Clarendon Laboratory
Parks Road

Oxford OX1 3PU, UK
Tel: +44 (0)1865 282438
Email: dawson@…4239…

On 12 March 2013 15:37, Andrew Dawson <dawson@…4239…> wrote:

Hi

I’d like to be able to clip a line so that the portion of it lying outside of a given polygon remains visible and the part that lies inside of the polygon is not visible. What I want is basically the opposite of:

line.set_clip_path(polygon)

which leaves only the part of the line inside the polygon visible. Is this possible?

I know I can just fill the polygon with the background color or something but this gets messy when there are other lines on the plot that don’t need to be clipped.

Thanks,

Andrew


Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester

Wave™: Endpoint Security, Q1 2013 and “remains a good choice” in the

endpoint security space. For insight on selecting the right partner to

tackle endpoint security challenges, access the full report.

http://p.sf.net/sfu/symantec-dev2dev


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

The reason that circle is no more circle is that simply inverting the
vertices does not always results in a correctly inverted path.
Instead of following line.

interior.vertices = interior.vertices[::-1]

You should use something like below.

interior = mpath.Path(np.concatenate([interior.vertices[-2::-1],
                                      interior.vertices[-1:]]),
                      interior.codes)

It would be good if we have a method to invert a path.

This will give you a circle. But the weird line width issue remains. This
seems to be an Agg issue, and the line width seems to depend on the dpi.
I guess @mdboom nay have some insight on this.

Regards,

-JJ

···

On Wed, Mar 13, 2013 at 2:17 AM, Andrew Dawson <dawson@...4239...> wrote:

You should see that the circle is no longer circular, and also there are
weird line width issues. What I want it basically exactly like the attached
without_clipping.png but with paths inside the circle removed.

Thanks, the clipping is working now. But as you say the weird line width issue still remains for Agg (and png, perhaps that uses Agg, I don’t know…). PDF output looks correct.

···

On 20 March 2013 05:48, Jae-Joon Lee <lee.j.joon@…287…> wrote:


Dr Andrew Dawson
Atmospheric, Oceanic & Planetary Physics
Clarendon Laboratory
Parks Road
Oxford OX1 3PU, UK
Tel: +44 (0)1865 282438
Email: dawson@…4239…
Web Site: http://www2.physics.ox.ac.uk/contacts/people/dawson

On Wed, Mar 13, 2013 at 2:17 AM, Andrew Dawson <dawson@…4239…> wrote:

You should see that the circle is no longer circular, and also there are weird line width issues. What I want it basically exactly like the attached without_clipping.png but with paths inside the circle removed.

The reason that circle is no more circle is that simply inverting the vertices does not always results in a correctly inverted path.

Instead of following line.

You should use something like below.

interior.vertices = interior.vertices[::-1]

interior.codes)

It would be good if we have a method to invert a path.

This will give you a circle. But the weird line width issue remains. This seems to be an Agg issue, and the line width seems to depend on the dpi.

I guess @mdboom nay have some insight on this.

Regards,

-JJ

interior = mpath.Path(np.concatenate([interior.vertices[-2::-1],

interior.vertices[-1:]]),

It's puzzler. I'm looking at it now.

Mike

···

On 03/22/2013 06:33 AM, Andrew Dawson wrote:

Thanks, the clipping is working now. But as you say the weird line width issue still remains for Agg (and png, perhaps that uses Agg, I don't know...). PDF output looks correct.

On 20 March 2013 05:48, Jae-Joon Lee <lee.j.joon@…287… > <mailto:lee.j.joon@…287…>> wrote:

    On Wed, Mar 13, 2013 at 2:17 AM, Andrew Dawson > <dawson@…4239… <mailto:dawson@…4239…>> wrote:

        You should see that the circle is no longer circular, and also
        there are weird line width issues. What I want it basically
        exactly like the attached without_clipping.png but with paths
        inside the circle removed.

    The reason that circle is no more circle is that simply inverting
    the vertices does not always results in a correctly inverted path.
    Instead of following line.

    interior.vertices = interior.vertices[::-1]

    You should use something like below.

    interior = mpath.Path(np.concatenate([interior.vertices[-2::-1],
    interior.vertices[-1:]]),
    interior.codes)

    It would be good if we have a method to invert a path.

    This will give you a circle. But the weird line width issue
    remains. This seems to be an Agg issue, and the line width seems
    to depend on the dpi.
    I guess @mdboom nay have some insight on this.

    Regards,

    -JJ


Dr Andrew Dawson
Atmospheric, Oceanic & Planetary Physics
Clarendon Laboratory
Parks Road
Oxford OX1 3PU, UK
Tel: +44 (0)1865 282438
Email: dawson@…4239… <mailto:dawson@…4239…>
Web Site: http://www2.physics.ox.ac.uk/contacts/people/dawson

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

See https://github.com/matplotlib/matplotlib/pull/1846

···

On 03/22/2013 11:17 AM, Michael Droettboom wrote:

It's puzzler. I'm looking at it now.

Mike

On 03/22/2013 06:33 AM, Andrew Dawson wrote:

Thanks, the clipping is working now. But as you say the weird line width issue still remains for Agg (and png, perhaps that uses Agg, I don't know...). PDF output looks correct.

On 20 March 2013 05:48, Jae-Joon Lee <lee.j.joon@…287… >> <mailto:lee.j.joon@…287…>> wrote:

    On Wed, Mar 13, 2013 at 2:17 AM, Andrew Dawson >> <dawson@…4239… <mailto:dawson@…4239…>> wrote:

        You should see that the circle is no longer circular, and
        also there are weird line width issues. What I want it
        basically exactly like the attached without_clipping.png but
        with paths inside the circle removed.

    The reason that circle is no more circle is that simply inverting
    the vertices does not always results in a correctly inverted path.
    Instead of following line.

    interior.vertices = interior.vertices[::-1]

    You should use something like below.

    interior = mpath.Path(np.concatenate([interior.vertices[-2::-1],
    interior.vertices[-1:]]),
    interior.codes)

    It would be good if we have a method to invert a path.

    This will give you a circle. But the weird line width issue
    remains. This seems to be an Agg issue, and the line width seems
    to depend on the dpi.
    I guess @mdboom nay have some insight on this.

    Regards,

    -JJ


Dr Andrew Dawson
Atmospheric, Oceanic & Planetary Physics
Clarendon Laboratory
Parks Road
Oxford OX1 3PU, UK
Tel: +44 (0)1865 282438
Email: dawson@…4239… <mailto:dawson@…4239…>
Web Site: http://www2.physics.ox.ac.uk/contacts/people/dawson

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users