提交 7cfdffa140d189746440185985ec92830f98d4d6

作者 nheweijun
1 个父辈 963ce9d5

2022.03.11 合并备份

1 -  
2 -from osgeo import ogr  
3 -  
4 -def envelop_2_polygon(env):  
5 - ring = ogr.Geometry(ogr.wkbLinearRing)  
6 - ring.AddPoint(env[0], env[2])  
7 - ring.AddPoint(env[0], env[3])  
8 - ring.AddPoint(env[1], env[3])  
9 - ring.AddPoint(env[1], env[2])  
10 - ring.AddPoint(env[0], env[2])  
11 - # Create polygon  
12 - poly = ogr.Geometry(ogr.wkbPolygon)  
13 - poly.AddGeometry(ring)  
14 - return poly  
15 -  
16 -  
17 -env = [1,3,1,3]  
18 -  
19 -poly = envelop_2_polygon(env)  
20 -line = ogr.Geometry(ogr.wkbLineString)  
21 -line.AddPoint(0, 2)  
22 -line.AddPoint(4, 2)  
23 -line.AddPoint(5, 2)  
24 -  
25 -print(poly)  
26 -print(line)  
27 -print(line.Simplify(1))  
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2022/3/8
  4 +#email: nheweijun@sina.com
  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 +os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
  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
  25 +
  26 +
  27 +class ShapeUtil:
  28 +
  29 + driver = ogr.GetDriverByName("ESRI Shapefile")
  30 +
  31 + @classmethod
  32 + def create_by_layer(cls,path,layer:Layer):
  33 + data_source: DataSource = cls.driver.CreateDataSource(path)
  34 + data_source.CopyLayer(layer,layer.GetName())
  35 + data_source.Destroy()
  36 +
  37 + @classmethod
  38 + def create_by_scheme(cls,path,name,sr,geo_type,scheme,features):
  39 + data_source: DataSource = cls.driver.CreateDataSource(path)
  40 + layer :Layer = data_source.CreateLayer(name, sr, geo_type)
  41 + if scheme:
  42 + layer.CreateFields(scheme)
  43 + for feature in features:
  44 + layer.CreateFeature(feature)
  45 + data_source.Destroy()
  46 +
  47 + @classmethod
  48 + def create_point(cls,path,name,point):
  49 + data_source: DataSource = cls.driver.CreateDataSource(path)
  50 + layer :Layer = data_source.CreateLayer(name, None, ogr.wkbPoint)
  51 +
  52 + feat_new = ogr.Feature(layer.GetLayerDefn())
  53 + feat_new.SetGeometry(point)
  54 + layer.CreateFeature(feat_new)
  55 + data_source.Destroy()
  56 +
  57 +
  58 +class ShapeData:
  59 +
  60 + def __init__(self,path):
  61 + driver: Driver = ogr.GetDriverByName("ESRI Shapefile")
  62 + self.ds: DataSource = driver.Open(path, 1)
  63 + if not self.ds:
  64 + raise Exception("打开数据失败!")
  65 + self.layer: Layer = self.ds.GetLayer(0)
  66 +
  67 +
  68 + def get_polygons(self):
  69 +
  70 + polygons = []
  71 + for feature in self.layer:
  72 + f:Feature = feature
  73 + geom : Geometry = f.GetGeometryRef()
  74 + if geom.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645:
  75 + polygons.append(geom)
  76 + if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642:
  77 + for i in range(geom.GetGeometryCount()):
  78 + polygons.append(geom.GetGeometryRef(i))
  79 + return polygons
  80 +
  81 + def close(self):
  82 + self.ds.Destroy()
  83 +
  84 +
  85 +class Zonghe:
  86 +
  87 + data:ShapeData
  88 + area_threshold = 10.0
  89 + buffer_threshold = 100.0
  90 +
  91 + def __init__(self,data):
  92 + self.data = data
  93 +
  94 +
  95 +
  96 + #只处理Polygon,MultiPolygon要拆开
  97 + def get_polygon_reprecent_point(self,polygon:Geometry):
  98 +
  99 + polygon_area = polygon.GetArea()
  100 +
  101 + polygon_env = polygon.GetEnvelope()
  102 +
  103 + line_length = max(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2])
  104 +
  105 + center:Geometry = polygon.Centroid()
  106 + if polygon.Contains(center):
  107 + return center
  108 +
  109 +
  110 + left_area = 0
  111 + right_area = polygon_area
  112 +
  113 + left_or_right = None
  114 + fen = False
  115 +
  116 + if polygon.GetGeometryCount() == 1:
  117 + polygon_line = ogr.ForceToLineString(polygon)
  118 + # 有孔Polygon
  119 + else:
  120 + polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  121 +
  122 + # print(len(polygon_line.GetPoints()))
  123 + point_i = 0
  124 +
  125 + line = None
  126 + next_point = polygon_line.GetPoint(point_i)
  127 + last_point = None
  128 + last_last_point = None
  129 +
  130 + angle = []
  131 +
  132 + calculate_times = 0
  133 +
  134 + while abs(left_area - right_area) > (polygon_area / self.area_threshold):
  135 + # print(calculate_times)
  136 + calculate_times += 1
  137 +
  138 + line,other_point = self.get_line(center.GetX(),center.GetY(),next_point[0],next_point[1],line_length)
  139 +
  140 + clip_geom:Geometry = polygon.Difference(line.Buffer(line_length/self.buffer_threshold))
  141 +
  142 +
  143 + if clip_geom.GetGeometryType() == 3 or clip_geom.GetGeometryType() == -2147483645:
  144 +
  145 + cl = ogr.ForceToLineString(clip_geom)
  146 + p1 = cl.GetPoint(0)
  147 + p2 = cl.GetPoint(1)
  148 + tp = [(p1[0] + p2[0])/2.0, (p1[1] + p2[1])/2.0]
  149 + # clip_geom_center = clip_geom.Centroid()
  150 +
  151 +
  152 + side_value = self.side(center,other_point,self.creat_point(tp))
  153 + if side_value > 0:
  154 + left_area = clip_geom.GetArea()
  155 + right_area = 0
  156 + else:
  157 + right_area = clip_geom.GetArea()
  158 + left_area = 0
  159 +
  160 +
  161 +
  162 + else:
  163 +
  164 + left_area = 0
  165 + right_area = 0
  166 +
  167 + for gi in range(clip_geom.GetGeometryCount()):
  168 + clip_geom_i :Geometry = clip_geom.GetGeometryRef(gi)
  169 + clip_geom_i_center = clip_geom_i.Centroid()
  170 + side_value = self.side(center, other_point, clip_geom_i_center)
  171 +
  172 + if side_value > 0:
  173 + left_area += clip_geom_i.GetArea()
  174 + else:
  175 + right_area += clip_geom_i.GetArea()
  176 +
  177 +
  178 + print(left_area,right_area)
  179 +
  180 + last_last_point = last_point
  181 + last_point = next_point
  182 + left_or_right = 1 if left_area > right_area else -1
  183 +
  184 +
  185 + # 进入二分法步骤
  186 + if fen:
  187 +
  188 + alternate:Geometry = ogr.Geometry(ogr.wkbPoint)
  189 + alternate.AddPoint(angle[0][0],angle[0][1])
  190 + # print(angle)
  191 + alternate_side = self.side(center, other_point, alternate)
  192 + print(alternate_side)
  193 + if left_or_right * alternate_side > 0:
  194 + angle = [angle[0],next_point]
  195 + next_point = ((next_point[0]+angle[0][0])/2.0,(next_point[1]+angle[0][1])/2.0)
  196 +
  197 + # print(abs(next_point[0]-angle[0][0]))
  198 + else:
  199 + angle = [angle[1],next_point]
  200 + next_point = ((next_point[0]+angle[1][0])/2.0,(next_point[1]+angle[1][1])/2.0)
  201 +
  202 + # print(abs(next_point[0] - angle[1][0]))
  203 +
  204 + else:
  205 + # print(point_i)
  206 + point_i += 1
  207 + next_point = polygon_line.GetPoint(point_i)
  208 +
  209 + next_point_side = self.side(center, other_point, self.creat_point(next_point))
  210 +
  211 + if left_or_right * next_point_side > 0 :
  212 + pass
  213 + else:
  214 + next_point = ((last_point[0]+last_last_point[0])/2.0,(last_point[1]+last_last_point[1])/2.0)
  215 + angle = [last_last_point,last_point]
  216 + fen = True
  217 +
  218 + print(calculate_times)
  219 +
  220 + point_intersection:Geometry = line.Intersection(polygon_line)
  221 +
  222 + xlist = []
  223 + ylist = []
  224 + for i in range(point_intersection.GetGeometryCount()):
  225 + pi = point_intersection.GetGeometryRef(i)
  226 + xlist.append(pi.GetX())
  227 + ylist.append(pi.GetY())
  228 +
  229 + reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0]
  230 +
  231 + return self.creat_point(reprecent_point)
  232 +
  233 +
  234 +
  235 + def get_line(self,x0,y0,x1,y1,len_size):
  236 +
  237 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  238 + line.AddPoint(x0, y0)
  239 + x2 = x0 + len_size
  240 +
  241 + if x1 != x0:
  242 + y2 = ((y1-y0)*(x2-x0))/(x1-x0) + y0
  243 + else:
  244 + x2 = x0
  245 + y2 = y0 + len_size
  246 + line.AddPoint(x2, y2)
  247 +
  248 + other_point = ogr.Geometry(ogr.wkbPoint)
  249 + other_point.AddPoint(x2, y2)
  250 +
  251 + return line, other_point
  252 + def creat_point(self,tuple):
  253 + p: Geometry = ogr.Geometry(ogr.wkbPoint)
  254 + p.AddPoint(tuple[0], tuple[1])
  255 + return p
  256 +
  257 +
  258 +
  259 + def side(self,A,B,P):
  260 +
  261 +
  262 + side = (B.GetX() - A.GetX()) * (P.GetY() - A.GetY()) - (B.GetY() - A.GetY()) * (P.GetX() - A.GetX())
  263 + return side
  264 +
  265 +
  266 +
  267 +
  268 + def process(self):
  269 + polygons = self.data.get_polygons()
  270 + for poly in polygons:
  271 + reprecent_point = self.get_polygon_reprecent_point(poly)
  272 + print(reprecent_point)
  273 +
  274 +
  275 +
  276 +if __name__ == '__main__':
  277 +
  278 + # sd = ShapeData(r"J:\Data\矢量数据\佛山\制图综合.shp")
  279 + # print(sd.get_polygons()[0])
  280 + # sd.close()
  281 +
  282 + driver: Driver = ogr.GetDriverByName("ESRI Shapefile")
  283 + ds: DataSource = driver.Open(r"J:\Data\矢量数据\佛山\制图综合\t2.shp",0)
  284 +
  285 + layer: Layer = ds.GetLayer(0)
  286 +
  287 + polygons = []
  288 + for feature in layer:
  289 + f:Feature = feature
  290 + geom : Geometry = f.GetGeometryRef()
  291 + if geom.GetGeometryType() == 3 or geom.GetGeometryType() == -2147483645:
  292 + polygons.append(geom)
  293 + if geom.GetGeometryType() == 6 or geom.GetGeometryType() == -2147483642:
  294 + for i in range(geom.GetGeometryCount()):
  295 + polygons.append(geom.GetGeometryRef(i))
  296 + del ds
  297 + zh = Zonghe("d")
  298 + pre = zh.get_polygon_reprecent_point(polygons[0])
  299 + print(pre)
  300 +
  301 + result="J:\Data\矢量数据\佛山\制图综合\zhresult.shp"
  302 + print(pre)
  303 +
  304 + ShapeUtil.create_point(result,"zh",pre)
  305 +
注册登录 后发表评论