正在显示
2 个修改的文件
包含
910 行增加
和
5 行删除
| @@ -6,8 +6,10 @@ from app.util.component.ParameterUtil import ParameterUtil | @@ -6,8 +6,10 @@ from app.util.component.ParameterUtil import ParameterUtil | ||
| 6 | from flask import current_app,request | 6 | from flask import current_app,request |
| 7 | import traceback | 7 | import traceback |
| 8 | import json | 8 | import json |
| 9 | -from app.modules.auth.models import OAuth2Token,User,db | 9 | +from app.models import db |
| 10 | +from app.modules.auth.models import OAuth2Token,User | ||
| 10 | import app | 11 | import app |
| 12 | + | ||
| 11 | class ApiTemplate: | 13 | class ApiTemplate: |
| 12 | #模板方法 | 14 | #模板方法 |
| 13 | para = dict() | 15 | para = dict() |
| @@ -28,10 +30,11 @@ class ApiTemplate: | @@ -28,10 +30,11 @@ class ApiTemplate: | ||
| 28 | if app.GLOBAL_DIC.get(token): | 30 | if app.GLOBAL_DIC.get(token): |
| 29 | self.para["creator"] = app.GLOBAL_DIC.get(token) | 31 | self.para["creator"] = app.GLOBAL_DIC.get(token) |
| 30 | else: | 32 | else: |
| 31 | - user = User.query.join(OAuth2Token).filter(OAuth2Token.access_token == token).one_or_none() | ||
| 32 | - if user: | ||
| 33 | - self.para["creator"] = user.username | ||
| 34 | - app.GLOBAL_DIC[token] = user.username | 33 | + sql = "select username from dmap_user join dmap_oauth2_token on dmap_user.id=dmap_oauth2_token.user_id where dmap_oauth2_token.access_token='{}'".format(token) |
| 34 | + result = db.session.execute(sql).fetchone() | ||
| 35 | + if result: | ||
| 36 | + self.para["creator"] = result[0] | ||
| 37 | + app.GLOBAL_DIC[token] = result[0] | ||
| 35 | 38 | ||
| 36 | def para_check(self): | 39 | def para_check(self): |
| 37 | pass | 40 | pass |
test/zonghe/Zonghebac.py
0 → 100644
| 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 numpy as np | ||
| 20 | + | ||
| 21 | +class Zonghe: | ||
| 22 | + | ||
| 23 | + data:ShapeData | ||
| 24 | + area_threshold = 100.0 | ||
| 25 | + buffer_threshold = 100.0 | ||
| 26 | + distance_buffer_threshold = 1.114691025217302e-04 | ||
| 27 | + | ||
| 28 | + def __init__(self,data): | ||
| 29 | + self.data = data | ||
| 30 | + | ||
| 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 | + | ||
| 42 | + short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2]) | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + center:Geometry = polygon.Centroid() | ||
| 47 | + # print(center) | ||
| 48 | + | ||
| 49 | + | ||
| 50 | + # 提前return | ||
| 51 | + if polygon.Contains(center): | ||
| 52 | + # print("\"" + center.ExportToWkt() + "\",") | ||
| 53 | + return RepresentPoint(center, polygon) | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + last_state = None | ||
| 57 | + line = None | ||
| 58 | + calculate_time = 0 | ||
| 59 | + | ||
| 60 | + direction = self.get_direction(polygon, center, line_length) | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + in_hole = False | ||
| 64 | + in_hole_line = None | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + #无孔Polygon | ||
| 68 | + if polygon.GetGeometryCount() == 1: | ||
| 69 | + polygon_line = ogr.ForceToLineString(polygon) | ||
| 70 | + | ||
| 71 | + # 有孔Polygon,要分2种情况 | ||
| 72 | + else: | ||
| 73 | + polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0)) | ||
| 74 | + for i in range(1,polygon.GetGeometryCount()): | ||
| 75 | + hole_line = polygon.GetGeometryRef(i) | ||
| 76 | + hole_polygon : Geometry = ogr.ForceToPolygon(hole_line) | ||
| 77 | + if hole_polygon.Contains(center): | ||
| 78 | + in_hole = True | ||
| 79 | + direction = range(0,190,10) | ||
| 80 | + in_hole_line = ogr.ForceToLineString(hole_line) | ||
| 81 | + # print("in_hole") | ||
| 82 | + | ||
| 83 | + angle1,angle2=None,None | ||
| 84 | + | ||
| 85 | + for angle in direction: | ||
| 86 | + | ||
| 87 | + if in_hole: | ||
| 88 | + line = self.get_doubleline(center.GetX(),center.GetY(),angle,line_length) | ||
| 89 | + else: | ||
| 90 | + line = self.get_line(center.GetX(),center.GetY(),angle,line_length) | ||
| 91 | + | ||
| 92 | + oneside_area, otherside_area = self.jude(polygon, line, angle, line_length) | ||
| 93 | + | ||
| 94 | + | ||
| 95 | + if last_state is None: | ||
| 96 | + | ||
| 97 | + angle2 = angle | ||
| 98 | + | ||
| 99 | + if oneside_area == 0 and otherside_area==0: | ||
| 100 | + last_state = 0 | ||
| 101 | + else: | ||
| 102 | + last_state = 1 if oneside_area < otherside_area else -1 | ||
| 103 | + else: | ||
| 104 | + | ||
| 105 | + angle1 = angle2 | ||
| 106 | + angle2 = angle | ||
| 107 | + | ||
| 108 | + if oneside_area == 0 and otherside_area==0: | ||
| 109 | + now_state = 0 | ||
| 110 | + else: | ||
| 111 | + now_state = 1 if oneside_area < otherside_area else -1 | ||
| 112 | + | ||
| 113 | + if last_state* now_state < 0: | ||
| 114 | + # print(angle) | ||
| 115 | + break | ||
| 116 | + else: | ||
| 117 | + last_state = now_state | ||
| 118 | + | ||
| 119 | + line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre) | ||
| 120 | + | ||
| 121 | + # 提前return | ||
| 122 | + if in_hole: | ||
| 123 | + | ||
| 124 | + point_intersection: Geometry = line.Intersection(in_hole_line) | ||
| 125 | + plist = [] | ||
| 126 | + for i in range(point_intersection.GetGeometryCount()): | ||
| 127 | + pi = point_intersection.GetGeometryRef(i) | ||
| 128 | + plist.append(pi) | ||
| 129 | + plist_d = [(pi,center.Distance(pi)) for pi in plist] | ||
| 130 | + plist_d.sort(key=lambda x:x[1]) | ||
| 131 | + | ||
| 132 | + nearest_point= plist_d[0][0] | ||
| 133 | + firt_short_length = short_length/20.0 | ||
| 134 | + radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length) | ||
| 135 | + # print("\"" + other_point.ExportToWkt() + "\",") | ||
| 136 | + | ||
| 137 | + | ||
| 138 | + while not polygon.Contains(other_point): | ||
| 139 | + | ||
| 140 | + firt_short_length = firt_short_length / 2 | ||
| 141 | + radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(), | ||
| 142 | + nearest_point.GetY(), firt_short_length) | ||
| 143 | + | ||
| 144 | + | ||
| 145 | + | ||
| 146 | + return RepresentPoint(other_point,polygon) | ||
| 147 | + | ||
| 148 | + | ||
| 149 | + point_intersection:Geometry = line.Intersection(polygon_line) | ||
| 150 | + xlist = [] | ||
| 151 | + ylist = [] | ||
| 152 | + plist = [] | ||
| 153 | + | ||
| 154 | + for i in range(point_intersection.GetGeometryCount()): | ||
| 155 | + pi = point_intersection.GetGeometryRef(i) | ||
| 156 | + xlist.append(pi.GetX()) | ||
| 157 | + ylist.append(pi.GetY()) | ||
| 158 | + plist.append(pi) | ||
| 159 | + | ||
| 160 | + reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0] | ||
| 161 | + | ||
| 162 | + reprecent_point = self.creat_point(reprecent_point) | ||
| 163 | + | ||
| 164 | + if not polygon.Contains(reprecent_point): | ||
| 165 | + plist_d = [(pi,center.Distance(pi)) for pi in plist] | ||
| 166 | + plist_d.sort(key=lambda x:x[1]) | ||
| 167 | + 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)) | ||
| 168 | + | ||
| 169 | + # print("\""+reprecent_point.ExportToWkt() + "\",") | ||
| 170 | + | ||
| 171 | + rp = RepresentPoint(reprecent_point,polygon) | ||
| 172 | + | ||
| 173 | + return rp | ||
| 174 | + | ||
| 175 | + | ||
| 176 | + | ||
| 177 | + | ||
| 178 | + | ||
| 179 | + def get_line(self, x0, y0 , angle, r): | ||
| 180 | + | ||
| 181 | + line: Geometry = ogr.Geometry(ogr.wkbLineString) | ||
| 182 | + line.AddPoint(x0, y0) | ||
| 183 | + hudu = angle/360.0 * 2 * math.pi | ||
| 184 | + dx = math.sin(hudu) * r | ||
| 185 | + dy = math.cos(hudu) * r | ||
| 186 | + line.AddPoint(x0+dx, y0+dy) | ||
| 187 | + | ||
| 188 | + return line | ||
| 189 | + | ||
| 190 | + def get_doubleline(self, x0, y0 , angle, r): | ||
| 191 | + | ||
| 192 | + line: Geometry = ogr.Geometry(ogr.wkbLineString) | ||
| 193 | + | ||
| 194 | + hudu = angle/360.0 * 2 * math.pi | ||
| 195 | + dx = math.sin(hudu) * r | ||
| 196 | + dy = math.cos(hudu) * r | ||
| 197 | + | ||
| 198 | + hudu = (angle+180)/360.0 * 2 * math.pi | ||
| 199 | + dx2 = math.sin(hudu) * r | ||
| 200 | + dy2 = math.cos(hudu) * r | ||
| 201 | + | ||
| 202 | + line.AddPoint(x0 + dx2, y0 + dy2) | ||
| 203 | + line.AddPoint(x0+dx, y0+dy) | ||
| 204 | + | ||
| 205 | + return line | ||
| 206 | + | ||
| 207 | + | ||
| 208 | + def get_radline(self,x0,y0,x1,y1,len_size): | ||
| 209 | + a2 = math.pow((x1-x0),2) | ||
| 210 | + b2 = math.pow((y1-y0),2) | ||
| 211 | + len_size = len_size+ math.sqrt(a2+b2) | ||
| 212 | + | ||
| 213 | + line: Geometry = ogr.Geometry(ogr.wkbLineString) | ||
| 214 | + line.AddPoint(x0, y0) | ||
| 215 | + tanx = abs(y1-y0) / abs(x1-x0) | ||
| 216 | + cosx = 1 / math.sqrt(1 + tanx *tanx) | ||
| 217 | + dx = cosx* len_size | ||
| 218 | + dy = tanx * dx | ||
| 219 | + | ||
| 220 | + if x1 == x0: | ||
| 221 | + x2 = x0 | ||
| 222 | + if y1 > y0 : | ||
| 223 | + y2 = y0 + abs(dy) | ||
| 224 | + else: | ||
| 225 | + y2 = y0 - abs(dy) | ||
| 226 | + else: | ||
| 227 | + if x1 < x0: | ||
| 228 | + x2 = x0 - dx | ||
| 229 | + else: | ||
| 230 | + x2 = x0 + dx | ||
| 231 | + | ||
| 232 | + if y1 < y0: | ||
| 233 | + y2 = y0 - dy | ||
| 234 | + else: | ||
| 235 | + y2 = y0 + dy | ||
| 236 | + | ||
| 237 | + line.AddPoint(x2, y2) | ||
| 238 | + | ||
| 239 | + other_point = ogr.Geometry(ogr.wkbPoint) | ||
| 240 | + other_point.AddPoint(x2, y2) | ||
| 241 | + | ||
| 242 | + return line , other_point | ||
| 243 | + | ||
| 244 | + def get_direction(self,polygon,center,line_length): | ||
| 245 | + ''' | ||
| 246 | + 判断旋转方向 | ||
| 247 | + :param polygon: | ||
| 248 | + :param center: | ||
| 249 | + :param line_length: | ||
| 250 | + :return: | ||
| 251 | + ''' | ||
| 252 | + | ||
| 253 | + line = self.get_line(center.GetX(),center.GetY(),0,line_length) | ||
| 254 | + | ||
| 255 | + oneside_area, otherside_area = self.jude(polygon,line,0,line_length) | ||
| 256 | + | ||
| 257 | + if oneside_area == 0 and otherside_area == 0 : | ||
| 258 | + return range(0, 390, 30) | ||
| 259 | + else: | ||
| 260 | + line = self.get_line(center.GetX(), center.GetY(), 10, line_length) | ||
| 261 | + oneside_area_contrast, otherside_area_contrast = self.jude(polygon, line, 30, line_length) | ||
| 262 | + | ||
| 263 | + if oneside_area_contrast == 0 and otherside_area_contrast == 0: | ||
| 264 | + return range(360, -30, -30) | ||
| 265 | + else: | ||
| 266 | + if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast): | ||
| 267 | + return range(0, 390, 30) | ||
| 268 | + else: | ||
| 269 | + return range(360, -30, -30) | ||
| 270 | + | ||
| 271 | + | ||
| 272 | + def jude(self,polygon,line,angle,line_length): | ||
| 273 | + | ||
| 274 | + line_buffer: Geometry = line.Buffer(line_length / self.buffer_threshold) | ||
| 275 | + clip_geom: Geometry = polygon.Difference(line_buffer) | ||
| 276 | + | ||
| 277 | + oneside_area = 0 | ||
| 278 | + otherside_area = 0 | ||
| 279 | + | ||
| 280 | + gc = clip_geom.GetGeometryCount() | ||
| 281 | + if gc <= 1: | ||
| 282 | + oneside_area = 0 | ||
| 283 | + otherside_area = 0 | ||
| 284 | + else: | ||
| 285 | + triangle1, triangle2 = self.get_side_triangle(line, angle) | ||
| 286 | + | ||
| 287 | + | ||
| 288 | + for gi in range(clip_geom.GetGeometryCount()): | ||
| 289 | + clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi) | ||
| 290 | + it = clip_geom_i.Intersection(triangle1) | ||
| 291 | + | ||
| 292 | + if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect( | ||
| 293 | + line_buffer): | ||
| 294 | + oneside_area += clip_geom_i.GetArea() | ||
| 295 | + else: | ||
| 296 | + otherside_area += clip_geom_i.GetArea() | ||
| 297 | + return oneside_area, otherside_area | ||
| 298 | + | ||
| 299 | + def division(self,polygon,center,in_hole,line_length,angle1,angle2,area_thre): | ||
| 300 | + | ||
| 301 | + mid_angle = (angle1 + angle2)/2.0 | ||
| 302 | + if in_hole: | ||
| 303 | + line = self.get_doubleline(center.GetX(), center.GetY(), mid_angle, line_length) | ||
| 304 | + else: | ||
| 305 | + line = self.get_line(center.GetX(), center.GetY(), mid_angle, line_length) | ||
| 306 | + | ||
| 307 | + one,other = self.jude(polygon,line,mid_angle,line_length) | ||
| 308 | + | ||
| 309 | + while abs(one - other) > area_thre: | ||
| 310 | + if one > other: | ||
| 311 | + if angle1 > angle2: | ||
| 312 | + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre) | ||
| 313 | + else: | ||
| 314 | + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre) | ||
| 315 | + else: | ||
| 316 | + if angle1 > angle2: | ||
| 317 | + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre) | ||
| 318 | + else: | ||
| 319 | + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre) | ||
| 320 | + return line | ||
| 321 | + | ||
| 322 | + | ||
| 323 | + def get_side_triangle(self,line:Geometry,angle): | ||
| 324 | + ''' | ||
| 325 | + 获取方向三角形 | ||
| 326 | + :param line: | ||
| 327 | + :param angle: | ||
| 328 | + :return: | ||
| 329 | + ''' | ||
| 330 | + | ||
| 331 | + start = line.GetPoint(0) | ||
| 332 | + end = line.GetPoint(1) | ||
| 333 | + | ||
| 334 | + | ||
| 335 | + angle_t = angle-30 | ||
| 336 | + hudu = angle_t/360.0 * 2 * math.pi | ||
| 337 | + | ||
| 338 | + r = line.Length() / (2*math.cos( math.pi/6)) | ||
| 339 | + dx = math.sin(hudu) * r | ||
| 340 | + dy = math.cos(hudu) * r | ||
| 341 | + | ||
| 342 | + | ||
| 343 | + ring1 = ogr.Geometry(ogr.wkbLinearRing) | ||
| 344 | + ring1.AddPoint(start[0], start[1]) | ||
| 345 | + ring1.AddPoint(start[0] + dx, start[1] + dy) | ||
| 346 | + ring1.AddPoint(end[0], end[1]) | ||
| 347 | + ring1.AddPoint(start[0], start[1]) | ||
| 348 | + triangle1 = ogr.Geometry(ogr.wkbPolygon) | ||
| 349 | + triangle1.AddGeometry(ring1) | ||
| 350 | + | ||
| 351 | + | ||
| 352 | + angle_t = angle+30 | ||
| 353 | + hudu = angle_t/360.0 * 2 * math.pi | ||
| 354 | + | ||
| 355 | + r = line.Length() / (2*math.cos( math.pi/6)) | ||
| 356 | + | ||
| 357 | + dx = math.sin(hudu) * r | ||
| 358 | + dy = math.cos(hudu) * r | ||
| 359 | + | ||
| 360 | + ring2 = ogr.Geometry(ogr.wkbLinearRing) | ||
| 361 | + ring2.AddPoint(start[0], start[1]) | ||
| 362 | + ring2.AddPoint(start[0]+dx, start[1]+dy) | ||
| 363 | + ring2.AddPoint(end[0], end[1]) | ||
| 364 | + ring2.AddPoint(start[0], start[1]) | ||
| 365 | + triangle2 = ogr.Geometry(ogr.wkbPolygon) | ||
| 366 | + triangle2.AddGeometry(ring2) | ||
| 367 | + | ||
| 368 | + return triangle1,triangle2 | ||
| 369 | + | ||
| 370 | + | ||
| 371 | + def creat_point(self,tuple): | ||
| 372 | + p: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 373 | + p.AddPoint(tuple[0], tuple[1]) | ||
| 374 | + return p | ||
| 375 | + | ||
| 376 | + | ||
| 377 | + | ||
| 378 | + | ||
| 379 | + def create_delauney(self,rps): | ||
| 380 | + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint) | ||
| 381 | + | ||
| 382 | + rp_dict = {} | ||
| 383 | + line_set = set() | ||
| 384 | + delauney_lines = [] | ||
| 385 | + | ||
| 386 | + for rp in rps: | ||
| 387 | + multipoint.AddGeometry(rp.point) | ||
| 388 | + | ||
| 389 | + rp_dict[rp.point.GetPoint(0).__str__()] = rp | ||
| 390 | + | ||
| 391 | + delauney:Geometry = multipoint.DelaunayTriangulation() | ||
| 392 | + | ||
| 393 | + for index in range(delauney.GetGeometryCount()): | ||
| 394 | + triangle = delauney.GetGeometryRef(index) | ||
| 395 | + | ||
| 396 | + triangle_line:Geometry = ogr.ForceToLineString(triangle) | ||
| 397 | + | ||
| 398 | + | ||
| 399 | + for pi in range(triangle_line.GetPointCount()-1): | ||
| 400 | + p = triangle_line.GetPoint(pi) | ||
| 401 | + p_next = triangle_line.GetPoint(pi+1) | ||
| 402 | + | ||
| 403 | + if p[0] < p_next[0]: | ||
| 404 | + key = "{}{}".format(p.__str__(),p_next.__str__()) | ||
| 405 | + elif p[0] > p_next[0]: | ||
| 406 | + key = "{}{}".format(p_next.__str__(), p.__str__()) | ||
| 407 | + else: | ||
| 408 | + if p[1] < p_next[1]: | ||
| 409 | + key = "{}{}".format(p.__str__(), p_next.__str__()) | ||
| 410 | + else: | ||
| 411 | + key = "{}{}".format(p_next.__str__(), p.__str__()) | ||
| 412 | + | ||
| 413 | + if not line_set.__contains__(key): | ||
| 414 | + line_set.add(key) | ||
| 415 | + rp1 = rp_dict.get(p.__str__()) | ||
| 416 | + rp2 = rp_dict.get(p_next.__str__()) | ||
| 417 | + | ||
| 418 | + delauney_line = DelauneyLine(rp1,rp2) | ||
| 419 | + delauney_lines.append(delauney_line) | ||
| 420 | + | ||
| 421 | + return delauney_lines | ||
| 422 | + | ||
| 423 | + | ||
| 424 | + | ||
| 425 | + def create_min_delauney(self,delauney_lines,rps,polygons): | ||
| 426 | + ''' | ||
| 427 | + 使用prim算法计算最小生成树 | ||
| 428 | + :param delauney_lines: | ||
| 429 | + :param polygons: | ||
| 430 | + :return: | ||
| 431 | + ''' | ||
| 432 | + | ||
| 433 | + kv = {} | ||
| 434 | + rps_set = set(rps) | ||
| 435 | + | ||
| 436 | + for delauney_line in delauney_lines: | ||
| 437 | + if kv.get(delauney_line.rp1): | ||
| 438 | + | ||
| 439 | + kv[delauney_line.rp1].add(delauney_line) | ||
| 440 | + else: | ||
| 441 | + kv[delauney_line.rp1] = set() | ||
| 442 | + kv[delauney_line.rp1].add(delauney_line) | ||
| 443 | + | ||
| 444 | + if kv.get(delauney_line.rp2): | ||
| 445 | + | ||
| 446 | + kv[delauney_line.rp2].add(delauney_line) | ||
| 447 | + else: | ||
| 448 | + | ||
| 449 | + kv[delauney_line.rp2] = set() | ||
| 450 | + kv[delauney_line.rp2].add(delauney_line) | ||
| 451 | + | ||
| 452 | + | ||
| 453 | + #初始化树 | ||
| 454 | + delauney_lines = sorted(delauney_lines,key=lambda x:x.distance) | ||
| 455 | + | ||
| 456 | + | ||
| 457 | + delauney_min_tree = DelauneyMinTree() | ||
| 458 | + delauney_min_tree.append(delauney_lines[0]) | ||
| 459 | + | ||
| 460 | + rps_set.remove(delauney_lines[0].rp1) | ||
| 461 | + rps_set.remove(delauney_lines[0].rp2) | ||
| 462 | + kv[delauney_lines[0].rp1].remove(delauney_lines[0]) | ||
| 463 | + kv[delauney_lines[0].rp2].remove(delauney_lines[0]) | ||
| 464 | + | ||
| 465 | + | ||
| 466 | + while rps_set.__len__()>0: | ||
| 467 | + | ||
| 468 | + relate_delauney_line = delauney_min_tree.get_other_relate_delauney_lines(kv) | ||
| 469 | + | ||
| 470 | + relate_delauney_line_sort = sorted(relate_delauney_line,key=lambda x:x.distance) | ||
| 471 | + | ||
| 472 | + min_distance_line = relate_delauney_line_sort[0] | ||
| 473 | + | ||
| 474 | + #删除 | ||
| 475 | + other_rp = delauney_min_tree.get_other_rp(min_distance_line) | ||
| 476 | + if other_rp is None: | ||
| 477 | + kv[min_distance_line.rp1].remove(min_distance_line) | ||
| 478 | + kv[min_distance_line.rp2].remove(min_distance_line) | ||
| 479 | + continue | ||
| 480 | + | ||
| 481 | + delauney_min_tree.append(min_distance_line) | ||
| 482 | + | ||
| 483 | + rps_set.remove(other_rp) | ||
| 484 | + | ||
| 485 | + kv[min_distance_line.rp1].remove(min_distance_line) | ||
| 486 | + kv[min_distance_line.rp2].remove(min_distance_line) | ||
| 487 | + | ||
| 488 | + | ||
| 489 | + | ||
| 490 | + for l in delauney_min_tree.delauney_lines_list: | ||
| 491 | + line = l.line | ||
| 492 | + # print("\"" + line.ExportToWkt() + "\",") | ||
| 493 | + | ||
| 494 | + # print(delauney_min_tree.delauney_lines_list.__len__()) | ||
| 495 | + | ||
| 496 | + return delauney_min_tree | ||
| 497 | + | ||
| 498 | + def cut_delauney_min_tree(self,delauney_min_tree:DelauneyMinTree,threshold): | ||
| 499 | + | ||
| 500 | + trees = [] | ||
| 501 | + kv = {} | ||
| 502 | + | ||
| 503 | + count = 0 | ||
| 504 | + | ||
| 505 | + for delauney_line in delauney_min_tree.delauney_lines_list: | ||
| 506 | + | ||
| 507 | + dn1 = kv.get(delauney_line.rp1) | ||
| 508 | + dn2 = kv.get(delauney_line.rp2) | ||
| 509 | + | ||
| 510 | + | ||
| 511 | + if not dn1: | ||
| 512 | + dn1 = DelauneyNode(delauney_line.rp1) | ||
| 513 | + kv[delauney_line.rp1] = dn1 | ||
| 514 | + | ||
| 515 | + if not dn2: | ||
| 516 | + | ||
| 517 | + trees.append(dn1) | ||
| 518 | + | ||
| 519 | + dn2 = DelauneyNode(delauney_line.rp2) | ||
| 520 | + kv[delauney_line.rp2] = dn2 | ||
| 521 | + | ||
| 522 | + if delauney_line.distance < threshold: | ||
| 523 | + dn1.add_children(dn2,delauney_line) | ||
| 524 | + count +=1 | ||
| 525 | + | ||
| 526 | + else: | ||
| 527 | + #断开 | ||
| 528 | + trees.append(dn2) | ||
| 529 | + else: | ||
| 530 | + | ||
| 531 | + if delauney_line.distance < threshold: | ||
| 532 | + dn2.add_children(dn1,delauney_line) | ||
| 533 | + count += 1 | ||
| 534 | + else: | ||
| 535 | + trees.append(dn1) | ||
| 536 | + else: | ||
| 537 | + | ||
| 538 | + dn2 = DelauneyNode(delauney_line.rp2) | ||
| 539 | + kv[delauney_line.rp2] = dn2 | ||
| 540 | + | ||
| 541 | + if delauney_line.distance < threshold: | ||
| 542 | + dn1.add_children(dn2,delauney_line) | ||
| 543 | + count += 1 | ||
| 544 | + else: | ||
| 545 | + trees.append(dn2) | ||
| 546 | + | ||
| 547 | + | ||
| 548 | + return trees | ||
| 549 | + | ||
| 550 | + def merge(self,trees): | ||
| 551 | + | ||
| 552 | + polygons = [] | ||
| 553 | + for tree in trees: | ||
| 554 | + | ||
| 555 | + merge_polygon_raw = list() | ||
| 556 | + | ||
| 557 | + dls = tree.get_delauney_lines() | ||
| 558 | + for dl in dls: | ||
| 559 | + p1 = dl.rp1.polygon | ||
| 560 | + p2 = dl.rp2.polygon | ||
| 561 | + | ||
| 562 | + merge_polygon_raw.append(p1) | ||
| 563 | + merge_polygon_raw.append(p2) | ||
| 564 | + line = dl.line | ||
| 565 | + | ||
| 566 | + p1_lines = self.get_polygon_lines(p1) | ||
| 567 | + p2_lines = self.get_polygon_lines(p2) | ||
| 568 | + | ||
| 569 | + p1_intersect_lines = [l for l in p1_lines if l.Intersect(line)] | ||
| 570 | + p2_intersect_lines = [l for l in p2_lines if l.Intersect(line)] | ||
| 571 | + | ||
| 572 | + if p1_intersect_lines.__len__()>1: | ||
| 573 | + p1_intersect_lines = sorted(p1_intersect_lines,key=lambda x:p2.Distance(x)) | ||
| 574 | + p1_intersect_line_rep = p1_intersect_lines[0] | ||
| 575 | + elif p1_intersect_lines.__len__()==1: | ||
| 576 | + p1_intersect_line_rep = p1_intersect_lines[0] | ||
| 577 | + else: | ||
| 578 | + continue | ||
| 579 | + | ||
| 580 | + | ||
| 581 | + if p2_intersect_lines.__len__()>1: | ||
| 582 | + p2_intersect_lines = sorted(p2_intersect_lines,key=lambda x:p1.Distance(x)) | ||
| 583 | + p2_intersect_line_rep = p2_intersect_lines[0] | ||
| 584 | + elif p2_intersect_lines.__len__()==1: | ||
| 585 | + p2_intersect_line_rep = p2_intersect_lines[0] | ||
| 586 | + else: | ||
| 587 | + continue | ||
| 588 | + | ||
| 589 | + | ||
| 590 | + # #两条线没有距离跳过 | ||
| 591 | + # if p2_intersect_line_rep.Distance(p1_intersect_line_rep) == 0: | ||
| 592 | + # continue | ||
| 593 | + # else: | ||
| 594 | + | ||
| 595 | + mid_polygon = self.create_mid_polygon(p1_intersect_line_rep,p2_intersect_line_rep,p1,p2) | ||
| 596 | + | ||
| 597 | + if mid_polygon.GetArea() > 0.0002116361000058077*0.0002116361000058077: | ||
| 598 | + continue | ||
| 599 | + | ||
| 600 | + merge_polygon_raw.append(mid_polygon) | ||
| 601 | + | ||
| 602 | + merge_polygon = None | ||
| 603 | + for p in merge_polygon_raw: | ||
| 604 | + if merge_polygon is None: | ||
| 605 | + merge_polygon = p | ||
| 606 | + else: | ||
| 607 | + merge_polygon = merge_polygon.Union(p) | ||
| 608 | + | ||
| 609 | + polygons.append(merge_polygon) | ||
| 610 | + | ||
| 611 | + | ||
| 612 | + return polygons | ||
| 613 | + | ||
| 614 | + | ||
| 615 | + def merge2(self,trees): | ||
| 616 | + | ||
| 617 | + polygons = [] | ||
| 618 | + | ||
| 619 | + | ||
| 620 | + | ||
| 621 | + | ||
| 622 | + for tree in trees: | ||
| 623 | + | ||
| 624 | + tree_polygons = tree.get_polygons() | ||
| 625 | + | ||
| 626 | + points = [] | ||
| 627 | + for p in tree_polygons: | ||
| 628 | + | ||
| 629 | + if p.GetGeometryCount() == 1: | ||
| 630 | + polygon_line: Geometry = ogr.ForceToLineString(p) | ||
| 631 | + | ||
| 632 | + polygon_line.Con | ||
| 633 | + # 有孔Polygon | ||
| 634 | + else: | ||
| 635 | + polygon_line: Geometry = ogr.ForceToLineString(p.GetGeometryRef(0)) | ||
| 636 | + | ||
| 637 | + points.extend(polygon_line.GetPoints()[:-1]) | ||
| 638 | + | ||
| 639 | + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint) | ||
| 640 | + | ||
| 641 | + for p in points: | ||
| 642 | + poi = ogr.Geometry(ogr.wkbPoint) | ||
| 643 | + poi.AddPoint(p[0],p[1]) | ||
| 644 | + multipoint.AddGeometry(poi) | ||
| 645 | + | ||
| 646 | + delauney: Geometry = multipoint.DelaunayTriangulation() | ||
| 647 | + merge_polygon = None | ||
| 648 | + | ||
| 649 | + for p in delauney: | ||
| 650 | + # if multi_polygon.Contains(p): | ||
| 651 | + # continue | ||
| 652 | + | ||
| 653 | + pline:Geometry = ogr.ForceToLineString(p) | ||
| 654 | + pline :list = pline.GetPoints() | ||
| 655 | + pline.append(pline[1]) | ||
| 656 | + | ||
| 657 | + | ||
| 658 | + pass_or_not = False | ||
| 659 | + for indx in range(3): | ||
| 660 | + p1 = pline[indx] | ||
| 661 | + p2 = pline[indx+1] | ||
| 662 | + | ||
| 663 | + ppline:Geometry = ogr.Geometry(ogr.wkbLineString) | ||
| 664 | + ppline.AddPoint(p1[0],p1[1]) | ||
| 665 | + ppline.AddPoint(p2[0], p2[1]) | ||
| 666 | + | ||
| 667 | + | ||
| 668 | + | ||
| 669 | + p3:Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 670 | + p3.AddPoint(pline[indx+2][0], pline[indx+2][1]) | ||
| 671 | + | ||
| 672 | + if p3.Distance(ppline) > 0.0002116361000058077 or ppline.Length() > 0.0002116361000058077: | ||
| 673 | + pass_or_not = True | ||
| 674 | + break | ||
| 675 | + | ||
| 676 | + if pass_or_not: | ||
| 677 | + continue | ||
| 678 | + | ||
| 679 | + if merge_polygon is None: | ||
| 680 | + merge_polygon = p | ||
| 681 | + else: | ||
| 682 | + merge_polygon = merge_polygon.Union(p) | ||
| 683 | + | ||
| 684 | + | ||
| 685 | + | ||
| 686 | + polygons.append(merge_polygon) | ||
| 687 | + | ||
| 688 | + | ||
| 689 | + return polygons | ||
| 690 | + | ||
| 691 | + def merge_circle(self): | ||
| 692 | + pass | ||
| 693 | + | ||
| 694 | + | ||
| 695 | + def create_mid_polygon(self,p1_intersect_line_rep,p2_intersect_line_rep,p1,p2): | ||
| 696 | + ''' | ||
| 697 | + 创建衔接polygon | ||
| 698 | + :param line: | ||
| 699 | + :return: | ||
| 700 | + ''' | ||
| 701 | + | ||
| 702 | + if p1_intersect_line_rep.Intersect(p2_intersect_line_rep): | ||
| 703 | + | ||
| 704 | + p1_rep_p1 = p1_intersect_line_rep.GetPoints()[0] | ||
| 705 | + p1_rep_p2 = p1_intersect_line_rep.GetPoints()[1] | ||
| 706 | + | ||
| 707 | + p2_rep_p1 = p2_intersect_line_rep.GetPoints()[0] | ||
| 708 | + p2_rep_p2 = p2_intersect_line_rep.GetPoints()[1] | ||
| 709 | + | ||
| 710 | + polygon = self.create_polygon(p1_rep_p1, p2_rep_p2, p1_rep_p2, p2_rep_p1) | ||
| 711 | + | ||
| 712 | + else: | ||
| 713 | + | ||
| 714 | + p1_rep_p1 = p1_intersect_line_rep.GetPoints()[0] | ||
| 715 | + p1_rep_p2 = p1_intersect_line_rep.GetPoints()[1] | ||
| 716 | + | ||
| 717 | + p2_rep_p1 = p2_intersect_line_rep.GetPoints()[0] | ||
| 718 | + p2_rep_p2 = p2_intersect_line_rep.GetPoints()[1] | ||
| 719 | + | ||
| 720 | + line1 = ogr.Geometry(ogr.wkbLineString) | ||
| 721 | + | ||
| 722 | + | ||
| 723 | + line1.AddPoint(p1_rep_p1[0], p1_rep_p1[1]) | ||
| 724 | + line1.AddPoint(p2_rep_p1[0], p2_rep_p1[1]) | ||
| 725 | + | ||
| 726 | + line2 = ogr.Geometry(ogr.wkbLineString) | ||
| 727 | + line2.AddPoint(p1_rep_p2[0], p1_rep_p2[1]) | ||
| 728 | + line2.AddPoint(p2_rep_p2[0], p2_rep_p2[1]) | ||
| 729 | + | ||
| 730 | + if line1.Intersect(line2): | ||
| 731 | + polygon = self.create_polygon(p1_rep_p1, p1_rep_p2, p2_rep_p1, p2_rep_p2) | ||
| 732 | + else: | ||
| 733 | + | ||
| 734 | + polygon = self.create_polygon(p1_rep_p1, p1_rep_p2, p2_rep_p2, p2_rep_p1) | ||
| 735 | + if polygon.Intersect(p1) or polygon.Intersect(p2): | ||
| 736 | + polygon = self.create_polygon(p1_rep_p1, p1_rep_p2, p2_rep_p1, p2_rep_p2) | ||
| 737 | + | ||
| 738 | + | ||
| 739 | + return polygon | ||
| 740 | + | ||
| 741 | + def create_polygon(self,p1,p2,p3,p4): | ||
| 742 | + | ||
| 743 | + ring = ogr.Geometry(ogr.wkbLinearRing) | ||
| 744 | + ring.AddPoint(p1[0], p1[1]) | ||
| 745 | + ring.AddPoint(p2[0], p2[1]) | ||
| 746 | + ring.AddPoint(p3[0], p3[1]) | ||
| 747 | + ring.AddPoint(p4[0], p4[1]) | ||
| 748 | + ring.AddPoint(p1[0], p1[1]) | ||
| 749 | + | ||
| 750 | + poly = ogr.Geometry(ogr.wkbPolygon) | ||
| 751 | + poly.AddGeometry(ring) | ||
| 752 | + return poly | ||
| 753 | + | ||
| 754 | + | ||
| 755 | + def get_polygon_lines(self,polygon): | ||
| 756 | + #无孔Polygon | ||
| 757 | + if polygon.GetGeometryCount() == 1: | ||
| 758 | + polygon_line : Geometry = ogr.ForceToLineString(polygon) | ||
| 759 | + # 有孔Polygon | ||
| 760 | + else: | ||
| 761 | + polygon_line : Geometry = ogr.ForceToLineString(polygon.GetGeometryRef(0)) | ||
| 762 | + | ||
| 763 | + points = polygon_line.GetPoints() | ||
| 764 | + | ||
| 765 | + lines = [] | ||
| 766 | + for index in range(len(points)-1): | ||
| 767 | + | ||
| 768 | + point_start = points[index] | ||
| 769 | + point_end = points[index+1] | ||
| 770 | + line = ogr.Geometry(ogr.wkbLineString) | ||
| 771 | + line.AddPoint(point_start[0], point_start[1]) | ||
| 772 | + line.AddPoint(point_end[0], point_end[1]) | ||
| 773 | + | ||
| 774 | + lines.append(line) | ||
| 775 | + | ||
| 776 | + return lines | ||
| 777 | + | ||
| 778 | + def merge_concave(self, trees, distance_threshold): | ||
| 779 | + merge_polygons = [] | ||
| 780 | + for tree in trees: | ||
| 781 | + polygons = list(tree.get_polygons()) | ||
| 782 | + | ||
| 783 | + merge_raw: Geometry = polygons[0] | ||
| 784 | + for p in polygons: | ||
| 785 | + merge_raw = merge_raw.Union(p) | ||
| 786 | + | ||
| 787 | + points = [] | ||
| 788 | + dd= merge_raw.GetGeometryCount() | ||
| 789 | + | ||
| 790 | + for i in range(merge_raw.GetGeometryCount()): | ||
| 791 | + | ||
| 792 | + poly = merge_raw.GetGeometryRef(i) | ||
| 793 | + if poly.GetGeometryCount() == 1: | ||
| 794 | + poly_line: Geometry = ogr.ForceToLineString(poly) | ||
| 795 | + # 有孔Polygon | ||
| 796 | + else: | ||
| 797 | + poly_line: Geometry = ogr.ForceToLineString(poly.GetGeometryRef(0)) | ||
| 798 | + if poly_line: | ||
| 799 | + for indx in range(poly_line.GetPointCount() - 1): | ||
| 800 | + poi = poly_line.GetPoint(indx) | ||
| 801 | + | ||
| 802 | + points.append(poi) | ||
| 803 | + | ||
| 804 | + poi_next = poly_line.GetPoint(indx + 1) | ||
| 805 | + | ||
| 806 | + dis = math.sqrt(math.pow(poi[0] - poi_next[0], 2) + math.pow(poi[1] - poi_next[1], 2)) | ||
| 807 | + # print(dis) | ||
| 808 | + if dis > distance_threshold: | ||
| 809 | + times = int(dis / distance_threshold) | ||
| 810 | + # print(times) | ||
| 811 | + for time in range(1, times + 1): | ||
| 812 | + x, y = self.get_subpoint(poi[0], poi[1], poi_next[0], poi_next[1], (time * distance_threshold)) | ||
| 813 | + points.append([x, y]) | ||
| 814 | + | ||
| 815 | + points = np.array([[p[0], p[1]] for p in points]) | ||
| 816 | + | ||
| 817 | + for pp in points: | ||
| 818 | + poi = ogr.Geometry(ogr.wkbPoint) | ||
| 819 | + poi.AddPoint(pp[0], pp[1]) | ||
| 820 | + | ||
| 821 | + merge_p_line = concaveHull(points, 3) | ||
| 822 | + | ||
| 823 | + ring = ogr.Geometry(ogr.wkbLinearRing) | ||
| 824 | + | ||
| 825 | + merge_p = ogr.Geometry(ogr.wkbPolygon) | ||
| 826 | + | ||
| 827 | + for l in merge_p_line: | ||
| 828 | + ring.AddPoint(l[0], l[1]) | ||
| 829 | + | ||
| 830 | + ring.AddPoint(merge_p_line[0][0], merge_p_line[0][1]) | ||
| 831 | + | ||
| 832 | + merge_p.AddGeometry(ring) | ||
| 833 | + | ||
| 834 | + merge_polygons.append(merge_p) | ||
| 835 | + | ||
| 836 | + return merge_polygons | ||
| 837 | + | ||
| 838 | + def get_subpoint(self, x0, y0, x1, y1, len_size): | ||
| 839 | + | ||
| 840 | + len_size = len_size | ||
| 841 | + tanx = abs(y1 - y0) / abs(x1 - x0) | ||
| 842 | + cosx = 1 / math.sqrt(1 + tanx * tanx) | ||
| 843 | + dx = cosx * len_size | ||
| 844 | + dy = tanx * dx | ||
| 845 | + | ||
| 846 | + if x1 == x0: | ||
| 847 | + x2 = x0 | ||
| 848 | + if y1 > y0: | ||
| 849 | + y2 = y0 + abs(dy) | ||
| 850 | + else: | ||
| 851 | + y2 = y0 - abs(dy) | ||
| 852 | + else: | ||
| 853 | + if x1 < x0: | ||
| 854 | + x2 = x0 - dx | ||
| 855 | + else: | ||
| 856 | + x2 = x0 + dx | ||
| 857 | + | ||
| 858 | + if y1 < y0: | ||
| 859 | + y2 = y0 - dy | ||
| 860 | + else: | ||
| 861 | + y2 = y0 + dy | ||
| 862 | + | ||
| 863 | + return x2, y2 | ||
| 864 | + | ||
| 865 | + def process(self): | ||
| 866 | + polygons = self.data.get_polygons() | ||
| 867 | + rps = [] | ||
| 868 | + for poly in polygons: | ||
| 869 | + rp = self.get_polygon_reprecent_point(poly) | ||
| 870 | + rps.append(rp) | ||
| 871 | + | ||
| 872 | + delauney_lines = self.create_delauney(rps) | ||
| 873 | + | ||
| 874 | + min_delauney = self.create_min_delauney(delauney_lines,rps,polygons) | ||
| 875 | + | ||
| 876 | + trees = self.cut_delauney_min_tree(min_delauney,self.distance_buffer_threshold) | ||
| 877 | + | ||
| 878 | + print(len(trees)) | ||
| 879 | + polygons = self.merge_concave(trees,0.00007) | ||
| 880 | + | ||
| 881 | + return [p.ExportToWkt() for p in polygons] | ||
| 882 | + | ||
| 883 | +if __name__ == '__main__': | ||
| 884 | + | ||
| 885 | + | ||
| 886 | + # print(sd.get_polygons()[0]) | ||
| 887 | + # sd.close() | ||
| 888 | + | ||
| 889 | + | ||
| 890 | + sd = ShapeData(r"J:\Data\制图综合\example.shp") | ||
| 891 | + | ||
| 892 | + ext = sd.layer.GetExtent() | ||
| 893 | + threshold = (ext[1]-ext[0])/20 | ||
| 894 | + print(threshold) | ||
| 895 | + | ||
| 896 | + | ||
| 897 | + zh = Zonghe(sd) | ||
| 898 | + wkts = zh.process() | ||
| 899 | + | ||
| 900 | + result = r"J:\Data\制图综合\zhonghe_concave2.shp" | ||
| 901 | + ShapeData.create_shp_fromwkts(result,"zh",wkts) | ||
| 902 | + |
请
注册
或
登录
后发表评论