Skip to content

Commit 1e01504

Browse files
authored
Merge pull request #26226 from ianthomas23/25114_tricontourf_closing_code
Use CLOSEPOLY kind code to close tricontourf polygons
2 parents ae723ba + bdd6d36 commit 1e01504

File tree

2 files changed

+71
-12
lines changed

2 files changed

+71
-12
lines changed

lib/matplotlib/tests/test_triangulation.py

+61
Original file line numberDiff line numberDiff line change
@@ -1340,3 +1340,64 @@ def test_triplot_label():
13401340
assert labels == ['label']
13411341
assert len(handles) == 1
13421342
assert handles[0] is lines
1343+
1344+
1345+
def test_tricontour_path():
1346+
x = [0, 4, 4, 0, 2]
1347+
y = [0, 0, 4, 4, 2]
1348+
triang = mtri.Triangulation(x, y)
1349+
_, ax = plt.subplots()
1350+
1351+
# Line strip from boundary to boundary
1352+
cs = ax.tricontour(triang, [1, 0, 0, 0, 0], levels=[0.5])
1353+
paths = cs.get_paths()
1354+
assert len(paths) == 1
1355+
expected_vertices = [[2, 0], [1, 1], [0, 2]]
1356+
assert_array_almost_equal(paths[0].vertices, expected_vertices)
1357+
assert_array_equal(paths[0].codes, [1, 2, 2])
1358+
assert_array_almost_equal(
1359+
paths[0].to_polygons(closed_only=False), [expected_vertices])
1360+
1361+
# Closed line loop inside domain
1362+
cs = ax.tricontour(triang, [0, 0, 0, 0, 1], levels=[0.5])
1363+
paths = cs.get_paths()
1364+
assert len(paths) == 1
1365+
expected_vertices = [[3, 1], [3, 3], [1, 3], [1, 1], [3, 1]]
1366+
assert_array_almost_equal(paths[0].vertices, expected_vertices)
1367+
assert_array_equal(paths[0].codes, [1, 2, 2, 2, 79])
1368+
assert_array_almost_equal(paths[0].to_polygons(), [expected_vertices])
1369+
1370+
1371+
def test_tricontourf_path():
1372+
x = [0, 4, 4, 0, 2]
1373+
y = [0, 0, 4, 4, 2]
1374+
triang = mtri.Triangulation(x, y)
1375+
_, ax = plt.subplots()
1376+
1377+
# Polygon inside domain
1378+
cs = ax.tricontourf(triang, [0, 0, 0, 0, 1], levels=[0.5, 1.5])
1379+
paths = cs.get_paths()
1380+
assert len(paths) == 1
1381+
expected_vertices = [[3, 1], [3, 3], [1, 3], [1, 1], [3, 1]]
1382+
assert_array_almost_equal(paths[0].vertices, expected_vertices)
1383+
assert_array_equal(paths[0].codes, [1, 2, 2, 2, 79])
1384+
assert_array_almost_equal(paths[0].to_polygons(), [expected_vertices])
1385+
1386+
# Polygon following boundary and inside domain
1387+
cs = ax.tricontourf(triang, [1, 0, 0, 0, 0], levels=[0.5, 1.5])
1388+
paths = cs.get_paths()
1389+
assert len(paths) == 1
1390+
expected_vertices = [[2, 0], [1, 1], [0, 2], [0, 0], [2, 0]]
1391+
assert_array_almost_equal(paths[0].vertices, expected_vertices)
1392+
assert_array_equal(paths[0].codes, [1, 2, 2, 2, 79])
1393+
assert_array_almost_equal(paths[0].to_polygons(), [expected_vertices])
1394+
1395+
# Polygon is outer boundary with hole
1396+
cs = ax.tricontourf(triang, [0, 0, 0, 0, 1], levels=[-0.5, 0.5])
1397+
paths = cs.get_paths()
1398+
assert len(paths) == 1
1399+
expected_vertices = [[0, 0], [4, 0], [4, 4], [0, 4], [0, 0],
1400+
[1, 1], [1, 3], [3, 3], [3, 1], [1, 1]]
1401+
assert_array_almost_equal(paths[0].vertices, expected_vertices)
1402+
assert_array_equal(paths[0].codes, [1, 2, 2, 2, 79, 1, 2, 2, 2, 79])
1403+
assert_array_almost_equal(paths[0].to_polygons(), np.split(expected_vertices, [5]))

src/tri/_tri.cpp

+10-12
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,9 @@ py::tuple TriContourGenerator::contour_to_segs_and_kinds(const Contour& contour)
733733
*segs_ptr++ = point->y;
734734
*codes_ptr++ = (point == line->begin() ? MOVETO : LINETO);
735735
}
736+
737+
if (line->size() > 1)
738+
*(codes_ptr-1) = CLOSEPOLY;
736739
}
737740

738741
py::list vertices_list(1);
@@ -849,11 +852,8 @@ void TriContourGenerator::find_boundary_lines_filled(Contour& contour,
849852
lower_level, upper_level, on_upper);
850853
} while (tri_edge != start_tri_edge);
851854

852-
// Filled contour lines must not have same first and last
853-
// points.
854-
if (contour_line.size() > 1 &&
855-
contour_line.front() == contour_line.back())
856-
contour_line.pop_back();
855+
// Close polygon.
856+
contour_line.push_back(contour_line.front());
857857
}
858858
}
859859
}
@@ -872,6 +872,9 @@ void TriContourGenerator::find_boundary_lines_filled(Contour& contour,
872872
for (Boundary::size_type j = 0; j < boundary.size(); ++j)
873873
contour_line.push_back(triang.get_point_coords(
874874
triang.get_triangle_point(boundary[j])));
875+
876+
// Close polygon.
877+
contour_line.push_back(contour_line.front());
875878
}
876879
}
877880
}
@@ -904,13 +907,8 @@ void TriContourGenerator::find_interior_lines(Contour& contour,
904907
TriEdge tri_edge = triang.get_neighbor_edge(tri, edge);
905908
follow_interior(contour_line, tri_edge, false, level, on_upper);
906909

907-
if (!filled)
908-
// Non-filled contour lines must be closed.
909-
contour_line.push_back(contour_line.front());
910-
else if (contour_line.size() > 1 &&
911-
contour_line.front() == contour_line.back())
912-
// Filled contour lines must not have same first and last points.
913-
contour_line.pop_back();
910+
// Close line loop
911+
contour_line.push_back(contour_line.front());
914912
}
915913
}
916914

0 commit comments

Comments
 (0)