Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3cf46cb

Browse filesBrowse files
authored
Pathing issue (#20395)
* added check for collinearity
1 parent 103c3ab commit 3cf46cb
Copy full SHA for 3cf46cb

File tree

Expand file treeCollapse file tree

2 files changed

+31
-12
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+31
-12
lines changed

‎lib/matplotlib/tests/test_path.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_path.py
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,16 @@ def test_path_intersect_path(phi):
410410
b = transform.transform_path(Path([(0, 1), (0, 2), (0, 5)]))
411411
assert a.intersects_path(b) and b.intersects_path(a)
412412

413+
# a and b are collinear but do not intersect
414+
a = transform.transform_path(Path([(1, -1), (0, -1)]))
415+
b = transform.transform_path(Path([(0, 1), (0.9, 1)]))
416+
assert not a.intersects_path(b) and not b.intersects_path(a)
417+
418+
# a and b are collinear but do not intersect
419+
a = transform.transform_path(Path([(0., -5.), (1., -5.)]))
420+
b = transform.transform_path(Path([(1., 5.), (0., 5.)]))
421+
assert not a.intersects_path(b) and not b.intersects_path(a)
422+
413423

414424
@pytest.mark.parametrize('offset', range(-720, 361, 45))
415425
def test_full_arc(offset):

‎src/_path.h

Copy file name to clipboardExpand all lines: src/_path.h
+21-12Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -833,21 +833,27 @@ inline bool segments_intersect(const double &x1,
833833
// determinant
834834
double den = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1));
835835

836-
if (isclose(den, 0.0)) { // collinear segments
837-
if (x1 == x2 && x2 == x3) { // segments have infinite slope (vertical lines)
838-
// and lie on the same line
839-
return (fmin(y1, y2) <= fmin(y3, y4) && fmin(y3, y4) <= fmax(y1, y2)) ||
840-
(fmin(y3, y4) <= fmin(y1, y2) && fmin(y1, y2) <= fmax(y3, y4));
841-
}
842-
else {
843-
double intercept = (y1*x2 - y2*x1)*(x4 - x3) - (y3*x4 - y4*x3)*(x1 - x2);
844-
if (isclose(intercept, 0.0)) { // segments lie on the same line
836+
// If den == 0 we have two possibilities:
837+
if (isclose(den, 0.0)) {
838+
float t_area = (x2*y3 - x3*y2) - x1*(y3 - y2) + y1*(x3 - x2);
839+
// 1 - If the area of the triangle made by the 3 first points (2 from the first segment
840+
// plus one from the second) is zero, they are collinear
841+
if (isclose(t_area, 0.0)) {
842+
if (x1 == x2 && x2 == x3) { // segments have infinite slope (vertical lines)
843+
// and lie on the same line
844+
return (fmin(y1, y2) <= fmin(y3, y4) && fmin(y3, y4) <= fmax(y1, y2)) ||
845+
(fmin(y3, y4) <= fmin(y1, y2) && fmin(y1, y2) <= fmax(y3, y4));
846+
}
847+
else {
845848
return (fmin(x1, x2) <= fmin(x3, x4) && fmin(x3, x4) <= fmax(x1, x2)) ||
846-
(fmin(x3, x4) <= fmin(x1, x2) && fmin(x1, x2) <= fmax(x3, x4));
849+
(fmin(x3, x4) <= fmin(x1, x2) && fmin(x1, x2) <= fmax(x3, x4));
850+
847851
}
848852
}
849-
850-
return false;
853+
// 2 - If t_area is not zero, the segments are parallel, but not collinear
854+
else {
855+
return false;
856+
}
851857
}
852858

853859
const double n1 = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3));
@@ -865,6 +871,7 @@ inline bool segments_intersect(const double &x1,
865871
template <class PathIterator1, class PathIterator2>
866872
bool path_intersects_path(PathIterator1 &p1, PathIterator2 &p2)
867873
{
874+
868875
typedef PathNanRemover<py::PathIterator> no_nans_t;
869876
typedef agg::conv_curve<no_nans_t> curve_t;
870877

@@ -889,12 +896,14 @@ bool path_intersects_path(PathIterator1 &p1, PathIterator2 &p2)
889896
}
890897
c2.rewind(0);
891898
c2.vertex(&x21, &y21);
899+
892900

893901
while (c2.vertex(&x22, &y22) != agg::path_cmd_stop) {
894902
// if the segment in path 2 is (almost) 0 length, skip to next vertex
895903
if ((isclose((x21 - x22) * (x21 - x22) + (y21 - y22) * (y21 - y22), 0))){
896904
continue;
897905
}
906+
898907
if (segments_intersect(x11, y11, x12, y12, x21, y21, x22, y22)) {
899908
return true;
900909
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.