PartSegCore-compiled-backend 0.15.9__tar.gz → 0.15.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/.pre-commit-config.yaml +2 -2
  2. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/PKG-INFO +1 -1
  3. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/triangulate.pyx +34 -10
  4. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/triangulation/triangulate.hpp +86 -2
  5. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/version.py +2 -2
  6. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/tests/test_triangulate.py +30 -0
  7. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/.gitignore +0 -0
  8. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/CMakeLists.txt +0 -0
  9. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/LICENSE.txt +0 -0
  10. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/MANIFEST.in +0 -0
  11. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/Readme.md +0 -0
  12. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/Makefile +0 -0
  13. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/calc_bounds.rst +0 -0
  14. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/conf.py +0 -0
  15. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/fast_unique.rst +0 -0
  16. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/index.rst +0 -0
  17. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/make.bat +0 -0
  18. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/napari_mapping.rst +0 -0
  19. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/docs/sprawl_utils.rst +0 -0
  20. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/pyproject.toml +0 -0
  21. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/__init__.py +0 -0
  22. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/_fast_unique.pyi +0 -0
  23. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/_fast_unique.pyx +0 -0
  24. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/_napari_mapping.pyx +0 -0
  25. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/calc_bounds.pyi +0 -0
  26. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/calc_bounds.pyx +0 -0
  27. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/color_image_cython.pyi +0 -0
  28. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/color_image_cython.pyx +0 -0
  29. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/fast_unique.py +0 -0
  30. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/multiscale_opening/__init__.py +0 -0
  31. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/multiscale_opening/mso.h +0 -0
  32. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/multiscale_opening/mso_bind.pyi +0 -0
  33. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/multiscale_opening/mso_bind.pyx +0 -0
  34. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/multiscale_opening/my_queue.h +0 -0
  35. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/napari_mapping.py +0 -0
  36. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/__init__.py +0 -0
  37. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/distance_utils.pxd +0 -0
  38. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/euclidean_cython.pyi +0 -0
  39. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/euclidean_cython.pyx +0 -0
  40. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/find_split.py +0 -0
  41. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/find_split.pyi +0 -0
  42. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/fuzzy_distance.pyx +0 -0
  43. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/global_consts.h +0 -0
  44. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/my_queue.h +0 -0
  45. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/path_sprawl_cython.pyi +0 -0
  46. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/path_sprawl_cython.pyx +0 -0
  47. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/put_borders_in_queue.pyx +0 -0
  48. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/sprawl_utils.pyi +0 -0
  49. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/sprawl_utils/sprawl_utils.pyx +0 -0
  50. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/triangulation/debug_util.hpp +0 -0
  51. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/triangulation/intersection.hpp +0 -0
  52. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/triangulation/point.hpp +0 -0
  53. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/PartSegCore_compiled_backend/utils.py +0 -0
  54. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/tests/test_calc_bounds.py +0 -0
  55. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/tests/test_coloring.py +0 -0
  56. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/tests/test_fast_unique.py +0 -0
  57. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/tests/test_napari_mapping.py +0 -0
  58. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/tests/test_sprawl_utils/__init__.py +0 -0
  59. {partsegcore_compiled_backend-0.15.9 → partsegcore_compiled_backend-0.15.11}/src/tests/test_sprawl_utils/test_euclidean.py +0 -0
@@ -4,7 +4,7 @@ default_language_version:
4
4
  repos:
5
5
  - repo: https://github.com/astral-sh/ruff-pre-commit
6
6
  # Ruff version.
7
- rev: v0.8.6
7
+ rev: v0.9.2
8
8
  hooks:
9
9
  # Run the linter.
10
10
  - id: ruff
@@ -36,7 +36,7 @@ repos:
36
36
  additional_dependencies:
37
37
  - tomli
38
38
  - repo: https://github.com/pre-commit/mirrors-clang-format
39
- rev: v19.1.6 # Use the sha / tag you want to point at
39
+ rev: v19.1.7 # Use the sha / tag you want to point at
40
40
  hooks:
41
41
  - id: clang-format
42
42
  args: ["-style=Google"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PartSegCore_compiled_backend
3
- Version: 0.15.9
3
+ Version: 0.15.11
4
4
  Summary: PartSegCore compiled backend,
5
5
  Keywords: bioimaging
6
6
  Author-Email: Grzegorz Bokota <g.bokota@cent.uw.edu.pl>
@@ -13,8 +13,6 @@ from libcpp cimport bool
13
13
  from libcpp.unordered_set cimport unordered_set
14
14
  from libcpp.utility cimport pair
15
15
  from libcpp.vector cimport vector
16
- from libcpp.unordered_map cimport unordered_map
17
- from libcpp.algorithm cimport sort
18
16
 
19
17
 
20
18
  cdef extern from "triangulation/point.hpp" namespace "partsegcore::point":
@@ -96,6 +94,7 @@ cdef extern from "triangulation/triangulate.hpp" namespace "partsegcore::triangu
96
94
  pair[vector[Triangle], vector[Point]] triangulate_polygon_face(const vector[Point]& polygon) except + nogil
97
95
  pair[vector[Triangle], vector[Point]] triangulate_polygon_face(const vector[vector[Point]]& polygon_list) except + nogil
98
96
  PathTriangulation triangulate_path_edge(const vector[Point]& path, bool closed, float limit, bool bevel) except + nogil
97
+ vector[vector[Point]] split_polygon_on_repeated_edges(const vector[Point]& polygon) except + nogil
99
98
 
100
99
 
101
100
  ctypedef fused float_types:
@@ -429,14 +428,15 @@ def triangulate_path_edge_numpy(cnp.ndarray[cnp.float32_t, ndim=2] path, bool cl
429
428
  )
430
429
 
431
430
 
432
- def triangulate_polygon_with_edge_numpy_li(polygon_li: list[np.ndarray]) -> tuple[tuple[np.ndarray, np.ndarray], tuple[np.ndarray, np.ndarray, np.ndarray]]:
431
+ def triangulate_polygon_with_edge_numpy_li(polygon_li: list[np.ndarray], split_edges: bool=False) -> tuple[tuple[np.ndarray, np.ndarray], tuple[np.ndarray, np.ndarray, np.ndarray]]:
433
432
  """ Triangulate polygon"""
434
433
  cdef vector[Point] polygon_vector
435
- cdef vector[vector[Point]] polygon_vector_list
434
+ cdef vector[vector[Point]] polygon_vector_list, edge_split_list
436
435
  cdef Point p1, p2
437
436
  cdef pair[vector[Triangle], vector[Point]] triangulation_result
438
437
  cdef vector[PathTriangulation] edge_result
439
438
  cdef cnp.ndarray[cnp.uint32_t, ndim=2] triangles, edge_triangles
439
+ cdef size_t triangle_count = 0
440
440
 
441
441
  cdef cnp.ndarray[cnp.float32_t, ndim=2] points, edge_offsets, edges_centers, polygon
442
442
  cdef size_t i, j, len_path, edge_triangle_count, edge_center_count, edge_triangle_index, edge_center_index
@@ -457,8 +457,14 @@ def triangulate_polygon_with_edge_numpy_li(polygon_li: list[np.ndarray]) -> tupl
457
457
  if polygon_vector.size() > 1 and polygon_vector.front() == polygon_vector.back():
458
458
  polygon_vector.pop_back()
459
459
  polygon_vector_list.push_back(polygon_vector)
460
- with cython.nogil:
461
- edge_result.push_back(triangulate_path_edge(polygon_vector, True, 3.0, False))
460
+ if split_edges:
461
+ with cython.nogil:
462
+ edge_split_list = split_polygon_on_repeated_edges(polygon_vector)
463
+ for edge_li in edge_split_list:
464
+ edge_result.push_back(triangulate_path_edge(edge_li, True, 3.0, False))
465
+ else:
466
+ with cython.nogil:
467
+ edge_result.push_back(triangulate_path_edge(polygon_vector, True, 3.0, False))
462
468
 
463
469
  with cython.nogil:
464
470
  triangulation_result = triangulate_polygon_face(polygon_vector_list)
@@ -470,7 +476,7 @@ def triangulate_polygon_with_edge_numpy_li(polygon_li: list[np.ndarray]) -> tupl
470
476
  triangles[i, 1] = triangulation_result.first[i].y
471
477
  triangles[i, 2] = triangulation_result.first[i].z
472
478
 
473
- points =np.empty((triangulation_result.second.size(), 2), dtype=np.float32)
479
+ points = np.empty((triangulation_result.second.size(), 2), dtype=np.float32)
474
480
  for i in range(triangulation_result.second.size()):
475
481
  points[i, 0] = triangulation_result.second[i].x
476
482
  points[i, 1] = triangulation_result.second[i].y
@@ -489,10 +495,11 @@ def triangulate_polygon_with_edge_numpy_li(polygon_li: list[np.ndarray]) -> tupl
489
495
  edge_center_index = 0
490
496
  for i in range(edge_result.size()):
491
497
  for j in range(edge_result[i].triangles.size()):
492
- edge_triangles[edge_triangle_index, 0] = edge_result[i].triangles[j].x
493
- edge_triangles[edge_triangle_index, 1] = edge_result[i].triangles[j].y
494
- edge_triangles[edge_triangle_index, 2] = edge_result[i].triangles[j].z
498
+ edge_triangles[edge_triangle_index, 0] = edge_result[i].triangles[j].x + triangle_count
499
+ edge_triangles[edge_triangle_index, 1] = edge_result[i].triangles[j].y + triangle_count
500
+ edge_triangles[edge_triangle_index, 2] = edge_result[i].triangles[j].z + triangle_count
495
501
  edge_triangle_index += 1
502
+ triangle_count += edge_result[i].centers.size()
496
503
 
497
504
  for j in range(edge_result[i].centers.size()):
498
505
  edges_centers[edge_center_index, 0] = edge_result[i].centers[j].x
@@ -511,3 +518,20 @@ def triangulate_polygon_with_edge_numpy_li(polygon_li: list[np.ndarray]) -> tupl
511
518
  edge_triangles,
512
519
  )
513
520
  )
521
+
522
+
523
+ def split_polygon_on_repeated_edges_py(polygon: Sequence[Sequence[float]]) -> list[list[tuple[float, float]]]:
524
+ """ Split polygon on repeated edges"""
525
+ cdef vector[Point] polygon_vector
526
+ cdef vector[vector[Point]] result
527
+ cdef Point p1, p2
528
+
529
+ polygon_vector.reserve(len(polygon))
530
+ for point in polygon:
531
+ polygon_vector.push_back(Point(point[0], point[1]))
532
+
533
+ result = split_polygon_on_repeated_edges(polygon_vector)
534
+ return [
535
+ [(point.x, point.y) for point in polygon_vector]
536
+ for polygon_vector in result
537
+ ]
@@ -2,9 +2,8 @@
2
2
  #define PARTSEGCORE_TRIANGULATE_H
3
3
 
4
4
  #include <algorithm>
5
- #include <cmath>
6
5
  #include <map>
7
- #include <memory>
6
+ #include <memory> // memory header is required on linux, and not on macos
8
7
  #include <set>
9
8
  #include <sstream>
10
9
  #include <unordered_map>
@@ -1288,6 +1287,91 @@ inline PathTriangulation triangulate_path_edge(
1288
1287
  return result;
1289
1288
  }
1290
1289
 
1290
+ /**
1291
+ * Represents an edge in a graph structure used for polygon processing.
1292
+ * Each edge contains a reference to its opposite point and a flag to track
1293
+ * if it has been visited during graph traversal.
1294
+ */
1295
+ struct GraphEdge {
1296
+ point::Point opposite_point;
1297
+ bool visited;
1298
+ explicit GraphEdge(point::Point p) : opposite_point(p), visited(false) {}
1299
+ };
1300
+
1301
+ /**
1302
+ * Represents a node in a graph structure used for polygon processing.
1303
+ * Each node contains its edges, a sub-index for traversal tracking,
1304
+ * and a visited flag for graph traversal.
1305
+ */
1306
+ struct GraphNode {
1307
+ std::vector<GraphEdge> edges;
1308
+ std::size_t sub_index;
1309
+ bool visited;
1310
+
1311
+ GraphNode() : sub_index(0), visited(false) {}
1312
+ };
1313
+
1314
+ /**
1315
+ * Splits a polygon into sub-polygons by identifying and removing edges that
1316
+ * appear more than once in the polygon's edge list.
1317
+ *
1318
+ * This function processes the given polygon and separates it wherever an
1319
+ * edge is repeated. It generates a collection of sub-polygons such that each
1320
+ * resulting sub-polygon contains unique edges. This operation can help to
1321
+ * resolve ambiguities in complex or self-intersecting polygons.
1322
+ *
1323
+ * Note: Polygons with exactly 2 points are treated as single line segments and
1324
+ * are not processed for edge deduplication between their first and last points.
1325
+ *
1326
+ * @param polygon The input polygon represented as a list of edges.
1327
+ *
1328
+ * @return A vector of sub-polygons, where each sub-polygon is free of repeated
1329
+ * edges.
1330
+ */
1331
+ inline std::vector<std::vector<point::Point>> split_polygon_on_repeated_edges(
1332
+ const std::vector<point::Point> &polygon) {
1333
+ if (polygon.size() < 3) return {polygon};
1334
+ auto edges_dedup = calc_dedup_edges({polygon});
1335
+ std::vector<std::vector<point::Point>> result;
1336
+ point::Segment segment;
1337
+
1338
+ std::unordered_set edges_set(edges_dedup.begin(), edges_dedup.end());
1339
+ std::unordered_map<point::Point, GraphNode> edges_map;
1340
+ for (std::size_t i = 0; i < polygon.size() - 1; i++) {
1341
+ segment = {polygon[i], polygon[(i + 1)]};
1342
+ if (edges_set.count(segment) > 0) {
1343
+ edges_map[polygon[i]].edges.emplace_back(polygon[i + 1]);
1344
+ }
1345
+ }
1346
+ segment = {polygon.back(), polygon.front()};
1347
+ if (edges_set.count(segment) > 0) {
1348
+ edges_map[polygon.back()].edges.emplace_back(polygon.front());
1349
+ }
1350
+ for (auto &edge : edges_map) {
1351
+ if (edge.second.visited) {
1352
+ continue;
1353
+ }
1354
+ edge.second.visited = true;
1355
+ std::vector<point::Point> new_polygon;
1356
+ new_polygon.push_back(edge.first);
1357
+ auto *current_edge = &edge.second;
1358
+ while (current_edge->sub_index < current_edge->edges.size()) {
1359
+ auto *prev = current_edge;
1360
+ auto next_point =
1361
+ current_edge->edges[current_edge->sub_index].opposite_point;
1362
+ current_edge = &edges_map.at(next_point);
1363
+ prev->sub_index++;
1364
+ current_edge->visited = true;
1365
+ new_polygon.push_back(next_point);
1366
+ }
1367
+ while (new_polygon.front() == new_polygon.back()) {
1368
+ new_polygon.pop_back();
1369
+ }
1370
+ result.push_back(new_polygon);
1371
+ }
1372
+ return result;
1373
+ }
1374
+
1291
1375
  } // namespace partsegcore::triangulation
1292
1376
 
1293
1377
  #endif // PARTSEGCORE_TRIANGULATE_H
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.15.9'
16
- __version_tuple__ = version_tuple = (0, 15, 9)
15
+ __version__ = version = '0.15.11'
16
+ __version_tuple__ = version_tuple = (0, 15, 11)
@@ -10,6 +10,7 @@ from PartSegCore_compiled_backend.triangulate import (
10
10
  on_segment,
11
11
  orientation,
12
12
  segment_left_to_right_comparator,
13
+ split_polygon_on_repeated_edges_py,
13
14
  triangle_convex_polygon,
14
15
  triangulate_monotone_polygon_py,
15
16
  triangulate_path_edge_numpy,
@@ -661,3 +662,32 @@ def test_triangulate_polygon_with_edge_numpy_li(polygon, expected):
661
662
  triangles_ = _renumerate_triangles(polygon, points, triangles)
662
663
  assert triangles_ == expected
663
664
  assert centers.shape == offsets.shape
665
+
666
+
667
+ def test_split_polygon_on_repeated_edges_py_no_split():
668
+ res = split_polygon_on_repeated_edges_py([[0, 0], [0, 1], [1, 1], [1, 0]])
669
+ assert len(res) == 1
670
+ assert len(res[0]) == 4
671
+ idx = res[0].index((0, 0))
672
+ assert res[0][idx:] + res[0][:idx] == [(0, 0), (0, 1), (1, 1), (1, 0)]
673
+
674
+
675
+ def test_split_polygon_on_repeated_edges_py_square_in_square():
676
+ res = split_polygon_on_repeated_edges_py(
677
+ [[0, 0], [0, 5], [1, 5], [1, 1], [9, 1], [9, 9], [1, 9], [1, 5], [0, 5], [0, 10], [10, 10], [10, 0]]
678
+ )
679
+ assert len(res) == 2
680
+ assert len(res[0]) == 5
681
+ assert len(res[1]) == 5
682
+ # idx = res[0].index((0, 0))
683
+ # assert res[0][idx:] + res[0][:idx] == [(0, 0), (0, 1), (1, 1), (1, 0)]
684
+
685
+
686
+ @pytest.mark.parametrize(('split_edges', 'triangles'), [(True, 20), (False, 24)])
687
+ def test_splitting_edges(split_edges, triangles):
688
+ polygon = np.array(
689
+ [[0, 0], [0, 5], [1, 5], [1, 1], [9, 1], [9, 9], [1, 9], [1, 5], [0, 5], [0, 10], [10, 10], [10, 0]],
690
+ dtype=np.float32,
691
+ )
692
+ triangles_ = triangulate_polygon_with_edge_numpy_li([polygon], split_edges=split_edges)[1][2]
693
+ assert len(triangles_) == triangles