正在显示
19 个修改的文件
包含
1947 行增加
和
137 行删除
| @@ -11,6 +11,8 @@ from ..models import Database,DES | @@ -11,6 +11,8 @@ from ..models import Database,DES | ||
| 11 | 11 | ||
| 12 | from app.util.component.ApiTemplate import ApiTemplate | 12 | from app.util.component.ApiTemplate import ApiTemplate |
| 13 | from app.util.component.ModelVisitor import ModelVisitor | 13 | from app.util.component.ModelVisitor import ModelVisitor |
| 14 | +from app.util.component.UserAlias import UserAlias | ||
| 15 | + | ||
| 14 | class Api(ApiTemplate): | 16 | class Api(ApiTemplate): |
| 15 | api_name = "获取数据库列表" | 17 | api_name = "获取数据库列表" |
| 16 | def process(self): | 18 | def process(self): |
| @@ -32,6 +34,9 @@ class Api(ApiTemplate): | @@ -32,6 +34,9 @@ class Api(ApiTemplate): | ||
| 32 | 34 | ||
| 33 | database = database.limit(page_size).offset(page_index * page_size).all() | 35 | database = database.limit(page_size).offset(page_index * page_size).all() |
| 34 | res["data"]["list"] =[] | 36 | res["data"]["list"] =[] |
| 37 | + | ||
| 38 | + user_alias = UserAlias() | ||
| 39 | + | ||
| 35 | for datab in database: | 40 | for datab in database: |
| 36 | # 测试连接 | 41 | # 测试连接 |
| 37 | try: | 42 | try: |
| @@ -45,6 +50,8 @@ class Api(ApiTemplate): | @@ -45,6 +50,8 @@ class Api(ApiTemplate): | ||
| 45 | datab_json = ModelVisitor.database_to_json(datab) | 50 | datab_json = ModelVisitor.database_to_json(datab) |
| 46 | datab_json["table_count"] = table_count | 51 | datab_json["table_count"] = table_count |
| 47 | datab_json["available"] = available | 52 | datab_json["available"] = available |
| 53 | + datab_json["display_name"] = user_alias.get_alias(datab_json["creator"]) | ||
| 54 | + | ||
| 48 | del datab_json["connectstr"] | 55 | del datab_json["connectstr"] |
| 49 | res["data"]["list"].append(datab_json) | 56 | res["data"]["list"].append(datab_json) |
| 50 | 57 |
| @@ -4,12 +4,13 @@ | @@ -4,12 +4,13 @@ | ||
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | from ..models import Table,Catalog | 6 | from ..models import Table,Catalog |
| 7 | - | 7 | +from app.modules.auth.models import User |
| 8 | from sqlalchemy import or_,and_ | 8 | from sqlalchemy import or_,and_ |
| 9 | - | 9 | +from sqlalchemy.orm import Query |
| 10 | from app.util.component.ApiTemplate import ApiTemplate | 10 | from app.util.component.ApiTemplate import ApiTemplate |
| 11 | - | 11 | +from app.util.component.UserAlias import UserAlias |
| 12 | from app.util.component.ModelVisitor import ModelVisitor | 12 | from app.util.component.ModelVisitor import ModelVisitor |
| 13 | + | ||
| 13 | class Api(ApiTemplate): | 14 | class Api(ApiTemplate): |
| 14 | api_name = "表列表" | 15 | api_name = "表列表" |
| 15 | def process(self): | 16 | def process(self): |
| @@ -37,10 +38,11 @@ class Api(ApiTemplate): | @@ -37,10 +38,11 @@ class Api(ApiTemplate): | ||
| 37 | 38 | ||
| 38 | sort = int(self.para.get("sort","1")) | 39 | sort = int(self.para.get("sort","1")) |
| 39 | if sort.__eq__(1): | 40 | if sort.__eq__(1): |
| 40 | - tables = Table.query.order_by(Table.update_time.desc(),Table.name) | 41 | + tables:Query = Table.query.order_by(Table.update_time.desc(),Table.name) |
| 41 | else: | 42 | else: |
| 42 | tables = Table.query.order_by(Table.name) | 43 | tables = Table.query.order_by(Table.name) |
| 43 | 44 | ||
| 45 | + | ||
| 44 | #过滤spatial_ref_sys | 46 | #过滤spatial_ref_sys |
| 45 | tables = tables.filter(Table.name.notin_(["spatial_ref_sys"])) | 47 | tables = tables.filter(Table.name.notin_(["spatial_ref_sys"])) |
| 46 | 48 | ||
| @@ -75,8 +77,12 @@ class Api(ApiTemplate): | @@ -75,8 +77,12 @@ class Api(ApiTemplate): | ||
| 75 | tables = tables.limit(page_size).offset(page_index * page_size).all() | 77 | tables = tables.limit(page_size).offset(page_index * page_size).all() |
| 76 | res["data"]["list"]=[] | 78 | res["data"]["list"]=[] |
| 77 | 79 | ||
| 80 | + | ||
| 81 | + user_alias = UserAlias() | ||
| 78 | for t in tables: | 82 | for t in tables: |
| 79 | - res["data"]["list"].append(ModelVisitor.table_to_json(t)) | 83 | + table_json = ModelVisitor.table_to_json(t) |
| 84 | + table_json["display_name"] = user_alias.get_alias(table_json["creator"]) | ||
| 85 | + res["data"]["list"].append(table_json) | ||
| 80 | 86 | ||
| 81 | res["result"] = True | 87 | res["result"] = True |
| 82 | except Exception as e: | 88 | except Exception as e: |
| @@ -10,7 +10,8 @@ from ..models import Task | @@ -10,7 +10,8 @@ from ..models import Task | ||
| 10 | from app.util.component.ApiTemplate import ApiTemplate | 10 | from app.util.component.ApiTemplate import ApiTemplate |
| 11 | from app.util.component.ModelVisitor import ModelVisitor | 11 | from app.util.component.ModelVisitor import ModelVisitor |
| 12 | import json | 12 | import json |
| 13 | - | 13 | +from app.modules.auth.models import User |
| 14 | +from app.util.component.UserAlias import UserAlias | ||
| 14 | 15 | ||
| 15 | class Api(ApiTemplate): | 16 | class Api(ApiTemplate): |
| 16 | api_name = "任务列表" | 17 | api_name = "任务列表" |
| @@ -33,7 +34,7 @@ class Api(ApiTemplate): | @@ -33,7 +34,7 @@ class Api(ApiTemplate): | ||
| 33 | 34 | ||
| 34 | state = parameter.get("state") | 35 | state = parameter.get("state") |
| 35 | 36 | ||
| 36 | - if creator: | 37 | + if creator and creator !="admin": |
| 37 | tasks = tasks.filter_by(creator=creator) | 38 | tasks = tasks.filter_by(creator=creator) |
| 38 | if start_time and end_time: | 39 | if start_time and end_time: |
| 39 | tasks = tasks.filter(Task.create_time.between(start_time, end_time)) | 40 | tasks = tasks.filter(Task.create_time.between(start_time, end_time)) |
| @@ -52,6 +53,8 @@ class Api(ApiTemplate): | @@ -52,6 +53,8 @@ class Api(ApiTemplate): | ||
| 52 | res["data"]["list"] = [ModelVisitor.task_to_json(task) for task in tasks] | 53 | res["data"]["list"] = [ModelVisitor.task_to_json(task) for task in tasks] |
| 53 | 54 | ||
| 54 | try: | 55 | try: |
| 56 | + user_alias = UserAlias() | ||
| 57 | + | ||
| 55 | for task_info in res["data"]["list"]: | 58 | for task_info in res["data"]["list"]: |
| 56 | if task_info["task_type"]==1: | 59 | if task_info["task_type"]==1: |
| 57 | task_info["layers"] = [] | 60 | task_info["layers"] = [] |
| @@ -60,6 +63,7 @@ class Api(ApiTemplate): | @@ -60,6 +63,7 @@ class Api(ApiTemplate): | ||
| 60 | for key in m.get("layer").keys(): | 63 | for key in m.get("layer").keys(): |
| 61 | 64 | ||
| 62 | task_info["layers"].append({"name":key,"new_name":m.get("layer").get(key)}) | 65 | task_info["layers"].append({"name":key,"new_name":m.get("layer").get(key)}) |
| 66 | + task_info["display_name"] = user_alias.get_alias(task_info["creator"]) | ||
| 63 | except: | 67 | except: |
| 64 | pass | 68 | pass |
| 65 | 69 |
| @@ -39,9 +39,15 @@ class Api(ApiTemplate): | @@ -39,9 +39,15 @@ class Api(ApiTemplate): | ||
| 39 | try: | 39 | try: |
| 40 | 40 | ||
| 41 | this_time = datetime.datetime.now() | 41 | this_time = datetime.datetime.now() |
| 42 | - service_guid = uuid.uuid1().__str__ida() | 42 | + service_guid = uuid.uuid1().__str__() |
| 43 | map_service_guid = uuid.uuid1().__str__() | 43 | map_service_guid = uuid.uuid1().__str__() |
| 44 | 44 | ||
| 45 | + token = self.para.get("token") | ||
| 46 | + creator = self.para.get("creator") | ||
| 47 | + if creator is None: | ||
| 48 | + raise Exception("用户检验失败!") | ||
| 49 | + | ||
| 50 | + | ||
| 45 | # 逻辑是,先调用引擎接口,引擎说可以,才做持久化 | 51 | # 逻辑是,先调用引擎接口,引擎说可以,才做持久化 |
| 46 | project_file = self.create_projectfile(self.para) | 52 | project_file = self.create_projectfile(self.para) |
| 47 | para = {"name":self.para.get("name"), | 53 | para = {"name":self.para.get("name"), |
| @@ -72,7 +78,7 @@ class Api(ApiTemplate): | @@ -72,7 +78,7 @@ class Api(ApiTemplate): | ||
| 72 | guid = service_guid, | 78 | guid = service_guid, |
| 73 | name = self.para.get("name"), | 79 | name = self.para.get("name"), |
| 74 | title = self.para.get("title"), | 80 | title = self.para.get("title"), |
| 75 | - creator=self.para.get("creator"), | 81 | + creator=creator, |
| 76 | state = 1, | 82 | state = 1, |
| 77 | create_time = this_time, | 83 | create_time = this_time, |
| 78 | update_time = this_time, | 84 | update_time = this_time, |
| @@ -103,7 +109,9 @@ class Api(ApiTemplate): | @@ -103,7 +109,9 @@ class Api(ApiTemplate): | ||
| 103 | db.session.commit() | 109 | db.session.commit() |
| 104 | 110 | ||
| 105 | res["data"] = service_guid | 111 | res["data"] = service_guid |
| 112 | + res["url"] = "" | ||
| 106 | res["result"] = True | 113 | res["result"] = True |
| 114 | + | ||
| 107 | except Exception as e: | 115 | except Exception as e: |
| 108 | db.session.rollback() | 116 | db.session.rollback() |
| 109 | raise e | 117 | raise e |
| @@ -294,6 +302,12 @@ class Api(ApiTemplate): | @@ -294,6 +302,12 @@ class Api(ApiTemplate): | ||
| 294 | "type": "string", | 302 | "type": "string", |
| 295 | "description": "表名", | 303 | "description": "表名", |
| 296 | "required": "true"}, | 304 | "required": "true"}, |
| 305 | + | ||
| 306 | + {"name": "token", | ||
| 307 | + "in": "formData", | ||
| 308 | + "type": "string", | ||
| 309 | + "description": "token", | ||
| 310 | + "required": "true"}, | ||
| 297 | ], | 311 | ], |
| 298 | "responses": { | 312 | "responses": { |
| 299 | 200: { | 313 | 200: { |
| @@ -11,6 +11,7 @@ from sqlalchemy import or_ | @@ -11,6 +11,7 @@ from sqlalchemy import or_ | ||
| 11 | import requests | 11 | import requests |
| 12 | import re | 12 | import re |
| 13 | from .util.ServiceType import ServiceType | 13 | from .util.ServiceType import ServiceType |
| 14 | +from app.util.component.UserAlias import UserAlias | ||
| 14 | 15 | ||
| 15 | class Api(ApiTemplate): | 16 | class Api(ApiTemplate): |
| 16 | api_name = "服务列表" | 17 | api_name = "服务列表" |
| @@ -99,6 +100,12 @@ class Api(ApiTemplate): | @@ -99,6 +100,12 @@ class Api(ApiTemplate): | ||
| 99 | services_json = sorted(services_json,key=lambda x:x["update_time"],reverse=True) | 100 | services_json = sorted(services_json,key=lambda x:x["update_time"],reverse=True) |
| 100 | 101 | ||
| 101 | res["data"]["list"] = services_json[page_index*page_size:(page_index+1)*page_size] | 102 | res["data"]["list"] = services_json[page_index*page_size:(page_index+1)*page_size] |
| 103 | + | ||
| 104 | + # 显示别名 | ||
| 105 | + user_alias = UserAlias() | ||
| 106 | + for service_json in res["data"]["list"]: | ||
| 107 | + service_json["display_name"] = user_alias.get_alias(service_json["creator"]) | ||
| 108 | + | ||
| 102 | res["result"] = True | 109 | res["result"] = True |
| 103 | 110 | ||
| 104 | except Exception as e: | 111 | except Exception as e: |
| @@ -15,6 +15,7 @@ class ParameterUtil: | @@ -15,6 +15,7 @@ class ParameterUtil: | ||
| 15 | parameter = dict() | 15 | parameter = dict() |
| 16 | parameter.update(request.args.items()) | 16 | parameter.update(request.args.items()) |
| 17 | parameter.update(request.form.items()) | 17 | parameter.update(request.form.items()) |
| 18 | + | ||
| 18 | try: | 19 | try: |
| 19 | request_json = request.get_json() | 20 | request_json = request.get_json() |
| 20 | if json: | 21 | if json: |
app/util/component/UserAlias.py
0 → 100644
| 1 | +# coding=utf-8 | ||
| 2 | +#author: 4N | ||
| 3 | +#createtime: 2022/3/17 | ||
| 4 | +#email: nheweijun@sina.com | ||
| 5 | + | ||
| 6 | +from app.modules.auth.models import User | ||
| 7 | + | ||
| 8 | +class UserAlias: | ||
| 9 | + def __init__(self): | ||
| 10 | + self.creator_dict = {} | ||
| 11 | + | ||
| 12 | + def get_alias(self,creator): | ||
| 13 | + alias = self.creator_dict.get(creator) | ||
| 14 | + if alias: | ||
| 15 | + return alias | ||
| 16 | + else: | ||
| 17 | + user = User.query.filter_by(username=creator).one_or_none() | ||
| 18 | + if user: | ||
| 19 | + self.creator_dict[creator] = user.displayname | ||
| 20 | + else: | ||
| 21 | + self.creator_dict[creator] = "" | ||
| 22 | + return self.creator_dict[creator] |
test/geo-matplot.py
0 → 100644
| 1 | +# coding=utf-8 | ||
| 2 | +#author: 4N | ||
| 3 | +#createtime: 2022/3/14 | ||
| 4 | +#email: nheweijun@sina.com | ||
| 5 | +import numpy as np | ||
| 6 | +import matplotlib.pyplot as plt | ||
| 7 | +from matplotlib.collections import PolyCollection,LineCollection | ||
| 8 | +import matplotlib as mpl | ||
| 9 | +from PIL import Image | ||
| 10 | +import os | ||
| 11 | + | ||
| 12 | + | ||
| 13 | +def draw(geom): | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + rectangle = [(0, 0), (0, 1), (1, 1), (1, 0),(0, 0)] | ||
| 18 | + # hexagon = [(0, 0), (0, 1), (1, 2), (2, 1), (2, 0), (1, -1)] | ||
| 19 | + l_shape = [(0, 0), (0, 3), (1, 3), (1, 1), (3, 1), (3, 0)] | ||
| 20 | + # concave = [(0, 0), (0, 3), (1, 3), (1, 1), (2, 1), (2, 3), (3, 3), (3, 0)] | ||
| 21 | + | ||
| 22 | + for points in [rectangle,l_shape]: | ||
| 23 | + xs, ys = zip(*points) | ||
| 24 | + # plt.plot(xs, ys, 'o') | ||
| 25 | + plt.plot(xs, ys, '-') | ||
| 26 | + | ||
| 27 | + plt.axis('off') | ||
| 28 | + png_path = "F:/temp.png" | ||
| 29 | + plt.savefig(png_path) | ||
| 30 | + png = Image.open(png_path) | ||
| 31 | + tif_path = "F:/temp.tif" | ||
| 32 | + png.save(tif_path) | ||
| 33 | + os.remove(png_path) | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +if __name__ == '__main__': | ||
| 37 | + draw() |
test/test.py
0 → 100644
| 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 | + | ||
| 11 | +class util: | ||
| 12 | + @classmethod | ||
| 13 | + def envelop_2_polygon(cls,env): | ||
| 14 | + ring = ogr.Geometry(ogr.wkbLinearRing) | ||
| 15 | + ring.AddPoint(env[0], env[2]) | ||
| 16 | + ring.AddPoint(env[0], env[3]) | ||
| 17 | + ring.AddPoint(env[1], env[3]) | ||
| 18 | + ring.AddPoint(env[1], env[2]) | ||
| 19 | + ring.AddPoint(env[0], env[2]) | ||
| 20 | + # Create polygon | ||
| 21 | + poly = ogr.Geometry(ogr.wkbPolygon) | ||
| 22 | + poly.AddGeometry(ring) | ||
| 23 | + return poly | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +p1= util.envelop_2_polygon([0,1,0,1]) | ||
| 27 | +p2 = util.envelop_2_polygon([2,3,2,3]) | ||
| 28 | + | ||
| 29 | +lll = p1.GetGeometryRef(0) | ||
| 30 | +print(lll.GetPoints()) | ||
| 31 | + | ||
| 32 | + |
test/zonghe/ConcaveHull.py
0 → 100644
| 1 | +#!/bin/env python | ||
| 2 | + | ||
| 3 | +## | ||
| 4 | +## calculate the concave hull of a set of points | ||
| 5 | +## see: CONCAVE HULL: A K-NEAREST NEIGHBOURS APPROACH | ||
| 6 | +## FOR THE COMPUTATION OF THE REGION OCCUPIED BY A | ||
| 7 | +## SET OF POINTS | ||
| 8 | +## Adriano Moreira and Maribel Yasmina Santos 2007 | ||
| 9 | +## | ||
| 10 | + | ||
| 11 | +import numpy as np | ||
| 12 | +import scipy.spatial as spt | ||
| 13 | +import matplotlib.pyplot as plt | ||
| 14 | +from matplotlib.path import Path | ||
| 15 | +from test.zonghe import lineintersect as li | ||
| 16 | + | ||
| 17 | +def GetFirstPoint(dataset): | ||
| 18 | + ''' Returns index of first point, which has the lowest y value ''' | ||
| 19 | + # todo: what if there is more than one point with lowest y? | ||
| 20 | + imin = np.argmin(dataset[:,1]) | ||
| 21 | + return dataset[imin] | ||
| 22 | + | ||
| 23 | +def GetNearestNeighbors(dataset, point, k): | ||
| 24 | + ''' Returns indices of k nearest neighbors of point in dataset''' | ||
| 25 | + # todo: experiment with leafsize for performance | ||
| 26 | + mytree = spt.cKDTree(dataset,leafsize=10) | ||
| 27 | + distances, indices = mytree.query(point,k) | ||
| 28 | + # todo: something strange here, we get more indices than points in dataset | ||
| 29 | + # so have to do this | ||
| 30 | + return dataset[indices[:dataset.shape[0]]] | ||
| 31 | + | ||
| 32 | +def SortByAngle(kNearestPoints, currentPoint, prevPoint): | ||
| 33 | + ''' Sorts the k nearest points given by angle ''' | ||
| 34 | + angles = np.zeros(kNearestPoints.shape[0]) | ||
| 35 | + i = 0 | ||
| 36 | + for NearestPoint in kNearestPoints: | ||
| 37 | + # calculate the angle | ||
| 38 | + angle = np.arctan2(NearestPoint[1]-currentPoint[1], | ||
| 39 | + NearestPoint[0]-currentPoint[0]) - \ | ||
| 40 | + np.arctan2(prevPoint[1]-currentPoint[1], | ||
| 41 | + prevPoint[0]-currentPoint[0]) | ||
| 42 | + angle = np.rad2deg(angle) | ||
| 43 | + # only positive angles | ||
| 44 | + angle = np.mod(angle+360,360) | ||
| 45 | + #print NearestPoint[0], NearestPoint[1], angle | ||
| 46 | + angles[i] = angle | ||
| 47 | + i=i+1 | ||
| 48 | + return kNearestPoints[np.argsort(angles)] | ||
| 49 | + | ||
| 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 | + | ||
| 72 | +def removePoint(dataset, point): | ||
| 73 | + delmask = [np.logical_or(dataset[:,0]!=point[0],dataset[:,1]!=point[1])] | ||
| 74 | + newdata = dataset[delmask] | ||
| 75 | + return newdata | ||
| 76 | + | ||
| 77 | + | ||
| 78 | +def concaveHull(dataset, k): | ||
| 79 | + assert k >= 3, 'k has to be greater or equal to 3.' | ||
| 80 | + points = dataset | ||
| 81 | + # todo: remove duplicate points from dataset | ||
| 82 | + # todo: check if dataset consists of only 3 or less points | ||
| 83 | + # todo: make sure that enough points for a given k can be found | ||
| 84 | + | ||
| 85 | + firstpoint = GetFirstPoint(points) | ||
| 86 | + # init hull as list to easily append stuff | ||
| 87 | + hull = [] | ||
| 88 | + # add first point to hull | ||
| 89 | + hull.append(firstpoint) | ||
| 90 | + # and remove it from dataset | ||
| 91 | + points = removePoint(points,firstpoint) | ||
| 92 | + currentPoint = firstpoint | ||
| 93 | + # set prevPoint to a Point righ of currentpoint (angle=0) | ||
| 94 | + prevPoint = (currentPoint[0]+10, currentPoint[1]) | ||
| 95 | + step = 2 | ||
| 96 | + | ||
| 97 | + while ( (not np.array_equal(firstpoint, currentPoint) or (step==2)) and points.size > 0 ): | ||
| 98 | + if ( step == 5 ): # we're far enough to close too early | ||
| 99 | + points = np.append(points, [firstpoint], axis=0) | ||
| 100 | + kNearestPoints = GetNearestNeighbors(points, currentPoint, k) | ||
| 101 | + cPoints = SortByAngle(kNearestPoints, currentPoint, prevPoint) | ||
| 102 | + # avoid intersections: select first candidate that does not intersect any | ||
| 103 | + # polygon edge | ||
| 104 | + its = True | ||
| 105 | + i = 0 | ||
| 106 | + while ( (its==True) and (i<cPoints.shape[0]) ): | ||
| 107 | + i=i+1 | ||
| 108 | + if ( np.array_equal(cPoints[i-1], firstpoint) ): | ||
| 109 | + lastPoint = 1 | ||
| 110 | + else: | ||
| 111 | + lastPoint = 0 | ||
| 112 | + j = 2 | ||
| 113 | + its = False | ||
| 114 | + while ( (its==False) and (j<np.shape(hull)[0]-lastPoint) ): | ||
| 115 | + its = li.doLinesIntersect(hull[step-1-1], cPoints[i-1], | ||
| 116 | + hull[step-1-j-1],hull[step-j-1]) | ||
| 117 | + j=j+1 | ||
| 118 | + if ( its==True ): | ||
| 119 | + print("all candidates intersect -- restarting with k = ",k+1) | ||
| 120 | + return concaveHull(dataset,k+1) | ||
| 121 | + prevPoint = currentPoint | ||
| 122 | + currentPoint = cPoints[i-1] | ||
| 123 | + # add current point to hull | ||
| 124 | + hull.append(currentPoint) | ||
| 125 | + points = removePoint(points,currentPoint) | ||
| 126 | + step = step+1 | ||
| 127 | + # check if all points are inside the hull | ||
| 128 | + p = Path(hull) | ||
| 129 | + pContained = p.contains_points(dataset, radius=0.0000000001) | ||
| 130 | + if (not pContained.all()): | ||
| 131 | + print("not all points of dataset contained in hull -- restarting with k = ",k+1) | ||
| 132 | + return concaveHull(dataset, k+1) | ||
| 133 | + | ||
| 134 | + print("finished with k = ",k) | ||
| 135 | + return hull | ||
| 136 | + | ||
| 137 | + | ||
| 138 | + | ||
| 139 | +if __name__ == '__main__': | ||
| 140 | + | ||
| 141 | + | ||
| 142 | + | ||
| 143 | + points_E = np.array([[1,1],[2,1],[3,1],[4,1],[5,1],[6,1],[6,2],[6,3],[5,3],[4,3], | ||
| 144 | + [3,3],[3,4],[3,5],[4,5],[5,5],[5,6],[5,7],[4,7],[3,7],[3,8], | ||
| 145 | + [3,9],[4,9],[5,9],[6,9],[6,10],[6,11],[5,11],[4,11],[3,11],[2,11], | ||
| 146 | + [1,11],[1,10],[1,9],[1,8],[1,7],[1,6],[1,5],[1,4],[1,3],[1,2], | ||
| 147 | + [5,2],[4,2],[3,2],[2,2],[2,3],[2,4],[2,5],[2,6],[2,7],[2,8], | ||
| 148 | + [2,9],[2,10],[3,10],[4,10],[5,10],[3,6],[4,6],[5,6],[4.5,7],[3,8.5], | ||
| 149 | + ]) | ||
| 150 | + | ||
| 151 | + print(concaveHull(points_E, 3)) | ||
| 152 | + | ||
| 153 | + |
test/zonghe/Delauney.py
0 → 100644
| 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 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +class DelauneyNode: | ||
| 16 | + | ||
| 17 | + def __init__(self, rp): | ||
| 18 | + self.rp = rp | ||
| 19 | + self.children_nodes = list() | ||
| 20 | + self.children_delauney_lines = list() | ||
| 21 | + | ||
| 22 | + def get_all_node(self): | ||
| 23 | + for node in self.children_nodes: | ||
| 24 | + yield node.get_all_node() | ||
| 25 | + yield self | ||
| 26 | + | ||
| 27 | + def get_rps(self): | ||
| 28 | + for node in self.children_nodes: | ||
| 29 | + for rp in node.get_rps(): | ||
| 30 | + yield rp | ||
| 31 | + yield self.rp | ||
| 32 | + | ||
| 33 | + def get_polygons(self): | ||
| 34 | + for node in self.children_nodes: | ||
| 35 | + for rp in node.get_rps(): | ||
| 36 | + yield rp.polygon | ||
| 37 | + yield self.rp.polygon | ||
| 38 | + | ||
| 39 | + def get_delauney_lines(self): | ||
| 40 | + for node in self.children_nodes: | ||
| 41 | + for ll in node.get_delauney_lines(): | ||
| 42 | + yield ll | ||
| 43 | + for l in self.children_delauney_lines: | ||
| 44 | + yield l | ||
| 45 | + | ||
| 46 | + def add_children(self,node,delauney_line): | ||
| 47 | + self.children_nodes.append(node) | ||
| 48 | + self.children_delauney_lines.append(delauney_line) | ||
| 49 | + | ||
| 50 | +class DelauneyLine: | ||
| 51 | + | ||
| 52 | + def __init__(self,rp1,rp2): | ||
| 53 | + | ||
| 54 | + self.rp1 = rp1 | ||
| 55 | + self.rp2 = rp2 | ||
| 56 | + self.distance = rp1.polygon.Distance(rp2.polygon) | ||
| 57 | + | ||
| 58 | + self.line = ogr.Geometry(ogr.wkbLineString) | ||
| 59 | + self.line.AddPoint(self.rp1.point.GetX(),self.rp1.point.GetY()) | ||
| 60 | + self.line.AddPoint(self.rp2.point.GetX(),self.rp2.point.GetY()) | ||
| 61 | + | ||
| 62 | + | ||
| 63 | +class DelauneyMinTree: | ||
| 64 | + | ||
| 65 | + def __init__(self): | ||
| 66 | + self.delauney_lines_list = list() | ||
| 67 | + self.rps = set() | ||
| 68 | + | ||
| 69 | + def append(self,delauney_line): | ||
| 70 | + # self.delauney_lines.add(delauney_line) | ||
| 71 | + | ||
| 72 | + self.rps.add(delauney_line.rp1) | ||
| 73 | + self.rps.add(delauney_line.rp2) | ||
| 74 | + | ||
| 75 | + self.delauney_lines_list.append(delauney_line) | ||
| 76 | + | ||
| 77 | + def get_rps(self): | ||
| 78 | + return self.rps | ||
| 79 | + | ||
| 80 | + def get_other_relate_delauney_lines(self,other_delauney_lines_kv): | ||
| 81 | + other_relate_delauney_lines = [] | ||
| 82 | + for rp in self.rps: | ||
| 83 | + other_relate_delauney_lines.extend(other_delauney_lines_kv.get(rp)) | ||
| 84 | + return other_relate_delauney_lines | ||
| 85 | + | ||
| 86 | + def get_other_rp(self,delauney_line): | ||
| 87 | + rp1 = delauney_line.rp1 | ||
| 88 | + rp2 = delauney_line.rp2 | ||
| 89 | + | ||
| 90 | + if not self.rps.__contains__(rp1): | ||
| 91 | + return rp1 | ||
| 92 | + if not self.rps.__contains__(rp2): | ||
| 93 | + return rp2 | ||
| 94 | + return None | ||
| 95 | + | ||
| 96 | + | ||
| 97 | + |
test/zonghe/RepresentPoint.py
0 → 100644
| 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 | +class RepresentPoint: | ||
| 12 | + | ||
| 13 | + def __init__(self,point,polygon): | ||
| 14 | + self.point = point | ||
| 15 | + self.polygon = polygon |
test/zonghe/ShapeData.py
0 → 100644
| 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, 0) | ||
| 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.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645: | ||
| 32 | + polygons.append(geom) | ||
| 33 | + if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642: | ||
| 34 | + for i in range(geom.GetGeometryCount()): | ||
| 35 | + polygons.append(geom.GetGeometryRef(i)) | ||
| 36 | + return polygons | ||
| 37 | + | ||
| 38 | + def close(self): | ||
| 39 | + self.ds.Destroy() | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + @classmethod | ||
| 45 | + def create_by_layer(cls,path,layer:Layer): | ||
| 46 | + data_source: DataSource = cls.driver.CreateDataSource(path) | ||
| 47 | + data_source.CopyLayer(layer,layer.GetName()) | ||
| 48 | + data_source.Destroy() | ||
| 49 | + | ||
| 50 | + @classmethod | ||
| 51 | + def create_by_scheme(cls,path,name,sr,geo_type,scheme,features): | ||
| 52 | + data_source: DataSource = cls.driver.CreateDataSource(path) | ||
| 53 | + layer :Layer = data_source.CreateLayer(name, sr, geo_type) | ||
| 54 | + if scheme: | ||
| 55 | + layer.CreateFields(scheme) | ||
| 56 | + for feature in features: | ||
| 57 | + layer.CreateFeature(feature) | ||
| 58 | + data_source.Destroy() | ||
| 59 | + | ||
| 60 | + @classmethod | ||
| 61 | + def create_point(cls,path,name,point): | ||
| 62 | + data_source: DataSource = cls.driver.CreateDataSource(path) | ||
| 63 | + layer :Layer = data_source.CreateLayer(name, None, ogr.wkbPoint) | ||
| 64 | + | ||
| 65 | + feat_new = ogr.Feature(layer.GetLayerDefn()) | ||
| 66 | + feat_new.SetGeometry(point) | ||
| 67 | + layer.CreateFeature(feat_new) | ||
| 68 | + data_source.Destroy() | ||
| 69 | + | ||
| 70 | + @classmethod | ||
| 71 | + def create_shp_fromwkts(cls,path,name,wkts): | ||
| 72 | + | ||
| 73 | + geo_type = None | ||
| 74 | + geoms = [] | ||
| 75 | + for wkt in wkts: | ||
| 76 | + geom : Geometry = ogr.CreateGeometryFromWkt(wkt) | ||
| 77 | + if geo_type is None: | ||
| 78 | + geo_type = geom.GetGeometryType() | ||
| 79 | + geoms.append(geom) | ||
| 80 | + | ||
| 81 | + if os.path.exists(path): | ||
| 82 | + | ||
| 83 | + pre_name = ".".join(path.split(".")[0:-1]) | ||
| 84 | + for bac in ["dbf","prj","cpg","shp","shx","sbn","sbx"]: | ||
| 85 | + try: | ||
| 86 | + os.remove(pre_name+"."+bac) | ||
| 87 | + except Exception as e: | ||
| 88 | + pass | ||
| 89 | + | ||
| 90 | + data_source: DataSource = cls.driver.CreateDataSource(path) | ||
| 91 | + layer :Layer = data_source.CreateLayer(name, None, geo_type) | ||
| 92 | + | ||
| 93 | + for geom in geoms: | ||
| 94 | + feat_new = ogr.Feature(layer.GetLayerDefn()) | ||
| 95 | + feat_new.SetGeometry(geom) | ||
| 96 | + layer.CreateFeature(feat_new) | ||
| 97 | + data_source.Destroy() |
test/zonghe/Util.py
0 → 100644
| 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 | + | ||
| 12 | +class Util: | ||
| 13 | + @classmethod | ||
| 14 | + def envelop_2_polygon(cls,env): | ||
| 15 | + ring = ogr.Geometry(ogr.wkbLinearRing) | ||
| 16 | + ring.AddPoint(env[0], env[2]) | ||
| 17 | + ring.AddPoint(env[0], env[3]) | ||
| 18 | + ring.AddPoint(env[1], env[3]) | ||
| 19 | + ring.AddPoint(env[1], env[2]) | ||
| 20 | + ring.AddPoint(env[0], env[2]) | ||
| 21 | + # Create polygon | ||
| 22 | + poly = ogr.Geometry(ogr.wkbPolygon) | ||
| 23 | + poly.AddGeometry(ring) | ||
| 24 | + return poly |
test/zonghe/Zonghe.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 | + | ||
| 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 | + | ||
| 20 | +class Zonghe: | ||
| 21 | + | ||
| 22 | + data:ShapeData | ||
| 23 | + area_threshold = 100.0 | ||
| 24 | + buffer_threshold = 100.0 | ||
| 25 | + distance_buffer_threshold = 2.114691025217302e-04 | ||
| 26 | + | ||
| 27 | + def __init__(self,data): | ||
| 28 | + self.data = data | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + #只处理Polygon,MultiPolygon要拆开 | ||
| 32 | + def get_polygon_reprecent_point(self,polygon:Geometry): | ||
| 33 | + | ||
| 34 | + polygon_env = polygon.GetEnvelope() | ||
| 35 | + | ||
| 36 | + area_thre = polygon.GetArea()/self.area_threshold | ||
| 37 | + | ||
| 38 | + line_length = math.sqrt(math.pow(polygon_env[1] - polygon_env[0],2) + math.pow(polygon_env[3] - polygon_env[2],2)) | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2]) | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + center:Geometry = polygon.Centroid() | ||
| 46 | + # print(center) | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + # 提前return | ||
| 50 | + if polygon.Contains(center): | ||
| 51 | + # print("\"" + center.ExportToWkt() + "\",") | ||
| 52 | + return RepresentPoint(center, polygon) | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + last_state = None | ||
| 56 | + line = None | ||
| 57 | + calculate_time = 0 | ||
| 58 | + | ||
| 59 | + direction = self.get_direction(polygon, center, line_length) | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + in_hole = False | ||
| 63 | + in_hole_line = None | ||
| 64 | + | ||
| 65 | + | ||
| 66 | + #无孔Polygon | ||
| 67 | + if polygon.GetGeometryCount() == 1: | ||
| 68 | + polygon_line = ogr.ForceToLineString(polygon) | ||
| 69 | + | ||
| 70 | + # 有孔Polygon,要分2种情况 | ||
| 71 | + else: | ||
| 72 | + polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0)) | ||
| 73 | + for i in range(1,polygon.GetGeometryCount()): | ||
| 74 | + hole_line = polygon.GetGeometryRef(i) | ||
| 75 | + hole_polygon : Geometry = ogr.ForceToPolygon(hole_line) | ||
| 76 | + if hole_polygon.Contains(center): | ||
| 77 | + in_hole = True | ||
| 78 | + direction = range(0,190,10) | ||
| 79 | + in_hole_line = ogr.ForceToLineString(hole_line) | ||
| 80 | + # print("in_hole") | ||
| 81 | + | ||
| 82 | + angle1,angle2=None,None | ||
| 83 | + | ||
| 84 | + for angle in direction: | ||
| 85 | + | ||
| 86 | + if in_hole: | ||
| 87 | + line = self.get_doubleline(center.GetX(),center.GetY(),angle,line_length) | ||
| 88 | + else: | ||
| 89 | + line = self.get_line(center.GetX(),center.GetY(),angle,line_length) | ||
| 90 | + | ||
| 91 | + oneside_area, otherside_area = self.jude(polygon, line, angle, line_length) | ||
| 92 | + | ||
| 93 | + | ||
| 94 | + if last_state is None: | ||
| 95 | + | ||
| 96 | + angle2 = angle | ||
| 97 | + | ||
| 98 | + if oneside_area == 0 and otherside_area==0: | ||
| 99 | + last_state = 0 | ||
| 100 | + else: | ||
| 101 | + last_state = 1 if oneside_area < otherside_area else -1 | ||
| 102 | + else: | ||
| 103 | + | ||
| 104 | + angle1 = angle2 | ||
| 105 | + angle2 = angle | ||
| 106 | + | ||
| 107 | + if oneside_area == 0 and otherside_area==0: | ||
| 108 | + now_state = 0 | ||
| 109 | + else: | ||
| 110 | + now_state = 1 if oneside_area < otherside_area else -1 | ||
| 111 | + | ||
| 112 | + if last_state* now_state < 0: | ||
| 113 | + # print(angle) | ||
| 114 | + break | ||
| 115 | + else: | ||
| 116 | + last_state = now_state | ||
| 117 | + | ||
| 118 | + line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre) | ||
| 119 | + | ||
| 120 | + # 提前return | ||
| 121 | + if in_hole: | ||
| 122 | + | ||
| 123 | + point_intersection: Geometry = line.Intersection(in_hole_line) | ||
| 124 | + plist = [] | ||
| 125 | + for i in range(point_intersection.GetGeometryCount()): | ||
| 126 | + pi = point_intersection.GetGeometryRef(i) | ||
| 127 | + plist.append(pi) | ||
| 128 | + plist_d = [(pi,center.Distance(pi)) for pi in plist] | ||
| 129 | + plist_d.sort(key=lambda x:x[1]) | ||
| 130 | + | ||
| 131 | + nearest_point= plist_d[0][0] | ||
| 132 | + firt_short_length = short_length/20.0 | ||
| 133 | + radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length) | ||
| 134 | + # print("\"" + other_point.ExportToWkt() + "\",") | ||
| 135 | + | ||
| 136 | + | ||
| 137 | + while not polygon.Contains(other_point): | ||
| 138 | + | ||
| 139 | + firt_short_length = firt_short_length / 2 | ||
| 140 | + radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(), | ||
| 141 | + nearest_point.GetY(), firt_short_length) | ||
| 142 | + | ||
| 143 | + | ||
| 144 | + | ||
| 145 | + return RepresentPoint(other_point,polygon) | ||
| 146 | + | ||
| 147 | + | ||
| 148 | + point_intersection:Geometry = line.Intersection(polygon_line) | ||
| 149 | + xlist = [] | ||
| 150 | + ylist = [] | ||
| 151 | + plist = [] | ||
| 152 | + | ||
| 153 | + for i in range(point_intersection.GetGeometryCount()): | ||
| 154 | + pi = point_intersection.GetGeometryRef(i) | ||
| 155 | + xlist.append(pi.GetX()) | ||
| 156 | + ylist.append(pi.GetY()) | ||
| 157 | + plist.append(pi) | ||
| 158 | + | ||
| 159 | + reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0] | ||
| 160 | + | ||
| 161 | + reprecent_point = self.creat_point(reprecent_point) | ||
| 162 | + | ||
| 163 | + if not polygon.Contains(reprecent_point): | ||
| 164 | + plist_d = [(pi,center.Distance(pi)) for pi in plist] | ||
| 165 | + plist_d.sort(key=lambda x:x[1]) | ||
| 166 | + 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)) | ||
| 167 | + | ||
| 168 | + # print("\""+reprecent_point.ExportToWkt() + "\",") | ||
| 169 | + | ||
| 170 | + rp = RepresentPoint(reprecent_point,polygon) | ||
| 171 | + | ||
| 172 | + return rp | ||
| 173 | + | ||
| 174 | + | ||
| 175 | + | ||
| 176 | + | ||
| 177 | + | ||
| 178 | + def get_line(self, x0, y0 , angle, r): | ||
| 179 | + | ||
| 180 | + line: Geometry = ogr.Geometry(ogr.wkbLineString) | ||
| 181 | + line.AddPoint(x0, y0) | ||
| 182 | + hudu = angle/360.0 * 2 * math.pi | ||
| 183 | + dx = math.sin(hudu) * r | ||
| 184 | + dy = math.cos(hudu) * r | ||
| 185 | + line.AddPoint(x0+dx, y0+dy) | ||
| 186 | + | ||
| 187 | + return line | ||
| 188 | + | ||
| 189 | + def get_doubleline(self, x0, y0 , angle, r): | ||
| 190 | + | ||
| 191 | + line: Geometry = ogr.Geometry(ogr.wkbLineString) | ||
| 192 | + | ||
| 193 | + hudu = angle/360.0 * 2 * math.pi | ||
| 194 | + dx = math.sin(hudu) * r | ||
| 195 | + dy = math.cos(hudu) * r | ||
| 196 | + | ||
| 197 | + hudu = (angle+180)/360.0 * 2 * math.pi | ||
| 198 | + dx2 = math.sin(hudu) * r | ||
| 199 | + dy2 = math.cos(hudu) * r | ||
| 200 | + | ||
| 201 | + line.AddPoint(x0 + dx2, y0 + dy2) | ||
| 202 | + line.AddPoint(x0+dx, y0+dy) | ||
| 203 | + | ||
| 204 | + return line | ||
| 205 | + | ||
| 206 | + | ||
| 207 | + def get_radline(self,x0,y0,x1,y1,len_size): | ||
| 208 | + a2 = math.pow((x1-x0),2) | ||
| 209 | + b2 = math.pow((y1-y0),2) | ||
| 210 | + len_size = len_size+ math.sqrt(a2+b2) | ||
| 211 | + | ||
| 212 | + line: Geometry = ogr.Geometry(ogr.wkbLineString) | ||
| 213 | + line.AddPoint(x0, y0) | ||
| 214 | + tanx = abs(y1-y0) / abs(x1-x0) | ||
| 215 | + cosx = 1 / math.sqrt(1 + tanx *tanx) | ||
| 216 | + dx = cosx* len_size | ||
| 217 | + dy = tanx * dx | ||
| 218 | + | ||
| 219 | + if x1 == x0: | ||
| 220 | + x2 = x0 | ||
| 221 | + if y1 > y0 : | ||
| 222 | + y2 = y0 + abs(dy) | ||
| 223 | + else: | ||
| 224 | + y2 = y0 - abs(dy) | ||
| 225 | + else: | ||
| 226 | + if x1 < x0: | ||
| 227 | + x2 = x0 - dx | ||
| 228 | + else: | ||
| 229 | + x2 = x0 + dx | ||
| 230 | + | ||
| 231 | + if y1 < y0: | ||
| 232 | + y2 = y0 - dy | ||
| 233 | + else: | ||
| 234 | + y2 = y0 + dy | ||
| 235 | + | ||
| 236 | + line.AddPoint(x2, y2) | ||
| 237 | + | ||
| 238 | + other_point = ogr.Geometry(ogr.wkbPoint) | ||
| 239 | + other_point.AddPoint(x2, y2) | ||
| 240 | + | ||
| 241 | + return line , other_point | ||
| 242 | + | ||
| 243 | + def get_direction(self,polygon,center,line_length): | ||
| 244 | + ''' | ||
| 245 | + 判断旋转方向 | ||
| 246 | + :param polygon: | ||
| 247 | + :param center: | ||
| 248 | + :param line_length: | ||
| 249 | + :return: | ||
| 250 | + ''' | ||
| 251 | + | ||
| 252 | + line = self.get_line(center.GetX(),center.GetY(),0,line_length) | ||
| 253 | + | ||
| 254 | + oneside_area, otherside_area = self.jude(polygon,line,0,line_length) | ||
| 255 | + | ||
| 256 | + if oneside_area == 0 and otherside_area == 0 : | ||
| 257 | + return range(0, 390, 30) | ||
| 258 | + else: | ||
| 259 | + line = self.get_line(center.GetX(), center.GetY(), 10, line_length) | ||
| 260 | + oneside_area_contrast, otherside_area_contrast = self.jude(polygon, line, 30, line_length) | ||
| 261 | + | ||
| 262 | + if oneside_area_contrast == 0 and otherside_area_contrast == 0: | ||
| 263 | + return range(360, -30, -30) | ||
| 264 | + else: | ||
| 265 | + if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast): | ||
| 266 | + return range(0, 390, 30) | ||
| 267 | + else: | ||
| 268 | + return range(360, -30, -30) | ||
| 269 | + | ||
| 270 | + | ||
| 271 | + def jude(self,polygon,line,angle,line_length): | ||
| 272 | + | ||
| 273 | + line_buffer: Geometry = line.Buffer(line_length / self.buffer_threshold) | ||
| 274 | + clip_geom: Geometry = polygon.Difference(line_buffer) | ||
| 275 | + | ||
| 276 | + oneside_area = 0 | ||
| 277 | + otherside_area = 0 | ||
| 278 | + | ||
| 279 | + gc = clip_geom.GetGeometryCount() | ||
| 280 | + if gc <= 1: | ||
| 281 | + oneside_area = 0 | ||
| 282 | + otherside_area = 0 | ||
| 283 | + else: | ||
| 284 | + triangle1, triangle2 = self.get_side_triangle(line, angle) | ||
| 285 | + | ||
| 286 | + | ||
| 287 | + for gi in range(clip_geom.GetGeometryCount()): | ||
| 288 | + clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi) | ||
| 289 | + it = clip_geom_i.Intersection(triangle1) | ||
| 290 | + | ||
| 291 | + if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect( | ||
| 292 | + line_buffer): | ||
| 293 | + oneside_area += clip_geom_i.GetArea() | ||
| 294 | + else: | ||
| 295 | + otherside_area += clip_geom_i.GetArea() | ||
| 296 | + return oneside_area, otherside_area | ||
| 297 | + | ||
| 298 | + def division(self,polygon,center,in_hole,line_length,angle1,angle2,area_thre): | ||
| 299 | + | ||
| 300 | + mid_angle = (angle1 + angle2)/2.0 | ||
| 301 | + if in_hole: | ||
| 302 | + line = self.get_doubleline(center.GetX(), center.GetY(), mid_angle, line_length) | ||
| 303 | + else: | ||
| 304 | + line = self.get_line(center.GetX(), center.GetY(), mid_angle, line_length) | ||
| 305 | + | ||
| 306 | + one,other = self.jude(polygon,line,mid_angle,line_length) | ||
| 307 | + | ||
| 308 | + while abs(one - other) > area_thre: | ||
| 309 | + if one > other: | ||
| 310 | + if angle1 > angle2: | ||
| 311 | + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre) | ||
| 312 | + else: | ||
| 313 | + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre) | ||
| 314 | + else: | ||
| 315 | + if angle1 > angle2: | ||
| 316 | + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre) | ||
| 317 | + else: | ||
| 318 | + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre) | ||
| 319 | + return line | ||
| 320 | + | ||
| 321 | + | ||
| 322 | + def get_side_triangle(self,line:Geometry,angle): | ||
| 323 | + ''' | ||
| 324 | + 获取方向三角形 | ||
| 325 | + :param line: | ||
| 326 | + :param angle: | ||
| 327 | + :return: | ||
| 328 | + ''' | ||
| 329 | + | ||
| 330 | + start = line.GetPoint(0) | ||
| 331 | + end = line.GetPoint(1) | ||
| 332 | + | ||
| 333 | + | ||
| 334 | + angle_t = angle-30 | ||
| 335 | + hudu = angle_t/360.0 * 2 * math.pi | ||
| 336 | + | ||
| 337 | + r = line.Length() / (2*math.cos( math.pi/6)) | ||
| 338 | + dx = math.sin(hudu) * r | ||
| 339 | + dy = math.cos(hudu) * r | ||
| 340 | + | ||
| 341 | + | ||
| 342 | + ring1 = ogr.Geometry(ogr.wkbLinearRing) | ||
| 343 | + ring1.AddPoint(start[0], start[1]) | ||
| 344 | + ring1.AddPoint(start[0] + dx, start[1] + dy) | ||
| 345 | + ring1.AddPoint(end[0], end[1]) | ||
| 346 | + ring1.AddPoint(start[0], start[1]) | ||
| 347 | + triangle1 = ogr.Geometry(ogr.wkbPolygon) | ||
| 348 | + triangle1.AddGeometry(ring1) | ||
| 349 | + | ||
| 350 | + | ||
| 351 | + angle_t = angle+30 | ||
| 352 | + hudu = angle_t/360.0 * 2 * math.pi | ||
| 353 | + | ||
| 354 | + r = line.Length() / (2*math.cos( math.pi/6)) | ||
| 355 | + | ||
| 356 | + dx = math.sin(hudu) * r | ||
| 357 | + dy = math.cos(hudu) * r | ||
| 358 | + | ||
| 359 | + ring2 = ogr.Geometry(ogr.wkbLinearRing) | ||
| 360 | + ring2.AddPoint(start[0], start[1]) | ||
| 361 | + ring2.AddPoint(start[0]+dx, start[1]+dy) | ||
| 362 | + ring2.AddPoint(end[0], end[1]) | ||
| 363 | + ring2.AddPoint(start[0], start[1]) | ||
| 364 | + triangle2 = ogr.Geometry(ogr.wkbPolygon) | ||
| 365 | + triangle2.AddGeometry(ring2) | ||
| 366 | + | ||
| 367 | + return triangle1,triangle2 | ||
| 368 | + | ||
| 369 | + | ||
| 370 | + def creat_point(self,tuple): | ||
| 371 | + p: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 372 | + p.AddPoint(tuple[0], tuple[1]) | ||
| 373 | + return p | ||
| 374 | + | ||
| 375 | + | ||
| 376 | + | ||
| 377 | + | ||
| 378 | + def create_delauney(self,rps): | ||
| 379 | + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint) | ||
| 380 | + | ||
| 381 | + rp_dict = {} | ||
| 382 | + line_set = set() | ||
| 383 | + delauney_lines = [] | ||
| 384 | + | ||
| 385 | + for rp in rps: | ||
| 386 | + multipoint.AddGeometry(rp.point) | ||
| 387 | + | ||
| 388 | + rp_dict[rp.point.GetPoint(0).__str__()] = rp | ||
| 389 | + | ||
| 390 | + delauney:Geometry = multipoint.DelaunayTriangulation() | ||
| 391 | + | ||
| 392 | + for index in range(delauney.GetGeometryCount()): | ||
| 393 | + triangle = delauney.GetGeometryRef(index) | ||
| 394 | + | ||
| 395 | + triangle_line:Geometry = ogr.ForceToLineString(triangle) | ||
| 396 | + | ||
| 397 | + | ||
| 398 | + for pi in range(triangle_line.GetPointCount()-1): | ||
| 399 | + p = triangle_line.GetPoint(pi) | ||
| 400 | + p_next = triangle_line.GetPoint(pi+1) | ||
| 401 | + | ||
| 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__()) | ||
| 416 | + | ||
| 417 | + delauney_line = DelauneyLine(rp1,rp2) | ||
| 418 | + delauney_lines.append(delauney_line) | ||
| 419 | + | ||
| 420 | + return delauney_lines | ||
| 421 | + | ||
| 422 | + | ||
| 423 | + | ||
| 424 | + def create_min_delauney(self,delauney_lines,rps,polygons): | ||
| 425 | + ''' | ||
| 426 | + 使用prim算法计算最小生成树 | ||
| 427 | + :param delauney_lines: | ||
| 428 | + :param polygons: | ||
| 429 | + :return: | ||
| 430 | + ''' | ||
| 431 | + | ||
| 432 | + kv = {} | ||
| 433 | + rps_set = set(rps) | ||
| 434 | + | ||
| 435 | + for delauney_line in delauney_lines: | ||
| 436 | + if kv.get(delauney_line.rp1): | ||
| 437 | + | ||
| 438 | + kv[delauney_line.rp1].add(delauney_line) | ||
| 439 | + else: | ||
| 440 | + kv[delauney_line.rp1] = set() | ||
| 441 | + kv[delauney_line.rp1].add(delauney_line) | ||
| 442 | + | ||
| 443 | + if kv.get(delauney_line.rp2): | ||
| 444 | + | ||
| 445 | + kv[delauney_line.rp2].add(delauney_line) | ||
| 446 | + else: | ||
| 447 | + | ||
| 448 | + kv[delauney_line.rp2] = set() | ||
| 449 | + kv[delauney_line.rp2].add(delauney_line) | ||
| 450 | + | ||
| 451 | + | ||
| 452 | + #初始化树 | ||
| 453 | + delauney_lines = sorted(delauney_lines,key=lambda x:x.distance) | ||
| 454 | + | ||
| 455 | + | ||
| 456 | + delauney_min_tree = DelauneyMinTree() | ||
| 457 | + delauney_min_tree.append(delauney_lines[0]) | ||
| 458 | + | ||
| 459 | + rps_set.remove(delauney_lines[0].rp1) | ||
| 460 | + rps_set.remove(delauney_lines[0].rp2) | ||
| 461 | + kv[delauney_lines[0].rp1].remove(delauney_lines[0]) | ||
| 462 | + kv[delauney_lines[0].rp2].remove(delauney_lines[0]) | ||
| 463 | + | ||
| 464 | + | ||
| 465 | + while rps_set.__len__()>0: | ||
| 466 | + | ||
| 467 | + relate_delauney_line = delauney_min_tree.get_other_relate_delauney_lines(kv) | ||
| 468 | + | ||
| 469 | + relate_delauney_line_sort = sorted(relate_delauney_line,key=lambda x:x.distance) | ||
| 470 | + | ||
| 471 | + min_distance_line = relate_delauney_line_sort[0] | ||
| 472 | + | ||
| 473 | + #删除 | ||
| 474 | + other_rp = delauney_min_tree.get_other_rp(min_distance_line) | ||
| 475 | + if other_rp is None: | ||
| 476 | + kv[min_distance_line.rp1].remove(min_distance_line) | ||
| 477 | + kv[min_distance_line.rp2].remove(min_distance_line) | ||
| 478 | + continue | ||
| 479 | + | ||
| 480 | + delauney_min_tree.append(min_distance_line) | ||
| 481 | + | ||
| 482 | + rps_set.remove(other_rp) | ||
| 483 | + | ||
| 484 | + kv[min_distance_line.rp1].remove(min_distance_line) | ||
| 485 | + kv[min_distance_line.rp2].remove(min_distance_line) | ||
| 486 | + | ||
| 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__()) | ||
| 494 | + | ||
| 495 | + return delauney_min_tree | ||
| 496 | + | ||
| 497 | + def cut_delauney_min_tree(self,delauney_min_tree:DelauneyMinTree,threshold): | ||
| 498 | + | ||
| 499 | + trees = [] | ||
| 500 | + kv = {} | ||
| 501 | + | ||
| 502 | + count = 0 | ||
| 503 | + | ||
| 504 | + for delauney_line in delauney_min_tree.delauney_lines_list: | ||
| 505 | + | ||
| 506 | + dn1 = kv.get(delauney_line.rp1) | ||
| 507 | + dn2 = kv.get(delauney_line.rp2) | ||
| 508 | + | ||
| 509 | + | ||
| 510 | + if not dn1: | ||
| 511 | + dn1 = DelauneyNode(delauney_line.rp1) | ||
| 512 | + kv[delauney_line.rp1] = dn1 | ||
| 513 | + | ||
| 514 | + if not dn2: | ||
| 515 | + | ||
| 516 | + trees.append(dn1) | ||
| 517 | + | ||
| 518 | + dn2 = DelauneyNode(delauney_line.rp2) | ||
| 519 | + kv[delauney_line.rp2] = dn2 | ||
| 520 | + | ||
| 521 | + if delauney_line.distance < threshold: | ||
| 522 | + dn1.add_children(dn2,delauney_line) | ||
| 523 | + count +=1 | ||
| 524 | + | ||
| 525 | + else: | ||
| 526 | + #断开 | ||
| 527 | + trees.append(dn2) | ||
| 528 | + else: | ||
| 529 | + | ||
| 530 | + if delauney_line.distance < threshold: | ||
| 531 | + dn2.add_children(dn1,delauney_line) | ||
| 532 | + count += 1 | ||
| 533 | + else: | ||
| 534 | + trees.append(dn1) | ||
| 535 | + else: | ||
| 536 | + | ||
| 537 | + dn2 = DelauneyNode(delauney_line.rp2) | ||
| 538 | + kv[delauney_line.rp2] = dn2 | ||
| 539 | + | ||
| 540 | + if delauney_line.distance < threshold: | ||
| 541 | + dn1.add_children(dn2,delauney_line) | ||
| 542 | + count += 1 | ||
| 543 | + else: | ||
| 544 | + trees.append(dn2) | ||
| 545 | + | ||
| 546 | + | ||
| 547 | + return trees | ||
| 548 | + | ||
| 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 | + | ||
| 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 | ||
| 612 | + | ||
| 613 | + | ||
| 614 | + def merge2(self,trees): | ||
| 615 | + | ||
| 616 | + polygons = [] | ||
| 617 | + | ||
| 618 | + | ||
| 619 | + | ||
| 620 | + | ||
| 621 | + for tree in trees: | ||
| 622 | + | ||
| 623 | + tree_polygons = tree.get_polygons() | ||
| 624 | + | ||
| 625 | + 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 | + | ||
| 683 | + | ||
| 684 | + | ||
| 685 | + polygons.append(merge_polygon) | ||
| 686 | + | ||
| 687 | + | ||
| 688 | + return polygons | ||
| 689 | + | ||
| 690 | + def merge_circle(self): | ||
| 691 | + pass | ||
| 692 | + | ||
| 693 | + | ||
| 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 | + | ||
| 701 | + if p1_intersect_line_rep.Intersect(p2_intersect_line_rep): | ||
| 702 | + | ||
| 703 | + p1_rep_p1 = p1_intersect_line_rep.GetPoints()[0] | ||
| 704 | + p1_rep_p2 = p1_intersect_line_rep.GetPoints()[1] | ||
| 705 | + | ||
| 706 | + p2_rep_p1 = p2_intersect_line_rep.GetPoints()[0] | ||
| 707 | + p2_rep_p2 = p2_intersect_line_rep.GetPoints()[1] | ||
| 708 | + | ||
| 709 | + polygon = self.create_polygon(p1_rep_p1, p2_rep_p2, p1_rep_p2, p2_rep_p1) | ||
| 710 | + | ||
| 711 | + else: | ||
| 712 | + | ||
| 713 | + p1_rep_p1 = p1_intersect_line_rep.GetPoints()[0] | ||
| 714 | + p1_rep_p2 = p1_intersect_line_rep.GetPoints()[1] | ||
| 715 | + | ||
| 716 | + p2_rep_p1 = p2_intersect_line_rep.GetPoints()[0] | ||
| 717 | + p2_rep_p2 = p2_intersect_line_rep.GetPoints()[1] | ||
| 718 | + | ||
| 719 | + line1 = ogr.Geometry(ogr.wkbLineString) | ||
| 720 | + | ||
| 721 | + | ||
| 722 | + line1.AddPoint(p1_rep_p1[0], p1_rep_p1[1]) | ||
| 723 | + line1.AddPoint(p2_rep_p1[0], p2_rep_p1[1]) | ||
| 724 | + | ||
| 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]) | ||
| 728 | + | ||
| 729 | + if line1.Intersect(line2): | ||
| 730 | + polygon = self.create_polygon(p1_rep_p1, p1_rep_p2, p2_rep_p1, p2_rep_p2) | ||
| 731 | + 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 | ||
| 759 | + 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]) | ||
| 772 | + | ||
| 773 | + lines.append(line) | ||
| 774 | + | ||
| 775 | + return lines | ||
| 776 | + | ||
| 777 | + def process(self): | ||
| 778 | + polygons = self.data.get_polygons() | ||
| 779 | + rps = [] | ||
| 780 | + for poly in polygons: | ||
| 781 | + rp = self.get_polygon_reprecent_point(poly) | ||
| 782 | + rps.append(rp) | ||
| 783 | + | ||
| 784 | + delauney_lines = self.create_delauney(rps) | ||
| 785 | + | ||
| 786 | + min_delauney = self.create_min_delauney(delauney_lines,rps,polygons) | ||
| 787 | + | ||
| 788 | + trees = self.cut_delauney_min_tree(min_delauney,self.distance_buffer_threshold) | ||
| 789 | + | ||
| 790 | + | ||
| 791 | + polygons = self.merge(trees) | ||
| 792 | + | ||
| 793 | + for polygon in polygons: | ||
| 794 | + print("\""+polygon.ExportToWkt() + "\",") | ||
| 795 | + | ||
| 796 | +if __name__ == '__main__': | ||
| 797 | + | ||
| 798 | + | ||
| 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 | + | ||
| 814 | + zh = Zonghe(sd) | ||
| 815 | + zh.process() | ||
| 816 | + else: | ||
| 817 | + wkts = [ | ||
| 818 | + ] | ||
| 819 | + | ||
| 820 | + result = r"J:\Data\制图综合\zhonghe3.shp" | ||
| 821 | + ShapeData.create_shp_fromwkts(result,"zh",wkts) | ||
| 822 | + |
test/zonghe/__init__.py
0 → 100644
test/zonghe/lineintersect.py
0 → 100644
| 1 | +#!/bin/env python | ||
| 2 | + | ||
| 3 | +## | ||
| 4 | +## determine if two line segments intersect | ||
| 5 | +## see: martin-thoma.com/how-to-check-if-two-line-segments-intersect/ | ||
| 6 | +## | ||
| 7 | + | ||
| 8 | +import numpy as np | ||
| 9 | + | ||
| 10 | +def doBoundingBoxesIntersect(a, b, c, d): | ||
| 11 | + ''' | ||
| 12 | + Check if bounding boxes do intersect. If one bounding box touches | ||
| 13 | + the other, they do intersect. | ||
| 14 | + First segment is of points a and b, second of c and d. | ||
| 15 | + ''' | ||
| 16 | + ll1_x = min(a[0],b[0]); ll2_x = min(c[0],d[0]) | ||
| 17 | + ll1_y = min(a[1],b[1]); ll2_y = min(c[1],d[1]) | ||
| 18 | + ur1_x = max(a[0],b[0]); ur2_x = max(c[0],d[0]) | ||
| 19 | + ur1_y = max(a[1],b[1]); ur2_y = max(c[1],d[1]) | ||
| 20 | + | ||
| 21 | + return ll1_x <= ur2_x and \ | ||
| 22 | + ur1_x >= ll2_x and \ | ||
| 23 | + ll1_y <= ur2_y and \ | ||
| 24 | + ur1_y >= ll2_y | ||
| 25 | + | ||
| 26 | +def isPointOnLine(a,b,c): | ||
| 27 | + ''' | ||
| 28 | + Check if a point is on a line. | ||
| 29 | + ''' | ||
| 30 | + # move to origin | ||
| 31 | + aTmp = (0,0) | ||
| 32 | + bTmp = (b[0] - a[0], b[1] - a[1]) | ||
| 33 | + cTmp = (c[0] - a[0], c[1] - a[1]) | ||
| 34 | + r = np.cross(bTmp, cTmp) | ||
| 35 | + return np.abs(r) < 0.0000000001 | ||
| 36 | + | ||
| 37 | +def isPointRightOfLine(a,b,c): | ||
| 38 | + ''' | ||
| 39 | + Check if a point (c) is right of a line (a-b). | ||
| 40 | + If (c) is on the line, it is not right it. | ||
| 41 | + ''' | ||
| 42 | + # move to origin | ||
| 43 | + aTmp = (0,0) | ||
| 44 | + bTmp = (b[0] - a[0], b[1] - a[1]) | ||
| 45 | + cTmp = (c[0] - a[0], c[1] - a[1]) | ||
| 46 | + return np.cross(bTmp, cTmp) < 0 | ||
| 47 | + | ||
| 48 | +def lineSegmentTouchesOrCrossesLine(a,b,c,d): | ||
| 49 | + ''' | ||
| 50 | + Check if line segment (a-b) touches or crosses | ||
| 51 | + line segment (c-d). | ||
| 52 | + ''' | ||
| 53 | + return isPointOnLine(a,b,c) or \ | ||
| 54 | + isPointOnLine(a,b,d) or \ | ||
| 55 | + (isPointRightOfLine(a,b,c) ^ | ||
| 56 | + isPointRightOfLine(a,b,d)) | ||
| 57 | + | ||
| 58 | +def doLinesIntersect(a,b,c,d): | ||
| 59 | + ''' | ||
| 60 | + Check if line segments (a-b) and (c-d) intersect. | ||
| 61 | + ''' | ||
| 62 | + return doBoundingBoxesIntersect(a,b,c,d) and \ | ||
| 63 | + lineSegmentTouchesOrCrossesLine(a,b,c,d) and \ | ||
| 64 | + lineSegmentTouchesOrCrossesLine(c,d,a,b) | ||
| 65 | + | ||
| 66 | + | ||
| 67 | +############################## | ||
| 68 | +## Tests | ||
| 69 | +############################## | ||
| 70 | + | ||
| 71 | +def test_doBoundingBoxesIntersect(): | ||
| 72 | + A=(1,1); B=(2,2); C=(3,1); D=(4,2) | ||
| 73 | + assert doBoundingBoxesIntersect(A,B,C,D) == False | ||
| 74 | + A=(1,2); B=(3,4); C=(2,1); D=(4,3) | ||
| 75 | + assert doBoundingBoxesIntersect(A,B,C,D) == True | ||
| 76 | + | ||
| 77 | +def test_isPointOnLine(): | ||
| 78 | + A=(1,1); B=(3,3); C=(2,2) | ||
| 79 | + assert isPointOnLine(A,B,C) == True | ||
| 80 | + A=(1,1); B=(3,3); C=(3,2) | ||
| 81 | + assert isPointOnLine(A,B,C) == False | ||
| 82 | + | ||
| 83 | + | ||
| 84 | +def test_isPointRightOfLine(): | ||
| 85 | + A=(1,1); B=(3,3); C=(2,2) | ||
| 86 | + assert isPointRightOfLine(A,B,C) == False | ||
| 87 | + A=(1,1); B=(3,3); C=(3,2) | ||
| 88 | + assert isPointRightOfLine(A,B,C) == True | ||
| 89 | + A=(1,1); B=(3,3); C=(1,2) | ||
| 90 | + assert isPointRightOfLine(A,B,C) == False | ||
| 91 | + | ||
| 92 | +# a lot of testcases to be tested with the final function | ||
| 93 | + | ||
| 94 | +def tcase(name): | ||
| 95 | + if name == 'F1': | ||
| 96 | + return (0,0), (7,7), (3,4), (4,5), False | ||
| 97 | + elif name == 'F2': | ||
| 98 | + return (-4,4), (-2,1), (-2,3), (0,0), False | ||
| 99 | + elif name == 'F3': | ||
| 100 | + return (0,0), (0,1), (2,2), (2,3), False | ||
| 101 | + elif name == 'F4': | ||
| 102 | + return (0,0), (0,1), (2,2), (3,2), False | ||
| 103 | + elif name == 'F5': | ||
| 104 | + return (-1,-1), (2,2), (3,3), (5,5), False | ||
| 105 | + elif name == 'F6': | ||
| 106 | + return (0,0), (1,1), (2,0), (0.5,2), False | ||
| 107 | + elif name == 'F7': | ||
| 108 | + return (1,1), (4,1), (2,2), (3,2), False | ||
| 109 | + elif name == 'F8': | ||
| 110 | + return (0,5), (6,0), (2,1), (2,2), False | ||
| 111 | + elif name == 'T1': | ||
| 112 | + return (0,-2), (0,2), (-2,0), (2,0), True | ||
| 113 | + elif name == 'T2': | ||
| 114 | + return (5,5), (0,0), (1,1), (8,2), True | ||
| 115 | + elif name == 'T3': | ||
| 116 | + return (-1,0), (0,0), (-1,-1), (-1,1), True | ||
| 117 | + elif name == 'T4': | ||
| 118 | + return (0,2), (2,2), (2,0), (2,4), True | ||
| 119 | + elif name == 'T5': | ||
| 120 | + return (0,0), (5,5), (1,1), (3,3), True | ||
| 121 | + elif name == 'T6': | ||
| 122 | + return (0,0), (3,3), (0,0), (3,3), True | ||
| 123 | + | ||
| 124 | +cases = ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', | ||
| 125 | + 'T1', 'T2', 'T3', 'T4', 'T5', 'T6'] | ||
| 126 | + | ||
| 127 | +def check_intersection(name): | ||
| 128 | + A,B,C,D, result = tcase(name) | ||
| 129 | + assert doLinesIntersect(A,B,C,D) == result | ||
| 130 | + | ||
| 131 | +def test_doLinesIntersect(): | ||
| 132 | + for case in cases: | ||
| 133 | + yield check_intersection, case | ||
| 134 | + |
test/zonghe/merge.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 | + | ||
| 14 | +from test.zonghe.ShapeData import ShapeData | ||
| 15 | +from test.zonghe.ConcaveHull import concaveHull | ||
| 16 | +import numpy as np | ||
| 17 | + | ||
| 18 | +class Zonghe: | ||
| 19 | + | ||
| 20 | + data:ShapeData | ||
| 21 | + area_threshold = 100.0 | ||
| 22 | + buffer_threshold = 100.0 | ||
| 23 | + distance_buffer_threshold = 2.114691025217302e-04 | ||
| 24 | + | ||
| 25 | + def __init__(self,data): | ||
| 26 | + self.data = data | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + def creat_point(self,tuple): | ||
| 30 | + p: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 31 | + p.AddPoint(tuple[0], tuple[1]) | ||
| 32 | + return p | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + def merge2(self,p1,p2): | ||
| 37 | + | ||
| 38 | + polygons = [] | ||
| 39 | + points = [] | ||
| 40 | + | ||
| 41 | + for p in [p1,p2]: | ||
| 42 | + | ||
| 43 | + if p.GetGeometryCount() == 1: | ||
| 44 | + polygon_line: Geometry = ogr.ForceToLineString(p) | ||
| 45 | + # 有孔Polygon | ||
| 46 | + else: | ||
| 47 | + polygon_line: Geometry = ogr.ForceToLineString(p.GetGeometryRef(0)) | ||
| 48 | + | ||
| 49 | + points.extend(polygon_line.GetPoints()[:-1]) | ||
| 50 | + | ||
| 51 | + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint) | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + for p in points: | ||
| 55 | + poi = ogr.Geometry(ogr.wkbPoint) | ||
| 56 | + poi.AddPoint(p[0],p[1]) | ||
| 57 | + multipoint.AddGeometry(poi) | ||
| 58 | + | ||
| 59 | + delauney: Geometry = multipoint.DelaunayTriangulation() | ||
| 60 | + merge_polygon = None | ||
| 61 | + | ||
| 62 | + for p in delauney: | ||
| 63 | + | ||
| 64 | + p_c = p.Centroid() | ||
| 65 | + | ||
| 66 | + # print("\"" + p_c.ExportToWkt() + "\",") | ||
| 67 | + if p1.Contains(p) or p2.Contains(p): | ||
| 68 | + continue | ||
| 69 | + print("\"" + p.ExportToWkt() + "\",") | ||
| 70 | + | ||
| 71 | + | ||
| 72 | + return polygons | ||
| 73 | + | ||
| 74 | + | ||
| 75 | + def merge(self,p1,p2): | ||
| 76 | + | ||
| 77 | + | ||
| 78 | + | ||
| 79 | + if p1.GetGeometryCount() == 1: | ||
| 80 | + polygon_line1: Geometry = ogr.ForceToLineString(p1) | ||
| 81 | + # 有孔Polygon | ||
| 82 | + else: | ||
| 83 | + polygon_line1: Geometry = ogr.ForceToLineString(p1.GetGeometryRef(0)) | ||
| 84 | + | ||
| 85 | + | ||
| 86 | + p1_points = polygon_line1.GetPoints()[:-1] | ||
| 87 | + | ||
| 88 | + if p2.GetGeometryCount() == 1: | ||
| 89 | + polygon_line2: Geometry = ogr.ForceToLineString(p2) | ||
| 90 | + # 有孔Polygon | ||
| 91 | + else: | ||
| 92 | + polygon_line2: Geometry = ogr.ForceToLineString(p2.GetGeometryRef(0)) | ||
| 93 | + | ||
| 94 | + p2_points = polygon_line2.GetPoints()[:-1] | ||
| 95 | + | ||
| 96 | + | ||
| 97 | + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint) | ||
| 98 | + | ||
| 99 | + | ||
| 100 | + | ||
| 101 | + | ||
| 102 | + for p in p1_points: | ||
| 103 | + | ||
| 104 | + p_t = False | ||
| 105 | + for pp in p2_points: | ||
| 106 | + line = ogr.Geometry(ogr.wkbLineString) | ||
| 107 | + line.AddPoint(p[0], p[1]) | ||
| 108 | + line.AddPoint(pp[0], pp[1]) | ||
| 109 | + | ||
| 110 | + ggg:Geometry = line.Intersection(p1) | ||
| 111 | + | ||
| 112 | + | ||
| 113 | + if ggg.GetGeometryType() in [1,-2147483647,3001]: | ||
| 114 | + p_t = True | ||
| 115 | + break | ||
| 116 | + if p_t: | ||
| 117 | + pppp = ogr.Geometry(ogr.wkbPoint) | ||
| 118 | + pppp.AddPoint(p[0],p[1]) | ||
| 119 | + | ||
| 120 | + multipoint.AddGeometry(pppp) | ||
| 121 | + | ||
| 122 | + for p in p2_points: | ||
| 123 | + | ||
| 124 | + p_t = False | ||
| 125 | + for pp in p1_points: | ||
| 126 | + line = ogr.Geometry(ogr.wkbLineString) | ||
| 127 | + line.AddPoint(p[0], p[1]) | ||
| 128 | + line.AddPoint(pp[0], pp[1]) | ||
| 129 | + | ||
| 130 | + ggg:Geometry = line.Intersection(p2) | ||
| 131 | + | ||
| 132 | + | ||
| 133 | + if ggg.GetGeometryType() in [1,-2147483647,3001]: | ||
| 134 | + p_t = True | ||
| 135 | + break | ||
| 136 | + if p_t: | ||
| 137 | + pppp = ogr.Geometry(ogr.wkbPoint) | ||
| 138 | + pppp.AddPoint(p[0],p[1]) | ||
| 139 | + multipoint.AddGeometry(pppp) | ||
| 140 | + | ||
| 141 | + | ||
| 142 | + delauney: Geometry = multipoint.DelaunayTriangulation() | ||
| 143 | + merge_polygon = None | ||
| 144 | + | ||
| 145 | + for p in delauney: | ||
| 146 | + | ||
| 147 | + print("\"" + p.ExportToWkt() + "\",") | ||
| 148 | + | ||
| 149 | + | ||
| 150 | + | ||
| 151 | + return None | ||
| 152 | + | ||
| 153 | + def merge3(self,polygons): | ||
| 154 | + | ||
| 155 | + multi_poly = ogr.Geometry(ogr.wkbMultiPolygon) | ||
| 156 | + | ||
| 157 | + points = [] | ||
| 158 | + for poly in polygons: | ||
| 159 | + multi_poly.AddGeometry(poly) | ||
| 160 | + if poly.GetGeometryCount() == 1: | ||
| 161 | + poly_line: Geometry = ogr.ForceToLineString(poly) | ||
| 162 | + # 有孔Polygon | ||
| 163 | + else: | ||
| 164 | + poly_line: Geometry = ogr.ForceToLineString(poly.GetGeometryRef(0)) | ||
| 165 | + | ||
| 166 | + points.extend(poly_line.GetPoints()[:-1]) | ||
| 167 | + | ||
| 168 | + | ||
| 169 | + points = np.array([[p[0],p[1]] for p in points]) | ||
| 170 | + | ||
| 171 | + merge_p_line = concaveHull(points, 3) | ||
| 172 | + | ||
| 173 | + ring = ogr.Geometry(ogr.wkbLinearRing) | ||
| 174 | + | ||
| 175 | + merge_p = ogr.Geometry(ogr.wkbPolygon) | ||
| 176 | + | ||
| 177 | + | ||
| 178 | + for l in merge_p_line: | ||
| 179 | + ring.AddPoint(l[0], l[1]) | ||
| 180 | + | ||
| 181 | + ring.AddPoint(merge_p_line[0][0], merge_p_line[0][1]) | ||
| 182 | + | ||
| 183 | + merge_p.AddGeometry(ring) | ||
| 184 | + | ||
| 185 | + | ||
| 186 | + # for p in polygons: | ||
| 187 | + # | ||
| 188 | + # merge_p = merge_p.Union(p) | ||
| 189 | + # | ||
| 190 | + # | ||
| 191 | + # | ||
| 192 | + # print(merge_p) | ||
| 193 | + | ||
| 194 | + return [merge_p.ExportToWkt()] | ||
| 195 | + | ||
| 196 | + | ||
| 197 | + | ||
| 198 | + | ||
| 199 | + def merge4(self,p1,p2): | ||
| 200 | + | ||
| 201 | + polygons = [] | ||
| 202 | + points = [] | ||
| 203 | + | ||
| 204 | + mp: Geometry = ogr.Geometry(ogr.wkbMultiPolygon) | ||
| 205 | + mp.AddGeometry(p1) | ||
| 206 | + mp.AddGeometry(p2) | ||
| 207 | + | ||
| 208 | + | ||
| 209 | + delauney: Geometry = mp.DelaunayTriangulation(bOnlyEdges=True) | ||
| 210 | + merge_polygon = None | ||
| 211 | + | ||
| 212 | + for p in delauney: | ||
| 213 | + | ||
| 214 | + p_c = p.Centroid() | ||
| 215 | + | ||
| 216 | + # print("\"" + p_c.ExportToWkt() + "\",") | ||
| 217 | + # if p1.Contains(p) or p2.Contains(p): | ||
| 218 | + # continue | ||
| 219 | + print("\"" + p.ExportToWkt() + "\",") | ||
| 220 | + | ||
| 221 | + | ||
| 222 | + return polygons | ||
| 223 | + | ||
| 224 | + def merge5(self,p1:Geometry,p2): | ||
| 225 | + | ||
| 226 | + | ||
| 227 | + | ||
| 228 | + ext = p1.GetEnvelope() | ||
| 229 | + | ||
| 230 | + tor = min(ext[1]-ext[0],ext[3]-ext[2]) | ||
| 231 | + | ||
| 232 | + pp = p1.Simplify(tor/20) | ||
| 233 | + | ||
| 234 | + pp2 = p2.Simplify(tor / 20) | ||
| 235 | + | ||
| 236 | + return [pp.ExportToWkt(),pp2.ExportToWkt() ] | ||
| 237 | + | ||
| 238 | + | ||
| 239 | + def process(self): | ||
| 240 | + polygons = self.data.get_polygons() | ||
| 241 | + | ||
| 242 | + return self.merge3(polygons) | ||
| 243 | + | ||
| 244 | + | ||
| 245 | +if __name__ == '__main__': | ||
| 246 | + | ||
| 247 | + | ||
| 248 | + # print(sd.get_polygons()[0]) | ||
| 249 | + # sd.close() | ||
| 250 | + | ||
| 251 | + # create = True | ||
| 252 | + # create = False | ||
| 253 | + # | ||
| 254 | + # if create: | ||
| 255 | + # | ||
| 256 | + # sd = ShapeData(r"J:\Data\制图综合\me.shp") | ||
| 257 | + # | ||
| 258 | + # ext = sd.layer.GetExtent() | ||
| 259 | + # threshold = (ext[1]-ext[0])/20 | ||
| 260 | + # print(threshold) | ||
| 261 | + # | ||
| 262 | + # | ||
| 263 | + # zh = Zonghe(sd) | ||
| 264 | + # zh.process() | ||
| 265 | + # else: | ||
| 266 | + # 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))" | ||
| 267 | + # ] | ||
| 268 | + # result = r"J:\Data\制图综合\mes.shp" | ||
| 269 | + # ShapeData.create_shp_fromwkts(result,"zh",wkts) | ||
| 270 | + # | ||
| 271 | + | ||
| 272 | + | ||
| 273 | + sd = ShapeData(r"J:\Data\制图综合\concave.shp") | ||
| 274 | + | ||
| 275 | + ext = sd.layer.GetExtent() | ||
| 276 | + threshold = (ext[1]-ext[0])/20 | ||
| 277 | + print(threshold) | ||
| 278 | + | ||
| 279 | + | ||
| 280 | + zh = Zonghe(sd) | ||
| 281 | + wkts = zh.process() | ||
| 282 | + | ||
| 283 | + | ||
| 284 | + result = r"J:\Data\制图综合\concave_merge.shp" | ||
| 285 | + ShapeData.create_shp_fromwkts(result,"zh",wkts) | ||
| 286 | + |
| @@ -8,6 +8,7 @@ from osgeo import ogr | @@ -8,6 +8,7 @@ from osgeo import ogr | ||
| 8 | from osgeo.ogr import * | 8 | from osgeo.ogr import * |
| 9 | import math | 9 | import math |
| 10 | import os | 10 | import os |
| 11 | +import copy | ||
| 11 | os.environ["CUDA_VISIBLE_DEVICES"] = "-1" | 12 | os.environ["CUDA_VISIBLE_DEVICES"] = "-1" |
| 12 | class util: | 13 | class util: |
| 13 | @classmethod | 14 | @classmethod |
| @@ -24,6 +25,39 @@ class util: | @@ -24,6 +25,39 @@ class util: | ||
| 24 | return poly | 25 | return poly |
| 25 | 26 | ||
| 26 | 27 | ||
| 28 | +class RepresentPoint(Geometry): | ||
| 29 | + user_data = None | ||
| 30 | + def SetUserData(self,object): | ||
| 31 | + self.user_data = object | ||
| 32 | + def GetUserData(self): | ||
| 33 | + return self.user_data | ||
| 34 | + | ||
| 35 | +class DelauneyNode: | ||
| 36 | + | ||
| 37 | + point = None | ||
| 38 | + node = None | ||
| 39 | + children_nodes = [] | ||
| 40 | + children_nodes_distance = [] | ||
| 41 | + polygon = None | ||
| 42 | + | ||
| 43 | + def __init__(self, point): | ||
| 44 | + self.point = point | ||
| 45 | + | ||
| 46 | + def get_all_node(self): | ||
| 47 | + for node in self.children_nodes: | ||
| 48 | + yield node.get_all_node() | ||
| 49 | + yield self.node | ||
| 50 | + | ||
| 51 | + | ||
| 52 | + def cut_tree(self,threshold): | ||
| 53 | + | ||
| 54 | + trees = [] | ||
| 55 | + | ||
| 56 | + for node in self.children_nodes: | ||
| 57 | + yield node.get_all_node() | ||
| 58 | + yield self.node | ||
| 59 | + | ||
| 60 | + | ||
| 27 | class ShapeUtil: | 61 | class ShapeUtil: |
| 28 | 62 | ||
| 29 | driver = ogr.GetDriverByName("ESRI Shapefile") | 63 | driver = ogr.GetDriverByName("ESRI Shapefile") |
| @@ -88,7 +122,7 @@ class ShapeData: | @@ -88,7 +122,7 @@ class ShapeData: | ||
| 88 | 122 | ||
| 89 | def __init__(self,path): | 123 | def __init__(self,path): |
| 90 | driver: Driver = ogr.GetDriverByName("ESRI Shapefile") | 124 | driver: Driver = ogr.GetDriverByName("ESRI Shapefile") |
| 91 | - self.ds: DataSource = driver.Open(path, 1) | 125 | + self.ds: DataSource = driver.Open(path, 0) |
| 92 | if not self.ds: | 126 | if not self.ds: |
| 93 | raise Exception("打开数据失败!") | 127 | raise Exception("打开数据失败!") |
| 94 | self.layer: Layer = self.ds.GetLayer(0) | 128 | self.layer: Layer = self.ds.GetLayer(0) |
| @@ -99,7 +133,7 @@ class ShapeData: | @@ -99,7 +133,7 @@ class ShapeData: | ||
| 99 | polygons = [] | 133 | polygons = [] |
| 100 | for feature in self.layer: | 134 | for feature in self.layer: |
| 101 | f:Feature = feature | 135 | f:Feature = feature |
| 102 | - geom : Geometry = f.GetGeometryRef() | 136 | + geom : Geometry = copy.deepcopy(f.GetGeometryRef()) |
| 103 | if geom.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645: | 137 | if geom.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645: |
| 104 | polygons.append(geom) | 138 | polygons.append(geom) |
| 105 | if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642: | 139 | if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642: |
| @@ -114,7 +148,7 @@ class ShapeData: | @@ -114,7 +148,7 @@ class ShapeData: | ||
| 114 | class Zonghe: | 148 | class Zonghe: |
| 115 | 149 | ||
| 116 | data:ShapeData | 150 | data:ShapeData |
| 117 | - area_threshold = 20.0 | 151 | + area_threshold = 100.0 |
| 118 | buffer_threshold = 100.0 | 152 | buffer_threshold = 100.0 |
| 119 | 153 | ||
| 120 | def __init__(self,data): | 154 | def __init__(self,data): |
| @@ -127,12 +161,20 @@ class Zonghe: | @@ -127,12 +161,20 @@ class Zonghe: | ||
| 127 | 161 | ||
| 128 | polygon_env = polygon.GetEnvelope() | 162 | polygon_env = polygon.GetEnvelope() |
| 129 | 163 | ||
| 130 | - line_length = max(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2]) | 164 | + area_thre = polygon.GetArea()/self.area_threshold |
| 165 | + | ||
| 166 | + # line_length = max(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2]) | ||
| 167 | + | ||
| 168 | + line_length = math.sqrt(math.pow(polygon_env[1] - polygon_env[0],2) + math.pow(polygon_env[3] - polygon_env[2],2)) | ||
| 131 | 169 | ||
| 132 | 170 | ||
| 133 | short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2]) | 171 | short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2]) |
| 134 | 172 | ||
| 173 | + | ||
| 174 | + | ||
| 135 | center:Geometry = polygon.Centroid() | 175 | center:Geometry = polygon.Centroid() |
| 176 | + # print(center) | ||
| 177 | + | ||
| 136 | 178 | ||
| 137 | # 提前return | 179 | # 提前return |
| 138 | if polygon.Contains(center): | 180 | if polygon.Contains(center): |
| @@ -141,7 +183,10 @@ class Zonghe: | @@ -141,7 +183,10 @@ class Zonghe: | ||
| 141 | last_state = None | 183 | last_state = None |
| 142 | line = None | 184 | line = None |
| 143 | calculate_time = 0 | 185 | calculate_time = 0 |
| 186 | + | ||
| 144 | direction = self.get_direction(polygon, center, line_length) | 187 | direction = self.get_direction(polygon, center, line_length) |
| 188 | + | ||
| 189 | + # print(direction) | ||
| 145 | in_hole = False | 190 | in_hole = False |
| 146 | in_hole_line = None | 191 | in_hole_line = None |
| 147 | 192 | ||
| @@ -160,9 +205,9 @@ class Zonghe: | @@ -160,9 +205,9 @@ class Zonghe: | ||
| 160 | in_hole = True | 205 | in_hole = True |
| 161 | direction = range(0,190,10) | 206 | direction = range(0,190,10) |
| 162 | in_hole_line = ogr.ForceToLineString(hole_line) | 207 | in_hole_line = ogr.ForceToLineString(hole_line) |
| 163 | - print("in_hole") | ||
| 164 | - | 208 | + # print("in_hole") |
| 165 | 209 | ||
| 210 | + angle1,angle2=None,None | ||
| 166 | 211 | ||
| 167 | for angle in direction: | 212 | for angle in direction: |
| 168 | 213 | ||
| @@ -171,45 +216,41 @@ class Zonghe: | @@ -171,45 +216,41 @@ class Zonghe: | ||
| 171 | else: | 216 | else: |
| 172 | line = self.get_line(center.GetX(),center.GetY(),angle,line_length) | 217 | line = self.get_line(center.GetX(),center.GetY(),angle,line_length) |
| 173 | 218 | ||
| 174 | - line_buffer:Geometry = line.Buffer(line_length / self.buffer_threshold) | ||
| 175 | - clip_geom: Geometry = polygon.Difference(line_buffer) | 219 | + oneside_area, otherside_area = self.jude(polygon, line, angle, line_length) |
| 220 | + # print(oneside_area, otherside_area) | ||
| 176 | 221 | ||
| 177 | - oneside_area = 0 | ||
| 178 | - otherside_area = 0 | 222 | + # print("\"" + line.ExportToWkt() + "\",") |
| 179 | 223 | ||
| 180 | - gc = clip_geom.GetGeometryCount() | ||
| 181 | - if gc <= 1: | ||
| 182 | - oneside_area = 0 | ||
| 183 | - otherside_area = 0 | ||
| 184 | - else: | ||
| 185 | - calculate_time += 1 | ||
| 186 | - triangle1, triangle2 = self.get_side_triangle(line, angle) | ||
| 187 | - | ||
| 188 | - for gi in range(clip_geom.GetGeometryCount()): | ||
| 189 | - clip_geom_i :Geometry = clip_geom.GetGeometryRef(gi) | ||
| 190 | - it = clip_geom_i.Intersection(triangle1) | ||
| 191 | - | ||
| 192 | - if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect(line_buffer): | ||
| 193 | - oneside_area += clip_geom_i.GetArea() | ||
| 194 | - else: | ||
| 195 | - otherside_area += clip_geom_i.GetArea() | ||
| 196 | - print(oneside_area,otherside_area) | ||
| 197 | if last_state is None: | 224 | if last_state is None: |
| 225 | + | ||
| 226 | + angle2 = angle | ||
| 227 | + | ||
| 198 | if oneside_area == 0 and otherside_area==0: | 228 | if oneside_area == 0 and otherside_area==0: |
| 199 | last_state = 0 | 229 | last_state = 0 |
| 200 | else: | 230 | else: |
| 201 | last_state = 1 if oneside_area < otherside_area else -1 | 231 | last_state = 1 if oneside_area < otherside_area else -1 |
| 202 | else: | 232 | else: |
| 233 | + | ||
| 234 | + angle1 = angle2 | ||
| 235 | + angle2 = angle | ||
| 236 | + | ||
| 203 | if oneside_area == 0 and otherside_area==0: | 237 | if oneside_area == 0 and otherside_area==0: |
| 204 | now_state = 0 | 238 | now_state = 0 |
| 205 | else: | 239 | else: |
| 206 | now_state = 1 if oneside_area < otherside_area else -1 | 240 | now_state = 1 if oneside_area < otherside_area else -1 |
| 207 | 241 | ||
| 208 | if last_state* now_state < 0: | 242 | if last_state* now_state < 0: |
| 243 | + # print(angle) | ||
| 209 | break | 244 | break |
| 210 | else: | 245 | else: |
| 211 | last_state = now_state | 246 | last_state = now_state |
| 212 | 247 | ||
| 248 | + | ||
| 249 | + # print("start division") | ||
| 250 | + # print(angle1, angle2) | ||
| 251 | + | ||
| 252 | + line = self.division(polygon, center, in_hole, line_length, angle1, angle2, area_thre) | ||
| 253 | + | ||
| 213 | # 提前return | 254 | # 提前return |
| 214 | if in_hole: | 255 | if in_hole: |
| 215 | # print(line) | 256 | # print(line) |
| @@ -232,14 +273,14 @@ class Zonghe: | @@ -232,14 +273,14 @@ class Zonghe: | ||
| 232 | 273 | ||
| 233 | radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length) | 274 | radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length) |
| 234 | 275 | ||
| 235 | - print(other_point) | 276 | + # print(other_point) |
| 236 | 277 | ||
| 237 | while not polygon.Contains(other_point): | 278 | while not polygon.Contains(other_point): |
| 238 | firt_short_length = firt_short_length / 2 | 279 | firt_short_length = firt_short_length / 2 |
| 239 | radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(), | 280 | radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(), |
| 240 | nearest_point.GetY(), firt_short_length) | 281 | nearest_point.GetY(), firt_short_length) |
| 241 | 282 | ||
| 242 | - print("return hole_rep") | 283 | + # print("return hole_rep") |
| 243 | 284 | ||
| 244 | return other_point | 285 | return other_point |
| 245 | 286 | ||
| @@ -264,60 +305,33 @@ class Zonghe: | @@ -264,60 +305,33 @@ class Zonghe: | ||
| 264 | plist_d.sort(key=lambda x:x[1]) | 305 | plist_d.sort(key=lambda x:x[1]) |
| 265 | 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)) | 306 | 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)) |
| 266 | 307 | ||
| 267 | - return reprecent_point | ||
| 268 | - | ||
| 269 | - | ||
| 270 | - def create_delauney(self,polygon:Geometry): | ||
| 271 | - de = polygon.DelaunayTriangulation() | ||
| 272 | - | ||
| 273 | - for i in range(de.GetGeometryCount()): | ||
| 274 | - d:Geometry = de.GetGeometryRef(i) | ||
| 275 | - | ||
| 276 | - print("\""+d.ExportToWkt()+"\",") | ||
| 277 | - | 308 | + print(reprecent_point) |
| 278 | 309 | ||
| 279 | - def create_delauney_test(self): | ||
| 280 | - | ||
| 281 | - mp:Geometry = ogr.Geometry(ogr.wkbMultiPoint) | ||
| 282 | - | ||
| 283 | - p1: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 284 | - p1.AddPoint(1,1) | ||
| 285 | - | ||
| 286 | - mp.AddGeometry(p1) | ||
| 287 | - | ||
| 288 | - p2: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 289 | - p2.AddPoint(1.5, 1.7) | ||
| 290 | - | ||
| 291 | - mp.AddGeometry(p2) | ||
| 292 | - | ||
| 293 | - | ||
| 294 | - p3: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 295 | - p3.AddPoint(2, 10) | ||
| 296 | - | ||
| 297 | - mp.AddGeometry(p3) | 310 | + return reprecent_point |
| 298 | 311 | ||
| 299 | - p4: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 300 | - p4.AddPoint(3, 5) | ||
| 301 | - mp.AddGeometry(p4) | ||
| 302 | 312 | ||
| 303 | - p5: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 304 | - p5.AddPoint(4, 2) | ||
| 305 | - mp.AddGeometry(p5) | 313 | + def create_delauney(self,points): |
| 314 | + multipoint: Geometry = ogr.Geometry(ogr.wkbMultiPoint) | ||
| 315 | + for point in points: | ||
| 316 | + multipoint.AddGeometry(point) | ||
| 317 | + delauney = multipoint.DelaunayTriangulation() | ||
| 306 | 318 | ||
| 307 | - p6: Geometry = ogr.Geometry(ogr.wkbPoint) | ||
| 308 | 319 | ||
| 309 | - p6.AddPoint(3, 1) | ||
| 310 | 320 | ||
| 311 | - mp.AddGeometry(p6) | ||
| 312 | 321 | ||
| 313 | - de = mp.DelaunayTriangulation() | ||
| 314 | 322 | ||
| 315 | - print(mp) | 323 | + # def delauney_min_tree(self,points,delauney): |
| 324 | + # lines = [] | ||
| 325 | + # for i in range(delauney.GetGeometryCount()): | ||
| 326 | + # triangle:Geometry = delauney.GetGeometryRef(i) | ||
| 327 | + # | ||
| 328 | + # triangle_line :Geometry = ogr.ForceToLineString(triangle) | ||
| 329 | + # triangle_line_points = triangle_line.GetPoints() | ||
| 330 | + # | ||
| 331 | + # distance = | ||
| 332 | + # bian1 = (triangle_line_points[0],triangle_line_points[1],) | ||
| 316 | 333 | ||
| 317 | - for i in range(de.GetGeometryCount()): | ||
| 318 | - d:Geometry = de.GetGeometryRef(i) | ||
| 319 | 334 | ||
| 320 | - print("\""+d.ExportToWkt()+"\",") | ||
| 321 | 335 | ||
| 322 | def get_line(self, x0, y0 , angle, r): | 336 | def get_line(self, x0, y0 , angle, r): |
| 323 | 337 | ||
| @@ -356,6 +370,8 @@ class Zonghe: | @@ -356,6 +370,8 @@ class Zonghe: | ||
| 356 | cosx = 1 / math.sqrt(1 + tanx *tanx) | 370 | cosx = 1 / math.sqrt(1 + tanx *tanx) |
| 357 | dx = cosx* len_size | 371 | dx = cosx* len_size |
| 358 | 372 | ||
| 373 | + | ||
| 374 | + | ||
| 359 | x2 = x1 + dx | 375 | x2 = x1 + dx |
| 360 | 376 | ||
| 361 | if x1 != x0: | 377 | if x1 != x0: |
| @@ -380,17 +396,42 @@ class Zonghe: | @@ -380,17 +396,42 @@ class Zonghe: | ||
| 380 | ''' | 396 | ''' |
| 381 | 397 | ||
| 382 | line = self.get_line(center.GetX(),center.GetY(),0,line_length) | 398 | line = self.get_line(center.GetX(),center.GetY(),0,line_length) |
| 383 | - line_buffer:Geometry = line.Buffer(line_length / self.buffer_threshold) | 399 | + |
| 400 | + oneside_area, otherside_area = self.jude(polygon,line,0,line_length) | ||
| 401 | + | ||
| 402 | + if oneside_area == 0 and otherside_area == 0 : | ||
| 403 | + return range(0, 390, 30) | ||
| 404 | + else: | ||
| 405 | + line = self.get_line(center.GetX(), center.GetY(), 10, line_length) | ||
| 406 | + oneside_area_contrast, otherside_area_contrast = self.jude(polygon, line, 30, line_length) | ||
| 407 | + | ||
| 408 | + if oneside_area_contrast == 0 and otherside_area_contrast == 0: | ||
| 409 | + return range(360, -30, -30) | ||
| 410 | + else: | ||
| 411 | + if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast): | ||
| 412 | + return range(0, 390, 30) | ||
| 413 | + else: | ||
| 414 | + return range(360, -30, -30) | ||
| 415 | + | ||
| 416 | + | ||
| 417 | + def jude(self,polygon,line,angle,line_length): | ||
| 418 | + | ||
| 419 | + line_buffer: Geometry = line.Buffer(line_length / self.buffer_threshold) | ||
| 384 | clip_geom: Geometry = polygon.Difference(line_buffer) | 420 | clip_geom: Geometry = polygon.Difference(line_buffer) |
| 385 | 421 | ||
| 386 | - gc = clip_geom.GetGeometryCount() | ||
| 387 | oneside_area = 0 | 422 | oneside_area = 0 |
| 388 | otherside_area = 0 | 423 | otherside_area = 0 |
| 389 | 424 | ||
| 425 | + gc = clip_geom.GetGeometryCount() | ||
| 390 | if gc <= 1: | 426 | if gc <= 1: |
| 391 | - return range(0,370,10) | 427 | + oneside_area = 0 |
| 428 | + otherside_area = 0 | ||
| 392 | else: | 429 | else: |
| 393 | - triangle1, triangle2 = self.get_side_triangle(line, 0) | 430 | + triangle1, triangle2 = self.get_side_triangle(line, angle) |
| 431 | + # print(angle) | ||
| 432 | + # print(line) | ||
| 433 | + # print(triangle1) | ||
| 434 | + # print(triangle2) | ||
| 394 | 435 | ||
| 395 | for gi in range(clip_geom.GetGeometryCount()): | 436 | for gi in range(clip_geom.GetGeometryCount()): |
| 396 | clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi) | 437 | clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi) |
| @@ -401,34 +442,35 @@ class Zonghe: | @@ -401,34 +442,35 @@ class Zonghe: | ||
| 401 | oneside_area += clip_geom_i.GetArea() | 442 | oneside_area += clip_geom_i.GetArea() |
| 402 | else: | 443 | else: |
| 403 | otherside_area += clip_geom_i.GetArea() | 444 | otherside_area += clip_geom_i.GetArea() |
| 445 | + return oneside_area, otherside_area | ||
| 404 | 446 | ||
| 405 | - oneside_area_contrast = 0 | ||
| 406 | - otherside_area_contrast = 0 | ||
| 407 | - | ||
| 408 | - line = self.get_line(center.GetX(), center.GetY(), 10, line_length) | ||
| 409 | - line_buffer: Geometry = line.Buffer(line_length / self.buffer_threshold) | ||
| 410 | - clip_geom: Geometry = polygon.Difference(line_buffer) | 447 | + def division(self,polygon,center,in_hole,line_length,angle1,angle2,area_thre): |
| 411 | 448 | ||
| 412 | - gc = clip_geom.GetGeometryCount() | ||
| 413 | - if gc <= 1: | ||
| 414 | - return range(360, -10, -10) | ||
| 415 | - else: | ||
| 416 | - triangle1, triangle2 = self.get_side_triangle(line, 10) | 449 | + mid_angle = (angle1 + angle2)/2.0 |
| 450 | + if in_hole: | ||
| 451 | + line = self.get_doubleline(center.GetX(), center.GetY(), mid_angle, line_length) | ||
| 452 | + else: | ||
| 453 | + line = self.get_line(center.GetX(), center.GetY(), mid_angle, line_length) | ||
| 417 | 454 | ||
| 418 | - for gi in range(clip_geom.GetGeometryCount()): | ||
| 419 | - clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi) | ||
| 420 | - it = clip_geom_i.Intersection(triangle1) | 455 | + # print("\""+line.ExportToWkt()+"\",") |
| 421 | 456 | ||
| 422 | - if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect( | ||
| 423 | - line_buffer): | ||
| 424 | - oneside_area_contrast += clip_geom_i.GetArea() | ||
| 425 | - else: | ||
| 426 | - otherside_area_contrast += clip_geom_i.GetArea() | 457 | + one,other = self.jude(polygon,line,mid_angle,line_length) |
| 458 | + # print(mid_angle) | ||
| 459 | + # print(one,other) | ||
| 427 | 460 | ||
| 428 | - if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast): | ||
| 429 | - return range(0, 370, 10) | 461 | + while abs(one - other) > area_thre: |
| 462 | + if one > other: | ||
| 463 | + if angle1 > angle2: | ||
| 464 | + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre) | ||
| 430 | else: | 465 | else: |
| 431 | - return range(360, -10, -10) | 466 | + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre) |
| 467 | + else: | ||
| 468 | + if angle1 > angle2: | ||
| 469 | + return self.division(polygon, center, in_hole, line_length, mid_angle, angle1, area_thre) | ||
| 470 | + else: | ||
| 471 | + return self.division(polygon, center, in_hole, line_length, angle2, mid_angle, area_thre) | ||
| 472 | + return line | ||
| 473 | + | ||
| 432 | 474 | ||
| 433 | def get_side_triangle(self,line:Geometry,angle): | 475 | def get_side_triangle(self,line:Geometry,angle): |
| 434 | ''' | 476 | ''' |
| @@ -483,57 +525,63 @@ class Zonghe: | @@ -483,57 +525,63 @@ class Zonghe: | ||
| 483 | p.AddPoint(tuple[0], tuple[1]) | 525 | p.AddPoint(tuple[0], tuple[1]) |
| 484 | return p | 526 | return p |
| 485 | 527 | ||
| 528 | + | ||
| 529 | + def merge(self,delauney_node:DelauneyNode): | ||
| 530 | + nodes = delauney_node.get_all_node() | ||
| 531 | + points = [node.point for node in nodes] | ||
| 532 | + | ||
| 533 | + return None | ||
| 534 | + | ||
| 535 | + | ||
| 486 | def process(self): | 536 | def process(self): |
| 487 | polygons = self.data.get_polygons() | 537 | polygons = self.data.get_polygons() |
| 538 | + | ||
| 539 | + Rps = [] | ||
| 488 | for poly in polygons: | 540 | for poly in polygons: |
| 489 | reprecent_point = self.get_polygon_reprecent_point(poly) | 541 | reprecent_point = self.get_polygon_reprecent_point(poly) |
| 490 | - print(reprecent_point) | 542 | + |
| 491 | 543 | ||
| 492 | 544 | ||
| 493 | 545 | ||
| 494 | if __name__ == '__main__': | 546 | if __name__ == '__main__': |
| 495 | 547 | ||
| 496 | - # sd = ShapeData(r"J:\Data\矢量数据\佛山\制图综合.shp") | 548 | + |
| 497 | # print(sd.get_polygons()[0]) | 549 | # print(sd.get_polygons()[0]) |
| 498 | # sd.close() | 550 | # sd.close() |
| 499 | 551 | ||
| 500 | create = True | 552 | create = True |
| 501 | - create = False | 553 | + # create = False |
| 502 | 554 | ||
| 503 | if create: | 555 | if create: |
| 504 | 556 | ||
| 505 | - driver: Driver = ogr.GetDriverByName("ESRI Shapefile") | ||
| 506 | - ds: DataSource = driver.Open(r"J:\Data\制图综合\t1.shp",0) | ||
| 507 | - | ||
| 508 | - layer: Layer = ds.GetLayer(0) | ||
| 509 | - | ||
| 510 | - polygons = [] | ||
| 511 | - for feature in layer: | ||
| 512 | - f:Feature = feature | ||
| 513 | - geom : Geometry = f.GetGeometryRef() | ||
| 514 | - if geom.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645: | ||
| 515 | - polygons.append(geom) | ||
| 516 | - if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642: | ||
| 517 | - for i in range(geom.GetGeometryCount()): | ||
| 518 | - polygons.append(geom.GetGeometryRef(i)) | ||
| 519 | - del ds | ||
| 520 | - zh = Zonghe("d") | ||
| 521 | - pre = zh.get_polygon_reprecent_point(polygons[0]) | 557 | + # driver: Driver = ogr.GetDriverByName("ESRI Shapefile") |
| 558 | + # ds: DataSource = driver.Open(r"J:\Data\制图综合\left.shp",0) | ||
| 559 | + # | ||
| 560 | + # layer: Layer = ds.GetLayer(0) | ||
| 561 | + # | ||
| 562 | + # polygons = [] | ||
| 563 | + # for feature in layer: | ||
| 564 | + # f:Feature = feature | ||
| 565 | + # geom : Geometry = f.GetGeometryRef() | ||
| 566 | + # if geom.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645: | ||
| 567 | + # polygons.append(geom) | ||
| 568 | + # if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642: | ||
| 569 | + # for i in range(geom.GetGeometryCount()): | ||
| 570 | + # polygons.append(geom.GetGeometryRef(i)) | ||
| 571 | + # del ds | ||
| 522 | 572 | ||
| 573 | + sd = ShapeData(r"J:\Data\制图综合\t5.shp") | ||
| 574 | + zh = Zonghe(sd) | ||
| 575 | + zh.process() | ||
| 523 | 576 | ||
| 524 | 577 | ||
| 525 | - zh.create_delauney_test() | ||
| 526 | - | ||
| 527 | 578 | ||
| 528 | else: | 579 | else: |
| 529 | 580 | ||
| 530 | 581 | ||
| 531 | - wkts = ["POLYGON ((2 10 0,1 1 0,1.5 1.7 0,2 10 0))", | ||
| 532 | -"POLYGON ((2 10 0,1.5 1.7 0,3 5 0,2 10 0))", | ||
| 533 | -"POLYGON ((2 10 0,3 5 0,4 2 0,2 10 0))", | ||
| 534 | -"POLYGON ((3 1 0,4 2 0,1.5 1.7 0,3 1 0))", | ||
| 535 | -"POLYGON ((3 1 0,1.5 1.7 0,1 1 0,3 1 0))", | ||
| 536 | -"POLYGON ((1.5 1.7 0,4 2 0,3 5 0,1.5 1.7 0))",] | ||
| 537 | - result = r"J:\Data\制图综合\mpde.shp" | 582 | + wkts = ["POINT (113.211177054031 22.8681300466504)" |
| 583 | + ] | ||
| 584 | + | ||
| 585 | + result = r"J:\Data\制图综合\left_center.shp" | ||
| 538 | ShapeUtil.create_shp_fromwkts(result,"zh",wkts) | 586 | ShapeUtil.create_shp_fromwkts(result,"zh",wkts) |
| 539 | 587 |
请
注册
或
登录
后发表评论