提交 e29795f697e7c4d728d9a07769ac301fab012d1f

作者 nheweijun
1 个父辈 6bb1b372

服务整合

正在显示 46 个修改的文件 包含 1774 行增加208 行删除
... ... @@ -265,9 +265,10 @@ pkgs.extend(list(glob.glob('%s/modules/*/*/models' % (current_dir))))
265 265 for pkg in pkgs :
266 266 pkg = os.path.normpath(pkg)
267 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 269 try:
270   - __import__(pkg_name)
  270 + if pkg_name.__contains__("models"):
  271 + __import__(pkg_name)
271 272 except Exception as e:
272 273 print(traceback.format_exc())
273 274 pass
\ No newline at end of file
... ...
... ... @@ -80,7 +80,7 @@ class Api(ApiTemplate):
80 80
81 81 api_doc={
82 82
83   - "tags":["目录接口"],
  83 + "tags":["矢量数据目录接口"],
84 84 "parameters":[
85 85 {"name": "name",
86 86 "in": "formData",
... ...
... ... @@ -67,7 +67,7 @@ class Api(ApiTemplate):
67 67
68 68
69 69 api_doc = {
70   - "tags": ["目录接口"],
  70 + "tags": ["矢量数据目录接口"],
71 71 "parameters": [
72 72 {"name": "guid",
73 73 "in": "formData",
... ...
... ... @@ -34,7 +34,7 @@ class Api(ApiTemplate):
34 34
35 35
36 36 api_doc = {
37   - "tags": ["目录接口"],
  37 + "tags": ["矢量数据目录接口"],
38 38 "parameters": [
39 39 {"name": "guid",
40 40 "in": "formData",
... ...
... ... @@ -35,7 +35,7 @@ class Api(ApiTemplate):
35 35
36 36 api_doc={
37 37
38   - "tags":["目录接口"],
  38 + "tags":["矢量数据目录接口"],
39 39 "parameters":[
40 40 {"name": "catalog_guid",
41 41 "in": "formData",
... ...
... ... @@ -51,7 +51,7 @@ class Api(ApiTemplate):
51 51
52 52 api_doc={
53 53
54   - "tags":["目录接口"],
  54 + "tags":["矢量数据目录接口"],
55 55 "parameters":[
56 56 {"name": "database_guid",
57 57 "in": "formData",
... ...
... ... @@ -42,7 +42,7 @@ class Api(ApiTemplate):
42 42
43 43 api_doc={
44 44
45   - "tags":["目录接口"],
  45 + "tags":["矢量数据目录接口"],
46 46 "parameters":[
47 47 {"name": "database_guid",
48 48 "in": "formData",
... ...
... ... @@ -7,9 +7,10 @@ from flasgger import swag_from
7 7 from flask import Blueprint
8 8 from app.util import BlueprintApi
9 9 from . import service_register
10   -from . import service_type
  10 +from . import service_exist_type
11 11 from . import service_list
12 12 from . import service_delete
  13 +from . import service_state
13 14 import os
14 15 from flask import send_from_directory
15 16
... ... @@ -17,6 +18,8 @@ from flask import send_from_directory
17 18 class DataManager(BlueprintApi):
18 19
19 20 bp = Blueprint("Service", __name__, url_prefix="/API/Service")
  21 + service_type = []
  22 +
20 23
21 24 @staticmethod
22 25 @bp.route('/Register', methods=['POST'])
... ... @@ -29,12 +32,21 @@ class DataManager(BlueprintApi):
29 32
30 33 @staticmethod
31 34 @bp.route('/Type', methods=['GET'])
32   - @swag_from(service_type.Api.api_doc)
  35 + @swag_from(service_exist_type.Api.api_doc)
33 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 51 @staticmethod
40 52 @bp.route('/List', methods=['POST'])
... ...
... ... @@ -19,7 +19,7 @@ from . import catalog_edit, catalog_tree, catalog_delete, catalog_create, catalo
19 19 class DataManager(BlueprintApi):
20 20
21 21 bp = Blueprint("ServiceCatalog", __name__, url_prefix="/API/Service/Catalog")
22   -
  22 + service_type = []
23 23
24 24 @staticmethod
25 25 @bp.route('/Create', methods=['POST'])
... ...
... ... @@ -17,7 +17,7 @@ from . import feature_edit
17 17 class DataManager(BlueprintApi):
18 18
19 19 bp = Blueprint("FeatureService", __name__, url_prefix="/API/FeatureService")
20   - service_type = ["要素服务"]
  20 + service_type = []
21 21 @staticmethod
22 22 @bp.route('/Query', methods=['POST'])
23 23 @swag_from(feature_query.Api.api_doc)
... ...
... ... @@ -7,22 +7,23 @@
7 7 from flasgger import swag_from
8 8 from flask import Blueprint
9 9 from app.util import BlueprintApi
10   -from . import image_register
11 10 from . import image_service_register
12 11 from . import image_server_list
13 12 from . import data_list
14 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 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 23 class DataManager(BlueprintApi):
23 24
24 25 bp = Blueprint("Image", __name__, url_prefix="/API/Service/Image")
25   - service_type = ["影像WMS服务","影像WMTS服务"]
  26 + service_type = ["ImageWMS","ImageWMTS"]
26 27
27 28 @staticmethod
28 29 @bp.route('/Register', methods=['POST'])
... ... @@ -33,6 +34,24 @@ class DataManager(BlueprintApi):
33 34 """
34 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 56 @staticmethod
38 57 @bp.route('/Overview', methods=['POST'])
... ... @@ -43,6 +62,35 @@ class DataManager(BlueprintApi):
43 62 """
44 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 94 @staticmethod
47 95 @bp.route('/ServiceRegister', methods=['POST'])
48 96 @swag_from(image_service_register.Api.api_doc)
... ... @@ -117,6 +165,24 @@ class DataManager(BlueprintApi):
117 165 """
118 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 188 @staticmethod
... ...
... ... @@ -11,6 +11,9 @@ from app.util.component.FileProcess import FileProcess
11 11 import datetime
12 12 from app.modules.service.image.util.ThriftConnect import ThriftConnect
13 13 import os
  14 +from app.models import db
  15 +from app.modules.service.image.models import Image
  16 +
14 17 class Api(ApiTemplate):
15 18
16 19 api_name = "影像数据列表"
... ... @@ -38,11 +41,20 @@ class Api(ApiTemplate):
38 41 for f in os.listdir(base_path):
39 42
40 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 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 59 if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif"):
48 60 file_info["type"] = "tif"
... ... @@ -61,6 +73,17 @@ class Api(ApiTemplate):
61 73 thrift_connect = ThriftConnect(data_server)
62 74 info= json.loads(thrift_connect.client.getImageList(path))
63 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 87 res["data"] = info
65 88
66 89 res["result"] = True
... ...
... ... @@ -41,6 +41,12 @@ class Api(ApiTemplate):
41 41 {"name": "alias",
42 42 "in": "formData",
43 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 51 "responses": {
46 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 from app.util.component.ApiTemplate import ApiTemplate
8 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 11 from sqlalchemy import or_,and_
12 12 class Api(ApiTemplate):
13 13
... ... @@ -23,6 +23,8 @@ class Api(ApiTemplate):
23 23
24 24 alias = self.para.get("alias")
25 25 name = self.para.get("name")
  26 + tag_guid = self.para.get("tag_guid")
  27 +
26 28 images = Image.query
27 29
28 30 # 并集
... ... @@ -33,6 +35,11 @@ class Api(ApiTemplate):
33 35 images = images.filter(Image.alias.like("%" + alias + "%"))
34 36 if name:
35 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 44 images = images.limit(page_size).offset(page_index).all()
38 45
... ... @@ -61,6 +68,9 @@ class Api(ApiTemplate):
61 68 {"name": "name",
62 69 "in": "formData",
63 70 "type": "string"},
  71 + {"name": "tag_guid",
  72 + "in": "formData",
  73 + "type": "string"},
64 74 ],
65 75 "responses": {
66 76 200: {
... ...
... ... @@ -47,11 +47,18 @@ class Api(ApiTemplate):
47 47 image = Image.query.filter_by(guid=guid).one_or_none()
48 48 # 该影像的服务器,随机选取一个
49 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 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 64 query_extent = json.loads(image.extent)
... ... @@ -63,7 +70,7 @@ class Api(ApiTemplate):
63 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 76 pixel_array = numpy.zeros((256, 256, 3), dtype=int)
... ...
... ... @@ -14,7 +14,9 @@ import datetime
14 14 from app.models import db
15 15 import uuid
16 16 import os
  17 +from .models import ImageTag
17 18 import math
  19 +
18 20 class Api(ApiTemplate):
19 21
20 22 api_name = "注册影像数据"
... ... @@ -28,6 +30,12 @@ class Api(ApiTemplate):
28 30 try:
29 31 data_server = self.para.get("data_server")
30 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 41 infos = []
... ... @@ -43,7 +51,7 @@ class Api(ApiTemplate):
43 51 origin = osr.SpatialReference()
44 52 origin.ImportFromWkt(image.GetProjection())
45 53
46   - authority_code = origin.GetAuthorityCode()
  54 + authority_code = origin.GetAuthorityCode(None)
47 55 band_count = image.RasterCount
48 56 band: Band = image.GetRasterBand(1)
49 57 count = band.GetOverviewCount()
... ... @@ -63,6 +71,7 @@ class Api(ApiTemplate):
63 71 # geo_origin_extent = [geo_left_top[1], geo_right_buttom[0], geo_right_buttom[1], geo_left_top[0]]
64 72
65 73 info = {"band_count": band_count,
  74 + "band_view":"[1,2,3]" if band_count>=3 else "[1,1,1]",
66 75 "overview_count": count,
67 76 "path":image_info["path"],
68 77 "xy_size": [image.RasterXSize, image.RasterYSize],
... ... @@ -108,17 +117,17 @@ class Api(ApiTemplate):
108 117 if exist_image.server.__contains__(data_server):
109 118 pass
110 119 else:
111   - exist_image.update({"server":"{},".format(data_server)})
  120 + exist_image.update({"server":"{},{}".format(exist_image.server,data_server)})
112 121 else:
113   - image = Image(guid= uuid.uuid1().__str__(),
  122 + img:Image = Image(guid= uuid.uuid1().__str__(),
114 123 overview_count=info.get("overview_count"),
115 124 raster_x_size=info["xy_size"][0],
116 125 raster_y_size=info["xy_size"][1],
117 126 cell_x_size = info.get("cell_x_size"),
118 127 cell_y_size = abs(info.get("cell_y_size")),
119 128 name=os.path.basename(info.get("path")),
  129 + alias = os.path.basename(info.get("path")),
120 130 extent=json.dumps(info["origin_extent"]),
121   - # geo_origin_extent = json.dumps(info["geo_origin_extent"]),
122 131 null_value=info.get("null_value"),
123 132 server=data_server,
124 133 path = os.path.normpath(info.get("path")),
... ... @@ -129,12 +138,10 @@ class Api(ApiTemplate):
129 138 band_count=info.get("band_count"),
130 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 144 db.session.commit()
134   - # res["data"] = guid
135   -
136   -
137   -
138 145 res["result"] = True
139 146
140 147 except Exception as e:
... ... @@ -181,7 +188,11 @@ class Api(ApiTemplate):
181 188 {"name": "paths",
182 189 "in": "formData",
183 190 "type": "string",
184   - "description": "paths"}
  191 + "description": "paths"},
  192 + {"name": "tags",
  193 + "in": "formData",
  194 + "type": "string",
  195 + "description": "tags以,相隔"}
185 196 ],
186 197 "responses": {
187 198 200: {
... ...
... ... @@ -139,7 +139,7 @@ class Api(ApiTemplate):
139 139 {"name": "type",
140 140 "in": "formData",
141 141 "type": "string",
142   - "enum": ["WMS", "WMTS", "影像WMS", "影像WMTS"],
  142 + "enum": ["WMS/WFS","WMTS","MTS","ImageWMS","ImageWMTS"],
143 143 "required": "true",
144 144 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
145 145 {"name": "catalog_guid",
... ...
... ... @@ -19,21 +19,18 @@ import cv2
19 19 from app.modules.service.image.models import ImageService,Image
20 20 from app.models import db,TileScheme
21 21 from app.util.component.ApiTemplate import ApiTemplate
22   -import uuid
23 22 from app.util.component.SliceScheme import SliceScheme
24   -from app.util.component.FileProcess import FileProcess
25 23 from app.util.component.ParameterUtil import ParameterUtil
26   -from app.util.component.GeometryAdapter import GeometryAdapter
27   -import os
28 24 import json
29 25 from kazoo.client import KazooClient
30   -
31 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 28 import gzip
36 29 import random
  30 +import copy
  31 +
  32 +
  33 +
37 34 class Api(ApiTemplate):
38 35
39 36 api_name = "切片"
... ... @@ -46,7 +43,7 @@ class Api(ApiTemplate):
46 43 self.col = col
47 44
48 45 def process(self):
49   - from app import GLOBAL_DIC
  46 +
50 47 result = {}
51 48 parameter: dict = self.para
52 49
... ... @@ -54,33 +51,13 @@ class Api(ApiTemplate):
54 51 if parameter.get("guid"):
55 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 59 parameter = ParameterUtil.to_lower(parameter)
82 60
83   -
84 61 if parameter.get("tilematrix"):
85 62 if parameter.get("tilematrix").__contains__(":"):
86 63 self.level = int(parameter.get("tilematrix").split(":")[-1])
... ... @@ -96,7 +73,6 @@ class Api(ApiTemplate):
96 73 slice_para = image_service_info["scheme"]
97 74 extent = SliceScheme.get_polygon(slice_para, self.level, self.row, self.col)
98 75
99   -
100 76 height, width = 256,256
101 77
102 78 # 多线程获取分布式数据
... ... @@ -106,20 +82,25 @@ class Api(ApiTemplate):
106 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 87 thread_list = []
115 88
116 89 for image in intersect_image:
  90 +
117 91 # 该影像的服务器,随机选取一个
118 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 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 104 thread.start()
124 105 thread_list.append(thread)
125 106
... ... @@ -128,51 +109,106 @@ class Api(ApiTemplate):
128 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 129 elif len(intersect_image) == 1:
148 130 # 该影像的服务器,随机选取一个
149 131 image = intersect_image[0]
150 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 143 pixel_array = numpy.zeros((height, width, 3), dtype=int)
  144 +
157 145 for ii in [0, 1, 2]:
158 146 # opencv 颜色排序为GBR
159 147 pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
160 148
161   -
162 149 else:
163 150 # 结果矩阵
164 151 pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536
165 152
  153 +
166 154 # 将图片生成在内存中,然后直接返回response
167 155 im_data = self.create_by_opencv(image_type, pixel_array, quality)
168 156 return Response(im_data, mimetype=image_type.lower())
169 157
  158 +
170 159 except Exception as e:
171 160 print(traceback.format_exc())
172 161 result["state"] = -1
173 162 result["message"] = e.__str__()
174 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 212 def determine_level(self, xysize, origin_extent, extent, max_level):
177 213 '''
178 214 根据范围判断调用金字塔的哪一层
... ... @@ -195,10 +231,12 @@ class Api(ApiTemplate):
195 231 (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1])))
196 232 return level
197 233
  234 +
198 235 def create_by_opencv(self, image_type, pixel_array, quality):
199 236
200 237 if image_type.__eq__("image/jpeg") or image_type.__eq__("image/jpg"):
201 238 r, buf = cv2.imencode(".jpg", pixel_array, [cv2.IMWRITE_JPEG_QUALITY, quality])
  239 + # r, buf = cv2.imencode(".jpg", pixel_array)
202 240 image_out = buf.tobytes()
203 241 else:
204 242 height, width = pixel_array[:, :, 0].shape
... ... @@ -208,17 +246,14 @@ class Api(ApiTemplate):
208 246 image_out = buf.tobytes()
209 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 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 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 257 return data
223 258
224 259 def get_remote_wms_data(self, image_server,image, extent, bands, height, width):
... ... @@ -230,24 +265,93 @@ class Api(ApiTemplate):
230 265 :return:
231 266 '''
232 267
233   -
234 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 293 thrift_connect = ThriftConnect(image_server)
237   - t1 = time.time()
238 294 image_extent = image.extent
239 295
240 296 data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height)
241 297
242 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 323 data = gzip.decompress(data)
246 324 data = numpy.frombuffer(data, dtype='int64')
247 325 data = data.reshape((height, width, 3))
248 326
249 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 355 def get_local_wms_data(self, image, extent, bands, height, width):
252 356 '''
253 357 获取本地数据
... ... @@ -259,20 +363,21 @@ class Api(ApiTemplate):
259 363 pixel_array = numpy.zeros((height, width, 3), dtype=int)
260 364 ceng = 0
261 365 img: Dataset = gdal.Open(image.path, 0)
262   - t1 = time.time()
  366 +
  367 +
  368 +
263 369 for band in bands:
264 370
265 371 # 自决定金字塔等级
266 372 xysize = [img.RasterXSize, img.RasterYSize]
267 373
268   - origin_extent = image.extent
  374 + origin_extent = json.loads(image.extent)
269 375 band_data: Band = img.GetRasterBand(band)
270 376
271 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 381 empty = numpy.zeros((height, width), dtype=int) + 65536
277 382 # 空间范围相交
278 383 else:
... ... @@ -351,10 +456,96 @@ class Api(ApiTemplate):
351 456 ceng += 1
352 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 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 550 api_doc = {
360 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 16 from app.modules.service.image.models import ImageService
17 17 from app.util.component.ApiTemplate import ApiTemplate
18 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 20 from app.util.component.ParameterUtil import ParameterUtil
21 21 import json
22 22 from kazoo.client import KazooClient
... ... @@ -30,7 +30,7 @@ class Api(ApiTemplate):
30 30 api_name = "WMS"
31 31
32 32 def process(self):
33   - from app import GLOBAL_DIC
  33 +
34 34
35 35 result = {}
36 36 parameter: dict = self.para
... ... @@ -38,41 +38,21 @@ class Api(ApiTemplate):
38 38 try:
39 39
40 40 parameter = ParameterUtil.to_lower(parameter)
41   - guid = parameter.get("guid")
  41 + self.guid = parameter.get("guid")
42 42 bbox = parameter.get("bbox")
43 43 width = int(parameter.get("width")) if parameter.get("width") else 256
44 44 height = int(parameter.get("height")) if parameter.get("height") else 256
45 45 image_type = parameter.get("format") if parameter.get("format") else "image/png"
46 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 50 re = parameter.get("request")
62   -
63 51 if re and re.__eq__("GetCapabilities"):
64 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 57 extent = [float(x) for x in bbox.split(",")]
78 58
... ... @@ -91,10 +71,14 @@ class Api(ApiTemplate):
91 71 for image in intersect_image:
92 72 #该影像的服务器,随机选取一个
93 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 82 thread.start()
99 83 thread_list.append(thread)
100 84
... ... @@ -124,9 +108,15 @@ class Api(ApiTemplate):
124 108 # 该影像的服务器,随机选取一个
125 109 image = intersect_image[0]
126 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 120 pixel_array = numpy.zeros((height, width, 3), dtype=int)
131 121 for ii in [0, 1, 2]:
132 122 # opencv 颜色排序为GBR
... ... @@ -148,6 +138,55 @@ class Api(ApiTemplate):
148 138 result["message"] = e.__str__()
149 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 190 def determine_level(self,xysize,origin_extent,extent,max_level):
152 191 '''
153 192 根据范围判断调用金字塔的哪一层
... ... @@ -182,17 +221,14 @@ class Api(ApiTemplate):
182 221 image_out = buf.tobytes()
183 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 226 if image_server.__eq__("本地服务器"):
188 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 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 232 return data
197 233
198 234
... ... @@ -206,7 +242,6 @@ class Api(ApiTemplate):
206 242 :return:
207 243 '''
208 244 thrift_connect = ThriftConnect(image_server)
209   - t1 = time.time()
210 245 image_extent = image.extent
211 246
212 247 data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands,width,height)
... ... @@ -219,6 +254,33 @@ class Api(ApiTemplate):
219 254
220 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 284 def get_local_wms_data(self,image,extent,bands,height,width):
223 285 '''
224 286 获取本地数据
... ... @@ -236,7 +298,7 @@ class Api(ApiTemplate):
236 298 # 自决定金字塔等级
237 299 xysize = [img.RasterXSize, img.RasterYSize]
238 300
239   - origin_extent = image.extent
  301 + origin_extent = json.loads(image.extent)
240 302 band_data: Band = img.GetRasterBand(band)
241 303
242 304
... ... @@ -244,8 +306,7 @@ class Api(ApiTemplate):
244 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 310 empty = numpy.zeros((height,width), dtype=int) + 65536
250 311 # 空间范围相交
251 312 else:
... ... @@ -324,10 +385,12 @@ class Api(ApiTemplate):
324 385 ceng += 1
325 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 395 def get_capabilities(self,image_service:ImageService):
333 396
... ...
... ... @@ -25,6 +25,7 @@ class Image(db.Model):
25 25 null_value = Column(Integer)
26 26 available = Column(Integer)#影像是否可用,不可用可能在创建金字塔中
27 27 band_count = Column(Integer)
  28 + band_view = Column(String)
28 29 path = Column(String)
29 30 server = Column(String)
30 31
... ...
... ... @@ -3,13 +3,13 @@
3 3 #createtime: 2021/9/26
4 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 8 from thrift.transport import TSocket
9 9 from thrift.transport import TTransport
10 10 from thrift.protocol import TBinaryProtocol
11 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 14 from struct import Struct
15 15
... ...
... ... @@ -16,15 +16,15 @@ else:
16 16 from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient
17 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 22 if len(sys.argv) <= 1 or sys.argv[1] == '--help':
23 23 print('')
24 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 25 print('')
26 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 28 print(' Raster getInfo(string path)')
29 29 print(' bool buildOverview(string path)')
30 30 print(' getImageList(string path)')
... ...
... ... @@ -505,9 +505,18 @@ class getData_result(object):
505 505 if ftype == TType.STOP:
506 506 break
507 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 520 else:
512 521 iprot.skip(ftype)
513 522 else:
... ... @@ -521,8 +530,14 @@ class getData_result(object):
521 530 return
522 531 oprot.writeStructBegin('getData_result')
523 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 541 oprot.writeFieldEnd()
527 542 oprot.writeFieldStop()
528 543 oprot.writeStructEnd()
... ... @@ -542,7 +557,7 @@ class getData_result(object):
542 557 return not (self == other)
543 558 all_structs.append(getData_result)
544 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 893 if fid == 0:
879 894 if ftype == TType.LIST:
880 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 901 iprot.readListEnd()
887 902 else:
888 903 iprot.skip(ftype)
... ... @@ -899,8 +914,8 @@ class getImageList_result(object):
899 914 if self.success is not None:
900 915 oprot.writeFieldBegin('success', TType.LIST, 0)
901 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 919 oprot.writeListEnd()
905 920 oprot.writeFieldEnd()
906 921 oprot.writeFieldStop()
... ...
... ... @@ -9,21 +9,55 @@
9 9 from thrift.transport import TSocket
10 10 from thrift.transport import TTransport
11 11 from thrift.protocol import TBinaryProtocol
  12 +
  13 +from app.modules.service.image.tutorial import Calculator
12 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))
\ No newline at end of file
  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 19 def __init__(self,data_server):
20 20 host = data_server.split(":")[0]
21 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 42 self.transport: TSocket = TSocket.TSocket(host, port)
23 43 self.transport = TTransport.TBufferedTransport(self.transport)
24 44 protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
25   - self.client = ImageDataService.Client(protocol)
  45 + # self.client = ImageDataService.Client(protocol)
26 46 self.transport.open()
27 47
28 48 def close(self):
29 49 self.transport.close()
30 50
31 51 class ThriftPool:
32   - pass
\ No newline at end of file
  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
\ No newline at end of file
... ...
... ... @@ -17,6 +17,7 @@ from . import scheme_resolve
17 17 class SchemeManager(BlueprintApi):
18 18
19 19 bp = Blueprint("Scheme", __name__, url_prefix="/API/Service/Scheme")
  20 + service_type = []
20 21
21 22 @staticmethod
22 23 @bp.route('/Create', methods=['POST'])
... ...
... ... @@ -24,6 +24,15 @@ class Api(ApiTemplate):
24 24 # extent = [float(x) for x in data.get("extent").split(",")] if data.get("extent") else [0,0,0,0]
25 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 38 guid = uuid.uuid1().__str__()
... ... @@ -46,7 +55,7 @@ class Api(ApiTemplate):
46 55 rows = int(data.get("rows")),
47 56 cols = int(data.get("cols")),
48 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 61 db.session.add(tile_scheme)
... ... @@ -92,9 +101,9 @@ class Api(ApiTemplate):
92 101 {"name": "levels",
93 102 "in": "formData",
94 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 109 "responses": {
... ...
... ... @@ -32,7 +32,7 @@ class Api(ApiTemplate):
32 32 "rows": scheme.parameter.get("rows"),
33 33 "cols": scheme.parameter.get("cols"),
34 34 "levels": scheme.levels,
35   - "parameter":scheme.parameter
  35 + # "parameter":scheme.parameter
36 36 }
37 37
38 38 res["data"] = data
... ...
... ... @@ -34,6 +34,128 @@ class Api(ApiTemplate):
34 34 api_doc = {
35 35 "tags": ["服务接口"],
36 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 160 "responses": {
39 161 200: {
... ...
... ... @@ -26,9 +26,14 @@ class Api(ApiTemplate):
26 26 name = self.para.get("name")
27 27 type = self.para.get("type")
28 28
  29 + catalog_guid = self.para.get("catalog_guid")
  30 +
29 31 services = Service.query
30 32 if type:
31 33 services = services.filter_by(type=type)
  34 +
  35 + if catalog_guid:
  36 + services = services.filter_by(catalog_guid=catalog_guid)
32 37 # 并集
33 38 if alias and name:
34 39 services = services.filter(
... ... @@ -72,7 +77,12 @@ class Api(ApiTemplate):
72 77 {"name": "type",
73 78 "in": "formData",
74 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 87 "responses": {
78 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 + }
\ No newline at end of file
... ...
... ... @@ -6,8 +6,28 @@
6 6 from flasgger import swag_from
7 7 from flask import Blueprint
8 8 from app.util import BlueprintApi
  9 +from . import wms_register,wms_edit
9 10
10 11 class DataManager(BlueprintApi):
11 12
12 13 bp = Blueprint("WMS", __name__, url_prefix="/API/Service/WMS")
13   - service_type = ["WMS"]
\ No newline at end of file
  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
\ No newline at end of file
... ...
... ... @@ -53,9 +53,76 @@ class Api(ApiTemplate):
53 53 return res
54 54
55 55 api_doc = {
56   - "tags": ["影像接口"],
  56 + "tags": ["WMS接口"],
57 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 127 "responses": {
61 128 200: {
... ...
... ... @@ -12,7 +12,7 @@ import datetime
12 12 import configure
13 13 class Api(ApiTemplate):
14 14
15   - api_name = "注册WMTS服务"
  15 + api_name = "注册WMS服务"
16 16
17 17 def process(self):
18 18 # 返回结果
... ... @@ -74,7 +74,7 @@ class Api(ApiTemplate):
74 74 return res
75 75
76 76 api_doc = {
77   - "tags": ["WMTS接口"],
  77 + "tags": ["WMS接口"],
78 78 "parameters": [
79 79
80 80 {"name": "name",
... ...
... ... @@ -7,16 +7,16 @@
7 7 from flasgger import swag_from
8 8 from flask import Blueprint
9 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 14 class DataManager(BlueprintApi):
17 15
18 16 bp = Blueprint("WMTS", __name__, url_prefix="/API/Service/WMTS")
19 17
  18 + service_type = ["WMTS","MTS"]
  19 +
20 20 @staticmethod
21 21 @bp.route('/UploadOverview', methods=['POST'])
22 22 @swag_from(upload_oview.Api.api_doc)
... ... @@ -25,3 +25,23 @@ class DataManager(BlueprintApi):
25 25 上传缩略图
26 26 """
27 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 51 return res
52 52
53 53 api_doc = {
54   - "tags": ["影像接口"],
  54 + "tags": ["WMTS接口"],
55 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 133 "responses": {
59 134 200: {
... ...
... ... @@ -75,7 +75,7 @@ class FileProcess:
75 75 text_size = "{}KB".format(round(fsize / float(1024), 1))
76 76 else:
77 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 2 #author: 4N
3 3 #createtime: 2021/6/3
4 4 #email: nheweijun@sina.com
5   -from osgeo import ogr
  5 +from osgeo import ogr,gdal
6 6 from osgeo.ogr import Geometry
7 7
8 8 class GeometryAdapter:
... ... @@ -182,4 +182,36 @@ class GeometryAdapter:
182 182 g: Geometry = fea.geometry()
183 183 geom_type = g.GetGeometryType()
184 184 layer.ResetReading()
185   - return geom_type
\ No newline at end of file
  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
\ No newline at end of file
... ...
  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)
\ No newline at end of file
... ...
  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)
\ No newline at end of file
... ...
不能预览此文件类型
注册登录 后发表评论