|
1 | | -# Copyright (c) 2020, Manfred Moitzi |
| 1 | +# Copyright (c) 2020-2024, Manfred Moitzi |
2 | 2 | # License: MIT License |
3 | 3 | import pytest |
4 | | -from ezdxf.math import is_point_in_polygon_2d, Vec2 |
| 4 | +from ezdxf.math import is_point_in_polygon_2d, Vec2, is_convex_polygon_2d |
5 | 5 |
|
6 | 6 |
|
7 | | -def test_inside_horiz_box(): |
| 7 | +def test_inside_horizontal_box(): |
8 | 8 | square = Vec2.list([(0, 0), (1, 0), (1, 1), (0, 1)]) |
9 | 9 | assert is_point_in_polygon_2d(Vec2(0.5, 0.5), square) == 1 |
10 | 10 |
|
11 | 11 |
|
12 | | -def test_outside_horiz_box(): |
| 12 | +def test_outside_horizontal_box(): |
13 | 13 | square = Vec2.list([(0, 0), (1, 0), (1, 1), (0, 1)]) |
14 | 14 | assert is_point_in_polygon_2d(Vec2(-0.5, 0.5), square) == -1 |
15 | 15 | assert is_point_in_polygon_2d(Vec2(1.5, 0.5), square) == -1 |
16 | 16 | assert is_point_in_polygon_2d(Vec2(0.5, -0.5), square) == -1 |
17 | 17 | assert is_point_in_polygon_2d(Vec2(0.5, 1.5), square) == -1 |
18 | 18 |
|
19 | 19 |
|
20 | | -def test_colinear_outside_horiz_box(): |
| 20 | +def test_colinear_outside_horizontal_box(): |
21 | 21 | square = Vec2.list([(0, 0), (1, 0), (1, 1), (0, 1)]) |
22 | 22 | assert is_point_in_polygon_2d(Vec2(1.5, 0), square) == -1 |
23 | 23 | assert is_point_in_polygon_2d(Vec2(-0.5, 0), square) == -1 |
24 | 24 | assert is_point_in_polygon_2d(Vec2(0, 1.5), square) == -1 |
25 | 25 | assert is_point_in_polygon_2d(Vec2(0, -0.5), square) == -1 |
26 | 26 |
|
27 | 27 |
|
28 | | -def test_corners_horiz_box(): |
| 28 | +def test_corners_horizontal_box(): |
29 | 29 | square = Vec2.list([(0, 0), (1, 0), (1, 1), (0, 1)]) |
30 | 30 | assert is_point_in_polygon_2d(Vec2(0, 0), square) == 0 |
31 | 31 | assert is_point_in_polygon_2d(Vec2(0, 1), square) == 0 |
@@ -62,5 +62,100 @@ def test_borders_slanted_box_stable(): |
62 | 62 | assert is_point_in_polygon_2d(Vec2(-0.5, 0.5), square) == 0 |
63 | 63 |
|
64 | 64 |
|
| 65 | +# Test concave polygon: |
| 66 | +# |
| 67 | +# 0123456 |
| 68 | +# 8 ....... |
| 69 | +# 7 .7---6. |
| 70 | +# 6 .|...|. |
| 71 | +# 5 .|.4-5. |
| 72 | +# 4 .|.|... |
| 73 | +# 3 .|.3-2. |
| 74 | +# 2 .|...|. |
| 75 | +# 1 .0---1. |
| 76 | +# 0 ....... |
| 77 | +# 0123456 |
| 78 | + |
| 79 | +SHAPE_C_CCW = Vec2.list( |
| 80 | + # 0 1 2 3 4 5 6 7 |
| 81 | + [(1, 1), (5, 1), (5, 3), (3, 3), (3, 5), (5, 5), (5, 7), (1, 7)] |
| 82 | +) |
| 83 | +SHAPE_C_CW = list(reversed(SHAPE_C_CCW)) |
| 84 | + |
| 85 | +# 0123456 |
| 86 | +# 8 ....... |
| 87 | +# 7 .+---+. |
| 88 | +# 6 .|678|. |
| 89 | +# 5 .|5+-+. |
| 90 | +# 4 .|4|... |
| 91 | +# 3 .|3+-+. |
| 92 | +# 2 .|012|. |
| 93 | +# 1 .+---+. |
| 94 | +# 0 ....... |
| 95 | +# 0123456 |
| 96 | + |
| 97 | +POINTS_INSIDE = Vec2.list( |
| 98 | + # 0 1 2 3 4 5 6 7 8 |
| 99 | + [(2, 2), (3, 2), (4, 2), (2, 3), (2, 4), (2, 5), (2, 6), (3, 6), (4, 6)] |
| 100 | +) |
| 101 | + |
| 102 | +# 0123456 |
| 103 | +# 8 b.c.d.e |
| 104 | +# 7 .+---+. |
| 105 | +# 6 9|...|a |
| 106 | +# 5 .|.+-+. |
| 107 | +# 4 6|.|7.8 |
| 108 | +# 3 .|.+-+. |
| 109 | +# 2 4|...|5 |
| 110 | +# 1 .+---+. |
| 111 | +# 0 0.1.2.3 |
| 112 | +# 0123456 |
| 113 | + |
| 114 | +POINTS_OUTSIDE = Vec2.list( |
| 115 | + [ |
| 116 | + (0, 0), # 0 |
| 117 | + (2, 0), # 1 |
| 118 | + (4, 0), # 2 |
| 119 | + (6, 0), # 3 |
| 120 | + (0, 2), # 4 |
| 121 | + (6, 2), # 5 |
| 122 | + (0, 4), # 6 |
| 123 | + (4, 4), # 7 |
| 124 | + (6, 2), # 8 |
| 125 | + (0, 6), # 9 |
| 126 | + (6, 6), # a |
| 127 | + (0, 8), # b |
| 128 | + (2, 8), # c |
| 129 | + (4, 8), # d |
| 130 | + (6, 8), # e |
| 131 | + ] |
| 132 | +) |
| 133 | + |
| 134 | + |
| 135 | +def test_shape_c_is_not_convex(): |
| 136 | + assert is_convex_polygon_2d(SHAPE_C_CCW) is False |
| 137 | + assert is_convex_polygon_2d(SHAPE_C_CW) is False |
| 138 | + |
| 139 | + |
| 140 | +@pytest.mark.parametrize("point", POINTS_INSIDE) |
| 141 | +def test_is_inside_ccw_polygon(point: Vec2): |
| 142 | + assert is_point_in_polygon_2d(point, SHAPE_C_CCW) >= 0 |
| 143 | + |
| 144 | + |
| 145 | +@pytest.mark.parametrize("point", POINTS_OUTSIDE) |
| 146 | +def test_is_outside_ccw_polygon(point: Vec2): |
| 147 | + assert is_point_in_polygon_2d(point, SHAPE_C_CCW) == -1 |
| 148 | + |
| 149 | + |
| 150 | +@pytest.mark.parametrize("point", POINTS_INSIDE) |
| 151 | +def test_is_inside_cw_polygon(point: Vec2): |
| 152 | + assert is_point_in_polygon_2d(point, SHAPE_C_CW) >= 0 |
| 153 | + |
| 154 | + |
| 155 | +@pytest.mark.parametrize("point", POINTS_OUTSIDE) |
| 156 | +def test_is_outside_cw_polygon(point: Vec2): |
| 157 | + assert is_point_in_polygon_2d(point, SHAPE_C_CW) == -1 |
| 158 | + |
| 159 | + |
65 | 160 | if __name__ == "__main__": |
66 | 161 | pytest.main([__file__]) |
0 commit comments