正在显示
2 个修改的文件
包含
910 行增加
和
5 行删除
... | ... | @@ -6,8 +6,10 @@ from app.util.component.ParameterUtil import ParameterUtil |
6 | 6 | from flask import current_app,request |
7 | 7 | import traceback |
8 | 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 | 11 | import app |
12 | + | |
11 | 13 | class ApiTemplate: |
12 | 14 | #模板方法 |
13 | 15 | para = dict() |
... | ... | @@ -28,10 +30,11 @@ class ApiTemplate: |
28 | 30 | if app.GLOBAL_DIC.get(token): |
29 | 31 | self.para["creator"] = app.GLOBAL_DIC.get(token) |
30 | 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 | 39 | def para_check(self): |
37 | 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 | + | ... | ... |
请
注册
或
登录
后发表评论