FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Issue detecting paths intersection with Path.intersects_path · Issue #6076 · matplotlib/matplotlib · GitHub

Repository navigation

Issue detecting paths intersection with Path.intersects_path #6076

Closed as not planned

Description

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.

  • 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.

Activity

  1. added this to the milestone on Feb 29, 2016
  2. self-assigned this
    on Feb 29, 2016
  3. mdboom commented on Feb 29, 2016

    Member

    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.

  4. afvincent commented on Feb 29, 2016

    ContributorAuthor

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

  5. modified the milestones: , on Mar 1, 2016
  6. modified the milestones: , on Oct 3, 2017
  7. github-actions commented on Mar 22, 2023

    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!

  8. added
    status: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.
    on May 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

status: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.status: inactiveMarked by the “Stale” Github Actiontopic: path handling

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


    Back | FazBrowse Home | New Git URL