Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Issue detecting paths intersection with Path.intersects_path #6076

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
5 tasks done
afvincent opened this issue Feb 29, 2016 · 3 comments
Closed
5 tasks done

Issue detecting paths intersection with Path.intersects_path #6076

afvincent opened this issue Feb 29, 2016 · 3 comments
Assignees
Labels
status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action topic: path handling

Comments

@afvincent
Copy link
Contributor

Short Description

I think there may be a bug in the Path.intersects_path method, in path module:

Signature: Path.intersects_path(self, other, filled=True)
Docstring:
Returns *True* if this path intersects another given path.

*filled*, when True, treats the paths as if they were filled.
That is, if one path completely encloses the other,
:meth:`intersects_path` will return True.
File:      ~/anaconda/lib/python2.7/site-packages/matplotlib/path.py
Type:      instancemethod

Playing with it, I encountered some cases where this method answers that the two paths are not intersecting, while after plotting them, they do (see the example script and picture below). I still didn't have time to look into further (especially the C++ code that is wrapped by the method), but it seems to me that this behavior is not correct, is it?

Details

  • Matplotlib version, Python version and Platform (Windows, OSX, Linux ...)

Matplotlib 1.5.1, with Python 2.7.11 (and IPython 4.0.1), on Linux (CentOS 7 or Manjaro)

  • How did you install Matplotlib and Python (pip, anaconda, from source ...)

Anaconda 2.4.0 (64-bit)

  • If possible please supply a Short, Self Contained, Correct, Example
    that demonstrates the issue i.e a small piece of code which reproduces the issue
    and can be run with out any other (or as few as possible) external dependencies.
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch
from matplotlib.path import Path

cubic_bezier_codes = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4]

def plot_ctrls(verts, ax, label='',
               ls='--', marker='o', ms=5, lw=1, alpha=0.6, color='Gray'):
    """Plot the control points of a Bezier curve (debugging purpose)
    """
    ax.plot(*zip(*verts), ls=ls, lw=lw, color=color, ms=ms, marker=marker,
            alpha=alpha, label=label)
    return ax

# For your viewing pleasure when plotting
detection_color = {True: "OliveDrab", False: "Crimson"}

if __name__ == "__main__":
    plt.ion()

    # A dummy path to play with
    verts_1 = [(0.5, 0.01), (0.21, 0.99), (0.99, 0.8), (0.99, 0.99)]
    path_1 = Path(verts_1, cubic_bezier_codes)

    # A path that does intersect with path_1 but for which the ad-hoc test
    # method fails
    verts_2a = [(0.5, 0.8), (0.5, 0.7), (0.6, 0.75), (0.56, 0.7)]
    path_2a = Path(verts_2a, cubic_bezier_codes)

    # Decreasing a bit the y-value of the last control point leads to a
    # correct detection of path intersecting.
    verts_2b = [(0.5, 0.8), (0.5, 0.7), (0.6, 0.75), (0.56, 0.6)]
    path_2b = Path(verts_2b, cubic_bezier_codes)

    # Plot everything to be sure
    fig, (axA, axB) = plt.subplots(ncols=2, sharex=True, sharey=True)
    title_prefix = "path_1.intersects_path(path_2):\n"
    for ax, p1, p2 in [(axA, path_1, path_2a), (axB, path_1, path_2b)]:
        # Detect if the two paths intersect
        detection = p1.intersects_path(p2)
        ax.set_title(title_prefix + "{}".format(detection))

        # Plot the two paths
        patch_1 = PathPatch(p1, lw=2, fc='none', ec='CornFlowerBlue')
        pc1 = ax.add_patch(patch_1)
        patch_2 = PathPatch(p2, lw=2, fc='none', ec=detection_color[detection])
        ax.add_patch(patch_2)

        # Plot the controls nodes for debugging
        ax = plot_ctrls(p1.vertices, ax, marker='s', color=patch_1.get_ec(),
                        label='verts_1')
        ax = plot_ctrls(p2.vertices, ax, color=patch_2.get_ec(),
                        label='verts_2')
        ax.legend(loc='lower right', handlelength=3.5)

    #fig.savefig("Issue_with_intersecting_path_detection.png", dpi=150)
  • If this is an image generation bug attach a screenshot demonstrating the issue.

The paths are plotted in solid lines, and the vertices (control points) of the paths are plotted with markers (with thin dashed lines between them, and of the same color as the path they correspond to).

  • Left panel: the red path (path_2) is indicated as non intersecting with the blue one (path_1) by path_1.intersects_path(path_2), while from the plot they seem to be intersecting…
  • Right panel: the green path (path_2) is indicated as intersecting with the blue one (path_1) by path_1.intersects_path(path_2), which seems correct from the plot…

The only difference between the two red and green paths is their last control point (on the right), which is a bit lower in the right panel case than in the left panel case.

issue_with_intersecting_path_detection

  • If this is a regression (Used to work in an earlier version of Matplotlib), please
    note where it used to work.

Never used Path.intersects_path method before, so I can't tell if it's a regression.

@tacaswell tacaswell added this to the 2.0.1 (next bug fix release) milestone Feb 29, 2016
@mdboom mdboom self-assigned this Feb 29, 2016
@mdboom
Copy link
Member

mdboom commented Feb 29, 2016

Here's the issue -- but I'll have to think on a fix.

Path intersection is done by converting the curves to line segments and then converting the intersection based on the line segments. This conversion happens by "sampling" the curve at increments of 1.0. This is generally the right thing to do when the paths are already scaled in display space, because sampling the curve at a resolution finer than a single pixel doesn't really help. However, when calculating the intersection in data space as you've done here, we obviously need to sample at a finer resolution.

A workaround that should work for you now would be to convert the paths to pixel space and do the intersection calculation there:

        detection = p1.transformed(ax.transData).intersects_path(
            p2.transformed(ax.transData))

Though I think the long term fix is to replace the algorithm with something that is directly curve-aware.

@afvincent
Copy link
Contributor Author

Thank you for the explanation. Your workaround indeed solves my problem of the misdetected intersecting path (left panel on previous picture).

@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.0.1 (next bug fix release) Mar 1, 2016
@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Oct 3, 2017
@github-actions
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Mar 22, 2023
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 22, 2023
@rcomer rcomer added the status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. label May 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action topic: path handling
Projects
None yet
Development

No branches or pull requests

4 participants