回答編集履歴
2
追記
    
        answer	
    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 
     | 
    
         
            -
             
     | 
| 
      
 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,3 +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 
     | 
    
         
             
            ```
         
     | 
| 
      
 67 
     | 
    
         
            +
            
         
     | 
| 
      
 68 
     | 
    
         
            +
            
         
     | 
1
追記
    
        answer	
    CHANGED
    
    | 
         @@ -11,4 +11,41 @@ 
     | 
|
| 
       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 
     | 
    
         
             
            ```
         
     |