提交 838afebfcb42828c7b9e3077230c32dca0aeab5e

作者 nheweijun
1 个父辈 c39bdbc1

修改服务整合ER结构前

正在显示 43 个修改的文件 包含 1346 行增加186 行删除
@@ -12,7 +12,7 @@ from . import data_download,data_download_task @@ -12,7 +12,7 @@ from . import data_download,data_download_task
12 from . import get_meta 12 from . import get_meta
13 from . import data_entry_by_meta 13 from . import data_entry_by_meta
14 from . import get_data_list 14 from . import get_data_list
15 - 15 +from . import data_entry_simple
16 16
17 class DataManager(BlueprintApi): 17 class DataManager(BlueprintApi):
18 18
@@ -99,4 +99,13 @@ class DataManager(BlueprintApi): @@ -99,4 +99,13 @@ class DataManager(BlueprintApi):
99 """ 99 """
100 数据入库ByMeta 100 数据入库ByMeta
101 """ 101 """
102 - return data_entry_by_meta.Api().result  
  102 + return data_entry_by_meta.Api().result
  103 +
  104 + @staticmethod
  105 + @bp.route('/DataEntrySimple', methods=['POST'])
  106 + @swag_from(data_entry_simple.Api.api_doc)
  107 + def data_entry_simple():
  108 + """
  109 + 数据入库Simple
  110 + """
  111 + return data_entry_simple.Api().result
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/1/27
  4 +#email: nheweijun@sina.com
  5 +
  6 +from osgeo.ogr import *
  7 +import uuid
  8 +
  9 +import time
  10 +from app.models import *
  11 +import json
  12 +import re
  13 +from app.util.component.ApiTemplate import ApiTemplate
  14 +from app.util.component.PGUtil import PGUtil
  15 +from .get_meta import Api as MetaApi
  16 +from threading import Thread
  17 +from app.util.component.EntryDataVacuate import EntryDataVacuate
  18 +
  19 +class Api(ApiTemplate):
  20 +
  21 + api_name = "Simple入库"
  22 +
  23 + def process(self):
  24 +
  25 +
  26 + data_path = self.para.get("data_path")
  27 + database_guid = self.para.get("database_guid")
  28 + is_task = self.para.get("is_task")
  29 +
  30 + self.para["overwrite"] = "yes"
  31 + self.para["task_guid"] = uuid.uuid1().__str__()
  32 + self.para["task_time"] = time.time()
  33 + self.para["task_name"] = "入库测试接口"
  34 + self.para["creator"] = "4N"
  35 +
  36 +
  37 + #返回结果
  38 + res={}
  39 + try:
  40 + meta_api = MetaApi()
  41 + meta_api.para["data_path"] = data_path
  42 + meta_list = json.loads(meta_api.process())["data"]
  43 +
  44 + if is_task:
  45 + task = Task(guid=self.para.get("task_guid"),
  46 + name=self.para.get("task_name"),
  47 + create_time=datetime.datetime.now(),
  48 + state=0,
  49 + task_type=1,
  50 + creator=self.para.get("creator"),
  51 + file_name=meta_list[0].get("filename"),
  52 + database_guid=self.para.get("database_guid"),
  53 + catalog_guid=self.para.get("catalog_guid"),
  54 + process="等待入库",
  55 + parameter=json.dumps(self.para))
  56 + db.session.add(task)
  57 + db.session.commit()
  58 +
  59 + res["result"] = True
  60 + res["msg"] = "数据录入提交成功!"
  61 + res["data"] = self.para["task_guid"]
  62 + else:
  63 + start = time.time()
  64 +
  65 + self.para["meta"] = meta_list
  66 +
  67 + task = Task(guid=self.para.get("task_guid"),
  68 + name=self.para.get("task_name"),
  69 + create_time=datetime.datetime.now(),
  70 + state=0,
  71 + task_type=-1,
  72 + creator=self.para.get("creator"),
  73 + file_name=meta_list[0].get("filename"),
  74 + database_guid=self.para.get("database_guid"),
  75 + catalog_guid=self.para.get("catalog_guid"),
  76 + process="等待入库",
  77 + parameter=json.dumps(self.para))
  78 + db.session.add(task)
  79 + db.session.commit()
  80 +
  81 + entry_data_thread = Thread(
  82 + target=EntryDataVacuate().entry, args=(self.para,))
  83 + entry_data_thread.start()
  84 + entry_data_thread.join()
  85 + res["result"] = True
  86 + res["msg"] = "数据入库成功!"
  87 + res["data"] = "耗时{}秒".format(time.time()-start)
  88 +
  89 + except Exception as e:
  90 + raise e
  91 + return res
  92 +
  93 +
  94 + api_doc={
  95 + "tags":["IO接口"],
  96 + "parameters":[
  97 + {"name": "data_path",
  98 + "in": "formData",
  99 + "type": "string",
  100 + "description": "服务器数据路径"},
  101 + {"name": "database_guid",
  102 + "in": "formData",
  103 + "type": "string",
  104 + "description": "数据库guid"},
  105 + {"name": "is_task",
  106 + "in": "formData",
  107 + "type": "boolean",
  108 + "description": "是否形成任务"}
  109 + ],
  110 + "responses":{
  111 + 200:{
  112 + "schema":{
  113 + "properties":{
  114 + }
  115 + }
  116 + }
  117 + }
  118 + }
@@ -23,7 +23,7 @@ class Api(ApiTemplate): @@ -23,7 +23,7 @@ class Api(ApiTemplate):
23 res = {} 23 res = {}
24 24
25 try: 25 try:
26 - project_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) 26 + project_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
27 base_path = os.path.join(project_path,"tmp") 27 base_path = os.path.join(project_path,"tmp")
28 if self.para.get("data_path"): 28 if self.para.get("data_path"):
29 base_path = os.path.normpath(self.para.get("data_path")) 29 base_path = os.path.normpath(self.para.get("data_path"))
@@ -14,12 +14,14 @@ from . import capabilities @@ -14,12 +14,14 @@ from . import capabilities
14 from . import image_tile,image_wms 14 from . import image_tile,image_wms
15 from . import image_service_list 15 from . import image_service_list
16 from . import image_tile_mask 16 from . import image_tile_mask
  17 +from . import image_wmts
17 18
18 from . import image_delete 19 from . import image_delete
19 from . import image_cancle 20 from . import image_cancle
20 from . import image_register,image_list,image_info,image_edit,image_overview 21 from . import image_register,image_list,image_info,image_edit,image_overview
21 from . import image_tag_create,image_tag_delete,image_tag_list 22 from . import image_tag_create,image_tag_delete,image_tag_list
22 - 23 +from . import image_wms_temporary
  24 +from . import image_wms_kv
23 25
24 class DataManager(BlueprintApi): 26 class DataManager(BlueprintApi):
25 27
@@ -169,7 +171,7 @@ class DataManager(BlueprintApi): @@ -169,7 +171,7 @@ class DataManager(BlueprintApi):
169 171
170 @staticmethod 172 @staticmethod
171 @bp.route('/Tile/<guid>/<l>/<y>/<z>', methods=['GET']) 173 @bp.route('/Tile/<guid>/<l>/<y>/<z>', methods=['GET'])
172 - @swag_from(image_tile.Api.api_doc) 174 + # @swag_from(image_tile.Api.api_doc)
173 def api_image_tile(guid,l,y,z): 175 def api_image_tile(guid,l,y,z):
174 """ 176 """
175 切片服务 177 切片服务
@@ -178,18 +180,11 @@ class DataManager(BlueprintApi): @@ -178,18 +180,11 @@ class DataManager(BlueprintApi):
178 180
179 181
180 182
181 - # @staticmethod  
182 - # @bp.route('/<service_name>/WMTS', methods=['GET'])  
183 - # @swag_from(image_tile.Api.api_doc)  
184 - # def api_image_tile(service_name):  
185 - # """  
186 - # 切片服务  
187 - # """  
188 - # return image_tile.Api(service_name).result 183 +
189 184
190 @staticmethod 185 @staticmethod
191 @bp.route('/Tile', methods=['GET','POST']) 186 @bp.route('/Tile', methods=['GET','POST'])
192 - @swag_from(image_tile.Api.api_doc) 187 + # @swag_from(image_tile.Api.api_doc)
193 def api_image_tile_kv(): 188 def api_image_tile_kv():
194 """ 189 """
195 切片服务 190 切片服务
@@ -217,10 +212,40 @@ class DataManager(BlueprintApi): @@ -217,10 +212,40 @@ class DataManager(BlueprintApi):
217 212
218 213
219 @staticmethod 214 @staticmethod
220 - @bp.route('/WMS', methods=['GET','POST']) 215 + @bp.route('/<service_name>/WMS', methods=['GET','POST'])
221 @swag_from(image_wms.Api.api_doc) 216 @swag_from(image_wms.Api.api_doc)
222 - def image_wms(): 217 + def image_wms(service_name):
  218 + """
  219 + WMS服务
  220 + """
  221 + return image_wms.Api(service_name).result
  222 +
  223 + @staticmethod
  224 + @bp.route('/<service_name>/WMTS', methods=['GET','POST'])
  225 + @swag_from(image_wmts.Api.api_doc)
  226 + def api_image_wmts(service_name):
  227 + """
  228 + 切片服务
  229 + """
  230 + return image_wmts.Api(service_name).result
  231 +
  232 +
  233 +
  234 + @staticmethod
  235 + @bp.route('/WMS', methods=['GET','POST'])
  236 + # @swag_from(image_wms_kv.Api.api_doc)
  237 + def image_wms_kv():
223 """ 238 """
224 WMS服务 239 WMS服务
225 """ 240 """
226 - return image_wms.Api().result  
  241 + return image_wms_kv.Api().result
  242 +
  243 +
  244 + @staticmethod
  245 + @bp.route('/WMSTem', methods=['GET','POST'])
  246 + @swag_from(image_wms_temporary.Api.api_doc)
  247 + def image_wms_temporary():
  248 + """
  249 + WMS服务预览
  250 + """
  251 + return image_wms_temporary.Api().result
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/18
  4 +#email: nheweijun@sina.com
@@ -48,7 +48,7 @@ class Api(ApiTemplate): @@ -48,7 +48,7 @@ class Api(ApiTemplate):
48 48
49 file_info = {"name": f, "path": file_path, "size": file_size, "create_time": fctime,"real_size": real_size} 49 file_info = {"name": f, "path": file_path, "size": file_size, "create_time": fctime,"real_size": real_size}
50 50
51 - if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif") or file_path.lower().endswith("img"): 51 + if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif") or file_path.lower().endswith("img") or os.path.isdir(file_path):
52 52
53 exist_image: Image = Image.query.filter_by(path=os.path.normpath(file_info.get("path")), 53 exist_image: Image = Image.query.filter_by(path=os.path.normpath(file_info.get("path")),
54 size=file_info.get("real_size")).one_or_none() 54 size=file_info.get("real_size")).one_or_none()
@@ -57,19 +57,33 @@ class Api(ApiTemplate): @@ -57,19 +57,33 @@ class Api(ApiTemplate):
57 if exist_image.server.__contains__(data_server): 57 if exist_image.server.__contains__(data_server):
58 file_info["exist"] = True 58 file_info["exist"] = True
59 59
  60 + file_info["type"] = ImageType.get_type(file_path)
  61 + data_list.append(file_info)
60 62
61 - file_info["type"] = ImageType.get_type(file_path)  
62 - data_list.append(file_info)  
63 63
  64 + info_dir = []
  65 + info_img = []
  66 + for dat in data_list:
64 67
65 - data_list_sorted = sorted(data_list, key=lambda x: x["name"])  
66 - res["data"] = data_list_sorted 68 + if dat["type"].__eq__("dir"):
  69 + info_dir.append(dat)
  70 + else:
  71 + info_img.append(dat)
  72 +
  73 + info_dir = sorted(info_dir,key = lambda x: x["name"])
  74 + info_img = sorted(info_img,key = lambda x: x["name"])
  75 + info_dir.extend(info_img)
  76 +
  77 + res["data"] = info_dir
67 78
68 else: 79 else:
69 thrift_connect = ThriftConnect(data_server) 80 thrift_connect = ThriftConnect(data_server)
70 info= json.loads(thrift_connect.client.getImageList(path)) 81 info= json.loads(thrift_connect.client.getImageList(path))
71 thrift_connect.close() 82 thrift_connect.close()
72 83
  84 +
  85 + info_dir = []
  86 + info_img = []
73 for inf in info: 87 for inf in info:
74 if inf["path"].lower().endswith("tiff") or inf["path"].lower().endswith("tif") or inf["path"].lower().endswith("img"): 88 if inf["path"].lower().endswith("tiff") or inf["path"].lower().endswith("tif") or inf["path"].lower().endswith("img"):
75 89
@@ -80,7 +94,16 @@ class Api(ApiTemplate): @@ -80,7 +94,16 @@ class Api(ApiTemplate):
80 if exist_image.server.__contains__(data_server): 94 if exist_image.server.__contains__(data_server):
81 inf["exist"] = True 95 inf["exist"] = True
82 96
83 - res["data"] = info 97 + if inf["type"].__eq__("dir"):
  98 + info_dir.append(inf)
  99 + else:
  100 + info_img.append(inf)
  101 +
  102 + info_dir = sorted(info_dir, key = lambda x: x["name"])
  103 + info_img = sorted(info_img, key = lambda x: x["name"])
  104 + info_dir.extend(info_img)
  105 +
  106 + res["data"] = info_dir
84 107
85 res["result"] = True 108 res["result"] = True
86 109
@@ -4,18 +4,12 @@ @@ -4,18 +4,12 @@
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
6 6
7 -from osgeo import gdal,ogr,osr  
8 -from osgeo.gdal import Dataset,Band  
9 from app.util.component.ApiTemplate import ApiTemplate 7 from app.util.component.ApiTemplate import ApiTemplate
10 -from app.modules.service.image.util.ThriftConnect import ThriftConnect  
11 import json 8 import json
12 from .models import Image 9 from .models import Image
13 import datetime 10 import datetime
14 from app.models import db 11 from app.models import db
15 -import uuid  
16 -import os  
17 -from .models import ImageTag  
18 -import math 12 +
19 13
20 class Api(ApiTemplate): 14 class Api(ApiTemplate):
21 15
@@ -6,14 +6,12 @@ @@ -6,14 +6,12 @@
6 6
7 7
8 from app.util.component.ApiTemplate import ApiTemplate 8 from app.util.component.ApiTemplate import ApiTemplate
9 -from app.util.component.ModelVisitor import ModelVisitor  
10 -  
11 from app.modules.service.image.models import Image,db,ImageTag 9 from app.modules.service.image.models import Image,db,ImageTag
12 -from sqlalchemy import or_,and_  
13 import datetime 10 import datetime
  11 +
14 class Api(ApiTemplate): 12 class Api(ApiTemplate):
15 13
16 - api_name = "影像数据List" 14 + api_name = "修改影像数据"
17 15
18 def process(self): 16 def process(self):
19 17
@@ -28,7 +26,8 @@ class Api(ApiTemplate): @@ -28,7 +26,8 @@ class Api(ApiTemplate):
28 this_time = datetime.datetime.now() 26 this_time = datetime.datetime.now()
29 27
30 del para["guid"] 28 del para["guid"]
31 - del para["tag_guids"] 29 + if para.get("tag_guids"):
  30 + del para["tag_guids"]
32 31
33 if para or tag_guids: 32 if para or tag_guids:
34 para["update_time"] = this_time 33 para["update_time"] = this_time
@@ -58,7 +57,7 @@ class Api(ApiTemplate): @@ -58,7 +57,7 @@ class Api(ApiTemplate):
58 {"name": "alias", 57 {"name": "alias",
59 "in": "formData", 58 "in": "formData",
60 "type": "string"}, 59 "type": "string"},
61 - {"name": "ym", 60 + {"name": "collect_time",
62 "in": "formData", 61 "in": "formData",
63 "type": "string","description":"成像时间字符串"}, 62 "type": "string","description":"成像时间字符串"},
64 {"name": "region", 63 {"name": "region",
@@ -67,9 +66,12 @@ class Api(ApiTemplate): @@ -67,9 +66,12 @@ class Api(ApiTemplate):
67 {"name": "satellite", 66 {"name": "satellite",
68 "in": "formData", 67 "in": "formData",
69 "type": "string", "description": "卫星类型"}, 68 "type": "string", "description": "卫星类型"},
70 - {"name": "epsg", 69 + {"name": "crs",
71 "in": "formData", 70 "in": "formData",
72 "type": "string", "description": "空间参考"}, 71 "type": "string", "description": "空间参考"},
  72 + {"name": "band_view",
  73 + "in": "formData",
  74 + "type": "string", "description": "波段设计[1,1,1]"},
73 {"name": "tag_guids", 75 {"name": "tag_guids",
74 "in": "formData", 76 "in": "formData",
75 "type": "string", "description": "tags"}, 77 "type": "string", "description": "tags"},
@@ -8,8 +8,8 @@ from app.util.component.ApiTemplate import ApiTemplate @@ -8,8 +8,8 @@ from app.util.component.ApiTemplate import ApiTemplate
8 from app.util.component.ModelVisitor import ModelVisitor 8 from app.util.component.ModelVisitor import ModelVisitor
9 9
10 from app.modules.service.image.models import Image,ImageTag 10 from app.modules.service.image.models import Image,ImageTag
11 -from sqlalchemy import or_,and_  
12 from app.util.component.FileProcess import FileProcess 11 from app.util.component.FileProcess import FileProcess
  12 +
13 class Api(ApiTemplate): 13 class Api(ApiTemplate):
14 14
15 api_name = "影像数据Info" 15 api_name = "影像数据Info"
@@ -8,7 +8,9 @@ from app.util.component.ApiTemplate import ApiTemplate @@ -8,7 +8,9 @@ from app.util.component.ApiTemplate import ApiTemplate
8 from app.util.component.ModelVisitor import ModelVisitor 8 from app.util.component.ModelVisitor import ModelVisitor
9 from app.util.component.FileProcess import FileProcess 9 from app.util.component.FileProcess import FileProcess
10 from app.modules.service.image.models import Image,ImageTag 10 from app.modules.service.image.models import Image,ImageTag
11 -from sqlalchemy import or_,and_ 11 +from sqlalchemy import or_
  12 +import datetime
  13 +
12 class Api(ApiTemplate): 14 class Api(ApiTemplate):
13 15
14 api_name = "影像数据List" 16 api_name = "影像数据List"
@@ -26,6 +28,7 @@ class Api(ApiTemplate): @@ -26,6 +28,7 @@ class Api(ApiTemplate):
26 band = self.para.get("band") 28 band = self.para.get("band")
27 region = self.para.get("region") 29 region = self.para.get("region")
28 tag_guid = self.para.get("tag_guid") 30 tag_guid = self.para.get("tag_guid")
  31 + collect_time = self.para.get("collect_time")
29 32
30 type = self.para.get("type") 33 type = self.para.get("type")
31 34
@@ -48,12 +51,20 @@ class Api(ApiTemplate): @@ -48,12 +51,20 @@ class Api(ApiTemplate):
48 if region: 51 if region:
49 images = images.filter(Image.region.in_(region.split(","))) 52 images = images.filter(Image.region.in_(region.split(",")))
50 53
  54 + if collect_time:
  55 + begin,end = collect_time.split(",")
  56 + begin = datetime.datetime.strptime(begin,"%Y-%m-%d %H:%M:%S")
  57 + end = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
  58 + images.filter(Image.collect_time>=begin).filter(Image.collect_time<=end)
  59 +
51 if tag_guid: 60 if tag_guid:
52 tag:ImageTag = ImageTag.query.filter_by(guid=tag_guid).one_or_none() 61 tag:ImageTag = ImageTag.query.filter_by(guid=tag_guid).one_or_none()
53 images_guid = [img.guid for img in tag.images.all()] 62 images_guid = [img.guid for img in tag.images.all()]
54 images = images.filter(Image.guid.in_(images_guid)) 63 images = images.filter(Image.guid.in_(images_guid))
55 64
56 65
  66 +
  67 +
57 res["data"] = {} 68 res["data"] = {}
58 res["data"]["count"] = images.count() 69 res["data"]["count"] = images.count()
59 imgs = images.limit(page_size).offset(page_index * page_size).all() 70 imgs = images.limit(page_size).offset(page_index * page_size).all()
@@ -89,7 +100,7 @@ class Api(ApiTemplate): @@ -89,7 +100,7 @@ class Api(ApiTemplate):
89 {"name": "name", 100 {"name": "name",
90 "in": "formData", 101 "in": "formData",
91 "type": "string"}, 102 "type": "string"},
92 - {"name": "ym", 103 + {"name": "collect_time",
93 "in": "formData", 104 "in": "formData",
94 "type": "string"}, 105 "type": "string"},
95 {"name": "region", 106 {"name": "region",
@@ -64,7 +64,7 @@ class Api(ApiTemplate): @@ -64,7 +64,7 @@ class Api(ApiTemplate):
64 64
65 bands = json.loads(image.band_view) 65 bands = json.loads(image.band_view)
66 66
67 - # bands = [1,2,3] if image.band_count>=3 else [1,1,1] 67 +
68 68
69 #计算查询范围,保持正常比例 69 #计算查询范围,保持正常比例
70 query_extent = json.loads(image.extent) 70 query_extent = json.loads(image.extent)
@@ -83,20 +83,17 @@ class Api(ApiTemplate): @@ -83,20 +83,17 @@ class Api(ApiTemplate):
83 pixel_array = numpy.zeros((height, width, 3), dtype=int) 83 pixel_array = numpy.zeros((height, width, 3), dtype=int)
84 84
85 for ii in [0, 1, 2]: 85 for ii in [0, 1, 2]:
86 - # opencv 颜色排序为GBR 86 + # opencv 颜色排序为BGR
87 pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] 87 pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
88 88
89 # 将图片生成在内存中,然后直接返回response 89 # 将图片生成在内存中,然后直接返回response
90 im_data = Opencv.create_image(format, pixel_array, 30) 90 im_data = Opencv.create_image(format, pixel_array, 30)
91 91
92 - return Response(im_data, mimetype=format)  
93 -  
94 except Exception as e: 92 except Exception as e:
95 StructurePrint().print(traceback.format_exc()) 93 StructurePrint().print(traceback.format_exc())
96 - res["state"] = -1  
97 - res["message"] = e.__str__()  
98 - return res 94 + raise e
99 95
  96 + return Response(im_data, mimetype=format)
100 97
101 api_doc = { 98 api_doc = {
102 "tags": ["影像接口"], 99 "tags": ["影像接口"],
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
6 6
7 -from osgeo import gdal,ogr,osr 7 +from osgeo import gdal,osr
8 from osgeo.gdal import Dataset,Band 8 from osgeo.gdal import Dataset,Band
9 from app.util.component.ApiTemplate import ApiTemplate 9 from app.util.component.ApiTemplate import ApiTemplate
10 from app.modules.service.image.util.ThriftConnect import ThriftConnect 10 from app.modules.service.image.util.ThriftConnect import ThriftConnect
@@ -15,7 +15,6 @@ from app.models import db @@ -15,7 +15,6 @@ from app.models import db
15 import uuid 15 import uuid
16 import os 16 import os
17 from .models import ImageTag 17 from .models import ImageTag
18 -import math  
19 from .util.ImageType import ImageType 18 from .util.ImageType import ImageType
20 19
21 class Api(ApiTemplate): 20 class Api(ApiTemplate):
@@ -60,8 +59,9 @@ class Api(ApiTemplate): @@ -60,8 +59,9 @@ class Api(ApiTemplate):
60 left_top = (geo[0], geo[3]) 59 left_top = (geo[0], geo[3])
61 60
62 right_buttom = (geo[0] + geo[1] * image.RasterXSize, geo[3] + geo[5] * image.RasterYSize) 61 right_buttom = (geo[0] + geo[1] * image.RasterXSize, geo[3] + geo[5] * image.RasterYSize)
63 - origin_extent = [left_top[0], right_buttom[0], right_buttom[1], left_top[1]]  
64 62
  63 +
  64 + origin_extent = [left_top[0], right_buttom[1], right_buttom[0], left_top[1]]
65 # target = origin.CloneGeogCS() 65 # target = origin.CloneGeogCS()
66 # tran = osr.CoordinateTransformation(origin, target) 66 # tran = osr.CoordinateTransformation(origin, target)
67 # 67 #
@@ -134,9 +134,9 @@ class Api(ApiTemplate): @@ -134,9 +134,9 @@ class Api(ApiTemplate):
134 server=data_server, 134 server=data_server,
135 path = os.path.normpath(info.get("path")), 135 path = os.path.normpath(info.get("path")),
136 size=info.get("size"), 136 size=info.get("size"),
137 - epsg= info.get("epsg"),  
138 - sr_wkt = info.get("sr_wkt"),  
139 - sr_proj4= info.get("sr_proj4"), 137 + crs = str(info.get("crs")),
  138 + crs_wkt = info.get("crs_wkt"),
  139 + crs_proj4= info.get("crs_proj4"),
140 band_count=info.get("band_count"), 140 band_count=info.get("band_count"),
141 band_view = "[1,2,3]" if info.get("band_count")>=3 else "[1,1,1]", 141 band_view = "[1,2,3]" if info.get("band_count")>=3 else "[1,1,1]",
142 create_time=this_time, 142 create_time=this_time,
@@ -32,7 +32,7 @@ class Api(ApiTemplate): @@ -32,7 +32,7 @@ class Api(ApiTemplate):
32 service_update = {} 32 service_update = {}
33 image_update = {} 33 image_update = {}
34 for key in self.para.keys(): 34 for key in self.para.keys():
35 - if key in ["name","title","state","description","catalog_guid"]: 35 + if key in ["name","title","state","description","catalog_guid","type"]:
36 service_update[key] = self.para.get(key) 36 service_update[key] = self.para.get(key)
37 if key in ["name","scheme_guid"]: 37 if key in ["name","scheme_guid"]:
38 image_update[key] = self.para.get(key) 38 image_update[key] = self.para.get(key)
@@ -98,6 +98,11 @@ class Api(ApiTemplate): @@ -98,6 +98,11 @@ class Api(ApiTemplate):
98 "type": "string", 98 "type": "string",
99 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 99 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
100 100
  101 + {"name": "type",
  102 + "in": "formData",
  103 + "type": "string",
  104 + "description": "修改服务类型"},
  105 +
101 {"name": "title", 106 {"name": "title",
102 "in": "formData", 107 "in": "formData",
103 "type": "string", 108 "type": "string",
@@ -3,11 +3,10 @@ @@ -3,11 +3,10 @@
3 #createtime: 2021/7/19 3 #createtime: 2021/7/19
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
6 -from app.modules.service.image.models import ImageService,Image 6 +from app.modules.service.image.models import ImageService
7 7
8 from app.util.component.ApiTemplate import ApiTemplate 8 from app.util.component.ApiTemplate import ApiTemplate
9 from app.util.component.ModelVisitor import ModelVisitor 9 from app.util.component.ModelVisitor import ModelVisitor
10 -from app.models import Service  
11 from sqlalchemy import or_ 10 from sqlalchemy import or_
12 class Api(ApiTemplate): 11 class Api(ApiTemplate):
13 12
@@ -7,8 +7,7 @@ from .models import ImageService,Image @@ -7,8 +7,7 @@ from .models import ImageService,Image
7 from app.models import db,Service 7 from app.models import db,Service
8 from app.util.component.ApiTemplate import ApiTemplate 8 from app.util.component.ApiTemplate import ApiTemplate
9 import uuid 9 import uuid
10 -from app.util.component.SliceScheme import SliceScheme  
11 -from app.util.component.FileProcess import FileProcess 10 +
12 import os 11 import os
13 import json 12 import json
14 import datetime 13 import datetime
@@ -93,7 +92,7 @@ class Api(ApiTemplate): @@ -93,7 +92,7 @@ class Api(ApiTemplate):
93 92
94 def get_overview(self,service,image_service): 93 def get_overview(self,service,image_service):
95 94
96 - api = RealApi() 95 + api = RealApi("")
97 96
98 97
99 query_extent = json.loads(image_service.extent) 98 query_extent = json.loads(image_service.extent)
@@ -106,7 +105,7 @@ class Api(ApiTemplate): @@ -106,7 +105,7 @@ class Api(ApiTemplate):
106 105
107 bbox = ",".join([str(x) for x in query_extent]) 106 bbox = ",".join([str(x) for x in query_extent])
108 107
109 - api.para = {"guid":image_service.guid,"bbox":bbox,"overview":1,"width":512,"height":512} 108 + api.para = {"service_name":service.name,"bbox":bbox,"overview":1,"width":512,"height":512}
110 res = api.process() 109 res = api.process()
111 dir_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "overview") 110 dir_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "overview")
112 gid = uuid.uuid1().__str__() 111 gid = uuid.uuid1().__str__()
@@ -5,9 +5,6 @@ @@ -5,9 +5,6 @@
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 kazoo.client import KazooClient  
10 -import configure  
11 from .models import ImageTag 8 from .models import ImageTag
12 import uuid 9 import uuid
13 from app.models import db 10 from app.models import db
@@ -6,8 +6,6 @@ @@ -6,8 +6,6 @@
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 8 from app.util.component.ModelVisitor import ModelVisitor
9 -from kazoo.client import KazooClient  
10 -import configure  
11 from .models import ImageTag 9 from .models import ImageTag
12 class Api(ApiTemplate): 10 class Api(ApiTemplate):
13 11
@@ -3,27 +3,15 @@ @@ -3,27 +3,15 @@
3 #createtime: 2021/3/24 3 #createtime: 2021/3/24
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
6 -from app.util import *  
7 import traceback 6 import traceback
8 -from osgeo import gdal  
9 -from osgeo.gdal import *  
10 -from numpy import ndarray  
11 import numpy 7 import numpy
12 from flask import Response 8 from flask import Response
13 from .util.ImageData import ImageData 9 from .util.ImageData import ImageData
14 10
15 -import time  
16 -import cv2  
17 -from app.modules.service.image.models import ImageService,Image  
18 -from app.models import db,TileScheme  
19 from app.util.component.ApiTemplate import ApiTemplate 11 from app.util.component.ApiTemplate import ApiTemplate
20 from app.util.component.SliceScheme import SliceScheme 12 from app.util.component.SliceScheme import SliceScheme
21 from app.util.component.ParameterUtil import ParameterUtil 13 from app.util.component.ParameterUtil import ParameterUtil
22 import json 14 import json
23 -from kazoo.client import KazooClient  
24 -from threading import Thread  
25 -from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPool  
26 -import gzip  
27 import random 15 import random
28 import copy 16 import copy
29 from .util.Opencv import Opencv 17 from .util.Opencv import Opencv
@@ -10,22 +10,19 @@ from osgeo.gdal import * @@ -10,22 +10,19 @@ from osgeo.gdal import *
10 from numpy import ndarray 10 from numpy import ndarray
11 import numpy 11 import numpy
12 from flask import Response 12 from flask import Response
13 -import io  
14 -import os  
15 -from PIL import Image  
16 13
17 import time 14 import time
18 import cv2 15 import cv2
19 from app.modules.service.image.models import ImageService,Image 16 from app.modules.service.image.models import ImageService,Image
20 from app.models import db,TileScheme 17 from app.models import db,TileScheme
21 from app.util.component.ApiTemplate import ApiTemplate 18 from app.util.component.ApiTemplate import ApiTemplate
22 -import uuid 19 +
23 from app.util.component.SliceScheme import SliceScheme 20 from app.util.component.SliceScheme import SliceScheme
24 -from app.util.component.FileProcess import FileProcess 21 +
25 from app.util.component.ParameterUtil import ParameterUtil 22 from app.util.component.ParameterUtil import ParameterUtil
26 from app.util.component.GeometryAdapter import GeometryAdapter 23 from app.util.component.GeometryAdapter import GeometryAdapter
27 from app.util.component.Geometry2Raster import Geometry2Raster 24 from app.util.component.Geometry2Raster import Geometry2Raster
28 -import os 25 +
29 import json 26 import json
30 from kazoo.client import KazooClient 27 from kazoo.client import KazooClient
31 28
@@ -61,6 +58,7 @@ class Api(ApiTemplate): @@ -61,6 +58,7 @@ class Api(ApiTemplate):
61 58
62 #缓存服务信息 59 #缓存服务信息
63 image_service_info = GLOBAL_DIC.get(self.guid) 60 image_service_info = GLOBAL_DIC.get(self.guid)
  61 +
64 if image_service_info is None: 62 if image_service_info is None:
65 image_service:ImageService = ImageService.query.filter_by(guid = self.guid).one_or_none() 63 image_service:ImageService = ImageService.query.filter_by(guid = self.guid).one_or_none()
66 images = image_service.images.all() 64 images = image_service.images.all()
@@ -21,6 +21,11 @@ class Api(ApiTemplate): @@ -21,6 +21,11 @@ class Api(ApiTemplate):
21 21
22 api_name = "WMS" 22 api_name = "WMS"
23 23
  24 +
  25 + def __init__(self,service_name):
  26 + super().__init__()
  27 + self.service_name = service_name
  28 +
24 def process(self): 29 def process(self):
25 30
26 31
@@ -30,21 +35,21 @@ class Api(ApiTemplate): @@ -30,21 +35,21 @@ class Api(ApiTemplate):
30 try: 35 try:
31 36
32 parameter = ParameterUtil.to_lower(parameter) 37 parameter = ParameterUtil.to_lower(parameter)
33 - self.guid = parameter.get("guid")  
34 - bbox = parameter.get("bbox")  
35 - width = int(parameter.get("width")) if parameter.get("width") else 256  
36 - height = int(parameter.get("height")) if parameter.get("height") else 256  
37 - image_type = parameter.get("format") if parameter.get("format") else "image/png"  
38 - quality = int(parameter.get("quality")) if parameter.get("quality") else 30 38 + if parameter.get("service_name"):
  39 + self.service_name = parameter.get("service_name")
39 40
40 - image_service_info, zoo, servers = Cache.cache_data(self.guid) 41 + #获取缓存信息
  42 + image_service_info, zoo, servers = Cache.cache_data(self.service_name, type="name")
41 43
42 re = parameter.get("request") 44 re = parameter.get("request")
43 if re and re.__eq__("GetCapabilities"): 45 if re and re.__eq__("GetCapabilities"):
44 return self.get_capabilities(image_service_info["service"]) 46 return self.get_capabilities(image_service_info["service"])
45 47
46 -  
47 - # bands = [1, 2, 3] 48 + bbox = parameter.get("bbox")
  49 + width = int(parameter.get("width")) if parameter.get("width") else 256
  50 + height = int(parameter.get("height")) if parameter.get("height") else 256
  51 + image_type = parameter.get("format") if parameter.get("format") else "image/png"
  52 + quality = int(parameter.get("quality")) if parameter.get("quality") else 30
48 53
49 extent = [float(x) for x in bbox.split(",")] 54 extent = [float(x) for x in bbox.split(",")]
50 55
@@ -267,6 +272,10 @@ class Api(ApiTemplate): @@ -267,6 +272,10 @@ class Api(ApiTemplate):
267 {"name": "guid", 272 {"name": "guid",
268 "in": "query", 273 "in": "query",
269 "type": "string"}, 274 "type": "string"},
  275 + {"name": "request",
  276 + "in": "query",
  277 + "type": "string",
  278 + "enum":["GetMap","GetCapabilities"]},
270 {"name": "bbox", 279 {"name": "bbox",
271 "in": "query", 280 "in": "query",
272 "type": "string"}, 281 "type": "string"},
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/3/24
  4 +#email: nheweijun@sina.com
  5 +
  6 +from app.util import *
  7 +import traceback
  8 +import numpy
  9 +from flask import Response
  10 +import random
  11 +from app.modules.service.image.models import ImageService
  12 +from app.util.component.ApiTemplate import ApiTemplate
  13 +from app.util.component.ParameterUtil import ParameterUtil
  14 +import json
  15 +from threading import Thread
  16 +from .util.ImageData import ImageData
  17 +from .util.Cache import Cache
  18 +from .util.Opencv import Opencv
  19 +
  20 +class Api(ApiTemplate):
  21 +
  22 + api_name = "WMS"
  23 +
  24 + def process(self):
  25 +
  26 +
  27 + result = {}
  28 + parameter: dict = self.para
  29 +
  30 + try:
  31 +
  32 + parameter = ParameterUtil.to_lower(parameter)
  33 + if parameter.get("guid"):
  34 + self.guid = parameter.get("guid")
  35 +
  36 + #获取缓存信息
  37 + if parameter.get("guid"):
  38 +
  39 + image_service_info, zoo, servers = Cache.cache_data(self.guid, type="guid")
  40 + else:
  41 + image_service_info, zoo, servers = Cache.cache_data(parameter.get("service_name"), type="name")
  42 +
  43 + re = parameter.get("request")
  44 + if re and re.__eq__("GetCapabilities"):
  45 + return self.get_capabilities(image_service_info["service"])
  46 +
  47 + bbox = parameter.get("bbox")
  48 + width = int(parameter.get("width")) if parameter.get("width") else 256
  49 + height = int(parameter.get("height")) if parameter.get("height") else 256
  50 + image_type = parameter.get("format") if parameter.get("format") else "image/png"
  51 + quality = int(parameter.get("quality")) if parameter.get("quality") else 30
  52 +
  53 +
  54 +
  55 + extent = [float(x) for x in bbox.split(",")]
  56 +
  57 + intersect_image = [im for im in image_service_info["images"] if self.determin_intersect(json.loads(im.extent),extent)]
  58 +
  59 + if len(intersect_image)>1:
  60 +
  61 + # 结果矩阵
  62 + empty_list = [numpy.zeros((height,width), dtype=int) + 65536,
  63 + numpy.zeros((height,width), dtype=int) + 65536,
  64 + numpy.zeros((height,width), dtype=int) + 65536]
  65 +
  66 + pixel_array = numpy.zeros((height,width,3), dtype=int)
  67 + thread_list = []
  68 +
  69 + for image in intersect_image:
  70 + #该影像的服务器,随机选取一个
  71 + image_servers = image.server.split(",")
  72 + image_servers = [ser for ser in image_servers if ser in servers]
  73 + if len(image_servers)>0:
  74 + indx = int(random.random() * len(image_servers))
  75 + image_server = image_servers[indx]
  76 + else:
  77 + image_server = "None"
  78 + bands = json.loads(image.band_view)
  79 +
  80 + image_data = ImageData(image_server, image)
  81 +
  82 + thread: MyThread = MyThread(image_data.get_data, args=(extent,bands,height,width))
  83 + thread.start()
  84 + thread_list.append(thread)
  85 +
  86 +
  87 + for thread in thread_list:
  88 + thread.join()
  89 + data = thread.get_result()
  90 +
  91 + # 掩膜在中央接口生成,合图
  92 + mask = numpy.zeros((height,width), dtype=int)
  93 + mask2 = numpy.zeros((height,width), dtype=int)
  94 + jizhun = data[:, :, 0]
  95 + mask[jizhun == 65536] = 1
  96 + mask[jizhun != 65536] = 0
  97 + mask2[jizhun == 65536] = 0
  98 + mask2[jizhun != 65536] = 1
  99 + # 掩膜计算
  100 + for i, d in enumerate(empty_list):
  101 + empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2
  102 +
  103 + for ii in [0, 1, 2]:
  104 + # opencv 颜色排序为GBR
  105 + pixel_array[:, :, 2 - ii] = empty_list[ii]
  106 +
  107 +
  108 + elif len(intersect_image)==1:
  109 + # 该影像的服务器,随机选取一个
  110 + image = intersect_image[0]
  111 + image_servers = image.server.split(",")
  112 + image_servers = [ser for ser in image_servers if ser in servers]
  113 + if len(image_servers) > 0:
  114 + indx = int(random.random() * len(image_servers))
  115 + image_server = image_servers[indx]
  116 + else:
  117 + image_server = "None"
  118 +
  119 + bands = json.loads(image.band_view)
  120 +
  121 + image_data = ImageData(image_server, image)
  122 +
  123 + pixel_array_t = image_data.get_data(extent,bands,height,width)
  124 +
  125 + pixel_array = numpy.zeros((height, width, 3), dtype=int)
  126 + for ii in [0, 1, 2]:
  127 + # opencv 颜色排序为GBR
  128 + pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
  129 + else:
  130 + # 结果矩阵
  131 + pixel_array = numpy.zeros((height, width, 3), dtype=int)+65536
  132 +
  133 + # 将图片生成在内存中,然后直接返回response
  134 + im_data = Opencv.create_image(image_type, pixel_array, quality)
  135 +
  136 + if self.para.get("overview"):
  137 + return pixel_array
  138 + return Response(im_data, mimetype=image_type.lower())
  139 +
  140 + except Exception as e:
  141 + print(traceback.format_exc())
  142 + result["state"] = -1
  143 + result["message"] = e.__str__()
  144 + return result
  145 +
  146 +
  147 +
  148 + def determin_intersect(self, extent1, extent2):
  149 + if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
  150 + 3] or extent2[3] < extent1[1]:
  151 + return False
  152 + else:
  153 + return True
  154 +
  155 + def get_capabilities(self,image_service:ImageService):
  156 +
  157 + xml = '''<?xml version="1.0" encoding="utf-8" ?>
  158 + <WMS_Capabilities version="1.2.0">
  159 + <Service>
  160 + <Name>WMS</Name>
  161 + <Title>{service_title}</Title>
  162 + <Abstract>{abstract}</Abstract>
  163 + <Keywords>GIMS</Keywords>
  164 + <OnlineResource/>
  165 + <Fees>none</Fees>
  166 + <AccessConstraints>none</AccessConstraints>
  167 + </Service>
  168 + <Capability>
  169 + <Request>
  170 + <GetCapabilities>
  171 + <Format>text/xml</Format>
  172 + <DCPType>
  173 + <HTTP>
  174 + <Get>
  175 + <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
  176 + </Get>
  177 + </HTTP>
  178 + </DCPType>
  179 + </GetCapabilities>
  180 + <GetMap>
  181 + <Format>png</Format>
  182 + <Format>jpeg</Format>
  183 + <Format>gif</Format>
  184 + <Format>image/png</Format>
  185 + <Format>image/jpeg</Format>
  186 + <Format>image/gif</Format>
  187 + <DCPType>
  188 + <HTTP>
  189 + <Get>
  190 + <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
  191 + </Get>
  192 + </HTTP>
  193 + </DCPType>
  194 + </GetMap>
  195 + <Map>
  196 + <Format>
  197 + <PNG/>
  198 + <GIF/>
  199 + <JPG/>
  200 + </Format>
  201 + <DCPType>
  202 + <HTTP>
  203 + <Get onlineResource="{url}"/>
  204 + </HTTP>
  205 + </DCPType>
  206 + </Map>
  207 + <Capabilities>
  208 + <Format>
  209 + <WMS_XML/>
  210 + </Format>
  211 + <DCPType>
  212 + <HTTP>
  213 + <Get onlineResource="{url}"/>
  214 + </HTTP>
  215 + </DCPType>
  216 + </Capabilities>
  217 + <FeatureInfo>
  218 + <Format>
  219 + <XML/>
  220 + <MIME/>
  221 + </Format>
  222 + <DCPType>
  223 + <HTTP>
  224 + <Get onlineResource="{url}"/>
  225 + </HTTP>
  226 + </DCPType>
  227 + </FeatureInfo>
  228 + </Request>
  229 + <Exception>
  230 + <Format>
  231 + <WMS_XML/>
  232 + <INIMAGE/>
  233 + <BLANK/>
  234 + </Format>
  235 + </Exception>
  236 + <Layer>
  237 + <Name>{service_name}</Name>
  238 + <Title>{service_title}</Title>
  239 + <CRS>{crs}</CRS>
  240 + <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>
  241 +
  242 + <Layer queryable="1">
  243 + <CRS>{crs}</CRS>
  244 + <Name>{layer_name}</Name>
  245 + <Title>{layer_title}</Title>
  246 + <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>
  247 + </Layer>
  248 + </Layer>
  249 + </Capability>
  250 + </WMS_Capabilities>'''
  251 +
  252 + extent = json.loads(image_service.extent)
  253 + xml = xml.format(service_title=image_service.name,
  254 + service_name=image_service.name,
  255 + abstract= "None" ,
  256 + crs="ESPG:4326",
  257 + layer_name=image_service.name,
  258 + layer_title=image_service.name,
  259 + maxx=extent[2],
  260 + maxy = extent[3],
  261 + minx = extent[0],
  262 + miny = extent[1],
  263 + url="http://{}/API/Service/Image/WMS?guid={}".format(configure.deploy_ip_host,image_service.guid))
  264 +
  265 +
  266 + r = Response(response=xml, status=200, mimetype="application/xml")
  267 + r.headers["Content-Type"] = "text/xml; charset=utf-8"
  268 + return r
  269 +
  270 + api_doc = {
  271 + "tags": ["影像接口"],
  272 + "parameters": [
  273 + {"name": "guid",
  274 + "in": "query",
  275 + "type": "string"},
  276 + {"name": "bbox",
  277 + "in": "query",
  278 + "type": "string"},
  279 + {"name": "width",
  280 + "in": "query",
  281 + "type": "string"},
  282 + {"name": "height",
  283 + "in": "query",
  284 + "type": "string"},
  285 + {"name": "format",
  286 + "in": "query",
  287 + "type": "string"},
  288 + {"name": "quality",
  289 + "in": "query",
  290 + "type": "string"}
  291 + ],
  292 + "responses": {
  293 + 200: {
  294 + "schema": {
  295 + "properties": {
  296 + }
  297 + }
  298 + }
  299 + }
  300 + }
  301 +
  302 +class MyThread(Thread):
  303 + def __init__(self,func,args=()):
  304 + super(MyThread,self).__init__()
  305 + self.func = func
  306 + self.args = args
  307 + def run(self):
  308 + self.result = self.func(*self.args)
  309 + def get_result(self):
  310 + try:
  311 + return self.result
  312 + except Exception:
  313 + return None
  314 +
  315 +
  316 +
@@ -9,7 +9,7 @@ import numpy @@ -9,7 +9,7 @@ import numpy
9 from flask import Response 9 from flask import Response
10 import random 10 import random
11 11
12 -from app.modules.service.image.models import ImageService,Image 12 +from app.modules.service.image.models import Image
13 from app.util.component.ApiTemplate import ApiTemplate 13 from app.util.component.ApiTemplate import ApiTemplate
14 14
15 from app.util.component.ParameterUtil import ParameterUtil 15 from app.util.component.ParameterUtil import ParameterUtil
@@ -36,6 +36,25 @@ class Api(ApiTemplate): @@ -36,6 +36,25 @@ class Api(ApiTemplate):
36 parameter = ParameterUtil.to_lower(parameter) 36 parameter = ParameterUtil.to_lower(parameter)
37 37
38 image_guids = parameter.get("image_guids") 38 image_guids = parameter.get("image_guids")
  39 +
  40 + get_extent = parameter.get("get_extent")
  41 + if get_extent and (get_extent == True or get_extent.lower().__eq__("true")):
  42 + tmp_extent = []
  43 + for g in image_guids.split(","):
  44 + image = Image.query.filter_by(guid=g).one_or_none()
  45 + if image:
  46 + image_extent = json.loads(image.extent)
  47 + if not tmp_extent:
  48 + tmp_extent = image_extent
  49 + else:
  50 + tmp_extent[0] = min(image_extent[0], tmp_extent[0])
  51 + tmp_extent[2] = max(image_extent[2], tmp_extent[2])
  52 + tmp_extent[1] = min(image_extent[1], tmp_extent[1])
  53 + tmp_extent[3] = max(image_extent[3], tmp_extent[3])
  54 +
  55 + result["result"] = True
  56 + result["data"] = tmp_extent
  57 + return result
39 58
40 bbox = parameter.get("bbox") 59 bbox = parameter.get("bbox")
41 width = int(parameter.get("width")) if parameter.get("width") else 256 60 width = int(parameter.get("width")) if parameter.get("width") else 256
@@ -147,9 +166,13 @@ class Api(ApiTemplate): @@ -147,9 +166,13 @@ class Api(ApiTemplate):
147 api_doc = { 166 api_doc = {
148 "tags": ["影像接口"], 167 "tags": ["影像接口"],
149 "parameters": [ 168 "parameters": [
150 - {"name": "guid", 169 + {"name": "image_guids",
151 "in": "query", 170 "in": "query",
152 "type": "string"}, 171 "type": "string"},
  172 + {"name": "get_extent",
  173 + "in": "query",
  174 + "type": "boolean",
  175 + "enum":[True,False]},
153 {"name": "bbox", 176 {"name": "bbox",
154 "in": "query", 177 "in": "query",
155 "type": "string"}, 178 "type": "string"},
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/3/24
  4 +#email: nheweijun@sina.com
  5 +
  6 +from app.util import *
  7 +import traceback
  8 +import numpy
  9 +from flask import Response
  10 +from .util.ImageData import ImageData
  11 +
  12 +from app.modules.service.image.models import ImageService
  13 +from app.models import TileScheme,Service
  14 +from app.util.component.ApiTemplate import ApiTemplate
  15 +from app.util.component.SliceScheme import SliceScheme
  16 +from app.util.component.ParameterUtil import ParameterUtil
  17 +import json
  18 +import random
  19 +import copy
  20 +from .util.Opencv import Opencv
  21 +from .util.Cache import Cache
  22 +from .util.MyThread import MyThread
  23 +
  24 +class Api(ApiTemplate):
  25 +
  26 + api_name = "切片"
  27 +
  28 + def __init__(self,service_name):
  29 + super().__init__()
  30 + self.service_name = service_name
  31 +
  32 + def process(self):
  33 +
  34 + result = {}
  35 + parameter: dict = self.para
  36 +
  37 + try:
  38 + if parameter.get("service_name"):
  39 + self.service_name = parameter.get("service_name")
  40 +
  41 + #获取缓存数据
  42 + image_service_info, zoo, servers = Cache.cache_data(self.service_name,type="name")
  43 +
  44 + # 转换参数
  45 + parameter = ParameterUtil.to_lower(parameter)
  46 +
  47 + re = parameter.get("request")
  48 + if re and re.__eq__("GetCapabilities"):
  49 + service = Service.query.filter_by(guid=image_service_info["service"].service_guid).one_or_none()
  50 + return self.get_capabilities(image_service_info["service"],service)
  51 +
  52 + if parameter.get("tilematrix"):
  53 + if parameter.get("tilematrix").__contains__(":"):
  54 + self.level = int(parameter.get("tilematrix").split(":")[-1])
  55 + else:
  56 + self.level = int(parameter.get("tilematrix"))
  57 + if parameter.get("tilerow"):
  58 + self.row = int(parameter.get("tilerow"))
  59 + if parameter.get("tilecol"):
  60 + self.col = int(parameter.get("tilecol"))
  61 +
  62 + image_type = parameter.get("format") if parameter.get("format") else "image/png"
  63 + quality = int(parameter.get("quality")) if parameter.get("quality") else 30
  64 + slice_para = image_service_info["scheme"]
  65 + extent = SliceScheme.get_polygon(slice_para, self.level, self.row, self.col)
  66 +
  67 + height, width = 256,256
  68 +
  69 + # 多线程获取分布式数据
  70 +
  71 + intersect_image = [im for im in image_service_info["images"] if self.determin_intersect(json.loads(im.extent),extent)]
  72 +
  73 + if len(intersect_image) > 1:
  74 +
  75 + # 结果矩阵
  76 + pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536
  77 +
  78 + thread_list = []
  79 +
  80 + for image in intersect_image:
  81 +
  82 + # 该影像的服务器,随机选取一个
  83 + image_servers = image.server.split(",")
  84 + image_servers = [ser for ser in image_servers if ser in servers]
  85 + if len(image_servers)>0:
  86 + indx = int(random.random() * len(image_servers))
  87 + image_server = image_servers[indx]
  88 + else:
  89 + image_server = "None"
  90 +
  91 + bands = json.loads(image.band_view)
  92 +
  93 + image_data = ImageData(image_server,image)
  94 +
  95 + thread: MyThread = MyThread(image_data.get_data,args=(extent, bands, height, width))
  96 +
  97 + thread.start()
  98 + thread_list.append(thread)
  99 +
  100 + for thread in thread_list:
  101 + thread.join()
  102 + data = thread.get_result()
  103 +
  104 + # 掩膜在中央接口生成,合图
  105 + mask = numpy.zeros((height, width, 3), dtype=int)
  106 + mask_data = numpy.zeros((height, width, 3), dtype=int)
  107 +
  108 + mask[data == 65536] = 1
  109 + mask[data != 65536] = 0
  110 + mask_data[data == 65536] = 0
  111 + mask_data[data != 65536] = 1
  112 +
  113 + # # 掩膜计算
  114 + pixel_array = pixel_array * mask + data * mask_data
  115 +
  116 + # opencv 颜色排序为GBR
  117 + d1 = copy.copy(pixel_array[:,:,0])
  118 + pixel_array[:, :, 0] = pixel_array[:,:,2]
  119 + pixel_array[:, :, 2] = d1
  120 +
  121 +
  122 + elif len(intersect_image) == 1:
  123 + # 该影像的服务器,随机选取一个
  124 + image = intersect_image[0]
  125 + image_servers = image.server.split(",")
  126 + #判断可用服务器
  127 + image_servers = [ser for ser in image_servers if ser in servers]
  128 + if len(image_servers) > 0:
  129 + indx = int(random.random() * len(image_servers))
  130 + image_server = image_servers[indx]
  131 + else:
  132 + image_server = "None"
  133 + # image_server = image_servers[0]
  134 + bands = json.loads(image.band_view)
  135 +
  136 + image_data = ImageData(image_server, image)
  137 + pixel_array_t: numpy.ndarray = image_data.get_data(extent, bands, height, width)
  138 + pixel_array = numpy.zeros((height, width, 3), dtype=int)
  139 +
  140 + for ii in [0, 1, 2]:
  141 + # opencv 颜色排序为GBR
  142 + pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
  143 +
  144 + else:
  145 + # 结果矩阵
  146 + pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536
  147 +
  148 +
  149 +
  150 +
  151 + # 将图片生成在内存中,然后直接返回response
  152 + im_data = Opencv.create_image(image_type, pixel_array, quality)
  153 + return Response(im_data, mimetype=image_type.lower())
  154 +
  155 +
  156 + except Exception as e:
  157 + print(traceback.format_exc())
  158 + result["state"] = -1
  159 + result["message"] = e.__str__()
  160 + return result
  161 +
  162 + def get_capabilities(self, image_service: ImageService, service: Service):
  163 + tile_scheme: TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none()
  164 + if not tile_scheme:
  165 + raise Exception("切片方案不存在!")
  166 +
  167 + xml = '''<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
  168 + <!-- Service Identification -->
  169 + <ows:ServiceIdentification>
  170 + <ows:Title>{title}</ows:Title>
  171 + <ows:ServiceType>OGC WMTS</ows:ServiceType>
  172 + <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
  173 + </ows:ServiceIdentification>
  174 +
  175 + <!-- Operations Metadata -->
  176 + <ows:OperationsMetadata>
  177 + <ows:Operation name="GetCapabilities">
  178 + <ows:DCP>
  179 + <ows:HTTP>
  180 + <ows:Get xlink:href="{capabilities_url}">
  181 + <ows:Constraint name="GetEncoding">
  182 + <ows:AllowedValues>
  183 + <ows:Value>RESTful</ows:Value>
  184 + </ows:AllowedValues>
  185 + </ows:Constraint>
  186 + </ows:Get>
  187 +
  188 + <!-- add KVP binding in 10.1 -->
  189 + <ows:Get xlink:href="{tile_url}?">
  190 + <ows:Constraint name="GetEncoding">
  191 + <ows:AllowedValues>
  192 + <ows:Value>KVP</ows:Value>
  193 + </ows:AllowedValues>
  194 + </ows:Constraint>
  195 + </ows:Get>
  196 + </ows:HTTP>
  197 + </ows:DCP>
  198 + </ows:Operation>
  199 + <ows:Operation name="GetTile">
  200 + <ows:DCP>
  201 + <ows:HTTP>
  202 + <ows:Get xlink:href="{tile_url}">
  203 + <ows:Constraint name="GetEncoding">
  204 + <ows:AllowedValues>
  205 + <ows:Value>RESTful</ows:Value>
  206 + </ows:AllowedValues>
  207 + </ows:Constraint>
  208 + </ows:Get>
  209 + <ows:Get xlink:href="{tile_url}?">
  210 + <ows:Constraint name="GetEncoding">
  211 + <ows:AllowedValues>
  212 + <ows:Value>KVP</ows:Value>
  213 + </ows:AllowedValues>
  214 + </ows:Constraint>
  215 + </ows:Get>
  216 + </ows:HTTP>
  217 + </ows:DCP>
  218 + </ows:Operation>
  219 + </ows:OperationsMetadata>
  220 +
  221 + <Contents>
  222 +
  223 + <!-- Layer -->
  224 +
  225 +
  226 + <Layer>
  227 + <ows:Title>{title}</ows:Title>
  228 + <ows:Identifier>{title}</ows:Identifier>
  229 + <ows:BoundingBox crs="{crs}">
  230 + <ows:LowerCorner>{xmin} {ymin}</ows:LowerCorner>
  231 + <ows:UpperCorner>{xmax} {ymax}</ows:UpperCorner>
  232 + </ows:BoundingBox>
  233 +
  234 + <Style isDefault="true">
  235 + <ows:Title>Default Style</ows:Title>
  236 + <ows:Identifier>default</ows:Identifier>
  237 + </Style>
  238 + <Format>image/png</Format>
  239 + <TileMatrixSetLink>
  240 + <TileMatrixSet>{tile_name}</TileMatrixSet>
  241 + </TileMatrixSetLink>
  242 +
  243 + <ResourceURL format="image/png" resourceType="tile" template="{tile_url}"/>
  244 +
  245 + </Layer>
  246 +
  247 + <!-- TileMatrixSet -->
  248 +
  249 +
  250 + <TileMatrixSet>
  251 +
  252 + <TileMatrix>
  253 + <ows:Title>{tile_title}</ows:Title>
  254 + <ows:Abstract>{tile_description}</ows:Abstract>
  255 + <ows:Identifier>{tile_name}</ows:Identifier>
  256 + <ows:SupportedCRS>{crs}</ows:SupportedCRS>
  257 +
  258 + {tile_matrix}
  259 +
  260 + </TileMatrix>
  261 +
  262 + </TileMatrixSet>
  263 +
  264 +
  265 + </Contents>
  266 + <ServiceMetadataURL xlink:href="{capabilities_url}"/>
  267 + </Capabilities>'''
  268 +
  269 + tile_matrix_each = '''
  270 + <TileMatrix>
  271 + <ows:Identifier>{lev}</ows:Identifier>
  272 + <ScaleDenominator>{scale}</ScaleDenominator>
  273 + <TopLeftCorner>{top_left}</TopLeftCorner>
  274 + <TileWidth>{cols}</TileWidth>
  275 + <TileHeight>{rows}</TileHeight>
  276 + </TileMatrix>
  277 + '''
  278 +
  279 + tile_matrix = ""
  280 + top_left = tile_scheme.top_left
  281 + for level in json.loads(tile_scheme.levels):
  282 + tile_matrix = "{}{}".format(tile_matrix, tile_matrix_each.format(lev=level["level"],
  283 + scale=level["scale"],
  284 + top_left=top_left,
  285 + cols=tile_scheme.cols,
  286 + rows=tile_scheme.rows))
  287 +
  288 + extent = json.loads(image_service.extent)
  289 +
  290 + xml = xml.format(
  291 + capabilities_url="http://{}/API/Service/Image/Capabilities?guid={}".format(configure.deploy_ip_host,
  292 + image_service.guid),
  293 + tile_url="http://{}/API/Service/Image/Tile?guid={}".format(configure.deploy_ip_host, image_service.guid),
  294 + crs=tile_scheme.crs,
  295 + xmin=extent[0],
  296 + ymin=extent[1],
  297 + xmax=extent[2],
  298 + ymax=extent[3],
  299 + # TileMatrix = "{TileMatrix}",
  300 + # TileRow = "{TileRow}",
  301 + # TileCol = "{TileCol}",
  302 + guid=image_service.guid,
  303 + title=service.title,
  304 + tile_title=tile_scheme.name,
  305 + tile_name=tile_scheme.name,
  306 + tile_description=tile_scheme.description,
  307 + tile_matrix=tile_matrix
  308 + )
  309 +
  310 + r = Response(response=xml, status=200, mimetype="application/xml")
  311 + r.headers["Content-Type"] = "text/xml; charset=utf-8"
  312 +
  313 + return r
  314 +
  315 +
  316 +
  317 + def determin_intersect(self, extent1, extent2):
  318 + if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
  319 + 3] or extent2[3] < extent1[1]:
  320 + return False
  321 + else:
  322 + return True
  323 +
  324 +
  325 + api_doc = {
  326 + "tags": ["影像接口"],
  327 + "parameters": [
  328 + {"name": "guid",
  329 + "in": "formData",
  330 + "type": "string"},
  331 + {"name": "request",
  332 + "in": "formData",
  333 + "type": "string",
  334 + "enum": ["GetTile", "GetCapabilities"]},
  335 + {"name": "tilematrix",
  336 + "in": "formData",
  337 + "type": "string"},
  338 + {"name": "tilerow",
  339 + "in": "formData",
  340 + "type": "string"},
  341 + {"name": "tilecol",
  342 + "in": "formData",
  343 + "type": "string"},
  344 + {"name": "format",
  345 + "in": "formData",
  346 + "type": "string"},
  347 + {"name": "quality",
  348 + "in": "formData",
  349 + "type": "string"}
  350 +
  351 + ],
  352 + "responses": {
  353 + 200: {
  354 + "schema": {
  355 + "properties": {
  356 + }
  357 + }
  358 + }
  359 + }
  360 + }
  361 +
  362 +
  363 +
@@ -31,16 +31,16 @@ class Image(db.Model): @@ -31,16 +31,16 @@ class Image(db.Model):
31 31
32 size = Column(Float) 32 size = Column(Float)
33 #坐标wkt 33 #坐标wkt
34 - sr_wkt = Column(Text) #坐标wkt  
35 - sr_proj4 = Column(Text)#坐标proj  
36 - epsg = Column(Integer)#坐标epsg 34 + crs_wkt = Column(Text) #坐标wkt
  35 + crs_proj4 = Column(Text)#坐标proj
  36 + crs = Column(String)#坐标
37 create_time = Column(DateTime) 37 create_time = Column(DateTime)
38 update_time = Column(DateTime) 38 update_time = Column(DateTime)
39 cell_x_size = Column(Float)#像元x大小 39 cell_x_size = Column(Float)#像元x大小
40 cell_y_size = Column(Float)#像元y大小 40 cell_y_size = Column(Float)#像元y大小
41 region = Column(Text) 41 region = Column(Text)
42 42
43 - ym = Column(String(256))#时间年份 43 + collect_time = Column(DateTime) #成像时间年份
44 44
45 satellite = Column(String)#卫星类型 45 satellite = Column(String)#卫星类型
46 type = Column(String(128)) 46 type = Column(String(128))
@@ -7,13 +7,14 @@ @@ -7,13 +7,14 @@
7 from kazoo.client import KazooClient 7 from kazoo.client import KazooClient
8 import configure 8 import configure
9 import time 9 import time
10 -from app.modules.service.image.models import ImageService,Image  
11 -from app.models import TileScheme 10 +from app.modules.service.image.models import ImageService
  11 +from app.models import TileScheme,Service
12 import json 12 import json
  13 +
13 class Cache: 14 class Cache:
14 15
15 @classmethod 16 @classmethod
16 - def cache_data(cls,guid): 17 + def cache_data(cls,guid_or_name,type="guid"):
17 18
18 from app import GLOBAL_DIC 19 from app import GLOBAL_DIC
19 20
@@ -38,7 +39,7 @@ class Cache: @@ -38,7 +39,7 @@ class Cache:
38 servers = GLOBAL_DIC.get("servers") 39 servers = GLOBAL_DIC.get("servers")
39 40
40 # 更新缓存 41 # 更新缓存
41 - if time.time() - GLOBAL_DIC["servers_updatetime"] > 10: 42 + if time.time() - GLOBAL_DIC["servers_updatetime"] > 30:
42 servers = zoo.get_children("/rpc") 43 servers = zoo.get_children("/rpc")
43 servers.append("本地服务器") 44 servers.append("本地服务器")
44 GLOBAL_DIC["servers"] = servers 45 GLOBAL_DIC["servers"] = servers
@@ -46,25 +47,31 @@ class Cache: @@ -46,25 +47,31 @@ class Cache:
46 47
47 48
48 # 缓存服务信息 49 # 缓存服务信息
49 - if guid:  
50 - image_service_info = GLOBAL_DIC.get(guid)  
51 - if image_service_info is None or time.time() - GLOBAL_DIC.get("service_updatetime") > 20:  
52 - image_service: ImageService = ImageService.query.filter_by(guid=guid).one_or_none() 50 + if guid_or_name:
  51 + image_service_info = GLOBAL_DIC.get(guid_or_name)
  52 + if image_service_info is None or time.time() - GLOBAL_DIC.get("service_updatetime") > 30:
  53 + if type.__eq__("guid"):
  54 + image_service: ImageService = ImageService.query.filter_by(guid=guid_or_name).one_or_none()
  55 + else:
  56 + service = Service.query.filter_by(name=guid_or_name).one_or_none()
  57 + image_service: ImageService = ImageService.query.filter_by(guid=service.service_guid).one_or_none()
53 images = image_service.images.all() 58 images = image_service.images.all()
54 59
55 if image_service.scheme_guid: 60 if image_service.scheme_guid:
56 scheme: TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none() 61 scheme: TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none()
57 - GLOBAL_DIC[guid] = {"service": image_service, "images": images, 62 + GLOBAL_DIC[guid_or_name] = {"service": image_service, "images": images,
58 "scheme": json.loads(scheme.parameter)} 63 "scheme": json.loads(scheme.parameter)}
59 else: 64 else:
60 65
61 - GLOBAL_DIC[guid] = {"service": image_service, "images": images} 66 + GLOBAL_DIC[guid_or_name] = {"service": image_service, "images": images}
62 GLOBAL_DIC["service_updatetime"] = time.time() 67 GLOBAL_DIC["service_updatetime"] = time.time()
63 - image_service_info = GLOBAL_DIC[guid] 68 + image_service_info = GLOBAL_DIC[guid_or_name]
64 69
65 else: 70 else:
66 - image_service_info = GLOBAL_DIC[guid] 71 + image_service_info = GLOBAL_DIC[guid_or_name]
67 else: 72 else:
68 image_service_info = None 73 image_service_info = None
69 74
70 - return image_service_info,zoo,servers  
  75 + return image_service_info,zoo,servers
  76 +
  77 +
@@ -82,77 +82,120 @@ class ImageData: @@ -82,77 +82,120 @@ class ImageData:
82 :param bands: 82 :param bands:
83 :return: 83 :return:
84 ''' 84 '''
85 - 85 + pixel_array = numpy.zeros((height, width, 3), dtype=int)
  86 + ceng = 0
86 img: Dataset = gdal.Open(self.image.path, 0) 87 img: Dataset = gdal.Open(self.image.path, 0)
87 88
88 - origin_extent = json.loads(self.image.extent) 89 + for band in bands:
89 90
90 - # 超出空间范围  
91 - if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[3] or extent[  
92 - 3] < origin_extent[1]:  
93 - empty = numpy.zeros((height, width, 3), dtype=int) + 65536  
94 - # 空间范围相交  
95 - else: 91 + # 自决定金字塔等级
  92 + xysize = [img.RasterXSize, img.RasterYSize]
96 93
97 - ox = img.RasterXSize  
98 - oy = img.RasterYSize 94 + origin_extent = json.loads(self.image.extent)
  95 + band_data: Band = img.GetRasterBand(band)
99 96
100 - # 网格大小  
101 - grid_x = (origin_extent[2] - origin_extent[0]) / (ox * 1.0)  
102 - grid_y = (origin_extent[3] - origin_extent[1]) / (oy * 1.0) 97 + max_level = band_data.GetOverviewCount()
103 98
104 - # 完全在影像范围内  
105 - if extent[0] > origin_extent[0] and extent[1] > origin_extent[1] and extent[2] < \  
106 - origin_extent[2] and extent[3] < origin_extent[3]: 99 + # 超出空间范围
  100 + if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[
  101 + 3] or extent[3] < origin_extent[1]:
  102 + empty = numpy.zeros((height, width), dtype=int) + 65536
  103 + # 空间范围相交
  104 + else:
  105 + image_level = self.determine_level(xysize, origin_extent, extent, max_level)
107 106
108 - # 网格偏移量  
109 - off_x = math.floor((extent[0] - origin_extent[0]) / grid_x)  
110 - off_y = math.floor((origin_extent[3] - extent[3]) / grid_y) 107 + if image_level == -1:
  108 + overview = band_data
  109 + else:
  110 + try:
  111 + overview: Band = band_data.GetOverview(image_level)
  112 + except:
  113 + raise Exception("该影像不存在该级别的金字塔数据!")
  114 + ox = overview.XSize
  115 + oy = overview.YSize
111 116
112 - # 截取后网格个数  
113 - x_g = math.ceil((extent[2] - extent[0]) / grid_x) 117 + # 网格大小
  118 + grid_x = (origin_extent[2] - origin_extent[0]) / (ox * 1.0)
  119 + grid_y = (origin_extent[3] - origin_extent[1]) / (oy * 1.0)
114 120
115 - y_g = math.ceil((extent[3] - extent[1]) / grid_y) 121 + # 完全在影像范围内
  122 + if extent[0] > origin_extent[0] and extent[1] > origin_extent[1] and extent[2] < \
  123 + origin_extent[2] and extent[3] < origin_extent[3]:
  124 +
  125 + # 网格偏移量
  126 + off_x = math.floor((extent[0] - origin_extent[0]) / grid_x)
  127 + off_y = math.floor((origin_extent[3] - extent[3]) / grid_y)
  128 +
  129 + # 截取后网格个数
  130 + x_g = math.ceil((extent[2] - extent[0]) / grid_x)
  131 +
  132 + y_g = math.ceil((extent[3] - extent[1]) / grid_y)
  133 +
  134 + empty = overview.ReadAsArray(off_x, off_y, x_g, y_g, width, height)
116 135
117 - empty = img.ReadRaster(off_x, off_y, x_g, y_g, 256, 256, band_list = bands)  
118 - img.ReadAsArray()  
119 - # 部分相交  
120 - else:  
121 136
122 - inter_extent = [0, 0, 0, 0]  
123 - inter_extent[0] = origin_extent[0] if origin_extent[0] > extent[0] else extent[0]  
124 - inter_extent[1] = origin_extent[1] if origin_extent[1] > extent[1] else extent[1]  
125 - inter_extent[2] = origin_extent[2] if origin_extent[2] < extent[2] else extent[2]  
126 - inter_extent[3] = origin_extent[3] if origin_extent[3] < extent[3] else extent[3] 137 + # 部分相交
  138 + else:
127 139
128 - # 网格偏移量  
129 - off_x = math.floor((inter_extent[0] - origin_extent[0]) / grid_x)  
130 - off_y = math.floor((origin_extent[3] - inter_extent[3]) / grid_y) 140 + inter_extent = [0, 0, 0, 0]
  141 + inter_extent[0] = origin_extent[0] if origin_extent[0] > extent[0] else extent[0]
  142 + inter_extent[1] = origin_extent[1] if origin_extent[1] > extent[1] else extent[1]
  143 + inter_extent[2] = origin_extent[2] if origin_extent[2] < extent[2] else extent[2]
  144 + inter_extent[3] = origin_extent[3] if origin_extent[3] < extent[3] else extent[3]
131 145
132 - # 截取后网格个数  
133 - x_g = math.floor((inter_extent[2] - inter_extent[0]) / grid_x)  
134 - y_g = math.floor((inter_extent[3] - inter_extent[1]) / grid_y) 146 + # 网格偏移量
  147 + off_x = math.floor((inter_extent[0] - origin_extent[0]) / grid_x)
  148 + off_y = math.floor((origin_extent[3] - inter_extent[3]) / grid_y)
135 149
136 - # 相对于出图的偏移量 150 + # 截取后网格个数
  151 + x_g = math.floor((inter_extent[2] - inter_extent[0]) / grid_x)
  152 + y_g = math.floor((inter_extent[3] - inter_extent[1]) / grid_y)
137 153
138 - # 出图的网格大小  
139 - out_grid_x = (extent[2] - extent[0]) / (width * 1.0)  
140 - out_grid_y = (extent[3] - extent[1]) / (height * 1.0) 154 + # 相对于出图的偏移量
141 155
142 - out_off_x = int(math.ceil((inter_extent[0] - extent[0]) / out_grid_x))  
143 - out_off_y = int(math.ceil((extent[3] - inter_extent[3]) / out_grid_y)) 156 + # 出图的网格大小
  157 + out_grid_x = (extent[2] - extent[0]) / (width * 1.0)
  158 + out_grid_y = (extent[3] - extent[1]) / (height * 1.0)
144 159
145 - out_x_g = int(math.floor((inter_extent[2] - inter_extent[0]) / out_grid_x))  
146 - out_y_g = int(math.floor((inter_extent[3] - inter_extent[1]) / out_grid_y)) 160 + out_off_x = int(math.ceil((inter_extent[0] - extent[0]) / out_grid_x))
  161 + out_off_y = int(math.ceil((extent[3] - inter_extent[3]) / out_grid_y))
147 162
148 - # 相交部分在出图的哪个位置 163 + out_x_g = int(math.floor((inter_extent[2] - inter_extent[0]) / out_grid_x))
  164 + out_y_g = int(math.floor((inter_extent[3] - inter_extent[1]) / out_grid_y))
149 165
150 - overview_raster: ndarray = img.ReadAsArray(off_x, off_y, x_g, y_g, out_x_g,  
151 - out_y_g) 166 + # 相交部分在出图的哪个位置
152 167
153 - dat = numpy.zeros((height, width, 3), dtype=int) + 65536  
154 - dat[out_off_y:out_off_y + out_y_g, out_off_x:out_off_x + out_x_g] = overview_raster  
155 - empty = dat 168 + overview_raster: ndarray = overview.ReadAsArray(off_x, off_y, x_g, y_g, out_x_g,
  169 + out_y_g)
156 170
157 - return empty 171 + dat = numpy.zeros((height, width), dtype=int) + 65536
  172 + dat[out_off_y:out_off_y + out_y_g, out_off_x:out_off_x + out_x_g] = overview_raster
158 173
  174 + empty = dat
  175 +
  176 + pixel_array[:, :, ceng] = empty
  177 + ceng += 1
  178 + return pixel_array
  179 +
  180 +
  181 + def determine_level(self, xysize, origin_extent, extent, max_level):
  182 + '''
  183 + 根据范围判断调用金字塔的哪一层
  184 + :param xysize:
  185 + :param origin_extent:
  186 + :param extent:
  187 + :param max_level:
  188 + :return:
  189 + '''
  190 + x = xysize[0]
  191 + y = xysize[1]
  192 + level = -1
  193 + pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / (
  194 + (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1])))
  195 + while pixel > 100000 and level < max_level - 1:
  196 + level += 1
  197 + x = x / 2
  198 + y = y / 2
  199 + pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / (
  200 + (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1])))
  201 + return level
@@ -27,9 +27,9 @@ class Api(ApiTemplate): @@ -27,9 +27,9 @@ class Api(ApiTemplate):
27 parameter = {} 27 parameter = {}
28 for l_dict in json.loads(data.get("levels")): 28 for l_dict in json.loads(data.get("levels")):
29 parameter[str(l_dict["level"])] = {"resolution":l_dict["resolution"],"scale":l_dict["scale"]} 29 parameter[str(l_dict["level"])] = {"resolution":l_dict["resolution"],"scale":l_dict["scale"]}
30 - parameter["cols"] = int(data.get("cols"))  
31 - parameter["rows"] = int(data.get("rows"))  
32 - parameter["dpi"] = int(data.get("dpi")) 30 + parameter["cols"] = int(data.get("cols",256))
  31 + parameter["rows"] = int(data.get("rows",256))
  32 + parameter["dpi"] = int(data.get("dpi",96))
33 parameter["wkt"] = data.get("crs_wkt") 33 parameter["wkt"] = data.get("crs_wkt")
34 parameter["x"] = eval(data.get("top_left").split(",")[0]) 34 parameter["x"] = eval(data.get("top_left").split(",")[0])
35 parameter["y"] = eval(data.get("top_left").split(",")[1]) 35 parameter["y"] = eval(data.get("top_left").split(",")[1])
@@ -51,9 +51,9 @@ class Api(ApiTemplate): @@ -51,9 +51,9 @@ class Api(ApiTemplate):
51 # origin_x = top_left[0], 51 # origin_x = top_left[0],
52 # origin_y = top_left[1], 52 # origin_y = top_left[1],
53 levels = json.dumps(json.loads(data.get("levels"))), 53 levels = json.dumps(json.loads(data.get("levels"))),
54 - dpi = int(data.get("dpi")),  
55 - rows = int(data.get("rows")),  
56 - cols = int(data.get("cols")), 54 + dpi = int(data.get("dpi",96)),
  55 + rows = int(data.get("rows",256)),
  56 + cols = int(data.get("cols",256)),
57 update_time = datetime.datetime.now(), 57 update_time = datetime.datetime.now(),
58 parameter=json.dumps(parameter) 58 parameter=json.dumps(parameter)
59 ) 59 )
@@ -19,6 +19,18 @@ class Api(ApiTemplate): @@ -19,6 +19,18 @@ class Api(ApiTemplate):
19 try: 19 try:
20 guid = self.para.get("guid") 20 guid = self.para.get("guid")
21 service = Service.query.filter_by(guid=guid).one_or_none() 21 service = Service.query.filter_by(guid=guid).one_or_none()
  22 + if service.type in ["ImageWMTS","ImageWMS"]:
  23 + from app.modules.service.image.models import ImageService
  24 + image_service = ImageService.query.filter_by(guid=service.service_guid).one_or_none()
  25 + db.session.delete(image_service)
  26 + if service.type in ["WMTS","TMS"]:
  27 + from app.modules.service.wmts.models import WMTS
  28 + wmts = WMTS.query.filter_by(guid=service.service_guid).one_or_none()
  29 + db.session.delete(wmts)
  30 + if service.type in ["WMTS", "TMS"]:
  31 + from app.modules.service.wms.models import WMS
  32 + wms = WMS.query.filter_by(guid=service.service_guid).one_or_none()
  33 + db.session.delete(wms)
22 db.session.delete(service) 34 db.session.delete(service)
23 db.session.commit() 35 db.session.commit()
24 res["result"] = True 36 res["result"] = True
@@ -44,12 +44,11 @@ class Api(ApiTemplate): @@ -44,12 +44,11 @@ class Api(ApiTemplate):
44 "type": "string", 44 "type": "string",
45 "description": "[WMS,WMTS,影像WMS,影像WMTS,guid]"}, 45 "description": "[WMS,WMTS,影像WMS,影像WMTS,guid]"},
46 46
47 - # {"name": "type",  
48 - # "in": "formData",  
49 - # "type": "string",  
50 - # "enum": ["WMS/WFS", "WMTS", "TMS", "ImageWMS", "ImageWMTS"],  
51 - # "required": "true",  
52 - # "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 47 + {"name": "type",
  48 + "in": "formData",
  49 + "type": "string",
  50 + "enum": ["WMS/WFS", "WMTS", "TMS", "ImageWMS", "ImageWMTS"],
  51 + "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
53 52
54 {"name": "name", 53 {"name": "name",
55 "in": "formData", 54 "in": "formData",
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/9/22
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from app.util.component.ApiTemplate import ApiTemplate
  8 +from app.util.component.ModelVisitor import ModelVisitor
  9 +from app.util.component.FileProcess import FileProcess
  10 +from app.models import Service
  11 +import os
  12 +
  13 +class Api(ApiTemplate):
  14 + '''
  15 + 解析md文件
  16 + '''
  17 + api_name = "服务resolve"
  18 +
  19 + def process(self):
  20 + res = {}
  21 + try:
  22 +
  23 + parent = os.path.dirname(os.path.realpath(__file__))
  24 + dir_path, store_file = FileProcess.save(parent)
  25 +
  26 +
  27 + except Exception as e:
  28 + raise e
  29 + return res
  30 +
  31 +
  32 + api_doc = {
  33 + "tags": ["服务接口"],
  34 + "parameters": [
  35 + {"name": "guid",
  36 + "in": "formData",
  37 + "type": "string",
  38 + "description": "guid"},
  39 + ],
  40 + "responses": {
  41 + 200: {
  42 + "schema": {
  43 + "properties": {
  44 + }
  45 + }
  46 + }
  47 + }
  48 + }
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/9/22
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from app.util.component.ApiTemplate import ApiTemplate
  8 +from app.util.component.ModelVisitor import ModelVisitor
  9 +from app.models import Service
  10 +
  11 +class Api(ApiTemplate):
  12 + '''
  13 + 保存服务到dmd文件
  14 + '''
  15 + api_name = "服务Save"
  16 + def process(self):
  17 + res = {}
  18 + try:
  19 + guid = self.para.get("guid")
  20 + service = Service.query.filter_by(guid=guid).one_or_none()
  21 + if not service:
  22 + raise Exception("服务不存在!")
  23 + res["data"] = {}
  24 +
  25 + if service.type in ["ImageWMS","ImageWMTS"]:
  26 + from app.modules.service.image.models import ImageService
  27 + speci_service = ImageService.query.filter_by(guid=service.service_guid).one_or_none()
  28 + relate_images = speci_service.images.all()
  29 + res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service)
  30 +
  31 + res["data"]["speci_service"]["images"] = [{"name":im["name"],"guid":im["guid"]} for im in ModelVisitor.objects_to_jsonarray(relate_images)]
  32 + res["data"]["speci_service"]["images"] = sorted(res["data"]["speci_service"]["images"], key=lambda x: x["name"])
  33 +
  34 + elif service.type.__eq__("WMTS") or service.type.__eq__("TMS"):
  35 + from app.modules.service.wmts.models import WMTS
  36 + speci_service = WMTS.query.filter_by(guid=service.service_guid).one_or_none()
  37 +
  38 + res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service)
  39 +
  40 + elif service.type.__eq__("WMS/WFS"):
  41 + from app.modules.service.wms.models import WMS
  42 + speci_service = WMS.query.filter_by(guid=service.service_guid).one_or_none()
  43 + res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service)
  44 + else:
  45 + res["data"] = {}
  46 +
  47 + res["data"]["service"] = ModelVisitor.object_to_json(service)
  48 +
  49 + except Exception as e:
  50 + raise e
  51 + return res
  52 +
  53 +
  54 + api_doc = {
  55 + "tags": ["服务接口"],
  56 + "parameters": [
  57 + {"name": "guid",
  58 + "in": "formData",
  59 + "type": "string",
  60 + "description": "guid"},
  61 + ],
  62 + "responses": {
  63 + 200: {
  64 + "schema": {
  65 + "properties": {
  66 + }
  67 + }
  68 + }
  69 + }
  70 + }
@@ -17,6 +17,8 @@ class Api(ApiTemplate): @@ -17,6 +17,8 @@ class Api(ApiTemplate):
17 state = int(self.para.get("state")) 17 state = int(self.para.get("state"))
18 Service.query.filter_by(guid=guid).update({"state":state}) 18 Service.query.filter_by(guid=guid).update({"state":state})
19 19
  20 + # 清理缓存,拒绝服务
  21 +
20 db.session.commit() 22 db.session.commit()
21 res["result"] = True 23 res["result"] = True
22 except Exception as e: 24 except Exception as e:
@@ -8,8 +8,10 @@ from flask import current_app @@ -8,8 +8,10 @@ from flask import current_app
8 import os 8 import os
9 9
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.StructuredPrint import StructurePrint 12 from app.util.component.StructuredPrint import StructurePrint
12 - 13 +from app.models import Service,db
  14 +from sqlalchemy.orm import load_only
13 from flask import current_app 15 from flask import current_app
14 class Api(ApiTemplate): 16 class Api(ApiTemplate):
15 17
@@ -24,7 +26,9 @@ class Api(ApiTemplate): @@ -24,7 +26,9 @@ class Api(ApiTemplate):
24 26
25 result=dict() 27 result=dict()
26 result.update(self.para) 28 result.update(self.para)
  29 + services = Service.query.options(load_only('guid')).all()
27 result["root_path"] = os.path.dirname(current_app.instance_path) 30 result["root_path"] = os.path.dirname(current_app.instance_path)
  31 + result["services"] = ModelVisitor.objects_to_jsonarray(services)
28 return result 32 return result
29 33
30 34
@@ -307,13 +307,6 @@ class ThisTask: @@ -307,13 +307,6 @@ class ThisTask:
307 :return: 表名 307 :return: 表名
308 ''' 308 '''
309 309
310 - # 在覆盖模式下,删除原有记录  
311 - if overwrite.__eq__("yes"):  
312 - old_table = self.sys_session.query(Table).filter_by(name=new_layer_name).one_or_none()  
313 - if old_table:  
314 - self.sys_session.delete(old_table)  
315 -  
316 -  
317 this_time = datetime.datetime.now() 310 this_time = datetime.datetime.now()
318 311
319 ext = layer.GetExtent() 312 ext = layer.GetExtent()
@@ -336,7 +329,7 @@ class ThisTask: @@ -336,7 +329,7 @@ class ThisTask:
336 is_vacuate=is_vacuate 329 is_vacuate=is_vacuate
337 ) 330 )
338 # 删除遗留业务数据 331 # 删除遗留业务数据
339 - history_table = self.sys_session.query(Table).filter_by(name=new_layer_name).all() 332 + history_table = self.sys_session.query(Table).filter_by(name=new_layer_name,database_guid=self.database.guid).all()
340 if history_table: 333 if history_table:
341 for ht in history_table: 334 for ht in history_table:
342 self.sys_session.delete(ht) 335 self.sys_session.delete(ht)
@@ -52,8 +52,8 @@ class SliceScheme: @@ -52,8 +52,8 @@ class SliceScheme:
52 col = int(col) 52 col = int(col)
53 detaxy = parameter.get(str(level)).get("resolution")* parameter.get("cols") 53 detaxy = parameter.get(str(level)).get("resolution")* parameter.get("cols")
54 54
55 - minx = detaxy * col + parameter.get("x")  
56 - maxy = -detaxy * row + parameter.get("y") 55 + minx = detaxy * col + int(parameter.get("x"))
  56 + maxy = -detaxy * row + int(parameter.get("y"))
57 maxx = detaxy + minx 57 maxx = detaxy + minx
58 miny = -detaxy + maxy 58 miny = -detaxy + maxy
59 59
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/21
  4 +#email: nheweijun@sina.com
  5 +
  6 +from osgeo import ogr
  7 +from osgeo import gdal
  8 +
  9 +def function():
  10 + gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
  11 +
  12 + fn = "PG: user=postgres password=chinadci host=172.26.60.101 port=5432 dbname=parcel"
  13 + driver = ogr.GetDriverByName("PostgreSQL")
  14 + ds:ogr.DataSource = driver.Open(fn, 1)
  15 +
  16 + layer:ogr.Layer = ds.GetLayerByName("ZDCLHX2000V14")
  17 +
  18 + output = r"E:\D2\桌面\工作\2021.10省厅测评\10w.shp"
  19 +
  20 + shp_driver = ogr.GetDriverByName("FileGDB")
  21 + output_ds: ogr.DataSource = shp_driver.CreateDataSource(output)
  22 +
  23 + out_layer:ogr.Layer = output_ds.CreateLayer(layer.GetName(),layer.GetSpatialRef(),layer.GetGeomType())
  24 +
  25 + field_names = ["id","预编号","土地使用者","所有权性质","土地证号","地址","镇区","测量日期","二维码信息","shape_area"]
  26 + field_names_yinwen = ["id", "precode", "user", "xingzhi", "tudi", "address", "region", "date", "code", "shape_area"]
  27 + scheme = [field for field in layer.schema if field.GetName() in field_names]
  28 +
  29 + out_layer.CreateFields(scheme)
  30 + count = 100000
  31 +
  32 + i=0
  33 + featureDefn = out_layer.GetLayerDefn()
  34 +
  35 + for f in layer:
  36 + ff :ogr.Feature = f
  37 + new_f = ogr.Feature(featureDefn)
  38 + new_f.SetGeometry(ff.geometry())
  39 + for field in field_names:
  40 + dd = ff.GetFieldIndex(field)
  41 + kkk = ff.GetField(dd)
  42 + new_f.SetField(field,kkk)
  43 + out_layer.CreateFeature(new_f)
  44 + i += 1
  45 + if i==count:
  46 + break
  47 +
  48 + output_ds.Destroy()
  49 +if __name__ == '__main__':
  50 +
  51 + function()
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/21
  4 +#email: nheweijun@sina.com
  5 +
  6 +from osgeo import ogr
  7 +from osgeo import gdal
  8 +
  9 +def function():
  10 + gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
  11 +
  12 + fn = "PG: user=postgres password=chinadci host=172.26.60.101 port=5432 dbname=parcel"
  13 + driver = ogr.GetDriverByName("PostgreSQL")
  14 + ds:ogr.DataSource = driver.Open(fn, 1)
  15 +
  16 + layer:ogr.Layer = ds.GetLayerByName("ZDCLHX2000V14")
  17 + output = r"E:\D2\桌面\工作\2021.10省厅测评\100w.shp"
  18 + shp_driver = ogr.GetDriverByName("ESRI Shapefile")
  19 + output_ds: ogr.DataSource = shp_driver.CreateDataSource(output)
  20 +
  21 + out_layer:ogr.Layer = output_ds.CreateLayer(layer.GetName(),layer.GetSpatialRef(),layer.GetGeomType())
  22 +
  23 + field_names = ["id","预编号","土地使用者","所有权性质","土地证号","地址","镇区","测量日期","二维码信息","shape_area"]
  24 + scheme = [field for field in layer.schema if field.GetName() in field_names]
  25 +
  26 + out_layer.CreateFields(scheme)
  27 + count = 1000000
  28 +
  29 + i=0
  30 + featureDefn = out_layer.GetLayerDefn()
  31 +
  32 + for f in layer:
  33 + ff :ogr.Feature = f
  34 + new_f = ogr.Feature(featureDefn)
  35 + new_f.SetGeometry(ff.geometry())
  36 + for field in field_names:
  37 + dd = ff.GetFieldIndex(field)
  38 + kkk = ff.GetField(dd)
  39 + new_f.SetField(field,kkk)
  40 + out_layer.CreateFeature(new_f)
  41 + i += 1
  42 + if i==count:
  43 + break
  44 +
  45 + output_ds.Destroy()
  46 +if __name__ == '__main__':
  47 +
  48 + function()
@@ -3,3 +3,8 @@ @@ -3,3 +3,8 @@
3 #createtime: 2021/10/15 3 #createtime: 2021/10/15
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
  6 +
  7 +
  8 +kk = {"dpi":"11","cols":"112"}
  9 +
  10 +print(int(kk.get("rows",256)))
注册登录 后发表评论