提交 7b9bbb467287c3351af45befac76863ff6d79527

作者 nheweijun
1 个父辈 372ebe57

2022.03.31 修复注册空表问题

要显示太多修改。

为保证性能只显示 28 of 30 个文件。

... ... @@ -205,7 +205,7 @@ class EntryDataVacuate:
205 205
206 206 # 复制原图层的属性
207 207 # 去掉fid的属性
208   - schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]
  208 + schema = [sche for sche in layer.schema if not sche.name.lower().__eq__(fid)]
209 209 pg_layer.CreateFields(schema)
210 210
211 211 #创建抽稀过程
... ...
... ... @@ -38,14 +38,7 @@ class Api(ApiTemplate):
38 38 append_dict["sr_wkt"] = sr.ExportToWkt()
39 39 append_dict["sr_proj4"] = sr.ExportToProj4()
40 40
41   - srid_sql = '''select st_srid("{}") from public."{}" limit 1'''.format(layer.GetGeometryColumn(),layer.GetName())
42   - srid_layer:Layer = pg_ds.ExecuteSQL(srid_sql)
43   - if srid_layer:
44   - srid_feature : Feature = srid_layer.GetNextFeature()
45   - if srid_feature:
46   - if srid_feature.GetField(0):
47   - append_dict["srid"] = str(srid_feature.GetField(0))
48   -
  41 + append_dict["srid"] = str(PGUtil.get_srid(pg_ds,layer.GetName()))
49 42 else:
50 43 append_dict["exist"]=0
51 44 columns = table.relate_columns.order_by(Columns.name).all()
... ...
... ... @@ -5,7 +5,6 @@
5 5
6 6 from app.models import db
7 7 from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time,Float,Binary,Sequence
8   -from sqlalchemy import Sequence
9 8 from sqlalchemy.orm import relationship
10 9 import base64
11 10 from pyDes import *
... ...
... ... @@ -38,7 +38,7 @@ class Api(ApiTemplate):
38 38 map_service_update = {}
39 39
40 40 for key in self.para.keys():
41   - if key in ["name","title","state","description","overview","catalog_guid"]:
  41 + if key in ["name","title","description","overview","catalog_guid"]:
42 42 service_update[key] = self.para.get(key)
43 43 if key in ["name","tile","project","capabilities"]:
44 44 map_service_update[key] = self.para.get(key)
... ... @@ -47,7 +47,9 @@ class Api(ApiTemplate):
47 47 "title":self.para.get("title"),
48 48 "type":"mapserver",
49 49 "capabilities":2,
50   - "project":self.para.get("project")}
  50 + "project":self.para.get("project"),
  51 + "state":service.state
  52 + }
51 53
52 54 map_service_register_url = "{}/dmap/api/manager/regservice".format(configure.dmap_engine)
53 55 resp: requests.Response = requests.post(map_service_register_url,data=json.dumps(para),
... ...
... ... @@ -199,11 +199,16 @@ class Api(ApiTemplate):
199 199
200 200 extent = [float(x) for x in table.extent.split(",")]
201 201
  202 + minx = para.get("minx")
  203 + miny = para.get("miny")
  204 + maxx = para.get("maxx")
  205 + maxy = para.get("maxy")
  206 +
202 207 xml = xml_format.format(name = para.get("name"),
203   - xmin = extent[0],
204   - xmax = extent[1],
205   - ymin = extent[2],
206   - ymax = extent[3],
  208 + xmin = minx if minx else extent[0],
  209 + xmax = maxx if maxx else extent[1],
  210 + ymin = miny if miny else extent[2],
  211 + ymax = maxy if maxy else extent[3],
207 212 feature_count = table.feature_count,
208 213 database_guid = table.database_guid,
209 214 gemetry_type = gemetry_type,
... ... @@ -302,12 +307,23 @@ class Api(ApiTemplate):
302 307 "type": "string",
303 308 "description": "表名",
304 309 "required": "true"},
305   -
306 310 {"name": "token",
307 311 "in": "formData",
308 312 "type": "string",
309 313 "description": "token",
310 314 "required": "true"},
  315 + {"name": "minx",
  316 + "in": "formData",
  317 + "type": "string"},
  318 + {"name": "miny",
  319 + "in": "formData",
  320 + "type": "string"},
  321 + {"name": "maxx",
  322 + "in": "formData",
  323 + "type": "string"},
  324 + {"name": "maxy",
  325 + "in": "formData",
  326 + "type": "string"},
311 327 ],
312 328 "responses": {
313 329 200: {
... ...
... ... @@ -3,7 +3,7 @@
3 3 #createtime: 2021/10/26
4 4 #email: nheweijun@sina.com
5 5
6   -from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time,Float,Binary
  6 +from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime
7 7 from sqlalchemy.orm import relationship
8 8 from app.models import db
9 9
... ...
... ... @@ -104,6 +104,7 @@ class Api(ApiTemplate):
104 104 # 显示别名
105 105 user_alias = UserAlias()
106 106 for service_json in res["data"]["list"]:
  107 +
107 108 service_json["display_name"] = user_alias.get_alias(service_json["creator"])
108 109
109 110 res["result"] = True
... ...
... ... @@ -6,6 +6,8 @@
6 6 from app.util.component.ApiTemplate import ApiTemplate
7 7 from .models import Service
8 8 from .util.ServiceType import ServiceType
  9 +
  10 +
9 11 class Api(ApiTemplate):
10 12 api_name = "注册服务"
11 13 def process(self):
... ...
... ... @@ -27,7 +27,6 @@ class Api(ApiTemplate):
27 27 if service:
28 28 service.state = state
29 29
30   -
31 30 operate = "startService" if state == 1 else "stopService"
32 31 server_type = "tileserver" if s_type == "电子地图" else "mapserver"
33 32 dmap_engine_url = "{}/dmap/api/manager/{}?servicename={}&servername={}".format(configure.dmap_engine,
... ...
... ... @@ -35,7 +35,7 @@ class Api(ApiTemplate):
35 35 service_update = {"update_time":this_time}
36 36 tile_update = {}
37 37 for key in self.para.keys():
38   - if key in ["name","title","state","description","overview","catalog_guid"]:
  38 + if key in ["name","title","description","overview","catalog_guid"]:
39 39 service_update[key] = self.para.get(key)
40 40 if key in ["name","tile_type","vendor","crs","datasource","description",
41 41 "layer_name","layer_alias","layer_title","layer_style","layer_format",
... ... @@ -61,7 +61,8 @@ class Api(ApiTemplate):
61 61
62 62 para = {"name":self.para.get("name") if self.para.get("name") else se.name,
63 63 "title":self.para.get("title") if self.para.get("title") else se.title,
64   - "type":"tileserver","capabilities":1 if tile_type == "WMTS" else 16,"project":project_file}
  64 + "type":"tileserver","capabilities":1 if tile_type == "WMTS" else 16,"project":project_file,
  65 + "state": service.state}
65 66
66 67
67 68 tile_service_edit_url = "{}/dmap/api/manager/RegService".format(configure.dmap_engine)
... ...
... ... @@ -7,7 +7,6 @@ from flask import current_app,request
7 7 import traceback
8 8 import json
9 9 from app.models import db
10   -from app.modules.auth.models import OAuth2Token,User
11 10 import app
12 11
13 12 class ApiTemplate:
... ...
... ... @@ -3,6 +3,7 @@
3 3 #createtime: 2021/5/24
4 4 #email: nheweijun@sina.com
5 5 from osgeo import ogr
  6 +from osgeo.ogr import Layer
6 7 from sqlalchemy import create_engine
7 8 from sqlalchemy.orm import sessionmaker,Session
8 9 from app.util.component.StructurePrint import StructurePrint
... ... @@ -126,16 +127,19 @@ class PGUtil:
126 127
127 128 @classmethod
128 129 def get_srid(cls,pg_ds,table_name):
129   - layer = pg_ds.GetLayerByName(table_name)
  130 + layer:Layer = pg_ds.GetLayerByName(table_name)
130 131 if not layer:
131 132 return None
132   - srid_sql = '''select st_srid("{}") from public."{}" limit 1'''.format(layer.GetGeometryColumn(), layer.GetName())
  133 +
  134 + srid_sql ="SELECT srid FROM public.geometry_columns where f_table_name='{}'".format(table_name)
  135 +
133 136 srid_layer = pg_ds.ExecuteSQL(srid_sql)
134 137 srid_feature = srid_layer.GetNextFeature()
135 138 if srid_feature:
136 139 if srid_feature.GetField(0):
137 140 return int(srid_feature.GetField(0))
138 141 else:
  142 +
139 143 return None
140 144
141 145
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/15
  4 +#email: nheweijun@sina.com
  5 +
  6 +from osgeo import ogr
  7 +from osgeo.ogr import *
  8 +import math
  9 +import os
  10 +import copy
  11 +from test.zonghe.RepresentPoint import RepresentPoint
  12 +import time
  13 +
  14 +class DelauneyNode:
  15 +
  16 + def __init__(self, rp):
  17 + self.rp = rp
  18 + self.children_nodes = list()
  19 + self.children_delauney_lines = list()
  20 +
  21 + def get_all_node(self):
  22 + for node in self.children_nodes:
  23 + yield node.get_all_node()
  24 + yield self
  25 +
  26 + def get_rps(self):
  27 + for node in self.children_nodes:
  28 + for rp in node.get_rps():
  29 + yield rp
  30 + yield self.rp
  31 +
  32 + def get_polygons(self):
  33 + for node in self.children_nodes:
  34 + for rp in node.get_rps():
  35 + yield rp.polygon
  36 + yield self.rp.polygon
  37 +
  38 + def get_delauney_lines(self):
  39 + for node in self.children_nodes:
  40 + for ll in node.get_delauney_lines():
  41 + yield ll
  42 + for l in self.children_delauney_lines:
  43 + yield l
  44 +
  45 + def add_children(self,node,delauney_line):
  46 + self.children_nodes.append(node)
  47 + self.children_delauney_lines.append(delauney_line)
  48 +
  49 +class DelauneyLine:
  50 +
  51 + def __init__(self,rp1,rp2):
  52 +
  53 + self.rp1 = rp1
  54 + self.rp2 = rp2
  55 + self.distance = rp1.polygon.Distance(rp2.polygon)
  56 +
  57 + self.line = ogr.Geometry(ogr.wkbLineString)
  58 + self.line.AddPoint(self.rp1.point.GetX(),self.rp1.point.GetY())
  59 + self.line.AddPoint(self.rp2.point.GetX(),self.rp2.point.GetY())
  60 +
  61 +
  62 +class DelauneyMinTree:
  63 +
  64 + def __init__(self):
  65 + self.delauney_lines_list = list()
  66 + self.rps = set()
  67 + self.touch_delauney_lines = set()
  68 +
  69 + def append(self,delauney_line,other_delauney_lines_kv):
  70 +
  71 +
  72 + candicates = []
  73 + if not self.rps.__contains__(delauney_line.rp1):
  74 + self.rps.add(delauney_line.rp1)
  75 +
  76 + candicates.extend(other_delauney_lines_kv.get(delauney_line.rp1))
  77 +
  78 + if not self.rps.__contains__(delauney_line.rp2):
  79 + self.rps.add(delauney_line.rp2)
  80 +
  81 + candicates.extend(other_delauney_lines_kv.get(delauney_line.rp2))
  82 +
  83 + for candicate in candicates:
  84 + if (candicate.rp1 in self.rps) and (candicate.rp2 in self.rps):
  85 + #初始化
  86 + try:
  87 + self.touch_delauney_lines.remove(candicate)
  88 + except:
  89 + print(111)
  90 +
  91 + else:
  92 + self.touch_delauney_lines.add(candicate)
  93 +
  94 + self.delauney_lines_list.append(delauney_line)
  95 +
  96 +
  97 +
  98 + def get_rps(self):
  99 + return self.rps
  100 +
  101 +
  102 + def get_other_relate_delauney_lines(self,other_delauney_lines_kv,rps_set):
  103 +
  104 + other_relate_delauney_lines = []
  105 +
  106 + for rp in self.rps:
  107 + candicates = other_delauney_lines_kv.get(rp)
  108 + candicates = [c for c in candicates if c.rp1 in rps_set or c.rp2 in rps_set]
  109 + other_relate_delauney_lines.extend(candicates)
  110 +
  111 + # other_relate_delauney_lines.append()
  112 +
  113 + return other_relate_delauney_lines
  114 +
  115 + def get_other_rp(self,delauney_line):
  116 + rp1 = delauney_line.rp1
  117 + rp2 = delauney_line.rp2
  118 +
  119 + if not self.rps.__contains__(rp1):
  120 + return rp1
  121 + if not self.rps.__contains__(rp2):
  122 + return rp2
  123 + return None
  124 +
  125 +
  126 +
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/31
  4 +#email: nheweijun@sina.com
  5 +
  6 +# coding=utf-8
  7 +#author: 4N
  8 +#createtime: 2022/3/8
  9 +#email: nheweijun@sina.com
  10 +
  11 +
  12 +from osgeo import ogr
  13 +from osgeo.ogr import *
  14 +import math
  15 +import os
  16 +import copy
  17 +os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
  18 +from test.MapSynthesize.ShapeData import ShapeData
  19 +from test.MapSynthesize.Delauney import DelauneyNode,DelauneyLine,DelauneyMinTree
  20 +from test.MapSynthesize.RepresentPoint import RepresentPoint
  21 +from test.MapSynthesize.PolygonMerge import PolygonMerge
  22 +import cv2
  23 +import time
  24 +import numpy as np
  25 +
  26 +class MapSynthesize:
  27 +
  28 + data:ShapeData
  29 + area_threshold = 10.0
  30 + buffer_threshold = 100.0
  31 + distance_buffer_threshold = 1.114691025217302e-04
  32 +
  33 + def __init__(self,data):
  34 + self.data = data
  35 +
  36 +
  37 + #只处理Polygon,MultiPolygon要拆开
  38 + def get_polygon_reprecent_point(self,polygon:Geometry):
  39 +
  40 + polygon_env = polygon.GetEnvelope()
  41 +
  42 + area_thre = polygon.GetArea()/self.area_threshold
  43 +
  44 + line_length = math.sqrt(math.pow(polygon_env[1] - polygon_env[0],2) + math.pow(polygon_env[3] - polygon_env[2],2))
  45 +
  46 + short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2])
  47 +
  48 + center:Geometry = polygon.Centroid()
  49 + # print(center)
  50 +
  51 +
  52 + # 提前return
  53 + if polygon.Contains(center):
  54 + # print("\"" + center.ExportToWkt() + "\",")
  55 + return RepresentPoint(center, polygon)
  56 +
  57 +
  58 + last_state = None
  59 + line = None
  60 + calculate_time = 0
  61 +
  62 + direction = self.get_direction(polygon, center, line_length)
  63 +
  64 +
  65 + in_hole = False
  66 + in_hole_line = None
  67 +
  68 +
  69 + #无孔Polygon
  70 + if polygon.GetGeometryCount() == 1:
  71 + polygon_line = ogr.ForceToLineString(polygon)
  72 +
  73 + # 有孔Polygon,要分2种情况
  74 + else:
  75 + polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  76 + for i in range(1,polygon.GetGeometryCount()):
  77 + hole_line = polygon.GetGeometryRef(i)
  78 + hole_polygon : Geometry = ogr.ForceToPolygon(hole_line)
  79 + if hole_polygon.Contains(center):
  80 + in_hole = True
  81 + direction = range(0,190,10)
  82 + in_hole_line = ogr.ForceToLineString(hole_line)
  83 + # print("in_hole")
  84 +
  85 + angle1,angle2=None,None
  86 + line = None
  87 + oneside_area, otherside_area = None,None
  88 + for angle in direction:
  89 +
  90 + if in_hole:
  91 + line = self.get_doubleline(center.GetX(),center.GetY(),angle,line_length)
  92 + else:
  93 + line = self.get_line(center.GetX(),center.GetY(),angle,line_length)
  94 +
  95 + oneside_area, otherside_area = self.jude(polygon, line, angle, line_length)
  96 +
  97 +
  98 + if oneside_area > 0 and otherside_area >0:
  99 + if abs(oneside_area-otherside_area) < area_thre:
  100 + break
  101 +
  102 + if last_state is None:
  103 +
  104 + angle2 = angle
  105 +
  106 + if oneside_area == 0 and otherside_area==0:
  107 + last_state = 0
  108 + else:
  109 + last_state = 1 if oneside_area < otherside_area else -1
  110 + else:
  111 +
  112 + angle1 = angle2
  113 + angle2 = angle
  114 +
  115 + if oneside_area == 0 and otherside_area==0:
  116 + now_state = 0
  117 + else:
  118 + now_state = 1 if oneside_area < otherside_area else -1
  119 +
  120 + if last_state* now_state < 0:
  121 + # print(angle)
  122 + break
  123 + else:
  124 + last_state = now_state
  125 +
  126 + #第一条线就是均分线
  127 + if angle1 is None or angle2 is None:
  128 + pass
  129 + else:
  130 + #如果面积差大于阈值,二分法查找
  131 + if abs(oneside_area - otherside_area) > area_thre:
  132 + line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre)
  133 +
  134 +
  135 + # 提前return
  136 + if in_hole:
  137 +
  138 + point_intersection: Geometry = line.Intersection(in_hole_line)
  139 + plist = []
  140 + for i in range(point_intersection.GetGeometryCount()):
  141 + pi = point_intersection.GetGeometryRef(i)
  142 + plist.append(pi)
  143 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  144 + plist_d.sort(key=lambda x:x[1])
  145 +
  146 + nearest_point= plist_d[0][0]
  147 + firt_short_length = short_length/20.0
  148 + radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length)
  149 + # print("\"" + other_point.ExportToWkt() + "\",")
  150 +
  151 +
  152 + while not polygon.Contains(other_point):
  153 +
  154 + firt_short_length = firt_short_length / 2
  155 + radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(),
  156 + nearest_point.GetY(), firt_short_length)
  157 +
  158 +
  159 +
  160 + return RepresentPoint(other_point,polygon)
  161 +
  162 +
  163 + point_intersection:Geometry = line.Intersection(polygon_line)
  164 + xlist = []
  165 + ylist = []
  166 + plist = []
  167 +
  168 + for i in range(point_intersection.GetGeometryCount()):
  169 + pi = point_intersection.GetGeometryRef(i)
  170 + xlist.append(pi.GetX())
  171 + ylist.append(pi.GetY())
  172 + plist.append(pi)
  173 +
  174 +
  175 + reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0]
  176 +
  177 + reprecent_point = self.creat_point(reprecent_point)
  178 +
  179 + if not polygon.Contains(reprecent_point):
  180 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  181 + plist_d.sort(key=lambda x:x[1])
  182 + reprecent_point = self.creat_point(((plist_d[0][0].GetX()+ plist_d[1][0].GetX())/2.0, (plist_d[0][0].GetY()+plist_d[1][0].GetY())/2.0))
  183 +
  184 + # print("\""+reprecent_point.ExportToWkt() + "\",")
  185 +
  186 + rp = RepresentPoint(reprecent_point,polygon)
  187 +
  188 + return rp
  189 +
  190 + def get_line(self, x0, y0 , angle, r):
  191 +
  192 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  193 + line.AddPoint(x0, y0)
  194 + hudu = angle/360.0 * 2 * math.pi
  195 + dx = math.sin(hudu) * r
  196 + dy = math.cos(hudu) * r
  197 + line.AddPoint(x0+dx, y0+dy)
  198 +
  199 + return line
  200 +
  201 + def get_doubleline(self, x0, y0 , angle, r):
  202 +
  203 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  204 +
  205 + hudu = angle/360.0 * 2 * math.pi
  206 + dx = math.sin(hudu) * r
  207 + dy = math.cos(hudu) * r
  208 +
  209 + hudu = (angle+180)/360.0 * 2 * math.pi
  210 + dx2 = math.sin(hudu) * r
  211 + dy2 = math.cos(hudu) * r
  212 +
  213 + line.AddPoint(x0 + dx2, y0 + dy2)
  214 + line.AddPoint(x0+dx, y0+dy)
  215 +
  216 + return line
  217 +
  218 + def get_radline(self,x0,y0,x1,y1,len_size):
  219 + a2 = math.pow((x1-x0),2)
  220 + b2 = math.pow((y1-y0),2)
  221 + len_size = len_size+ math.sqrt(a2+b2)
  222 +
  223 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  224 + line.AddPoint(x0, y0)
  225 + tanx = abs(y1-y0) / abs(x1-x0)
  226 + cosx = 1 / math.sqrt(1 + tanx *tanx)
  227 + dx = cosx* len_size
  228 + dy = tanx * dx
  229 +
  230 + if x1 == x0:
  231 + x2 = x0
  232 + if y1 > y0 :
  233 + y2 = y0 + abs(dy)
  234 + else:
  235 + y2 = y0 - abs(dy)
  236 + else:
  237 + if x1 < x0:
  238 + x2 = x0 - dx
  239 + else:
  240 + x2 = x0 + dx
  241 +
  242 + if y1 < y0:
  243 + y2 = y0 - dy
  244 + else:
  245 + y2 = y0 + dy
  246 +
  247 + line.AddPoint(x2, y2)
  248 +
  249 + other_point = ogr.Geometry(ogr.wkbPoint)
  250 + other_point.AddPoint(x2, y2)
  251 +
  252 + return line , other_point
  253 +
  254 + def get_direction(self,polygon,center,line_length):
  255 + '''
  256 + 判断旋转方向
  257 + :param polygon:
  258 + :param center:
  259 + :param line_length:
  260 + :return:
  261 + '''
  262 +
  263 + line = self.get_line(center.GetX(),center.GetY(),0,line_length)
  264 +
  265 + oneside_area, otherside_area = self.jude(polygon,line,0,line_length)
  266 +
  267 + if oneside_area == 0 and otherside_area == 0 :
  268 + return range(0, 390, 30)
  269 + else:
  270 + line = self.get_line(center.GetX(), center.GetY(), 10, line_length)
  271 + oneside_area_contrast, otherside_area_contrast = self.jude(polygon, line, 30, line_length)
  272 +
  273 + if oneside_area_contrast == 0 and otherside_area_contrast == 0:
  274 + return range(360, -30, -30)
  275 + else:
  276 + if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast):
  277 + return range(0, 390, 30)
  278 + else:
  279 + return range(360, -30, -30)
  280 +
  281 + def jude(self,polygon,line,angle,line_length):
  282 +
  283 + line_buffer: Geometry = line.Buffer(line_length / self.buffer_threshold)
  284 + clip_geom: Geometry = polygon.Difference(line_buffer)
  285 +
  286 + oneside_area = 0
  287 + otherside_area = 0
  288 +
  289 + gc = clip_geom.GetGeometryCount()
  290 + if gc <= 1:
  291 + oneside_area = 0
  292 + otherside_area = 0
  293 + else:
  294 + triangle1, triangle2 = self.get_side_triangle(line, angle)
  295 +
  296 +
  297 + for gi in range(clip_geom.GetGeometryCount()):
  298 + clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi)
  299 + it = clip_geom_i.Intersection(triangle1)
  300 +
  301 + if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect(
  302 + line_buffer):
  303 + oneside_area += clip_geom_i.GetArea()
  304 + else:
  305 + otherside_area += clip_geom_i.GetArea()
  306 + return oneside_area, otherside_area
  307 +
  308 + def division(self,polygon,center,in_hole,line_length,angle1,angle2,area_thre):
  309 + '''
  310 + 二分法查找
  311 + :param polygon:
  312 + :param center:
  313 + :param in_hole:
  314 + :param line_length:
  315 + :param angle1:
  316 + :param angle2:
  317 + :param area_thre:
  318 + :return:
  319 + '''
  320 +
  321 + mid_angle = (angle1 + angle2)/2.0
  322 +
  323 +
  324 + if in_hole:
  325 + line = self.get_doubleline(center.GetX(), center.GetY(), mid_angle, line_length)
  326 + else:
  327 + line = self.get_line(center.GetX(), center.GetY(), mid_angle, line_length)
  328 +
  329 + one,other = self.jude(polygon,line,mid_angle,line_length)
  330 +
  331 + while abs(one - other) > area_thre:
  332 + if one > other:
  333 + if angle1 > angle2:
  334 + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre)
  335 + else:
  336 + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre)
  337 + else:
  338 + if angle1 > angle2:
  339 + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre)
  340 + else:
  341 + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre)
  342 + return line
  343 +
  344 + def get_side_triangle(self,line:Geometry,angle):
  345 + '''
  346 + 获取方向三角形
  347 + :param line:
  348 + :param angle:
  349 + :return:
  350 + '''
  351 +
  352 + start = line.GetPoint(0)
  353 + end = line.GetPoint(1)
  354 +
  355 +
  356 + angle_t = angle-30
  357 + hudu = angle_t/360.0 * 2 * math.pi
  358 +
  359 + r = line.Length() / (2*math.cos( math.pi/6))
  360 + dx = math.sin(hudu) * r
  361 + dy = math.cos(hudu) * r
  362 +
  363 +
  364 + ring1 = ogr.Geometry(ogr.wkbLinearRing)
  365 + ring1.AddPoint(start[0], start[1])
  366 + ring1.AddPoint(start[0] + dx, start[1] + dy)
  367 + ring1.AddPoint(end[0], end[1])
  368 + ring1.AddPoint(start[0], start[1])
  369 + triangle1 = ogr.Geometry(ogr.wkbPolygon)
  370 + triangle1.AddGeometry(ring1)
  371 +
  372 +
  373 + angle_t = angle+30
  374 + hudu = angle_t/360.0 * 2 * math.pi
  375 +
  376 + r = line.Length() / (2*math.cos( math.pi/6))
  377 +
  378 + dx = math.sin(hudu) * r
  379 + dy = math.cos(hudu) * r
  380 +
  381 + ring2 = ogr.Geometry(ogr.wkbLinearRing)
  382 + ring2.AddPoint(start[0], start[1])
  383 + ring2.AddPoint(start[0]+dx, start[1]+dy)
  384 + ring2.AddPoint(end[0], end[1])
  385 + ring2.AddPoint(start[0], start[1])
  386 + triangle2 = ogr.Geometry(ogr.wkbPolygon)
  387 + triangle2.AddGeometry(ring2)
  388 +
  389 + return triangle1,triangle2
  390 +
  391 + def creat_point(self,tuple):
  392 + p: Geometry = ogr.Geometry(ogr.wkbPoint)
  393 + p.AddPoint(tuple[0], tuple[1])
  394 + return p
  395 +
  396 + def create_delauney(self,rps):
  397 + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
  398 +
  399 + rp_dict = {}
  400 + delauney_lines = []
  401 +
  402 + rps_sub = set()
  403 + for rp in rps:
  404 + multipoint.AddGeometry(rp.point)
  405 + # 多边形代表点相同,需要融合多边形
  406 + if rp_dict.get(rp.point.GetPoint(0).__str__()):
  407 + rp_exist = rp_dict.get(rp.point.GetPoint(0).__str__())
  408 + rp_exist.polygon = rp_exist.polygon.Union(rp.polygon)
  409 + else:
  410 + rp_dict[rp.point.GetPoint(0).__str__()] = rp
  411 + rps_sub.add(rp)
  412 +
  413 + delauney:Geometry = multipoint.DelaunayTriangulation(bOnlyEdges=True)
  414 +
  415 + for index in range(delauney.GetGeometryCount()):
  416 + triangle_line:Geometry = delauney.GetGeometryRef(index)
  417 + p = triangle_line.GetPoint(0)
  418 + p_next = triangle_line.GetPoint(1)
  419 +
  420 + rp1 = rp_dict.get(p.__str__())
  421 + rp2 = rp_dict.get(p_next.__str__())
  422 +
  423 + delauney_line = DelauneyLine(rp1,rp2)
  424 + delauney_lines.append(delauney_line)
  425 +
  426 + return delauney_lines,rps_sub
  427 +
  428 + def create_min_delauney(self,delauney_lines,rps):
  429 + '''
  430 + 使用prim算法计算最小生成树
  431 + :param delauney_lines:
  432 + :param polygons:
  433 + :return:
  434 + '''
  435 +
  436 + kv = dict()
  437 + print(len(rps))
  438 +
  439 +
  440 + rps_set = set(rps)
  441 +
  442 + for delauney_line in delauney_lines:
  443 + if kv.get(delauney_line.rp1):
  444 + kv[delauney_line.rp1].add(delauney_line)
  445 + else:
  446 + kv[delauney_line.rp1] = set()
  447 + kv[delauney_line.rp1].add(delauney_line)
  448 +
  449 + if kv.get(delauney_line.rp2):
  450 + kv[delauney_line.rp2].add(delauney_line)
  451 + else:
  452 + kv[delauney_line.rp2] = set()
  453 + kv[delauney_line.rp2].add(delauney_line)
  454 +
  455 + print(len(kv))
  456 +
  457 + print("完成三角边倒排索引")
  458 +
  459 + #初始化树
  460 + delauney_lines = sorted(delauney_lines,key=lambda x:x.distance)
  461 + delauney_min_tree = DelauneyMinTree()
  462 +
  463 + delauney_min_tree.append(delauney_lines[0],kv)
  464 +
  465 + rps_set.remove(delauney_lines[0].rp1)
  466 + rps_set.remove(delauney_lines[0].rp2)
  467 +
  468 + kv[delauney_lines[0].rp1].remove(delauney_lines[0])
  469 + kv[delauney_lines[0].rp2].remove(delauney_lines[0])
  470 +
  471 + print("完成最小生成树初始化")
  472 +
  473 + while rps_set.__len__()>0:
  474 +
  475 + print(rps_set.__len__())
  476 + t1 = time.time()
  477 + # relate_delauney_line = delauney_min_tree.get_other_relate_delauney_lines(kv,rps_set)
  478 +
  479 + relate_delauney_line = delauney_min_tree.touch_delauney_lines
  480 +
  481 +
  482 + relate_delauney_line_sort = sorted(relate_delauney_line,key=lambda x:x.distance)
  483 +
  484 + min_distance_line = relate_delauney_line_sort[0]
  485 + #删除
  486 + other_rp = delauney_min_tree.get_other_rp(min_distance_line)
  487 +
  488 + if other_rp is None:
  489 + kv[min_distance_line.rp1].remove(min_distance_line)
  490 + kv[min_distance_line.rp2].remove(min_distance_line)
  491 + continue
  492 +
  493 + delauney_min_tree.append(min_distance_line,kv)
  494 +
  495 + rps_set.remove(other_rp)
  496 +
  497 + kv[min_distance_line.rp1].remove(min_distance_line)
  498 + kv[min_distance_line.rp2].remove(min_distance_line)
  499 +
  500 + # print(time.time() - t2)
  501 + print("完成最小生成树")
  502 +
  503 + return delauney_min_tree
  504 +
  505 + def cut_delauney_min_tree(self,delauney_min_tree:DelauneyMinTree,threshold):
  506 +
  507 + trees = []
  508 + kv = {}
  509 +
  510 + count = 0
  511 +
  512 + for delauney_line in delauney_min_tree.delauney_lines_list:
  513 +
  514 + dn1 = kv.get(delauney_line.rp1)
  515 + dn2 = kv.get(delauney_line.rp2)
  516 +
  517 +
  518 + if not dn1:
  519 + dn1 = DelauneyNode(delauney_line.rp1)
  520 + kv[delauney_line.rp1] = dn1
  521 +
  522 + if not dn2:
  523 +
  524 + trees.append(dn1)
  525 +
  526 + dn2 = DelauneyNode(delauney_line.rp2)
  527 + kv[delauney_line.rp2] = dn2
  528 +
  529 + if delauney_line.distance < threshold:
  530 + dn1.add_children(dn2,delauney_line)
  531 + count +=1
  532 +
  533 + else:
  534 + #断开
  535 + trees.append(dn2)
  536 + else:
  537 +
  538 + if delauney_line.distance < threshold:
  539 + dn2.add_children(dn1,delauney_line)
  540 + count += 1
  541 + else:
  542 + trees.append(dn1)
  543 + else:
  544 +
  545 + dn2 = DelauneyNode(delauney_line.rp2)
  546 + kv[delauney_line.rp2] = dn2
  547 +
  548 + if delauney_line.distance < threshold:
  549 + dn1.add_children(dn2,delauney_line)
  550 + count += 1
  551 + else:
  552 + trees.append(dn2)
  553 +
  554 +
  555 + return trees
  556 +
  557 + def create_polygon(self,p1,p2,p3,p4):
  558 +
  559 + ring = ogr.Geometry(ogr.wkbLinearRing)
  560 + ring.AddPoint(p1[0], p1[1])
  561 + ring.AddPoint(p2[0], p2[1])
  562 + ring.AddPoint(p3[0], p3[1])
  563 + ring.AddPoint(p4[0], p4[1])
  564 + ring.AddPoint(p1[0], p1[1])
  565 +
  566 + poly = ogr.Geometry(ogr.wkbPolygon)
  567 + poly.AddGeometry(ring)
  568 + return poly
  569 +
  570 + def get_polygon_lines(self,polygon):
  571 + #无孔Polygon
  572 + if polygon.GetGeometryCount() in [0,1]:
  573 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  574 + # 有孔Polygon
  575 + else:
  576 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  577 +
  578 + return polygon_line
  579 +
  580 + def merge_concave(self, trees, distance_threshold):
  581 + merge_polygons = []
  582 + count = 1
  583 +
  584 + for tree in trees:
  585 + print(count)
  586 + count+=1
  587 + polygons = list(tree.get_polygons())
  588 +
  589 + merge_raw: Geometry = polygons[0]
  590 + for p in polygons:
  591 + merge_raw = merge_raw.Union(p)
  592 +
  593 + points = []
  594 +
  595 +
  596 + for i in range(merge_raw.GetGeometryCount()):
  597 +
  598 + poly = merge_raw.GetGeometryRef(i)
  599 + poly_line :Geometry = self.get_polygon_lines(poly)
  600 + if poly_line:
  601 + for indx in range(poly_line.GetPointCount() - 1):
  602 + poi = poly_line.GetPoint(indx)
  603 +
  604 + points.append(poi)
  605 +
  606 + poi_next = poly_line.GetPoint(indx + 1)
  607 +
  608 + dis = math.sqrt(math.pow(poi[0] - poi_next[0], 2) + math.pow(poi[1] - poi_next[1], 2))
  609 + # print(dis)
  610 + if dis > distance_threshold:
  611 + times = int(dis / distance_threshold)
  612 + # print(times)
  613 + for time in range(1, times + 1):
  614 + x, y = self.get_subpoint(poi[0], poi[1], poi_next[0], poi_next[1], (time * distance_threshold))
  615 + points.append([x, y])
  616 +
  617 + points = np.array([[p[0], p[1]] for p in points])
  618 +
  619 +
  620 + cp = []
  621 + for pp in points:
  622 + poi = ogr.Geometry(ogr.wkbPoint)
  623 + poi.AddPoint(pp[0], pp[1])
  624 + cp.append(poi)
  625 +
  626 + merge_p_line = concaveHull(points, 3)
  627 +
  628 + ring = ogr.Geometry(ogr.wkbLinearRing)
  629 +
  630 + merge_p = ogr.Geometry(ogr.wkbPolygon)
  631 +
  632 + for l in merge_p_line:
  633 + ring.AddPoint(l[0], l[1])
  634 +
  635 + ring.AddPoint(merge_p_line[0][0], merge_p_line[0][1])
  636 +
  637 + merge_p.AddGeometry(ring)
  638 + merge_p = merge_p.Simplify(self.distance_buffer_threshold/10)
  639 + merge_polygons.append(merge_p)
  640 +
  641 + return merge_polygons
  642 +
  643 + def get_subpoint(self, x0, y0, x1, y1, len_size):
  644 +
  645 + len_size = len_size
  646 + tanx = abs(y1 - y0) / abs(x1 - x0)
  647 + cosx = 1 / math.sqrt(1 + tanx * tanx)
  648 + dx = cosx * len_size
  649 + dy = tanx * dx
  650 +
  651 + if x1 == x0:
  652 + x2 = x0
  653 + if y1 > y0:
  654 + y2 = y0 + abs(dy)
  655 + else:
  656 + y2 = y0 - abs(dy)
  657 + else:
  658 + if x1 < x0:
  659 + x2 = x0 - dx
  660 + else:
  661 + x2 = x0 + dx
  662 +
  663 + if y1 < y0:
  664 + y2 = y0 - dy
  665 + else:
  666 + y2 = y0 + dy
  667 +
  668 + return x2, y2
  669 +
  670 + def process(self):
  671 + polygons = self.data.get_polygons()
  672 + rps = []
  673 +
  674 + for poly in polygons:
  675 + rp = self.get_polygon_reprecent_point(poly)
  676 + rps.append(rp)
  677 + print("完成代表点计算")
  678 +
  679 + #代表点要融合
  680 + delauney_lines,rps_sub = self.create_delauney(rps)
  681 +
  682 + print("完成树生成计算")
  683 + min_delauney = self.create_min_delauney(delauney_lines,rps_sub)
  684 + print("完成最小生成树计算")
  685 + trees = self.cut_delauney_min_tree(min_delauney,self.distance_buffer_threshold)
  686 + print("完成树裁剪")
  687 +
  688 + polygon_result = []
  689 + for index,tree in enumerate(trees):
  690 +
  691 + polygons = tree.get_polygons()
  692 + print(index)
  693 + polygons = list(polygons)
  694 + print(len(polygons))
  695 + polygon_result.append(PolygonMerge.merge(polygons,self.distance_buffer_threshold))
  696 +
  697 + # polygons = self.merge_concave(trees,self.distance_buffer_threshold)
  698 +
  699 + return [p.ExportToWkt() for p in polygon_result]
  700 +
  701 +if __name__ == '__main__':
  702 +
  703 +
  704 +
  705 + t1 = time.time()
  706 + sd = ShapeData(r"J:\Data\制图综合result\zhongshansub.shp")
  707 +
  708 + mapsynthesize = MapSynthesize(sd)
  709 + wkts = mapsynthesize.process()
  710 + result = r"J:\Data\制图综合result\zhongshansub_merge22.shp"
  711 + ShapeData.create_shp_fromwkts(result,"zh",wkts)
  712 +
  713 + print(time.time()-t1)
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/30
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from osgeo import ogr,gdal
  8 +from osgeo.ogr import *
  9 +
  10 +from test.zonghe.ShapeData import ShapeData
  11 +import copy
  12 +
  13 +from rtreelib import RTree,Rect
  14 +
  15 +
  16 +
  17 +class RTreeData:
  18 +
  19 + def __init__(self,triangle,state):
  20 + self.state = state
  21 + self.triangle = triangle
  22 +
  23 + def set_state(self,state):
  24 + self.state = state
  25 +
  26 +
  27 +def env2rect(env):
  28 + return Rect(env[0],env[2],env[1],env[3])
  29 +
  30 +
  31 +class PolygonMerge:
  32 +
  33 + @classmethod
  34 + def get_delauney(cls,polygon):
  35 +
  36 + polygon_line = cls.get_polygon_lines(polygon)
  37 + polygon_line_points:list = polygon_line.GetPoints()
  38 +
  39 + if len(polygon_line_points)==4:
  40 + tris = [polygon]
  41 + else:
  42 + d = 0
  43 + for ind in range(len(polygon_line_points) - 1):
  44 + p = polygon_line_points[ind]
  45 + p_n = polygon_line_points[ind + 1]
  46 +
  47 + d += -0.5 * (p_n[1] + p[1]) * (p_n[0] - p[0])
  48 +
  49 + if d < 0:
  50 + polygon_line_points.reverse()
  51 +
  52 + tris = list(cls.get_tri(polygon_line_points))
  53 +
  54 + return tris
  55 +
  56 + @classmethod
  57 + def get_tri(cls,polygon_line_points:list):
  58 +
  59 + if len(polygon_line_points) == 4 or len(polygon_line_points) == 3:
  60 + yield cls.create_polygon(polygon_line_points)
  61 + else:
  62 + for index,point in enumerate(polygon_line_points):
  63 + if index == 0:
  64 + continue
  65 + else:
  66 + try:
  67 + point_front = polygon_line_points[index-1]
  68 + point_next = polygon_line_points[index+1]
  69 + except Exception as e:
  70 + print(e)
  71 + kk=1
  72 + d=1
  73 +
  74 + check = (point[0]-point_front[0]) * (point_next[1]-point[1]) - (point_next[0]-point[0])*(point[1]-point_front[1])
  75 +
  76 + if check > 0:
  77 + triangle = cls.create_polygon([point_front,point,point_next,point_front])
  78 + yield triangle
  79 +
  80 + polygon_line_points.pop(index)
  81 + for tri in cls.get_tri(polygon_line_points):
  82 + yield tri
  83 + break
  84 +
  85 + @classmethod
  86 + def merge(cls,polygons:list,distance_buffer_threshold):
  87 +
  88 + rtree = RTree()
  89 +
  90 + polygon:Geometry = polygons[0]
  91 + # multipolygon = ogr.Geometry(ogr.wkbMultiPolygon)
  92 + # for poly in polygons:
  93 + # multipolygon.AddGeometry(poly)
  94 +
  95 + for poly in polygons:
  96 + polygon = polygon.Union(poly)
  97 +
  98 +
  99 +
  100 + delauney: Geometry = polygon.DelaunayTriangulation()
  101 +
  102 + for index in range(delauney.GetGeometryCount()):
  103 + de:Geometry = copy.deepcopy(delauney.GetGeometryRef(index))
  104 + de_extent = de.GetEnvelope()
  105 + rtree.insert(RTreeData(de,1), env2rect(de_extent))
  106 +
  107 + bians: list = cls.get_bian(polygon)
  108 +
  109 +
  110 + for bian in bians:
  111 +
  112 + bian_ext = bian.GetEnvelope()
  113 +
  114 + query_result = rtree.query(env2rect(bian_ext))
  115 +
  116 + intersection_data = []
  117 +
  118 +
  119 + for entry in query_result:
  120 +
  121 + # 已被抛弃的不要
  122 + if entry.data.state == 0:
  123 + continue
  124 + intersection_geom: Geometry = bian.Intersection(entry.data.triangle)
  125 +
  126 + if not intersection_geom.IsEmpty():
  127 + if not intersection_geom.Equals(bian):
  128 + if intersection_geom.GetGeometryType() in [2, 5, -2147483643, -2147483646, 3002, 3005]:
  129 + intersection_data.append(entry.data)
  130 +
  131 +
  132 + for data in intersection_data:
  133 + data.set_state(0)
  134 +
  135 + if intersection_data:
  136 +
  137 + inter_tri_merge:Geometry = intersection_data[0].triangle
  138 +
  139 + for ind in range(1,len(intersection_data)):
  140 + inter_tri_merge = inter_tri_merge.Union(intersection_data[ind].triangle)
  141 +
  142 +
  143 + inter_tri_merge_line:Geometry = cls.get_polygon_lines(inter_tri_merge)
  144 +
  145 + inter_tri_merge_line_points:list = inter_tri_merge_line.GetPoints()
  146 +
  147 + bian_ps = bian.GetPoints()
  148 +
  149 + if len(inter_tri_merge_line_points[0]) == 3:
  150 + try:
  151 + first_index = inter_tri_merge_line_points.index(bian_ps[0])
  152 + second_index = inter_tri_merge_line_points.index(bian_ps[1])
  153 + except:
  154 + rtree.insert(RTreeData(inter_tri_merge, 1), env2rect(inter_tri_merge.GetEnvelope()))
  155 + continue
  156 + else:
  157 + try:
  158 + first_index = inter_tri_merge_line_points.index((bian_ps[0][0],bian_ps[0][1]))
  159 + second_index = inter_tri_merge_line_points.index((bian_ps[1][0],bian_ps[1][1]))
  160 + except:
  161 + rtree.insert(RTreeData(inter_tri_merge, 1), env2rect(inter_tri_merge.GetEnvelope()))
  162 + continue
  163 +
  164 +
  165 +
  166 + small_index = min(first_index,second_index)
  167 + big_index = max(first_index,second_index)
  168 +
  169 + small_points:list = inter_tri_merge_line_points[:small_index+1]
  170 + small_points.extend(inter_tri_merge_line_points[big_index:])
  171 + small_polygon:Geometry = cls.create_polygon(small_points)
  172 +
  173 + delauney = cls.get_delauney(small_polygon)
  174 + for de in delauney:
  175 + de_extent = de.GetEnvelope()
  176 + rtree.insert(RTreeData(de, 1), env2rect(de_extent))
  177 +
  178 + big_points = inter_tri_merge_line_points[small_index:big_index+1]
  179 + big_points.append(inter_tri_merge_line_points[small_index])
  180 +
  181 + big_polygon:Geometry = cls.create_polygon(big_points)
  182 +
  183 + delauney = cls.get_delauney(big_polygon)
  184 + for de in delauney:
  185 + de_extent = de.GetEnvelope()
  186 + rtree.insert(RTreeData(de, 1), env2rect(de_extent))
  187 +
  188 + for entry in rtree.get_leaf_entries():
  189 + triangle = entry.data.triangle
  190 + if entry.data.state==0:
  191 + continue
  192 + if polygon.Contains(triangle):
  193 + pass
  194 + else:
  195 + tri_center,tri_center2 = cls.get_center(triangle)
  196 + distance = tri_center.Distance(polygon)
  197 + distance2 = tri_center2.Distance(polygon)
  198 +
  199 + if distance > distance_buffer_threshold :
  200 + continue
  201 + # if distance2 > distance_buffer_threshold:
  202 + # continue
  203 +
  204 + polygon = polygon.Union(triangle)
  205 + # polygon.AddGeometry(triangle)
  206 +
  207 + result :Geometry = polygon
  208 +
  209 + return result
  210 +
  211 +
  212 + @classmethod
  213 + def get_center(cls,tri:Geometry):
  214 +
  215 + tri_line: Geometry = cls.get_polygon_lines(tri)
  216 + tri_line_points = tri_line.GetPoints()
  217 +
  218 + lines = []
  219 +
  220 + for index in range(len(tri_line_points)-1):
  221 + first = tri_line_points[index]
  222 + second = tri_line_points[index+1]
  223 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  224 + line.AddPoint(first[0], first[1])
  225 + line.AddPoint(second[0], second[1])
  226 + lines.append(line)
  227 +
  228 + lines = sorted(lines,key=lambda l:l.Length())
  229 +
  230 + return lines[-1].Centroid(),lines[-2].Centroid()
  231 +
  232 + @classmethod
  233 + def get_polygon_lines(cls,polygon):
  234 + #无孔Polygon
  235 + if polygon.GetGeometryCount() in [0,1]:
  236 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  237 + # 有孔Polygon
  238 + else:
  239 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  240 +
  241 + return polygon_line
  242 +
  243 + @classmethod
  244 + def get_bian(cls,polygon):
  245 +
  246 + bians = []
  247 +
  248 + polygon_lines = []
  249 +
  250 + if polygon.GetGeometryCount() in [0, 1]:
  251 + polygon_line: Geometry = ogr.ForceToLineString(polygon)
  252 + polygon_lines.append(polygon_line)
  253 + # 有孔Polygon
  254 + else:
  255 + for index in range(polygon.GetGeometryCount()):
  256 + polygon_line: Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(index))
  257 + polygon_lines.append(polygon_line)
  258 +
  259 + for polygon_line in polygon_lines:
  260 + for index in range(polygon_line.GetPointCount()-1):
  261 + p = polygon_line.GetPoint(index)
  262 + p_next = polygon_line.GetPoint(index+1)
  263 +
  264 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  265 +
  266 + if len(p) ==2:
  267 + line.AddPoint(p[0], p[1],0)
  268 + line.AddPoint(p_next[0], p_next[1],0)
  269 + else:
  270 + line.AddPoint(p[0], p[1])
  271 + line.AddPoint(p_next[0], p_next[1])
  272 + bians.append(line)
  273 +
  274 + return bians
  275 +
  276 + @classmethod
  277 + def create_polygon(cls,ps):
  278 +
  279 + ring = ogr.Geometry(ogr.wkbLinearRing)
  280 + for p in ps:
  281 + ring.AddPoint(p[0], p[1])
  282 + poly = ogr.Geometry(ogr.wkbPolygon)
  283 + poly.AddGeometry(ring)
  284 + return poly
  285 +
  286 +
  287 +if __name__ == '__main__':
  288 + import time
  289 + t1 = time.time()
  290 +
  291 +
  292 + # sd = ShapeData(r"J:\Data\制图综合result\t4.shp")
  293 + # mp = ogr.Geometry(ogr.wkbMultiPolygon)
  294 + # polygons = sd.get_polygons()
  295 + #
  296 + # wkts = PolygonMerge.merge(polygons)
  297 + #
  298 + # result = r"J:\Data\制图综合result\t4_merge.shp"
  299 + #
  300 + # ShapeData.create_shp_fromwkts(result,"zh",wkts)
  301 + #
  302 + # print(time.time()-t1)
  303 +
  304 +
  305 + p = PolygonMerge.create_polygon([(113.37029204400005, 22.526576828100076, 0.0), (113.36972403800007, 22.526369320699985, 0.0), (113.36974547200009, 22.526379207800005, 0.0), (113.37025989200004, 22.52656695200011, 0.0), (113.37029204400005, 22.526576828100076, 0.0)])
  306 +
  307 + pl:Geometry = ogr.ForceToLineString(p)
  308 +
  309 + ps:list = pl.GetPoints()
  310 + ps.reverse()
  311 +
  312 + PolygonMerge.get_tri(ps)
  313 +
  314 + # wkts =[p.ExportToWkt()]
  315 + #
  316 + # result = r"J:\Data\制图综合result\error.shp"
  317 + #
  318 + # ShapeData.create_shp_fromwkts(result,"zh",wkts)
  319 + #
  320 + # print(time.time()-t1)
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/15
  4 +#email: nheweijun@sina.com
  5 +
  6 +import uuid
  7 +class RepresentPoint:
  8 +
  9 + def __init__(self,point,polygon):
  10 + self.point = point
  11 + self.polygon = polygon
  12 + self.uuid = uuid.uuid1().__str__()
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/15
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from osgeo import ogr
  8 +from osgeo.ogr import *
  9 +import math
  10 +import os
  11 +import copy
  12 +
  13 +class ShapeData:
  14 +
  15 + driver = ogr.GetDriverByName("ESRI Shapefile")
  16 +
  17 + def __init__(self,path):
  18 +
  19 + self.ds: DataSource = self.driver.Open(path, 1)
  20 + if not self.ds:
  21 + raise Exception("打开数据失败!")
  22 + self.layer: Layer = self.ds.GetLayer(0)
  23 +
  24 +
  25 + def get_polygons(self):
  26 +
  27 + polygons = []
  28 + for feature in self.layer:
  29 + f:Feature = feature
  30 + geom : Geometry = copy.deepcopy(f.GetGeometryRef())
  31 + if geom is None:
  32 + continue
  33 + if geom.GetGeometryType() in [3,-2147483645,3001]:
  34 + polygons.append(ogr.ForceToPolygon(geom))
  35 + if geom.GetGeometryType() in [6 ,-2147483642 ,3006]:
  36 + for i in range(geom.GetGeometryCount()):
  37 + polygons.append(ogr.ForceToPolygon(geom.GetGeometryRef(i)))
  38 +
  39 + # p_cs = []
  40 + # for p in polygons:
  41 + # polygon_line: Geometry = self.get_polygon_lines(p)
  42 + # print(polygon_line)
  43 + # p_cs.append(self.create_polygon(polygon_line.GetPoints()))
  44 + #
  45 + # return p_cs
  46 + return polygons
  47 +
  48 +
  49 + def get_polygon_lines(self,polygon):
  50 + #无孔Polygon
  51 + if polygon.GetGeometryCount() in [0,1]:
  52 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  53 + # 有孔Polygon
  54 + else:
  55 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  56 +
  57 + return polygon_line
  58 +
  59 +
  60 + def create_polygon(self,ps):
  61 +
  62 + ring = ogr.Geometry(ogr.wkbLinearRing)
  63 + for p in ps:
  64 + ring.AddPoint(p[0], p[1],0)
  65 + poly = ogr.Geometry(ogr.wkbPolygon)
  66 + poly.AddGeometry(ring)
  67 + return poly
  68 +
  69 +
  70 +
  71 + def close(self):
  72 + self.ds.Destroy()
  73 +
  74 +
  75 +
  76 +
  77 + @classmethod
  78 + def create_by_layer(cls,path,layer:Layer):
  79 + data_source: DataSource = cls.driver.CreateDataSource(path)
  80 + data_source.CopyLayer(layer,layer.GetName())
  81 + data_source.Destroy()
  82 +
  83 + @classmethod
  84 + def create_by_scheme(cls,path,name,sr,geo_type,scheme,features):
  85 + data_source: DataSource = cls.driver.CreateDataSource(path)
  86 + layer :Layer = data_source.CreateLayer(name, sr, geo_type)
  87 + if scheme:
  88 + layer.CreateFields(scheme)
  89 + for feature in features:
  90 + layer.CreateFeature(feature)
  91 + data_source.Destroy()
  92 +
  93 + @classmethod
  94 + def create_point(cls,path,name,point):
  95 + data_source: DataSource = cls.driver.CreateDataSource(path)
  96 + layer :Layer = data_source.CreateLayer(name, None, ogr.wkbPoint)
  97 +
  98 + feat_new = ogr.Feature(layer.GetLayerDefn())
  99 + feat_new.SetGeometry(point)
  100 + layer.CreateFeature(feat_new)
  101 + data_source.Destroy()
  102 +
  103 + @classmethod
  104 + def create_shp_fromwkts(cls,path,name,wkts):
  105 +
  106 + geo_type = None
  107 + geoms = []
  108 + for wkt in wkts:
  109 + geom : Geometry = ogr.CreateGeometryFromWkt(wkt)
  110 + if geo_type is None:
  111 + geo_type = geom.GetGeometryType()
  112 + geoms.append(geom)
  113 +
  114 + if os.path.exists(path):
  115 +
  116 + pre_name = ".".join(path.split(".")[0:-1])
  117 + for bac in ["dbf","prj","cpg","shp","shx","sbn","sbx"]:
  118 + try:
  119 + os.remove(pre_name+"."+bac)
  120 + except Exception as e:
  121 + pass
  122 +
  123 + data_source: DataSource = cls.driver.CreateDataSource(path)
  124 + layer :Layer = data_source.CreateLayer(name, None, geo_type)
  125 +
  126 + for geom in geoms:
  127 + feat_new = ogr.Feature(layer.GetLayerDefn())
  128 + feat_new.SetGeometry(geom)
  129 + layer.CreateFeature(feat_new)
  130 + data_source.Destroy()
  131 +
  132 +
  133 +if __name__ == '__main__':
  134 + sd = ShapeData(r"J:\Data\制图综合result\test.shp")
  135 + # polygons = sd.get_polygons()
  136 + # wkts = []
  137 + # for p in polygons:
  138 + # # print(p.ExportToWkt())
  139 + # wkts.append(p.ExportToWkt())
  140 + # result = r"J:\Data\制图综合result\zhongshan_ronghe.shp"
  141 + # ShapeData.create_shp_fromwkts(result,"zh",wkts)
  142 +
  143 + layer = sd.layer
  144 +
  145 + fn = "PG: user=postgres password=chinadci host=172.26.60.101 port=5432 dbname=ceshi "
  146 + driver = ogr.GetDriverByName("PostgreSQL")
  147 + if driver is None:
  148 + raise Exception("打开PostgreSQL驱动失败,可能是当前GDAL未支持PostgreSQL驱动!")
  149 + ds:DataSource = driver.Open(fn, 1)
  150 +
  151 +
  152 + pg_layer = ds.CreateLayer("test", layer.GetSpatialRef(), layer.GetGeomType(), ["overwrite=yes"])
  153 + schema = layer.schema
  154 + pg_layer.CreateFields(schema)
  155 + for feature in layer:
  156 + out_feature: Feature = copy.copy(feature)
  157 + out_feature.SetFID(out_feature.GetFID() + 1)
  158 + pg_layer.CreateFeature(out_feature)
  159 +
  160 +
  161 + ds.Destroy()
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/31
  4 +#email: nheweijun@sina.com
... ...
... ... @@ -10,7 +10,6 @@
10 10
11 11 import numpy as np
12 12 import scipy.spatial as spt
13   -import matplotlib.pyplot as plt
14 13 from matplotlib.path import Path
15 14 from test.zonghe import lineintersect as li
16 15
... ... @@ -47,27 +46,6 @@ def SortByAngle(kNearestPoints, currentPoint, prevPoint):
47 46 i=i+1
48 47 return kNearestPoints[np.argsort(angles)]
49 48
50   -# def plotPoints(dataset):
51   -# plt.plot(dataset[:,0],dataset[:,1],'o',markersize=10,markerfacecolor='0.75',
52   -# markeredgewidth=1)
53   -# plt.axis('equal')
54   -# plt.axis([min(dataset[:,0])-0.5,max(dataset[:,0])+0.5,min(dataset[:,1])-0.5,
55   -# max(dataset[:,1])+0.5])
56   -# plt.show()
57   -#
58   -# def plotPath(dataset, path):
59   -# plt.plot(dataset[:,0],dataset[:,1],'o',markersize=10,markerfacecolor='0.65',
60   -# markeredgewidth=0)
61   -# path = np.asarray(path)
62   -# plt.plot(path[:,0],path[:,1],'o',markersize=10,markerfacecolor='0.55',
63   -# markeredgewidth=0)
64   -# plt.plot(path[:,0],path[:,1],'-',lw=1.4,color='k')
65   -# plt.axis('equal')
66   -# plt.axis([min(dataset[:,0])-0.5,max(dataset[:,0])+0.5,min(dataset[:,1])-0.5,
67   -# max(dataset[:,1])+0.5])
68   -# plt.axis('off')
69   -# plt.savefig('./doc/figure_1.png', bbox_inches='tight')
70   -# plt.show()
71 49
72 50 def removePoint(dataset, point):
73 51 delmask = [np.logical_or(dataset[:,0]!=point[0],dataset[:,1]!=point[1])]
... ... @@ -89,9 +67,13 @@ def concaveHull(dataset, k):
89 67 hull.append(firstpoint)
90 68 # and remove it from dataset
91 69 points = removePoint(points,firstpoint)
  70 +
92 71 currentPoint = firstpoint
93 72 # set prevPoint to a Point righ of currentpoint (angle=0)
  73 +
94 74 prevPoint = (currentPoint[0]+10, currentPoint[1])
  75 +
  76 +
95 77 step = 2
96 78
97 79 while ( (not np.array_equal(firstpoint, currentPoint) or (step==2)) and points.size > 0 ):
... ... @@ -116,7 +98,7 @@ def concaveHull(dataset, k):
116 98 hull[step-1-j-1],hull[step-j-1])
117 99 j=j+1
118 100 if ( its==True ):
119   - print("all candidates intersect -- restarting with k = ",k+1)
  101 + # print("all candidates intersect -- restarting with k = ",k+1)
120 102 return concaveHull(dataset,k+1)
121 103 prevPoint = currentPoint
122 104 currentPoint = cPoints[i-1]
... ... @@ -127,11 +109,12 @@ def concaveHull(dataset, k):
127 109 # check if all points are inside the hull
128 110 p = Path(hull)
129 111 pContained = p.contains_points(dataset, radius=0.0000000001)
  112 +
130 113 if (not pContained.all()):
131   - print("not all points of dataset contained in hull -- restarting with k = ",k+1)
  114 + # print("not all points of dataset contained in hull -- restarting with k = ",k+1)
132 115 return concaveHull(dataset, k+1)
133 116
134   - print("finished with k = ",k)
  117 + # print("finished with k = ",k)
135 118 return hull
136 119
137 120
... ...
... ... @@ -9,8 +9,7 @@ import math
9 9 import os
10 10 import copy
11 11 from test.zonghe.RepresentPoint import RepresentPoint
12   -
13   -
  12 +import time
14 13
15 14 class DelauneyNode:
16 15
... ... @@ -65,22 +64,52 @@ class DelauneyMinTree:
65 64 def __init__(self):
66 65 self.delauney_lines_list = list()
67 66 self.rps = set()
  67 + self.touch_delauney_lines = set()
  68 +
  69 + def append(self,delauney_line,other_delauney_lines_kv):
  70 +
  71 +
  72 + candicates = []
  73 + if not self.rps.__contains__(delauney_line.rp1):
  74 + self.rps.add(delauney_line.rp1)
  75 +
  76 + candicates.extend(other_delauney_lines_kv.get(delauney_line.rp1))
  77 +
  78 + if not self.rps.__contains__(delauney_line.rp2):
  79 + self.rps.add(delauney_line.rp2)
  80 +
  81 + candicates.extend(other_delauney_lines_kv.get(delauney_line.rp2))
68 82
69   - def append(self,delauney_line):
70   - # self.delauney_lines.add(delauney_line)
  83 + for candicate in candicates:
  84 + if (candicate.rp1 in self.rps) and (candicate.rp2 in self.rps):
  85 + #初始化
  86 + try:
  87 + self.touch_delauney_lines.remove(candicate)
  88 + except:
  89 + print(111)
71 90
72   - self.rps.add(delauney_line.rp1)
73   - self.rps.add(delauney_line.rp2)
  91 + else:
  92 + self.touch_delauney_lines.add(candicate)
74 93
75 94 self.delauney_lines_list.append(delauney_line)
76 95
  96 +
  97 +
77 98 def get_rps(self):
78 99 return self.rps
79 100
80   - def get_other_relate_delauney_lines(self,other_delauney_lines_kv):
  101 +
  102 + def get_other_relate_delauney_lines(self,other_delauney_lines_kv,rps_set):
  103 +
81 104 other_relate_delauney_lines = []
  105 +
82 106 for rp in self.rps:
83   - other_relate_delauney_lines.extend(other_delauney_lines_kv.get(rp))
  107 + candicates = other_delauney_lines_kv.get(rp)
  108 + candicates = [c for c in candicates if c.rp1 in rps_set or c.rp2 in rps_set]
  109 + other_relate_delauney_lines.extend(candicates)
  110 +
  111 + # other_relate_delauney_lines.append()
  112 +
84 113 return other_relate_delauney_lines
85 114
86 115 def get_other_rp(self,delauney_line):
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/30
  4 +#email: nheweijun@sina.com
  5 +
  6 +import math
  7 +
  8 +from osgeo import ogr,gdal
  9 +from osgeo.ogr import *
  10 +
  11 +from test.zonghe.ShapeData import ShapeData
  12 +import copy
  13 +
  14 +from scipy import spatial
  15 +from rtreelib import RTree,Rect
  16 +
  17 +
  18 +
  19 +class RTreeData:
  20 +
  21 + def __init__(self,triangle,state):
  22 + self.state = state
  23 + self.triangle = triangle
  24 +
  25 + def set_state(self,state):
  26 + self.state = state
  27 +
  28 +
  29 +def env2rect(env):
  30 + return Rect(env[0],env[2],env[1],env[3])
  31 +
  32 +
  33 +class PolygonDivision:
  34 +
  35 + @classmethod
  36 + def get_delauney(cls,polygon):
  37 +
  38 + polygon_line = cls.get_polygon_lines(polygon)
  39 + polygon_line_points:list = polygon_line.GetPoints()
  40 +
  41 + if len(polygon_line_points)==4:
  42 + tris = [polygon]
  43 + else:
  44 + d = 0
  45 + for ind in range(len(polygon_line_points) - 1):
  46 + p = polygon_line_points[ind]
  47 + p_n = polygon_line_points[ind + 1]
  48 +
  49 + d += -0.5 * (p_n[1] + p[1]) * (p_n[0] - p[0])
  50 +
  51 + if d < 0:
  52 + polygon_line_points.reverse()
  53 +
  54 + tris = list(cls.get_tri(polygon_line_points))
  55 +
  56 + return tris
  57 +
  58 + @classmethod
  59 + def get_tri(cls,polygon_line_points:list):
  60 +
  61 + if len(polygon_line_points) == 4:
  62 + yield cls.create_polygon(polygon_line_points)
  63 + else:
  64 + for index,point in enumerate(polygon_line_points):
  65 + if index == 0:
  66 + continue
  67 + # elif index == len(polygon_line_points)-1 :
  68 + # pass
  69 + else:
  70 + point_front = polygon_line_points[index-1]
  71 + point_next = polygon_line_points[index+1]
  72 +
  73 + check = (point[0]-point_front[0]) * (point_next[1]-point[1]) - (point_next[0]-point[0])*(point[1]-point_front[1])
  74 +
  75 + if check > 0:
  76 + triangle = cls.create_polygon([point_front,point,point_next,point_front])
  77 + yield triangle
  78 + polygon_line_points.pop(index)
  79 + for tri in cls.get_tri(polygon_line_points):
  80 + yield tri
  81 + break
  82 +
  83 + @classmethod
  84 + def triangle_division(cls,polygon:Geometry):
  85 +
  86 + rtree = RTree()
  87 + polygon = polygon.UnionCascaded()
  88 + delauney: Geometry = polygon.DelaunayTriangulation()
  89 +
  90 + for index in range(delauney.GetGeometryCount()):
  91 + de:Geometry = copy.deepcopy(delauney.GetGeometryRef(index))
  92 + de_extent = de.GetEnvelope()
  93 + rtree.insert(RTreeData(de,1), env2rect(de_extent))
  94 +
  95 +
  96 + # return [entry.data.triangle.ExportToWkt() for entry in rtree.get_leaf_entries()]
  97 + bians: list = cls.get_bian(polygon)
  98 +
  99 +
  100 + for bian in bians:
  101 +
  102 + bian_ext = bian.GetEnvelope()
  103 +
  104 + query_result = rtree.query(env2rect(bian_ext))
  105 +
  106 + intersection_data = []
  107 +
  108 +
  109 + for entry in query_result:
  110 +
  111 + # 已被抛弃的不要
  112 + if entry.data.state == 0:
  113 + continue
  114 + intersection_geom: Geometry = bian.Intersection(entry.data.triangle)
  115 +
  116 + if not intersection_geom.IsEmpty():
  117 + if not intersection_geom.Equals(bian):
  118 + if intersection_geom.GetGeometryType() in [2, 5, -2147483643, -2147483646, 3002, 3005]:
  119 + intersection_data.append(entry.data)
  120 +
  121 +
  122 + for data in intersection_data:
  123 + data.set_state(0)
  124 +
  125 + if intersection_data:
  126 +
  127 + inter_tri_merge:Geometry = intersection_data[0].triangle
  128 +
  129 + for ind in range(1,len(intersection_data)):
  130 + inter_tri_merge = inter_tri_merge.Union(intersection_data[ind].triangle)
  131 +
  132 +
  133 +
  134 + inter_tri_merge_line:Geometry = cls.get_polygon_lines(inter_tri_merge)
  135 +
  136 + inter_tri_merge_line_points:list = inter_tri_merge_line.GetPoints()
  137 +
  138 + bian_ps = bian.GetPoints()
  139 +
  140 + if len(inter_tri_merge_line_points[0]) == 3:
  141 + try:
  142 + first_index = inter_tri_merge_line_points.index(bian_ps[0])
  143 + second_index = inter_tri_merge_line_points.index(bian_ps[1])
  144 + except:
  145 + print(11)
  146 + print(bian)
  147 + print(inter_tri_merge)
  148 +
  149 + rtree.insert(RTreeData(inter_tri_merge, 1), env2rect(inter_tri_merge.GetEnvelope()))
  150 +
  151 + continue
  152 + else:
  153 + try:
  154 + first_index = inter_tri_merge_line_points.index((bian_ps[0][0],bian_ps[0][1]))
  155 + second_index = inter_tri_merge_line_points.index((bian_ps[1][0],bian_ps[1][1]))
  156 + except:
  157 + print(11)
  158 + print(bian)
  159 + print(inter_tri_merge)
  160 +
  161 + rtree.insert(RTreeData(inter_tri_merge, 1), env2rect(inter_tri_merge.GetEnvelope()))
  162 + continue
  163 +
  164 +
  165 +
  166 + small_index = min(first_index,second_index)
  167 + big_index = max(first_index,second_index)
  168 +
  169 + small_points:list = inter_tri_merge_line_points[:small_index+1]
  170 + small_points.extend(inter_tri_merge_line_points[big_index:])
  171 + small_polygon:Geometry = cls.create_polygon(small_points)
  172 +
  173 +
  174 +
  175 + # delauney: Geometry = small_polygon.DelaunayTriangulation()
  176 + #
  177 + # for index in range(delauney.GetGeometryCount()):
  178 + # de: Geometry = copy.deepcopy(delauney.GetGeometryRef(index))
  179 + #
  180 + # if small_polygon.Contains(de):
  181 + # de_extent = de.GetEnvelope()
  182 + # rtree.insert(RTreeData(de, 1), env2rect(de_extent))
  183 +
  184 + delauney = cls.get_delauney(small_polygon)
  185 + for de in delauney:
  186 + de_extent = de.GetEnvelope()
  187 + rtree.insert(RTreeData(de, 1), env2rect(de_extent))
  188 +
  189 +
  190 + big_points = inter_tri_merge_line_points[small_index:big_index+1]
  191 + big_points.append(inter_tri_merge_line_points[small_index])
  192 +
  193 + big_polygon:Geometry = cls.create_polygon(big_points)
  194 +
  195 + # delauney: Geometry = big_polygon.DelaunayTriangulation()
  196 + #
  197 + # for index in range(delauney.GetGeometryCount()):
  198 + # de: Geometry = copy.deepcopy(delauney.GetGeometryRef(index))
  199 + #
  200 + # if big_polygon.Contains(de):
  201 + #
  202 + # de_extent = de.GetEnvelope()
  203 + # rtree.insert(RTreeData(de, 1), env2rect(de_extent))
  204 +
  205 + delauney = cls.get_delauney(big_polygon)
  206 + for de in delauney:
  207 + de_extent = de.GetEnvelope()
  208 + rtree.insert(RTreeData(de, 1), env2rect(de_extent))
  209 +
  210 + tris = []
  211 +
  212 + for entry in rtree.get_leaf_entries():
  213 + if entry.data.state==0:
  214 + continue
  215 + if polygon.Contains(entry.data.triangle):
  216 + pass
  217 + else:
  218 + tris.append(entry.data.triangle)
  219 +
  220 + for tri in tris:
  221 +
  222 + tri_center,long_line = cls.get_center(tri)
  223 + dd = tri_center.Distance(polygon)
  224 + if dd > 1.114691025217302e-04:
  225 + continue
  226 +
  227 + polygon.AddGeometry(tri)
  228 + result :Geometry = polygon.UnionCascaded()
  229 + return [result.ExportToWkt()]
  230 +
  231 +
  232 + @classmethod
  233 + def get_center(cls,tri:Geometry):
  234 + tri_line: Geometry = ogr.ForceToLineString(tri)
  235 + tri_line_points = tri_line.GetPoints()
  236 +
  237 + lines = []
  238 +
  239 + for index in range(len(tri_line_points)-1):
  240 + first = tri_line_points[index]
  241 + second = tri_line_points[index+1]
  242 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  243 + line.AddPoint(first[0], first[1])
  244 + line.AddPoint(second[0], second[1])
  245 + lines.append(line)
  246 +
  247 + lines = sorted(lines,key=lambda l:l.Length())
  248 +
  249 + return lines[-1].Centroid(),lines[-1]
  250 +
  251 + @classmethod
  252 + def get_polygon_lines(cls,polygon):
  253 + #无孔Polygon
  254 + if polygon.GetGeometryCount() in [0,1]:
  255 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  256 + # 有孔Polygon
  257 + else:
  258 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  259 +
  260 + return polygon_line
  261 +
  262 + @classmethod
  263 + def get_bian(cls,polygon):
  264 +
  265 + bians = []
  266 +
  267 + polygon_lines = []
  268 +
  269 + if polygon.GetGeometryCount() in [0, 1]:
  270 + polygon_line: Geometry = ogr.ForceToLineString(polygon)
  271 + polygon_lines.append(polygon_line)
  272 + # 有孔Polygon
  273 + else:
  274 + for index in range(polygon.GetGeometryCount()):
  275 + polygon_line: Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(index))
  276 + polygon_lines.append(polygon_line)
  277 +
  278 + for polygon_line in polygon_lines:
  279 + for index in range(polygon_line.GetPointCount()-1):
  280 + p = polygon_line.GetPoint(index)
  281 + p_next = polygon_line.GetPoint(index+1)
  282 +
  283 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  284 +
  285 + if len(p) ==2:
  286 + line.AddPoint(p[0], p[1],0)
  287 + line.AddPoint(p_next[0], p_next[1],0)
  288 + else:
  289 + line.AddPoint(p[0], p[1])
  290 + line.AddPoint(p_next[0], p_next[1])
  291 + bians.append(line)
  292 +
  293 + return bians
  294 +
  295 + @classmethod
  296 + def create_polygon(cls,ps):
  297 +
  298 + ring = ogr.Geometry(ogr.wkbLinearRing)
  299 + for p in ps:
  300 + ring.AddPoint(p[0], p[1])
  301 + poly = ogr.Geometry(ogr.wkbPolygon)
  302 + poly.AddGeometry(ring)
  303 + return poly
  304 +
  305 +
  306 +if __name__ == '__main__':
  307 + import time
  308 + t1 = time.time()
  309 + gdal.UseExceptions()
  310 +
  311 + sd = ShapeData(r"J:\Data\制图综合result\t4.shp")
  312 + mp = ogr.Geometry(ogr.wkbMultiPolygon)
  313 + polygons = sd.get_polygons()
  314 + for p in polygons:
  315 + mp.AddGeometry(p)
  316 +
  317 + wkts = PolygonDivision.triangle_division(mp)
  318 +
  319 + result = r"J:\Data\制图综合result\t4_merge.shp"
  320 +
  321 + ShapeData.create_shp_fromwkts(result,"zh",wkts)
  322 +
  323 + print(time.time()-t1)
  324 +
  325 +
... ...
... ... @@ -3,13 +3,10 @@
3 3 #createtime: 2022/3/15
4 4 #email: nheweijun@sina.com
5 5
6   -from osgeo import ogr
7   -from osgeo.ogr import *
8   -import math
9   -import os
10   -import copy
  6 +import uuid
11 7 class RepresentPoint:
12 8
13 9 def __init__(self,point,polygon):
14 10 self.point = point
15 11 self.polygon = polygon
  12 + self.uuid = uuid.uuid1().__str__()
... ...
... ... @@ -16,7 +16,7 @@ class ShapeData:
16 16
17 17 def __init__(self,path):
18 18
19   - self.ds: DataSource = self.driver.Open(path, 0)
  19 + self.ds: DataSource = self.driver.Open(path, 1)
20 20 if not self.ds:
21 21 raise Exception("打开数据失败!")
22 22 self.layer: Layer = self.ds.GetLayer(0)
... ... @@ -28,13 +28,46 @@ class ShapeData:
28 28 for feature in self.layer:
29 29 f:Feature = feature
30 30 geom : Geometry = copy.deepcopy(f.GetGeometryRef())
31   - if geom.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645:
32   - polygons.append(geom)
33   - if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642:
  31 + if geom is None:
  32 + continue
  33 + if geom.GetGeometryType() in [3,-2147483645,3001]:
  34 + polygons.append(ogr.ForceToPolygon(geom))
  35 + if geom.GetGeometryType() in [6 ,-2147483642 ,3006]:
34 36 for i in range(geom.GetGeometryCount()):
35   - polygons.append(geom.GetGeometryRef(i))
  37 + polygons.append(ogr.ForceToPolygon(geom.GetGeometryRef(i)))
  38 +
  39 + # p_cs = []
  40 + # for p in polygons:
  41 + # polygon_line: Geometry = self.get_polygon_lines(p)
  42 + # print(polygon_line)
  43 + # p_cs.append(self.create_polygon(polygon_line.GetPoints()))
  44 + #
  45 + # return p_cs
36 46 return polygons
37 47
  48 +
  49 + def get_polygon_lines(self,polygon):
  50 + #无孔Polygon
  51 + if polygon.GetGeometryCount() in [0,1]:
  52 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  53 + # 有孔Polygon
  54 + else:
  55 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  56 +
  57 + return polygon_line
  58 +
  59 +
  60 + def create_polygon(self,ps):
  61 +
  62 + ring = ogr.Geometry(ogr.wkbLinearRing)
  63 + for p in ps:
  64 + ring.AddPoint(p[0], p[1],0)
  65 + poly = ogr.Geometry(ogr.wkbPolygon)
  66 + poly.AddGeometry(ring)
  67 + return poly
  68 +
  69 +
  70 +
38 71 def close(self):
39 72 self.ds.Destroy()
40 73
... ... @@ -94,4 +127,35 @@ class ShapeData:
94 127 feat_new = ogr.Feature(layer.GetLayerDefn())
95 128 feat_new.SetGeometry(geom)
96 129 layer.CreateFeature(feat_new)
97   - data_source.Destroy()
\ No newline at end of file
  130 + data_source.Destroy()
  131 +
  132 +
  133 +if __name__ == '__main__':
  134 + sd = ShapeData(r"J:\Data\制图综合result\test.shp")
  135 + # polygons = sd.get_polygons()
  136 + # wkts = []
  137 + # for p in polygons:
  138 + # # print(p.ExportToWkt())
  139 + # wkts.append(p.ExportToWkt())
  140 + # result = r"J:\Data\制图综合result\zhongshan_ronghe.shp"
  141 + # ShapeData.create_shp_fromwkts(result,"zh",wkts)
  142 +
  143 + layer = sd.layer
  144 +
  145 + fn = "PG: user=postgres password=chinadci host=172.26.60.101 port=5432 dbname=ceshi "
  146 + driver = ogr.GetDriverByName("PostgreSQL")
  147 + if driver is None:
  148 + raise Exception("打开PostgreSQL驱动失败,可能是当前GDAL未支持PostgreSQL驱动!")
  149 + ds:DataSource = driver.Open(fn, 1)
  150 +
  151 +
  152 + pg_layer = ds.CreateLayer("test", layer.GetSpatialRef(), layer.GetGeomType(), ["overwrite=yes"])
  153 + schema = layer.schema
  154 + pg_layer.CreateFields(schema)
  155 + for feature in layer:
  156 + out_feature: Feature = copy.copy(feature)
  157 + out_feature.SetFID(out_feature.GetFID() + 1)
  158 + pg_layer.CreateFeature(out_feature)
  159 +
  160 +
  161 + ds.Destroy()
... ...
... ... @@ -10,19 +10,21 @@ import math
10 10 import os
11 11 import copy
12 12 os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
13   -
  13 +from test.zonghe.ConcaveHull import concaveHull
14 14 from test.zonghe.ShapeData import ShapeData
15 15 from test.zonghe.Delauney import DelauneyNode,DelauneyLine,DelauneyMinTree
16 16 from test.zonghe.RepresentPoint import RepresentPoint
17 17 from test.zonghe.Util import Util
18 18 import cv2
  19 +import time
  20 +import numpy as np
19 21
20 22 class Zonghe:
21 23
22 24 data:ShapeData
23   - area_threshold = 100.0
  25 + area_threshold = 10.0
24 26 buffer_threshold = 100.0
25   - distance_buffer_threshold = 2.114691025217302e-04
  27 + distance_buffer_threshold = 1.114691025217302e-04
26 28
27 29 def __init__(self,data):
28 30 self.data = data
... ... @@ -37,11 +39,8 @@ class Zonghe:
37 39
38 40 line_length = math.sqrt(math.pow(polygon_env[1] - polygon_env[0],2) + math.pow(polygon_env[3] - polygon_env[2],2))
39 41
40   -
41 42 short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2])
42 43
43   -
44   -
45 44 center:Geometry = polygon.Centroid()
46 45 # print(center)
47 46
... ... @@ -80,7 +79,8 @@ class Zonghe:
80 79 # print("in_hole")
81 80
82 81 angle1,angle2=None,None
83   -
  82 + line = None
  83 + oneside_area, otherside_area = None,None
84 84 for angle in direction:
85 85
86 86 if in_hole:
... ... @@ -91,6 +91,10 @@ class Zonghe:
91 91 oneside_area, otherside_area = self.jude(polygon, line, angle, line_length)
92 92
93 93
  94 + if oneside_area > 0 and otherside_area >0:
  95 + if abs(oneside_area-otherside_area) < area_thre:
  96 + break
  97 +
94 98 if last_state is None:
95 99
96 100 angle2 = angle
... ... @@ -115,7 +119,14 @@ class Zonghe:
115 119 else:
116 120 last_state = now_state
117 121
118   - line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre)
  122 + #第一条线就是均分线
  123 + if angle1 is None or angle2 is None:
  124 + pass
  125 + else:
  126 + #如果面积差大于阈值,二分法查找
  127 + if abs(oneside_area - otherside_area) > area_thre:
  128 + line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre)
  129 +
119 130
120 131 # 提前return
121 132 if in_hole:
... ... @@ -156,6 +167,7 @@ class Zonghe:
156 167 ylist.append(pi.GetY())
157 168 plist.append(pi)
158 169
  170 +
159 171 reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0]
160 172
161 173 reprecent_point = self.creat_point(reprecent_point)
... ... @@ -298,6 +310,8 @@ class Zonghe:
298 310 def division(self,polygon,center,in_hole,line_length,angle1,angle2,area_thre):
299 311
300 312 mid_angle = (angle1 + angle2)/2.0
  313 +
  314 +
301 315 if in_hole:
302 316 line = self.get_doubleline(center.GetX(), center.GetY(), mid_angle, line_length)
303 317 else:
... ... @@ -373,55 +387,41 @@ class Zonghe:
373 387 return p
374 388
375 389
376   -
377   -
378 390 def create_delauney(self,rps):
379 391 multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
380 392
381 393 rp_dict = {}
382   - line_set = set()
383 394 delauney_lines = []
384 395
  396 + rps_sub = set()
385 397 for rp in rps:
386 398 multipoint.AddGeometry(rp.point)
  399 + # 多边形代表点相同,需要融合多边形
  400 + if rp_dict.get(rp.point.GetPoint(0).__str__()):
  401 + rp_exist = rp_dict.get(rp.point.GetPoint(0).__str__())
  402 + rp_exist.polygon = rp_exist.polygon.Union(rp.polygon)
  403 + else:
  404 + rp_dict[rp.point.GetPoint(0).__str__()] = rp
  405 + rps_sub.add(rp)
387 406
388   - rp_dict[rp.point.GetPoint(0).__str__()] = rp
389   -
390   - delauney:Geometry = multipoint.DelaunayTriangulation()
  407 + delauney:Geometry = multipoint.DelaunayTriangulation(bOnlyEdges=True)
391 408
392 409 for index in range(delauney.GetGeometryCount()):
393   - triangle = delauney.GetGeometryRef(index)
394   -
395   - triangle_line:Geometry = ogr.ForceToLineString(triangle)
396   -
  410 + triangle_line:Geometry = delauney.GetGeometryRef(index)
  411 + p = triangle_line.GetPoint(0)
  412 + p_next = triangle_line.GetPoint(1)
397 413
398   - for pi in range(triangle_line.GetPointCount()-1):
399   - p = triangle_line.GetPoint(pi)
400   - p_next = triangle_line.GetPoint(pi+1)
  414 + rp1 = rp_dict.get(p.__str__())
  415 + rp2 = rp_dict.get(p_next.__str__())
401 416
402   - if p[0] < p_next[0]:
403   - key = "{}{}".format(p.__str__(),p_next.__str__())
404   - elif p[0] > p_next[0]:
405   - key = "{}{}".format(p_next.__str__(), p.__str__())
406   - else:
407   - if p[1] < p_next[1]:
408   - key = "{}{}".format(p.__str__(), p_next.__str__())
409   - else:
410   - key = "{}{}".format(p_next.__str__(), p.__str__())
411   -
412   - if not line_set.__contains__(key):
413   - line_set.add(key)
414   - rp1 = rp_dict.get(p.__str__())
415   - rp2 = rp_dict.get(p_next.__str__())
  417 + delauney_line = DelauneyLine(rp1,rp2)
  418 + delauney_lines.append(delauney_line)
416 419
417   - delauney_line = DelauneyLine(rp1,rp2)
418   - delauney_lines.append(delauney_line)
  420 + return delauney_lines,rps_sub
419 421
420   - return delauney_lines
421 422
422 423
423   -
424   - def create_min_delauney(self,delauney_lines,rps,polygons):
  424 + def create_min_delauney(self,delauney_lines,rps):
425 425 '''
426 426 使用prim算法计算最小生成树
427 427 :param delauney_lines:
... ... @@ -429,68 +429,72 @@ class Zonghe:
429 429 :return:
430 430 '''
431 431
432   - kv = {}
  432 + kv = dict()
  433 + print(len(rps))
  434 +
  435 +
433 436 rps_set = set(rps)
434 437
435 438 for delauney_line in delauney_lines:
436 439 if kv.get(delauney_line.rp1):
437   -
438 440 kv[delauney_line.rp1].add(delauney_line)
439 441 else:
440 442 kv[delauney_line.rp1] = set()
441 443 kv[delauney_line.rp1].add(delauney_line)
442 444
443 445 if kv.get(delauney_line.rp2):
444   -
445 446 kv[delauney_line.rp2].add(delauney_line)
446 447 else:
447   -
448 448 kv[delauney_line.rp2] = set()
449 449 kv[delauney_line.rp2].add(delauney_line)
450 450
  451 + print(len(kv))
  452 +
  453 + print("完成三角边倒排索引")
451 454
452 455 #初始化树
453 456 delauney_lines = sorted(delauney_lines,key=lambda x:x.distance)
454   -
455   -
456 457 delauney_min_tree = DelauneyMinTree()
457   - delauney_min_tree.append(delauney_lines[0])
  458 +
  459 + delauney_min_tree.append(delauney_lines[0],kv)
458 460
459 461 rps_set.remove(delauney_lines[0].rp1)
460 462 rps_set.remove(delauney_lines[0].rp2)
  463 +
461 464 kv[delauney_lines[0].rp1].remove(delauney_lines[0])
462 465 kv[delauney_lines[0].rp2].remove(delauney_lines[0])
463 466
  467 + print("完成最小生成树初始化")
464 468
465 469 while rps_set.__len__()>0:
466 470
467   - relate_delauney_line = delauney_min_tree.get_other_relate_delauney_lines(kv)
  471 + print(rps_set.__len__())
  472 + t1 = time.time()
  473 + # relate_delauney_line = delauney_min_tree.get_other_relate_delauney_lines(kv,rps_set)
  474 +
  475 + relate_delauney_line = delauney_min_tree.touch_delauney_lines
  476 +
468 477
469 478 relate_delauney_line_sort = sorted(relate_delauney_line,key=lambda x:x.distance)
470 479
471 480 min_distance_line = relate_delauney_line_sort[0]
472   -
473 481 #删除
474 482 other_rp = delauney_min_tree.get_other_rp(min_distance_line)
  483 +
475 484 if other_rp is None:
476 485 kv[min_distance_line.rp1].remove(min_distance_line)
477 486 kv[min_distance_line.rp2].remove(min_distance_line)
478 487 continue
479 488
480   - delauney_min_tree.append(min_distance_line)
  489 + delauney_min_tree.append(min_distance_line,kv)
481 490
482 491 rps_set.remove(other_rp)
483 492
484 493 kv[min_distance_line.rp1].remove(min_distance_line)
485 494 kv[min_distance_line.rp2].remove(min_distance_line)
486 495
487   -
488   -
489   - for l in delauney_min_tree.delauney_lines_list:
490   - line = l.line
491   - # print("\"" + line.ExportToWkt() + "\",")
492   -
493   - # print(delauney_min_tree.delauney_lines_list.__len__())
  496 + # print(time.time() - t2)
  497 + print("完成最小生成树")
494 498
495 499 return delauney_min_tree
496 500
... ... @@ -546,277 +550,154 @@ class Zonghe:
546 550
547 551 return trees
548 552
549   - def merge(self,trees):
550   -
551   - polygons = []
552   - for tree in trees:
553   -
554   - merge_polygon_raw = list()
555   -
556   - dls = tree.get_delauney_lines()
557   - for dl in dls:
558   - p1 = dl.rp1.polygon
559   - p2 = dl.rp2.polygon
560   -
561   - merge_polygon_raw.append(p1)
562   - merge_polygon_raw.append(p2)
563   - line = dl.line
564   -
565   - p1_lines = self.get_polygon_lines(p1)
566   - p2_lines = self.get_polygon_lines(p2)
567   -
568   - p1_intersect_lines = [l for l in p1_lines if l.Intersect(line)]
569   - p2_intersect_lines = [l for l in p2_lines if l.Intersect(line)]
570   -
571   - if p1_intersect_lines.__len__()>1:
572   - p1_intersect_lines = sorted(p1_intersect_lines,key=lambda x:p2.Distance(x))
573   - p1_intersect_line_rep = p1_intersect_lines[0]
574   - elif p1_intersect_lines.__len__()==1:
575   - p1_intersect_line_rep = p1_intersect_lines[0]
576   - else:
577   - continue
578   -
579   -
580   - if p2_intersect_lines.__len__()>1:
581   - p2_intersect_lines = sorted(p2_intersect_lines,key=lambda x:p1.Distance(x))
582   - p2_intersect_line_rep = p2_intersect_lines[0]
583   - elif p2_intersect_lines.__len__()==1:
584   - p2_intersect_line_rep = p2_intersect_lines[0]
585   - else:
586   - continue
587   -
588   -
589   - # #两条线没有距离跳过
590   - # if p2_intersect_line_rep.Distance(p1_intersect_line_rep) == 0:
591   - # continue
592   - # else:
593   -
594   - mid_polygon = self.create_mid_polygon(p1_intersect_line_rep,p2_intersect_line_rep,p1,p2)
595   -
596   - if mid_polygon.GetArea() > 0.0002116361000058077*0.0002116361000058077:
597   - continue
598 553
599   - merge_polygon_raw.append(mid_polygon)
600   -
601   - merge_polygon = None
602   - for p in merge_polygon_raw:
603   - if merge_polygon is None:
604   - merge_polygon = p
605   - else:
606   - merge_polygon = merge_polygon.Union(p)
607   -
608   - polygons.append(merge_polygon)
609   -
610   -
611   - return polygons
  554 + def create_polygon(self,p1,p2,p3,p4):
612 555
  556 + ring = ogr.Geometry(ogr.wkbLinearRing)
  557 + ring.AddPoint(p1[0], p1[1])
  558 + ring.AddPoint(p2[0], p2[1])
  559 + ring.AddPoint(p3[0], p3[1])
  560 + ring.AddPoint(p4[0], p4[1])
  561 + ring.AddPoint(p1[0], p1[1])
613 562
614   - def merge2(self,trees):
  563 + poly = ogr.Geometry(ogr.wkbPolygon)
  564 + poly.AddGeometry(ring)
  565 + return poly
615 566
616   - polygons = []
617 567
  568 + def get_polygon_lines(self,polygon):
  569 + #无孔Polygon
  570 + if polygon.GetGeometryCount() in [0,1]:
  571 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  572 + # 有孔Polygon
  573 + else:
  574 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
618 575
  576 + return polygon_line
619 577
  578 + def merge_concave(self, trees, distance_threshold):
  579 + merge_polygons = []
  580 + count = 1
620 581
621 582 for tree in trees:
  583 + print(count)
  584 + count+=1
  585 + polygons = list(tree.get_polygons())
622 586
623   - tree_polygons = tree.get_polygons()
  587 + merge_raw: Geometry = polygons[0]
  588 + for p in polygons:
  589 + merge_raw = merge_raw.Union(p)
624 590
625 591 points = []
626   - for p in tree_polygons:
627   -
628   - if p.GetGeometryCount() == 1:
629   - polygon_line: Geometry = ogr.ForceToLineString(p)
630   -
631   - polygon_line.Con
632   - # 有孔Polygon
633   - else:
634   - polygon_line: Geometry = ogr.ForceToLineString(p.GetGeometryRef(0))
635   -
636   - points.extend(polygon_line.GetPoints()[:-1])
637   -
638   - multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
639   -
640   - for p in points:
641   - poi = ogr.Geometry(ogr.wkbPoint)
642   - poi.AddPoint(p[0],p[1])
643   - multipoint.AddGeometry(poi)
644   -
645   - delauney: Geometry = multipoint.DelaunayTriangulation()
646   - merge_polygon = None
647   -
648   - for p in delauney:
649   - # if multi_polygon.Contains(p):
650   - # continue
651   -
652   - pline:Geometry = ogr.ForceToLineString(p)
653   - pline :list = pline.GetPoints()
654   - pline.append(pline[1])
655   -
656   -
657   - pass_or_not = False
658   - for indx in range(3):
659   - p1 = pline[indx]
660   - p2 = pline[indx+1]
661   -
662   - ppline:Geometry = ogr.Geometry(ogr.wkbLineString)
663   - ppline.AddPoint(p1[0],p1[1])
664   - ppline.AddPoint(p2[0], p2[1])
665   -
666   -
667   -
668   - p3:Geometry = ogr.Geometry(ogr.wkbPoint)
669   - p3.AddPoint(pline[indx+2][0], pline[indx+2][1])
670   -
671   - if p3.Distance(ppline) > 0.0002116361000058077 or ppline.Length() > 0.0002116361000058077:
672   - pass_or_not = True
673   - break
674   -
675   - if pass_or_not:
676   - continue
677   -
678   - if merge_polygon is None:
679   - merge_polygon = p
680   - else:
681   - merge_polygon = merge_polygon.Union(p)
682 592
683 593
  594 + for i in range(merge_raw.GetGeometryCount()):
684 595
685   - polygons.append(merge_polygon)
  596 + poly = merge_raw.GetGeometryRef(i)
  597 + poly_line :Geometry = self.get_polygon_lines(poly)
  598 + if poly_line:
  599 + for indx in range(poly_line.GetPointCount() - 1):
  600 + poi = poly_line.GetPoint(indx)
686 601
  602 + points.append(poi)
687 603
688   - return polygons
  604 + poi_next = poly_line.GetPoint(indx + 1)
689 605
690   - def merge_circle(self):
691   - pass
  606 + dis = math.sqrt(math.pow(poi[0] - poi_next[0], 2) + math.pow(poi[1] - poi_next[1], 2))
  607 + # print(dis)
  608 + if dis > distance_threshold:
  609 + times = int(dis / distance_threshold)
  610 + # print(times)
  611 + for time in range(1, times + 1):
  612 + x, y = self.get_subpoint(poi[0], poi[1], poi_next[0], poi_next[1], (time * distance_threshold))
  613 + points.append([x, y])
692 614
  615 + points = np.array([[p[0], p[1]] for p in points])
693 616
694   - def create_mid_polygon(self,p1_intersect_line_rep,p2_intersect_line_rep,p1,p2):
695   - '''
696   - 创建衔接polygon
697   - :param line:
698   - :return:
699   - '''
700 617
701   - if p1_intersect_line_rep.Intersect(p2_intersect_line_rep):
  618 + cp = []
  619 + for pp in points:
  620 + poi = ogr.Geometry(ogr.wkbPoint)
  621 + poi.AddPoint(pp[0], pp[1])
  622 + cp.append(poi)
702 623
703   - p1_rep_p1 = p1_intersect_line_rep.GetPoints()[0]
704   - p1_rep_p2 = p1_intersect_line_rep.GetPoints()[1]
  624 + merge_p_line = concaveHull(points, 3)
705 625
706   - p2_rep_p1 = p2_intersect_line_rep.GetPoints()[0]
707   - p2_rep_p2 = p2_intersect_line_rep.GetPoints()[1]
  626 + ring = ogr.Geometry(ogr.wkbLinearRing)
708 627
709   - polygon = self.create_polygon(p1_rep_p1, p2_rep_p2, p1_rep_p2, p2_rep_p1)
  628 + merge_p = ogr.Geometry(ogr.wkbPolygon)
710 629
711   - else:
  630 + for l in merge_p_line:
  631 + ring.AddPoint(l[0], l[1])
712 632
713   - p1_rep_p1 = p1_intersect_line_rep.GetPoints()[0]
714   - p1_rep_p2 = p1_intersect_line_rep.GetPoints()[1]
  633 + ring.AddPoint(merge_p_line[0][0], merge_p_line[0][1])
715 634
716   - p2_rep_p1 = p2_intersect_line_rep.GetPoints()[0]
717   - p2_rep_p2 = p2_intersect_line_rep.GetPoints()[1]
  635 + merge_p.AddGeometry(ring)
  636 + merge_p = merge_p.Simplify(self.distance_buffer_threshold/10)
  637 + merge_polygons.append(merge_p)
718 638
719   - line1 = ogr.Geometry(ogr.wkbLineString)
  639 + return merge_polygons
720 640
721 641
722   - line1.AddPoint(p1_rep_p1[0], p1_rep_p1[1])
723   - line1.AddPoint(p2_rep_p1[0], p2_rep_p1[1])
  642 + def get_subpoint(self, x0, y0, x1, y1, len_size):
724 643
725   - line2 = ogr.Geometry(ogr.wkbLineString)
726   - line2.AddPoint(p1_rep_p2[0], p1_rep_p2[1])
727   - line2.AddPoint(p2_rep_p2[0], p2_rep_p2[1])
  644 + len_size = len_size
  645 + tanx = abs(y1 - y0) / abs(x1 - x0)
  646 + cosx = 1 / math.sqrt(1 + tanx * tanx)
  647 + dx = cosx * len_size
  648 + dy = tanx * dx
728 649
729   - if line1.Intersect(line2):
730   - polygon = self.create_polygon(p1_rep_p1, p1_rep_p2, p2_rep_p1, p2_rep_p2)
  650 + if x1 == x0:
  651 + x2 = x0
  652 + if y1 > y0:
  653 + y2 = y0 + abs(dy)
731 654 else:
732   -
733   - polygon = self.create_polygon(p1_rep_p1, p1_rep_p2, p2_rep_p2, p2_rep_p1)
734   - if polygon.Intersect(p1) or polygon.Intersect(p2):
735   - polygon = self.create_polygon(p1_rep_p1, p1_rep_p2, p2_rep_p1, p2_rep_p2)
736   -
737   -
738   - return polygon
739   -
740   - def create_polygon(self,p1,p2,p3,p4):
741   -
742   - ring = ogr.Geometry(ogr.wkbLinearRing)
743   - ring.AddPoint(p1[0], p1[1])
744   - ring.AddPoint(p2[0], p2[1])
745   - ring.AddPoint(p3[0], p3[1])
746   - ring.AddPoint(p4[0], p4[1])
747   - ring.AddPoint(p1[0], p1[1])
748   -
749   - poly = ogr.Geometry(ogr.wkbPolygon)
750   - poly.AddGeometry(ring)
751   - return poly
752   -
753   -
754   - def get_polygon_lines(self,polygon):
755   - #无孔Polygon
756   - if polygon.GetGeometryCount() == 1:
757   - polygon_line : Geometry = ogr.ForceToLineString(polygon)
758   - # 有孔Polygon
  655 + y2 = y0 - abs(dy)
759 656 else:
760   - polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
761   -
762   - points = polygon_line.GetPoints()
763   -
764   - lines = []
765   - for index in range(len(points)-1):
766   -
767   - point_start = points[index]
768   - point_end = points[index+1]
769   - line = ogr.Geometry(ogr.wkbLineString)
770   - line.AddPoint(point_start[0], point_start[1])
771   - line.AddPoint(point_end[0], point_end[1])
  657 + if x1 < x0:
  658 + x2 = x0 - dx
  659 + else:
  660 + x2 = x0 + dx
772 661
773   - lines.append(line)
  662 + if y1 < y0:
  663 + y2 = y0 - dy
  664 + else:
  665 + y2 = y0 + dy
774 666
775   - return lines
  667 + return x2, y2
776 668
777 669 def process(self):
778 670 polygons = self.data.get_polygons()
779 671 rps = []
  672 +
780 673 for poly in polygons:
781 674 rp = self.get_polygon_reprecent_point(poly)
782 675 rps.append(rp)
  676 + print("完成代表点计算")
783 677
784   - delauney_lines = self.create_delauney(rps)
785   -
786   - min_delauney = self.create_min_delauney(delauney_lines,rps,polygons)
  678 + #代表点要融合
  679 + delauney_lines,rps_sub = self.create_delauney(rps)
787 680
  681 + print("完成树生成计算")
  682 + min_delauney = self.create_min_delauney(delauney_lines,rps_sub)
  683 + print("完成最小生成树计算")
788 684 trees = self.cut_delauney_min_tree(min_delauney,self.distance_buffer_threshold)
  685 + print("完成树裁剪")
789 686
  687 + polygons = self.merge_concave(trees,self.distance_buffer_threshold)
790 688
791   - polygons = self.merge(trees)
792   -
793   - for polygon in polygons:
794   - print("\""+polygon.ExportToWkt() + "\",")
  689 + return [p.ExportToWkt() for p in polygons]
795 690
796 691 if __name__ == '__main__':
797 692
798 693
799   - # print(sd.get_polygons()[0])
800   - # sd.close()
801   -
802   - create = True
803   - create = False
804   -
805   - if create:
806   -
807   - sd = ShapeData(r"J:\Data\制图综合\example.shp")
808   -
809   - ext = sd.layer.GetExtent()
810   - threshold = (ext[1]-ext[0])/20
811   - print(threshold)
812   -
813 694
814   - zh = Zonghe(sd)
815   - zh.process()
816   - else:
817   - wkts = [
818   - ]
  695 + t1 = time.time()
  696 + sd = ShapeData(r"J:\Data\制图综合result\zhongshansub.shp")
819 697
820   - result = r"J:\Data\制图综合\zhonghe3.shp"
821   - ShapeData.create_shp_fromwkts(result,"zh",wkts)
  698 + zh = Zonghe(sd)
  699 + wkts = zh.process()
  700 + result = r"J:\Data\制图综合result\zhongshan_single.shp"
  701 + ShapeData.create_shp_fromwkts(result,"zh",wkts)
822 702
  703 + print(time.time()-t1)
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/8
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from osgeo import ogr
  8 +from osgeo.ogr import *
  9 +import math
  10 +import os
  11 +import copy
  12 +os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
  13 +from test.zonghe.ConcaveHull import concaveHull
  14 +from test.zonghe.ShapeData import ShapeData
  15 +from test.zonghe.Delauney import DelauneyNode,DelauneyLine,DelauneyMinTree
  16 +from test.zonghe.RepresentPoint import RepresentPoint
  17 +from test.zonghe.Util import Util
  18 +import cv2
  19 +import time
  20 +import numpy as np
  21 +
  22 +class Zonghe:
  23 +
  24 + data:ShapeData
  25 + area_threshold = 10.0
  26 + buffer_threshold = 100.0
  27 + distance_buffer_threshold = 1.114691025217302e-04
  28 +
  29 + def __init__(self,data):
  30 + self.data = data
  31 +
  32 + #只处理Polygon,MultiPolygon要拆开
  33 + def get_polygon_reprecent_point(self,polygon:Geometry):
  34 +
  35 + polygon_env = polygon.GetEnvelope()
  36 +
  37 + area_thre = polygon.GetArea()/self.area_threshold
  38 +
  39 + line_length = math.sqrt(math.pow(polygon_env[1] - polygon_env[0],2) + math.pow(polygon_env[3] - polygon_env[2],2))
  40 +
  41 + short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2])
  42 +
  43 + center:Geometry = polygon.Centroid()
  44 + # print(center)
  45 +
  46 +
  47 + # 提前return
  48 + if polygon.Contains(center):
  49 + # print("\"" + center.ExportToWkt() + "\",")
  50 + return RepresentPoint(center, polygon)
  51 +
  52 +
  53 + last_state = None
  54 + line = None
  55 + calculate_time = 0
  56 +
  57 + direction = self.get_direction(polygon, center, line_length)
  58 +
  59 +
  60 + in_hole = False
  61 + in_hole_line = None
  62 +
  63 +
  64 + #无孔Polygon
  65 + if polygon.GetGeometryCount() == 1:
  66 + polygon_line = ogr.ForceToLineString(polygon)
  67 +
  68 + # 有孔Polygon,要分2种情况
  69 + else:
  70 + polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  71 + for i in range(1,polygon.GetGeometryCount()):
  72 + hole_line = polygon.GetGeometryRef(i)
  73 + hole_polygon : Geometry = ogr.ForceToPolygon(hole_line)
  74 + if hole_polygon.Contains(center):
  75 + in_hole = True
  76 + direction = range(0,190,10)
  77 + in_hole_line = ogr.ForceToLineString(hole_line)
  78 + # print("in_hole")
  79 +
  80 + angle1,angle2=None,None
  81 + line = None
  82 + oneside_area, otherside_area = None,None
  83 + for angle in direction:
  84 +
  85 + if in_hole:
  86 + line = self.get_doubleline(center.GetX(),center.GetY(),angle,line_length)
  87 + else:
  88 + line = self.get_line(center.GetX(),center.GetY(),angle,line_length)
  89 +
  90 + oneside_area, otherside_area = self.jude(polygon, line, angle, line_length)
  91 +
  92 +
  93 + if oneside_area > 0 and otherside_area >0:
  94 + if abs(oneside_area-otherside_area) < area_thre:
  95 + break
  96 +
  97 + if last_state is None:
  98 +
  99 + angle2 = angle
  100 +
  101 + if oneside_area == 0 and otherside_area==0:
  102 + last_state = 0
  103 + else:
  104 + last_state = 1 if oneside_area < otherside_area else -1
  105 + else:
  106 +
  107 + angle1 = angle2
  108 + angle2 = angle
  109 +
  110 + if oneside_area == 0 and otherside_area==0:
  111 + now_state = 0
  112 + else:
  113 + now_state = 1 if oneside_area < otherside_area else -1
  114 +
  115 + if last_state* now_state < 0:
  116 + # print(angle)
  117 + break
  118 + else:
  119 + last_state = now_state
  120 +
  121 + #第一条线就是均分线
  122 + if angle1 is None or angle2 is None:
  123 + pass
  124 + else:
  125 + #如果面积差大于阈值,二分法查找
  126 + if abs(oneside_area - otherside_area) > area_thre:
  127 + line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre)
  128 +
  129 +
  130 + # 提前return
  131 + if in_hole:
  132 +
  133 + point_intersection: Geometry = line.Intersection(in_hole_line)
  134 + plist = []
  135 + for i in range(point_intersection.GetGeometryCount()):
  136 + pi = point_intersection.GetGeometryRef(i)
  137 + plist.append(pi)
  138 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  139 + plist_d.sort(key=lambda x:x[1])
  140 +
  141 + nearest_point= plist_d[0][0]
  142 + firt_short_length = short_length/20.0
  143 + radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length)
  144 + # print("\"" + other_point.ExportToWkt() + "\",")
  145 +
  146 +
  147 + while not polygon.Contains(other_point):
  148 +
  149 + firt_short_length = firt_short_length / 2
  150 + radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(),
  151 + nearest_point.GetY(), firt_short_length)
  152 +
  153 +
  154 +
  155 + return RepresentPoint(other_point,polygon)
  156 +
  157 +
  158 + point_intersection:Geometry = line.Intersection(polygon_line)
  159 + xlist = []
  160 + ylist = []
  161 + plist = []
  162 +
  163 + for i in range(point_intersection.GetGeometryCount()):
  164 + pi = point_intersection.GetGeometryRef(i)
  165 + xlist.append(pi.GetX())
  166 + ylist.append(pi.GetY())
  167 + plist.append(pi)
  168 +
  169 +
  170 + reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0]
  171 +
  172 + reprecent_point = self.creat_point(reprecent_point)
  173 +
  174 + if not polygon.Contains(reprecent_point):
  175 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  176 + plist_d.sort(key=lambda x:x[1])
  177 + reprecent_point = self.creat_point(((plist_d[0][0].GetX()+ plist_d[1][0].GetX())/2.0, (plist_d[0][0].GetY()+plist_d[1][0].GetY())/2.0))
  178 +
  179 + # print("\""+reprecent_point.ExportToWkt() + "\",")
  180 +
  181 + rp = RepresentPoint(reprecent_point,polygon)
  182 +
  183 + return rp
  184 +
  185 + def get_line(self, x0, y0 , angle, r):
  186 +
  187 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  188 + line.AddPoint(x0, y0)
  189 + hudu = angle/360.0 * 2 * math.pi
  190 + dx = math.sin(hudu) * r
  191 + dy = math.cos(hudu) * r
  192 + line.AddPoint(x0+dx, y0+dy)
  193 +
  194 + return line
  195 +
  196 + def get_doubleline(self, x0, y0 , angle, r):
  197 +
  198 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  199 +
  200 + hudu = angle/360.0 * 2 * math.pi
  201 + dx = math.sin(hudu) * r
  202 + dy = math.cos(hudu) * r
  203 +
  204 + hudu = (angle+180)/360.0 * 2 * math.pi
  205 + dx2 = math.sin(hudu) * r
  206 + dy2 = math.cos(hudu) * r
  207 +
  208 + line.AddPoint(x0 + dx2, y0 + dy2)
  209 + line.AddPoint(x0+dx, y0+dy)
  210 +
  211 + return line
  212 +
  213 + def get_radline(self,x0,y0,x1,y1,len_size):
  214 + a2 = math.pow((x1-x0),2)
  215 + b2 = math.pow((y1-y0),2)
  216 + len_size = len_size+ math.sqrt(a2+b2)
  217 +
  218 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  219 + line.AddPoint(x0, y0)
  220 + tanx = abs(y1-y0) / abs(x1-x0)
  221 + cosx = 1 / math.sqrt(1 + tanx *tanx)
  222 + dx = cosx* len_size
  223 + dy = tanx * dx
  224 +
  225 + if x1 == x0:
  226 + x2 = x0
  227 + if y1 > y0 :
  228 + y2 = y0 + abs(dy)
  229 + else:
  230 + y2 = y0 - abs(dy)
  231 + else:
  232 + if x1 < x0:
  233 + x2 = x0 - dx
  234 + else:
  235 + x2 = x0 + dx
  236 +
  237 + if y1 < y0:
  238 + y2 = y0 - dy
  239 + else:
  240 + y2 = y0 + dy
  241 +
  242 + line.AddPoint(x2, y2)
  243 +
  244 + other_point = ogr.Geometry(ogr.wkbPoint)
  245 + other_point.AddPoint(x2, y2)
  246 +
  247 + return line , other_point
  248 +
  249 + def get_direction(self,polygon,center,line_length):
  250 + '''
  251 + 判断旋转方向
  252 + :param polygon:
  253 + :param center:
  254 + :param line_length:
  255 + :return:
  256 + '''
  257 +
  258 + line = self.get_line(center.GetX(),center.GetY(),0,line_length)
  259 +
  260 + oneside_area, otherside_area = self.jude(polygon,line,0,line_length)
  261 +
  262 + if oneside_area == 0 and otherside_area == 0 :
  263 + return range(0, 390, 30)
  264 + else:
  265 + line = self.get_line(center.GetX(), center.GetY(), 10, line_length)
  266 + oneside_area_contrast, otherside_area_contrast = self.jude(polygon, line, 30, line_length)
  267 +
  268 + if oneside_area_contrast == 0 and otherside_area_contrast == 0:
  269 + return range(360, -30, -30)
  270 + else:
  271 + if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast):
  272 + return range(0, 390, 30)
  273 + else:
  274 + return range(360, -30, -30)
  275 +
  276 + def jude(self,polygon,line,angle,line_length):
  277 +
  278 + line_buffer: Geometry = line.Buffer(line_length / self.buffer_threshold)
  279 + clip_geom: Geometry = polygon.Difference(line_buffer)
  280 +
  281 + oneside_area = 0
  282 + otherside_area = 0
  283 +
  284 + gc = clip_geom.GetGeometryCount()
  285 + if gc <= 1:
  286 + oneside_area = 0
  287 + otherside_area = 0
  288 + else:
  289 + triangle1, triangle2 = self.get_side_triangle(line, angle)
  290 +
  291 +
  292 + for gi in range(clip_geom.GetGeometryCount()):
  293 + clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi)
  294 + it = clip_geom_i.Intersection(triangle1)
  295 +
  296 + if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect(
  297 + line_buffer):
  298 + oneside_area += clip_geom_i.GetArea()
  299 + else:
  300 + otherside_area += clip_geom_i.GetArea()
  301 + return oneside_area, otherside_area
  302 +
  303 + def division(self,polygon,center,in_hole,line_length,angle1,angle2,area_thre):
  304 +
  305 + mid_angle = (angle1 + angle2)/2.0
  306 +
  307 +
  308 + if in_hole:
  309 + line = self.get_doubleline(center.GetX(), center.GetY(), mid_angle, line_length)
  310 + else:
  311 + line = self.get_line(center.GetX(), center.GetY(), mid_angle, line_length)
  312 +
  313 + one,other = self.jude(polygon,line,mid_angle,line_length)
  314 +
  315 + while abs(one - other) > area_thre:
  316 + if one > other:
  317 + if angle1 > angle2:
  318 + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre)
  319 + else:
  320 + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre)
  321 + else:
  322 + if angle1 > angle2:
  323 + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre)
  324 + else:
  325 + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre)
  326 + return line
  327 +
  328 + def get_side_triangle(self,line:Geometry,angle):
  329 + '''
  330 + 获取方向三角形
  331 + :param line:
  332 + :param angle:
  333 + :return:
  334 + '''
  335 +
  336 + start = line.GetPoint(0)
  337 + end = line.GetPoint(1)
  338 +
  339 +
  340 + angle_t = angle-30
  341 + hudu = angle_t/360.0 * 2 * math.pi
  342 +
  343 + r = line.Length() / (2*math.cos( math.pi/6))
  344 + dx = math.sin(hudu) * r
  345 + dy = math.cos(hudu) * r
  346 +
  347 +
  348 + ring1 = ogr.Geometry(ogr.wkbLinearRing)
  349 + ring1.AddPoint(start[0], start[1])
  350 + ring1.AddPoint(start[0] + dx, start[1] + dy)
  351 + ring1.AddPoint(end[0], end[1])
  352 + ring1.AddPoint(start[0], start[1])
  353 + triangle1 = ogr.Geometry(ogr.wkbPolygon)
  354 + triangle1.AddGeometry(ring1)
  355 +
  356 +
  357 + angle_t = angle+30
  358 + hudu = angle_t/360.0 * 2 * math.pi
  359 +
  360 + r = line.Length() / (2*math.cos( math.pi/6))
  361 +
  362 + dx = math.sin(hudu) * r
  363 + dy = math.cos(hudu) * r
  364 +
  365 + ring2 = ogr.Geometry(ogr.wkbLinearRing)
  366 + ring2.AddPoint(start[0], start[1])
  367 + ring2.AddPoint(start[0]+dx, start[1]+dy)
  368 + ring2.AddPoint(end[0], end[1])
  369 + ring2.AddPoint(start[0], start[1])
  370 + triangle2 = ogr.Geometry(ogr.wkbPolygon)
  371 + triangle2.AddGeometry(ring2)
  372 +
  373 + return triangle1,triangle2
  374 +
  375 + def creat_point(self,tuple):
  376 + p: Geometry = ogr.Geometry(ogr.wkbPoint)
  377 + p.AddPoint(tuple[0], tuple[1])
  378 + return p
  379 +
  380 + def create_delauney(self,rps):
  381 + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
  382 +
  383 + rp_dict = {}
  384 + delauney_lines = []
  385 +
  386 + rps_sub = set()
  387 + for rp in rps:
  388 + multipoint.AddGeometry(rp.point)
  389 + # 多边形代表点相同,需要融合多边形
  390 + if rp_dict.get(rp.point.GetPoint(0).__str__()):
  391 + rp_exist = rp_dict.get(rp.point.GetPoint(0).__str__())
  392 + rp_exist.polygon = rp_exist.polygon.Union(rp.polygon)
  393 + else:
  394 + rp_dict[rp.point.GetPoint(0).__str__()] = rp
  395 + rps_sub.add(rp)
  396 +
  397 + delauney:Geometry = multipoint.DelaunayTriangulation(bOnlyEdges=True)
  398 +
  399 + for index in range(delauney.GetGeometryCount()):
  400 + triangle_line:Geometry = delauney.GetGeometryRef(index)
  401 + p = triangle_line.GetPoint(0)
  402 + p_next = triangle_line.GetPoint(1)
  403 +
  404 + rp1 = rp_dict.get(p.__str__())
  405 + rp2 = rp_dict.get(p_next.__str__())
  406 +
  407 + delauney_line = DelauneyLine(rp1,rp2)
  408 + delauney_lines.append(delauney_line)
  409 +
  410 + return delauney_lines,rps_sub
  411 +
  412 + def create_min_delauney(self,delauney_lines,rps):
  413 + '''
  414 + 使用prim算法计算最小生成树
  415 + :param delauney_lines:
  416 + :param polygons:
  417 + :return:
  418 + '''
  419 +
  420 + kv = dict()
  421 + # print(len(rps))
  422 +
  423 +
  424 + rps_set = set(rps)
  425 +
  426 + for delauney_line in delauney_lines:
  427 + if kv.get(delauney_line.rp1):
  428 + kv[delauney_line.rp1].add(delauney_line)
  429 + else:
  430 + kv[delauney_line.rp1] = set()
  431 + kv[delauney_line.rp1].add(delauney_line)
  432 +
  433 + if kv.get(delauney_line.rp2):
  434 + kv[delauney_line.rp2].add(delauney_line)
  435 + else:
  436 + kv[delauney_line.rp2] = set()
  437 + kv[delauney_line.rp2].add(delauney_line)
  438 +
  439 +
  440 +
  441 + print("完成三角边倒排索引")
  442 +
  443 + #初始化树
  444 + delauney_lines = sorted(delauney_lines,key=lambda x:x.distance)
  445 + delauney_min_tree = DelauneyMinTree()
  446 +
  447 + delauney_min_tree.append(delauney_lines[0],kv)
  448 +
  449 + rps_set.remove(delauney_lines[0].rp1)
  450 + rps_set.remove(delauney_lines[0].rp2)
  451 +
  452 + kv[delauney_lines[0].rp1].remove(delauney_lines[0])
  453 + kv[delauney_lines[0].rp2].remove(delauney_lines[0])
  454 +
  455 + print("完成最小生成树初始化")
  456 +
  457 + while rps_set.__len__()>0:
  458 +
  459 + relate_delauney_line = delauney_min_tree.touch_delauney_lines
  460 +
  461 +
  462 + relate_delauney_line_sort = sorted(relate_delauney_line,key=lambda x:x.distance)
  463 +
  464 + min_distance_line = relate_delauney_line_sort[0]
  465 + #删除
  466 + other_rp = delauney_min_tree.get_other_rp(min_distance_line)
  467 +
  468 + if other_rp is None:
  469 + kv[min_distance_line.rp1].remove(min_distance_line)
  470 + kv[min_distance_line.rp2].remove(min_distance_line)
  471 + continue
  472 +
  473 + delauney_min_tree.append(min_distance_line,kv)
  474 +
  475 + rps_set.remove(other_rp)
  476 +
  477 + kv[min_distance_line.rp1].remove(min_distance_line)
  478 + kv[min_distance_line.rp2].remove(min_distance_line)
  479 +
  480 +
  481 + print("完成最小生成树")
  482 +
  483 + return delauney_min_tree
  484 +
  485 + def cut_delauney_min_tree(self,delauney_min_tree:DelauneyMinTree,threshold):
  486 +
  487 + trees = []
  488 + kv = {}
  489 +
  490 + count = 0
  491 +
  492 + for delauney_line in delauney_min_tree.delauney_lines_list:
  493 +
  494 + dn1 = kv.get(delauney_line.rp1)
  495 + dn2 = kv.get(delauney_line.rp2)
  496 +
  497 +
  498 + if not dn1:
  499 + dn1 = DelauneyNode(delauney_line.rp1)
  500 + kv[delauney_line.rp1] = dn1
  501 +
  502 + if not dn2:
  503 +
  504 + trees.append(dn1)
  505 +
  506 + dn2 = DelauneyNode(delauney_line.rp2)
  507 + kv[delauney_line.rp2] = dn2
  508 +
  509 + if delauney_line.distance < threshold:
  510 + dn1.add_children(dn2,delauney_line)
  511 + count +=1
  512 +
  513 + else:
  514 + #断开
  515 + trees.append(dn2)
  516 + else:
  517 +
  518 + if delauney_line.distance < threshold:
  519 + dn2.add_children(dn1,delauney_line)
  520 + count += 1
  521 + else:
  522 + trees.append(dn1)
  523 + else:
  524 +
  525 + dn2 = DelauneyNode(delauney_line.rp2)
  526 + kv[delauney_line.rp2] = dn2
  527 +
  528 + if delauney_line.distance < threshold:
  529 + dn1.add_children(dn2,delauney_line)
  530 + count += 1
  531 + else:
  532 + trees.append(dn2)
  533 +
  534 +
  535 + return trees
  536 +
  537 + def create_polygon(self,p1,p2,p3,p4):
  538 +
  539 + ring = ogr.Geometry(ogr.wkbLinearRing)
  540 + ring.AddPoint(p1[0], p1[1])
  541 + ring.AddPoint(p2[0], p2[1])
  542 + ring.AddPoint(p3[0], p3[1])
  543 + ring.AddPoint(p4[0], p4[1])
  544 + ring.AddPoint(p1[0], p1[1])
  545 +
  546 + poly = ogr.Geometry(ogr.wkbPolygon)
  547 + poly.AddGeometry(ring)
  548 + return poly
  549 +
  550 + def get_polygon_lines(self,polygon):
  551 + #无孔Polygon
  552 + if polygon.GetGeometryCount() in [0,1]:
  553 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  554 + # 有孔Polygon
  555 + else:
  556 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  557 +
  558 + return polygon_line
  559 +
  560 + def merge_concave(self, trees, distance_threshold):
  561 + merge_polygons = []
  562 + count = 1
  563 +
  564 + for tree in trees:
  565 + print(count)
  566 + count+=1
  567 + polygons = list(tree.get_polygons())
  568 +
  569 + merge_raw: Geometry = polygons[0]
  570 + for p in polygons:
  571 + merge_raw = merge_raw.Union(p)
  572 +
  573 + points = []
  574 +
  575 +
  576 + for i in range(merge_raw.GetGeometryCount()):
  577 +
  578 + poly = merge_raw.GetGeometryRef(i)
  579 + poly_line :Geometry = self.get_polygon_lines(poly)
  580 + if poly_line:
  581 + for indx in range(poly_line.GetPointCount() - 1):
  582 + poi = poly_line.GetPoint(indx)
  583 +
  584 + points.append(poi)
  585 +
  586 + poi_next = poly_line.GetPoint(indx + 1)
  587 +
  588 + dis = math.sqrt(math.pow(poi[0] - poi_next[0], 2) + math.pow(poi[1] - poi_next[1], 2))
  589 + # print(dis)
  590 + if dis > distance_threshold:
  591 + times = int(dis / distance_threshold)
  592 + # print(times)
  593 + for ts in range(1, times + 1):
  594 + x, y = self.get_subpoint(poi[0], poi[1], poi_next[0], poi_next[1], (ts * distance_threshold))
  595 + points.append([x, y])
  596 +
  597 + points = np.array([[p[0], p[1]] for p in points])
  598 +
  599 +
  600 + cp = []
  601 + for pp in points:
  602 + poi = ogr.Geometry(ogr.wkbPoint)
  603 + poi.AddPoint(pp[0], pp[1])
  604 + cp.append(poi)
  605 +
  606 +
  607 + merge_p_line = concaveHull(points, 3)
  608 +
  609 + ring = ogr.Geometry(ogr.wkbLinearRing)
  610 +
  611 + merge_p = ogr.Geometry(ogr.wkbPolygon)
  612 +
  613 + for l in merge_p_line:
  614 + ring.AddPoint(l[0], l[1])
  615 +
  616 + ring.AddPoint(merge_p_line[0][0], merge_p_line[0][1])
  617 +
  618 + merge_p.AddGeometry(ring)
  619 + merge_p = merge_p.Simplify(self.distance_buffer_threshold/10)
  620 + merge_polygons.append(merge_p)
  621 +
  622 + return merge_polygons
  623 + # return cp
  624 +
  625 + def get_subpoint(self, x0, y0, x1, y1, len_size):
  626 +
  627 + len_size = len_size
  628 + tanx = abs(y1 - y0) / abs(x1 - x0)
  629 + cosx = 1 / math.sqrt(1 + tanx * tanx)
  630 + dx = cosx * len_size
  631 + dy = tanx * dx
  632 +
  633 + if x1 == x0:
  634 + x2 = x0
  635 + if y1 > y0:
  636 + y2 = y0 + abs(dy)
  637 + else:
  638 + y2 = y0 - abs(dy)
  639 + else:
  640 + if x1 < x0:
  641 + x2 = x0 - dx
  642 + else:
  643 + x2 = x0 + dx
  644 +
  645 + if y1 < y0:
  646 + y2 = y0 - dy
  647 + else:
  648 + y2 = y0 + dy
  649 +
  650 + return x2, y2
  651 +
  652 + def merge_delauney(self,trees):
  653 +
  654 + merge_polygons = []
  655 + count = 1
  656 +
  657 + for tree in trees:
  658 +
  659 + polygons = list(tree.get_polygons())
  660 +
  661 + mp: Geometry = ogr.Geometry(ogr.wkbMultiPolygon)
  662 + for p in polygons:
  663 + mp.AddGeometry(p)
  664 +
  665 +
  666 +
  667 + delauney: Geometry = mp.DelaunayTriangulation()
  668 +
  669 + intp = []
  670 + for p in delauney:
  671 +
  672 + res = p
  673 + ispass = False
  674 + for pp in polygons:
  675 + check:Geometry = res.Difference(pp)
  676 + if check.IsEmpty():
  677 + ispass = True
  678 + break
  679 + else:
  680 + res = check
  681 + if not ispass:
  682 + res_extend = self.extend_tri(res)
  683 + intp.append(res_extend)
  684 +
  685 + # polygons.extend(intp)
  686 + #
  687 + # mp: Geometry = ogr.Geometry(ogr.wkbMultiPolygon)
  688 + #
  689 + # for p in polygons:
  690 + # mp.AddGeometry(p)
  691 + # merge:Geometry = mp.UnionCascaded()
  692 + # merge_polygons.append(merge)
  693 +
  694 + return intp
  695 +
  696 +
  697 +
  698 + def extend_tri(self,triangle:Geometry):
  699 +
  700 + center:Geometry = triangle.Centroid()
  701 + tri_line: Geometry = self.get_polygon_lines(triangle)
  702 +
  703 + result_geo = ogr.Geometry(ogr.wkbPolygon)
  704 + result_geo_ring:Geometry = ogr.Geometry(ogr.wkbLinearRing)
  705 + for point in tri_line.GetPoints():
  706 + radpoint = self.get_radpoint(center.GetX(),center.GetY(),point[0],point[1],0.00000001)
  707 +
  708 + result_geo_ring.AddPoint(radpoint.GetX(),radpoint.GetY())
  709 + result_geo.AddGeometry(result_geo_ring)
  710 +
  711 + return result_geo
  712 +
  713 + def get_radpoint(self,x0,y0,x1,y1,len_size):
  714 + a2 = math.pow((x1-x0),2)
  715 + b2 = math.pow((y1-y0),2)
  716 + len_size = len_size+ math.sqrt(a2+b2)
  717 +
  718 + tanx = abs(y1-y0) / abs(x1-x0)
  719 + cosx = 1 / math.sqrt(1 + tanx *tanx)
  720 + dx = cosx* len_size
  721 + dy = tanx * dx
  722 +
  723 + if x1 == x0:
  724 + x2 = x0
  725 + if y1 > y0 :
  726 + y2 = y0 + abs(dy)
  727 + else:
  728 + y2 = y0 - abs(dy)
  729 + else:
  730 + if x1 < x0:
  731 + x2 = x0 - dx
  732 + else:
  733 + x2 = x0 + dx
  734 +
  735 + if y1 < y0:
  736 + y2 = y0 - dy
  737 + else:
  738 + y2 = y0 + dy
  739 +
  740 + other_point = ogr.Geometry(ogr.wkbPoint)
  741 + other_point.AddPoint(x2, y2)
  742 +
  743 + return other_point
  744 +
  745 +
  746 + def process(self):
  747 + polygons = self.data.get_polygons()
  748 + rps = []
  749 +
  750 + for poly in polygons:
  751 + rp = self.get_polygon_reprecent_point(poly)
  752 + rps.append(rp)
  753 + print("完成代表点计算")
  754 +
  755 + #代表点要融合
  756 + delauney_lines,rps_sub = self.create_delauney(rps)
  757 +
  758 + print("完成树生成计算")
  759 + min_delauney = self.create_min_delauney(delauney_lines,rps_sub)
  760 + print("完成最小生成树计算")
  761 + trees = self.cut_delauney_min_tree(min_delauney,self.distance_buffer_threshold)
  762 + print("完成树裁剪")
  763 +
  764 + polygons = self.merge_concave(trees,self.distance_buffer_threshold)
  765 + # polygons = self.merge_delauney(trees)
  766 +
  767 + return [p.ExportToWkt() for p in polygons]
  768 +
  769 +if __name__ == '__main__':
  770 +
  771 +
  772 + # print(sd.get_polygons()[0])
  773 + # sd.close()
  774 +
  775 + t1 = time.time()
  776 + sd = ShapeData(r"J:\Data\制图综合result\zhongshansub2.shp")
  777 +
  778 + zh = Zonghe(sd)
  779 + wkts = zh.process()
  780 + result = r"J:\Data\制图综合result\zhongshansub2_m2.shp"
  781 + ShapeData.create_shp_fromwkts(result,"zh",wkts)
  782 +
  783 + print(time.time()-t1)
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/8
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from osgeo import ogr
  8 +from osgeo.ogr import *
  9 +import math
  10 +import os
  11 +import copy
  12 +os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
  13 +from test.zonghe.ConcaveHull import concaveHull
  14 +from test.zonghe.ShapeData import ShapeData
  15 +from test.zonghe.Delauney import DelauneyNode,DelauneyLine,DelauneyMinTree
  16 +from test.zonghe.RepresentPoint import RepresentPoint
  17 +
  18 +import time
  19 +
  20 +import numpy as np
  21 +from multiprocessing import Process
  22 +from threading import Thread
  23 +class MyThread(Thread):
  24 + def __init__(self,func,args=()):
  25 + super(MyThread,self).__init__()
  26 + self.func = func
  27 + self.args = args
  28 + def run(self):
  29 + self.result = self.func(*self.args)
  30 + def get_result(self):
  31 + try:
  32 + return self.result
  33 + except Exception:
  34 + return None
  35 +
  36 +class Zonghe:
  37 +
  38 + data:ShapeData
  39 + area_threshold = 10.0
  40 + buffer_threshold = 100.0
  41 + distance_buffer_threshold = 1.114691025217302e-04
  42 +
  43 + def __init__(self,data):
  44 + self.data = data
  45 +
  46 +
  47 + #只处理Polygon,MultiPolygon要拆开
  48 + def get_polygon_reprecent_point(self,polygon:Geometry):
  49 +
  50 + polygon_env = polygon.GetEnvelope()
  51 +
  52 + area_thre = polygon.GetArea()/self.area_threshold
  53 +
  54 + line_length = math.sqrt(math.pow(polygon_env[1] - polygon_env[0],2) + math.pow(polygon_env[3] - polygon_env[2],2))
  55 +
  56 + short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2])
  57 +
  58 + center:Geometry = polygon.Centroid()
  59 + # print(center)
  60 +
  61 +
  62 + # 提前return
  63 + if polygon.Contains(center):
  64 + # print("\"" + center.ExportToWkt() + "\",")
  65 + return RepresentPoint(center, polygon)
  66 +
  67 +
  68 + last_state = None
  69 + line = None
  70 + calculate_time = 0
  71 +
  72 + direction = self.get_direction(polygon, center, line_length)
  73 +
  74 +
  75 + in_hole = False
  76 + in_hole_line = None
  77 +
  78 +
  79 + #无孔Polygon
  80 + if polygon.GetGeometryCount() == 1:
  81 + polygon_line = ogr.ForceToLineString(polygon)
  82 +
  83 + # 有孔Polygon,要分2种情况
  84 + else:
  85 + polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  86 + for i in range(1,polygon.GetGeometryCount()):
  87 + hole_line = polygon.GetGeometryRef(i)
  88 + hole_polygon : Geometry = ogr.ForceToPolygon(hole_line)
  89 + if hole_polygon.Contains(center):
  90 + in_hole = True
  91 + direction = range(0,190,10)
  92 + in_hole_line = ogr.ForceToLineString(hole_line)
  93 + # print("in_hole")
  94 +
  95 + angle1,angle2=None,None
  96 + line = None
  97 + oneside_area, otherside_area = None,None
  98 + for angle in direction:
  99 +
  100 + if in_hole:
  101 + line = self.get_doubleline(center.GetX(),center.GetY(),angle,line_length)
  102 + else:
  103 + line = self.get_line(center.GetX(),center.GetY(),angle,line_length)
  104 +
  105 + oneside_area, otherside_area = self.jude(polygon, line, angle, line_length)
  106 +
  107 +
  108 + if oneside_area > 0 and otherside_area >0:
  109 + if abs(oneside_area-otherside_area) < area_thre:
  110 + break
  111 +
  112 + if last_state is None:
  113 +
  114 + angle2 = angle
  115 +
  116 + if oneside_area == 0 and otherside_area==0:
  117 + last_state = 0
  118 + else:
  119 + last_state = 1 if oneside_area < otherside_area else -1
  120 + else:
  121 +
  122 + angle1 = angle2
  123 + angle2 = angle
  124 +
  125 + if oneside_area == 0 and otherside_area==0:
  126 + now_state = 0
  127 + else:
  128 + now_state = 1 if oneside_area < otherside_area else -1
  129 +
  130 + if last_state* now_state < 0:
  131 + # print(angle)
  132 + break
  133 + else:
  134 + last_state = now_state
  135 +
  136 + #第一条线就是均分线
  137 + if angle1 is None or angle2 is None:
  138 + pass
  139 + else:
  140 + #如果面积差大于阈值,二分法查找
  141 + if abs(oneside_area - otherside_area) > area_thre:
  142 + line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre)
  143 +
  144 +
  145 + # 提前return
  146 + if in_hole:
  147 +
  148 + point_intersection: Geometry = line.Intersection(in_hole_line)
  149 + plist = []
  150 + for i in range(point_intersection.GetGeometryCount()):
  151 + pi = point_intersection.GetGeometryRef(i)
  152 + plist.append(pi)
  153 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  154 + plist_d.sort(key=lambda x:x[1])
  155 +
  156 + nearest_point= plist_d[0][0]
  157 + firt_short_length = short_length/20.0
  158 + radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length)
  159 + # print("\"" + other_point.ExportToWkt() + "\",")
  160 +
  161 +
  162 + while not polygon.Contains(other_point):
  163 +
  164 + firt_short_length = firt_short_length / 2
  165 + radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(),
  166 + nearest_point.GetY(), firt_short_length)
  167 +
  168 +
  169 +
  170 + return RepresentPoint(other_point,polygon)
  171 +
  172 +
  173 + point_intersection:Geometry = line.Intersection(polygon_line)
  174 + xlist = []
  175 + ylist = []
  176 + plist = []
  177 +
  178 + for i in range(point_intersection.GetGeometryCount()):
  179 + pi = point_intersection.GetGeometryRef(i)
  180 + xlist.append(pi.GetX())
  181 + ylist.append(pi.GetY())
  182 + plist.append(pi)
  183 +
  184 +
  185 + reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0]
  186 +
  187 + reprecent_point = self.creat_point(reprecent_point)
  188 +
  189 + if not polygon.Contains(reprecent_point):
  190 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  191 + plist_d.sort(key=lambda x:x[1])
  192 + reprecent_point = self.creat_point(((plist_d[0][0].GetX()+ plist_d[1][0].GetX())/2.0, (plist_d[0][0].GetY()+plist_d[1][0].GetY())/2.0))
  193 +
  194 + # print("\""+reprecent_point.ExportToWkt() + "\",")
  195 +
  196 + rp = RepresentPoint(reprecent_point,polygon)
  197 +
  198 + return rp
  199 +
  200 + def get_line(self, x0, y0 , angle, r):
  201 +
  202 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  203 + line.AddPoint(x0, y0)
  204 + hudu = angle/360.0 * 2 * math.pi
  205 + dx = math.sin(hudu) * r
  206 + dy = math.cos(hudu) * r
  207 + line.AddPoint(x0+dx, y0+dy)
  208 +
  209 + return line
  210 +
  211 + def get_doubleline(self, x0, y0 , angle, r):
  212 +
  213 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  214 +
  215 + hudu = angle/360.0 * 2 * math.pi
  216 + dx = math.sin(hudu) * r
  217 + dy = math.cos(hudu) * r
  218 +
  219 + hudu = (angle+180)/360.0 * 2 * math.pi
  220 + dx2 = math.sin(hudu) * r
  221 + dy2 = math.cos(hudu) * r
  222 +
  223 + line.AddPoint(x0 + dx2, y0 + dy2)
  224 + line.AddPoint(x0+dx, y0+dy)
  225 +
  226 + return line
  227 +
  228 + def get_radline(self,x0,y0,x1,y1,len_size):
  229 + a2 = math.pow((x1-x0),2)
  230 + b2 = math.pow((y1-y0),2)
  231 + len_size = len_size+ math.sqrt(a2+b2)
  232 +
  233 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  234 + line.AddPoint(x0, y0)
  235 + tanx = abs(y1-y0) / abs(x1-x0)
  236 + cosx = 1 / math.sqrt(1 + tanx *tanx)
  237 + dx = cosx* len_size
  238 + dy = tanx * dx
  239 +
  240 + if x1 == x0:
  241 + x2 = x0
  242 + if y1 > y0 :
  243 + y2 = y0 + abs(dy)
  244 + else:
  245 + y2 = y0 - abs(dy)
  246 + else:
  247 + if x1 < x0:
  248 + x2 = x0 - dx
  249 + else:
  250 + x2 = x0 + dx
  251 +
  252 + if y1 < y0:
  253 + y2 = y0 - dy
  254 + else:
  255 + y2 = y0 + dy
  256 +
  257 + line.AddPoint(x2, y2)
  258 +
  259 + other_point = ogr.Geometry(ogr.wkbPoint)
  260 + other_point.AddPoint(x2, y2)
  261 +
  262 + return line , other_point
  263 +
  264 + def get_direction(self,polygon,center,line_length):
  265 + '''
  266 + 判断旋转方向
  267 + :param polygon:
  268 + :param center:
  269 + :param line_length:
  270 + :return:
  271 + '''
  272 +
  273 + line = self.get_line(center.GetX(),center.GetY(),0,line_length)
  274 +
  275 + oneside_area, otherside_area = self.jude(polygon,line,0,line_length)
  276 +
  277 + if oneside_area == 0 and otherside_area == 0 :
  278 + return range(0, 390, 30)
  279 + else:
  280 + line = self.get_line(center.GetX(), center.GetY(), 10, line_length)
  281 + oneside_area_contrast, otherside_area_contrast = self.jude(polygon, line, 30, line_length)
  282 +
  283 + if oneside_area_contrast == 0 and otherside_area_contrast == 0:
  284 + return range(360, -30, -30)
  285 + else:
  286 + if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast):
  287 + return range(0, 390, 30)
  288 + else:
  289 + return range(360, -30, -30)
  290 +
  291 + def jude(self,polygon,line,angle,line_length):
  292 +
  293 + line_buffer: Geometry = line.Buffer(line_length / self.buffer_threshold)
  294 + clip_geom: Geometry = polygon.Difference(line_buffer)
  295 +
  296 + oneside_area = 0
  297 + otherside_area = 0
  298 +
  299 + gc = clip_geom.GetGeometryCount()
  300 + if gc <= 1:
  301 + oneside_area = 0
  302 + otherside_area = 0
  303 + else:
  304 + triangle1, triangle2 = self.get_side_triangle(line, angle)
  305 +
  306 +
  307 + for gi in range(clip_geom.GetGeometryCount()):
  308 + clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi)
  309 + it = clip_geom_i.Intersection(triangle1)
  310 +
  311 + if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect(
  312 + line_buffer):
  313 + oneside_area += clip_geom_i.GetArea()
  314 + else:
  315 + otherside_area += clip_geom_i.GetArea()
  316 + return oneside_area, otherside_area
  317 +
  318 + def division(self,polygon,center,in_hole,line_length,angle1,angle2,area_thre):
  319 +
  320 + mid_angle = (angle1 + angle2)/2.0
  321 +
  322 +
  323 + if in_hole:
  324 + line = self.get_doubleline(center.GetX(), center.GetY(), mid_angle, line_length)
  325 + else:
  326 + line = self.get_line(center.GetX(), center.GetY(), mid_angle, line_length)
  327 +
  328 + one,other = self.jude(polygon,line,mid_angle,line_length)
  329 +
  330 + while abs(one - other) > area_thre:
  331 + if one > other:
  332 + if angle1 > angle2:
  333 + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre)
  334 + else:
  335 + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre)
  336 + else:
  337 + if angle1 > angle2:
  338 + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre)
  339 + else:
  340 + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre)
  341 + return line
  342 +
  343 + def get_side_triangle(self,line:Geometry,angle):
  344 + '''
  345 + 获取方向三角形
  346 + :param line:
  347 + :param angle:
  348 + :return:
  349 + '''
  350 +
  351 + start = line.GetPoint(0)
  352 + end = line.GetPoint(1)
  353 +
  354 +
  355 + angle_t = angle-30
  356 + hudu = angle_t/360.0 * 2 * math.pi
  357 +
  358 + r = line.Length() / (2*math.cos( math.pi/6))
  359 + dx = math.sin(hudu) * r
  360 + dy = math.cos(hudu) * r
  361 +
  362 +
  363 + ring1 = ogr.Geometry(ogr.wkbLinearRing)
  364 + ring1.AddPoint(start[0], start[1])
  365 + ring1.AddPoint(start[0] + dx, start[1] + dy)
  366 + ring1.AddPoint(end[0], end[1])
  367 + ring1.AddPoint(start[0], start[1])
  368 + triangle1 = ogr.Geometry(ogr.wkbPolygon)
  369 + triangle1.AddGeometry(ring1)
  370 +
  371 +
  372 + angle_t = angle+30
  373 + hudu = angle_t/360.0 * 2 * math.pi
  374 +
  375 + r = line.Length() / (2*math.cos( math.pi/6))
  376 +
  377 + dx = math.sin(hudu) * r
  378 + dy = math.cos(hudu) * r
  379 +
  380 + ring2 = ogr.Geometry(ogr.wkbLinearRing)
  381 + ring2.AddPoint(start[0], start[1])
  382 + ring2.AddPoint(start[0]+dx, start[1]+dy)
  383 + ring2.AddPoint(end[0], end[1])
  384 + ring2.AddPoint(start[0], start[1])
  385 + triangle2 = ogr.Geometry(ogr.wkbPolygon)
  386 + triangle2.AddGeometry(ring2)
  387 +
  388 + return triangle1,triangle2
  389 +
  390 + def creat_point(self,tuple):
  391 + p: Geometry = ogr.Geometry(ogr.wkbPoint)
  392 + p.AddPoint(tuple[0], tuple[1])
  393 + return p
  394 +
  395 + def create_delauney(self,rps):
  396 + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
  397 +
  398 + rp_dict = {}
  399 + delauney_lines = []
  400 +
  401 + rps_sub = set()
  402 + for rp in rps:
  403 + multipoint.AddGeometry(rp.point)
  404 + # 多边形代表点相同,需要融合多边形
  405 + if rp_dict.get(rp.point.GetPoint(0).__str__()):
  406 + rp_exist = rp_dict.get(rp.point.GetPoint(0).__str__())
  407 + rp_exist.polygon = rp_exist.polygon.Union(rp.polygon)
  408 + else:
  409 + rp_dict[rp.point.GetPoint(0).__str__()] = rp
  410 + rps_sub.add(rp)
  411 +
  412 + delauney:Geometry = multipoint.DelaunayTriangulation(bOnlyEdges=True)
  413 +
  414 + for index in range(delauney.GetGeometryCount()):
  415 + triangle_line:Geometry = delauney.GetGeometryRef(index)
  416 + p = triangle_line.GetPoint(0)
  417 + p_next = triangle_line.GetPoint(1)
  418 +
  419 + rp1 = rp_dict.get(p.__str__())
  420 + rp2 = rp_dict.get(p_next.__str__())
  421 +
  422 + delauney_line = DelauneyLine(rp1,rp2)
  423 + delauney_lines.append(delauney_line)
  424 +
  425 + return delauney_lines,rps_sub
  426 +
  427 + def create_min_delauney(self,delauney_lines,rps):
  428 + '''
  429 + 使用prim算法计算最小生成树
  430 + :param delauney_lines:
  431 + :param polygons:
  432 + :return:
  433 + '''
  434 +
  435 + kv = dict()
  436 + print(len(rps))
  437 +
  438 +
  439 + rps_set = set(rps)
  440 +
  441 + for delauney_line in delauney_lines:
  442 + if kv.get(delauney_line.rp1):
  443 + kv[delauney_line.rp1].add(delauney_line)
  444 + else:
  445 + kv[delauney_line.rp1] = set()
  446 + kv[delauney_line.rp1].add(delauney_line)
  447 +
  448 + if kv.get(delauney_line.rp2):
  449 + kv[delauney_line.rp2].add(delauney_line)
  450 + else:
  451 + kv[delauney_line.rp2] = set()
  452 + kv[delauney_line.rp2].add(delauney_line)
  453 +
  454 + print(len(kv))
  455 +
  456 + print("完成三角边倒排索引")
  457 +
  458 + #初始化树
  459 + delauney_lines = sorted(delauney_lines,key=lambda x:x.distance)
  460 + delauney_min_tree = DelauneyMinTree()
  461 +
  462 + delauney_min_tree.append(delauney_lines[0],kv)
  463 +
  464 + rps_set.remove(delauney_lines[0].rp1)
  465 + rps_set.remove(delauney_lines[0].rp2)
  466 +
  467 + kv[delauney_lines[0].rp1].remove(delauney_lines[0])
  468 + kv[delauney_lines[0].rp2].remove(delauney_lines[0])
  469 +
  470 + print("完成最小生成树初始化")
  471 +
  472 + while rps_set.__len__()>0:
  473 +
  474 + print(rps_set.__len__())
  475 + t1 = time.time()
  476 + # relate_delauney_line = delauney_min_tree.get_other_relate_delauney_lines(kv,rps_set)
  477 +
  478 + relate_delauney_line = delauney_min_tree.touch_delauney_lines
  479 +
  480 +
  481 + relate_delauney_line_sort = sorted(relate_delauney_line,key=lambda x:x.distance)
  482 +
  483 + min_distance_line = relate_delauney_line_sort[0]
  484 + #删除
  485 + other_rp = delauney_min_tree.get_other_rp(min_distance_line)
  486 +
  487 + if other_rp is None:
  488 + kv[min_distance_line.rp1].remove(min_distance_line)
  489 + kv[min_distance_line.rp2].remove(min_distance_line)
  490 + continue
  491 +
  492 + delauney_min_tree.append(min_distance_line,kv)
  493 +
  494 + rps_set.remove(other_rp)
  495 +
  496 + kv[min_distance_line.rp1].remove(min_distance_line)
  497 + kv[min_distance_line.rp2].remove(min_distance_line)
  498 +
  499 + # print(time.time() - t2)
  500 + print("完成最小生成树")
  501 +
  502 + return delauney_min_tree
  503 +
  504 + def cut_delauney_min_tree(self,delauney_min_tree:DelauneyMinTree,threshold):
  505 +
  506 + trees = []
  507 + kv = {}
  508 +
  509 + count = 0
  510 +
  511 + for delauney_line in delauney_min_tree.delauney_lines_list:
  512 +
  513 + dn1 = kv.get(delauney_line.rp1)
  514 + dn2 = kv.get(delauney_line.rp2)
  515 +
  516 +
  517 + if not dn1:
  518 + dn1 = DelauneyNode(delauney_line.rp1)
  519 + kv[delauney_line.rp1] = dn1
  520 +
  521 + if not dn2:
  522 +
  523 + trees.append(dn1)
  524 +
  525 + dn2 = DelauneyNode(delauney_line.rp2)
  526 + kv[delauney_line.rp2] = dn2
  527 +
  528 + if delauney_line.distance < threshold:
  529 + dn1.add_children(dn2,delauney_line)
  530 + count +=1
  531 +
  532 + else:
  533 + #断开
  534 + trees.append(dn2)
  535 + else:
  536 +
  537 + if delauney_line.distance < threshold:
  538 + dn2.add_children(dn1,delauney_line)
  539 + count += 1
  540 + else:
  541 + trees.append(dn1)
  542 + else:
  543 +
  544 + dn2 = DelauneyNode(delauney_line.rp2)
  545 + kv[delauney_line.rp2] = dn2
  546 +
  547 + if delauney_line.distance < threshold:
  548 + dn1.add_children(dn2,delauney_line)
  549 + count += 1
  550 + else:
  551 + trees.append(dn2)
  552 +
  553 +
  554 + return trees
  555 +
  556 + def create_polygon(self,p1,p2,p3,p4):
  557 +
  558 + ring = ogr.Geometry(ogr.wkbLinearRing)
  559 + ring.AddPoint(p1[0], p1[1])
  560 + ring.AddPoint(p2[0], p2[1])
  561 + ring.AddPoint(p3[0], p3[1])
  562 + ring.AddPoint(p4[0], p4[1])
  563 + ring.AddPoint(p1[0], p1[1])
  564 +
  565 + poly = ogr.Geometry(ogr.wkbPolygon)
  566 + poly.AddGeometry(ring)
  567 + return poly
  568 +
  569 + def get_polygon_lines(self,polygon):
  570 + #无孔Polygon
  571 + if polygon.GetGeometryCount() in [0,1]:
  572 + polygon_line : Geometry = ogr.ForceToLineString(polygon)
  573 + # 有孔Polygon
  574 + else:
  575 + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  576 +
  577 + return polygon_line
  578 +
  579 + def get_subpoint(self, x0, y0, x1, y1, len_size):
  580 +
  581 + len_size = len_size
  582 + tanx = abs(y1 - y0) / abs(x1 - x0)
  583 + cosx = 1 / math.sqrt(1 + tanx * tanx)
  584 + dx = cosx * len_size
  585 + dy = tanx * dx
  586 +
  587 + if x1 == x0:
  588 + x2 = x0
  589 + if y1 > y0:
  590 + y2 = y0 + abs(dy)
  591 + else:
  592 + y2 = y0 - abs(dy)
  593 + else:
  594 + if x1 < x0:
  595 + x2 = x0 - dx
  596 + else:
  597 + x2 = x0 + dx
  598 +
  599 + if y1 < y0:
  600 + y2 = y0 - dy
  601 + else:
  602 + y2 = y0 + dy
  603 +
  604 + return x2, y2
  605 +
  606 + def merge_concave_parallel(self, trees, distance_threshold):
  607 + merge_polygons = []
  608 +
  609 + tree_set = set(trees)
  610 + thread_set = set()
  611 +
  612 + while len(tree_set) > 0 :
  613 + while len(thread_set) < 16 and len(tree_set) > 0:
  614 +
  615 + print(len(tree_set))
  616 + tree = tree_set.pop()
  617 + polygons = list(tree.get_polygons())
  618 + merge_threading = MyThread(self.merge,args=(polygons,distance_threshold))
  619 + merge_threading.start()
  620 + thread_set.add(merge_threading)
  621 +
  622 +
  623 + remove_list = []
  624 + for thread in thread_set:
  625 +
  626 +
  627 + if not thread.is_alive():
  628 + merge_polygons.append(thread.get_result())
  629 + remove_list.append(thread)
  630 + for re in remove_list:
  631 + thread_set.remove(re)
  632 + del re
  633 +
  634 + for thread in thread_set:
  635 + thread.join()
  636 + merge_polygons.append(thread.get_result())
  637 +
  638 + return merge_polygons
  639 +
  640 + def merge(self,polygons,distance_threshold):
  641 + merge_raw: Geometry = polygons[0]
  642 + for p in polygons:
  643 + merge_raw = merge_raw.Union(p)
  644 +
  645 + points = []
  646 +
  647 + for i in range(merge_raw.GetGeometryCount()):
  648 +
  649 + poly = merge_raw.GetGeometryRef(i)
  650 + poly_line: Geometry = self.get_polygon_lines(poly)
  651 + if poly_line:
  652 + for indx in range(poly_line.GetPointCount() - 1):
  653 + poi = poly_line.GetPoint(indx)
  654 +
  655 + points.append(poi)
  656 +
  657 + poi_next = poly_line.GetPoint(indx + 1)
  658 +
  659 + dis = math.sqrt(math.pow(poi[0] - poi_next[0], 2) + math.pow(poi[1] - poi_next[1], 2))
  660 + # print(dis)
  661 + if dis > distance_threshold:
  662 + times = int(dis / distance_threshold)
  663 + # print(times)
  664 + for time in range(1, times + 1):
  665 + x, y = self.get_subpoint(poi[0], poi[1], poi_next[0], poi_next[1],
  666 + (time * distance_threshold))
  667 + points.append([x, y])
  668 +
  669 + points = np.array([[p[0], p[1]] for p in points])
  670 +
  671 + cp = []
  672 + for pp in points:
  673 + poi = ogr.Geometry(ogr.wkbPoint)
  674 + poi.AddPoint(pp[0], pp[1])
  675 + cp.append(poi)
  676 +
  677 + merge_p_line = concaveHull(points, 3)
  678 +
  679 + ring = ogr.Geometry(ogr.wkbLinearRing)
  680 +
  681 + merge_p = ogr.Geometry(ogr.wkbPolygon)
  682 +
  683 + for l in merge_p_line:
  684 + ring.AddPoint(l[0], l[1])
  685 +
  686 + ring.AddPoint(merge_p_line[0][0], merge_p_line[0][1])
  687 +
  688 + merge_p.AddGeometry(ring)
  689 + merge_p = merge_p.Simplify(self.distance_buffer_threshold / 10)
  690 +
  691 + return merge_p
  692 +
  693 + def process(self):
  694 + polygons = self.data.get_polygons()
  695 + rps = []
  696 +
  697 + for poly in polygons:
  698 + rp = self.get_polygon_reprecent_point(poly)
  699 + rps.append(rp)
  700 + print("完成代表点计算")
  701 +
  702 + #代表点要融合
  703 + delauney_lines,rps_sub = self.create_delauney(rps)
  704 +
  705 + print("完成树生成计算")
  706 + min_delauney = self.create_min_delauney(delauney_lines,rps_sub)
  707 + print("完成最小生成树计算")
  708 + trees = self.cut_delauney_min_tree(min_delauney,self.distance_buffer_threshold)
  709 + print("完成树裁剪")
  710 +
  711 + polygons = self.merge_concave_parallel(trees,self.distance_buffer_threshold)
  712 +
  713 + return [p.ExportToWkt() for p in polygons]
  714 +
  715 +if __name__ == '__main__':
  716 +
  717 +
  718 + # print(sd.get_polygons()[0])
  719 + # sd.close()
  720 +
  721 + t1 = time.time()
  722 + sd = ShapeData(r"J:\Data\制图综合result\zhongshansub.shp")
  723 +
  724 + zh = Zonghe(sd)
  725 + wkts = zh.process()
  726 + result = r"J:\Data\制图综合result\zhongshansub_pm.shp"
  727 + ShapeData.create_shp_fromwkts(result,"zh",wkts)
  728 +
  729 + print(time.time()-t1)
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/8
  4 +#email: nheweijun@sina.com
  5 +
  6 +import math
  7 +
  8 +from osgeo import ogr
  9 +from osgeo.ogr import *
  10 +
  11 +from test.zonghe.ShapeData import ShapeData
  12 +
  13 +
  14 +class Zonghe:
  15 +
  16 + data:ShapeData
  17 + area_threshold = 100.0
  18 + buffer_threshold = 100.0
  19 + distance_buffer_threshold = 2.114691025217302e-04
  20 +
  21 + def __init__(self,data):
  22 + self.data = data
  23 +
  24 +
  25 + def creat_point(self,tuple):
  26 + p: Geometry = ogr.Geometry(ogr.wkbPoint)
  27 + p.AddPoint(tuple[0], tuple[1])
  28 + return p
  29 +
  30 +
  31 +
  32 + def merge2(self,p1,p2):
  33 +
  34 + polygons = []
  35 + points = []
  36 +
  37 + for p in [p1,p2]:
  38 +
  39 + if p.GetGeometryCount() == 1:
  40 + polygon_line: Geometry = ogr.ForceToLineString(p)
  41 + # 有孔Polygon
  42 + else:
  43 + polygon_line: Geometry = ogr.ForceToLineString(p.GetGeometryRef(0))
  44 +
  45 + points.extend(polygon_line.GetPoints()[:-1])
  46 +
  47 + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
  48 +
  49 +
  50 + for p in points:
  51 + poi = ogr.Geometry(ogr.wkbPoint)
  52 + poi.AddPoint(p[0],p[1])
  53 + multipoint.AddGeometry(poi)
  54 +
  55 + delauney: Geometry = multipoint.DelaunayTriangulation()
  56 + merge_polygon = None
  57 +
  58 + for p in delauney:
  59 +
  60 + p_c = p.Centroid()
  61 +
  62 + # print("\"" + p_c.ExportToWkt() + "\",")
  63 + if p1.Contains(p) or p2.Contains(p):
  64 + continue
  65 + print("\"" + p.ExportToWkt() + "\",")
  66 +
  67 +
  68 + return polygons
  69 +
  70 +
  71 +
  72 + #这个是融合面
  73 + def merge(self,p1,p2):
  74 +
  75 + if p1.GetGeometryCount() == 1:
  76 + polygon_line1: Geometry = ogr.ForceToLineString(p1)
  77 + # 有孔Polygon
  78 + else:
  79 + polygon_line1: Geometry = ogr.ForceToLineString(p1.GetGeometryRef(0))
  80 +
  81 +
  82 + p1_points = polygon_line1.GetPoints()[:-1]
  83 +
  84 + if p2.GetGeometryCount() == 1:
  85 + polygon_line2: Geometry = ogr.ForceToLineString(p2)
  86 + # 有孔Polygon
  87 + else:
  88 + polygon_line2: Geometry = ogr.ForceToLineString(p2.GetGeometryRef(0))
  89 +
  90 + p2_points = polygon_line2.GetPoints()[:-1]
  91 + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
  92 +
  93 + p1_int = []
  94 + for indx,p in enumerate(p1_points):
  95 +
  96 + p_t = False
  97 + for pp in p2_points:
  98 + line = ogr.Geometry(ogr.wkbLineString)
  99 + line.AddPoint(p[0], p[1])
  100 + line.AddPoint(pp[0], pp[1])
  101 +
  102 + ggg:Geometry = line.Intersection(p1)
  103 +
  104 + if ggg.GetGeometryType() in [1,-2147483647,3001]:
  105 + p_t = True
  106 + break
  107 + if p_t:
  108 + pppp = ogr.Geometry(ogr.wkbPoint)
  109 + pppp.AddPoint(p[0],p[1])
  110 + p1_int.append(p)
  111 + multipoint.AddGeometry(pppp)
  112 +
  113 +
  114 + for indx,p in enumerate(p2_points):
  115 +
  116 + p_t = False
  117 + for pp in p1_int:
  118 + line = ogr.Geometry(ogr.wkbLineString)
  119 + line.AddPoint(p[0], p[1])
  120 + line.AddPoint(pp[0], pp[1])
  121 +
  122 + ggg:Geometry = line.Intersection(p2)
  123 +
  124 +
  125 + if ggg.GetGeometryType() in [1,-2147483647,3001]:
  126 + p_t = True
  127 + break
  128 + if p_t:
  129 +
  130 + pppp = ogr.Geometry(ogr.wkbPoint)
  131 + pppp.AddPoint(p[0],p[1])
  132 +
  133 +
  134 + multipoint.AddGeometry(pppp)
  135 +
  136 +
  137 +
  138 + delauney: Geometry = multipoint.DelaunayTriangulation()
  139 +
  140 + for indx in range(delauney.GetGeometryCount()):
  141 + tri:Geometry = delauney.GetGeometryRef(indx)
  142 + dif1:Geometry = tri.Difference(p1)
  143 + dif2:Geometry = tri.Difference(p2)
  144 +
  145 + # return [multipoint.ExportToWkt()]
  146 +
  147 + return [p.ExportToWkt() for p in delauney]
  148 +
  149 +
  150 +
  151 + #这个是融合面
  152 + def mergebac(self,p1,p2):
  153 +
  154 + if p1.GetGeometryCount() == 1:
  155 + polygon_line1: Geometry = ogr.ForceToLineString(p1)
  156 + # 有孔Polygon
  157 + else:
  158 + polygon_line1: Geometry = ogr.ForceToLineString(p1.GetGeometryRef(0))
  159 +
  160 +
  161 + p1_points = polygon_line1.GetPoints()[:-1]
  162 +
  163 + if p2.GetGeometryCount() == 1:
  164 + polygon_line2: Geometry = ogr.ForceToLineString(p2)
  165 + # 有孔Polygon
  166 + else:
  167 + polygon_line2: Geometry = ogr.ForceToLineString(p2.GetGeometryRef(0))
  168 +
  169 + p2_points = polygon_line2.GetPoints()[:-1]
  170 + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
  171 +
  172 +
  173 + p1_point_start = None
  174 + p1_point_end = None
  175 +
  176 + for indx,p in enumerate(p1_points):
  177 +
  178 + p_t = False
  179 + for pp in p2_points:
  180 + line = ogr.Geometry(ogr.wkbLineString)
  181 + line.AddPoint(p[0], p[1])
  182 + line.AddPoint(pp[0], pp[1])
  183 +
  184 + ggg:Geometry = line.Intersection(p1)
  185 +
  186 + if ggg.GetGeometryType() in [1,-2147483647,3001]:
  187 + p_t = True
  188 + break
  189 + if p_t:
  190 + pppp = ogr.Geometry(ogr.wkbPoint)
  191 + pppp.AddPoint(p[0],p[1])
  192 +
  193 + if p1_point_start is None:
  194 + p1_point_start = indx
  195 +
  196 + multipoint.AddGeometry(pppp)
  197 + p1_point_end = indx
  198 +
  199 + p1_int = p1_points[p1_point_start:p1_point_end+1]
  200 +
  201 +
  202 + p2_point_start = None
  203 + p2_point_end = None
  204 +
  205 +
  206 + for indx,p in enumerate(p2_points):
  207 +
  208 + p_t = False
  209 + for pp in p1_int:
  210 + line = ogr.Geometry(ogr.wkbLineString)
  211 + line.AddPoint(p[0], p[1])
  212 + line.AddPoint(pp[0], pp[1])
  213 +
  214 + ggg:Geometry = line.Intersection(p2)
  215 +
  216 +
  217 + if ggg.GetGeometryType() in [1,-2147483647,3001]:
  218 + p_t = True
  219 + break
  220 + if p_t:
  221 +
  222 + pppp = ogr.Geometry(ogr.wkbPoint)
  223 + pppp.AddPoint(p[0],p[1])
  224 +
  225 + if p2_point_start is None:
  226 + p2_point_start = indx
  227 +
  228 + multipoint.AddGeometry(pppp)
  229 +
  230 + p2_point_end = indx
  231 +
  232 + delauney: Geometry = multipoint.DelaunayTriangulation()
  233 +
  234 + p2_int = p2_points[p2_point_start:p2_point_end + 1]
  235 + if p2_point_end == len(p2_points)-1:
  236 + p2_int = p2_points[p2_point_start:p2_point_end + 1]
  237 +
  238 + p1_int.extend(p2_int)
  239 +
  240 + print(p2_point_start,p2_point_end)
  241 +
  242 + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint)
  243 +
  244 + for p in p1_int:
  245 + pppp = ogr.Geometry(ogr.wkbPoint)
  246 + pppp.AddPoint(p[0], p[1])
  247 + multipoint.AddGeometry(pppp)
  248 +
  249 + return [multipoint.ExportToWkt()]
  250 +
  251 + # return [p.ExportToWkt() for p in delauney]
  252 +
  253 +
  254 + def merge4(self,polygons):
  255 +
  256 +
  257 + mp: Geometry = ogr.Geometry(ogr.wkbMultiPolygon)
  258 + for p in polygons:
  259 + mp.AddGeometry(p)
  260 +
  261 +
  262 +
  263 + delauney: Geometry = mp.DelaunayTriangulation()
  264 +
  265 + intp = []
  266 + for p in delauney:
  267 +
  268 + res = p
  269 + ispass = False
  270 + for pp in polygons:
  271 + check:Geometry = res.Difference(pp)
  272 + if check.IsEmpty():
  273 + ispass = True
  274 + break
  275 + else:
  276 + res = check
  277 + if not ispass:
  278 + res_buffer = self.extend_tri(res)
  279 +
  280 + intp.append(res_buffer)
  281 +
  282 +
  283 + polygons.extend(intp)
  284 +
  285 + mp: Geometry = ogr.Geometry(ogr.wkbMultiPolygon)
  286 +
  287 + for p in polygons:
  288 + mp.AddGeometry(p)
  289 +
  290 +
  291 +
  292 + merge:Geometry = mp.UnionCascaded()
  293 +
  294 + return [merge.ExportToWkt()]
  295 +
  296 + # return [p.ExportToWkt() for p in intp]
  297 +
  298 +
  299 + def extend_tri(self,triangle:Geometry):
  300 +
  301 + center:Geometry = triangle.Centroid()
  302 + tri_line: Geometry = ogr.ForceToLineString(triangle)
  303 +
  304 + result_geo = ogr.Geometry(ogr.wkbPolygon)
  305 + result_geo_ring:Geometry = ogr.Geometry(ogr.wkbLinearRing)
  306 + for point in tri_line.GetPoints():
  307 + radpoint = self.get_radpoint(center.GetX(),center.GetY(),point[0],point[1],0.00000001)
  308 +
  309 + result_geo_ring.AddPoint(radpoint.GetX(),radpoint.GetY())
  310 + result_geo.AddGeometry(result_geo_ring)
  311 +
  312 + return result_geo
  313 +
  314 + def get_radpoint(self,x0,y0,x1,y1,len_size):
  315 + a2 = math.pow((x1-x0),2)
  316 + b2 = math.pow((y1-y0),2)
  317 + len_size = len_size+ math.sqrt(a2+b2)
  318 +
  319 + tanx = abs(y1-y0) / abs(x1-x0)
  320 + cosx = 1 / math.sqrt(1 + tanx *tanx)
  321 + dx = cosx* len_size
  322 + dy = tanx * dx
  323 +
  324 + if x1 == x0:
  325 + x2 = x0
  326 + if y1 > y0 :
  327 + y2 = y0 + abs(dy)
  328 + else:
  329 + y2 = y0 - abs(dy)
  330 + else:
  331 + if x1 < x0:
  332 + x2 = x0 - dx
  333 + else:
  334 + x2 = x0 + dx
  335 +
  336 + if y1 < y0:
  337 + y2 = y0 - dy
  338 + else:
  339 + y2 = y0 + dy
  340 +
  341 + other_point = ogr.Geometry(ogr.wkbPoint)
  342 + other_point.AddPoint(x2, y2)
  343 +
  344 + return other_point
  345 +
  346 +
  347 +
  348 + def merge5(self,p1:Geometry,p2):
  349 +
  350 +
  351 +
  352 + ext = p1.GetEnvelope()
  353 +
  354 + tor = min(ext[1]-ext[0],ext[3]-ext[2])
  355 +
  356 + pp = p1.Simplify(tor/20)
  357 +
  358 + pp2 = p2.Simplify(tor / 20)
  359 +
  360 + return [pp.ExportToWkt(),pp2.ExportToWkt() ]
  361 +
  362 + def process(self):
  363 + polygons = self.data.get_polygons()
  364 +
  365 + # return self.merge(polygons[0],polygons[1])
  366 +
  367 + return self.merge4(polygons)
  368 +
  369 +
  370 +if __name__ == '__main__':
  371 +
  372 +
  373 + # print(sd.get_polygons()[0])
  374 + # sd.close()
  375 +
  376 + # create = True
  377 + # create = False
  378 + #
  379 + # if create:
  380 + #
  381 + # sd = ShapeData(r"J:\Data\制图综合\me.shp")
  382 + #
  383 + # ext = sd.layer.GetExtent()
  384 + # threshold = (ext[1]-ext[0])/20
  385 + # print(threshold)
  386 + #
  387 + #
  388 + # zh = Zonghe(sd)
  389 + # zh.process()
  390 + # else:
  391 + # wkts = ["POLYGON ((113.371086251 22.5101043861001,113.371311338 22.5099257505,113.371611445 22.5098560668001,113.371450698 22.5095291511,113.370775465 22.5096884259,113.371086251 22.5101043861001))"
  392 + # ]
  393 + # result = r"J:\Data\制图综合\mes.shp"
  394 + # ShapeData.create_shp_fromwkts(result,"zh",wkts)
  395 + #
  396 +
  397 +
  398 + sd = ShapeData(r"J:\Data\制图综合result\ex1.shp")
  399 +
  400 + ext = sd.layer.GetExtent()
  401 + threshold = (ext[1]-ext[0])/20
  402 +
  403 + zh = Zonghe(sd)
  404 + wkts = zh.process()
  405 +
  406 + result = r"J:\Data\制图综合result\ex1_1.shp"
  407 + ShapeData.create_shp_fromwkts(result,"zh",wkts)
  408 +
... ...
... ... @@ -150,26 +150,53 @@ class Zonghe:
150 150
151 151 return None
152 152
153   - def merge3(self,polygons):
  153 + def merge3(self,polygons,distance_threshold):
  154 +
  155 + merge_raw :Geometry = polygons[0]
  156 + for p in polygons:
  157 + merge_raw = merge_raw.Union(p)
154 158
155   - multi_poly = ogr.Geometry(ogr.wkbMultiPolygon)
156 159
157 160 points = []
158   - for poly in polygons:
159   - multi_poly.AddGeometry(poly)
  161 +
  162 + for i in range(merge_raw.GetGeometryCount()):
  163 +
  164 + poly = merge_raw.GetGeometryRef(i)
160 165 if poly.GetGeometryCount() == 1:
161 166 poly_line: Geometry = ogr.ForceToLineString(poly)
162 167 # 有孔Polygon
163 168 else:
164 169 poly_line: Geometry = ogr.ForceToLineString(poly.GetGeometryRef(0))
165 170
166   - points.extend(poly_line.GetPoints()[:-1])
167 171
  172 + for indx in range(poly_line.GetPointCount() -1) :
  173 + poi = poly_line.GetPoint(indx)
  174 +
  175 + points.append(poi)
  176 +
  177 + poi_next = poly_line.GetPoint(indx+1)
  178 +
  179 + dis = math.sqrt(math.pow(poi[0] - poi_next[0],2) + math.pow(poi[1] - poi_next[1],2))
  180 + # print(dis)
  181 + if dis > distance_threshold:
  182 + times = int(dis/distance_threshold)
  183 + # print(times)
  184 + for time in range(1,times+1):
  185 + x,y = self.get_radline(poi[0],poi[1],poi_next[0],poi_next[1],(time*distance_threshold))
  186 + points.append([x,y])
168 187
169 188 points = np.array([[p[0],p[1]] for p in points])
170 189
  190 +
  191 + for pp in points:
  192 + poi = ogr.Geometry(ogr.wkbPoint)
  193 + poi.AddPoint(pp[0],pp[1])
  194 + print("\"" + poi.ExportToWkt() + "\",")
  195 +
  196 +
171 197 merge_p_line = concaveHull(points, 3)
172 198
  199 +
173 200 ring = ogr.Geometry(ogr.wkbLinearRing)
174 201
175 202 merge_p = ogr.Geometry(ogr.wkbPolygon)
... ... @@ -194,32 +221,46 @@ class Zonghe:
194 221 return [merge_p.ExportToWkt()]
195 222
196 223
  224 + def get_radline(self,x0,y0,x1,y1,len_size):
197 225
  226 + len_size = len_size
  227 + tanx = abs(y1-y0) / abs(x1-x0)
  228 + cosx = 1 / math.sqrt(1 + tanx *tanx)
  229 + dx = cosx* len_size
  230 + dy = tanx * dx
  231 +
  232 + if x1 == x0:
  233 + x2 = x0
  234 + if y1 > y0 :
  235 + y2 = y0 + abs(dy)
  236 + else:
  237 + y2 = y0 - abs(dy)
  238 + else:
  239 + if x1 < x0:
  240 + x2 = x0 - dx
  241 + else:
  242 + x2 = x0 + dx
198 243
199   - def merge4(self,p1,p2):
  244 + if y1 < y0:
  245 + y2 = y0 - dy
  246 + else:
  247 + y2 = y0 + dy
200 248
201   - polygons = []
202   - points = []
  249 + return x2,y2
203 250
204   - mp: Geometry = ogr.Geometry(ogr.wkbMultiPolygon)
205   - mp.AddGeometry(p1)
206   - mp.AddGeometry(p2)
  251 + def merge4(self,polygons):
207 252
208 253
209   - delauney: Geometry = mp.DelaunayTriangulation(bOnlyEdges=True)
210   - merge_polygon = None
  254 + mp: Geometry = ogr.Geometry(ogr.wkbMultiPolygon)
  255 + for p in polygons:
  256 + mp.AddGeometry(p)
211 257
212   - for p in delauney:
213 258
214   - p_c = p.Centroid()
215 259
216   - # print("\"" + p_c.ExportToWkt() + "\",")
217   - # if p1.Contains(p) or p2.Contains(p):
218   - # continue
219   - print("\"" + p.ExportToWkt() + "\",")
  260 + delauney: Geometry = mp.DelaunayTriangulation()
220 261
221 262
222   - return polygons
  263 + return [p.ExportToWkt() for p in delauney]
223 264
224 265 def merge5(self,p1:Geometry,p2):
225 266
... ... @@ -239,7 +280,9 @@ class Zonghe:
239 280 def process(self):
240 281 polygons = self.data.get_polygons()
241 282
242   - return self.merge3(polygons)
  283 + # return self.merge3(polygons,0.00007)
  284 +
  285 + return self.merge4(polygons)
243 286
244 287
245 288 if __name__ == '__main__':
... ... @@ -270,7 +313,7 @@ if __name__ == '__main__':
270 313 #
271 314
272 315
273   - sd = ShapeData(r"J:\Data\制图综合\concave.shp")
  316 + sd = ShapeData(r"J:\Data\制图综合\concave5.shp")
274 317
275 318 ext = sd.layer.GetExtent()
276 319 threshold = (ext[1]-ext[0])/20
... ... @@ -280,7 +323,6 @@ if __name__ == '__main__':
280 323 zh = Zonghe(sd)
281 324 wkts = zh.process()
282 325
283   -
284   - result = r"J:\Data\制图综合\concave_merge.shp"
  326 + result = r"J:\Data\制图综合\concave5_merge.shp"
285 327 ShapeData.create_shp_fromwkts(result,"zh",wkts)
286 328
... ...
注册登录 后发表评论