提交 e29795f697e7c4d728d9a07769ac301fab012d1f

作者 nheweijun
1 个父辈 6bb1b372

服务整合

正在显示 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
@@ -80,7 +80,7 @@ class Api(ApiTemplate): @@ -80,7 +80,7 @@ class Api(ApiTemplate):
80 80
81 api_doc={ 81 api_doc={
82 82
83 - "tags":["目录接口"], 83 + "tags":["矢量数据目录接口"],
84 "parameters":[ 84 "parameters":[
85 {"name": "name", 85 {"name": "name",
86 "in": "formData", 86 "in": "formData",
@@ -67,7 +67,7 @@ class Api(ApiTemplate): @@ -67,7 +67,7 @@ class Api(ApiTemplate):
67 67
68 68
69 api_doc = { 69 api_doc = {
70 - "tags": ["目录接口"], 70 + "tags": ["矢量数据目录接口"],
71 "parameters": [ 71 "parameters": [
72 {"name": "guid", 72 {"name": "guid",
73 "in": "formData", 73 "in": "formData",
@@ -34,7 +34,7 @@ class Api(ApiTemplate): @@ -34,7 +34,7 @@ class Api(ApiTemplate):
34 34
35 35
36 api_doc = { 36 api_doc = {
37 - "tags": ["目录接口"], 37 + "tags": ["矢量数据目录接口"],
38 "parameters": [ 38 "parameters": [
39 {"name": "guid", 39 {"name": "guid",
40 "in": "formData", 40 "in": "formData",
@@ -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: {
  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": ["影像接口"],
  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: {
  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
  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
  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)
  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)
不能预览此文件类型
注册登录 后发表评论