提交 f54eb3c010c2e764ee363d46bb390eac2c134395

作者 nheweijun
1 个父辈 7cfdffa1

2022.03.11 合并备份

@@ -17,7 +17,7 @@ from app.util.component.StructurePrint import StructurePrint @@ -17,7 +17,7 @@ from app.util.component.StructurePrint import StructurePrint
17 from app.util.component.PGUtil import PGUtil 17 from app.util.component.PGUtil import PGUtil
18 import os 18 import os
19 from app.modules.monitor.schedule import start_schedule 19 from app.modules.monitor.schedule import start_schedule
20 -import requests 20 +import platform
21 21
22 class JSONEncoder(_JSONEncoder): 22 class JSONEncoder(_JSONEncoder):
23 """ 23 """
@@ -128,7 +128,7 @@ def create_app(): @@ -128,7 +128,7 @@ def create_app():
128 128
129 # 不检测https 129 # 不检测https
130 os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' 130 os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
131 -  
132 - start_schedule() 131 + if platform.system().lower() == "linux":
  132 + start_schedule()
133 return app 133 return app
134 134
@@ -13,7 +13,7 @@ import time @@ -13,7 +13,7 @@ import time
13 from app.models import SM3, AESHelper 13 from app.models import SM3, AESHelper
14 from app.util.component.StructurePrint import StructurePrint 14 from app.util.component.StructurePrint import StructurePrint
15 import traceback 15 import traceback
16 -from oauthlib import oauth2 16 +# from oauthlib import oauth2
17 import requests 17 import requests
18 from app.modules.auth.models import OAuth2Token, User, db 18 from app.modules.auth.models import OAuth2Token, User, db
19 19
@@ -37,7 +37,7 @@ class Api(ApiTemplate): @@ -37,7 +37,7 @@ class Api(ApiTemplate):
37 download_process.start() 37 download_process.start()
38 38
39 task = Task(guid=task_guid, 39 task = Task(guid=task_guid,
40 - name="下载|{}".format(self.para.get("table_name")), 40 + name="下载 | {}".format(self.para.get("table_name")),
41 create_time=datetime.datetime.now(), 41 create_time=datetime.datetime.now(),
42 state=0, 42 state=0,
43 task_type=4, 43 task_type=4,
@@ -83,7 +83,7 @@ class Api(ApiTemplate): @@ -83,7 +83,7 @@ class Api(ApiTemplate):
83 # 录入数据后台进程,录入主函数为entry 83 # 录入数据后台进程,录入主函数为entry
84 # 初始化task 84 # 初始化task
85 task = Task(guid=self.para.get("task_guid"), 85 task = Task(guid=self.para.get("task_guid"),
86 - name="入库|{}".format(self.para.get("task_name")), 86 + name="入库 | {}".format(self.para.get("task_name")),
87 create_time=datetime.datetime.now(), 87 create_time=datetime.datetime.now(),
88 state=0, 88 state=0,
89 task_type=1, 89 task_type=1,
@@ -323,6 +323,7 @@ class ThisTask: @@ -323,6 +323,7 @@ class ThisTask:
323 this_time = datetime.datetime.now() 323 this_time = datetime.datetime.now()
324 324
325 ext = layer.GetExtent() 325 ext = layer.GetExtent()
  326 +
326 if ext[0] < 360: 327 if ext[0] < 360:
327 ext = [round(e, 6) for e in ext] 328 ext = [round(e, 6) for e in ext]
328 else: 329 else:
@@ -23,7 +23,7 @@ class Api(ApiTemplate): @@ -23,7 +23,7 @@ class Api(ApiTemplate):
23 raise Exception("数据不存在!") 23 raise Exception("数据不存在!")
24 24
25 #验证权限 25 #验证权限
26 - UserCheck.verify(column.relate_table.relate_database.creator) 26 + UserCheck.verify(column.relate_table.creator)
27 27
28 try: 28 try:
29 if self.para.get("column_alias"): 29 if self.para.get("column_alias"):
@@ -35,7 +35,7 @@ class Api(ApiTemplate): @@ -35,7 +35,7 @@ class Api(ApiTemplate):
35 database = Database.query.filter_by(guid=table.database_guid).one_or_none() 35 database = Database.query.filter_by(guid=table.database_guid).one_or_none()
36 36
37 #验证权限 37 #验证权限
38 - UserCheck.verify(database.creator) 38 + UserCheck.verify(table.creator)
39 39
40 if not database: 40 if not database:
41 res["result"]=False 41 res["result"]=False
@@ -33,7 +33,7 @@ class Api(ApiTemplate): @@ -33,7 +33,7 @@ class Api(ApiTemplate):
33 return res 33 return res
34 34
35 #验证权限 35 #验证权限
36 - UserCheck.verify(table.one_or_none().relate_database.creator) 36 + UserCheck.verify(table.one_or_none().creator)
37 37
38 if self.para.__contains__("catalog_guid"): 38 if self.para.__contains__("catalog_guid"):
39 if catalog_guid is None: 39 if catalog_guid is None:
@@ -39,7 +39,7 @@ class Api(ApiTemplate): @@ -39,7 +39,7 @@ class Api(ApiTemplate):
39 refresh_process.start() 39 refresh_process.start()
40 40
41 task = Task(guid=task_guid, 41 task = Task(guid=task_guid,
42 - name="更新|{}".format(database.alias), 42 + name="更新 | {}".format(database.alias),
43 create_time=datetime.datetime.now(), 43 create_time=datetime.datetime.now(),
44 state=0, 44 state=0,
45 task_type=3, 45 task_type=3,
@@ -335,7 +335,7 @@ class Api(ApiTemplate): @@ -335,7 +335,7 @@ class Api(ApiTemplate):
335 try: 335 try:
336 # 删除表 336 # 删除表
337 if table.name not in db_tables_names: 337 if table.name not in db_tables_names:
338 - StructurePrint().print("空间表减少!") 338 + StructurePrint().print("{}空间表减少!".format(table.name))
339 sys_session.delete(table) 339 sys_session.delete(table)
340 # 修改表 340 # 修改表
341 else: 341 else:
@@ -42,7 +42,7 @@ class Api(ApiTemplate): @@ -42,7 +42,7 @@ class Api(ApiTemplate):
42 raise Exception("数据不存在!") 42 raise Exception("数据不存在!")
43 43
44 #验证权限 44 #验证权限
45 - UserCheck.verify(table.relate_database.creator) 45 + UserCheck.verify(table.creator)
46 46
47 pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) 47 pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri))
48 layer = pg_ds.GetLayerByName(table.name) 48 layer = pg_ds.GetLayerByName(table.name)
@@ -76,7 +76,7 @@ class Api(ApiTemplate): @@ -76,7 +76,7 @@ class Api(ApiTemplate):
76 76
77 77
78 task = Task(guid=task_guid, 78 task = Task(guid=task_guid,
79 - name="矢量金字塔|{}".format(table.name), 79 + name="矢量金字塔 | {}".format(table.name),
80 table_guid=table_guid, 80 table_guid=table_guid,
81 create_time=datetime.datetime.now(), 81 create_time=datetime.datetime.now(),
82 state=0, 82 state=0,
@@ -42,7 +42,7 @@ class Api(ApiTemplate): @@ -42,7 +42,7 @@ class Api(ApiTemplate):
42 raise Exception("数据不存在!") 42 raise Exception("数据不存在!")
43 43
44 #验证权限 44 #验证权限
45 - UserCheck.verify(table.relate_database.creator) 45 + UserCheck.verify(table.creator)
46 46
47 # 判断图层是否存在 47 # 判断图层是否存在
48 48
@@ -80,7 +80,7 @@ class Api(ApiTemplate): @@ -80,7 +80,7 @@ class Api(ApiTemplate):
80 80
81 task = Task(guid=task_guid, 81 task = Task(guid=task_guid,
82 # name="矢量金字塔|{},网格大小:{}".format(table.name,self.para.get("grids")), 82 # name="矢量金字塔|{},网格大小:{}".format(table.name,self.para.get("grids")),
83 - name="矢量金字塔|{}".format(table.name), 83 + name="矢量金字塔 | {}".format(table.name),
84 table_guid=table_guid, 84 table_guid=table_guid,
85 create_time=datetime.datetime.now(), 85 create_time=datetime.datetime.now(),
86 state=0, 86 state=0,
@@ -33,7 +33,7 @@ class Api(ApiTemplate): @@ -33,7 +33,7 @@ class Api(ApiTemplate):
33 33
34 34
35 task = Task(guid=task_guid, 35 task = Task(guid=task_guid,
36 - name="影像金字塔|{}".format(self.para.get("alias")), 36 + name="影像金字塔 | {}".format(self.para.get("alias")),
37 create_time=datetime.datetime.now(), 37 create_time=datetime.datetime.now(),
38 state=0, 38 state=0,
39 task_type=5, 39 task_type=5,
@@ -3,13 +3,12 @@ @@ -3,13 +3,12 @@
3 #createtime: 2021/7/19 3 #createtime: 2021/7/19
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
6 -  
7 from app.util.component.ApiTemplate import ApiTemplate 6 from app.util.component.ApiTemplate import ApiTemplate
8 -from .models import TileService,db,Service,MapService  
9 from app.util.component.ModelVisitor import ModelVisitor 7 from app.util.component.ModelVisitor import ModelVisitor
10 -from .tile_service.util.ProjectFile import ProjectFile  
11 - 8 +from .models import TileService,Service,MapService
12 from .util.ServiceType import ServiceType 9 from .util.ServiceType import ServiceType
  10 +from .util.TileProjectFile import ProjectFile
  11 +
13 class Api(ApiTemplate): 12 class Api(ApiTemplate):
14 13
15 api_name = "服务reload" 14 api_name = "服务reload"
@@ -5,9 +5,7 @@ @@ -5,9 +5,7 @@
5 5
6 6
7 from app.util.component.ApiTemplate import ApiTemplate 7 from app.util.component.ApiTemplate import ApiTemplate
8 -from app.util.component.ModelVisitor import ModelVisitor  
9 from app.util.component.FileProcess import FileProcess 8 from app.util.component.FileProcess import FileProcess
10 -from .models import Service  
11 import os 9 import os
12 10
13 class Api(ApiTemplate): 11 class Api(ApiTemplate):
@@ -3,12 +3,12 @@ @@ -3,12 +3,12 @@
3 #createtime: 2021/9/14 3 #createtime: 2021/9/14
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
  6 +import requests
  7 +import configure
6 from app.util.component.UserCheck import UserCheck 8 from app.util.component.UserCheck import UserCheck
7 from app.util.component.ApiTemplate import ApiTemplate 9 from app.util.component.ApiTemplate import ApiTemplate
8 from .models import Service,db 10 from .models import Service,db
9 -import requests  
10 from .util.ServiceType import ServiceType 11 from .util.ServiceType import ServiceType
11 -import configure  
12 12
13 class Api(ApiTemplate): 13 class Api(ApiTemplate):
14 api_name = "修改服务状态" 14 api_name = "修改服务状态"
@@ -26,20 +26,20 @@ class Api(ApiTemplate): @@ -26,20 +26,20 @@ class Api(ApiTemplate):
26 26
27 if service: 27 if service:
28 service.state = state 28 service.state = state
29 - db.session.commit()  
30 29
31 - # operate = "startService" if state == 1 else "stopService"  
32 - # server_type = "tileserver" if s_type == "电子地图" else "mapserver"  
33 - # dmap_engine_url = "{}/dmap/api/manager/{}?servicename={}&servername={}".format(configure.dmap_engine,  
34 - # operate,service.name,  
35 - # server_type)  
36 - # state_result = requests.get(dmap_engine_url)  
37 - # if state_result.status_code == 200:  
38 - # if not state_result.json().get("result"):  
39 - # raise Exception("修改服务状态失败!")  
40 - # else:  
41 - # raise Exception("修改服务状态失败!")  
42 30
  31 + operate = "startService" if state == 1 else "stopService"
  32 + server_type = "tileserver" if s_type == "电子地图" else "mapserver"
  33 + dmap_engine_url = "{}/dmap/api/manager/{}?servicename={}&servername={}".format(configure.dmap_engine,
  34 + operate,service.name,
  35 + server_type)
  36 + state_result = requests.get(dmap_engine_url)
  37 + if state_result.status_code == 200:
  38 + if state_result.json().get("status") == "false":
  39 + raise Exception("修改服务状态失败!")
  40 + else:
  41 + raise Exception("修改服务状态失败!")
  42 + db.session.commit()
43 res["result"] = True 43 res["result"] = True
44 else: 44 else:
45 raise Exception("服务不存在!") 45 raise Exception("服务不存在!")
@@ -10,7 +10,7 @@ import uuid @@ -10,7 +10,7 @@ import uuid
10 from ..models import TileService,Service,db,ServiceFunction,TileScheme 10 from ..models import TileService,Service,db,ServiceFunction,TileScheme
11 import datetime 11 import datetime
12 import requests 12 import requests
13 -from .util.ProjectFile import ProjectFile 13 +from ..util.TileProjectFile import ProjectFile
14 import json 14 import json
15 from requests import Response 15 from requests import Response
16 import configure 16 import configure
@@ -14,7 +14,7 @@ import configure @@ -14,7 +14,7 @@ import configure
14 import requests 14 import requests
15 from requests import Response 15 from requests import Response
16 import json 16 import json
17 -from .util.ProjectFile import ProjectFile 17 +from ..util.TileProjectFile import ProjectFile
18 18
19 class Api(ApiTemplate): 19 class Api(ApiTemplate):
20 20
@@ -9,7 +9,7 @@ from ..models import TileService,db,Service,MapService @@ -9,7 +9,7 @@ from ..models import TileService,db,Service,MapService
9 import configure 9 import configure
10 from app.util.component.ModelVisitor import ModelVisitor 10 from app.util.component.ModelVisitor import ModelVisitor
11 11
12 -from .util.ProjectFile import ProjectFile 12 +from ..util.TileProjectFile import ProjectFile
13 from ..util.ServiceType import ServiceType 13 from ..util.ServiceType import ServiceType
14 14
15 class Api(ApiTemplate): 15 class Api(ApiTemplate):
@@ -6,10 +6,6 @@ @@ -6,10 +6,6 @@
6 6
7 from app.util.component.ApiTemplate import ApiTemplate 7 from app.util.component.ApiTemplate import ApiTemplate
8 import os 8 import os
9 -from app.util.component.FileProcess import FileProcess  
10 -from app.util.component.SliceScheme import SliceScheme  
11 -import shutil  
12 -from app.util.component.StructurePrint import StructurePrint  
13 from flask import request 9 from flask import request
14 import uuid 10 import uuid
15 import configure 11 import configure
@@ -92,21 +92,28 @@ class GeometryAdapter: @@ -92,21 +92,28 @@ class GeometryAdapter:
92 # PolyhedralSurface = 15, 92 # PolyhedralSurface = 15,
93 # LinearRing = 101, 93 # LinearRing = 101,
94 94
  95 + # PointZ = -2147483647
  96 + # LINESTRINGZ=-2147483646
  97 + # POLYGONZ=-2147483645
  98 +
  99 + # PointZM = 3001
  100 + # LINESTRINGZM= 3002
  101 + # POLYGONZM= 3003
  102 +
95 # MultiPointZ = -2147483644 103 # MultiPointZ = -2147483644
96 # MultiLineStringZ = -2147483643 104 # MultiLineStringZ = -2147483643
97 # MultiPolygonZ = -2147483642 105 # MultiPolygonZ = -2147483642
98 106
99 - # PointZ = -2147483647  
100 - # LINESTRINGZ=-2147483646  
101 - # POLYGONZ=-2147483645 107 + # MultiPointZM = 3004
  108 + # MultiLineStringZM = 3005
  109 + # MultiPolygonZM = 3006
  110 +
102 111
103 - if raw == 4 or raw == 5 or raw == 6:  
104 - return raw - 3  
105 - elif raw == -2147483644 or raw == -2147483647: 112 + if raw in [1, 4, -2147483644, -2147483647, 3001, 3004] :
106 return 1 113 return 1
107 - elif raw == -2147483643 or raw == -2147483646: 114 + elif raw in [2, 5, -2147483643, -2147483646, 3002, 3005]:
108 return 2 115 return 2
109 - elif raw == -2147483642 or raw == -2147483645: 116 + elif raw in [3, 6, -2147483642, -2147483645, 3003, 3006] :
110 return 3 117 return 3
111 return raw 118 return raw
112 119
@@ -34,7 +34,7 @@ class SQLUtil: @@ -34,7 +34,7 @@ class SQLUtil:
34 :return: 34 :return:
35 ''' 35 '''
36 pri = session.execute("select * from information_schema.table_privileges " 36 pri = session.execute("select * from information_schema.table_privileges "
37 - "where grantee='{}' and table_name='{}' and privilege_type='{}' " 37 + "where grantee='{}' and table_name='{}' and privilege_type='{}' and table_schema='public' "
38 .format(user,table_name,pri_type)).fetchall() 38 .format(user,table_name,pri_type)).fetchall()
39 if len(pri) == 1: 39 if len(pri) == 1:
40 return True 40 return True
@@ -9,10 +9,14 @@ import shutil @@ -9,10 +9,14 @@ import shutil
9 9
10 def compile(des): 10 def compile(des):
11 11
  12 +
  13 + project_dir = os.path.dirname(os.path.realpath(__file__))
  14 + if os.path.normpath(project_dir) == os.path.normpath(des):
  15 + raise Exception("目标目录不能与代码目录一样!")
  16 +
12 if os.path.exists(des): 17 if os.path.exists(des):
13 os.system("rd/s/q {}".format(des)) 18 os.system("rd/s/q {}".format(des))
14 shutil.rmtree(des, True) 19 shutil.rmtree(des, True)
15 - project_dir = os.path.dirname(os.path.realpath(__file__))  
16 20
17 shutil.copytree(project_dir, des) 21 shutil.copytree(project_dir, des)
18 git_path = os.path.join(des,".git") 22 git_path = os.path.join(des,".git")
@@ -353,6 +353,19 @@ AddDefaultCharset UTF-8 @@ -353,6 +353,19 @@ AddDefaultCharset UTF-8
353 #EnableMMAP off 353 #EnableMMAP off
354 EnableSendfile on 354 EnableSendfile on
355 355
  356 +#3.1.2
  357 +LoadModule headers_module modules/mod_headers.so
  358 +Header set X-Content-Type-Options nosniff
  359 +
  360 +#3.1.3
  361 +ServerSignature Off
  362 +
  363 +#3.1.10禁用trace
  364 + off
  365 +
  366 +#3.1.11
  367 +ServerTokens Prod
  368 +
356 # Supplemental configuration 369 # Supplemental configuration
357 # 370 #
358 # Load config files in the "/etc/httpd/conf.d" directory, if any. 371 # Load config files in the "/etc/httpd/conf.d" directory, if any.
@@ -22,88 +22,20 @@ from osgeo.ogr import * @@ -22,88 +22,20 @@ from osgeo.ogr import *
22 import base64 22 import base64
23 23
24 from kazoo.client import KazooClient 24 from kazoo.client import KazooClient
25 -def query_thread():  
26 - def get_db_session(db_url, autocommit=False) -> Session:  
27 - engine = create_engine(db_url, pool_size=100)  
28 25
29 - system_session: Session = sessionmaker(bind=engine, autocommit=autocommit)()  
30 -  
31 - return system_session  
32 -  
33 - ses: Session = get_db_session("postgresql://postgres:chinadci@172.26.99.168:5432/postgres")  
34 - bbox = "113.2470703125 22.840576171875,113.258056640625 {}"  
35 - yy= 22.8515625  
36 -  
37 - table="fs1kw"  
38 -  
39 - left = True  
40 - for i in range(1):  
41 - if left:  
42 - yy+=0.00001  
43 - left=False  
44 -  
45 - else:  
46 - yy-=0.00001  
47 - left=True  
48 - bbox = bbox.format(yy)  
49 - sql = "SELECT geom FROM {} WHERE geom && 'BOX3D({})'::box3d limit 100000".format(table, bbox)  
50 - time1=time.time()  
51 - dd = ses.execute(sql)  
52 - for x in dd:  
53 - dddd = x  
54 - print(multiprocessing.current_process(),time.time()-time1)  
55 - ses.close()  
56 -# query_thread()  
57 if __name__ == '__main__': 26 if __name__ == '__main__':
58 - # kk="PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxkbWFwIHByb2plY3RuYW1lPSJ3bXRzdGVzdCIgdmVyc2lvbj0iNC4wIj4KICA8cHJvamVjdENycz4KICAgIDxzcGF0aWFscmVmc3lzPgogICAgICA8d2t0Pjwvd2t0PgogICAgICA8cHJvajQ+PC9wcm9qND4KICAgICAgPHNyaWQ+NDQ5MDwvc3JpZD4KICAgICAgPGRlc2NyaXB0aW9uLz4KICAgICAgPHByb2plY3Rpb25hY3JvbnltLz4KICAgIDwvc3BhdGlhbHJlZnN5cz4KICA8L3Byb2plY3RDcnM+CiAgPHByb2plY3RsYXllcnM+CiAgICA8bWFwbGF5ZXIgbmFtZT0ibGF5ZXIiIGFsaWFzPSJOb25lIiB0eXBlPSIwIj4KICAgICAgPGV4dGVudD4KICAgICAgICA8eG1pbj4xMDcuNzg5ODE0OTQxODA2MTg8L3htaW4+CiAgICAgICAgPHltaW4+MTIwLjQzNTUzNjAzOTM1Njc1PC95bWluPgogICAgICAgIDx4bWF4PjEyMC40MzU1MzYwMzkzNTY3NTwveG1heD4KICAgICAgICA8eW1heD4yNS45OTk4Njg3NTc3MzcwMzM8L3ltYXg+CiAgICAgIDwvZXh0ZW50PgogICAgICA8c3R5bGU+ZGVmYXVsdDwvc3R5bGU+CiAgICAgIDxmb3JtYXQ+aW1hZ2UvcG5nPC9mb3JtYXQ+CiAgICAgIDx2ZW5kb3I+RVNSSV9WMTwvdmVuZG9yPgogICAgICA8ZGF0YXNvdXJjZT4vdXNyL2xvY2FsL2RtYXA0L2dkbWFwL19hbGxsYXllcnM8L2RhdGFzb3VyY2U+CiAgICAgIDx0aWxlTWF0cml4U2V0cz4KICAgICAgICA8dGlsZU1hdHJpeFNldD4KICAgICAgICAgIDxpZD5kZWZhdWx0PC9pZD4KICAgICAgICAgIDxjcnM+RVBTRzo6NDQ5MDwvY3JzPgogICAgICAgICAgPHRpbGVDb2xzPjI1NjwvdGlsZUNvbHM+CiAgICAgICAgICA8dGlsZVJvd3M+MjU2PC90aWxlUm93cz4KICAgICAgICAgIDxkcGk+OTY8L2RwaT4KICAgICAgICAgIDx0aWxlT3JpZ2luPgogICAgICAgICAgICA8WD40MDA8L1g+CiAgICAgICAgICAgIDxZPi00MDA8L1k+CiAgICAgICAgICA8L3RpbGVPcmlnaW4+CiAgICAgICAgICA8bGV2ZWxzPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjA8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjU5MDk5NTE4Ni4xMjwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4xLjQwNjI1MDAwMDAwNTk0ODg8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+MTwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+Mjk1NDk3NTkzLjA2PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuNzAzMTI1MDAwMDAyOTc0NDwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4yPC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xNDc3NDg3OTYuNTM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4zNTE1NjI1MDAwMDE0ODcyPC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjM8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjczODc0Mzk4LjI2NTwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4wLjE3NTc4MTI1MDAwMDc0MzY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+NDwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MzY5MzcxOTkuMTMyNTwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4wLjA4Nzg5MDYyNTAwMDM3MTg8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+NTwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MTg0Njg1OTkuNTY2MjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wNDM5NDUzMTI1MDAxODU5PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjY8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjkyMzQyOTkuNzgzMTI1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDIxOTcyNjU2MjUwMDkyOTU8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+NzwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NDYxNzE0OS44OTE1NjI1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDEwOTg2MzI4MTI1MDQ2NDc1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjg8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjIzMDg1NzQuOTQ1NzgxMjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDU0OTMxNjQwNjI1MjMyMzc1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjk8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjExNTQyODcuNDcyODkwNjI1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDAyNzQ2NTgyMDMxMjYxNjE4NzwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4xMDwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NTc3MTQzLjczNjQ0NTMxMjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDEzNzMyOTEwMTU2MzA4MDk0PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjExPC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4yODg1NzEuODY4MjIyNjU2MjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDA2ODY2NDU1MDc4MTU0MDQ3PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjEyPC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xNDQyODUuOTM0MTExMzI4MTM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDAzNDMzMjI3NTM5MDc3MDIzNDwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4xMzwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NzIxNDIuOTY3MDU1NjY0MDY8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDAxNzE2NjEzNzY5NTM4NTExNzwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4xNDwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MzYwNzEuNDgzNTI3ODMyMDM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+OC41ODMwNjg4NDc2OTI1NTllLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE1PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xODAzNS43NDE3NjM5MTYwMTY8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+NC4yOTE1MzQ0MjM4NDYyNzllLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE2PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj45MDE3Ljg3MDg4MTk1ODAwODwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4yLjE0NTc2NzIxMTkyMzEzOTZlLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE3PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj40NTA4LjkzNTQ0MDk3OTAwNDwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4xLjA3Mjg4MzYwNTk2MTU2OThlLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE4PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4yMjU0LjQ2NzcyMDQ4OTUwMjwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj41LjM2NDQxODAyOTgwNzg0OWUtMDY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+MTk8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjExMjcuMjMzODYwMjQ0NzUxPC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjIuNjgyMjA5MDE0OTAzOTI0NmUtMDY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+MjA8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjU2My42MTY5MzAxMjIzNzU1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjEuMzQxMTA0NTA3NDUxOTYyM2UtMDY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICA8L2xldmVscz4KICAgICAgICA8L3RpbGVNYXRyaXhTZXQ+CiAgICAgIDwvdGlsZU1hdHJpeFNldHM+CiAgICA8L21hcGxheWVyPgogIDwvcHJvamVjdGxheWVycz4KPC9kbWFwPg=="  
59 - # kk="PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxkbWFwIHByb2plY3RuYW1lPSJ3bXRzdGVzdCIgdmVyc2lvbj0iNC4wIj4KICA8cHJvamVjdENycz4KICAgIDxzcGF0aWFscmVmc3lzPgogICAgICA8d2t0Pjwvd2t0PgogICAgICA8cHJvajQ+PC9wcm9qND4KICAgICAgPHNyaWQ+NDQ5MDwvc3JpZD4KICAgICAgPGRlc2NyaXB0aW9uLz4KICAgICAgPHByb2plY3Rpb25hY3JvbnltLz4KICAgIDwvc3BhdGlhbHJlZnN5cz4KICA8L3Byb2plY3RDcnM+CiAgPHByb2plY3RsYXllcnM+CiAgICA8bWFwbGF5ZXIgbmFtZT0ibGF5ZXIiIGFsaWFzPSJOb25lIiB0eXBlPSIwIj4KICAgICAgPGV4dGVudD4KICAgICAgICA8eG1pbj4xMDcuNzg5ODE0OTQxODA2MTg8L3htaW4+CiAgICAgICAgPHltaW4+MTIwLjQzNTUzNjAzOTM1Njc1PC95bWluPgogICAgICAgIDx4bWF4PjEyMC40MzU1MzYwMzkzNTY3NTwveG1heD4KICAgICAgICA8eW1heD4yNS45OTk4Njg3NTc3MzcwMzM8L3ltYXg+CiAgICAgIDwvZXh0ZW50PgogICAgICA8c3R5bGU+ZGVmYXVsdDwvc3R5bGU+CiAgICAgIDxmb3JtYXQ+aW1hZ2UvcG5nPC9mb3JtYXQ+CiAgICAgIDx2ZW5kb3I+RVNSSV9WMTwvdmVuZG9yPgogICAgICA8ZGF0YXNvdXJjZT4vdXNyL2xvY2FsL2RtYXA0L2dkbWFwL19hbGxsYXllcnM8L2RhdGFzb3VyY2U+CiAgICAgIDx0aWxlTWF0cml4U2V0cz4KICAgICAgICA8dGlsZU1hdHJpeFNldD4KICAgICAgICAgIDxpZD5kZWZhdWx0PC9pZD4KICAgICAgICAgIDxjcnM+RVBTRzo6NDQ5MDwvY3JzPgogICAgICAgICAgPHRpbGVDb2xzPjI1NjwvdGlsZUNvbHM+CiAgICAgICAgICA8dGlsZVJvd3M+MjU2PC90aWxlUm93cz4KICAgICAgICAgIDxkcGk+OTY8L2RwaT4KICAgICAgICAgIDx0aWxlT3JpZ2luPgogICAgICAgICAgICA8WD40MDA8L1g+CiAgICAgICAgICAgIDxZPi00MDA8L1k+CiAgICAgICAgICA8L3RpbGVPcmlnaW4+CiAgICAgICAgICA8bGV2ZWxzPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjA8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjU5MDk5NTE4Ni4xMjwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4xLjQwNjI1MDAwMDAwNTk0ODg8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+MTwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+Mjk1NDk3NTkzLjA2PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuNzAzMTI1MDAwMDAyOTc0NDwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4yPC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xNDc3NDg3OTYuNTM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4zNTE1NjI1MDAwMDE0ODcyPC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjM8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjczODc0Mzk4LjI2NTwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4wLjE3NTc4MTI1MDAwMDc0MzY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+NDwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MzY5MzcxOTkuMTMyNTwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4wLjA4Nzg5MDYyNTAwMDM3MTg8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+NTwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MTg0Njg1OTkuNTY2MjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wNDM5NDUzMTI1MDAxODU5PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjY8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjkyMzQyOTkuNzgzMTI1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDIxOTcyNjU2MjUwMDkyOTU8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+NzwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NDYxNzE0OS44OTE1NjI1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDEwOTg2MzI4MTI1MDQ2NDc1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjg8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjIzMDg1NzQuOTQ1NzgxMjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDU0OTMxNjQwNjI1MjMyMzc1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjk8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjExNTQyODcuNDcyODkwNjI1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDAyNzQ2NTgyMDMxMjYxNjE4NzwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4xMDwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NTc3MTQzLjczNjQ0NTMxMjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDEzNzMyOTEwMTU2MzA4MDk0PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjExPC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4yODg1NzEuODY4MjIyNjU2MjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDA2ODY2NDU1MDc4MTU0MDQ3PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjEyPC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xNDQyODUuOTM0MTExMzI4MTM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDAzNDMzMjI3NTM5MDc3MDIzNDwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4xMzwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NzIxNDIuOTY3MDU1NjY0MDY8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDAxNzE2NjEzNzY5NTM4NTExNzwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgPC9sZXZlbD4KICAgICAgICAgICAgPGxldmVsPgogICAgICAgICAgICAgIDxpZD4xNDwvaWQ+CiAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MzYwNzEuNDgzNTI3ODMyMDM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+OC41ODMwNjg4NDc2OTI1NTllLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE1PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xODAzNS43NDE3NjM5MTYwMTY8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgPHJlc29sdXRpb24+NC4yOTE1MzQ0MjM4NDYyNzllLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE2PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj45MDE3Ljg3MDg4MTk1ODAwODwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4yLjE0NTc2NzIxMTkyMzEzOTZlLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE3PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj40NTA4LjkzNTQ0MDk3OTAwNDwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4xLjA3Mjg4MzYwNTk2MTU2OThlLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgPGlkPjE4PC9pZD4KICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4yMjU0LjQ2NzcyMDQ4OTUwMjwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICA8cmVzb2x1dGlvbj41LjM2NDQxODAyOTgwNzg0OWUtMDY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+MTk8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjExMjcuMjMzODYwMjQ0NzUxPC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjIuNjgyMjA5MDE0OTAzOTI0NmUtMDY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICAgIDxsZXZlbD4KICAgICAgICAgICAgICA8aWQ+MjA8L2lkPgogICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjU2My42MTY5MzAxMjIzNzU1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjEuMzQxMTA0NTA3NDUxOTYyM2UtMDY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgIDwvbGV2ZWw+CiAgICAgICAgICA8L2xldmVscz4KICAgICAgICA8L3RpbGVNYXRyaXhTZXQ+CiAgICAgIDwvdGlsZU1hdHJpeFNldHM+CiAgICA8L21hcGxheWVyPgogIDwvcHJvamVjdGxheWVycz4KPC9kbWFwPg=="  
60 - # kk="PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxkbWFwIHByb2plY3RuYW1lPSJ0bXN0ZXN0IiB2ZXJzaW9uPSI0LjAiPgogIDxwcm9qZWN0Q3JzPgogICAgPHNwYXRpYWxyZWZzeXM+CiAgICAgIDx3a3Q+PC93a3Q+CiAgICAgIDxwcm9qND48L3Byb2o0PgogICAgICA8c3JpZD40NDkwPC9zcmlkPgogICAgICA8ZGVzY3JpcHRpb24vPgogICAgICA8cHJvamVjdGlvbmFjcm9ueW0vPgogICAgPC9zcGF0aWFscmVmc3lzPgogIDwvcHJvamVjdENycz4KICA8cHJvamVjdGxheWVycz4KICAgIDxtYXBsYXllciBuYW1lPSJsYXllciIgYWxpYXM9Ik5vbmUiIHR5cGU9IjMiPgogICAgICA8ZXh0ZW50PgogICAgICAgIDx4bWluPjEwNy43ODk4MTQ5NDE4MDYxODwveG1pbj4KICAgICAgICA8eW1pbj4xMjAuNDM1NTM2MDM5MzU2NzU8L3ltaW4+CiAgICAgICAgPHhtYXg+MTIwLjQzNTUzNjAzOTM1Njc1PC94bWF4PgogICAgICAgIDx5bWF4PjI1Ljk5OTg2ODc1NzczNzAzMzwveW1heD4KICAgICAgPC9leHRlbnQ+CiAgICAgIDxzdHlsZT5kZWZhdWx0PC9zdHlsZT4KICAgICAgPGZvcm1hdD5pbWFnZS9wbmc8L2Zvcm1hdD4KICAgICAgPHZlbmRvcj5RR0lTPC92ZW5kb3I+CiAgICAgIDxkYXRhc291cmNlPi91c3IvbG9jYWwvZG1hcDQvcWdpczwvZGF0YXNvdXJjZT4KICAgIDwvbWFwbGF5ZXI+CiAgPC9wcm9qZWN0bGF5ZXJzPgo8L2RtYXA+"  
61 - # kk="PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxkbWFwIHByb2plY3RuYW1lPSJ0bXN0ZXN0IiB2ZXJzaW9uPSI0LjAiPgogIDxwcm9qZWN0Q3JzPgogICAgPHNwYXRpYWxyZWZzeXM+CiAgICAgIDx3a3Q+PC93a3Q+CiAgICAgIDxwcm9qND48L3Byb2o0PgogICAgICA8c3JpZD40NDkwPC9zcmlkPgogICAgICA8ZGVzY3JpcHRpb24vPgogICAgICA8cHJvamVjdGlvbmFjcm9ueW0vPgogICAgPC9zcGF0aWFscmVmc3lzPgogIDwvcHJvamVjdENycz4KICA8cHJvamVjdGxheWVycz4KICAgIDxtYXBsYXllciBuYW1lPSJsYXllciIgYWxpYXM9IiIgdHlwZT0iMyI+CiAgICAgIDxleHRlbnQ+CiAgICAgICAgPHhtaW4+MTA3Ljc4OTgxNDk0MTgwNjE4PC94bWluPgogICAgICAgIDx5bWluPjEyMC40MzU1MzYwMzkzNTY3NTwveW1pbj4KICAgICAgICA8eG1heD4xMjAuNDM1NTM2MDM5MzU2NzU8L3htYXg+CiAgICAgICAgPHltYXg+MjUuOTk5ODY4NzU3NzM3MDMzPC95bWF4PgogICAgICA8L2V4dGVudD4KICAgICAgPHN0eWxlPmRlZmF1bHQ8L3N0eWxlPgogICAgICA8Zm9ybWF0PmltYWdlL3BuZzwvZm9ybWF0PgogICAgICA8dmVuZG9yPlFHSVM8L3ZlbmRvcj4KICAgICAgPGRhdGFzb3VyY2U+L3Vzci9sb2NhbC9kbWFwNC9xZ2lzPC9kYXRhc291cmNlPgogICAgPC9tYXBsYXllcj4KICA8L3Byb2plY3RsYXllcnM+CjwvZG1hcD4="  
62 - # print(str(base64.b64decode(kk), "utf-8"))  
63 - # daf=0  
64 -  
65 - # zoo: KazooClient = KazooClient(hosts="172.26.99.168:2181", timeout=1)  
66 - # zoo.start()  
67 - # while 1:  
68 - # time.sleep(1)  
69 - # print(zoo.connected)  
70 - # print(zoo.get_children("/rpc"))  
71 -  
72 - # fn = "PG: user=postgres password=chinadci host=172.26.99.160 port=5432 dbname=ceshi "  
73 - # driver = ogr.GetDriverByName("PostgreSQL")  
74 - # if driver is None:  
75 - # raise Exception("打开PostgreSQL驱动失败,可能是当前GDAL未支持PostgreSQL驱动!")  
76 - # ds = driver.Open(fn, 1)  
77 - #  
78 - # layer:Layer = ds.GetLayerByName("shiyqzd_500_bdc")  
79 -  
80 -  
81 - driver2 = ogr.GetDriverByName("ESRI Shapefile")  
82 - data_source: DataSource = driver2.CreateDataSource("H://t3.shp")  
83 -  
84 -  
85 - fid = layer.GetFIDColumn()  
86 - pg_layer: Layer = data_source.CreateLayer("t", layer.GetSpatialRef(), layer.GetGeomType(),["ENCODING=GBK"])  
87 -  
88 - #可能有问题,不支持binary  
89 - schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]  
90 -  
91 - schema_chage = []  
92 - for sche in schema:  
93 - ss :FieldDefn = sche  
94 - if ss.GetType() == ogr.OFTBinary :  
95 - print(ss.name)  
96 - ss.SetType(ogr.OFTInteger)  
97 - schema_chage.append(ss)  
98 27
99 - pg_layer.CreateFields(schema_chage)  
100 28
  29 + fn = "PG: user=postgres password=chinadci host=172.26.60.101 port=5432 dbname=ceshi "
  30 + driver = ogr.GetDriverByName("PostgreSQL")
  31 + if driver is None:
  32 + raise Exception("打开PostgreSQL驱动失败,可能是当前GDAL未支持PostgreSQL驱动!")
  33 + ds :DataSource= driver.Open(fn, 1)
  34 + if ds is None:
  35 + raise Exception("打开数据源失败!")
101 36
102 - count =0  
103 - for feature in layer:  
104 - pg_layer.CreateFeature(feature)  
105 - count+=1  
106 - if count==1000:  
107 - break 37 + for i in range(1,13):
  38 + tn = "t{}".format(i)
  39 + layer : Layer = ds.GetLayerByName(tn)
108 40
109 - data_source.Destroy()  
  41 + print(layer.GetGeomType())
@@ -2,3 +2,304 @@ @@ -2,3 +2,304 @@
2 #author: 4N 2 #author: 4N
3 #createtime: 2022/3/8 3 #createtime: 2022/3/8
4 #email: nheweijun@sina.com 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 +
@@ -54,6 +54,35 @@ class ShapeUtil: @@ -54,6 +54,35 @@ class ShapeUtil:
54 layer.CreateFeature(feat_new) 54 layer.CreateFeature(feat_new)
55 data_source.Destroy() 55 data_source.Destroy()
56 56
  57 + @classmethod
  58 + def create_shp_fromwkts(cls,path,name,wkts):
  59 +
  60 + geo_type = None
  61 + geoms = []
  62 + for wkt in wkts:
  63 + geom : Geometry = ogr.CreateGeometryFromWkt(wkt)
  64 + if geo_type is None:
  65 + geo_type = geom.GetGeometryType()
  66 + geoms.append(geom)
  67 +
  68 + if os.path.exists(path):
  69 +
  70 + pre_name = ".".join(path.split(".")[0:-1])
  71 + for bac in ["dbf","prj","cpg","shp","shx","sbn","sbx"]:
  72 + try:
  73 + os.remove(pre_name+"."+bac)
  74 + except Exception as e:
  75 + pass
  76 +
  77 + data_source: DataSource = cls.driver.CreateDataSource(path)
  78 + layer :Layer = data_source.CreateLayer(name, None, geo_type)
  79 +
  80 + for geom in geoms:
  81 + feat_new = ogr.Feature(layer.GetLayerDefn())
  82 + feat_new.SetGeometry(geom)
  83 + layer.CreateFeature(feat_new)
  84 + data_source.Destroy()
  85 +
57 86
58 class ShapeData: 87 class ShapeData:
59 88
@@ -85,7 +114,7 @@ class ShapeData: @@ -85,7 +114,7 @@ class ShapeData:
85 class Zonghe: 114 class Zonghe:
86 115
87 data:ShapeData 116 data:ShapeData
88 - area_threshold = 10.0 117 + area_threshold = 20.0
89 buffer_threshold = 100.0 118 buffer_threshold = 100.0
90 119
91 def __init__(self,data): 120 def __init__(self,data):
@@ -96,174 +125,363 @@ class Zonghe: @@ -96,174 +125,363 @@ class Zonghe:
96 #只处理Polygon,MultiPolygon要拆开 125 #只处理Polygon,MultiPolygon要拆开
97 def get_polygon_reprecent_point(self,polygon:Geometry): 126 def get_polygon_reprecent_point(self,polygon:Geometry):
98 127
99 - polygon_area = polygon.GetArea()  
100 -  
101 polygon_env = polygon.GetEnvelope() 128 polygon_env = polygon.GetEnvelope()
102 129
103 line_length = max(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2]) 130 line_length = max(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2])
104 131
  132 +
  133 + short_length = min(polygon_env[1]-polygon_env[0],polygon_env[3]-polygon_env[2])
  134 +
105 center:Geometry = polygon.Centroid() 135 center:Geometry = polygon.Centroid()
  136 +
  137 + # 提前return
106 if polygon.Contains(center): 138 if polygon.Contains(center):
107 return center 139 return center
108 140
  141 + last_state = None
  142 + line = None
  143 + calculate_time = 0
  144 + direction = self.get_direction(polygon, center, line_length)
  145 + in_hole = False
  146 + in_hole_line = None
109 147
110 - left_area = 0  
111 - right_area = polygon_area  
112 -  
113 - left_or_right = None  
114 - fen = False  
115 148
  149 + #无孔Polygon
116 if polygon.GetGeometryCount() == 1: 150 if polygon.GetGeometryCount() == 1:
117 polygon_line = ogr.ForceToLineString(polygon) 151 polygon_line = ogr.ForceToLineString(polygon)
118 - # 有孔Polygon 152 +
  153 + # 有孔Polygon,要分2种情况
119 else: 154 else:
120 polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0)) 155 polygon_line = ogr.ForceToLineString(polygon.GetGeometryRef(0))
  156 + for i in range(1,polygon.GetGeometryCount()):
  157 + hole_line = polygon.GetGeometryRef(i)
  158 + hole_polygon : Geometry = ogr.ForceToPolygon(hole_line)
  159 + if hole_polygon.Contains(center):
  160 + in_hole = True
  161 + direction = range(0,190,10)
  162 + in_hole_line = ogr.ForceToLineString(hole_line)
  163 + print("in_hole")
121 164
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 165
140 - clip_geom:Geometry = polygon.Difference(line.Buffer(line_length/self.buffer_threshold))  
141 166
  167 + for angle in direction:
142 168
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 169 + if in_hole:
  170 + line = self.get_doubleline(center.GetX(),center.GetY(),angle,line_length)
  171 + else:
  172 + line = self.get_line(center.GetX(),center.GetY(),angle,line_length)
159 173
  174 + line_buffer:Geometry = line.Buffer(line_length / self.buffer_threshold)
  175 + clip_geom: Geometry = polygon.Difference(line_buffer)
160 176
  177 + oneside_area = 0
  178 + otherside_area = 0
161 179
  180 + gc = clip_geom.GetGeometryCount()
  181 + if gc <= 1:
  182 + oneside_area = 0
  183 + otherside_area = 0
162 else: 184 else:
163 -  
164 - left_area = 0  
165 - right_area = 0 185 + calculate_time += 1
  186 + triangle1, triangle2 = self.get_side_triangle(line, angle)
166 187
167 for gi in range(clip_geom.GetGeometryCount()): 188 for gi in range(clip_geom.GetGeometryCount()):
168 clip_geom_i :Geometry = clip_geom.GetGeometryRef(gi) 189 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) 190 + it = clip_geom_i.Intersection(triangle1)
171 191
172 - if side_value > 0:  
173 - left_area += clip_geom_i.GetArea() 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()
174 else: 194 else:
175 - right_area += clip_geom_i.GetArea()  
176 -  
177 -  
178 - print(left_area,right_area) 195 + otherside_area += clip_geom_i.GetArea()
  196 + print(oneside_area,otherside_area)
  197 + if last_state is None:
  198 + if oneside_area == 0 and otherside_area==0:
  199 + last_state = 0
  200 + else:
  201 + last_state = 1 if oneside_area < otherside_area else -1
  202 + else:
  203 + if oneside_area == 0 and otherside_area==0:
  204 + now_state = 0
  205 + else:
  206 + now_state = 1 if oneside_area < otherside_area else -1
179 207
180 - last_last_point = last_point  
181 - last_point = next_point  
182 - left_or_right = 1 if left_area > right_area else -1 208 + if last_state* now_state < 0:
  209 + break
  210 + else:
  211 + last_state = now_state
183 212
  213 + # 提前return
  214 + if in_hole:
  215 + # print(line)
  216 + # print(in_hole_line)
  217 + point_intersection: Geometry = line.Intersection(in_hole_line)
  218 + plist = []
  219 + for i in range(point_intersection.GetGeometryCount()):
  220 + pi = point_intersection.GetGeometryRef(i)
  221 + plist.append(pi)
  222 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  223 + plist_d.sort(key=lambda x:x[1])
184 224
185 - # 进入二分法步骤  
186 - if fen: 225 + nearest_point= plist_d[0][0]
  226 + # print(line_length)
  227 + # print(short_length)
  228 + # print(nearest_point)
187 229
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) 230 + firt_short_length = short_length/20.0
  231 + # print(firt_short_length)
196 232
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) 233 + radline,other_point = self.get_radline(center.GetX(),center.GetY(),nearest_point.GetX(),nearest_point.GetY(),firt_short_length)
201 234
202 - # print(abs(next_point[0] - angle[1][0])) 235 + print(other_point)
203 236
204 - else:  
205 - # print(point_i)  
206 - point_i += 1  
207 - next_point = polygon_line.GetPoint(point_i) 237 + while not polygon.Contains(other_point):
  238 + firt_short_length = firt_short_length / 2
  239 + radline, other_point = self.get_radline(center.GetX(), center.GetY(), nearest_point.GetX(),
  240 + nearest_point.GetY(), firt_short_length)
208 241
209 - next_point_side = self.side(center, other_point, self.creat_point(next_point)) 242 + print("return hole_rep")
210 243
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 244 + return other_point
217 245
218 - print(calculate_times)  
219 246
220 point_intersection:Geometry = line.Intersection(polygon_line) 247 point_intersection:Geometry = line.Intersection(polygon_line)
221 -  
222 xlist = [] 248 xlist = []
223 ylist = [] 249 ylist = []
  250 + plist = []
  251 +
224 for i in range(point_intersection.GetGeometryCount()): 252 for i in range(point_intersection.GetGeometryCount()):
225 pi = point_intersection.GetGeometryRef(i) 253 pi = point_intersection.GetGeometryRef(i)
226 xlist.append(pi.GetX()) 254 xlist.append(pi.GetX())
227 ylist.append(pi.GetY()) 255 ylist.append(pi.GetY())
  256 + plist.append(pi)
228 257
229 reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0] 258 reprecent_point = [(min(xlist)+max(xlist))/2.0,(min(ylist)+max(ylist))/2.0]
230 259
231 - return self.creat_point(reprecent_point) 260 + reprecent_point = self.creat_point(reprecent_point)
  261 +
  262 + if not polygon.Contains(reprecent_point):
  263 + plist_d = [(pi,center.Distance(pi)) for pi in plist]
  264 + 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))
  266 +
  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 +
  278 +
  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)
  298 +
  299 + p4: Geometry = ogr.Geometry(ogr.wkbPoint)
  300 + p4.AddPoint(3, 5)
  301 + mp.AddGeometry(p4)
  302 +
  303 + p5: Geometry = ogr.Geometry(ogr.wkbPoint)
  304 + p5.AddPoint(4, 2)
  305 + mp.AddGeometry(p5)
  306 +
  307 + p6: Geometry = ogr.Geometry(ogr.wkbPoint)
  308 +
  309 + p6.AddPoint(3, 1)
  310 +
  311 + mp.AddGeometry(p6)
  312 +
  313 + de = mp.DelaunayTriangulation()
  314 +
  315 + print(mp)
  316 +
  317 + for i in range(de.GetGeometryCount()):
  318 + d:Geometry = de.GetGeometryRef(i)
  319 +
  320 + print("\""+d.ExportToWkt()+"\",")
  321 +
  322 + def get_line(self, x0, y0 , angle, r):
232 323
  324 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  325 + line.AddPoint(x0, y0)
  326 + hudu = angle/360.0 * 2 * math.pi
  327 + dx = math.sin(hudu) * r
  328 + dy = math.cos(hudu) * r
  329 + line.AddPoint(x0+dx, y0+dy)
  330 +
  331 + return line
  332 +
  333 + def get_doubleline(self, x0, y0 , angle, r):
  334 +
  335 + line: Geometry = ogr.Geometry(ogr.wkbLineString)
  336 +
  337 + hudu = angle/360.0 * 2 * math.pi
  338 + dx = math.sin(hudu) * r
  339 + dy = math.cos(hudu) * r
  340 +
  341 + hudu = (angle+180)/360.0 * 2 * math.pi
  342 + dx2 = math.sin(hudu) * r
  343 + dy2 = math.cos(hudu) * r
233 344
  345 + line.AddPoint(x0 + dx2, y0 + dy2)
  346 + line.AddPoint(x0+dx, y0+dy)
234 347
235 - def get_line(self,x0,y0,x1,y1,len_size): 348 + return line
  349 +
  350 +
  351 + def get_radline(self,x0,y0,x1,y1,len_size):
236 352
237 line: Geometry = ogr.Geometry(ogr.wkbLineString) 353 line: Geometry = ogr.Geometry(ogr.wkbLineString)
238 line.AddPoint(x0, y0) 354 line.AddPoint(x0, y0)
239 - x2 = x0 + len_size 355 + tanx = (y1-y0) / (x1-x0)
  356 + cosx = 1 / math.sqrt(1 + tanx *tanx)
  357 + dx = cosx* len_size
  358 +
  359 + x2 = x1 + dx
240 360
241 if x1 != x0: 361 if x1 != x0:
242 y2 = ((y1-y0)*(x2-x0))/(x1-x0) + y0 362 y2 = ((y1-y0)*(x2-x0))/(x1-x0) + y0
243 else: 363 else:
244 x2 = x0 364 x2 = x0
245 - y2 = y0 + len_size 365 + y2 = y0 + dx
246 line.AddPoint(x2, y2) 366 line.AddPoint(x2, y2)
247 367
248 other_point = ogr.Geometry(ogr.wkbPoint) 368 other_point = ogr.Geometry(ogr.wkbPoint)
249 other_point.AddPoint(x2, y2) 369 other_point.AddPoint(x2, y2)
250 370
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 371 + return line , other_point
  372 +
  373 + def get_direction(self,polygon,center,line_length):
  374 + '''
  375 + 判断旋转方向
  376 + :param polygon:
  377 + :param center:
  378 + :param line_length:
  379 + :return:
  380 + '''
  381 +
  382 + line = self.get_line(center.GetX(),center.GetY(),0,line_length)
  383 + line_buffer:Geometry = line.Buffer(line_length / self.buffer_threshold)
  384 + clip_geom: Geometry = polygon.Difference(line_buffer)
  385 +
  386 + gc = clip_geom.GetGeometryCount()
  387 + oneside_area = 0
  388 + otherside_area = 0
  389 +
  390 + if gc <= 1:
  391 + return range(0,370,10)
  392 + else:
  393 + triangle1, triangle2 = self.get_side_triangle(line, 0)
  394 +
  395 + for gi in range(clip_geom.GetGeometryCount()):
  396 + clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi)
  397 + it = clip_geom_i.Intersection(triangle1)
  398 +
  399 + if clip_geom_i.Intersect(triangle1) and it.Buffer(line_length / self.buffer_threshold).Intersect(
  400 + line_buffer):
  401 + oneside_area += clip_geom_i.GetArea()
  402 + else:
  403 + otherside_area += clip_geom_i.GetArea()
  404 +
  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)
  411 +
  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)
  417 +
  418 + for gi in range(clip_geom.GetGeometryCount()):
  419 + clip_geom_i: Geometry = clip_geom.GetGeometryRef(gi)
  420 + it = clip_geom_i.Intersection(triangle1)
  421 +
  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()
  427 +
  428 + if abs(oneside_area - otherside_area) > abs(oneside_area_contrast - otherside_area_contrast):
  429 + return range(0, 370, 10)
  430 + else:
  431 + return range(360, -10, -10)
  432 +
  433 + def get_side_triangle(self,line:Geometry,angle):
  434 + '''
  435 + 获取方向三角形
  436 + :param line:
  437 + :param angle:
  438 + :return:
  439 + '''
  440 +
  441 + start = line.GetPoint(0)
  442 + end = line.GetPoint(1)
  443 +
  444 +
  445 + angle_t = angle-30
  446 + hudu = angle_t/360.0 * 2 * math.pi
  447 +
  448 + r = line.Length() / (2*math.cos( math.pi/6))
  449 + dx = math.sin(hudu) * r
  450 + dy = math.cos(hudu) * r
  451 +
  452 +
  453 + ring1 = ogr.Geometry(ogr.wkbLinearRing)
  454 + ring1.AddPoint(start[0], start[1])
  455 + ring1.AddPoint(start[0] + dx, start[1] + dy)
  456 + ring1.AddPoint(end[0], end[1])
  457 + ring1.AddPoint(start[0], start[1])
  458 + triangle1 = ogr.Geometry(ogr.wkbPolygon)
  459 + triangle1.AddGeometry(ring1)
256 460
257 461
  462 + angle_t = angle+30
  463 + hudu = angle_t/360.0 * 2 * math.pi
258 464
259 - def side(self,A,B,P): 465 + r = line.Length() / (2*math.cos( math.pi/6))
260 466
  467 + dx = math.sin(hudu) * r
  468 + dy = math.cos(hudu) * r
261 469
262 - side = (B.GetX() - A.GetX()) * (P.GetY() - A.GetY()) - (B.GetY() - A.GetY()) * (P.GetX() - A.GetX())  
263 - return side 470 + ring2 = ogr.Geometry(ogr.wkbLinearRing)
  471 + ring2.AddPoint(start[0], start[1])
  472 + ring2.AddPoint(start[0]+dx, start[1]+dy)
  473 + ring2.AddPoint(end[0], end[1])
  474 + ring2.AddPoint(start[0], start[1])
  475 + triangle2 = ogr.Geometry(ogr.wkbPolygon)
  476 + triangle2.AddGeometry(ring2)
264 477
  478 + return triangle1,triangle2
265 479
266 480
  481 + def creat_point(self,tuple):
  482 + p: Geometry = ogr.Geometry(ogr.wkbPoint)
  483 + p.AddPoint(tuple[0], tuple[1])
  484 + return p
267 485
268 def process(self): 486 def process(self):
269 polygons = self.data.get_polygons() 487 polygons = self.data.get_polygons()
@@ -279,27 +497,43 @@ if __name__ == '__main__': @@ -279,27 +497,43 @@ if __name__ == '__main__':
279 # print(sd.get_polygons()[0]) 497 # print(sd.get_polygons()[0])
280 # sd.close() 498 # sd.close()
281 499
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) 500 + create = True
  501 + create = False
  502 +
  503 + if create:
  504 +
  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])
  522 +
  523 +
  524 +
  525 + zh.create_delauney_test()
  526 +
  527 +
  528 + else:
  529 +
  530 +
  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"
  538 + ShapeUtil.create_shp_fromwkts(result,"zh",wkts)
305 539
注册登录 后发表评论