回答編集履歴

2

追記

2023/06/20 08:43

投稿

can110
can110

スコア38278

test CHANGED
@@ -1,17 +1,32 @@
1
1
  [Shapely](https://shapely.readthedocs.io/en/stable/index.html)の[unary_union](https://shapely.readthedocs.io/en/stable/reference/shapely.unary_union.html#shapely-unary-union)が使えそうです。
2
2
  結合後、直線区間中に連続する点は残りますが、それを除く方法はおそらく難しくなく、Shapelyの関数としても用意されているかもしれません。
3
+
4
+ ### 追記
5
+
6
+ 不要な点の削除は[normalize](https://shapely.readthedocs.io/en/stable/reference/shapely.Polygon.html#shapely.Polygon.normalize)して[simplify](https://shapely.readthedocs.io/en/stable/reference/shapely.Polygon.html#shapely.Polygon.simplify)すればよい感じです。
7
+ 参考:[Simplify method can not simplify duplicated vertices of a ring #1638](https://github.com/shapely/shapely/issues/1638)
8
+
3
9
  ```Python
10
+ import matplotlib.pyplot as plt
4
11
  import shapely
5
12
  from shapely.geometry import Polygon
6
13
 
7
14
  # ポリゴンは反時計回りで定義
8
15
  p1 = Polygon([(10,0),(10,10),(20,10),(20,15),(25,15),(25,5),(30,5),(30,0)][::-1])
9
16
  p2 = Polygon([(5,25),(25,25),(25,15),(20,15),(20,10),(15,10),(15,20),(5,20)][::-1])
17
+ p3 = shapely.unary_union([p1,p2])
10
18
 
11
- p3 = shapely.unary_union([p1,p2])
19
+ plt.plot(*p3.exterior.xy, marker="o")
20
+ plt.show()
12
21
  print(p3)
13
22
  # POLYGON ((25 15, 25 5, 30 5, 30 0, 10 0, 10 10, 15 10, 15 20, 5 20, 5 25, 25 25, 25 15))
14
23
 
24
+ # 不要な点を取り除く
25
+ p3 = p3.normalize().simplify(0.1)
26
+ plt.plot(*p3.exterior.xy, marker="o")
27
+ plt.show()
28
+ print(p3)
29
+ # POLYGON ((5 20, 5 25, 25 25, 25 5, 30 5, 30 0, 10 0, 10 10, 15 10, 15 20, 5 20))
15
30
 
16
31
  # 重ならない
17
32
  p1 = Polygon([(0,0),(1,0),(1,1),(0,1),(0,0)])
@@ -49,4 +64,5 @@
49
64
  print(shapely.unary_union([p1,p2]))
50
65
  # POLYGON ((3 1, 3 0, 0 0, 0 1, 0 3, 3 3, 3 1), (1 1, 2 1, 2 2, 1 2, 1 1))
51
66
  ```
52
-
67
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2023-06-20/94f090e8-4fa7-4131-a91c-53aee179df88.png)
68
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2023-06-20/bd359cc7-250e-4aff-8928-51532fc0b62a.png)

1

追記

2023/06/20 05:05

投稿

can110
can110

スコア38278

test CHANGED
@@ -11,5 +11,42 @@
11
11
  p3 = shapely.unary_union([p1,p2])
12
12
  print(p3)
13
13
  # POLYGON ((25 15, 25 5, 30 5, 30 0, 10 0, 10 10, 15 10, 15 20, 5 20, 5 25, 25 25, 25 15))
14
+
15
+
16
+ # 重ならない
17
+ p1 = Polygon([(0,0),(1,0),(1,1),(0,1),(0,0)])
18
+ p2 = Polygon([(2,0),(3,0),(3,1),(2,1),(2,0)])
19
+ print(shapely.unary_union([p1,p2]))
20
+ # MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)), ((2 0, 3 0, 3 1, 2 1, 2 0)))
21
+
22
+ # 内包
23
+ p1 = Polygon([(0,0),(3,0),(3,3),(0,3),(0,0)])
24
+ p2 = Polygon([(1,1),(2,1),(2,2),(1,2),(1,1)])
25
+ print(shapely.unary_union([p1,p2]))
26
+ # POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0))
27
+
28
+ # 辺で接する
29
+ p1 = Polygon([(0,0),(1,0),(1,1),(0,1),(0,0)])
30
+ p2 = Polygon([(1,0),(2,0),(2,1),(1,1),(1,0)])
31
+ print(shapely.unary_union([p1,p2]))
32
+ # POLYGON ((1 0, 0 0, 0 1, 1 1, 2 1, 2 0, 1 0))
33
+
34
+ # 点で接する
35
+ p1 = Polygon([(0,0),(1,0),(1,1),(0,1),(0,0)])
36
+ p2 = Polygon([(1,1),(2,1),(2,2),(1,2),(1,1)])
37
+ print(shapely.unary_union([p1,p2]))
38
+ # MULTIPOLYGON (((1 1, 1 0, 0 0, 0 1, 1 1)), ((1 1, 1 2, 2 2, 2 1, 1 1)))
39
+
40
+ # 重複
41
+ p1 = Polygon([(0,0),(2,0),(2,2),(0,2),(0,0)])
42
+ p2 = Polygon([(0,1),(2,1),(2,3),(0,1)])
43
+ print(shapely.unary_union([p1,p2]))
44
+ # POLYGON ((2 1, 2 0, 0 0, 0 1, 0 2, 1 2, 2 3, 2 2, 2 1))
45
+
46
+ # 穴ができる
47
+ p1 = Polygon([(0,0),(3,0),(3,1),(0,1),(0,0)])
48
+ p2 = Polygon([(2,1),(3,1),(3,3),(0,3),(0,1),(1,1),(1,2),(2,2),(2,1)])
49
+ print(shapely.unary_union([p1,p2]))
50
+ # POLYGON ((3 1, 3 0, 0 0, 0 1, 0 3, 3 3, 3 1), (1 1, 2 1, 2 2, 1 2, 1 1))
14
51
  ```
15
52