正在显示
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 |
app/modules/data/io/data_entry_simple.py
0 → 100644
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 |
不能预览此文件类型
app/modules/service/image/data/d.py
0 → 100644
@@ -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"}, |
app/modules/service/image/image_wms_kv.py
0 → 100644
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"}, |
app/modules/service/image/image_wmts.py
0 → 100644
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 |

24.9 KB

14.4 KB

14.4 KB

14.4 KB
@@ -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", |
app/modules/service/service_resolve.py
0 → 100644
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 | + } |
app/modules/service/service_save.py
0 → 100644
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 |
test/pg2gdb.py
0 → 100644
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() |
test/pg2shp.py
0 → 100644
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() |
请
注册
或
登录
后发表评论