正在显示
46 个修改的文件
包含
1774 行增加
和
208 行删除
@@ -265,9 +265,10 @@ pkgs.extend(list(glob.glob('%s/modules/*/*/models' % (current_dir)))) | @@ -265,9 +265,10 @@ pkgs.extend(list(glob.glob('%s/modules/*/*/models' % (current_dir)))) | ||
265 | for pkg in pkgs : | 265 | for pkg in pkgs : |
266 | pkg = os.path.normpath(pkg) | 266 | pkg = os.path.normpath(pkg) |
267 | node_list = pkg.split(os.path.sep) | 267 | node_list = pkg.split(os.path.sep) |
268 | - pkg_name = ".".join(node_list[node_list.index("app"):]) | 268 | + pkg_name = "app.{}".format(".".join(node_list[node_list.index("modules"):])) |
269 | try: | 269 | try: |
270 | - __import__(pkg_name) | 270 | + if pkg_name.__contains__("models"): |
271 | + __import__(pkg_name) | ||
271 | except Exception as e: | 272 | except Exception as e: |
272 | print(traceback.format_exc()) | 273 | print(traceback.format_exc()) |
273 | pass | 274 | pass |
@@ -35,7 +35,7 @@ class Api(ApiTemplate): | @@ -35,7 +35,7 @@ class Api(ApiTemplate): | ||
35 | 35 | ||
36 | api_doc={ | 36 | api_doc={ |
37 | 37 | ||
38 | - "tags":["目录接口"], | 38 | + "tags":["矢量数据目录接口"], |
39 | "parameters":[ | 39 | "parameters":[ |
40 | {"name": "catalog_guid", | 40 | {"name": "catalog_guid", |
41 | "in": "formData", | 41 | "in": "formData", |
@@ -51,7 +51,7 @@ class Api(ApiTemplate): | @@ -51,7 +51,7 @@ class Api(ApiTemplate): | ||
51 | 51 | ||
52 | api_doc={ | 52 | api_doc={ |
53 | 53 | ||
54 | - "tags":["目录接口"], | 54 | + "tags":["矢量数据目录接口"], |
55 | "parameters":[ | 55 | "parameters":[ |
56 | {"name": "database_guid", | 56 | {"name": "database_guid", |
57 | "in": "formData", | 57 | "in": "formData", |
@@ -42,7 +42,7 @@ class Api(ApiTemplate): | @@ -42,7 +42,7 @@ class Api(ApiTemplate): | ||
42 | 42 | ||
43 | api_doc={ | 43 | api_doc={ |
44 | 44 | ||
45 | - "tags":["目录接口"], | 45 | + "tags":["矢量数据目录接口"], |
46 | "parameters":[ | 46 | "parameters":[ |
47 | {"name": "database_guid", | 47 | {"name": "database_guid", |
48 | "in": "formData", | 48 | "in": "formData", |
@@ -7,9 +7,10 @@ from flasgger import swag_from | @@ -7,9 +7,10 @@ from flasgger import swag_from | ||
7 | from flask import Blueprint | 7 | from flask import Blueprint |
8 | from app.util import BlueprintApi | 8 | from app.util import BlueprintApi |
9 | from . import service_register | 9 | from . import service_register |
10 | -from . import service_type | 10 | +from . import service_exist_type |
11 | from . import service_list | 11 | from . import service_list |
12 | from . import service_delete | 12 | from . import service_delete |
13 | +from . import service_state | ||
13 | import os | 14 | import os |
14 | from flask import send_from_directory | 15 | from flask import send_from_directory |
15 | 16 | ||
@@ -17,6 +18,8 @@ from flask import send_from_directory | @@ -17,6 +18,8 @@ from flask import send_from_directory | ||
17 | class DataManager(BlueprintApi): | 18 | class DataManager(BlueprintApi): |
18 | 19 | ||
19 | bp = Blueprint("Service", __name__, url_prefix="/API/Service") | 20 | bp = Blueprint("Service", __name__, url_prefix="/API/Service") |
21 | + service_type = [] | ||
22 | + | ||
20 | 23 | ||
21 | @staticmethod | 24 | @staticmethod |
22 | @bp.route('/Register', methods=['POST']) | 25 | @bp.route('/Register', methods=['POST']) |
@@ -29,12 +32,21 @@ class DataManager(BlueprintApi): | @@ -29,12 +32,21 @@ class DataManager(BlueprintApi): | ||
29 | 32 | ||
30 | @staticmethod | 33 | @staticmethod |
31 | @bp.route('/Type', methods=['GET']) | 34 | @bp.route('/Type', methods=['GET']) |
32 | - @swag_from(service_type.Api.api_doc) | 35 | + @swag_from(service_exist_type.Api.api_doc) |
33 | def api_service_type(): | 36 | def api_service_type(): |
34 | """ | 37 | """ |
35 | 可用服务类型 | 38 | 可用服务类型 |
36 | """ | 39 | """ |
37 | - return service_type.Api().result | 40 | + return service_exist_type.Api().result |
41 | + | ||
42 | + @staticmethod | ||
43 | + @bp.route('/State', methods=['GET']) | ||
44 | + @swag_from(service_state.Api.api_doc) | ||
45 | + def api_service_state(): | ||
46 | + """ | ||
47 | + 修改服务状态 | ||
48 | + """ | ||
49 | + return service_state.Api().result | ||
38 | 50 | ||
39 | @staticmethod | 51 | @staticmethod |
40 | @bp.route('/List', methods=['POST']) | 52 | @bp.route('/List', methods=['POST']) |
@@ -19,7 +19,7 @@ from . import catalog_edit, catalog_tree, catalog_delete, catalog_create, catalo | @@ -19,7 +19,7 @@ from . import catalog_edit, catalog_tree, catalog_delete, catalog_create, catalo | ||
19 | class DataManager(BlueprintApi): | 19 | class DataManager(BlueprintApi): |
20 | 20 | ||
21 | bp = Blueprint("ServiceCatalog", __name__, url_prefix="/API/Service/Catalog") | 21 | bp = Blueprint("ServiceCatalog", __name__, url_prefix="/API/Service/Catalog") |
22 | - | 22 | + service_type = [] |
23 | 23 | ||
24 | @staticmethod | 24 | @staticmethod |
25 | @bp.route('/Create', methods=['POST']) | 25 | @bp.route('/Create', methods=['POST']) |
@@ -17,7 +17,7 @@ from . import feature_edit | @@ -17,7 +17,7 @@ from . import feature_edit | ||
17 | class DataManager(BlueprintApi): | 17 | class DataManager(BlueprintApi): |
18 | 18 | ||
19 | bp = Blueprint("FeatureService", __name__, url_prefix="/API/FeatureService") | 19 | bp = Blueprint("FeatureService", __name__, url_prefix="/API/FeatureService") |
20 | - service_type = ["要素服务"] | 20 | + service_type = [] |
21 | @staticmethod | 21 | @staticmethod |
22 | @bp.route('/Query', methods=['POST']) | 22 | @bp.route('/Query', methods=['POST']) |
23 | @swag_from(feature_query.Api.api_doc) | 23 | @swag_from(feature_query.Api.api_doc) |
@@ -7,22 +7,23 @@ | @@ -7,22 +7,23 @@ | ||
7 | from flasgger import swag_from | 7 | from flasgger import swag_from |
8 | from flask import Blueprint | 8 | from flask import Blueprint |
9 | from app.util import BlueprintApi | 9 | from app.util import BlueprintApi |
10 | -from . import image_register | ||
11 | from . import image_service_register | 10 | from . import image_service_register |
12 | from . import image_server_list | 11 | from . import image_server_list |
13 | from . import data_list | 12 | from . import data_list |
14 | from . import capabilities | 13 | from . import capabilities |
15 | -from . import image_list | ||
16 | -from . import image_tile | ||
17 | -from . import image_wms | ||
18 | -from . import image_overview | 14 | +from . import image_tile,image_wms |
19 | from . import image_service_list | 15 | from . import image_service_list |
16 | +from . import image_tile_mask | ||
17 | + | ||
18 | + | ||
19 | +from . import image_register,image_list,image_info,image_edit,image_overview | ||
20 | +from . import image_tag_create,image_tag_delete,image_tag_list | ||
20 | 21 | ||
21 | 22 | ||
22 | class DataManager(BlueprintApi): | 23 | class DataManager(BlueprintApi): |
23 | 24 | ||
24 | bp = Blueprint("Image", __name__, url_prefix="/API/Service/Image") | 25 | bp = Blueprint("Image", __name__, url_prefix="/API/Service/Image") |
25 | - service_type = ["影像WMS服务","影像WMTS服务"] | 26 | + service_type = ["ImageWMS","ImageWMTS"] |
26 | 27 | ||
27 | @staticmethod | 28 | @staticmethod |
28 | @bp.route('/Register', methods=['POST']) | 29 | @bp.route('/Register', methods=['POST']) |
@@ -33,6 +34,24 @@ class DataManager(BlueprintApi): | @@ -33,6 +34,24 @@ class DataManager(BlueprintApi): | ||
33 | """ | 34 | """ |
34 | return image_register.Api().result | 35 | return image_register.Api().result |
35 | 36 | ||
37 | + @staticmethod | ||
38 | + @bp.route('/Edit', methods=['POST']) | ||
39 | + @swag_from(image_edit.Api.api_doc) | ||
40 | + def api_image_edit(): | ||
41 | + """ | ||
42 | + 影像Info | ||
43 | + """ | ||
44 | + return image_edit.Api().result | ||
45 | + | ||
46 | + @staticmethod | ||
47 | + @bp.route('/Info', methods=['POST']) | ||
48 | + @swag_from(image_info.Api.api_doc) | ||
49 | + def api_image_info(): | ||
50 | + """ | ||
51 | + 影像Info | ||
52 | + """ | ||
53 | + return image_info.Api().result | ||
54 | + | ||
36 | 55 | ||
37 | @staticmethod | 56 | @staticmethod |
38 | @bp.route('/Overview', methods=['POST']) | 57 | @bp.route('/Overview', methods=['POST']) |
@@ -43,6 +62,35 @@ class DataManager(BlueprintApi): | @@ -43,6 +62,35 @@ class DataManager(BlueprintApi): | ||
43 | """ | 62 | """ |
44 | return image_overview.Api().result | 63 | return image_overview.Api().result |
45 | 64 | ||
65 | + | ||
66 | + @staticmethod | ||
67 | + @bp.route('/TagCreate', methods=['POST']) | ||
68 | + @swag_from(image_tag_create.Api.api_doc) | ||
69 | + def api_image_tag_create(): | ||
70 | + """ | ||
71 | + Tag创建 | ||
72 | + """ | ||
73 | + return image_tag_create.Api().result | ||
74 | + | ||
75 | + @staticmethod | ||
76 | + @bp.route('/TagDelete', methods=['POST']) | ||
77 | + @swag_from(image_tag_delete.Api.api_doc) | ||
78 | + def api_image_tag_delete(): | ||
79 | + """ | ||
80 | + Tag删除 | ||
81 | + """ | ||
82 | + return image_tag_delete.Api().result | ||
83 | + | ||
84 | + @staticmethod | ||
85 | + @bp.route('/TagList', methods=['POST']) | ||
86 | + @swag_from(image_tag_list.Api.api_doc) | ||
87 | + def api_image_tag_list(): | ||
88 | + """ | ||
89 | + TagList | ||
90 | + """ | ||
91 | + return image_tag_list.Api().result | ||
92 | + | ||
93 | + | ||
46 | @staticmethod | 94 | @staticmethod |
47 | @bp.route('/ServiceRegister', methods=['POST']) | 95 | @bp.route('/ServiceRegister', methods=['POST']) |
48 | @swag_from(image_service_register.Api.api_doc) | 96 | @swag_from(image_service_register.Api.api_doc) |
@@ -117,6 +165,24 @@ class DataManager(BlueprintApi): | @@ -117,6 +165,24 @@ class DataManager(BlueprintApi): | ||
117 | """ | 165 | """ |
118 | return image_tile.Api("1",1,1,1).result | 166 | return image_tile.Api("1",1,1,1).result |
119 | 167 | ||
168 | + # @staticmethod | ||
169 | + # @bp.route('/TileMask/<guid>/<l>/<y>/<z>', methods=['GET']) | ||
170 | + # @swag_from(image_tile_mask.Api.api_doc) | ||
171 | + # def api_image_tile_mask(guid,l,y,z): | ||
172 | + # """ | ||
173 | + # 切片服务 | ||
174 | + # """ | ||
175 | + # return image_tile_mask.Api(guid,l,y,z).result | ||
176 | + # | ||
177 | + # @staticmethod | ||
178 | + # @bp.route('/TileMask', methods=['GET','POST']) | ||
179 | + # @swag_from(image_tile_mask.Api.api_doc) | ||
180 | + # def api_image_tile_mask_kv(): | ||
181 | + # """ | ||
182 | + # 切片服务 | ||
183 | + # """ | ||
184 | + # return image_tile_mask.Api("1",1,1,1).result | ||
185 | + | ||
120 | 186 | ||
121 | 187 | ||
122 | @staticmethod | 188 | @staticmethod |
@@ -11,6 +11,9 @@ from app.util.component.FileProcess import FileProcess | @@ -11,6 +11,9 @@ from app.util.component.FileProcess import FileProcess | ||
11 | import datetime | 11 | import datetime |
12 | from app.modules.service.image.util.ThriftConnect import ThriftConnect | 12 | from app.modules.service.image.util.ThriftConnect import ThriftConnect |
13 | import os | 13 | import os |
14 | +from app.models import db | ||
15 | +from app.modules.service.image.models import Image | ||
16 | + | ||
14 | class Api(ApiTemplate): | 17 | class Api(ApiTemplate): |
15 | 18 | ||
16 | api_name = "影像数据列表" | 19 | api_name = "影像数据列表" |
@@ -38,11 +41,20 @@ class Api(ApiTemplate): | @@ -38,11 +41,20 @@ class Api(ApiTemplate): | ||
38 | for f in os.listdir(base_path): | 41 | for f in os.listdir(base_path): |
39 | 42 | ||
40 | file_path = os.path.normpath(os.path.join(base_path, f)) | 43 | file_path = os.path.normpath(os.path.join(base_path, f)) |
41 | - file_size = FileProcess.get_file_size(file_path) | 44 | + file_size, real_size = FileProcess.get_file_size(file_path) |
42 | 45 | ||
43 | fctime = datetime.datetime.fromtimestamp(os.path.getctime(file_path)).strftime('%Y-%m-%d %H:%M:%S') | 46 | fctime = datetime.datetime.fromtimestamp(os.path.getctime(file_path)).strftime('%Y-%m-%d %H:%M:%S') |
44 | 47 | ||
45 | - file_info = {"name": f, "path": file_path, "size": file_size, "create_time": fctime} | 48 | + file_info = {"name": f, "path": file_path, "size": file_size, "create_time": fctime,"real_size": real_size} |
49 | + | ||
50 | + if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif") or file_path.lower().endswith("img"): | ||
51 | + | ||
52 | + exist_image: Image = Image.query.filter_by(path=os.path.normpath(file_info.get("path")), | ||
53 | + size=file_info.get("size")).one_or_none() | ||
54 | + file_info["exist"] = False | ||
55 | + if exist_image: | ||
56 | + if exist_image.server.__contains__(data_server): | ||
57 | + file_info["exist"] = True | ||
46 | 58 | ||
47 | if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif"): | 59 | if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif"): |
48 | file_info["type"] = "tif" | 60 | file_info["type"] = "tif" |
@@ -61,6 +73,17 @@ class Api(ApiTemplate): | @@ -61,6 +73,17 @@ class Api(ApiTemplate): | ||
61 | thrift_connect = ThriftConnect(data_server) | 73 | thrift_connect = ThriftConnect(data_server) |
62 | info= json.loads(thrift_connect.client.getImageList(path)) | 74 | info= json.loads(thrift_connect.client.getImageList(path)) |
63 | thrift_connect.close() | 75 | thrift_connect.close() |
76 | + | ||
77 | + for inf in info: | ||
78 | + if inf["path"].lower().endswith("tiff") or inf["path"].lower().endswith("tif") or inf["path"].lower().endswith("img"): | ||
79 | + dd = os.path.normpath(inf.get("path")) | ||
80 | + exist_image = Image.query.filter_by(path=os.path.normpath(inf.get("path")), | ||
81 | + size=inf.get("real_size")).one_or_none() | ||
82 | + inf["exist"] = False | ||
83 | + if exist_image: | ||
84 | + if exist_image.server.__contains__(data_server): | ||
85 | + inf["exist"] = True | ||
86 | + | ||
64 | res["data"] = info | 87 | res["data"] = info |
65 | 88 | ||
66 | res["result"] = True | 89 | res["result"] = True |
@@ -41,6 +41,12 @@ class Api(ApiTemplate): | @@ -41,6 +41,12 @@ class Api(ApiTemplate): | ||
41 | {"name": "alias", | 41 | {"name": "alias", |
42 | "in": "formData", | 42 | "in": "formData", |
43 | "type": "string"}, | 43 | "type": "string"}, |
44 | + {"name": "ym", | ||
45 | + "in": "formData", | ||
46 | + "type": "string","description":"成像时间字符串"}, | ||
47 | + {"name": "region", | ||
48 | + "in": "formData", | ||
49 | + "type": "string", "description": "所属区域"}, | ||
44 | ], | 50 | ], |
45 | "responses": { | 51 | "responses": { |
46 | 200: { | 52 | 200: { |
app/modules/service/image/image_info.py
0 → 100644
1 | +# coding=utf-8 | ||
2 | +#author: 4N | ||
3 | +#createtime: 2021/7/19 | ||
4 | +#email: nheweijun@sina.com | ||
5 | + | ||
6 | + | ||
7 | +from app.util.component.ApiTemplate import ApiTemplate | ||
8 | +from app.util.component.ModelVisitor import ModelVisitor | ||
9 | + | ||
10 | +from app.modules.service.image.models import Image,ImageTag | ||
11 | +from sqlalchemy import or_,and_ | ||
12 | +class Api(ApiTemplate): | ||
13 | + | ||
14 | + api_name = "影像数据Info" | ||
15 | + | ||
16 | + def process(self): | ||
17 | + | ||
18 | + # 返回结果 | ||
19 | + res = {} | ||
20 | + try: | ||
21 | + | ||
22 | + guid = self.para.get("guid") | ||
23 | + | ||
24 | + image = Image.query.filter_by(guid=guid).one_or_none() | ||
25 | + if not image: | ||
26 | + raise Exception("数据不存在!") | ||
27 | + tags:ImageTag = image.image_tags.all() | ||
28 | + tag_names = [tag.name for tag in tags] | ||
29 | + | ||
30 | + res["data"] = ModelVisitor.object_to_json(image) | ||
31 | + res["data"]["tag"] = ",".join(tag_names) | ||
32 | + res["result"] = True | ||
33 | + except Exception as e: | ||
34 | + raise e | ||
35 | + | ||
36 | + return res | ||
37 | + | ||
38 | + | ||
39 | + api_doc = { | ||
40 | + "tags": ["影像接口"], | ||
41 | + "parameters": [ | ||
42 | + {"name": "guid", | ||
43 | + "in": "formData", | ||
44 | + "type": "string"}, | ||
45 | + ], | ||
46 | + "responses": { | ||
47 | + 200: { | ||
48 | + "schema": { | ||
49 | + "properties": { | ||
50 | + } | ||
51 | + } | ||
52 | + } | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + |
@@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
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 | 9 | ||
10 | -from app.modules.service.image.models import Image | 10 | +from app.modules.service.image.models import Image,ImageTag |
11 | from sqlalchemy import or_,and_ | 11 | from sqlalchemy import or_,and_ |
12 | class Api(ApiTemplate): | 12 | class Api(ApiTemplate): |
13 | 13 | ||
@@ -23,6 +23,8 @@ class Api(ApiTemplate): | @@ -23,6 +23,8 @@ class Api(ApiTemplate): | ||
23 | 23 | ||
24 | alias = self.para.get("alias") | 24 | alias = self.para.get("alias") |
25 | name = self.para.get("name") | 25 | name = self.para.get("name") |
26 | + tag_guid = self.para.get("tag_guid") | ||
27 | + | ||
26 | images = Image.query | 28 | images = Image.query |
27 | 29 | ||
28 | # 并集 | 30 | # 并集 |
@@ -33,6 +35,11 @@ class Api(ApiTemplate): | @@ -33,6 +35,11 @@ class Api(ApiTemplate): | ||
33 | images = images.filter(Image.alias.like("%" + alias + "%")) | 35 | images = images.filter(Image.alias.like("%" + alias + "%")) |
34 | if name: | 36 | if name: |
35 | images = images.filter(Image.name.like("%" + name + "%")) | 37 | images = images.filter(Image.name.like("%" + name + "%")) |
38 | + if tag_guid: | ||
39 | + tag:ImageTag = ImageTag.query.filter_by(guid=tag_guid).one_or_none() | ||
40 | + images_guid = [img.guid for img in tag.images.all()] | ||
41 | + images = images.filter(Image.guid.in_(images_guid)) | ||
42 | + | ||
36 | 43 | ||
37 | images = images.limit(page_size).offset(page_index).all() | 44 | images = images.limit(page_size).offset(page_index).all() |
38 | 45 | ||
@@ -61,6 +68,9 @@ class Api(ApiTemplate): | @@ -61,6 +68,9 @@ class Api(ApiTemplate): | ||
61 | {"name": "name", | 68 | {"name": "name", |
62 | "in": "formData", | 69 | "in": "formData", |
63 | "type": "string"}, | 70 | "type": "string"}, |
71 | + {"name": "tag_guid", | ||
72 | + "in": "formData", | ||
73 | + "type": "string"}, | ||
64 | ], | 74 | ], |
65 | "responses": { | 75 | "responses": { |
66 | 200: { | 76 | 200: { |
@@ -47,11 +47,18 @@ class Api(ApiTemplate): | @@ -47,11 +47,18 @@ class Api(ApiTemplate): | ||
47 | image = Image.query.filter_by(guid=guid).one_or_none() | 47 | image = Image.query.filter_by(guid=guid).one_or_none() |
48 | # 该影像的服务器,随机选取一个 | 48 | # 该影像的服务器,随机选取一个 |
49 | image_servers = image.server.split(",") | 49 | image_servers = image.server.split(",") |
50 | - indx = int(random.random() * len(image_servers)) | ||
51 | - image_server = image_servers[indx] | 50 | + image_servers = [ser for ser in image_servers if zoo.exists("/rpc/{}".format(ser)) or ser.__eq__("本地服务器") ] |
51 | + if len(image_servers) > 0: | ||
52 | + indx = int(random.random() * len(image_servers)) | ||
53 | + image_server = image_servers[indx] | ||
54 | + else: | ||
55 | + image_server = "None" | ||
56 | + | ||
52 | wms_api = WMSApi() | 57 | wms_api = WMSApi() |
53 | 58 | ||
54 | - bands = [1,2,3] if image.band_count>=3 else [1,1,1] | 59 | + bands = json.loads(image.band_view) |
60 | + | ||
61 | + # bands = [1,2,3] if image.band_count>=3 else [1,1,1] | ||
55 | 62 | ||
56 | #计算查询范围,保持正常比例 | 63 | #计算查询范围,保持正常比例 |
57 | query_extent = json.loads(image.extent) | 64 | query_extent = json.loads(image.extent) |
@@ -63,7 +70,7 @@ class Api(ApiTemplate): | @@ -63,7 +70,7 @@ class Api(ApiTemplate): | ||
63 | query_extent = [query_extent[0] - offset, query_extent[1], query_extent[2] + offset, query_extent[3]] | 70 | query_extent = [query_extent[0] - offset, query_extent[1], query_extent[2] + offset, query_extent[3]] |
64 | 71 | ||
65 | 72 | ||
66 | - pixel_array_t = wms_api.get_data(zoo, image_server, image, query_extent, bands, 256, 256) | 73 | + pixel_array_t = wms_api.get_data(image_server, image, query_extent, bands, 256, 256) |
67 | 74 | ||
68 | 75 | ||
69 | pixel_array = numpy.zeros((256, 256, 3), dtype=int) | 76 | pixel_array = numpy.zeros((256, 256, 3), dtype=int) |
@@ -14,7 +14,9 @@ import datetime | @@ -14,7 +14,9 @@ import datetime | ||
14 | from app.models import db | 14 | from app.models import db |
15 | import uuid | 15 | import uuid |
16 | import os | 16 | import os |
17 | +from .models import ImageTag | ||
17 | import math | 18 | import math |
19 | + | ||
18 | class Api(ApiTemplate): | 20 | class Api(ApiTemplate): |
19 | 21 | ||
20 | api_name = "注册影像数据" | 22 | api_name = "注册影像数据" |
@@ -28,6 +30,12 @@ class Api(ApiTemplate): | @@ -28,6 +30,12 @@ class Api(ApiTemplate): | ||
28 | try: | 30 | try: |
29 | data_server = self.para.get("data_server") | 31 | data_server = self.para.get("data_server") |
30 | paths = json.loads(self.para.get("paths")) | 32 | paths = json.loads(self.para.get("paths")) |
33 | + tag_guids = self.para.get("tag_guids") | ||
34 | + if tag_guids: | ||
35 | + tags = db.session.query(ImageTag).filter(ImageTag.guid.in_(tag_guids.split(","))).all() | ||
36 | + else: | ||
37 | + tags = [] | ||
38 | + | ||
31 | 39 | ||
32 | #注册某影像 | 40 | #注册某影像 |
33 | infos = [] | 41 | infos = [] |
@@ -43,7 +51,7 @@ class Api(ApiTemplate): | @@ -43,7 +51,7 @@ class Api(ApiTemplate): | ||
43 | origin = osr.SpatialReference() | 51 | origin = osr.SpatialReference() |
44 | origin.ImportFromWkt(image.GetProjection()) | 52 | origin.ImportFromWkt(image.GetProjection()) |
45 | 53 | ||
46 | - authority_code = origin.GetAuthorityCode() | 54 | + authority_code = origin.GetAuthorityCode(None) |
47 | band_count = image.RasterCount | 55 | band_count = image.RasterCount |
48 | band: Band = image.GetRasterBand(1) | 56 | band: Band = image.GetRasterBand(1) |
49 | count = band.GetOverviewCount() | 57 | count = band.GetOverviewCount() |
@@ -63,6 +71,7 @@ class Api(ApiTemplate): | @@ -63,6 +71,7 @@ class Api(ApiTemplate): | ||
63 | # geo_origin_extent = [geo_left_top[1], geo_right_buttom[0], geo_right_buttom[1], geo_left_top[0]] | 71 | # geo_origin_extent = [geo_left_top[1], geo_right_buttom[0], geo_right_buttom[1], geo_left_top[0]] |
64 | 72 | ||
65 | info = {"band_count": band_count, | 73 | info = {"band_count": band_count, |
74 | + "band_view":"[1,2,3]" if band_count>=3 else "[1,1,1]", | ||
66 | "overview_count": count, | 75 | "overview_count": count, |
67 | "path":image_info["path"], | 76 | "path":image_info["path"], |
68 | "xy_size": [image.RasterXSize, image.RasterYSize], | 77 | "xy_size": [image.RasterXSize, image.RasterYSize], |
@@ -108,17 +117,17 @@ class Api(ApiTemplate): | @@ -108,17 +117,17 @@ class Api(ApiTemplate): | ||
108 | if exist_image.server.__contains__(data_server): | 117 | if exist_image.server.__contains__(data_server): |
109 | pass | 118 | pass |
110 | else: | 119 | else: |
111 | - exist_image.update({"server":"{},".format(data_server)}) | 120 | + exist_image.update({"server":"{},{}".format(exist_image.server,data_server)}) |
112 | else: | 121 | else: |
113 | - image = Image(guid= uuid.uuid1().__str__(), | 122 | + img:Image = Image(guid= uuid.uuid1().__str__(), |
114 | overview_count=info.get("overview_count"), | 123 | overview_count=info.get("overview_count"), |
115 | raster_x_size=info["xy_size"][0], | 124 | raster_x_size=info["xy_size"][0], |
116 | raster_y_size=info["xy_size"][1], | 125 | raster_y_size=info["xy_size"][1], |
117 | cell_x_size = info.get("cell_x_size"), | 126 | cell_x_size = info.get("cell_x_size"), |
118 | cell_y_size = abs(info.get("cell_y_size")), | 127 | cell_y_size = abs(info.get("cell_y_size")), |
119 | name=os.path.basename(info.get("path")), | 128 | name=os.path.basename(info.get("path")), |
129 | + alias = os.path.basename(info.get("path")), | ||
120 | extent=json.dumps(info["origin_extent"]), | 130 | extent=json.dumps(info["origin_extent"]), |
121 | - # geo_origin_extent = json.dumps(info["geo_origin_extent"]), | ||
122 | null_value=info.get("null_value"), | 131 | null_value=info.get("null_value"), |
123 | server=data_server, | 132 | server=data_server, |
124 | path = os.path.normpath(info.get("path")), | 133 | path = os.path.normpath(info.get("path")), |
@@ -129,12 +138,10 @@ class Api(ApiTemplate): | @@ -129,12 +138,10 @@ class Api(ApiTemplate): | ||
129 | band_count=info.get("band_count"), | 138 | band_count=info.get("band_count"), |
130 | create_time=this_time | 139 | create_time=this_time |
131 | ) | 140 | ) |
132 | - db.session.add(image) | 141 | + for tag in tags: |
142 | + img.image_tags.append(tag) | ||
143 | + db.session.add(img) | ||
133 | db.session.commit() | 144 | db.session.commit() |
134 | - # res["data"] = guid | ||
135 | - | ||
136 | - | ||
137 | - | ||
138 | res["result"] = True | 145 | res["result"] = True |
139 | 146 | ||
140 | except Exception as e: | 147 | except Exception as e: |
@@ -181,7 +188,11 @@ class Api(ApiTemplate): | @@ -181,7 +188,11 @@ class Api(ApiTemplate): | ||
181 | {"name": "paths", | 188 | {"name": "paths", |
182 | "in": "formData", | 189 | "in": "formData", |
183 | "type": "string", | 190 | "type": "string", |
184 | - "description": "paths"} | 191 | + "description": "paths"}, |
192 | + {"name": "tags", | ||
193 | + "in": "formData", | ||
194 | + "type": "string", | ||
195 | + "description": "tags以,相隔"} | ||
185 | ], | 196 | ], |
186 | "responses": { | 197 | "responses": { |
187 | 200: { | 198 | 200: { |
@@ -139,7 +139,7 @@ class Api(ApiTemplate): | @@ -139,7 +139,7 @@ class Api(ApiTemplate): | ||
139 | {"name": "type", | 139 | {"name": "type", |
140 | "in": "formData", | 140 | "in": "formData", |
141 | "type": "string", | 141 | "type": "string", |
142 | - "enum": ["WMS", "WMTS", "影像WMS", "影像WMTS"], | 142 | + "enum": ["WMS/WFS","WMTS","MTS","ImageWMS","ImageWMTS"], |
143 | "required": "true", | 143 | "required": "true", |
144 | "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | 144 | "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, |
145 | {"name": "catalog_guid", | 145 | {"name": "catalog_guid", |
@@ -19,21 +19,18 @@ import cv2 | @@ -19,21 +19,18 @@ import cv2 | ||
19 | from app.modules.service.image.models import ImageService,Image | 19 | from app.modules.service.image.models import ImageService,Image |
20 | from app.models import db,TileScheme | 20 | from app.models import db,TileScheme |
21 | from app.util.component.ApiTemplate import ApiTemplate | 21 | from app.util.component.ApiTemplate import ApiTemplate |
22 | -import uuid | ||
23 | from app.util.component.SliceScheme import SliceScheme | 22 | from app.util.component.SliceScheme import SliceScheme |
24 | -from app.util.component.FileProcess import FileProcess | ||
25 | from app.util.component.ParameterUtil import ParameterUtil | 23 | from app.util.component.ParameterUtil import ParameterUtil |
26 | -from app.util.component.GeometryAdapter import GeometryAdapter | ||
27 | -import os | ||
28 | import json | 24 | import json |
29 | from kazoo.client import KazooClient | 25 | from kazoo.client import KazooClient |
30 | - | ||
31 | from threading import Thread | 26 | from threading import Thread |
32 | - | ||
33 | -from app.modules.service.image.util.ThriftConnect import ThriftConnect | ||
34 | -from flask import current_app | 27 | +from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPool |
35 | import gzip | 28 | import gzip |
36 | import random | 29 | import random |
30 | +import copy | ||
31 | + | ||
32 | + | ||
33 | + | ||
37 | class Api(ApiTemplate): | 34 | class Api(ApiTemplate): |
38 | 35 | ||
39 | api_name = "切片" | 36 | api_name = "切片" |
@@ -46,7 +43,7 @@ class Api(ApiTemplate): | @@ -46,7 +43,7 @@ class Api(ApiTemplate): | ||
46 | self.col = col | 43 | self.col = col |
47 | 44 | ||
48 | def process(self): | 45 | def process(self): |
49 | - from app import GLOBAL_DIC | 46 | + |
50 | result = {} | 47 | result = {} |
51 | parameter: dict = self.para | 48 | parameter: dict = self.para |
52 | 49 | ||
@@ -54,33 +51,13 @@ class Api(ApiTemplate): | @@ -54,33 +51,13 @@ class Api(ApiTemplate): | ||
54 | if parameter.get("guid"): | 51 | if parameter.get("guid"): |
55 | self.guid = parameter.get("guid") | 52 | self.guid = parameter.get("guid") |
56 | 53 | ||
57 | - #缓存服务信息 | ||
58 | - image_service_info = GLOBAL_DIC.get(self.guid) | ||
59 | - if image_service_info is None: | ||
60 | - image_service:ImageService = ImageService.query.filter_by(guid = self.guid).one_or_none() | ||
61 | - images = image_service.images.all() | ||
62 | - scheme:TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none() | ||
63 | - GLOBAL_DIC[self.guid] = {"service":image_service,"images":images,"scheme":json.loads(scheme.parameter)} | ||
64 | - image_service_info = GLOBAL_DIC[self.guid] | ||
65 | - else: | ||
66 | - image_service_info = GLOBAL_DIC[self.guid] | ||
67 | - | ||
68 | - zoo = GLOBAL_DIC.get("zookeeper") | ||
69 | - if zoo is None: | ||
70 | - zoo :KazooClient = KazooClient(hosts=configure.zookeeper, timeout=100) | ||
71 | - zoo.start() | ||
72 | - GLOBAL_DIC["zookeeper"] = zoo | ||
73 | - else : | ||
74 | - if not zoo.connected: | ||
75 | - zoo.start() | ||
76 | - | ||
77 | - bands = [1, 2, 3] | 54 | + image_service_info, zoo, servers = self.cache_data() |
78 | 55 | ||
56 | + # bands = [1, 2, 3] | ||
79 | 57 | ||
80 | # 转换参数 | 58 | # 转换参数 |
81 | parameter = ParameterUtil.to_lower(parameter) | 59 | parameter = ParameterUtil.to_lower(parameter) |
82 | 60 | ||
83 | - | ||
84 | if parameter.get("tilematrix"): | 61 | if parameter.get("tilematrix"): |
85 | if parameter.get("tilematrix").__contains__(":"): | 62 | if parameter.get("tilematrix").__contains__(":"): |
86 | self.level = int(parameter.get("tilematrix").split(":")[-1]) | 63 | self.level = int(parameter.get("tilematrix").split(":")[-1]) |
@@ -96,7 +73,6 @@ class Api(ApiTemplate): | @@ -96,7 +73,6 @@ class Api(ApiTemplate): | ||
96 | slice_para = image_service_info["scheme"] | 73 | slice_para = image_service_info["scheme"] |
97 | extent = SliceScheme.get_polygon(slice_para, self.level, self.row, self.col) | 74 | extent = SliceScheme.get_polygon(slice_para, self.level, self.row, self.col) |
98 | 75 | ||
99 | - | ||
100 | height, width = 256,256 | 76 | height, width = 256,256 |
101 | 77 | ||
102 | # 多线程获取分布式数据 | 78 | # 多线程获取分布式数据 |
@@ -106,20 +82,25 @@ class Api(ApiTemplate): | @@ -106,20 +82,25 @@ class Api(ApiTemplate): | ||
106 | if len(intersect_image) > 1: | 82 | if len(intersect_image) > 1: |
107 | 83 | ||
108 | # 结果矩阵 | 84 | # 结果矩阵 |
109 | - empty_list = [numpy.zeros((height, width), dtype=int) + 65536, | ||
110 | - numpy.zeros((height, width), dtype=int) + 65536, | ||
111 | - numpy.zeros((height, width), dtype=int) + 65536] | 85 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 |
112 | 86 | ||
113 | - pixel_array = numpy.zeros((height, width, 3), dtype=int) | ||
114 | thread_list = [] | 87 | thread_list = [] |
115 | 88 | ||
116 | for image in intersect_image: | 89 | for image in intersect_image: |
90 | + | ||
117 | # 该影像的服务器,随机选取一个 | 91 | # 该影像的服务器,随机选取一个 |
118 | image_servers = image.server.split(",") | 92 | image_servers = image.server.split(",") |
119 | - indx = int(random.random() * len(image_servers)) | ||
120 | - image_server = image_servers[indx] | 93 | + image_servers = [ser for ser in image_servers if ser in servers] |
94 | + if len(image_servers)>0: | ||
95 | + indx = int(random.random() * len(image_servers)) | ||
96 | + image_server = image_servers[indx] | ||
97 | + else: | ||
98 | + image_server = "None" | ||
99 | + | ||
100 | + bands = json.loads(image.band_view) | ||
101 | + | ||
121 | thread: MyThread = MyThread(self.get_data, | 102 | thread: MyThread = MyThread(self.get_data, |
122 | - args=(zoo, image_server, image, extent, bands, height, width)) | 103 | + args=(image_server, image, extent, bands, height, width)) |
123 | thread.start() | 104 | thread.start() |
124 | thread_list.append(thread) | 105 | thread_list.append(thread) |
125 | 106 | ||
@@ -128,51 +109,106 @@ class Api(ApiTemplate): | @@ -128,51 +109,106 @@ class Api(ApiTemplate): | ||
128 | data = thread.get_result() | 109 | data = thread.get_result() |
129 | 110 | ||
130 | # 掩膜在中央接口生成,合图 | 111 | # 掩膜在中央接口生成,合图 |
131 | - mask = numpy.zeros((height, width), dtype=int) | ||
132 | - mask2 = numpy.zeros((height, width), dtype=int) | ||
133 | - jizhun = data[:, :, 0] | ||
134 | - mask[jizhun == 65536] = 1 | ||
135 | - mask[jizhun != 65536] = 0 | ||
136 | - mask2[jizhun == 65536] = 0 | ||
137 | - mask2[jizhun != 65536] = 1 | ||
138 | - # 掩膜计算 | ||
139 | - for i, d in enumerate(empty_list): | ||
140 | - empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2 | 112 | + mask = numpy.zeros((height, width, 3), dtype=int) |
113 | + mask_data = numpy.zeros((height, width, 3), dtype=int) | ||
141 | 114 | ||
142 | - for ii in [0, 1, 2]: | ||
143 | - # opencv 颜色排序为GBR | ||
144 | - pixel_array[:, :, 2 - ii] = empty_list[ii] | 115 | + mask[data == 65536] = 1 |
116 | + mask[data != 65536] = 0 | ||
117 | + mask_data[data == 65536] = 0 | ||
118 | + mask_data[data != 65536] = 1 | ||
119 | + | ||
120 | + # # 掩膜计算 | ||
121 | + pixel_array = pixel_array * mask + data * mask_data | ||
122 | + | ||
123 | + # opencv 颜色排序为GBR | ||
124 | + d1 = copy.copy(pixel_array[:,:,0]) | ||
125 | + pixel_array[:, :, 0] = pixel_array[:,:,2] | ||
126 | + pixel_array[:, :, 2] = d1 | ||
145 | 127 | ||
146 | 128 | ||
147 | elif len(intersect_image) == 1: | 129 | elif len(intersect_image) == 1: |
148 | # 该影像的服务器,随机选取一个 | 130 | # 该影像的服务器,随机选取一个 |
149 | image = intersect_image[0] | 131 | image = intersect_image[0] |
150 | image_servers = image.server.split(",") | 132 | image_servers = image.server.split(",") |
151 | - indx = int(random.random() * len(image_servers)) | ||
152 | - | ||
153 | - image_server = image_servers[indx] | ||
154 | - | ||
155 | - pixel_array_t = self.get_data(zoo, image_server, image, extent, bands, height, width) | 133 | + #判断可用服务器 |
134 | + image_servers = [ser for ser in image_servers if ser in servers] | ||
135 | + if len(image_servers) > 0: | ||
136 | + indx = int(random.random() * len(image_servers)) | ||
137 | + image_server = image_servers[indx] | ||
138 | + else: | ||
139 | + image_server = "None" | ||
140 | + # image_server = image_servers[0] | ||
141 | + bands = json.loads(image.band_view) | ||
142 | + pixel_array_t:numpy.ndarray = self.get_data(image_server, image, extent, bands, height, width) | ||
156 | pixel_array = numpy.zeros((height, width, 3), dtype=int) | 143 | pixel_array = numpy.zeros((height, width, 3), dtype=int) |
144 | + | ||
157 | for ii in [0, 1, 2]: | 145 | for ii in [0, 1, 2]: |
158 | # opencv 颜色排序为GBR | 146 | # opencv 颜色排序为GBR |
159 | pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] | 147 | pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] |
160 | 148 | ||
161 | - | ||
162 | else: | 149 | else: |
163 | # 结果矩阵 | 150 | # 结果矩阵 |
164 | pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 | 151 | pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 |
165 | 152 | ||
153 | + | ||
166 | # 将图片生成在内存中,然后直接返回response | 154 | # 将图片生成在内存中,然后直接返回response |
167 | im_data = self.create_by_opencv(image_type, pixel_array, quality) | 155 | im_data = self.create_by_opencv(image_type, pixel_array, quality) |
168 | return Response(im_data, mimetype=image_type.lower()) | 156 | return Response(im_data, mimetype=image_type.lower()) |
169 | 157 | ||
158 | + | ||
170 | except Exception as e: | 159 | except Exception as e: |
171 | print(traceback.format_exc()) | 160 | print(traceback.format_exc()) |
172 | result["state"] = -1 | 161 | result["state"] = -1 |
173 | result["message"] = e.__str__() | 162 | result["message"] = e.__str__() |
174 | return result | 163 | return result |
175 | 164 | ||
165 | + def cache_data(self): | ||
166 | + | ||
167 | + from app import GLOBAL_DIC | ||
168 | + | ||
169 | + # 缓存zookeeper | ||
170 | + zoo = GLOBAL_DIC.get("zookeeper") | ||
171 | + if zoo is None: | ||
172 | + zoo: KazooClient = KazooClient(hosts=configure.zookeeper, timeout=100) | ||
173 | + zoo.start() | ||
174 | + GLOBAL_DIC["zookeeper"] = zoo | ||
175 | + else: | ||
176 | + if not zoo.connected: | ||
177 | + zoo.start() | ||
178 | + | ||
179 | + # 缓存数据服务器 | ||
180 | + servers = GLOBAL_DIC.get("servers") | ||
181 | + if servers is None: | ||
182 | + servers = zoo.get_children("/rpc") | ||
183 | + servers.append("本地服务器") | ||
184 | + GLOBAL_DIC["servers"] = servers | ||
185 | + GLOBAL_DIC["servers_updatetime"] = time.time() | ||
186 | + else: | ||
187 | + servers = GLOBAL_DIC.get("servers") | ||
188 | + | ||
189 | + # 更新缓存 | ||
190 | + if time.time() - GLOBAL_DIC["servers_updatetime"] > 10: | ||
191 | + servers = zoo.get_children("/rpc") | ||
192 | + servers.append("本地服务器") | ||
193 | + GLOBAL_DIC["servers"] = servers | ||
194 | + GLOBAL_DIC["servers_updatetime"] = time.time() | ||
195 | + | ||
196 | + | ||
197 | + # 缓存服务信息 | ||
198 | + image_service_info = GLOBAL_DIC.get(self.guid) | ||
199 | + if image_service_info is None or time.time() - GLOBAL_DIC.get("service_updatetime") > 20: | ||
200 | + image_service: ImageService = ImageService.query.filter_by(guid=self.guid).one_or_none() | ||
201 | + images = image_service.images.all() | ||
202 | + scheme: TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none() | ||
203 | + GLOBAL_DIC[self.guid] = {"service": image_service, "images": images, "scheme": json.loads(scheme.parameter)} | ||
204 | + GLOBAL_DIC["service_updatetime"] = time.time() | ||
205 | + image_service_info = GLOBAL_DIC[self.guid] | ||
206 | + | ||
207 | + else: | ||
208 | + image_service_info = GLOBAL_DIC[self.guid] | ||
209 | + | ||
210 | + return image_service_info,zoo,servers | ||
211 | + | ||
176 | def determine_level(self, xysize, origin_extent, extent, max_level): | 212 | def determine_level(self, xysize, origin_extent, extent, max_level): |
177 | ''' | 213 | ''' |
178 | 根据范围判断调用金字塔的哪一层 | 214 | 根据范围判断调用金字塔的哪一层 |
@@ -195,10 +231,12 @@ class Api(ApiTemplate): | @@ -195,10 +231,12 @@ class Api(ApiTemplate): | ||
195 | (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1]))) | 231 | (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1]))) |
196 | return level | 232 | return level |
197 | 233 | ||
234 | + | ||
198 | def create_by_opencv(self, image_type, pixel_array, quality): | 235 | def create_by_opencv(self, image_type, pixel_array, quality): |
199 | 236 | ||
200 | if image_type.__eq__("image/jpeg") or image_type.__eq__("image/jpg"): | 237 | if image_type.__eq__("image/jpeg") or image_type.__eq__("image/jpg"): |
201 | r, buf = cv2.imencode(".jpg", pixel_array, [cv2.IMWRITE_JPEG_QUALITY, quality]) | 238 | r, buf = cv2.imencode(".jpg", pixel_array, [cv2.IMWRITE_JPEG_QUALITY, quality]) |
239 | + # r, buf = cv2.imencode(".jpg", pixel_array) | ||
202 | image_out = buf.tobytes() | 240 | image_out = buf.tobytes() |
203 | else: | 241 | else: |
204 | height, width = pixel_array[:, :, 0].shape | 242 | height, width = pixel_array[:, :, 0].shape |
@@ -208,17 +246,14 @@ class Api(ApiTemplate): | @@ -208,17 +246,14 @@ class Api(ApiTemplate): | ||
208 | image_out = buf.tobytes() | 246 | image_out = buf.tobytes() |
209 | return image_out | 247 | return image_out |
210 | 248 | ||
211 | - def get_data(self, zoo, image_server, image, extent, bands, height, width): | 249 | + def get_data(self,image_server, image, extent, bands, height, width): |
212 | 250 | ||
213 | if image_server.__eq__("本地服务器"): | 251 | if image_server.__eq__("本地服务器"): |
214 | - data = self.get_local_wms_data(image, extent, bands, height, width) | 252 | + data = self.get_local_wms_data2(image, extent, bands, height, width) |
253 | + elif image_server.__eq__("None"): | ||
254 | + data = numpy.zeros((height, width, 3), dtype=int) + 65536 | ||
215 | else: | 255 | else: |
216 | - ser = image_server | ||
217 | - if zoo.exists("/rpc/{}".format(ser)): | ||
218 | - data = self.get_remote_wms_data(ser,image, extent, bands, height, width) | ||
219 | - else: | ||
220 | - data = numpy.zeros((height, width, 3), dtype=int) + 65536 | ||
221 | - | 256 | + data = self.get_remote_wms_data(image_server,image, extent, bands, height, width) |
222 | return data | 257 | return data |
223 | 258 | ||
224 | def get_remote_wms_data(self, image_server,image, extent, bands, height, width): | 259 | def get_remote_wms_data(self, image_server,image, extent, bands, height, width): |
@@ -230,24 +265,93 @@ class Api(ApiTemplate): | @@ -230,24 +265,93 @@ class Api(ApiTemplate): | ||
230 | :return: | 265 | :return: |
231 | ''' | 266 | ''' |
232 | 267 | ||
233 | - | ||
234 | #需要做thrift连接的缓存,连接池 | 268 | #需要做thrift连接的缓存,连接池 |
269 | + thrift_connect = ThriftConnect(image_server) | ||
270 | + image_extent = image.extent | ||
271 | + | ||
272 | + data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height) | ||
273 | + | ||
274 | + thrift_connect.close() | ||
275 | + | ||
276 | + data = gzip.decompress(data) | ||
277 | + data = numpy.frombuffer(data, dtype='int64') | ||
278 | + data = data.reshape((height, width, 3)) | ||
279 | + | ||
280 | + return data | ||
281 | + | ||
235 | 282 | ||
283 | + def get_remote_wms_data_cpp(self, image_server,image, extent, bands, height, width): | ||
284 | + ''' | ||
285 | + 通过RPC获取远程数据 | ||
286 | + :param image: | ||
287 | + :param extent: | ||
288 | + :param bands: | ||
289 | + :return: | ||
290 | + ''' | ||
291 | + | ||
292 | + #需要做thrift连接的缓存,连接池 | ||
236 | thrift_connect = ThriftConnect(image_server) | 293 | thrift_connect = ThriftConnect(image_server) |
237 | - t1 = time.time() | ||
238 | image_extent = image.extent | 294 | image_extent = image.extent |
239 | 295 | ||
240 | data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height) | 296 | data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height) |
241 | 297 | ||
242 | thrift_connect.close() | 298 | thrift_connect.close() |
243 | 299 | ||
244 | - # current_app.logger.info("time {}".format(time.time() - t1)) | 300 | + return data |
301 | + | ||
302 | + def get_remote_wms_data_client(self,image_server,image, extent, bands, height, width): | ||
303 | + ''' | ||
304 | + 通过RPC获取远程数据 | ||
305 | + :param image: | ||
306 | + :param extent: | ||
307 | + :param bands: | ||
308 | + :return: | ||
309 | + ''' | ||
310 | + from app import GLOBAL_DIC | ||
311 | + | ||
312 | + # 缓存thrift_pool | ||
313 | + thrift_pool = GLOBAL_DIC.get(image_server) | ||
314 | + if thrift_pool is None: | ||
315 | + thrift_pool = ThriftPool(image_server) | ||
316 | + GLOBAL_DIC["image_server"] = thrift_pool | ||
317 | + image_extent = image.extent | ||
318 | + | ||
319 | + client,transport = thrift_pool.get_client() | ||
320 | + transport.open() | ||
321 | + data = client.getData(image.path, extent, json.loads(image_extent), bands, width, height) | ||
322 | + transport.close() | ||
245 | data = gzip.decompress(data) | 323 | data = gzip.decompress(data) |
246 | data = numpy.frombuffer(data, dtype='int64') | 324 | data = numpy.frombuffer(data, dtype='int64') |
247 | data = data.reshape((height, width, 3)) | 325 | data = data.reshape((height, width, 3)) |
248 | 326 | ||
249 | return data | 327 | return data |
250 | 328 | ||
329 | + # def get_remote_wms_data_c(self, image_server,image, extent, bands, height, width): | ||
330 | + # ''' | ||
331 | + # 通过RPC获取远程数据 | ||
332 | + # :param image: | ||
333 | + # :param extent: | ||
334 | + # :param bands: | ||
335 | + # :return: | ||
336 | + # ''' | ||
337 | + # | ||
338 | + # #需要做thrift连接的缓存,连接池 | ||
339 | + # thrift_connect = ThriftConnect_C(image_server) | ||
340 | + # image_extent = image.extent | ||
341 | + # | ||
342 | + # data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height) | ||
343 | + # | ||
344 | + # thrift_connect.close() | ||
345 | + # | ||
346 | + # data = gzip.decompress(data) | ||
347 | + # data = numpy.frombuffer(data, dtype='int64') | ||
348 | + # | ||
349 | + # | ||
350 | + # data = data.reshape((height, width, 3)) | ||
351 | + # | ||
352 | + # return data | ||
353 | + | ||
354 | + | ||
251 | def get_local_wms_data(self, image, extent, bands, height, width): | 355 | def get_local_wms_data(self, image, extent, bands, height, width): |
252 | ''' | 356 | ''' |
253 | 获取本地数据 | 357 | 获取本地数据 |
@@ -259,20 +363,21 @@ class Api(ApiTemplate): | @@ -259,20 +363,21 @@ class Api(ApiTemplate): | ||
259 | pixel_array = numpy.zeros((height, width, 3), dtype=int) | 363 | pixel_array = numpy.zeros((height, width, 3), dtype=int) |
260 | ceng = 0 | 364 | ceng = 0 |
261 | img: Dataset = gdal.Open(image.path, 0) | 365 | img: Dataset = gdal.Open(image.path, 0) |
262 | - t1 = time.time() | 366 | + |
367 | + | ||
368 | + | ||
263 | for band in bands: | 369 | for band in bands: |
264 | 370 | ||
265 | # 自决定金字塔等级 | 371 | # 自决定金字塔等级 |
266 | xysize = [img.RasterXSize, img.RasterYSize] | 372 | xysize = [img.RasterXSize, img.RasterYSize] |
267 | 373 | ||
268 | - origin_extent = image.extent | 374 | + origin_extent = json.loads(image.extent) |
269 | band_data: Band = img.GetRasterBand(band) | 375 | band_data: Band = img.GetRasterBand(band) |
270 | 376 | ||
271 | max_level = band_data.GetOverviewCount() | 377 | max_level = band_data.GetOverviewCount() |
272 | 378 | ||
273 | # 超出空间范围 | 379 | # 超出空间范围 |
274 | - if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[ | ||
275 | - 3] or extent[3] < origin_extent[1]: | 380 | + if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[3] or extent[3] < origin_extent[1]: |
276 | empty = numpy.zeros((height, width), dtype=int) + 65536 | 381 | empty = numpy.zeros((height, width), dtype=int) + 65536 |
277 | # 空间范围相交 | 382 | # 空间范围相交 |
278 | else: | 383 | else: |
@@ -351,10 +456,96 @@ class Api(ApiTemplate): | @@ -351,10 +456,96 @@ class Api(ApiTemplate): | ||
351 | ceng += 1 | 456 | ceng += 1 |
352 | return pixel_array | 457 | return pixel_array |
353 | 458 | ||
459 | + def get_local_wms_data2(self, image, extent, bands, height, width): | ||
460 | + ''' | ||
461 | + 获取本地数据 | ||
462 | + :param image: | ||
463 | + :param extent: | ||
464 | + :param bands: | ||
465 | + :return: | ||
466 | + ''' | ||
467 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) | ||
468 | + ceng = 0 | ||
469 | + img: Dataset = gdal.Open(image.path, 0) | ||
470 | + | ||
471 | + origin_extent = json.loads(image.extent) | ||
472 | + | ||
473 | + # 超出空间范围 | ||
474 | + if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[3] or extent[ | ||
475 | + 3] < origin_extent[1]: | ||
476 | + empty = numpy.zeros((height, width,3), dtype=int) + 65536 | ||
477 | + # 空间范围相交 | ||
478 | + else: | ||
479 | + | ||
480 | + ox = img.RasterXSize | ||
481 | + oy = img.RasterYSize | ||
482 | + | ||
483 | + # 网格大小 | ||
484 | + grid_x = (origin_extent[2] - origin_extent[0]) / (ox * 1.0) | ||
485 | + grid_y = (origin_extent[3] - origin_extent[1]) / (oy * 1.0) | ||
486 | + | ||
487 | + # 完全在影像范围内 | ||
488 | + if extent[0] > origin_extent[0] and extent[1] > origin_extent[1] and extent[2] < \ | ||
489 | + origin_extent[2] and extent[3] < origin_extent[3]: | ||
490 | + | ||
491 | + # 网格偏移量 | ||
492 | + off_x = math.floor((extent[0] - origin_extent[0]) / grid_x) | ||
493 | + off_y = math.floor((origin_extent[3] - extent[3]) / grid_y) | ||
494 | + | ||
495 | + # 截取后网格个数 | ||
496 | + x_g = math.ceil((extent[2] - extent[0]) / grid_x) | ||
497 | + | ||
498 | + y_g = math.ceil((extent[3] - extent[1]) / grid_y) | ||
499 | + | ||
500 | + empty = img.ReadRaster(off_x, off_y, x_g, y_g,256,256,band_list=[1,2,3]) | ||
501 | + img.ReadAsArray() | ||
502 | + # 部分相交 | ||
503 | + else: | ||
504 | + | ||
505 | + inter_extent = [0, 0, 0, 0] | ||
506 | + inter_extent[0] = origin_extent[0] if origin_extent[0] > extent[0] else extent[0] | ||
507 | + inter_extent[1] = origin_extent[1] if origin_extent[1] > extent[1] else extent[1] | ||
508 | + inter_extent[2] = origin_extent[2] if origin_extent[2] < extent[2] else extent[2] | ||
509 | + inter_extent[3] = origin_extent[3] if origin_extent[3] < extent[3] else extent[3] | ||
510 | + | ||
511 | + # 网格偏移量 | ||
512 | + off_x = math.floor((inter_extent[0] - origin_extent[0]) / grid_x) | ||
513 | + off_y = math.floor((origin_extent[3] - inter_extent[3]) / grid_y) | ||
514 | + | ||
515 | + # 截取后网格个数 | ||
516 | + x_g = math.floor((inter_extent[2] - inter_extent[0]) / grid_x) | ||
517 | + y_g = math.floor((inter_extent[3] - inter_extent[1]) / grid_y) | ||
518 | + | ||
519 | + # 相对于出图的偏移量 | ||
520 | + | ||
521 | + # 出图的网格大小 | ||
522 | + out_grid_x = (extent[2] - extent[0]) / (width * 1.0) | ||
523 | + out_grid_y = (extent[3] - extent[1]) / (height * 1.0) | ||
524 | + | ||
525 | + out_off_x = int(math.ceil((inter_extent[0] - extent[0]) / out_grid_x)) | ||
526 | + out_off_y = int(math.ceil((extent[3] - inter_extent[3]) / out_grid_y)) | ||
527 | + | ||
528 | + out_x_g = int(math.floor((inter_extent[2] - inter_extent[0]) / out_grid_x)) | ||
529 | + out_y_g = int(math.floor((inter_extent[3] - inter_extent[1]) / out_grid_y)) | ||
530 | + | ||
531 | + # 相交部分在出图的哪个位置 | ||
532 | + | ||
533 | + overview_raster: ndarray = img.ReadAsArray(off_x, off_y, x_g, y_g, out_x_g, | ||
534 | + out_y_g) | ||
535 | + | ||
536 | + dat = numpy.zeros((height, width,3), dtype=int) + 65536 | ||
537 | + dat[out_off_y:out_off_y + out_y_g, out_off_x:out_off_x + out_x_g] = overview_raster | ||
538 | + empty = dat | ||
539 | + | ||
540 | + return empty | ||
541 | + | ||
354 | def determin_intersect(self, extent1, extent2): | 542 | def determin_intersect(self, extent1, extent2): |
355 | - g1 = GeometryAdapter.bbox_2_polygon(extent1) | ||
356 | - g2 = GeometryAdapter.bbox_2_polygon(extent2) | ||
357 | - return g1.Intersect(g2) | 543 | + if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ |
544 | + 3] or extent2[3] < extent1[1]: | ||
545 | + return False | ||
546 | + else: | ||
547 | + return True | ||
548 | + | ||
358 | 549 | ||
359 | api_doc = { | 550 | api_doc = { |
360 | "tags": ["影像接口"], | 551 | "tags": ["影像接口"], |
app/modules/service/image/image_tile_mask.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 | +from osgeo import gdal | ||
9 | +from osgeo.gdal import * | ||
10 | +from numpy import ndarray | ||
11 | +import numpy | ||
12 | +from flask import Response | ||
13 | +import io | ||
14 | +import os | ||
15 | +from PIL import Image | ||
16 | + | ||
17 | +import time | ||
18 | +import cv2 | ||
19 | +from app.modules.service.image.models import ImageService,Image | ||
20 | +from app.models import db,TileScheme | ||
21 | +from app.util.component.ApiTemplate import ApiTemplate | ||
22 | +import uuid | ||
23 | +from app.util.component.SliceScheme import SliceScheme | ||
24 | +from app.util.component.FileProcess import FileProcess | ||
25 | +from app.util.component.ParameterUtil import ParameterUtil | ||
26 | +from app.util.component.GeometryAdapter import GeometryAdapter | ||
27 | +from app.util.component.Geometry2Raster import Geometry2Raster | ||
28 | +import os | ||
29 | +import json | ||
30 | +from kazoo.client import KazooClient | ||
31 | + | ||
32 | +from threading import Thread | ||
33 | + | ||
34 | +from app.modules.service.image.util.ThriftConnect import ThriftConnect | ||
35 | +from flask import current_app | ||
36 | +import gzip | ||
37 | +import random | ||
38 | +class Api(ApiTemplate): | ||
39 | + | ||
40 | + api_name = "切片" | ||
41 | + | ||
42 | + def __init__(self,guid,level, row, col): | ||
43 | + super().__init__() | ||
44 | + self.guid = guid | ||
45 | + self.level = level | ||
46 | + self.row = row | ||
47 | + self.col = col | ||
48 | + | ||
49 | + def process(self): | ||
50 | + from app import GLOBAL_DIC | ||
51 | + result = {} | ||
52 | + parameter: dict = self.para | ||
53 | + | ||
54 | + | ||
55 | + | ||
56 | + | ||
57 | + | ||
58 | + try: | ||
59 | + if parameter.get("guid"): | ||
60 | + self.guid = parameter.get("guid") | ||
61 | + | ||
62 | + #缓存服务信息 | ||
63 | + image_service_info = GLOBAL_DIC.get(self.guid) | ||
64 | + if image_service_info is None: | ||
65 | + image_service:ImageService = ImageService.query.filter_by(guid = self.guid).one_or_none() | ||
66 | + images = image_service.images.all() | ||
67 | + scheme:TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none() | ||
68 | + | ||
69 | + # test mask | ||
70 | + ring = ogr.Geometry(ogr.wkbLinearRing) | ||
71 | + ring.AddPoint(111.62, 29) | ||
72 | + ring.AddPoint(111.62, 29.03) | ||
73 | + ring.AddPoint(111.727, 29.03) | ||
74 | + ring.AddPoint(111.727, 29) | ||
75 | + ring.AddPoint(111.62, 29) | ||
76 | + # Create polygon | ||
77 | + mask_poly = ogr.Geometry(ogr.wkbPolygon) | ||
78 | + mask_poly.AddGeometry(ring) | ||
79 | + | ||
80 | + GLOBAL_DIC[self.guid] = {"service": image_service, "images": images, | ||
81 | + "scheme": json.loads(scheme.parameter),"mask": | ||
82 | + mask_poly} | ||
83 | + | ||
84 | + | ||
85 | + image_service_info = GLOBAL_DIC[self.guid] | ||
86 | + else: | ||
87 | + image_service_info = GLOBAL_DIC[self.guid] | ||
88 | + | ||
89 | + zoo = GLOBAL_DIC.get("zookeeper") | ||
90 | + if zoo is None: | ||
91 | + zoo :KazooClient = KazooClient(hosts=configure.zookeeper, timeout=100) | ||
92 | + zoo.start() | ||
93 | + GLOBAL_DIC["zookeeper"] = zoo | ||
94 | + else : | ||
95 | + if not zoo.connected: | ||
96 | + zoo.start() | ||
97 | + | ||
98 | + bands = [1, 2, 3] | ||
99 | + | ||
100 | + | ||
101 | + # 转换参数 | ||
102 | + parameter = ParameterUtil.to_lower(parameter) | ||
103 | + | ||
104 | + | ||
105 | + if parameter.get("tilematrix"): | ||
106 | + if parameter.get("tilematrix").__contains__(":"): | ||
107 | + self.level = int(parameter.get("tilematrix").split(":")[-1]) | ||
108 | + else: | ||
109 | + self.level = int(parameter.get("tilematrix")) | ||
110 | + if parameter.get("tilerow"): | ||
111 | + self.row = int(parameter.get("tilerow")) | ||
112 | + if parameter.get("tilecol"): | ||
113 | + self.col = int(parameter.get("tilecol")) | ||
114 | + | ||
115 | + image_type = parameter.get("format") if parameter.get("format") else "image/png" | ||
116 | + quality = int(parameter.get("quality")) if parameter.get("quality") else 30 | ||
117 | + slice_para = image_service_info["scheme"] | ||
118 | + extent = SliceScheme.get_polygon(slice_para, self.level, self.row, self.col) | ||
119 | + | ||
120 | + | ||
121 | + height, width = 256,256 | ||
122 | + | ||
123 | + # 多线程获取分布式数据 | ||
124 | + | ||
125 | + intersect_image = [im for im in image_service_info["images"] if | ||
126 | + self.determin_intersect(json.loads(im.extent), extent,image_service_info["mask"])] | ||
127 | + | ||
128 | + masker_raster = Geometry2Raster.convert(image_service_info["mask"],extent,height) | ||
129 | + | ||
130 | + if len(intersect_image) > 1: | ||
131 | + | ||
132 | + # 结果矩阵 | ||
133 | + empty_list = [numpy.zeros((height, width), dtype=int) + 65536, | ||
134 | + numpy.zeros((height, width), dtype=int) + 65536, | ||
135 | + numpy.zeros((height, width), dtype=int) + 65536] | ||
136 | + | ||
137 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) | ||
138 | + thread_list = [] | ||
139 | + | ||
140 | + for image in intersect_image: | ||
141 | + # 该影像的服务器,随机选取一个 | ||
142 | + image_servers = image.server.split(",") | ||
143 | + image_servers = [ser for ser in image_servers if zoo.exists("/rpc/{}".format(ser))] | ||
144 | + if len(image_servers)>0: | ||
145 | + indx = int(random.random() * len(image_servers)) | ||
146 | + image_server = image_servers[indx] | ||
147 | + else: | ||
148 | + image_server = "None" | ||
149 | + | ||
150 | + thread: MyThread = MyThread(self.get_data, | ||
151 | + args=(image_server, image, extent, bands, height, width)) | ||
152 | + thread.start() | ||
153 | + thread_list.append(thread) | ||
154 | + | ||
155 | + for thread in thread_list: | ||
156 | + thread.join() | ||
157 | + data = thread.get_result() | ||
158 | + | ||
159 | + # 掩膜在中央接口生成,合图 | ||
160 | + mask = numpy.zeros((height, width), dtype=int) | ||
161 | + mask2 = numpy.zeros((height, width), dtype=int) | ||
162 | + jizhun = data[:, :, 0] | ||
163 | + mask[jizhun == 65536] = 1 | ||
164 | + mask[jizhun != 65536] = 0 | ||
165 | + mask2[jizhun == 65536] = 0 | ||
166 | + mask2[jizhun != 65536] = 1 | ||
167 | + # 掩膜计算 | ||
168 | + for i, d in enumerate(empty_list): | ||
169 | + empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2 | ||
170 | + | ||
171 | + e = numpy.zeros((height, width), dtype=int) + 65536 | ||
172 | + e_mask = numpy.zeros((height, width), dtype=int) | ||
173 | + e_mask[masker_raster == 1] = 0 | ||
174 | + e_mask[masker_raster == 0] = 1 | ||
175 | + | ||
176 | + for ii in [0, 1, 2]: | ||
177 | + # opencv 颜色排序为GBR | ||
178 | + # pixel_array[:, :, 2 - ii] = empty_list[ii] | ||
179 | + #mask | ||
180 | + pixel_array[:, :, 2 - ii] = e * e_mask + empty_list[ii] * masker_raster | ||
181 | + | ||
182 | + elif len(intersect_image) == 1: | ||
183 | + # 该影像的服务器,随机选取一个 | ||
184 | + image = intersect_image[0] | ||
185 | + image_servers = image.server.split(",") | ||
186 | + #判断可用服务器 | ||
187 | + image_servers = [ser for ser in image_servers if zoo.exists("/rpc/{}".format(ser))] | ||
188 | + if len(image_servers) > 0: | ||
189 | + indx = int(random.random() * len(image_servers)) | ||
190 | + image_server = image_servers[indx] | ||
191 | + else: | ||
192 | + image_server = "None" | ||
193 | + pixel_array_t = self.get_data(image_server, image, extent, bands, height, width) | ||
194 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) | ||
195 | + | ||
196 | + e = numpy.zeros((height, width), dtype=int) + 65536 | ||
197 | + e_mask = numpy.zeros((height, width), dtype=int) | ||
198 | + e_mask[masker_raster == 1] = 0 | ||
199 | + e_mask[masker_raster == 0] = 1 | ||
200 | + | ||
201 | + for ii in [0, 1, 2]: | ||
202 | + # opencv 颜色排序为GBR | ||
203 | + # pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] | ||
204 | + pixel_array[:, :, 2 - ii] = e * e_mask + pixel_array_t[:, :, ii] * masker_raster | ||
205 | + else: | ||
206 | + # 结果矩阵 | ||
207 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 | ||
208 | + | ||
209 | + | ||
210 | + # 将图片生成在内存中,然后直接返回response | ||
211 | + im_data = self.create_by_opencv(image_type, pixel_array, quality) | ||
212 | + return Response(im_data, mimetype=image_type.lower()) | ||
213 | + | ||
214 | + except Exception as e: | ||
215 | + print(traceback.format_exc()) | ||
216 | + result["state"] = -1 | ||
217 | + result["message"] = e.__str__() | ||
218 | + return result | ||
219 | + | ||
220 | + def determine_level(self, xysize, origin_extent, extent, max_level): | ||
221 | + ''' | ||
222 | + 根据范围判断调用金字塔的哪一层 | ||
223 | + :param xysize: | ||
224 | + :param origin_extent: | ||
225 | + :param extent: | ||
226 | + :param max_level: | ||
227 | + :return: | ||
228 | + ''' | ||
229 | + x = xysize[0] | ||
230 | + y = xysize[1] | ||
231 | + level = -1 | ||
232 | + pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / ( | ||
233 | + (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1]))) | ||
234 | + while pixel > 100000 and level < max_level - 1: | ||
235 | + level += 1 | ||
236 | + x = x / 2 | ||
237 | + y = y / 2 | ||
238 | + pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / ( | ||
239 | + (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1]))) | ||
240 | + return level | ||
241 | + | ||
242 | + def create_by_opencv(self, image_type, pixel_array, quality): | ||
243 | + | ||
244 | + if image_type.__eq__("image/jpeg") or image_type.__eq__("image/jpg"): | ||
245 | + r, buf = cv2.imencode(".jpg", pixel_array, [cv2.IMWRITE_JPEG_QUALITY, quality]) | ||
246 | + image_out = buf.tobytes() | ||
247 | + else: | ||
248 | + height, width = pixel_array[:, :, 0].shape | ||
249 | + four = numpy.zeros((height, width), dtype=int) + 255 | ||
250 | + four[pixel_array[:, :, 0] == 65536] = 0 | ||
251 | + r, buf = cv2.imencode(".png", numpy.dstack((pixel_array, four))) | ||
252 | + image_out = buf.tobytes() | ||
253 | + return image_out | ||
254 | + | ||
255 | + def get_data(self,image_server, image, extent, bands, height, width): | ||
256 | + | ||
257 | + if image_server.__eq__("本地服务器"): | ||
258 | + data = self.get_local_wms_data(image, extent, bands, height, width) | ||
259 | + elif image_server.__eq__("None"): | ||
260 | + data = numpy.zeros((height, width, 3), dtype=int) + 65536 | ||
261 | + else: | ||
262 | + data = self.get_remote_wms_data(image_server,image, extent, bands, height, width) | ||
263 | + return data | ||
264 | + | ||
265 | + def get_remote_wms_data(self, image_server,image, extent, bands, height, width): | ||
266 | + ''' | ||
267 | + 通过RPC获取远程数据 | ||
268 | + :param image: | ||
269 | + :param extent: | ||
270 | + :param bands: | ||
271 | + :return: | ||
272 | + ''' | ||
273 | + | ||
274 | + #需要做thrift连接的缓存,连接池 | ||
275 | + thrift_connect = ThriftConnect(image_server) | ||
276 | + image_extent = image.extent | ||
277 | + | ||
278 | + data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height) | ||
279 | + | ||
280 | + thrift_connect.close() | ||
281 | + | ||
282 | + data = gzip.decompress(data) | ||
283 | + data = numpy.frombuffer(data, dtype='int64') | ||
284 | + data = data.reshape((height, width, 3)) | ||
285 | + | ||
286 | + return data | ||
287 | + | ||
288 | + def get_local_wms_data(self, image, extent, bands, height, width): | ||
289 | + ''' | ||
290 | + 获取本地数据 | ||
291 | + :param image: | ||
292 | + :param extent: | ||
293 | + :param bands: | ||
294 | + :return: | ||
295 | + ''' | ||
296 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) | ||
297 | + ceng = 0 | ||
298 | + img: Dataset = gdal.Open(image.path, 0) | ||
299 | + t1 = time.time() | ||
300 | + for band in bands: | ||
301 | + | ||
302 | + # 自决定金字塔等级 | ||
303 | + xysize = [img.RasterXSize, img.RasterYSize] | ||
304 | + | ||
305 | + origin_extent = image.extent | ||
306 | + band_data: Band = img.GetRasterBand(band) | ||
307 | + | ||
308 | + max_level = band_data.GetOverviewCount() | ||
309 | + | ||
310 | + # 超出空间范围 | ||
311 | + if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[ | ||
312 | + 3] or extent[3] < origin_extent[1]: | ||
313 | + empty = numpy.zeros((height, width), dtype=int) + 65536 | ||
314 | + # 空间范围相交 | ||
315 | + else: | ||
316 | + image_level = self.determine_level(xysize, origin_extent, extent, max_level) | ||
317 | + | ||
318 | + if image_level == -1: | ||
319 | + overview = band_data | ||
320 | + else: | ||
321 | + try: | ||
322 | + overview: Band = band_data.GetOverview(image_level) | ||
323 | + except: | ||
324 | + raise Exception("该影像不存在该级别的金字塔数据!") | ||
325 | + ox = overview.XSize | ||
326 | + oy = overview.YSize | ||
327 | + | ||
328 | + # 网格大小 | ||
329 | + grid_x = (origin_extent[2] - origin_extent[0]) / (ox * 1.0) | ||
330 | + grid_y = (origin_extent[3] - origin_extent[1]) / (oy * 1.0) | ||
331 | + | ||
332 | + # 完全在影像范围内 | ||
333 | + if extent[0] > origin_extent[0] and extent[1] > origin_extent[1] and extent[2] < \ | ||
334 | + origin_extent[2] and extent[3] < origin_extent[3]: | ||
335 | + | ||
336 | + # 网格偏移量 | ||
337 | + off_x = math.floor((extent[0] - origin_extent[0]) / grid_x) | ||
338 | + off_y = math.floor((origin_extent[3] - extent[3]) / grid_y) | ||
339 | + | ||
340 | + # 截取后网格个数 | ||
341 | + x_g = math.ceil((extent[2] - extent[0]) / grid_x) | ||
342 | + | ||
343 | + y_g = math.ceil((extent[3] - extent[1]) / grid_y) | ||
344 | + | ||
345 | + empty = overview.ReadAsArray(off_x, off_y, x_g, y_g, width, height) | ||
346 | + | ||
347 | + | ||
348 | + # 部分相交 | ||
349 | + else: | ||
350 | + | ||
351 | + inter_extent = [0, 0, 0, 0] | ||
352 | + inter_extent[0] = origin_extent[0] if origin_extent[0] > extent[0] else extent[0] | ||
353 | + inter_extent[1] = origin_extent[1] if origin_extent[1] > extent[1] else extent[1] | ||
354 | + inter_extent[2] = origin_extent[2] if origin_extent[2] < extent[2] else extent[2] | ||
355 | + inter_extent[3] = origin_extent[3] if origin_extent[3] < extent[3] else extent[3] | ||
356 | + | ||
357 | + # 网格偏移量 | ||
358 | + off_x = math.floor((inter_extent[0] - origin_extent[0]) / grid_x) | ||
359 | + off_y = math.floor((origin_extent[3] - inter_extent[3]) / grid_y) | ||
360 | + | ||
361 | + # 截取后网格个数 | ||
362 | + x_g = math.floor((inter_extent[2] - inter_extent[0]) / grid_x) | ||
363 | + y_g = math.floor((inter_extent[3] - inter_extent[1]) / grid_y) | ||
364 | + | ||
365 | + # 相对于出图的偏移量 | ||
366 | + | ||
367 | + # 出图的网格大小 | ||
368 | + out_grid_x = (extent[2] - extent[0]) / (width * 1.0) | ||
369 | + out_grid_y = (extent[3] - extent[1]) / (height * 1.0) | ||
370 | + | ||
371 | + out_off_x = int(math.ceil((inter_extent[0] - extent[0]) / out_grid_x)) | ||
372 | + out_off_y = int(math.ceil((extent[3] - inter_extent[3]) / out_grid_y)) | ||
373 | + | ||
374 | + out_x_g = int(math.floor((inter_extent[2] - inter_extent[0]) / out_grid_x)) | ||
375 | + out_y_g = int(math.floor((inter_extent[3] - inter_extent[1]) / out_grid_y)) | ||
376 | + | ||
377 | + # 相交部分在出图的哪个位置 | ||
378 | + | ||
379 | + overview_raster: ndarray = overview.ReadAsArray(off_x, off_y, x_g, y_g, out_x_g, | ||
380 | + out_y_g) | ||
381 | + | ||
382 | + dat = numpy.zeros((height, width), dtype=int) + 65536 | ||
383 | + dat[out_off_y:out_off_y + out_y_g, out_off_x:out_off_x + out_x_g] = overview_raster | ||
384 | + | ||
385 | + empty = dat | ||
386 | + | ||
387 | + pixel_array[:, :, ceng] = empty | ||
388 | + ceng += 1 | ||
389 | + return pixel_array | ||
390 | + | ||
391 | + | ||
392 | + def determin_intersect(self, extent1, extent2, mask): | ||
393 | + g1 = GeometryAdapter.bbox_2_polygon(extent1) | ||
394 | + g2 = GeometryAdapter.bbox_2_polygon(extent2) | ||
395 | + if g1.Intersect(g2): | ||
396 | + return g2.Intersect(mask) | ||
397 | + else: | ||
398 | + return False | ||
399 | + | ||
400 | + api_doc = { | ||
401 | + "tags": ["影像接口"], | ||
402 | + "parameters": [ | ||
403 | + {"name": "guid", | ||
404 | + "in": "formData", | ||
405 | + "type": "string"}, | ||
406 | + {"name": "tilematrix", | ||
407 | + "in": "formData", | ||
408 | + "type": "string"}, | ||
409 | + {"name": "tilerow", | ||
410 | + "in": "formData", | ||
411 | + "type": "string"}, | ||
412 | + {"name": "tilecol", | ||
413 | + "in": "formData", | ||
414 | + "type": "string"}, | ||
415 | + {"name": "format", | ||
416 | + "in": "formData", | ||
417 | + "type": "string"}, | ||
418 | + {"name": "quality", | ||
419 | + "in": "formData", | ||
420 | + "type": "string"} | ||
421 | + | ||
422 | + ], | ||
423 | + "responses": { | ||
424 | + 200: { | ||
425 | + "schema": { | ||
426 | + "properties": { | ||
427 | + } | ||
428 | + } | ||
429 | + } | ||
430 | + } | ||
431 | + } | ||
432 | + | ||
433 | +class MyThread(Thread): | ||
434 | + def __init__(self,func,args=()): | ||
435 | + super(MyThread,self).__init__() | ||
436 | + self.func = func | ||
437 | + self.args = args | ||
438 | + def run(self): | ||
439 | + self.result = self.func(*self.args) | ||
440 | + def get_result(self): | ||
441 | + try: | ||
442 | + return self.result | ||
443 | + except Exception: | ||
444 | + return None | ||
445 | + | ||
446 | + | ||
447 | + |
@@ -16,7 +16,7 @@ import cv2 | @@ -16,7 +16,7 @@ import cv2 | ||
16 | from app.modules.service.image.models import ImageService | 16 | from app.modules.service.image.models import ImageService |
17 | from app.util.component.ApiTemplate import ApiTemplate | 17 | from app.util.component.ApiTemplate import ApiTemplate |
18 | from app.util.component.GeometryAdapter import GeometryAdapter | 18 | from app.util.component.GeometryAdapter import GeometryAdapter |
19 | -from app.modules.service.image.util.ThriftConnect import ThriftConnect | 19 | +from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPool |
20 | from app.util.component.ParameterUtil import ParameterUtil | 20 | from app.util.component.ParameterUtil import ParameterUtil |
21 | import json | 21 | import json |
22 | from kazoo.client import KazooClient | 22 | from kazoo.client import KazooClient |
@@ -30,7 +30,7 @@ class Api(ApiTemplate): | @@ -30,7 +30,7 @@ class Api(ApiTemplate): | ||
30 | api_name = "WMS" | 30 | api_name = "WMS" |
31 | 31 | ||
32 | def process(self): | 32 | def process(self): |
33 | - from app import GLOBAL_DIC | 33 | + |
34 | 34 | ||
35 | result = {} | 35 | result = {} |
36 | parameter: dict = self.para | 36 | parameter: dict = self.para |
@@ -38,41 +38,21 @@ class Api(ApiTemplate): | @@ -38,41 +38,21 @@ class Api(ApiTemplate): | ||
38 | try: | 38 | try: |
39 | 39 | ||
40 | parameter = ParameterUtil.to_lower(parameter) | 40 | parameter = ParameterUtil.to_lower(parameter) |
41 | - guid = parameter.get("guid") | 41 | + self.guid = parameter.get("guid") |
42 | bbox = parameter.get("bbox") | 42 | bbox = parameter.get("bbox") |
43 | width = int(parameter.get("width")) if parameter.get("width") else 256 | 43 | width = int(parameter.get("width")) if parameter.get("width") else 256 |
44 | height = int(parameter.get("height")) if parameter.get("height") else 256 | 44 | height = int(parameter.get("height")) if parameter.get("height") else 256 |
45 | image_type = parameter.get("format") if parameter.get("format") else "image/png" | 45 | image_type = parameter.get("format") if parameter.get("format") else "image/png" |
46 | quality = int(parameter.get("quality")) if parameter.get("quality") else 30 | 46 | quality = int(parameter.get("quality")) if parameter.get("quality") else 30 |
47 | 47 | ||
48 | - | ||
49 | - #缓存起来 | ||
50 | - #缓存服务信息 | ||
51 | - image_service_info = GLOBAL_DIC.get(guid) | ||
52 | - if image_service_info is None: | ||
53 | - image_service:ImageService = ImageService.query.filter_by(guid=guid).one_or_none() | ||
54 | - images = image_service.images.all() | ||
55 | - GLOBAL_DIC[guid] = {"service":image_service,"images":images} | ||
56 | - image_service_info = GLOBAL_DIC[guid] | ||
57 | - else: | ||
58 | - image_service_info = GLOBAL_DIC[guid] | ||
59 | - | 48 | + image_service_info, zoo, servers = self.cache_data() |
60 | 49 | ||
61 | re = parameter.get("request") | 50 | re = parameter.get("request") |
62 | - | ||
63 | if re and re.__eq__("GetCapabilities"): | 51 | if re and re.__eq__("GetCapabilities"): |
64 | return self.get_capabilities(image_service_info["service"]) | 52 | return self.get_capabilities(image_service_info["service"]) |
65 | 53 | ||
66 | - zoo = GLOBAL_DIC.get("zookeeper") | ||
67 | - if zoo is None: | ||
68 | - zoo :KazooClient = KazooClient(hosts=configure.zookeeper, timeout=100) | ||
69 | - zoo.start() | ||
70 | - GLOBAL_DIC["zookeeper"] = zoo | ||
71 | - else : | ||
72 | - if not zoo.connected: | ||
73 | - zoo.start() | ||
74 | 54 | ||
75 | - bands = [1, 2, 3] | 55 | + # bands = [1, 2, 3] |
76 | 56 | ||
77 | extent = [float(x) for x in bbox.split(",")] | 57 | extent = [float(x) for x in bbox.split(",")] |
78 | 58 | ||
@@ -91,10 +71,14 @@ class Api(ApiTemplate): | @@ -91,10 +71,14 @@ class Api(ApiTemplate): | ||
91 | for image in intersect_image: | 71 | for image in intersect_image: |
92 | #该影像的服务器,随机选取一个 | 72 | #该影像的服务器,随机选取一个 |
93 | image_servers = image.server.split(",") | 73 | image_servers = image.server.split(",") |
94 | - indx = int(random.random()*len(image_servers)) | ||
95 | - image_server = image_servers[indx] | ||
96 | - | ||
97 | - thread: MyThread = MyThread(self.get_data, args=(zoo,image_server,image,extent,bands,height,width)) | 74 | + image_servers = [ser for ser in image_servers if ser in servers] |
75 | + if len(image_servers)>0: | ||
76 | + indx = int(random.random() * len(image_servers)) | ||
77 | + image_server = image_servers[indx] | ||
78 | + else: | ||
79 | + image_server = "None" | ||
80 | + bands = json.loads(image.band_view) | ||
81 | + thread: MyThread = MyThread(self.get_data, args=(image_server,image,extent,bands,height,width)) | ||
98 | thread.start() | 82 | thread.start() |
99 | thread_list.append(thread) | 83 | thread_list.append(thread) |
100 | 84 | ||
@@ -124,9 +108,15 @@ class Api(ApiTemplate): | @@ -124,9 +108,15 @@ class Api(ApiTemplate): | ||
124 | # 该影像的服务器,随机选取一个 | 108 | # 该影像的服务器,随机选取一个 |
125 | image = intersect_image[0] | 109 | image = intersect_image[0] |
126 | image_servers = image.server.split(",") | 110 | image_servers = image.server.split(",") |
127 | - indx = int(random.random() * len(image_servers)) | ||
128 | - image_server = image_servers[indx] | ||
129 | - pixel_array_t = self.get_data(zoo,image_server,image,extent,bands,height,width) | 111 | + image_servers = [ser for ser in image_servers if ser in servers] |
112 | + if len(image_servers) > 0: | ||
113 | + indx = int(random.random() * len(image_servers)) | ||
114 | + image_server = image_servers[indx] | ||
115 | + else: | ||
116 | + image_server = "None" | ||
117 | + | ||
118 | + bands = json.loads(image.band_view) | ||
119 | + pixel_array_t = self.get_data(image_server,image,extent,bands,height,width) | ||
130 | pixel_array = numpy.zeros((height, width, 3), dtype=int) | 120 | pixel_array = numpy.zeros((height, width, 3), dtype=int) |
131 | for ii in [0, 1, 2]: | 121 | for ii in [0, 1, 2]: |
132 | # opencv 颜色排序为GBR | 122 | # opencv 颜色排序为GBR |
@@ -148,6 +138,55 @@ class Api(ApiTemplate): | @@ -148,6 +138,55 @@ class Api(ApiTemplate): | ||
148 | result["message"] = e.__str__() | 138 | result["message"] = e.__str__() |
149 | return result | 139 | return result |
150 | 140 | ||
141 | + | ||
142 | + def cache_data(self): | ||
143 | + | ||
144 | + from app import GLOBAL_DIC | ||
145 | + | ||
146 | + # 缓存zookeeper | ||
147 | + zoo = GLOBAL_DIC.get("zookeeper") | ||
148 | + if zoo is None: | ||
149 | + zoo: KazooClient = KazooClient(hosts=configure.zookeeper, timeout=100) | ||
150 | + zoo.start() | ||
151 | + GLOBAL_DIC["zookeeper"] = zoo | ||
152 | + else: | ||
153 | + if not zoo.connected: | ||
154 | + zoo.start() | ||
155 | + | ||
156 | + # 缓存数据服务器 | ||
157 | + servers = GLOBAL_DIC.get("servers") | ||
158 | + if servers is None: | ||
159 | + servers = zoo.get_children("/rpc") | ||
160 | + servers.append("本地服务器") | ||
161 | + GLOBAL_DIC["servers"] = servers | ||
162 | + GLOBAL_DIC["servers_updatetime"] = time.time() | ||
163 | + else: | ||
164 | + servers = GLOBAL_DIC.get("servers") | ||
165 | + | ||
166 | + # 更新缓存 | ||
167 | + if time.time() - GLOBAL_DIC["servers_updatetime"] > 10: | ||
168 | + servers = zoo.get_children("/rpc") | ||
169 | + servers.append("本地服务器") | ||
170 | + GLOBAL_DIC["servers"] = servers | ||
171 | + GLOBAL_DIC["servers_updatetime"] = time.time() | ||
172 | + | ||
173 | + | ||
174 | + # 缓存服务信息 | ||
175 | + image_service_info = GLOBAL_DIC.get(self.guid) | ||
176 | + if image_service_info is None or time.time() - GLOBAL_DIC.get("service_updatetime") > 20: | ||
177 | + image_service: ImageService = ImageService.query.filter_by(guid=self.guid).one_or_none() | ||
178 | + images = image_service.images.all() | ||
179 | + GLOBAL_DIC[self.guid] = {"service": image_service, "images": images} | ||
180 | + GLOBAL_DIC["service_updatetime"] = time.time() | ||
181 | + image_service_info = GLOBAL_DIC[self.guid] | ||
182 | + | ||
183 | + else: | ||
184 | + image_service_info = GLOBAL_DIC[self.guid] | ||
185 | + | ||
186 | + return image_service_info,zoo,servers | ||
187 | + | ||
188 | + | ||
189 | + | ||
151 | def determine_level(self,xysize,origin_extent,extent,max_level): | 190 | def determine_level(self,xysize,origin_extent,extent,max_level): |
152 | ''' | 191 | ''' |
153 | 根据范围判断调用金字塔的哪一层 | 192 | 根据范围判断调用金字塔的哪一层 |
@@ -182,17 +221,14 @@ class Api(ApiTemplate): | @@ -182,17 +221,14 @@ class Api(ApiTemplate): | ||
182 | image_out = buf.tobytes() | 221 | image_out = buf.tobytes() |
183 | return image_out | 222 | return image_out |
184 | 223 | ||
185 | - def get_data(self,zoo,image_server,image,extent,bands,height,width): | 224 | + def get_data(self,image_server, image, extent, bands, height, width): |
186 | 225 | ||
187 | if image_server.__eq__("本地服务器"): | 226 | if image_server.__eq__("本地服务器"): |
188 | data = self.get_local_wms_data(image, extent, bands, height, width) | 227 | data = self.get_local_wms_data(image, extent, bands, height, width) |
228 | + elif image_server.__eq__("None"): | ||
229 | + data = numpy.zeros((height, width, 3), dtype=int) + 65536 | ||
189 | else: | 230 | else: |
190 | - ser = image_server | ||
191 | - if zoo.exists("/rpc/{}".format(ser)): | ||
192 | - data = self.get_remote_wms_data(image_server,image, extent, bands, height, width) | ||
193 | - else: | ||
194 | - data = numpy.zeros((height, width, 3), dtype=int) + 65536 | ||
195 | - | 231 | + data = self.get_remote_wms_data(image_server,image, extent, bands, height, width) |
196 | return data | 232 | return data |
197 | 233 | ||
198 | 234 | ||
@@ -206,7 +242,6 @@ class Api(ApiTemplate): | @@ -206,7 +242,6 @@ class Api(ApiTemplate): | ||
206 | :return: | 242 | :return: |
207 | ''' | 243 | ''' |
208 | thrift_connect = ThriftConnect(image_server) | 244 | thrift_connect = ThriftConnect(image_server) |
209 | - t1 = time.time() | ||
210 | image_extent = image.extent | 245 | image_extent = image.extent |
211 | 246 | ||
212 | data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands,width,height) | 247 | data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands,width,height) |
@@ -219,6 +254,33 @@ class Api(ApiTemplate): | @@ -219,6 +254,33 @@ class Api(ApiTemplate): | ||
219 | 254 | ||
220 | return data | 255 | return data |
221 | 256 | ||
257 | + def get_remote_wms_data_client(self,image_server,image, extent, bands, height, width): | ||
258 | + ''' | ||
259 | + 通过RPC获取远程数据 | ||
260 | + :param image: | ||
261 | + :param extent: | ||
262 | + :param bands: | ||
263 | + :return: | ||
264 | + ''' | ||
265 | + from app import GLOBAL_DIC | ||
266 | + | ||
267 | + # 缓存thrift_pool | ||
268 | + thrift_pool = GLOBAL_DIC.get(image_server) | ||
269 | + if thrift_pool is None: | ||
270 | + thrift_pool = ThriftPool(image_server) | ||
271 | + GLOBAL_DIC["image_server"] = thrift_pool | ||
272 | + client = thrift_pool.get_client() | ||
273 | + | ||
274 | + image_extent = image.extent | ||
275 | + | ||
276 | + data = client.getData(image.path, extent, json.loads(image_extent), bands, width, height) | ||
277 | + | ||
278 | + data = gzip.decompress(data) | ||
279 | + data = numpy.frombuffer(data, dtype='int64') | ||
280 | + data = data.reshape((height, width, 3)) | ||
281 | + | ||
282 | + return data | ||
283 | + | ||
222 | def get_local_wms_data(self,image,extent,bands,height,width): | 284 | def get_local_wms_data(self,image,extent,bands,height,width): |
223 | ''' | 285 | ''' |
224 | 获取本地数据 | 286 | 获取本地数据 |
@@ -236,7 +298,7 @@ class Api(ApiTemplate): | @@ -236,7 +298,7 @@ class Api(ApiTemplate): | ||
236 | # 自决定金字塔等级 | 298 | # 自决定金字塔等级 |
237 | xysize = [img.RasterXSize, img.RasterYSize] | 299 | xysize = [img.RasterXSize, img.RasterYSize] |
238 | 300 | ||
239 | - origin_extent = image.extent | 301 | + origin_extent = json.loads(image.extent) |
240 | band_data: Band = img.GetRasterBand(band) | 302 | band_data: Band = img.GetRasterBand(band) |
241 | 303 | ||
242 | 304 | ||
@@ -244,8 +306,7 @@ class Api(ApiTemplate): | @@ -244,8 +306,7 @@ class Api(ApiTemplate): | ||
244 | max_level = band_data.GetOverviewCount() | 306 | max_level = band_data.GetOverviewCount() |
245 | 307 | ||
246 | # 超出空间范围 | 308 | # 超出空间范围 |
247 | - if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[ | ||
248 | - 3] or extent[3] < origin_extent[1]: | 309 | + if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[3] or extent[3] < origin_extent[1]: |
249 | empty = numpy.zeros((height,width), dtype=int) + 65536 | 310 | empty = numpy.zeros((height,width), dtype=int) + 65536 |
250 | # 空间范围相交 | 311 | # 空间范围相交 |
251 | else: | 312 | else: |
@@ -324,10 +385,12 @@ class Api(ApiTemplate): | @@ -324,10 +385,12 @@ class Api(ApiTemplate): | ||
324 | ceng += 1 | 385 | ceng += 1 |
325 | return pixel_array | 386 | return pixel_array |
326 | 387 | ||
327 | - def determin_intersect(self,extent1,extent2): | ||
328 | - g1 = GeometryAdapter.bbox_2_polygon(extent1) | ||
329 | - g2 = GeometryAdapter.bbox_2_polygon(extent2) | ||
330 | - return g1.Intersect(g2) | 388 | + def determin_intersect(self, extent1, extent2): |
389 | + if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ | ||
390 | + 3] or extent2[3] < extent1[1]: | ||
391 | + return False | ||
392 | + else: | ||
393 | + return True | ||
331 | 394 | ||
332 | def get_capabilities(self,image_service:ImageService): | 395 | def get_capabilities(self,image_service:ImageService): |
333 | 396 |
@@ -25,6 +25,7 @@ class Image(db.Model): | @@ -25,6 +25,7 @@ class Image(db.Model): | ||
25 | null_value = Column(Integer) | 25 | null_value = Column(Integer) |
26 | available = Column(Integer)#影像是否可用,不可用可能在创建金字塔中 | 26 | available = Column(Integer)#影像是否可用,不可用可能在创建金字塔中 |
27 | band_count = Column(Integer) | 27 | band_count = Column(Integer) |
28 | + band_view = Column(String) | ||
28 | path = Column(String) | 29 | path = Column(String) |
29 | server = Column(String) | 30 | server = Column(String) |
30 | 31 |
@@ -3,13 +3,13 @@ | @@ -3,13 +3,13 @@ | ||
3 | #createtime: 2021/9/26 | 3 | #createtime: 2021/9/26 |
4 | #email: nheweijun@sina.com | 4 | #email: nheweijun@sina.com |
5 | 5 | ||
6 | -from app.modules.service.image.tutorial.ttypes import RasterData | 6 | +from app.modules.service.image.tutorial2.ttypes import RasterData |
7 | 7 | ||
8 | from thrift.transport import TSocket | 8 | from thrift.transport import TSocket |
9 | from thrift.transport import TTransport | 9 | from thrift.transport import TTransport |
10 | from thrift.protocol import TBinaryProtocol | 10 | from thrift.protocol import TBinaryProtocol |
11 | from app.modules.service.image.ImageDataService import ImageDataService | 11 | from app.modules.service.image.ImageDataService import ImageDataService |
12 | -from app.modules.service.image.tutorial import Calculator | 12 | +from app.modules.service.image.tutorial2 import Calculator |
13 | 13 | ||
14 | from struct import Struct | 14 | from struct import Struct |
15 | 15 |
@@ -16,15 +16,15 @@ else: | @@ -16,15 +16,15 @@ else: | ||
16 | from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient | 16 | from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient |
17 | from thrift.protocol.TBinaryProtocol import TBinaryProtocol | 17 | from thrift.protocol.TBinaryProtocol import TBinaryProtocol |
18 | 18 | ||
19 | -from . import Calculator | ||
20 | -from .ttypes import * | 19 | +from tutorial import Calculator |
20 | +from tutorial.ttypes import * | ||
21 | 21 | ||
22 | if len(sys.argv) <= 1 or sys.argv[1] == '--help': | 22 | if len(sys.argv) <= 1 or sys.argv[1] == '--help': |
23 | print('') | 23 | print('') |
24 | print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] [-novalidate] [-ca_certs certs] [-keyfile keyfile] [-certfile certfile] function [arg1 [arg2...]]') | 24 | print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] [-novalidate] [-ca_certs certs] [-keyfile keyfile] [-certfile certfile] function [arg1 [arg2...]]') |
25 | print('') | 25 | print('') |
26 | print('Functions:') | 26 | print('Functions:') |
27 | - print(' RasterData getData(string path, queryRange, originRange, bands, i32 width, i32 height)') | 27 | + print(' getData(string path, queryRange, originRange, bands, i32 width, i32 height)') |
28 | print(' Raster getInfo(string path)') | 28 | print(' Raster getInfo(string path)') |
29 | print(' bool buildOverview(string path)') | 29 | print(' bool buildOverview(string path)') |
30 | print(' getImageList(string path)') | 30 | print(' getImageList(string path)') |
@@ -505,9 +505,18 @@ class getData_result(object): | @@ -505,9 +505,18 @@ class getData_result(object): | ||
505 | if ftype == TType.STOP: | 505 | if ftype == TType.STOP: |
506 | break | 506 | break |
507 | if fid == 0: | 507 | if fid == 0: |
508 | - if ftype == TType.STRUCT: | ||
509 | - self.success = RasterData() | ||
510 | - self.success.read(iprot) | 508 | + if ftype == TType.LIST: |
509 | + self.success = [] | ||
510 | + (_etype59, _size56) = iprot.readListBegin() | ||
511 | + for _i60 in range(_size56): | ||
512 | + _elem61 = [] | ||
513 | + (_etype65, _size62) = iprot.readListBegin() | ||
514 | + for _i66 in range(_size62): | ||
515 | + _elem67 = iprot.readI16() | ||
516 | + _elem61.append(_elem67) | ||
517 | + iprot.readListEnd() | ||
518 | + self.success.append(_elem61) | ||
519 | + iprot.readListEnd() | ||
511 | else: | 520 | else: |
512 | iprot.skip(ftype) | 521 | iprot.skip(ftype) |
513 | else: | 522 | else: |
@@ -521,8 +530,14 @@ class getData_result(object): | @@ -521,8 +530,14 @@ class getData_result(object): | ||
521 | return | 530 | return |
522 | oprot.writeStructBegin('getData_result') | 531 | oprot.writeStructBegin('getData_result') |
523 | if self.success is not None: | 532 | if self.success is not None: |
524 | - oprot.writeFieldBegin('success', TType.STRUCT, 0) | ||
525 | - self.success.write(oprot) | 533 | + oprot.writeFieldBegin('success', TType.LIST, 0) |
534 | + oprot.writeListBegin(TType.LIST, len(self.success)) | ||
535 | + for iter68 in self.success: | ||
536 | + oprot.writeListBegin(TType.I16, len(iter68)) | ||
537 | + for iter69 in iter68: | ||
538 | + oprot.writeI16(iter69) | ||
539 | + oprot.writeListEnd() | ||
540 | + oprot.writeListEnd() | ||
526 | oprot.writeFieldEnd() | 541 | oprot.writeFieldEnd() |
527 | oprot.writeFieldStop() | 542 | oprot.writeFieldStop() |
528 | oprot.writeStructEnd() | 543 | oprot.writeStructEnd() |
@@ -542,7 +557,7 @@ class getData_result(object): | @@ -542,7 +557,7 @@ class getData_result(object): | ||
542 | return not (self == other) | 557 | return not (self == other) |
543 | all_structs.append(getData_result) | 558 | all_structs.append(getData_result) |
544 | getData_result.thrift_spec = ( | 559 | getData_result.thrift_spec = ( |
545 | - (0, TType.STRUCT, 'success', [RasterData, None], None, ), # 0 | 560 | + (0, TType.LIST, 'success', (TType.LIST, (TType.I16, None, False), False), None, ), # 0 |
546 | ) | 561 | ) |
547 | 562 | ||
548 | 563 | ||
@@ -878,11 +893,11 @@ class getImageList_result(object): | @@ -878,11 +893,11 @@ class getImageList_result(object): | ||
878 | if fid == 0: | 893 | if fid == 0: |
879 | if ftype == TType.LIST: | 894 | if ftype == TType.LIST: |
880 | self.success = [] | 895 | self.success = [] |
881 | - (_etype59, _size56) = iprot.readListBegin() | ||
882 | - for _i60 in range(_size56): | ||
883 | - _elem61 = Image() | ||
884 | - _elem61.read(iprot) | ||
885 | - self.success.append(_elem61) | 896 | + (_etype73, _size70) = iprot.readListBegin() |
897 | + for _i74 in range(_size70): | ||
898 | + _elem75 = Image() | ||
899 | + _elem75.read(iprot) | ||
900 | + self.success.append(_elem75) | ||
886 | iprot.readListEnd() | 901 | iprot.readListEnd() |
887 | else: | 902 | else: |
888 | iprot.skip(ftype) | 903 | iprot.skip(ftype) |
@@ -899,8 +914,8 @@ class getImageList_result(object): | @@ -899,8 +914,8 @@ class getImageList_result(object): | ||
899 | if self.success is not None: | 914 | if self.success is not None: |
900 | oprot.writeFieldBegin('success', TType.LIST, 0) | 915 | oprot.writeFieldBegin('success', TType.LIST, 0) |
901 | oprot.writeListBegin(TType.STRUCT, len(self.success)) | 916 | oprot.writeListBegin(TType.STRUCT, len(self.success)) |
902 | - for iter62 in self.success: | ||
903 | - iter62.write(oprot) | 917 | + for iter76 in self.success: |
918 | + iter76.write(oprot) | ||
904 | oprot.writeListEnd() | 919 | oprot.writeListEnd() |
905 | oprot.writeFieldEnd() | 920 | oprot.writeFieldEnd() |
906 | oprot.writeFieldStop() | 921 | oprot.writeFieldStop() |
@@ -9,21 +9,55 @@ | @@ -9,21 +9,55 @@ | ||
9 | from thrift.transport import TSocket | 9 | from thrift.transport import TSocket |
10 | from thrift.transport import TTransport | 10 | from thrift.transport import TTransport |
11 | from thrift.protocol import TBinaryProtocol | 11 | from thrift.protocol import TBinaryProtocol |
12 | + | ||
13 | +from app.modules.service.image.tutorial import Calculator | ||
12 | from app.modules.service.image.ImageDataService import ImageDataService | 14 | from app.modules.service.image.ImageDataService import ImageDataService |
13 | -from . import Calculator | 15 | +import time |
16 | + | ||
17 | +def test1(): | ||
18 | + | ||
19 | + host = "172.26.60.100" | ||
20 | + port = 8850 | ||
21 | + | ||
22 | + transport: TSocket = TSocket.TSocket(host, port) | ||
23 | + transport = TTransport.TBufferedTransport(transport) | ||
24 | + protocol = TBinaryProtocol.TBinaryProtocol(transport) | ||
25 | + client = Calculator.Client(protocol) | ||
26 | + | ||
27 | + | ||
28 | + transport.open() | ||
29 | + import sys | ||
30 | + test = client.getData("江南_01.tif",[1340.27, -1911.31, 4351.79, 5410.6],[1340.27, -1911.31, 4351.79, 5410.6],[3,2,1],768,768) | ||
31 | + print(sys.getsizeof(test[1])) | ||
32 | + # print(test) | ||
33 | + | ||
34 | +def test2(): | ||
35 | + host = "172.26.60.100" | ||
36 | + port = 9090 | ||
14 | 37 | ||
15 | -from struct import Struct | 38 | + transport: TSocket = TSocket.TSocket(host, port) |
39 | + transport = TTransport.TBufferedTransport(transport) | ||
40 | + protocol = TBinaryProtocol.TBinaryProtocol(transport) | ||
41 | + client = ImageDataService.Client(protocol) | ||
16 | 42 | ||
17 | -host = 1 | ||
18 | -port = 9090 | ||
19 | -transport: TSocket = TSocket.TSocket(host, port) | ||
20 | -transport = TTransport.TBufferedTransport(transport) | ||
21 | -protocol = TBinaryProtocol.TBinaryProtocol(transport) | 43 | + transport.open() |
22 | 44 | ||
23 | -client = Calculator.Client(protocol) | 45 | + test = client.getData("/usr/src/data/江南_01.tif", [1340.27, -1911.31, 4351.79, 5410.6], [1340.27, -1911.31, 4351.79, 5410.6], |
46 | + [1,2,3], 768, 768) | ||
24 | 47 | ||
48 | + import gzip,numpy | ||
49 | + data = gzip.decompress(test) | ||
50 | + # data = numpy.frombuffer(data, dtype='int64') | ||
51 | + # data = data.reshape((768, 768, 3)) | ||
25 | 52 | ||
26 | -transport.open() | 53 | + import sys |
54 | + print(sys.getsizeof(data)) | ||
55 | + # print(test) | ||
27 | 56 | ||
28 | -test = client.getData("江南_01.tif",[1340.27, -1911.31, 4351.79, 5410.6],[1340.27, -1911.31, 4351.79, 5410.6],[3,2,1],768,768) | ||
29 | -print(type(test)) | ||
57 | +if __name__ == '__main__': | ||
58 | + t1 = time.time() | ||
59 | + # test1() | ||
60 | + print(time.time()-t1) | ||
61 | + t2 = time.time() | ||
62 | + test2() | ||
63 | + print(time.time()-t2) |
@@ -19,14 +19,64 @@ class ThriftConnect: | @@ -19,14 +19,64 @@ class ThriftConnect: | ||
19 | def __init__(self,data_server): | 19 | def __init__(self,data_server): |
20 | host = data_server.split(":")[0] | 20 | host = data_server.split(":")[0] |
21 | port = int(data_server.split(":")[1]) | 21 | port = int(data_server.split(":")[1]) |
22 | + socket: TSocket = TSocket.TSocket(host, port) | ||
23 | + self.transport = TTransport.TBufferedTransport(socket) | ||
24 | + protocol = TBinaryProtocol.TBinaryProtocol(self.transport) | ||
25 | + self.client = ImageDataService.Client(protocol) | ||
26 | + self.transport.open() | ||
27 | + | ||
28 | + def close(self): | ||
29 | + self.transport.close() | ||
30 | + | ||
31 | +class ThriftConnectCpp: | ||
32 | + ''' | ||
33 | + thrift连接类 | ||
34 | + ''' | ||
35 | + | ||
36 | + client = None | ||
37 | + transport = None | ||
38 | + | ||
39 | + def __init__(self,data_server): | ||
40 | + host = data_server.split(":")[0] | ||
41 | + port = int(data_server.split(":")[1]) | ||
22 | self.transport: TSocket = TSocket.TSocket(host, port) | 42 | self.transport: TSocket = TSocket.TSocket(host, port) |
23 | self.transport = TTransport.TBufferedTransport(self.transport) | 43 | self.transport = TTransport.TBufferedTransport(self.transport) |
24 | protocol = TBinaryProtocol.TBinaryProtocol(self.transport) | 44 | protocol = TBinaryProtocol.TBinaryProtocol(self.transport) |
25 | - self.client = ImageDataService.Client(protocol) | 45 | + # self.client = ImageDataService.Client(protocol) |
26 | self.transport.open() | 46 | self.transport.open() |
27 | 47 | ||
28 | def close(self): | 48 | def close(self): |
29 | self.transport.close() | 49 | self.transport.close() |
30 | 50 | ||
31 | class ThriftPool: | 51 | class ThriftPool: |
32 | - pass | ||
52 | + ''' | ||
53 | + thrift线程池 | ||
54 | + ''' | ||
55 | + clients = [] | ||
56 | + transports = [] | ||
57 | + host = None | ||
58 | + port = None | ||
59 | + index = -1 | ||
60 | + | ||
61 | + def __init__(self,data_server): | ||
62 | + self.host = data_server.split(":")[0] | ||
63 | + self.port = int(data_server.split(":")[1]) | ||
64 | + | ||
65 | + def get_client(self): | ||
66 | + if len(self.clients) < 20: | ||
67 | + socket: TSocket = TSocket.TSocket(self.host, self.port) | ||
68 | + transport = TTransport.TBufferedTransport(socket) | ||
69 | + protocol = TBinaryProtocol.TBinaryProtocol(transport) | ||
70 | + client = ImageDataService.Client(protocol) | ||
71 | + self.clients.append(client) | ||
72 | + self.transports.append(transport) | ||
73 | + return client,transport | ||
74 | + else: | ||
75 | + self.index += 1 | ||
76 | + if self.index == 20: | ||
77 | + self.index = 0 | ||
78 | + return self.clients[self.index],self.transports[self.index] | ||
79 | + | ||
80 | + | ||
81 | + def close(self): | ||
82 | + pass |
@@ -17,6 +17,7 @@ from . import scheme_resolve | @@ -17,6 +17,7 @@ from . import scheme_resolve | ||
17 | class SchemeManager(BlueprintApi): | 17 | class SchemeManager(BlueprintApi): |
18 | 18 | ||
19 | bp = Blueprint("Scheme", __name__, url_prefix="/API/Service/Scheme") | 19 | bp = Blueprint("Scheme", __name__, url_prefix="/API/Service/Scheme") |
20 | + service_type = [] | ||
20 | 21 | ||
21 | @staticmethod | 22 | @staticmethod |
22 | @bp.route('/Create', methods=['POST']) | 23 | @bp.route('/Create', methods=['POST']) |
@@ -24,6 +24,15 @@ class Api(ApiTemplate): | @@ -24,6 +24,15 @@ class Api(ApiTemplate): | ||
24 | # extent = [float(x) for x in data.get("extent").split(",")] if data.get("extent") else [0,0,0,0] | 24 | # extent = [float(x) for x in data.get("extent").split(",")] if data.get("extent") else [0,0,0,0] |
25 | # top_left = [float(x) for x in data.get("top_left").split(",")] if data.get("top_left") else [0, 0] | 25 | # top_left = [float(x) for x in data.get("top_left").split(",")] if data.get("top_left") else [0, 0] |
26 | 26 | ||
27 | + paramenter = {} | ||
28 | + for l_dict in json.loads(data.get("levels")): | ||
29 | + paramenter[str(l_dict["level"])] = {"resolution":l_dict["resolution"],"scale":l_dict["scale"]} | ||
30 | + paramenter["cols"] = int(data.get("cols")) | ||
31 | + paramenter["rows"] = int(data.get("rows")) | ||
32 | + paramenter["dpi"] = int(data.get("dpi")) | ||
33 | + paramenter["wkt"] = data.get("crs_wkt") | ||
34 | + paramenter["x"] = eval(data.get("top_left").split(",")[0]) | ||
35 | + paramenter["y"] = eval(data.get("top_left").split(",")[1]) | ||
27 | 36 | ||
28 | 37 | ||
29 | guid = uuid.uuid1().__str__() | 38 | guid = uuid.uuid1().__str__() |
@@ -46,7 +55,7 @@ class Api(ApiTemplate): | @@ -46,7 +55,7 @@ class Api(ApiTemplate): | ||
46 | rows = int(data.get("rows")), | 55 | rows = int(data.get("rows")), |
47 | cols = int(data.get("cols")), | 56 | cols = int(data.get("cols")), |
48 | update_time = datetime.datetime.now(), | 57 | update_time = datetime.datetime.now(), |
49 | - parameter=json.dumps(json.loads(data.get("parameter"))) | 58 | + parameter=json.dumps(paramenter) |
50 | ) | 59 | ) |
51 | 60 | ||
52 | db.session.add(tile_scheme) | 61 | db.session.add(tile_scheme) |
@@ -92,9 +101,9 @@ class Api(ApiTemplate): | @@ -92,9 +101,9 @@ class Api(ApiTemplate): | ||
92 | {"name": "levels", | 101 | {"name": "levels", |
93 | "in": "formData", | 102 | "in": "formData", |
94 | "type": "string"}, | 103 | "type": "string"}, |
95 | - {"name": "parameter", | ||
96 | - "in": "formData", | ||
97 | - "type": "string"}, | 104 | + # {"name": "parameter", |
105 | + # "in": "formData", | ||
106 | + # "type": "string"}, | ||
98 | 107 | ||
99 | ], | 108 | ], |
100 | "responses": { | 109 | "responses": { |
@@ -32,7 +32,7 @@ class Api(ApiTemplate): | @@ -32,7 +32,7 @@ class Api(ApiTemplate): | ||
32 | "rows": scheme.parameter.get("rows"), | 32 | "rows": scheme.parameter.get("rows"), |
33 | "cols": scheme.parameter.get("cols"), | 33 | "cols": scheme.parameter.get("cols"), |
34 | "levels": scheme.levels, | 34 | "levels": scheme.levels, |
35 | - "parameter":scheme.parameter | 35 | + # "parameter":scheme.parameter |
36 | } | 36 | } |
37 | 37 | ||
38 | res["data"] = data | 38 | res["data"] = data |
@@ -34,6 +34,128 @@ class Api(ApiTemplate): | @@ -34,6 +34,128 @@ class Api(ApiTemplate): | ||
34 | api_doc = { | 34 | api_doc = { |
35 | "tags": ["服务接口"], | 35 | "tags": ["服务接口"], |
36 | "parameters": [ | 36 | "parameters": [ |
37 | + | ||
38 | + | ||
39 | + {"name": "name", | ||
40 | + "in": "formData", | ||
41 | + "type": "string", | ||
42 | + "required": "true", | ||
43 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
44 | + {"name": "alias", | ||
45 | + "in": "formData", | ||
46 | + "type": "string", | ||
47 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
48 | + {"name": "description", | ||
49 | + "in": "formData", | ||
50 | + "type": "string", | ||
51 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
52 | + | ||
53 | + {"name": "catalog_guid", | ||
54 | + "in": "formData", | ||
55 | + "type": "string", | ||
56 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
57 | + | ||
58 | + # 影像参数 | ||
59 | + {"name": "guids", | ||
60 | + "in": "formData", | ||
61 | + "type": "string", | ||
62 | + "description": "[影像WMS,影像WMTS]影像guids,以英文逗号相隔"}, | ||
63 | + {"name": "scheme_guid", | ||
64 | + "in": "formData", | ||
65 | + "type": "string", | ||
66 | + "description": "[WMTS,影像WMTS]切片方案"}, | ||
67 | + | ||
68 | + # WMTS参数 | ||
69 | + {"name": "overview", | ||
70 | + "in": "formData", | ||
71 | + "type": "string", | ||
72 | + "description": "[WMTS]缩略图"}, | ||
73 | + {"name": "wmts_type", | ||
74 | + "in": "formData", | ||
75 | + "type": "string", | ||
76 | + "description": "[WMTS]wmts_type"}, | ||
77 | + {"name": "vendor", | ||
78 | + "in": "formData", | ||
79 | + "type": "string", | ||
80 | + "description": "[WMTS]厂商"}, | ||
81 | + {"name": "crs", | ||
82 | + "in": "formData", | ||
83 | + "type": "string", | ||
84 | + "description": "[WMTS]坐标系"}, | ||
85 | + {"name": "datasource", | ||
86 | + "in": "formData", | ||
87 | + "type": "string", | ||
88 | + "description": "[WMTS]数据路径"}, | ||
89 | + {"name": "layer_name", | ||
90 | + "in": "formData", | ||
91 | + "type": "string", | ||
92 | + "description": "[WMTS]图层名"}, | ||
93 | + {"name": "layer_alias", | ||
94 | + "in": "formData", | ||
95 | + "type": "string", | ||
96 | + "description": "[WMTS]图层别名"}, | ||
97 | + {"name": "layer_title", | ||
98 | + "in": "formData", | ||
99 | + "type": "string", | ||
100 | + "description": "[WMTS]图层标题"}, | ||
101 | + {"name": "layer_style", | ||
102 | + "in": "formData", | ||
103 | + "type": "string", | ||
104 | + "description": "[WMTS,WMS]图层样式"}, | ||
105 | + {"name": "layer_format", | ||
106 | + "in": "formData", | ||
107 | + "type": "string", | ||
108 | + "description": "[WMTS]图层format"}, | ||
109 | + {"name": "layer_extent", | ||
110 | + "in": "formData", | ||
111 | + "type": "string", | ||
112 | + "description": "[WMTS]图层范围"}, | ||
113 | + {"name": "layer_description", | ||
114 | + "in": "formData", | ||
115 | + "type": "string", | ||
116 | + "description": "[WMTS]图层描述"}, | ||
117 | + | ||
118 | + # WMS参数 | ||
119 | + {"name": "status", | ||
120 | + "in": "formData", | ||
121 | + "type": "string", | ||
122 | + "description": "[WMS]status"}, | ||
123 | + {"name": "username", | ||
124 | + "in": "formData", | ||
125 | + "type": "string", | ||
126 | + "description": "[WMS]username"}, | ||
127 | + {"name": "readonly", | ||
128 | + "in": "formData", | ||
129 | + "type": "string", | ||
130 | + "description": "[WMS]readonly"}, | ||
131 | + {"name": "sid", | ||
132 | + "in": "formData", | ||
133 | + "type": "string", | ||
134 | + "description": "[WMS]sid"}, | ||
135 | + {"name": "stype", | ||
136 | + "in": "formData", | ||
137 | + "type": "string", | ||
138 | + "description": "[WMS]stype"}, | ||
139 | + {"name": "ssupply", | ||
140 | + "in": "formData", | ||
141 | + "type": "string", | ||
142 | + "description": "[WMS]ssupply"}, | ||
143 | + {"name": "sctime", | ||
144 | + "in": "formData", | ||
145 | + "type": "string", | ||
146 | + "description": "[WMS]sctime"}, | ||
147 | + {"name": "company", | ||
148 | + "in": "formData", | ||
149 | + "type": "string", | ||
150 | + "description": "[WMS]company"}, | ||
151 | + {"name": "abstract", | ||
152 | + "in": "formData", | ||
153 | + "type": "string", | ||
154 | + "description": "[WMS]abstract"}, | ||
155 | + {"name": "thumbnail", | ||
156 | + "in": "formData", | ||
157 | + "type": "string", | ||
158 | + "description": "[WMS]thumbnail"}, | ||
37 | ], | 159 | ], |
38 | "responses": { | 160 | "responses": { |
39 | 200: { | 161 | 200: { |
@@ -26,9 +26,14 @@ class Api(ApiTemplate): | @@ -26,9 +26,14 @@ class Api(ApiTemplate): | ||
26 | name = self.para.get("name") | 26 | name = self.para.get("name") |
27 | type = self.para.get("type") | 27 | type = self.para.get("type") |
28 | 28 | ||
29 | + catalog_guid = self.para.get("catalog_guid") | ||
30 | + | ||
29 | services = Service.query | 31 | services = Service.query |
30 | if type: | 32 | if type: |
31 | services = services.filter_by(type=type) | 33 | services = services.filter_by(type=type) |
34 | + | ||
35 | + if catalog_guid: | ||
36 | + services = services.filter_by(catalog_guid=catalog_guid) | ||
32 | # 并集 | 37 | # 并集 |
33 | if alias and name: | 38 | if alias and name: |
34 | services = services.filter( | 39 | services = services.filter( |
@@ -72,7 +77,12 @@ class Api(ApiTemplate): | @@ -72,7 +77,12 @@ class Api(ApiTemplate): | ||
72 | {"name": "type", | 77 | {"name": "type", |
73 | "in": "formData", | 78 | "in": "formData", |
74 | "type": "string", | 79 | "type": "string", |
75 | - "description": "服务类型"}, | 80 | + "description": "服务类型", |
81 | + "enum":["WMTS","TMS","WMS/WFS","ImageWMTS","ImageWMS"]}, | ||
82 | + {"name": "catalog_guid", | ||
83 | + "in": "formData", | ||
84 | + "type": "string", | ||
85 | + "description": "服务目录"}, | ||
76 | ], | 86 | ], |
77 | "responses": { | 87 | "responses": { |
78 | 200: { | 88 | 200: { |
app/modules/service/service_state.py
0 → 100644
1 | +# coding=utf-8 | ||
2 | +#author: 4N | ||
3 | +#createtime: 2021/9/14 | ||
4 | +#email: nheweijun@sina.com | ||
5 | + | ||
6 | + | ||
7 | + | ||
8 | + | ||
9 | +from app.util.component.ApiTemplate import ApiTemplate | ||
10 | +from app.models import Service,db | ||
11 | +class Api(ApiTemplate): | ||
12 | + api_name = "修改服务状态" | ||
13 | + def process(self): | ||
14 | + res = {} | ||
15 | + try: | ||
16 | + guid = self.para.get("guid") | ||
17 | + state = int(self.para.get("state")) | ||
18 | + Service.query.filter_by(guid=guid).update({"state":state}) | ||
19 | + | ||
20 | + | ||
21 | + #更新缓存 | ||
22 | + | ||
23 | + | ||
24 | + | ||
25 | + db.session.commit() | ||
26 | + except Exception as e: | ||
27 | + raise e | ||
28 | + return res | ||
29 | + | ||
30 | + | ||
31 | + api_doc = { | ||
32 | + "tags": ["服务接口"], | ||
33 | + "parameters": [ | ||
34 | + {"name": "guid", | ||
35 | + "in": "formData", | ||
36 | + "type": "string", | ||
37 | + "description": "guid"}, | ||
38 | + {"name": "stat", | ||
39 | + "in": "formData", | ||
40 | + "type": "int", | ||
41 | + "description": "state"}, | ||
42 | + ], | ||
43 | + "responses": { | ||
44 | + 200: { | ||
45 | + "schema": { | ||
46 | + "properties": { | ||
47 | + } | ||
48 | + } | ||
49 | + } | ||
50 | + } | ||
51 | + } |
@@ -6,8 +6,28 @@ | @@ -6,8 +6,28 @@ | ||
6 | from flasgger import swag_from | 6 | from flasgger import swag_from |
7 | from flask import Blueprint | 7 | from flask import Blueprint |
8 | from app.util import BlueprintApi | 8 | from app.util import BlueprintApi |
9 | +from . import wms_register,wms_edit | ||
9 | 10 | ||
10 | class DataManager(BlueprintApi): | 11 | class DataManager(BlueprintApi): |
11 | 12 | ||
12 | bp = Blueprint("WMS", __name__, url_prefix="/API/Service/WMS") | 13 | bp = Blueprint("WMS", __name__, url_prefix="/API/Service/WMS") |
13 | - service_type = ["WMS"] | ||
14 | + service_type = ["WMS/WFS"] | ||
15 | + | ||
16 | + @staticmethod | ||
17 | + @bp.route('/Register', methods=['POST']) | ||
18 | + @swag_from(wms_register.Api.api_doc) | ||
19 | + def api_wms_register(): | ||
20 | + """ | ||
21 | + 注册WMS | ||
22 | + """ | ||
23 | + return wms_register.Api().result | ||
24 | + | ||
25 | + | ||
26 | + @staticmethod | ||
27 | + @bp.route('/Edit', methods=['POST']) | ||
28 | + @swag_from(wms_edit.Api.api_doc) | ||
29 | + def api_wms_edit(): | ||
30 | + """ | ||
31 | + 修改WMS | ||
32 | + """ | ||
33 | + return wms_edit.Api().result |
@@ -53,9 +53,76 @@ class Api(ApiTemplate): | @@ -53,9 +53,76 @@ class Api(ApiTemplate): | ||
53 | return res | 53 | return res |
54 | 54 | ||
55 | api_doc = { | 55 | api_doc = { |
56 | - "tags": ["影像接口"], | 56 | + "tags": ["WMS接口"], |
57 | "parameters": [ | 57 | "parameters": [ |
58 | 58 | ||
59 | + {"name": "name", | ||
60 | + "in": "formData", | ||
61 | + "type": "string", | ||
62 | + "required": "true", | ||
63 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
64 | + {"name": "alias", | ||
65 | + "in": "formData", | ||
66 | + "type": "string", | ||
67 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
68 | + {"name": "description", | ||
69 | + "in": "formData", | ||
70 | + "type": "string", | ||
71 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
72 | + {"name": "catalog_guid", | ||
73 | + "in": "formData", | ||
74 | + "type": "string", | ||
75 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
76 | + | ||
77 | + | ||
78 | + | ||
79 | + {"name": "layer_style", | ||
80 | + "in": "formData", | ||
81 | + "type": "string", | ||
82 | + "description": "[WMTS,WMS]图层样式"}, | ||
83 | + | ||
84 | + # WMS参数 | ||
85 | + {"name": "status", | ||
86 | + "in": "formData", | ||
87 | + "type": "string", | ||
88 | + "description": "[WMS]status"}, | ||
89 | + {"name": "username", | ||
90 | + "in": "formData", | ||
91 | + "type": "string", | ||
92 | + "description": "[WMS]username"}, | ||
93 | + {"name": "readonly", | ||
94 | + "in": "formData", | ||
95 | + "type": "string", | ||
96 | + "description": "[WMS]readonly"}, | ||
97 | + {"name": "sid", | ||
98 | + "in": "formData", | ||
99 | + "type": "string", | ||
100 | + "description": "[WMS]sid"}, | ||
101 | + {"name": "stype", | ||
102 | + "in": "formData", | ||
103 | + "type": "string", | ||
104 | + "description": "[WMS]stype"}, | ||
105 | + {"name": "ssupply", | ||
106 | + "in": "formData", | ||
107 | + "type": "string", | ||
108 | + "description": "[WMS]ssupply"}, | ||
109 | + {"name": "sctime", | ||
110 | + "in": "formData", | ||
111 | + "type": "string", | ||
112 | + "description": "[WMS]sctime"}, | ||
113 | + {"name": "company", | ||
114 | + "in": "formData", | ||
115 | + "type": "string", | ||
116 | + "description": "[WMS]company"}, | ||
117 | + {"name": "abstract", | ||
118 | + "in": "formData", | ||
119 | + "type": "string", | ||
120 | + "description": "[WMS]abstract"}, | ||
121 | + {"name": "thumbnail", | ||
122 | + "in": "formData", | ||
123 | + "type": "string", | ||
124 | + "description": "[WMS]thumbnail"}, | ||
125 | + | ||
59 | ], | 126 | ], |
60 | "responses": { | 127 | "responses": { |
61 | 200: { | 128 | 200: { |
@@ -12,7 +12,7 @@ import datetime | @@ -12,7 +12,7 @@ import datetime | ||
12 | import configure | 12 | import configure |
13 | class Api(ApiTemplate): | 13 | class Api(ApiTemplate): |
14 | 14 | ||
15 | - api_name = "注册WMTS服务" | 15 | + api_name = "注册WMS服务" |
16 | 16 | ||
17 | def process(self): | 17 | def process(self): |
18 | # 返回结果 | 18 | # 返回结果 |
@@ -74,7 +74,7 @@ class Api(ApiTemplate): | @@ -74,7 +74,7 @@ class Api(ApiTemplate): | ||
74 | return res | 74 | return res |
75 | 75 | ||
76 | api_doc = { | 76 | api_doc = { |
77 | - "tags": ["WMTS接口"], | 77 | + "tags": ["WMS接口"], |
78 | "parameters": [ | 78 | "parameters": [ |
79 | 79 | ||
80 | {"name": "name", | 80 | {"name": "name", |
@@ -7,16 +7,16 @@ | @@ -7,16 +7,16 @@ | ||
7 | from flasgger import swag_from | 7 | from flasgger import swag_from |
8 | from flask import Blueprint | 8 | from flask import Blueprint |
9 | from app.util import BlueprintApi | 9 | from app.util import BlueprintApi |
10 | -from . import upload_oview | 10 | +from . import upload_oview,wmts_register,wmts_edit |
11 | 11 | ||
12 | -import os | ||
13 | -from flask import send_from_directory | ||
14 | 12 | ||
15 | 13 | ||
16 | class DataManager(BlueprintApi): | 14 | class DataManager(BlueprintApi): |
17 | 15 | ||
18 | bp = Blueprint("WMTS", __name__, url_prefix="/API/Service/WMTS") | 16 | bp = Blueprint("WMTS", __name__, url_prefix="/API/Service/WMTS") |
19 | 17 | ||
18 | + service_type = ["WMTS","MTS"] | ||
19 | + | ||
20 | @staticmethod | 20 | @staticmethod |
21 | @bp.route('/UploadOverview', methods=['POST']) | 21 | @bp.route('/UploadOverview', methods=['POST']) |
22 | @swag_from(upload_oview.Api.api_doc) | 22 | @swag_from(upload_oview.Api.api_doc) |
@@ -25,3 +25,23 @@ class DataManager(BlueprintApi): | @@ -25,3 +25,23 @@ class DataManager(BlueprintApi): | ||
25 | 上传缩略图 | 25 | 上传缩略图 |
26 | """ | 26 | """ |
27 | return upload_oview.Api().result | 27 | return upload_oview.Api().result |
28 | + | ||
29 | + | ||
30 | + @staticmethod | ||
31 | + @bp.route('/Register', methods=['POST']) | ||
32 | + @swag_from(wmts_register.Api.api_doc) | ||
33 | + def api_wmts_register(): | ||
34 | + """ | ||
35 | + 注册WMTS | ||
36 | + """ | ||
37 | + return wmts_register.Api().result | ||
38 | + | ||
39 | + @staticmethod | ||
40 | + @bp.route('/Edit', methods=['POST']) | ||
41 | + @swag_from(wmts_edit.Api.api_doc) | ||
42 | + def api_wmts_edit(): | ||
43 | + """ | ||
44 | + 修改WMTS | ||
45 | + """ | ||
46 | + return wmts_edit.Api().result | ||
47 | + |
@@ -51,9 +51,84 @@ class Api(ApiTemplate): | @@ -51,9 +51,84 @@ class Api(ApiTemplate): | ||
51 | return res | 51 | return res |
52 | 52 | ||
53 | api_doc = { | 53 | api_doc = { |
54 | - "tags": ["影像接口"], | 54 | + "tags": ["WMTS接口"], |
55 | "parameters": [ | 55 | "parameters": [ |
56 | 56 | ||
57 | + {"name": "name", | ||
58 | + "in": "formData", | ||
59 | + "type": "string", | ||
60 | + "required": "true", | ||
61 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
62 | + {"name": "alias", | ||
63 | + "in": "formData", | ||
64 | + "type": "string", | ||
65 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
66 | + {"name": "description", | ||
67 | + "in": "formData", | ||
68 | + "type": "string", | ||
69 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
70 | + | ||
71 | + {"name": "catalog_guid", | ||
72 | + "in": "formData", | ||
73 | + "type": "string", | ||
74 | + "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | ||
75 | + | ||
76 | + {"name": "scheme_guid", | ||
77 | + "in": "formData", | ||
78 | + "type": "string", | ||
79 | + "description": "[WMTS,影像WMTS]切片方案"}, | ||
80 | + | ||
81 | + # WMTS参数 | ||
82 | + {"name": "overview", | ||
83 | + "in": "formData", | ||
84 | + "type": "string", | ||
85 | + "description": "[WMTS]缩略图"}, | ||
86 | + {"name": "wmts_type", | ||
87 | + "in": "formData", | ||
88 | + "type": "string", | ||
89 | + "description": "[WMTS]wmts_type"}, | ||
90 | + {"name": "vendor", | ||
91 | + "in": "formData", | ||
92 | + "type": "string", | ||
93 | + "description": "[WMTS]厂商"}, | ||
94 | + {"name": "crs", | ||
95 | + "in": "formData", | ||
96 | + "type": "string", | ||
97 | + "description": "[WMTS]坐标系"}, | ||
98 | + {"name": "datasource", | ||
99 | + "in": "formData", | ||
100 | + "type": "string", | ||
101 | + "description": "[WMTS]数据路径"}, | ||
102 | + {"name": "layer_name", | ||
103 | + "in": "formData", | ||
104 | + "type": "string", | ||
105 | + "description": "[WMTS]图层名"}, | ||
106 | + {"name": "layer_alias", | ||
107 | + "in": "formData", | ||
108 | + "type": "string", | ||
109 | + "description": "[WMTS]图层别名"}, | ||
110 | + {"name": "layer_title", | ||
111 | + "in": "formData", | ||
112 | + "type": "string", | ||
113 | + "description": "[WMTS]图层标题"}, | ||
114 | + {"name": "layer_style", | ||
115 | + "in": "formData", | ||
116 | + "type": "string", | ||
117 | + "description": "[WMTS,WMS]图层样式"}, | ||
118 | + {"name": "layer_format", | ||
119 | + "in": "formData", | ||
120 | + "type": "string", | ||
121 | + "description": "[WMTS]图层format"}, | ||
122 | + {"name": "layer_extent", | ||
123 | + "in": "formData", | ||
124 | + "type": "string", | ||
125 | + "description": "[WMTS]图层范围"}, | ||
126 | + {"name": "layer_description", | ||
127 | + "in": "formData", | ||
128 | + "type": "string", | ||
129 | + "description": "[WMTS]图层描述"}, | ||
130 | + | ||
131 | + | ||
57 | ], | 132 | ], |
58 | "responses": { | 133 | "responses": { |
59 | 200: { | 134 | 200: { |
@@ -75,7 +75,7 @@ class FileProcess: | @@ -75,7 +75,7 @@ class FileProcess: | ||
75 | text_size = "{}KB".format(round(fsize / float(1024), 1)) | 75 | text_size = "{}KB".format(round(fsize / float(1024), 1)) |
76 | else: | 76 | else: |
77 | text_size = "{}B".format(round(fsize / float(1), 1)) | 77 | text_size = "{}B".format(round(fsize / float(1), 1)) |
78 | - return text_size | 78 | + return text_size,fsize |
79 | 79 | ||
80 | 80 | ||
81 | 81 |
app/util/component/Geometry2Raster.py
0 → 100644
1 | +# coding=utf-8 | ||
2 | +#author: 4N | ||
3 | +#createtime: 2021/9/29 | ||
4 | +#email: nheweijun@sina.com | ||
5 | + | ||
6 | +from osgeo.ogr import Layer,Geometry | ||
7 | +from osgeo import gdal,ogr | ||
8 | + | ||
9 | + | ||
10 | +class Geometry2Raster: | ||
11 | + | ||
12 | + | ||
13 | + def __init__(self): | ||
14 | + pass | ||
15 | + | ||
16 | + @classmethod | ||
17 | + def convert(cls,geometry:Geometry,bbox, xy_res): | ||
18 | + ''' | ||
19 | + 根据Geometry和bbox将空间对象栅格化 | ||
20 | + :param geometry: 空间对象 | ||
21 | + :param bbox: 栅格化范围 | ||
22 | + :param xy_res: 分辨率 | ||
23 | + :return: | ||
24 | + ''' | ||
25 | + | ||
26 | + #计算像素大小 | ||
27 | + x_min,y_min,x_max, y_max = bbox | ||
28 | + pixel_size = (x_max - x_min) / xy_res | ||
29 | + #创建内存栅格对象 | ||
30 | + target_ds = gdal.GetDriverByName('MEM').Create('', xy_res, xy_res, gdal.GDT_Byte) | ||
31 | + target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size)) | ||
32 | + band = target_ds.GetRasterBand(1) | ||
33 | + #创建内存图层对象,因为gdal只提供栅格化图层的方法 | ||
34 | + layer_ds = ogr.GetDriverByName('Memory').CreateDataSource('') | ||
35 | + mem_layer= layer_ds.CreateLayer("mem", geom_type=ogr.wkbUnknown) | ||
36 | + feature_defn = mem_layer.GetLayerDefn() | ||
37 | + feature = ogr.Feature(feature_defn) | ||
38 | + feature.SetGeometry(geometry) | ||
39 | + mem_layer.CreateFeature(feature) | ||
40 | + #栅格化 | ||
41 | + gdal.RasterizeLayer(target_ds, [1], mem_layer, burn_values=[1]) | ||
42 | + data = band.ReadAsArray() | ||
43 | + del target_ds | ||
44 | + del layer_ds | ||
45 | + return data | ||
46 | + | ||
47 | +if __name__ == '__main__': | ||
48 | + | ||
49 | + # Create ring | ||
50 | + ring = ogr.Geometry(ogr.wkbLinearRing) | ||
51 | + ring.AddPoint(111.62, 29) | ||
52 | + ring.AddPoint(111.62, 29.03) | ||
53 | + ring.AddPoint(111.727, 29.03) | ||
54 | + ring.AddPoint(111.727, 29) | ||
55 | + ring.AddPoint(111.62, 29) | ||
56 | + | ||
57 | + # Create polygon | ||
58 | + poly = ogr.Geometry(ogr.wkbPolygon) | ||
59 | + poly.AddGeometry(ring) | ||
60 | + | ||
61 | + poly.ExportToWkt() | ||
62 | + | ||
63 | + |
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | #author: 4N | 2 | #author: 4N |
3 | #createtime: 2021/6/3 | 3 | #createtime: 2021/6/3 |
4 | #email: nheweijun@sina.com | 4 | #email: nheweijun@sina.com |
5 | -from osgeo import ogr | 5 | +from osgeo import ogr,gdal |
6 | from osgeo.ogr import Geometry | 6 | from osgeo.ogr import Geometry |
7 | 7 | ||
8 | class GeometryAdapter: | 8 | class GeometryAdapter: |
@@ -182,4 +182,36 @@ class GeometryAdapter: | @@ -182,4 +182,36 @@ class GeometryAdapter: | ||
182 | g: Geometry = fea.geometry() | 182 | g: Geometry = fea.geometry() |
183 | geom_type = g.GetGeometryType() | 183 | geom_type = g.GetGeometryType() |
184 | layer.ResetReading() | 184 | layer.ResetReading() |
185 | - return geom_type | ||
185 | + return geom_type | ||
186 | + | ||
187 | + @classmethod | ||
188 | + def convert(cls, geometry: Geometry, bbox, xy_res): | ||
189 | + ''' | ||
190 | + 根据Geometry和bbox将空间对象栅格化 | ||
191 | + :param geometry: 空间对象 | ||
192 | + :param bbox: 栅格化范围 | ||
193 | + :param xy_res: 分辨率 | ||
194 | + :return: | ||
195 | + ''' | ||
196 | + | ||
197 | + # 计算像素大小 | ||
198 | + x_min, y_min, x_max, y_max = bbox | ||
199 | + pixel_size = (x_max - x_min) / xy_res | ||
200 | + # 创建内存栅格对象 | ||
201 | + target_ds = gdal.GetDriverByName('MEM').Create('', xy_res, xy_res, gdal.GDT_Byte) | ||
202 | + target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size)) | ||
203 | + band = target_ds.GetRasterBand(1) | ||
204 | + # 创建内存图层对象,因为gdal只提供栅格化图层的方法 | ||
205 | + layer_ds = ogr.GetDriverByName('Memory').CreateDataSource('') | ||
206 | + mem_layer = layer_ds.CreateLayer("mem", geom_type=ogr.wkbUnknown) | ||
207 | + feature_defn = mem_layer.GetLayerDefn() | ||
208 | + feature = ogr.Feature(feature_defn) | ||
209 | + feature.SetGeometry(geometry) | ||
210 | + mem_layer.CreateFeature(feature) | ||
211 | + # 栅格化 | ||
212 | + gdal.RasterizeLayer(target_ds, [1], mem_layer, burn_values=[1]) | ||
213 | + data = band.ReadAsArray() | ||
214 | + del target_ds | ||
215 | + del layer_ds | ||
216 | + # Read as array | ||
217 | + return data |
test/numpy_test.py
0 → 100644
1 | +# coding=utf-8 | ||
2 | +#author: 4N | ||
3 | +#createtime: 2021/9/29 | ||
4 | +#email: nheweijun@sina.com | ||
5 | + | ||
6 | +def determine_level(xysize, origin_extent, extent, max_level): | ||
7 | + ''' | ||
8 | + 根据范围判断调用金字塔的哪一层 | ||
9 | + :param xysize: | ||
10 | + :param origin_extent: | ||
11 | + :param extent: | ||
12 | + :param max_level: | ||
13 | + :return: | ||
14 | + ''' | ||
15 | + x = xysize[0] | ||
16 | + y = xysize[1] | ||
17 | + level = -1 | ||
18 | + pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / ( | ||
19 | + (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1]))) | ||
20 | + while pixel > 100000 and level < max_level - 1: | ||
21 | + level += 1 | ||
22 | + x = x / 2 | ||
23 | + y = y / 2 | ||
24 | + pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / ( | ||
25 | + (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1]))) | ||
26 | + return level | ||
27 | + | ||
28 | +import math | ||
29 | +def determine_level2(xysize, origin_extent, extent, max_level): | ||
30 | + ''' | ||
31 | + 根据范围判断调用金字塔的哪一层 | ||
32 | + :param xysize: | ||
33 | + :param origin_extent: | ||
34 | + :param extent: | ||
35 | + :param max_level: | ||
36 | + :return: | ||
37 | + ''' | ||
38 | + x = xysize[0] | ||
39 | + y = xysize[1] | ||
40 | + | ||
41 | + level_up = round (math.sqrt( round (math.sqrt((x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / ( | ||
42 | + (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1])))) / 100000)))) | ||
43 | + | ||
44 | + | ||
45 | + return level_up - 1 if level_up < max_level else max_level - 1 | ||
46 | + | ||
47 | +import time | ||
48 | +t1 = time.time() | ||
49 | + | ||
50 | +print(determine_level2([108488,90777],[111.639350712, 28.9170588759, 111.751508603, 29.032941696], | ||
51 | + [111.739350712, 29.0070588759, 111.751508603, 29.032941696],9)) | ||
52 | +print(time.time()-t1) | ||
53 | +t1 = time.time() | ||
54 | + | ||
55 | +print(determine_level([108488,90777],[111.639350712, 28.9170588759, 111.751508603, 29.032941696], | ||
56 | + [111.739350712, 29.0070588759, 111.751508603, 29.032941696],9)) | ||
57 | + | ||
58 | +print(time.time()-t1) |
test/shp2raster.py
0 → 100644
1 | +# coding=utf-8 | ||
2 | +#author: 4N | ||
3 | +#createtime: 2021/9/28 | ||
4 | +#email: nheweijun@sina.com | ||
5 | + | ||
6 | + | ||
7 | +from osgeo import gdal,ogr | ||
8 | +from osgeo.ogr import Layer,Feature | ||
9 | + | ||
10 | +vector_fn = r'E:\Data\广东边界\gdsample.shp' | ||
11 | + | ||
12 | +# Define pixel_size and NoData value of new raster | ||
13 | +pixel_size = 0.1 | ||
14 | +NoData_value = 255 | ||
15 | + | ||
16 | +# Open the data source and read in the extent | ||
17 | +source_ds = ogr.Open(vector_fn) | ||
18 | +source_layer:Layer = source_ds.GetLayer() | ||
19 | +source_srs = source_layer.GetSpatialRef() | ||
20 | +x_min, x_max, y_min, y_max = source_layer.GetExtent() | ||
21 | + | ||
22 | +# Create the destination data source | ||
23 | +x_res = int((x_max - (x_min-2)) / pixel_size) | ||
24 | +y_res = int((y_max - y_min) / pixel_size) | ||
25 | +target_ds = gdal.GetDriverByName('GTiff').Create('t.tiff', x_res, y_res, gdal.GDT_Byte) | ||
26 | +target_ds.SetGeoTransform((x_min-2, pixel_size, 0, y_max, 0, -pixel_size)) | ||
27 | +band = target_ds.GetRasterBand(1) | ||
28 | +band.SetNoDataValue(NoData_value) | ||
29 | + | ||
30 | +# Rasterize | ||
31 | +kk:Feature = source_layer.GetFeature(0) | ||
32 | + | ||
33 | +layer_ds = ogr.GetDriverByName('Memory').CreateDataSource('') | ||
34 | +outLayer = layer_ds.CreateLayer("mem",geom_type=ogr.wkbUnknown) | ||
35 | +featureDefn = outLayer.GetLayerDefn() | ||
36 | +outFeature = ogr.Feature(featureDefn) | ||
37 | +outFeature.SetGeometry(kk.geometry()) | ||
38 | +outLayer.CreateFeature(outFeature) | ||
39 | + | ||
40 | +gdal.RasterizeLayer(target_ds, [1], outLayer, burn_values=[1]) | ||
41 | + | ||
42 | + | ||
43 | +# Read as array | ||
44 | +array = band.ReadAsArray() | ||
45 | +print(array) |
test/t.tiff
0 → 100644
不能预览此文件类型
请
注册
或
登录
后发表评论