提交 c39bdbc1612fde43b8322a43755c1f73312f1fb2

作者 nheweijun
1 个父辈 e29795f6

面向对象优化

正在显示 46 个修改的文件 包含 2804 行增加1313 行删除

要显示太多修改。

为保证性能只显示 46 of 60 个文件。

... ... @@ -192,7 +192,10 @@ class Service(db.Model):
192 192 __tablename__ = 'dmap_service'
193 193 guid = Column(String(256), primary_key=True)
194 194 name = Column(String(256))
195   - alias = Column(String(256))
  195 + # alias = Column(String(256))
  196 +
  197 + title = Column(String(256))
  198 +
196 199 #服务状态
197 200 state= Column(Integer)
198 201 create_time = Column(DateTime)
... ... @@ -217,7 +220,6 @@ class ServiceCatalog(db.Model):
217 220 '''
218 221 __tablename__ = 'dmap_service_catalog'
219 222 guid = Column(String(256), primary_key=True)
220   - database_guid = Column(String(256), ForeignKey('dmap_database.guid'))
221 223 pguid = Column(String(256))
222 224 path = Column(Text)
223 225 name = Column(String(256))
... ...
... ... @@ -8,7 +8,7 @@ from app.util import BlueprintApi
8 8
9 9 from flask import send_from_directory
10 10 import os
11   -from . import data_download
  11 +from . import data_download,data_download_task
12 12 from . import get_meta
13 13 from . import data_entry_by_meta
14 14 from . import get_data_list
... ... @@ -64,6 +64,15 @@ class DataManager(BlueprintApi):
64 64 """
65 65 return data_download.Api().result
66 66
  67 + @staticmethod
  68 + @bp.route('/DataDownloadTask', methods=['POST'])
  69 + @swag_from(data_download_task.Api.api_doc)
  70 + def api_data_download_task():
  71 + """
  72 + 下载数据任务
  73 + """
  74 + return data_download_task.Api().result
  75 +
67 76
68 77 @staticmethod
69 78 @bp.route('/GetMeta', methods=['POST'])
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2020/11/27
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from app.models import *
  8 +
  9 +import traceback
  10 +
  11 +from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature
  12 +from osgeo import gdal,ogr
  13 +import os
  14 +import uuid
  15 +import configure
  16 +from app.util.component.ApiTemplate import ApiTemplate
  17 +from app.util.component.PGUtil import PGUtil
  18 +from app.util.component.ZipUtil import ZipUtil
  19 +import multiprocessing
  20 +
  21 +class Api(ApiTemplate):
  22 +
  23 + def process(self):
  24 +
  25 + res = {}
  26 + #获取参数
  27 + try:
  28 +
  29 + task_guid = uuid.uuid1().__str__()
  30 + download_process = multiprocessing.Process(target=self.download, args=(task_guid,self.para))
  31 +
  32 + task = Task(guid=task_guid,
  33 + name="{}下载".format(self.para.get("table_name")),
  34 + create_time=datetime.datetime.now(),
  35 + state=0,
  36 + task_type=4,
  37 + creator=self.para.get("creator"),
  38 + file_name=None,
  39 + process="数据下载中",
  40 + database_guid=self.para.get("database_guid"))
  41 +
  42 + db.session.add(task)
  43 + db.session.commit()
  44 + download_process.start()
  45 +
  46 + res["data"] = "下载任务已提交!"
  47 + res["state"] = True
  48 +
  49 + except Exception as e:
  50 + raise e
  51 + return res
  52 +
  53 +
  54 + def download(self,task_guid,para):
  55 +
  56 + sys_session = None
  57 + ds: DataSource = None
  58 +
  59 + # 设置编码
  60 + encoding = para.get("encoding")
  61 + if encoding:
  62 + gdal.SetConfigOption("SHAPE_ENCODING", encoding)
  63 + else:
  64 + gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
  65 +
  66 + try:
  67 +
  68 + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
  69 +
  70 + table_names = para.get("table_name").split(",")
  71 + database_guid = para.get("database_guid")
  72 + database = sys_session.query(Database).filter_by(guid=database_guid).one_or_none()
  73 + if not database:
  74 + raise Exception("数据库不存在!")
  75 +
  76 + ds: DataSource = PGUtil.open_pg_data_source(0, DES.decode(database.sqlalchemy_uri))
  77 +
  78 + download_type = para.get("download_type")
  79 +
  80 + data = None
  81 + if download_type.__eq__("shp"):
  82 + data = self.download_shp(table_names, ds)
  83 + if download_type.__eq__("gdb"):
  84 + data = self.download_gdb(sys_session,table_names, ds, database_guid)
  85 +
  86 + sys_session.query(Task).filter_by(guid=task_guid).update({"state":1,"update_time":datetime.datetime.now(),
  87 + "process" : "下载完成",
  88 + "parameter":data[0]["download_url"]})
  89 + sys_session.commit()
  90 +
  91 +
  92 + except Exception as e:
  93 + try:
  94 + sys_session.query(Task).filter_by(guid=task_guid).update({"state": -1,"update_time":datetime.datetime.now(),
  95 + "process": "下载失败"})
  96 +
  97 + message = "{} {}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), e.__str__())
  98 + task_process_guid = uuid.uuid1().__str__()
  99 + task_process = Process(guid=task_process_guid, message=message, time=datetime.datetime.now(),
  100 + task_guid=task_guid)
  101 + sys_session.add(task_process)
  102 + sys_session.commit()
  103 + except Exception as ee:
  104 + print(traceback.format_exc())
  105 + raise e
  106 + finally:
  107 + try:
  108 + if ds:
  109 + ds.Destroy()
  110 + if sys_session:
  111 + sys_session.close()
  112 + except:
  113 + print(traceback.format_exc())
  114 +
  115 +
  116 + def download_shp(self,table_names,ds):
  117 + data = []
  118 + for table_name in table_names:
  119 + url = self.download_one(ds, table_name)
  120 + data.append({"name": table_name, "download_url": url})
  121 + return data
  122 +
  123 + def download_one(self,ds,table_name):
  124 +
  125 + layer: Layer = ds.GetLayerByName(table_name)
  126 + driver = ogr.GetDriverByName("ESRI Shapefile")
  127 + uuid_ = uuid.uuid1().__str__()
  128 + parent = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
  129 + dirpath = os.path.join(parent, "file_tmp", uuid_)
  130 + os.makedirs(dirpath)
  131 + data_source: DataSource = driver.CreateDataSource(dirpath + "/{}.shp".format(table_name))
  132 + # data_source.CopyLayer(layer, table_name)
  133 +
  134 + fid = layer.GetFIDColumn()
  135 + pg_layer: Layer = data_source.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType())
  136 + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]
  137 +
  138 + pg_layer.CreateFields(schema)
  139 + layer.ResetReading()
  140 + for feature in layer:
  141 + pg_layer.CreateFeature(feature)
  142 +
  143 + data_source.Destroy()
  144 +
  145 +
  146 + ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name+"_"+uuid_) + ".zip", [dirpath])
  147 +
  148 + return "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(table_name+"_"+uuid_ + ".zip")
  149 +
  150 +
  151 + def download_gdb(self,sys_session,table_names,ds,database_guid):
  152 + ogr.RegisterAll()
  153 + data = []
  154 + gdal.UseExceptions()
  155 + gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
  156 +
  157 + # 创建一个gdb datasource
  158 + gdb_driver = ogr.GetDriverByName('FileGDB')
  159 + uuid_ = uuid.uuid1().__str__()
  160 + parent = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
  161 + gdb_path = os.path.join(parent, "file_tmp", uuid_+".gdb")
  162 +
  163 + gdb_ds: DataSource = gdb_driver.CreateDataSource(gdb_path)
  164 +
  165 +
  166 + for table_name in table_names:
  167 +
  168 + layer: Layer = ds.GetLayerByName(table_name)
  169 + table = sys_session.query(Table).filter_by(name=table_name, database_guid=database_guid).one_or_none()
  170 + feature_defn: FeatureDefn = layer.GetLayerDefn()
  171 +
  172 + for i in range(feature_defn.GetFieldCount()):
  173 + field_defn:FieldDefn = feature_defn.GetFieldDefn(i)
  174 + field_alias = sys_session.query(Columns).filter_by(table_guid=table.guid,name=field_defn.GetName()).one_or_none().alias
  175 + field_defn.SetAlternativeName(field_alias)
  176 +
  177 + table_alias= table.alias
  178 +
  179 + # if is_chinese(table_name):
  180 + # if not table_alias:
  181 + # table_alias = table_name
  182 + # table_name = "table{}".format(table_name.__hash__())
  183 +
  184 + fid = layer.GetFIDColumn()
  185 + pg_layer: Layer = gdb_ds.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType(),["LAYER_ALIAS={}".format(table_alias)])
  186 + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]
  187 + # schema = layer.schema
  188 + pg_layer.CreateFields(schema)
  189 +
  190 +
  191 + # gdb 不支持fid=0的要素,所以识别到后要+1
  192 + offset = 0
  193 + f1:Feature = layer.GetNextFeature()
  194 + if f1:
  195 + if f1.GetFID().__eq__(0):
  196 + offset = 1
  197 + layer.ResetReading()
  198 + for feature in layer:
  199 + feature.SetFID(feature.GetFID()+offset)
  200 + pg_layer.CreateFeature(feature)
  201 +
  202 +
  203 + # gdb_ds.CopyLayer(layer, table_name,["LAYER_ALIAS={}".format(table_alias)])
  204 +
  205 + gdb_ds.Destroy()
  206 + ZipUtil.create_zip(gdb_path + ".zip", [gdb_path])
  207 + data.append({"name": ",".join(table_names), "download_url": "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(uuid_+".gdb" + ".zip")})
  208 +
  209 +
  210 + return data
  211 +
  212 +
  213 +
  214 +
  215 + api_doc={
  216 + "tags":["IO接口"],
  217 + "description":"下载数据",
  218 + "parameters":[
  219 + {"name": "table_name",
  220 + "in": "formData",
  221 + "type":"string","description":"支持多图层下载,以逗号相隔","required":"true"},
  222 + {"name": "encoding",
  223 + "in": "formData",
  224 + "type": "string",
  225 + "enum":["GBK","UTF-8"]},
  226 + {"name": "download_type",
  227 + "in": "formData",
  228 + "type": "string",
  229 + "enum": ["shp", "gdb"],"required":"true"
  230 + },
  231 + {"name": "database_guid",
  232 + "in": "formData",
  233 + "type": "string","required":"true"
  234 + },
  235 + {"name": "creator",
  236 + "in": "formData",
  237 + "type": "string"
  238 + }
  239 + ],
  240 + "responses":{
  241 + 200:{
  242 + "schema":{
  243 + "properties":{
  244 + "content":{
  245 + "type": "string",
  246 + "description": "The name of the user"
  247 + }
  248 + }
  249 + }
  250 + }
  251 + }
  252 +}
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/11
  4 +#email: nheweijun@sina.com
  5 +
  6 +from app.models import Task
  7 +import configure
  8 +from app.models import InsertingLayerName, Database, DES, Task,Columns
  9 +from sqlalchemy.orm import Session
  10 +import multiprocessing
  11 +from app.util.component.EntryDataVacuate import EntryDataVacuate
  12 +import json
  13 +from sqlalchemy import distinct
  14 +import uuid
  15 +from osgeo.ogr import DataSource
  16 +from app.util.component.StructuredPrint import StructurePrint
  17 +from app.util.component.PGUtil import PGUtil
  18 +import time
  19 +import datetime
  20 +import traceback
  21 +from app.models import Table, Database, DES,Task,db,TableVacuate
  22 +from app.util.component.ApiTemplate import ApiTemplate
  23 +from app.util.component.PGUtil import PGUtil
  24 +from app.util.component.EntryDataVacuate import Process
  25 +from app.util.component.SQLUtil import SQLUtil
  26 +import multiprocessing
  27 +import uuid
  28 +import configure
  29 +from osgeo.ogr import DataSource,Layer,Geometry,FieldDefn,FeatureDefn
  30 +from osgeo import ogr
  31 +from app.util.component.StructuredPrint import StructurePrint
  32 +from app.util.component.VacuateConf import VacuateConf
  33 +import datetime
  34 +import traceback
  35 +from app.models import Table, Database, DES,Task,db,TableVacuate,Process
  36 +
  37 +from sqlalchemy.engine import ResultProxy
  38 +from app.util.component.ApiTemplate import ApiTemplate
  39 +
  40 +from app.util.component.StructuredPrint import StructurePrint
  41 +from app.util.component.PGUtil import PGUtil
  42 +import multiprocessing
  43 +import uuid
  44 +import configure
  45 +from osgeo.ogr import DataSource,Layer,Geometry
  46 +from osgeo import ogr
  47 +from app.util.component.VacuateConf import VacuateConf
  48 +from app.util.component.GeometryAdapter import GeometryAdapter
  49 +from app.models import *
  50 +
  51 +import traceback
  52 +
  53 +from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature
  54 +from osgeo import gdal,ogr
  55 +import os
  56 +import uuid
  57 +import configure
  58 +from app.util.component.ApiTemplate import ApiTemplate
  59 +from app.util.component.PGUtil import PGUtil
  60 +from app.util.component.ZipUtil import ZipUtil
  61 +import multiprocessing
  62 +
  63 +
  64 +
  65 +def task_consumer():
  66 +
  67 + running_dict = {}
  68 + sys_session: Session = PGUtil.get_db_session(
  69 + configure.SQLALCHEMY_DATABASE_URI)
  70 +
  71 + while True:
  72 +
  73 + try:
  74 + time.sleep(3)
  75 +
  76 + # 已经结束的进程 从监测中删除
  77 + remove_process = []
  78 +
  79 + # structured_print(running_dict.__len__().__str__())
  80 +
  81 + for process, layer_names in running_dict.items():
  82 + if not process.is_alive():
  83 + for l in layer_names:
  84 + inserted = sys_session.query(
  85 + InsertingLayerName).filter_by(name=l).one_or_none()
  86 + if inserted:
  87 + sys_session.delete(inserted)
  88 + sys_session.commit()
  89 + remove_process.append(process)
  90 + for process in remove_process:
  91 + running_dict.pop(process)
  92 +
  93 + # StructurePrint().print("listening...")
  94 +
  95 + # 入库进程少于阈值,开启入库进程
  96 +
  97 + inter_size = sys_session.query(
  98 + distinct(InsertingLayerName.task_guid)).count()
  99 +
  100 + if inter_size < configure.entry_data_thread:
  101 + # 锁表啊
  102 + ready_task: Task = sys_session.query(Task).filter_by(state=0).order_by(
  103 + Task.create_time).with_lockmode("update").limit(1).one_or_none()
  104 + if ready_task:
  105 +
  106 + if ready_task.task_type == 1:
  107 + task_entry_data(ready_task,sys_session,running_dict)
  108 + elif ready_task.task_type == 2:
  109 + task_table_refresh()
  110 + elif ready_task.task_type == 3:
  111 + task_vacuate()
  112 + elif ready_task.task_type == 4:
  113 + task_download()
  114 +
  115 + else:
  116 + # 解表啊
  117 + sys_session.commit()
  118 + except Exception as e:
  119 + sys_session.commit()
  120 + StructurePrint().print(e.__str__(), "error")
  121 +
  122 +
  123 +
  124 +def task_download(para,task_guid):
  125 + sys_session = None
  126 + ds: DataSource = None
  127 +
  128 + # 设置编码
  129 + encoding = para.get("encoding")
  130 + if encoding:
  131 + gdal.SetConfigOption("SHAPE_ENCODING", encoding)
  132 + else:
  133 + gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
  134 +
  135 + try:
  136 +
  137 + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
  138 +
  139 + table_names = para.get("table_name").split(",")
  140 + database_guid = para.get("database_guid")
  141 + database = sys_session.query(Database).filter_by(guid=database_guid).one_or_none()
  142 + if not database:
  143 + raise Exception("数据库不存在!")
  144 +
  145 + ds: DataSource = PGUtil.open_pg_data_source(0, DES.decode(database.sqlalchemy_uri))
  146 +
  147 + download_type = para.get("download_type")
  148 +
  149 + data = None
  150 + if download_type.__eq__("shp"):
  151 + data = download_shp(table_names, ds)
  152 + if download_type.__eq__("gdb"):
  153 + data = download_gdb(sys_session, table_names, ds, database_guid)
  154 +
  155 + sys_session.query(Task).filter_by(guid=task_guid).update({"state": 1, "update_time": datetime.datetime.now(),
  156 + "process": "下载完成",
  157 + "parameter": data[0]["download_url"]})
  158 + sys_session.commit()
  159 +
  160 +
  161 + except Exception as e:
  162 + try:
  163 + sys_session.query(Task).filter_by(guid=task_guid).update(
  164 + {"state": -1, "update_time": datetime.datetime.now(),
  165 + "process": "下载失败"})
  166 +
  167 + message = "{} {}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), e.__str__())
  168 + task_process_guid = uuid.uuid1().__str__()
  169 + task_process = Process(guid=task_process_guid, message=message, time=datetime.datetime.now(),
  170 + task_guid=task_guid)
  171 + sys_session.add(task_process)
  172 + sys_session.commit()
  173 + except Exception as ee:
  174 + print(traceback.format_exc())
  175 + raise e
  176 + finally:
  177 + try:
  178 + if ds:
  179 + ds.Destroy()
  180 + if sys_session:
  181 + sys_session.close()
  182 + except:
  183 + print(traceback.format_exc())
  184 +
  185 +
  186 +def download_shp(table_names, ds):
  187 + data = []
  188 + for table_name in table_names:
  189 + url = download_one(ds, table_name)
  190 + data.append({"name": table_name, "download_url": url})
  191 + return data
  192 +
  193 +
  194 +def download_one( ds, table_name):
  195 + layer: Layer = ds.GetLayerByName(table_name)
  196 + driver = ogr.GetDriverByName("ESRI Shapefile")
  197 + uuid_ = uuid.uuid1().__str__()
  198 + parent = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
  199 + dirpath = os.path.join(parent, "file_tmp", uuid_)
  200 + os.makedirs(dirpath)
  201 + data_source: DataSource = driver.CreateDataSource(dirpath + "/{}.shp".format(table_name))
  202 + # data_source.CopyLayer(layer, table_name)
  203 +
  204 + fid = layer.GetFIDColumn()
  205 + pg_layer: Layer = data_source.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType())
  206 + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]
  207 +
  208 + pg_layer.CreateFields(schema)
  209 + layer.ResetReading()
  210 + for feature in layer:
  211 + pg_layer.CreateFeature(feature)
  212 +
  213 + data_source.Destroy()
  214 +
  215 + ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name + "_" + uuid_) + ".zip", [dirpath])
  216 +
  217 + return "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(table_name + "_" + uuid_ + ".zip")
  218 +
  219 +
  220 +def download_gdb( sys_session, table_names, ds, database_guid):
  221 + ogr.RegisterAll()
  222 + data = []
  223 + gdal.UseExceptions()
  224 + gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
  225 +
  226 + # 创建一个gdb datasource
  227 + gdb_driver = ogr.GetDriverByName('FileGDB')
  228 + uuid_ = uuid.uuid1().__str__()
  229 + parent = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
  230 + gdb_path = os.path.join(parent, "file_tmp", uuid_ + ".gdb")
  231 +
  232 + gdb_ds: DataSource = gdb_driver.CreateDataSource(gdb_path)
  233 +
  234 + for table_name in table_names:
  235 +
  236 + layer: Layer = ds.GetLayerByName(table_name)
  237 + table = sys_session.query(Table).filter_by(name=table_name, database_guid=database_guid).one_or_none()
  238 + feature_defn: FeatureDefn = layer.GetLayerDefn()
  239 +
  240 + for i in range(feature_defn.GetFieldCount()):
  241 + field_defn: FieldDefn = feature_defn.GetFieldDefn(i)
  242 + field_alias = sys_session.query(Columns).filter_by(table_guid=table.guid,
  243 + name=field_defn.GetName()).one_or_none().alias
  244 + field_defn.SetAlternativeName(field_alias)
  245 +
  246 + table_alias = table.alias
  247 +
  248 + # if is_chinese(table_name):
  249 + # if not table_alias:
  250 + # table_alias = table_name
  251 + # table_name = "table{}".format(table_name.__hash__())
  252 +
  253 + fid = layer.GetFIDColumn()
  254 + pg_layer: Layer = gdb_ds.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType(),
  255 + ["LAYER_ALIAS={}".format(table_alias)])
  256 + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]
  257 + # schema = layer.schema
  258 + pg_layer.CreateFields(schema)
  259 +
  260 + # gdb 不支持fid=0的要素,所以识别到后要+1
  261 + offset = 0
  262 + f1: Feature = layer.GetNextFeature()
  263 + if f1:
  264 + if f1.GetFID().__eq__(0):
  265 + offset = 1
  266 + layer.ResetReading()
  267 + for feature in layer:
  268 + feature.SetFID(feature.GetFID() + offset)
  269 + pg_layer.CreateFeature(feature)
  270 +
  271 + # gdb_ds.CopyLayer(layer, table_name,["LAYER_ALIAS={}".format(table_alias)])
  272 +
  273 + gdb_ds.Destroy()
  274 + ZipUtil.create_zip(gdb_path + ".zip", [gdb_path])
  275 + data.append({"name": ",".join(table_names),
  276 + "download_url": "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(
  277 + uuid_ + ".gdb" + ".zip")})
  278 +
  279 + return data
  280 +
  281 +
  282 +def task_entry_data(ready_task,sys_session,running_dict):
  283 + try:
  284 + parameter = json.loads(ready_task.parameter)
  285 + StructurePrint().print("检测到入库任务")
  286 + ready_task.state = 2
  287 + ready_task.process = "入库中"
  288 + sys_session.commit()
  289 +
  290 + metas: list = json.loads(
  291 + parameter.get("meta").__str__())
  292 + parameter["meta"] = metas
  293 +
  294 + database = sys_session.query(Database).filter_by(
  295 + guid=ready_task.database_guid).one_or_none()
  296 + pg_ds: DataSource = PGUtil.open_pg_data_source(
  297 + 1, DES.decode(database.sqlalchemy_uri))
  298 +
  299 + this_task_layer = []
  300 + for meta in metas:
  301 + overwrite = parameter.get("overwrite", "no")
  302 +
  303 + for layer_name_origin, layer_name in meta.get("layer").items():
  304 + origin_name = layer_name
  305 + no = 1
  306 +
  307 + while (overwrite.__eq__("no") and pg_ds.GetLayerByName(layer_name)) or sys_session.query(
  308 + InsertingLayerName).filter_by(name=layer_name).one_or_none():
  309 + layer_name = origin_name + "_{}".format(no)
  310 + no += 1
  311 +
  312 + # 添加到正在入库的列表中
  313 + iln = InsertingLayerName(guid=uuid.uuid1().__str__(),
  314 + task_guid=ready_task.guid,
  315 + name=layer_name)
  316 +
  317 + sys_session.add(iln)
  318 + sys_session.commit()
  319 + this_task_layer.append(layer_name)
  320 + # 修改表名
  321 + meta["layer"][layer_name_origin] = layer_name
  322 +
  323 + pg_ds.Destroy()
  324 + entry_data_process = multiprocessing.Process(
  325 + target=EntryDataVacuate().entry, args=(parameter,))
  326 + entry_data_process.start()
  327 + running_dict[entry_data_process] = this_task_layer
  328 + except Exception as e:
  329 + sys_session.query(Task).filter_by(guid=ready_task.guid).update(
  330 + {"state": -1, "process": "入库失败"})
  331 + sys_session.commit()
  332 + StructurePrint().print(e.__str__(), "error")
  333 +
  334 +
  335 +def task_table_refresh(database,task_guid):
  336 + pg_ds =None
  337 + sys_ds =None
  338 + data_session=None
  339 + result = {}
  340 + sys_session = None
  341 + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri))
  342 +
  343 + try:
  344 + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
  345 + sys_ds = PGUtil.open_pg_data_source(0,configure.SQLALCHEMY_DATABASE_URI)
  346 +
  347 + this_time = datetime.datetime.now()
  348 + database_guid = database.guid
  349 +
  350 + # 已注册空间表
  351 + spatial_tables = sys_session.query(Table).order_by(Table.create_time.desc()).filter_by(database_guid=database_guid).filter(
  352 + Table.table_type != 0).all()
  353 +
  354 + # 已注册空间表名
  355 + spatial_tables_names = [table.name for table in spatial_tables]
  356 +
  357 + # 实体库datasource
  358 + pg_ds: DataSource = PGUtil.open_pg_data_source(1, DES.decode(database.sqlalchemy_uri))
  359 +
  360 + # 更新空间表
  361 + # 增加表
  362 + db_tables_names = add_spatail_table(database, pg_ds, sys_session,spatial_tables_names, this_time,db_tuple)# 实体库中空间表名
  363 +
  364 + # 删除/修改表
  365 + edit_spatial_table(pg_ds, sys_session,spatial_tables, db_tables_names, this_time,db_tuple)
  366 +
  367 + # 空间表处理完毕
  368 + sys_session.commit()
  369 +
  370 +
  371 + # 空间表处理完毕
  372 + sys_session.commit()
  373 +
  374 + # 注册普通表
  375 + # 实体库连接
  376 + data_session: Session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri))
  377 +
  378 + # 处理后空间表
  379 + spatial_tables = sys_session.query(Table).order_by(Table.create_time.desc()).filter_by(database_guid=database_guid).filter(
  380 + Table.table_type != 0).all()
  381 + # 处理后空间表名
  382 + spatial_tables_names = [table.name for table in spatial_tables]
  383 +
  384 + # 原有普通表
  385 + common_tables = sys_session.query(Table).order_by(Table.create_time.desc()).filter_by(database_guid=database_guid).filter(
  386 + Table.table_type == 0).all()
  387 + # 原有普通表 名
  388 + origin_common_tables_name = [table.name for table in common_tables]
  389 +
  390 + # 现有普通表
  391 + real_common_tables_name = []
  392 +
  393 + # 只注册public中的表
  394 + common_result = data_session.execute(
  395 + "select relname as tabname from pg_class c where relkind = 'r' and relnamespace=2200 and relname not like 'pg_%' and relname not like 'sql_%' order by relname").fetchall()
  396 + for re in common_result:
  397 + table_name = re[0]
  398 + if table_name not in spatial_tables_names and (not table_name.__contains__("_vacuate_")):
  399 + real_common_tables_name.append(table_name)
  400 +
  401 + # 增加新普通表
  402 +
  403 + add_common_table(data_session, sys_session, database_guid, real_common_tables_name, origin_common_tables_name,
  404 + this_time,db_tuple)
  405 +
  406 + # 删除、修改普通表
  407 + edit_common_table(data_session,sys_session, database_guid, real_common_tables_name, origin_common_tables_name,
  408 + this_time,db_tuple)
  409 +
  410 + sys_session.commit()
  411 + result["data"] = "刷新数据成功!"
  412 + result["state"] = 1
  413 + sys_session.query(Task).filter_by(guid=task_guid).update(
  414 + {"state": 1, "update_time": datetime.datetime.now(),"process":"更新成功"})
  415 + sys_session.commit()
  416 +
  417 + except Exception as e:
  418 + try:
  419 + print(traceback.format_exc())
  420 + sys_session.query(Task).filter_by(guid=task_guid).update(
  421 + {"state": -1, "update_time": datetime.datetime.now(),"process":"更新失败"})
  422 + message = "{} {}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), e.__str__())
  423 + task_process_guid = uuid.uuid1().__str__()
  424 + task_process = Process(guid=task_process_guid, message=message, time=datetime.datetime.now(),
  425 + task_guid=task_guid)
  426 + sys_session.add(task_process)
  427 + sys_session.commit()
  428 + except Exception as ee:
  429 + print(traceback.format_exc())
  430 + finally:
  431 + if pg_ds:
  432 + pg_ds.Destroy()
  433 + if data_session:
  434 + data_session.close()
  435 + if sys_session:
  436 + sys_session.close()
  437 + if sys_ds:
  438 + sys_ds.Destroy()
  439 + return result
  440 +
  441 +def add_spatail_table(database,pg_ds,sys_session,spatial_tables_names,this_time,db_tuple):
  442 + '''
  443 + 注册新增空间表
  444 + :param database:
  445 + :param pg_ds:
  446 + :param spatial_tables_names: 已注册空间表名
  447 + :param this_time:
  448 + :return: 实体库中空间表名
  449 + '''
  450 +
  451 + db_tables_names=[]
  452 +
  453 + for i in range(pg_ds.GetLayerCount()):
  454 + layer: Layer = pg_ds.GetLayer(i)
  455 + geom_column = layer.GetGeometryColumn()
  456 + db_tables_names.append(layer.GetName())
  457 + if not geom_column:
  458 + continue
  459 + if layer.GetName() not in spatial_tables_names:
  460 + l_name = layer.GetName()
  461 +
  462 + try:
  463 + # 只注册public的空间表,其他表空间的表名会有.
  464 + if layer.GetName().__contains__("."):
  465 + continue
  466 + # 略过抽稀表
  467 + if layer.GetName().__contains__("_vacuate_"):
  468 + continue
  469 +
  470 + # 没有权限的表跳过
  471 + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds):
  472 + StructurePrint().print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn")
  473 + continue
  474 +
  475 +
  476 + # 范围统计和数量统计以100w为界限
  477 + query_count_layer: Layer = pg_ds.ExecuteSQL(
  478 + '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(
  479 + l_name))
  480 +
  481 + feature_count = query_count_layer.GetFeature(0).GetField("ec")
  482 + # 要素少于100w可以精确统计
  483 + if feature_count < 1000000:
  484 + feature_count = layer.GetFeatureCount()
  485 + ext = layer.GetExtent()
  486 + else:
  487 + query_ext_layer: Layer = pg_ds.ExecuteSQL(
  488 + "select geometry(ST_EstimatedExtent('public', '{}','{}'))".format(l_name,
  489 + layer.GetGeometryColumn()))
  490 + ext = query_ext_layer.GetExtent()
  491 + if ext[0] < 360:
  492 + ext = [round(e, 6) for e in ext]
  493 + else:
  494 + ext = [round(e, 2) for e in ext]
  495 + extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3])
  496 +
  497 + StructurePrint().print("空间表增加!")
  498 +
  499 + geom_type = GeometryAdapter.get_geometry_type(layer)
  500 + except:
  501 + StructurePrint().print("表{}注册失败!".format(l_name), "warn")
  502 + continue
  503 +
  504 + table_guid = uuid.uuid1().__str__()
  505 + table = Table(guid=table_guid,
  506 + database_guid=database.guid,
  507 + # alias=layer.GetName(),
  508 + name=layer.GetName(), create_time=this_time, update_time=this_time,
  509 + table_type=GeometryAdapter.get_table_type(geom_type),
  510 + extent=extent,
  511 + feature_count=feature_count
  512 + )
  513 + sys_session.add(table)
  514 + feature_defn: FeatureDefn = layer.GetLayerDefn()
  515 +
  516 + for i in range(feature_defn.GetFieldCount()):
  517 + field_defn: FieldDefn = feature_defn.GetFieldDefn(i)
  518 + field_name = field_defn.GetName().lower()
  519 + field_alias = field_name if field_defn.GetAlternativeName() is None or field_defn.GetAlternativeName().__eq__(
  520 + "") else field_defn.GetAlternativeName()
  521 + column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid,
  522 + name=field_name, alias=field_alias, create_time=this_time, update_time=this_time)
  523 + sys_session.add(column)
  524 + return db_tables_names
  525 +
  526 +def deal_vacuate_table(sys_ds,sys_session,database_guid):
  527 +
  528 +
  529 + for i in range(sys_ds.GetLayerCount()):
  530 + layer: Layer = sys_ds.GetLayer(i)
  531 + geom_column = layer.GetGeometryColumn()
  532 +
  533 + if not geom_column:
  534 + continue
  535 +
  536 +
  537 +
  538 + if layer.GetName().__contains__("_vacuate_"):
  539 + l_name = layer.GetName()
  540 +
  541 + base_layer_name = l_name.split("_vacuate_")[0].split("_")[1]
  542 +
  543 + level = l_name.split("_")[-2]
  544 +
  545 + pixel_distance_str: str ="0"
  546 + try:
  547 + pixel_distance_str: str = l_name.split("_")[-1]
  548 + if pixel_distance_str.startswith("0"):
  549 + pixel_distance_str = "0.{}".format(pixel_distance_str)
  550 + except:
  551 + pass
  552 +
  553 + base_table =sys_session.query(Table).filter_by(name=base_layer_name,database_guid=database_guid).one_or_none()
  554 + if base_table:
  555 + if not sys_session.query(TableVacuate).filter_by(table_guid=base_table.guid,name=l_name).one_or_none():
  556 + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),
  557 + table_guid=base_table.guid,
  558 + level=level,
  559 + name=l_name,
  560 + pixel_distance=float(pixel_distance_str))
  561 + sys_session.add(table_vacuate)
  562 +
  563 + sys_session.query(Table).filter_by(guid=base_table.guid).update({"is_vacuate": 1})
  564 + else:
  565 + kk=1
  566 +
  567 +
  568 +
  569 +def edit_spatial_table(pg_ds,sys_session,spatial_tables,db_tables_names,this_time,db_tuple):
  570 +
  571 +
  572 +
  573 + for table in spatial_tables:
  574 +
  575 + # 删除表
  576 + if table.name not in db_tables_names:
  577 + StructurePrint().print("空间表减少!")
  578 + sys_session.delete(table)
  579 + # 修改表
  580 + else:
  581 + layer: Layer = pg_ds.GetLayerByName(table.name)
  582 + l_name = layer.GetName()
  583 +
  584 + # 只注册public的空间表,其他表空间的表名会有.
  585 + if layer.GetName().__contains__("."):
  586 + continue
  587 +
  588 + if layer.GetName().__contains__("_vacuate_"):
  589 + continue
  590 +
  591 + # 没有权限的表跳过
  592 + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds):
  593 + StructurePrint().print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn")
  594 + sys_session.delete(table)
  595 + continue
  596 +
  597 + columns = table.relate_columns
  598 + columns_names = [column.name for column in columns]
  599 + feature_defn: FeatureDefn = layer.GetLayerDefn()
  600 + db_columns_names = []
  601 +
  602 + # 增加列
  603 + for i in range(feature_defn.GetFieldCount()):
  604 + field_defn: FieldDefn = feature_defn.GetFieldDefn(i)
  605 + field_name = field_defn.GetName().lower()
  606 + db_columns_names.append(field_name)
  607 +
  608 + if field_name not in columns_names:
  609 + StructurePrint().print("{}空间表属性增加!".format(table.name))
  610 + field_alias = field_name if field_defn.GetAlternativeName() is None or field_defn.GetAlternativeName().__eq__(
  611 + "") else field_defn.GetAlternativeName()
  612 + column = Columns(guid=uuid.uuid1().__str__(), table_guid=table.guid,
  613 + name=field_name, alias=field_alias, create_time=this_time,
  614 + update_time=this_time)
  615 + sys_session.add(column)
  616 +
  617 + # 删除列
  618 + for column in columns:
  619 + if column.name not in db_columns_names:
  620 + StructurePrint().print("{}空间表属性减少!".format(table.name))
  621 + sys_session.delete(column)
  622 +
  623 + # 范围统计和数量统计以100w为界限
  624 + query_count_layer: Layer = pg_ds.ExecuteSQL(
  625 + '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(
  626 + l_name))
  627 + feature_count = query_count_layer.GetFeature(0).GetField("ec")
  628 + # 要素少于100w可以精确统计
  629 + if feature_count < 1000000:
  630 + feature_count = layer.GetFeatureCount()
  631 + ext = layer.GetExtent()
  632 +
  633 + else:
  634 + query_ext_layer: Layer = pg_ds.ExecuteSQL(
  635 + "select geometry(ST_EstimatedExtent('public', '{}','{}'))".format(l_name,
  636 + layer.GetGeometryColumn()))
  637 + ext = query_ext_layer.GetExtent()
  638 + if ext[0] < 360:
  639 + ext = [round(e, 6) for e in ext]
  640 + else:
  641 + ext = [round(e, 2) for e in ext]
  642 + extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3])
  643 +
  644 + # 修改要素量
  645 + if not table.feature_count.__eq__(feature_count):
  646 + StructurePrint().print("{}空间表要素!".format(table.name))
  647 + sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": feature_count,
  648 + "extent": extent})
  649 +
  650 +
  651 +def add_common_table(data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time,db_tuple):
  652 + for table_name in real_common_tables_name:
  653 + if table_name not in origin_common_tables_name:
  654 + StructurePrint().print("{}非空间表增加!".format(table_name))
  655 + table_guid = uuid.uuid1().__str__()
  656 +
  657 +
  658 + # 没有权限的表跳过
  659 + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], data_session):
  660 + StructurePrint().print("用户{}对表{}没有select权限!".format(db_tuple[0], table_name), "warn")
  661 + continue
  662 +
  663 + count = data_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0]
  664 +
  665 + table = Table(guid=table_guid,
  666 + database_guid=database_guid,
  667 + name=table_name, create_time=this_time, update_time=this_time,
  668 + table_type=0,
  669 + feature_count=count
  670 + )
  671 +
  672 + sys_session.add(table)
  673 +
  674 + sql = '''
  675 + SELECT
  676 + a.attnum,
  677 + a.attname AS field
  678 + FROM
  679 + pg_class c,
  680 + pg_attribute a,
  681 + pg_type t
  682 + WHERE
  683 + c.relname = '{}'
  684 + and a.attnum > 0
  685 + and a.attrelid = c.oid
  686 + and a.atttypid = t.oid
  687 + ORDER BY a.attnum
  688 + '''.format(table_name)
  689 +
  690 + cols = data_session.execute(sql).fetchall()
  691 + for col in cols:
  692 + column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid,
  693 + name=col[1], create_time=this_time, update_time=this_time)
  694 + sys_session.add(column)
  695 +
  696 + # 删除不存在的表
  697 + for n in origin_common_tables_name:
  698 + if n not in real_common_tables_name:
  699 + tables = Table.query.filter_by(name=n).filter_by(database_guid=database_guid).all()
  700 + for table in tables:
  701 + sys_session.delete(table)
  702 +
  703 +def edit_common_table(data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time,db_tuple):
  704 + for table_name in origin_common_tables_name:
  705 + tables = sys_session.query(Table).filter_by(name=table_name).filter_by(database_guid=database_guid).all()
  706 + for table in tables:
  707 + if table_name not in real_common_tables_name:
  708 + StructurePrint().print("{}非空间表减少!".format(table_name))
  709 + sys_session.delete(table)
  710 + # 修改表
  711 + else:
  712 +
  713 + # 没有权限的表删除
  714 + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], data_session):
  715 + StructurePrint().print("用户{}对表{}没有select权限!".format(db_tuple[0], table_name), "warn")
  716 + sys_session.delete(table)
  717 + continue
  718 +
  719 + columns = table.relate_columns
  720 + columns_names = [column.name for column in columns]
  721 +
  722 + sql = '''
  723 + SELECT
  724 + a.attnum,
  725 + a.attname AS field
  726 + FROM
  727 + pg_class c,
  728 + pg_attribute a,
  729 + pg_type t
  730 + WHERE
  731 + c.relname = '{}'
  732 + and a.attnum > 0
  733 + and a.attrelid = c.oid
  734 + and a.atttypid = t.oid
  735 + ORDER BY a.attnum
  736 + '''.format(table_name)
  737 +
  738 + cols = data_session.execute(sql).fetchall()
  739 + real_cols_name = [col[1] for col in cols]
  740 +
  741 + # 属性增加
  742 + for col in real_cols_name:
  743 + if col not in columns_names:
  744 + StructurePrint().print("{}表要素属性增加!".format(table_name))
  745 + column = Columns(guid=uuid.uuid1().__str__(), table_guid=table.guid,
  746 + name=col, create_time=this_time, update_time=this_time)
  747 + sys_session.add(column)
  748 +
  749 + # 属性减少
  750 + for column in columns:
  751 + if column.name not in real_cols_name:
  752 + StructurePrint().print("{}表要素属性减少!".format(table_name))
  753 + sys_session.delete(column)
  754 +
  755 + # 修改要素量
  756 + # sql = 'select count(*) from "{}"'.format(table_name)
  757 + # count = data_session.execute(sql).fetchone()[0]
  758 +
  759 + count = SQLUtil.get_table_count(table_name,data_session)
  760 +
  761 + if not table.feature_count.__eq__(count):
  762 + StructurePrint().print("{}表要素变化!".format(table_name))
  763 + sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": count})
  764 +
  765 +
  766 +def task_vacuate(table,task_guid):
  767 +
  768 + sys_session = None
  769 + pg_session = None
  770 + pg_ds = None
  771 + vacuate_process = None
  772 + try:
  773 + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
  774 + sys_session.query(Table).filter_by(guid=table.guid).update(
  775 + {"is_vacuate": 2, "update_time": datetime.datetime.now()})
  776 + sys_session.commit()
  777 +
  778 + database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none()
  779 + pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri))
  780 +
  781 + pg_ds: DataSource = PGUtil.open_pg_data_source(0, DES.decode(database.sqlalchemy_uri))
  782 +
  783 + # 删除原有数据
  784 + tvs = sys_session.query(TableVacuate).filter_by(table_guid=table.guid).all()
  785 + for tv in tvs:
  786 + sys_session.delete(tv)
  787 + # try:
  788 + # pg_ds.DeleteLayer(tv.name)
  789 + # except Exception as e :
  790 + # StructurePrint().print("抽稀图层不存在!","warn")
  791 +
  792 + # 创建抽稀过程
  793 + options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name, pg_session)),
  794 + "PRECISION=NO"]
  795 +
  796 + layer = pg_ds.GetLayerByName(table.name)
  797 +
  798 + vacuate_process: VacuateProcess = VacuateProcess(layer, table.guid, options, database.sqlalchemy_uri)
  799 +
  800 + for feature in layer:
  801 + geo = feature.GetGeometryRef()
  802 + # 插入抽稀图层
  803 + if geo is not None:
  804 + vacuate_process.vacuate(geo, feature)
  805 +
  806 + vacuate_process.set_vacuate_count()
  807 +
  808 + # 新增
  809 + if configure.VACUATE_DB_URI:
  810 + user, passwd, host, port, datab = PGUtil.get_info_from_sqlachemy_uri(configure.VACUATE_DB_URI)
  811 + else:
  812 + user, passwd, host, port, datab = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri))
  813 + connectstr = "hostaddr={} port={} dbname='{}' user='{}' password='{}'".format(host, port, datab, user,
  814 + passwd)
  815 + for l in range(vacuate_process.max_level):
  816 + lev = vacuate_process.t_grid_size.index(vacuate_process.this_gridsize[l])
  817 +
  818 + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),
  819 + table_guid=table.guid,
  820 + level=lev,
  821 + name=vacuate_process.vacuate_layers[l].GetName(),
  822 + pixel_distance=vacuate_process.this_gridsize[l],
  823 + connectstr=DES.encode(connectstr))
  824 + sys_session.add(table_vacuate)
  825 +
  826 + sys_session.query(Task).filter_by(guid=task_guid).update({"state": 1, "update_time": datetime.datetime.now(),
  827 + "process": "精化完成"})
  828 + sys_session.query(Table).filter_by(guid=table.guid).update(
  829 + {"is_vacuate": 1, "update_time": datetime.datetime.now()})
  830 + sys_session.commit()
  831 +
  832 + except Exception as e:
  833 + try:
  834 + sys_session.query(Task).filter_by(guid=task_guid).update(
  835 + {"state": -1, "update_time": datetime.datetime.now(),
  836 + "process": "精化失败"})
  837 + sys_session.query(Table).filter_by(guid=table.guid).update(
  838 + {"is_vacuate": 0, "update_time": datetime.datetime.now()})
  839 +
  840 + message = "{} {}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), e.__str__())
  841 + task_process_guid = uuid.uuid1().__str__()
  842 + task_process = Process(guid=task_process_guid, message=message, time=datetime.datetime.now(),
  843 + task_guid=task_guid)
  844 + sys_session.add(task_process)
  845 + sys_session.commit()
  846 + if vacuate_process:
  847 + vacuate_process.rollback()
  848 +
  849 + print(traceback.format_exc())
  850 + except Exception as ee:
  851 + print(traceback.format_exc())
  852 + finally:
  853 + if vacuate_process:
  854 + vacuate_process.end()
  855 + if sys_session:
  856 + sys_session.close()
  857 + if pg_session:
  858 + pg_session.close()
  859 + if pg_ds:
  860 + pg_ds.Destroy()
  861 +
  862 +
  863 +class VacuateProcess:
  864 +
  865 + max_level=0
  866 + fill_dict={}
  867 + vacuate_layers={}
  868 + vacuate_layers_gridsize={}
  869 + pg_ds_dict = {}
  870 + # 图层要素大于5W才抽稀
  871 + least_vacuate_count = VacuateConf.least_vacuate_count
  872 +
  873 + extent=[]
  874 + is_spatial=False
  875 +
  876 + lonlat_gridsize = VacuateConf.lonlat_gridsize
  877 + project_gridsize = VacuateConf.project_gridsize
  878 +
  879 + # 该抽稀过程使用的grid_size
  880 + t_grid_size = []
  881 +
  882 + # 该抽稀过程的抽稀网格
  883 + this_gridsize=[]
  884 +
  885 +
  886 + def __init__(self,layer:Layer,table_guid, options,sqlalchemy_uri):
  887 +
  888 + #是空间图层才初始化
  889 + if layer.GetExtent()[0] > 0 or layer.GetExtent()[0] < 0:
  890 +
  891 + self.is_spatial=True
  892 +
  893 + # 判断需要抽稀多少级
  894 +
  895 + lc = layer.GetFeatureCount()
  896 + extent = layer.GetExtent()
  897 + self.extent=extent
  898 +
  899 + #判断疏密程度
  900 + p_x = (extent[1]-extent[0])/10.0
  901 + p_y = (extent[3] - extent[2]) / 10.0
  902 + fill_precent=0
  903 + StructurePrint().print("判断疏密")
  904 + for ix in range(10):
  905 + for iy in range(10):
  906 + grid_extent = [extent[0]+ix*p_x,extent[0]+ix*p_x+p_x,extent[2]+iy*p_y,extent[2]+iy*p_y+p_y]
  907 + poly = GeometryAdapter.envelop_2_polygon(grid_extent)
  908 +
  909 + layer.SetSpatialFilter(None)
  910 + layer.SetSpatialFilter(poly)
  911 + layer.ResetReading()
  912 + if layer.GetNextFeature():
  913 + fill_precent += 1
  914 +
  915 + print(fill_precent)
  916 + StructurePrint().print("判断疏密结束")
  917 +
  918 + layer.SetSpatialFilter(None)
  919 + layer.ResetReading()
  920 + # 固有疏密程度
  921 + original_density=8
  922 +
  923 +
  924 + # 额外一层
  925 + # self.this_gridsize.append(0.000075)
  926 + # self.max_level += 1
  927 + ######
  928 +
  929 + if extent[0]>180:
  930 + self.t_grid_size=self.project_gridsize
  931 + else:
  932 + self.t_grid_size = self.lonlat_gridsize
  933 +
  934 + for grid_size in self.t_grid_size:
  935 + # 最少抽稀个数
  936 + if lc > self.least_vacuate_count:
  937 + # 网格数至少大于
  938 + if ((extent[1] - extent[0]) * (extent[3] - extent[2])) / (grid_size**2)>self.least_vacuate_count:
  939 + # 要素数量大于网格数量
  940 + # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数
  941 + if lc * original_density * (100.0/fill_precent)>((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2) :
  942 + print(grid_size)
  943 + self.this_gridsize.append(grid_size)
  944 + self.max_level += 1
  945 +
  946 +
  947 +
  948 + # 创建抽稀ds
  949 + for l in range(self.max_level):
  950 + # pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, DES.decode(sqlalchemy_uri))
  951 + if configure.VACUATE_DB_URI:
  952 + pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, configure.VACUATE_DB_URI)
  953 + else:
  954 + pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, DES.decode(sqlalchemy_uri))
  955 + pg_ds_l.StartTransaction()
  956 + self.pg_ds_dict[l] = pg_ds_l
  957 +
  958 + # 生成抽稀图层
  959 + options = options[1:]
  960 + options.append("OVERWRITE=yes")
  961 + options.append("LAUNDER=no")
  962 +
  963 + schema = layer.schema
  964 + # 增加统计字段
  965 + schema.append(ogr.FieldDefn("_dcigrid_count_", ogr.OFTInteger))
  966 + schema.append(ogr.FieldDefn("_dcigrid_name_", ogr.OFTString))
  967 +
  968 + for l in range(self.max_level):
  969 + this_grid_len = self.this_gridsize[l]
  970 +
  971 + self.vacuate_layers_gridsize[l] = this_grid_len
  972 +
  973 + pg = self.pg_ds_dict[l]
  974 +
  975 + grid_name = str(this_grid_len)
  976 + if this_grid_len<1:
  977 + grid_name = str(this_grid_len).split(".")[-1]
  978 + if this_grid_len.__eq__(0.00008):
  979 + grid_name = "00008"
  980 +
  981 + # 抽稀图层是点面混合的
  982 + # 抽稀表有固定的命名规则
  983 + # 抽稀表一定要覆盖
  984 +
  985 +
  986 + print("{}:{}".format(self.t_grid_size.index(this_grid_len),this_grid_len))
  987 +
  988 +
  989 + v_ln = "z{}_vacuate_{}_{}".format(table_guid, self.t_grid_size.index(this_grid_len), grid_name)
  990 + vl = pg.CreateLayer(v_ln, layer.GetSpatialRef(),ogr.wkbUnknown, options)
  991 + # 抽稀表需要属性
  992 + vl.CreateFields(schema)
  993 + self.vacuate_layers[l] = vl
  994 +
  995 + else:
  996 + pass
  997 +
  998 +
  999 + def vacuate(self,g,feature):
  1000 +
  1001 + if self.is_spatial:
  1002 +
  1003 + # 插入到所有抽稀图层中
  1004 + for level in range(self.max_level):
  1005 +
  1006 + center: Geometry = g.Centroid()
  1007 +
  1008 + extent = g.GetEnvelope()
  1009 + long_extent= extent[1]-extent[0]
  1010 + lat_extent = extent[3]-extent[2]
  1011 +
  1012 + this_grid_len =self.vacuate_layers_gridsize[level]
  1013 + #超大的直接加入
  1014 + # if long_extent > 10*this_grid_len or lat_extent >10*this_grid_len:
  1015 + # vacuate_layer: Layer = self.vacuate_layers.get(level)
  1016 + # feat = ogr.Feature(vacuate_layer.GetLayerDefn())
  1017 + # feat.SetGeometry(g)
  1018 + # vacuate_layer.CreateFeature(feat)
  1019 + # else:
  1020 +
  1021 + row = int((center.GetY() - self.extent[2]) / this_grid_len)
  1022 + col = int((center.GetX() - self.extent[0]) / this_grid_len)
  1023 + key = "{}.{}.{}".format(level, row, col)
  1024 +
  1025 + if not self.fill_dict.get(key):
  1026 + self.fill_dict[key] = 0
  1027 + if self.fill_dict[key] == 0:
  1028 +
  1029 + vacuate_layer: Layer = self.vacuate_layers.get(level)
  1030 + feat = ogr.Feature(vacuate_layer.GetLayerDefn())
  1031 + # 如果图形比网格小,直接存储其中心点
  1032 + if this_grid_len>long_extent and this_grid_len>lat_extent:
  1033 + feat.SetGeometry(center)
  1034 + else:
  1035 + feat.SetGeometry(g)
  1036 +
  1037 + # 复制旧feature属性
  1038 + field_dict = feature.items()
  1039 + for field_name in field_dict:
  1040 + feat.SetField(field_name, field_dict[field_name])
  1041 + feat.SetField("_dcigrid_name_",".".join(key.split(".")[1:]))
  1042 +
  1043 + vacuate_layer.CreateFeature(feat)
  1044 + self.fill_dict[key] += 1
  1045 + #超大的还有机会
  1046 + elif (long_extent > 10*this_grid_len or lat_extent >10*this_grid_len) and self.fill_dict[key]<5:
  1047 + vacuate_layer: Layer = self.vacuate_layers.get(level)
  1048 + feat = ogr.Feature(vacuate_layer.GetLayerDefn())
  1049 + feat.SetGeometry(g)
  1050 +
  1051 + # 复制旧feature属性
  1052 + field_dict = feature.items()
  1053 + for field_name in field_dict:
  1054 + feat.SetField(field_name, field_dict[field_name])
  1055 + feat.SetField("_dcigrid_name_",".".join(key.split(".")[1:]))
  1056 +
  1057 + vacuate_layer.CreateFeature(feat)
  1058 + self.fill_dict[key] += 1
  1059 + else:
  1060 + self.fill_dict[key] += 1
  1061 +
  1062 + def set_vacuate_count(self):
  1063 + if self.is_spatial:
  1064 + # 插入到所有抽稀图层中
  1065 + for level in range(self.max_level):
  1066 + vacuate_layer: Layer = self.vacuate_layers.get(level)
  1067 + for feat in vacuate_layer:
  1068 + key = "{}.{}".format(level,feat.GetField("_dcigrid_name_"))
  1069 + feat.SetField("_dcigrid_count_",self.fill_dict.get(key))
  1070 + vacuate_layer.SetFeature(feat)
  1071 +
  1072 + def end(self):
  1073 + for pg in self.pg_ds_dict.values():
  1074 + pg.Destroy()
  1075 +
  1076 + def rollback(self):
  1077 + for pg in self.pg_ds_dict.values():
  1078 + pg.RollbackTransaction()
... ...
... ... @@ -11,6 +11,8 @@ from . import service_exist_type
11 11 from . import service_list
12 12 from . import service_delete
13 13 from . import service_state
  14 +from . import service_info
  15 +from . import service_edit
14 16 import os
15 17 from flask import send_from_directory
16 18
... ... @@ -40,7 +42,7 @@ class DataManager(BlueprintApi):
40 42 return service_exist_type.Api().result
41 43
42 44 @staticmethod
43   - @bp.route('/State', methods=['GET'])
  45 + @bp.route('/State', methods=['POST'])
44 46 @swag_from(service_state.Api.api_doc)
45 47 def api_service_state():
46 48 """
... ... @@ -57,6 +59,25 @@ class DataManager(BlueprintApi):
57 59 """
58 60 return service_list.Api().result
59 61
  62 + @staticmethod
  63 + @bp.route('/Info', methods=['POST'])
  64 + @swag_from(service_info.Api.api_doc)
  65 + def api_service_info():
  66 + """
  67 + 服务Info
  68 + """
  69 + return service_info.Api().result
  70 +
  71 + @staticmethod
  72 + @bp.route('/Edit', methods=['POST'])
  73 + @swag_from(service_edit.Api.api_doc)
  74 + def api_service_edit():
  75 + """
  76 + 服务Edit
  77 + """
  78 + return service_edit.Api().result
  79 +
  80 +
60 81
61 82 @staticmethod
62 83 @bp.route('/Delete', methods=['POST'])
... ...
... ... @@ -19,8 +19,7 @@ class Api(ApiTemplate):
19 19
20 20
21 21 if ServiceCatalog.query.filter_by(name=self.para.get("name"),
22   - pguid=self.para.get("pguid"),
23   - database_guid=self.para.get("database_guid")).one_or_none():
  22 + pguid=self.para.get("pguid")).one_or_none():
24 23 res["msg"]="目录已经存在!"
25 24 return res
26 25
... ...
... ... @@ -38,11 +38,6 @@ class Api(ApiTemplate):
38 38 "in": "formData",
39 39 "type": "string",
40 40 "description":"目录guid","required": "true"},
41   - {"name": "database_guid",
42   - "in": "formData",
43   - "type": "string",
44   - "description": "数据库guid", "required": "true"},
45   -
46 41 ],
47 42 "responses":{
48 43 200:{
... ...
... ... @@ -52,11 +52,6 @@ class Api(ApiTemplate):
52 52
53 53 "tags":["服务目录接口"],
54 54 "parameters":[
55   - {"name": "database_guid",
56   - "in": "formData",
57   - "type": "string",
58   - "description": "数据库guid", "required": "true"},
59   -
60 55 ],
61 56 "responses":{
62 57 200:{
... ...
... ... @@ -21,7 +21,6 @@ class Api(ApiTemplate):
21 21 catalog_guids = [c.guid for c in ServiceCatalog.query.filter(ServiceCatalog.path.like("%" + cata.guid + "%")).all()]
22 22 service_count = Service.query.filter(Service.catalog_guid.in_(catalog_guids)).count()
23 23 cata_json ={}
24   - cata_json["database_guid"]=cata.database_guid
25 24 cata_json["description"] = cata.description
26 25 cata_json["guid"] = cata.guid
27 26 cata_json["name"] = cata.name
... ... @@ -41,11 +40,6 @@ class Api(ApiTemplate):
41 40
42 41 "tags":["服务目录接口"],
43 42 "parameters":[
44   - {"name": "database_guid",
45   - "in": "formData",
46   - "type": "string",
47   - "description": "数据库guid", "required": "true"},
48   -
49 43 ],
50 44 "responses":{
51 45 200:{
... ...
... ... @@ -15,7 +15,8 @@ from . import image_tile,image_wms
15 15 from . import image_service_list
16 16 from . import image_tile_mask
17 17
18   -
  18 +from . import image_delete
  19 +from . import image_cancle
19 20 from . import image_register,image_list,image_info,image_edit,image_overview
20 21 from . import image_tag_create,image_tag_delete,image_tag_list
21 22
... ... @@ -34,12 +35,31 @@ class DataManager(BlueprintApi):
34 35 """
35 36 return image_register.Api().result
36 37
  38 +
  39 + @staticmethod
  40 + @bp.route('/Delete', methods=['POST'])
  41 + @swag_from(image_delete.Api.api_doc)
  42 + def api_image_delete():
  43 + """
  44 + 影像删除
  45 + """
  46 + return image_delete.Api().result
  47 +
  48 + @staticmethod
  49 + @bp.route('/Cancle', methods=['POST'])
  50 + @swag_from(image_cancle.Api.api_doc)
  51 + def api_image_cancle():
  52 + """
  53 + 影像取消注册
  54 + """
  55 + return image_cancle.Api().result
  56 +
37 57 @staticmethod
38 58 @bp.route('/Edit', methods=['POST'])
39 59 @swag_from(image_edit.Api.api_doc)
40 60 def api_image_edit():
41 61 """
42   - 影像Info
  62 + 影像Edit
43 63 """
44 64 return image_edit.Api().result
45 65
... ... @@ -129,7 +149,7 @@ class DataManager(BlueprintApi):
129 149 return data_list.Api().result
130 150
131 151 @staticmethod
132   - @bp.route('/Capabilities', methods=['POST'])
  152 + @bp.route('/Capabilities', methods=['GET','POST'])
133 153 @swag_from(capabilities.Api.api_doc)
134 154 def capabilities():
135 155 """
... ... @@ -156,6 +176,17 @@ class DataManager(BlueprintApi):
156 176 """
157 177 return image_tile.Api(guid,l,y,z).result
158 178
  179 +
  180 +
  181 + # @staticmethod
  182 + # @bp.route('/<service_name>/WMTS', methods=['GET'])
  183 + # @swag_from(image_tile.Api.api_doc)
  184 + # def api_image_tile(service_name):
  185 + # """
  186 + # 切片服务
  187 + # """
  188 + # return image_tile.Api(service_name).result
  189 +
159 190 @staticmethod
160 191 @bp.route('/Tile', methods=['GET','POST'])
161 192 @swag_from(image_tile.Api.api_doc)
... ...
... ... @@ -6,489 +6,297 @@
6 6
7 7 from flask import Response
8 8 from app.util.component.ApiTemplate import ApiTemplate
  9 +from .models import ImageService
  10 +from app.models import Service,TileScheme
  11 +import json
  12 +import configure
  13 +
  14 +
9 15 class Api(ApiTemplate):
10 16
11   - api_name = "影像数据列表"
  17 + api_name = "影像能力文档"
12 18
13 19 def process(self):
14 20
15   - x = '''<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
16   - <!-- Service Identification -->
17   - <ows:ServiceIdentification>
18   - <ows:Title>localimage</ows:Title>
19   - <ows:ServiceType>OGC WMTS</ows:ServiceType>
20   - <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
21   - </ows:ServiceIdentification>
22   - <!-- Operations Metadata -->
23   - <ows:OperationsMetadata>
24   - <ows:Operation name="GetCapabilities">
25   - <ows:DCP>
26   - <ows:HTTP>
27   - <ows:Get xlink:href="http://172.26.99.160:8840/API/Image/Capabilities">
28   - <ows:Constraint name="GetEncoding">
29   - <ows:AllowedValues>
30   - <ows:Value>RESTful</ows:Value>
31   - </ows:AllowedValues>
32   - </ows:Constraint>
33   - </ows:Get>
34   - <!-- add KVP binding in 10.1 -->
35   - <ows:Get xlink:href="http://172.26.99.160:8840/API/Image/TileMany?">
36   - <ows:Constraint name="GetEncoding">
37   - <ows:AllowedValues>
38   - <ows:Value>KVP</ows:Value>
39   - </ows:AllowedValues>
40   - </ows:Constraint>
41   - </ows:Get>
42   - </ows:HTTP>
43   - </ows:DCP>
44   - </ows:Operation>
45   - <ows:Operation name="GetTile">
46   - <ows:DCP>
47   - <ows:HTTP>
48   - <ows:Get xlink:href="http://172.26.99.160:8840/API/Image/TileMany">
49   - <ows:Constraint name="GetEncoding">
50   - <ows:AllowedValues>
51   - <ows:Value>RESTful</ows:Value>
52   - </ows:AllowedValues>
53   - </ows:Constraint>
54   - </ows:Get>
55   - <ows:Get xlink:href="http://172.26.99.160:8840/API/Image/TileMany?">
56   - <ows:Constraint name="GetEncoding">
57   - <ows:AllowedValues>
58   - <ows:Value>KVP</ows:Value>
59   - </ows:AllowedValues>
60   - </ows:Constraint>
61   - </ows:Get>
62   - </ows:HTTP>
63   - </ows:DCP>
64   - </ows:Operation>
65   - </ows:OperationsMetadata>
66   - <Contents>
67   - <!-- Layer -->
68   - <Layer>
69   - <ows:Title>changde</ows:Title>
70   - <ows:Identifier>changde</ows:Identifier>
71   - <ows:BoundingBox crs="urn:ogc:def:crs:EPSG::4490">
72   - <ows:LowerCorner>111.604613312 28.9170588759</ows:LowerCorner>
73   - <ows:UpperCorner>111.751508603 29.079435995</ows:UpperCorner>
74   - </ows:BoundingBox>
75   - <ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84">
76   - <ows:LowerCorner>111.604613312 28.9170588759</ows:LowerCorner>
77   - <ows:UpperCorner>111.751508603 29.079435995</ows:UpperCorner>
78   - </ows:WGS84BoundingBox>
79   - <Style isDefault="true">
80   - <ows:Title>Default Style</ows:Title>
81   - <ows:Identifier>default</ows:Identifier>
82   - </Style>
83   - <Format>image/png</Format>
84   - <TileMatrixSetLink>
85   - <TileMatrixSet>default028mm</TileMatrixSet>
86   - </TileMatrixSetLink>
87   - <TileMatrixSetLink>
88   - <TileMatrixSet>nativeTileMatrixSet</TileMatrixSet>
89   - </TileMatrixSetLink>
90   - <ResourceURL format="image/png" resourceType="tile" template="http://172.26.99.160:8840/API/Image/TileMany/{TileMatrix}/{TileRow}/{TileCol}?format=image/png"/>
91   - </Layer>
92   - <!-- TileMatrixSet -->
93   - <TileMatrixSet>
94   - <ows:Title>Default TileMatrix using 0.28mm</ows:Title>
95   - <ows:Abstract>The tile matrix set that has scale values calculated based on the dpi defined by OGC specification (dpi assumes 0.28mm as the physical distance of a pixel).</ows:Abstract>
96   - <ows:Identifier>default028mm</ows:Identifier>
97   - <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4490</ows:SupportedCRS>
98   - <TileMatrix>
99   - <ows:Identifier>0</ows:Identifier>
100   - <ScaleDenominator>5.584552725961496E8</ScaleDenominator>
101   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
102   - <TileWidth>256</TileWidth>
103   - <TileHeight>256</TileHeight>
104   - <MatrixWidth>1</MatrixWidth>
105   - <MatrixHeight>1</MatrixHeight>
106   - </TileMatrix>
107   - <TileMatrix>
108   - <ows:Identifier>1</ows:Identifier>
109   - <ScaleDenominator>2.792276362980748E8</ScaleDenominator>
110   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
111   - <TileWidth>256</TileWidth>
112   - <TileHeight>256</TileHeight>
113   - <MatrixWidth>1</MatrixWidth>
114   - <MatrixHeight>1</MatrixHeight>
115   - </TileMatrix>
116   - <TileMatrix>
117   - <ows:Identifier>2</ows:Identifier>
118   - <ScaleDenominator>1.396138181490374E8</ScaleDenominator>
119   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
120   - <TileWidth>256</TileWidth>
121   - <TileHeight>256</TileHeight>
122   - <MatrixWidth>1</MatrixWidth>
123   - <MatrixHeight>1</MatrixHeight>
124   - </TileMatrix>
125   - <TileMatrix>
126   - <ows:Identifier>3</ows:Identifier>
127   - <ScaleDenominator>6.98069090745187E7</ScaleDenominator>
128   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
129   - <TileWidth>256</TileWidth>
130   - <TileHeight>256</TileHeight>
131   - <MatrixWidth>1</MatrixWidth>
132   - <MatrixHeight>1</MatrixHeight>
133   - </TileMatrix>
134   - <TileMatrix>
135   - <ows:Identifier>4</ows:Identifier>
136   - <ScaleDenominator>3.490345453725935E7</ScaleDenominator>
137   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
138   - <TileWidth>256</TileWidth>
139   - <TileHeight>256</TileHeight>
140   - <MatrixWidth>1</MatrixWidth>
141   - <MatrixHeight>1</MatrixHeight>
142   - </TileMatrix>
143   - <TileMatrix>
144   - <ows:Identifier>5</ows:Identifier>
145   - <ScaleDenominator>1.7451727268629674E7</ScaleDenominator>
146   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
147   - <TileWidth>256</TileWidth>
148   - <TileHeight>256</TileHeight>
149   - <MatrixWidth>1</MatrixWidth>
150   - <MatrixHeight>1</MatrixHeight>
151   - </TileMatrix>
152   - <TileMatrix>
153   - <ows:Identifier>6</ows:Identifier>
154   - <ScaleDenominator>8725863.634314837</ScaleDenominator>
155   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
156   - <TileWidth>256</TileWidth>
157   - <TileHeight>256</TileHeight>
158   - <MatrixWidth>1</MatrixWidth>
159   - <MatrixHeight>1</MatrixHeight>
160   - </TileMatrix>
161   - <TileMatrix>
162   - <ows:Identifier>7</ows:Identifier>
163   - <ScaleDenominator>4362931.8171574185</ScaleDenominator>
164   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
165   - <TileWidth>256</TileWidth>
166   - <TileHeight>256</TileHeight>
167   - <MatrixWidth>1</MatrixWidth>
168   - <MatrixHeight>1</MatrixHeight>
169   - </TileMatrix>
170   - <TileMatrix>
171   - <ows:Identifier>8</ows:Identifier>
172   - <ScaleDenominator>2181465.9085787092</ScaleDenominator>
173   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
174   - <TileWidth>256</TileWidth>
175   - <TileHeight>256</TileHeight>
176   - <MatrixWidth>2</MatrixWidth>
177   - <MatrixHeight>2</MatrixHeight>
178   - </TileMatrix>
179   - <TileMatrix>
180   - <ows:Identifier>9</ows:Identifier>
181   - <ScaleDenominator>1090732.9542893546</ScaleDenominator>
182   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
183   - <TileWidth>256</TileWidth>
184   - <TileHeight>256</TileHeight>
185   - <MatrixWidth>3</MatrixWidth>
186   - <MatrixHeight>3</MatrixHeight>
187   - </TileMatrix>
188   - <TileMatrix>
189   - <ows:Identifier>10</ows:Identifier>
190   - <ScaleDenominator>545366.4771446773</ScaleDenominator>
191   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
192   - <TileWidth>256</TileWidth>
193   - <TileHeight>256</TileHeight>
194   - <MatrixWidth>6</MatrixWidth>
195   - <MatrixHeight>6</MatrixHeight>
196   - </TileMatrix>
197   - <TileMatrix>
198   - <ows:Identifier>11</ows:Identifier>
199   - <ScaleDenominator>272683.23857233865</ScaleDenominator>
200   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
201   - <TileWidth>256</TileWidth>
202   - <TileHeight>256</TileHeight>
203   - <MatrixWidth>11</MatrixWidth>
204   - <MatrixHeight>11</MatrixHeight>
205   - </TileMatrix>
206   - <TileMatrix>
207   - <ows:Identifier>12</ows:Identifier>
208   - <ScaleDenominator>136341.61928616933</ScaleDenominator>
209   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
210   - <TileWidth>256</TileWidth>
211   - <TileHeight>256</TileHeight>
212   - <MatrixWidth>21</MatrixWidth>
213   - <MatrixHeight>20</MatrixHeight>
214   - </TileMatrix>
215   - <TileMatrix>
216   - <ows:Identifier>13</ows:Identifier>
217   - <ScaleDenominator>68170.80964308466</ScaleDenominator>
218   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
219   - <TileWidth>256</TileWidth>
220   - <TileHeight>256</TileHeight>
221   - <MatrixWidth>42</MatrixWidth>
222   - <MatrixHeight>40</MatrixHeight>
223   - </TileMatrix>
224   - <TileMatrix>
225   - <ows:Identifier>14</ows:Identifier>
226   - <ScaleDenominator>34085.40482154233</ScaleDenominator>
227   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
228   - <TileWidth>256</TileWidth>
229   - <TileHeight>256</TileHeight>
230   - <MatrixWidth>83</MatrixWidth>
231   - <MatrixHeight>80</MatrixHeight>
232   - </TileMatrix>
233   - <TileMatrix>
234   - <ows:Identifier>15</ows:Identifier>
235   - <ScaleDenominator>17042.702410771166</ScaleDenominator>
236   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
237   - <TileWidth>256</TileWidth>
238   - <TileHeight>256</TileHeight>
239   - <MatrixWidth>166</MatrixWidth>
240   - <MatrixHeight>158</MatrixHeight>
241   - </TileMatrix>
242   - <TileMatrix>
243   - <ows:Identifier>16</ows:Identifier>
244   - <ScaleDenominator>8521.351205385583</ScaleDenominator>
245   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
246   - <TileWidth>256</TileWidth>
247   - <TileHeight>256</TileHeight>
248   - <MatrixWidth>331</MatrixWidth>
249   - <MatrixHeight>314</MatrixHeight>
250   - </TileMatrix>
251   - <TileMatrix>
252   - <ows:Identifier>17</ows:Identifier>
253   - <ScaleDenominator>4260.6756026927915</ScaleDenominator>
254   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
255   - <TileWidth>256</TileWidth>
256   - <TileHeight>256</TileHeight>
257   - <MatrixWidth>661</MatrixWidth>
258   - <MatrixHeight>627</MatrixHeight>
259   - </TileMatrix>
260   - <TileMatrix>
261   - <ows:Identifier>18</ows:Identifier>
262   - <ScaleDenominator>2130.3378013463957</ScaleDenominator>
263   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
264   - <TileWidth>256</TileWidth>
265   - <TileHeight>256</TileHeight>
266   - <MatrixWidth>1321</MatrixWidth>
267   - <MatrixHeight>1254</MatrixHeight>
268   - </TileMatrix>
269   - <TileMatrix>
270   - <ows:Identifier>19</ows:Identifier>
271   - <ScaleDenominator>1065.1689006731979</ScaleDenominator>
272   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
273   - <TileWidth>256</TileWidth>
274   - <TileHeight>256</TileHeight>
275   - <MatrixWidth>2642</MatrixWidth>
276   - <MatrixHeight>2508</MatrixHeight>
277   - </TileMatrix>
278   - <TileMatrix>
279   - <ows:Identifier>20</ows:Identifier>
280   - <ScaleDenominator>532.5844503365989</ScaleDenominator>
281   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
282   - <TileWidth>256</TileWidth>
283   - <TileHeight>256</TileHeight>
284   - <MatrixWidth>5283</MatrixWidth>
285   - <MatrixHeight>5014</MatrixHeight>
286   - </TileMatrix>
287   - </TileMatrixSet>
288   - <TileMatrixSet>
289   - <ows:Title>Native TiledMapService TileMatrixSet</ows:Title>
290   - <ows:Abstract>the tile matrix set that has scale values calculated based on the dpi defined by ArcGIS Server tiled map service. The current tile dpi is 96</ows:Abstract>
291   - <ows:Identifier>nativeTileMatrixSet</ows:Identifier>
292   - <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4490</ows:SupportedCRS>
293   - <TileMatrix>
294   - <ows:Identifier>0</ows:Identifier>
295   - <ScaleDenominator>5.909951861175001E8</ScaleDenominator>
296   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
297   - <TileWidth>256</TileWidth>
298   - <TileHeight>256</TileHeight>
299   - <MatrixWidth>1</MatrixWidth>
300   - <MatrixHeight>1</MatrixHeight>
301   - </TileMatrix>
302   - <TileMatrix>
303   - <ows:Identifier>1</ows:Identifier>
304   - <ScaleDenominator>2.9549759305875003E8</ScaleDenominator>
305   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
306   - <TileWidth>256</TileWidth>
307   - <TileHeight>256</TileHeight>
308   - <MatrixWidth>1</MatrixWidth>
309   - <MatrixHeight>1</MatrixHeight>
310   - </TileMatrix>
311   - <TileMatrix>
312   - <ows:Identifier>2</ows:Identifier>
313   - <ScaleDenominator>1.4774879652937502E8</ScaleDenominator>
314   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
315   - <TileWidth>256</TileWidth>
316   - <TileHeight>256</TileHeight>
317   - <MatrixWidth>1</MatrixWidth>
318   - <MatrixHeight>1</MatrixHeight>
319   - </TileMatrix>
320   - <TileMatrix>
321   - <ows:Identifier>3</ows:Identifier>
322   - <ScaleDenominator>7.387439826468751E7</ScaleDenominator>
323   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
324   - <TileWidth>256</TileWidth>
325   - <TileHeight>256</TileHeight>
326   - <MatrixWidth>1</MatrixWidth>
327   - <MatrixHeight>1</MatrixHeight>
328   - </TileMatrix>
329   - <TileMatrix>
330   - <ows:Identifier>4</ows:Identifier>
331   - <ScaleDenominator>3.6937199132343754E7</ScaleDenominator>
332   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
333   - <TileWidth>256</TileWidth>
334   - <TileHeight>256</TileHeight>
335   - <MatrixWidth>1</MatrixWidth>
336   - <MatrixHeight>1</MatrixHeight>
337   - </TileMatrix>
338   - <TileMatrix>
339   - <ows:Identifier>5</ows:Identifier>
340   - <ScaleDenominator>1.8468599566171877E7</ScaleDenominator>
341   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
342   - <TileWidth>256</TileWidth>
343   - <TileHeight>256</TileHeight>
344   - <MatrixWidth>1</MatrixWidth>
345   - <MatrixHeight>1</MatrixHeight>
346   - </TileMatrix>
347   - <TileMatrix>
348   - <ows:Identifier>6</ows:Identifier>
349   - <ScaleDenominator>9234299.783085939</ScaleDenominator>
350   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
351   - <TileWidth>256</TileWidth>
352   - <TileHeight>256</TileHeight>
353   - <MatrixWidth>1</MatrixWidth>
354   - <MatrixHeight>1</MatrixHeight>
355   - </TileMatrix>
356   - <TileMatrix>
357   - <ows:Identifier>7</ows:Identifier>
358   - <ScaleDenominator>4617149.891542969</ScaleDenominator>
359   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
360   - <TileWidth>256</TileWidth>
361   - <TileHeight>256</TileHeight>
362   - <MatrixWidth>1</MatrixWidth>
363   - <MatrixHeight>1</MatrixHeight>
364   - </TileMatrix>
365   - <TileMatrix>
366   - <ows:Identifier>8</ows:Identifier>
367   - <ScaleDenominator>2308574.9457714846</ScaleDenominator>
368   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
369   - <TileWidth>256</TileWidth>
370   - <TileHeight>256</TileHeight>
371   - <MatrixWidth>2</MatrixWidth>
372   - <MatrixHeight>2</MatrixHeight>
373   - </TileMatrix>
374   - <TileMatrix>
375   - <ows:Identifier>9</ows:Identifier>
376   - <ScaleDenominator>1154287.4728857423</ScaleDenominator>
377   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
378   - <TileWidth>256</TileWidth>
379   - <TileHeight>256</TileHeight>
380   - <MatrixWidth>3</MatrixWidth>
381   - <MatrixHeight>3</MatrixHeight>
382   - </TileMatrix>
383   - <TileMatrix>
384   - <ows:Identifier>10</ows:Identifier>
385   - <ScaleDenominator>577143.7364428712</ScaleDenominator>
386   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
387   - <TileWidth>256</TileWidth>
388   - <TileHeight>256</TileHeight>
389   - <MatrixWidth>6</MatrixWidth>
390   - <MatrixHeight>6</MatrixHeight>
391   - </TileMatrix>
392   - <TileMatrix>
393   - <ows:Identifier>11</ows:Identifier>
394   - <ScaleDenominator>288571.8682214356</ScaleDenominator>
395   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
396   - <TileWidth>256</TileWidth>
397   - <TileHeight>256</TileHeight>
398   - <MatrixWidth>11</MatrixWidth>
399   - <MatrixHeight>11</MatrixHeight>
400   - </TileMatrix>
401   - <TileMatrix>
402   - <ows:Identifier>12</ows:Identifier>
403   - <ScaleDenominator>144285.9341107178</ScaleDenominator>
404   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
405   - <TileWidth>256</TileWidth>
406   - <TileHeight>256</TileHeight>
407   - <MatrixWidth>21</MatrixWidth>
408   - <MatrixHeight>20</MatrixHeight>
409   - </TileMatrix>
410   - <TileMatrix>
411   - <ows:Identifier>13</ows:Identifier>
412   - <ScaleDenominator>72142.9670553589</ScaleDenominator>
413   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
414   - <TileWidth>256</TileWidth>
415   - <TileHeight>256</TileHeight>
416   - <MatrixWidth>42</MatrixWidth>
417   - <MatrixHeight>40</MatrixHeight>
418   - </TileMatrix>
419   - <TileMatrix>
420   - <ows:Identifier>14</ows:Identifier>
421   - <ScaleDenominator>36071.48352767945</ScaleDenominator>
422   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
423   - <TileWidth>256</TileWidth>
424   - <TileHeight>256</TileHeight>
425   - <MatrixWidth>83</MatrixWidth>
426   - <MatrixHeight>80</MatrixHeight>
427   - </TileMatrix>
428   - <TileMatrix>
429   - <ows:Identifier>15</ows:Identifier>
430   - <ScaleDenominator>18035.741763839724</ScaleDenominator>
431   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
432   - <TileWidth>256</TileWidth>
433   - <TileHeight>256</TileHeight>
434   - <MatrixWidth>166</MatrixWidth>
435   - <MatrixHeight>158</MatrixHeight>
436   - </TileMatrix>
437   - <TileMatrix>
438   - <ows:Identifier>16</ows:Identifier>
439   - <ScaleDenominator>9017.870881919862</ScaleDenominator>
440   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
441   - <TileWidth>256</TileWidth>
442   - <TileHeight>256</TileHeight>
443   - <MatrixWidth>331</MatrixWidth>
444   - <MatrixHeight>314</MatrixHeight>
445   - </TileMatrix>
446   - <TileMatrix>
447   - <ows:Identifier>17</ows:Identifier>
448   - <ScaleDenominator>4508.935440959931</ScaleDenominator>
449   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
450   - <TileWidth>256</TileWidth>
451   - <TileHeight>256</TileHeight>
452   - <MatrixWidth>661</MatrixWidth>
453   - <MatrixHeight>627</MatrixHeight>
454   - </TileMatrix>
455   - <TileMatrix>
456   - <ows:Identifier>18</ows:Identifier>
457   - <ScaleDenominator>2254.4677204799655</ScaleDenominator>
458   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
459   - <TileWidth>256</TileWidth>
460   - <TileHeight>256</TileHeight>
461   - <MatrixWidth>1321</MatrixWidth>
462   - <MatrixHeight>1254</MatrixHeight>
463   - </TileMatrix>
464   - <TileMatrix>
465   - <ows:Identifier>19</ows:Identifier>
466   - <ScaleDenominator>1127.2338602399827</ScaleDenominator>
467   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
468   - <TileWidth>256</TileWidth>
469   - <TileHeight>256</TileHeight>
470   - <MatrixWidth>2642</MatrixWidth>
471   - <MatrixHeight>2508</MatrixHeight>
472   - </TileMatrix>
473   - <TileMatrix>
474   - <ows:Identifier>20</ows:Identifier>
475   - <ScaleDenominator>563.6169301199914</ScaleDenominator>
476   - <TopLeftCorner>90.0 -180.0</TopLeftCorner>
477   - <TileWidth>256</TileWidth>
478   - <TileHeight>256</TileHeight>
479   - <MatrixWidth>5283</MatrixWidth>
480   - <MatrixHeight>5014</MatrixHeight>
481   - </TileMatrix>
482   - </TileMatrixSet>
483   - </Contents>
484   - <ServiceMetadataURL xlink:href="http://172.26.99.160:8840/API/Image/Capabilities"/>
485   - </Capabilities>'''
  21 + guid = self.para.get("guid")
  22 + image_service:ImageService = ImageService.query.filter_by(guid=guid).one_or_none()
  23 + if not image_service:
  24 + raise Exception("服务不存在!")
  25 + service = Service.query.filter_by(guid=image_service.service_guid).one_or_none()
  26 +
  27 + if service.type.__eq__("ImageWMS"):
  28 + xml = self.get_wms_capabilities(image_service)
  29 +
  30 + elif service.type.__eq__("ImageWMTS"):
  31 + #arcgis能加载
  32 + xml = self.get_wmts_capabilities(image_service,service)
  33 + else:
  34 + xml = ""
486 35
487   - r = Response(response=x, status=200, mimetype="application/xml")
  36 + r = Response(response=xml, status=200, mimetype="application/xml")
488 37 r.headers["Content-Type"] = "text/xml; charset=utf-8"
489 38 return r
490 39
  40 + def get_wms_capabilities(self,image_service:ImageService):
  41 +
  42 + xml = '''<?xml version="1.0" encoding="utf-8" ?>
  43 + <WMS_Capabilities version="1.2.0">
  44 + <Service>
  45 + <Name>WMS</Name>
  46 + <Title>{service_title}</Title>
  47 + <Abstract>{abstract}</Abstract>
  48 + <Keywords>GIMS</Keywords>
  49 + <OnlineResource/>
  50 + <Fees>none</Fees>
  51 + <AccessConstraints>none</AccessConstraints>
  52 + </Service>
  53 + <Capability>
  54 + <Request>
  55 + <GetCapabilities>
  56 + <Format>text/xml</Format>
  57 + <DCPType>
  58 + <HTTP>
  59 + <Get>
  60 + <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
  61 + </Get>
  62 + </HTTP>
  63 + </DCPType>
  64 + </GetCapabilities>
  65 + <GetMap>
  66 + <Format>png</Format>
  67 + <Format>jpeg</Format>
  68 + <Format>gif</Format>
  69 + <Format>image/png</Format>
  70 + <Format>image/jpeg</Format>
  71 + <Format>image/gif</Format>
  72 + <DCPType>
  73 + <HTTP>
  74 + <Get>
  75 + <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
  76 + </Get>
  77 + </HTTP>
  78 + </DCPType>
  79 + </GetMap>
  80 + <Map>
  81 + <Format>
  82 + <PNG/>
  83 + <GIF/>
  84 + <JPG/>
  85 + </Format>
  86 + <DCPType>
  87 + <HTTP>
  88 + <Get onlineResource="{url}"/>
  89 + </HTTP>
  90 + </DCPType>
  91 + </Map>
  92 + <Capabilities>
  93 + <Format>
  94 + <WMS_XML/>
  95 + </Format>
  96 + <DCPType>
  97 + <HTTP>
  98 + <Get onlineResource="{url}"/>
  99 + </HTTP>
  100 + </DCPType>
  101 + </Capabilities>
  102 + <FeatureInfo>
  103 + <Format>
  104 + <XML/>
  105 + <MIME/>
  106 + </Format>
  107 + <DCPType>
  108 + <HTTP>
  109 + <Get onlineResource="{url}"/>
  110 + </HTTP>
  111 + </DCPType>
  112 + </FeatureInfo>
  113 + </Request>
  114 + <Exception>
  115 + <Format>
  116 + <WMS_XML/>
  117 + <INIMAGE/>
  118 + <BLANK/>
  119 + </Format>
  120 + </Exception>
  121 + <Layer>
  122 + <Name>{service_name}</Name>
  123 + <Title>{service_title}</Title>
  124 + <CRS>{crs}</CRS>
  125 + <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>
  126 + <Layer queryable="1">
  127 + <CRS>{crs}</CRS>
  128 + <Name>{layer_name}</Name>
  129 + <Title>{layer_title}</Title>
  130 + <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>
  131 + </Layer>
  132 + </Layer>
  133 + </Capability>
  134 + </WMS_Capabilities>'''
  135 +
  136 + extent = json.loads(image_service.extent)
  137 + xml = xml.format(service_title=image_service.name,
  138 + service_name=image_service.name,
  139 + abstract= "None" ,
  140 + crs="ESPG:4326",
  141 + layer_name=image_service.name,
  142 + layer_title=image_service.name,
  143 + maxx=extent[2],
  144 + maxy = extent[3],
  145 + minx = extent[0],
  146 + miny = extent[1],
  147 + url="http://{}/API/Service/Image/WMS?guid={}".format(configure.deploy_ip_host,image_service.guid))
  148 + return xml
  149 +
  150 + def get_wmts_capabilities(self, image_service: ImageService,service:Service):
  151 + tile_scheme:TileScheme = TileScheme.query.filter_by(guid = image_service.scheme_guid).one_or_none()
  152 + if not tile_scheme:
  153 + raise Exception("切片方案不存在!")
  154 +
  155 + xml = '''<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
  156 + <!-- Service Identification -->
  157 + <ows:ServiceIdentification>
  158 + <ows:Title>{title}</ows:Title>
  159 + <ows:ServiceType>OGC WMTS</ows:ServiceType>
  160 + <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
  161 + </ows:ServiceIdentification>
  162 +
  163 + <!-- Operations Metadata -->
  164 + <ows:OperationsMetadata>
  165 + <ows:Operation name="GetCapabilities">
  166 + <ows:DCP>
  167 + <ows:HTTP>
  168 + <ows:Get xlink:href="{capabilities_url}">
  169 + <ows:Constraint name="GetEncoding">
  170 + <ows:AllowedValues>
  171 + <ows:Value>RESTful</ows:Value>
  172 + </ows:AllowedValues>
  173 + </ows:Constraint>
  174 + </ows:Get>
  175 +
  176 + <!-- add KVP binding in 10.1 -->
  177 + <ows:Get xlink:href="{tile_url}?">
  178 + <ows:Constraint name="GetEncoding">
  179 + <ows:AllowedValues>
  180 + <ows:Value>KVP</ows:Value>
  181 + </ows:AllowedValues>
  182 + </ows:Constraint>
  183 + </ows:Get>
  184 + </ows:HTTP>
  185 + </ows:DCP>
  186 + </ows:Operation>
  187 + <ows:Operation name="GetTile">
  188 + <ows:DCP>
  189 + <ows:HTTP>
  190 + <ows:Get xlink:href="{tile_url}">
  191 + <ows:Constraint name="GetEncoding">
  192 + <ows:AllowedValues>
  193 + <ows:Value>RESTful</ows:Value>
  194 + </ows:AllowedValues>
  195 + </ows:Constraint>
  196 + </ows:Get>
  197 + <ows:Get xlink:href="{tile_url}?">
  198 + <ows:Constraint name="GetEncoding">
  199 + <ows:AllowedValues>
  200 + <ows:Value>KVP</ows:Value>
  201 + </ows:AllowedValues>
  202 + </ows:Constraint>
  203 + </ows:Get>
  204 + </ows:HTTP>
  205 + </ows:DCP>
  206 + </ows:Operation>
  207 + </ows:OperationsMetadata>
  208 +
  209 + <Contents>
  210 +
  211 + <!-- Layer -->
  212 +
  213 +
  214 + <Layer>
  215 + <ows:Title>{title}</ows:Title>
  216 + <ows:Identifier>{title}</ows:Identifier>
  217 + <ows:BoundingBox crs="{crs}">
  218 + <ows:LowerCorner>{xmin} {ymin}</ows:LowerCorner>
  219 + <ows:UpperCorner>{xmax} {ymax}</ows:UpperCorner>
  220 + </ows:BoundingBox>
  221 +
  222 + <Style isDefault="true">
  223 + <ows:Title>Default Style</ows:Title>
  224 + <ows:Identifier>default</ows:Identifier>
  225 + </Style>
  226 + <Format>image/png</Format>
  227 + <TileMatrixSetLink>
  228 + <TileMatrixSet>{tile_name}</TileMatrixSet>
  229 + </TileMatrixSetLink>
  230 +
  231 + <ResourceURL format="image/png" resourceType="tile" template="{tile_url}"/>
  232 +
  233 + </Layer>
  234 +
  235 + <!-- TileMatrixSet -->
  236 +
  237 +
  238 + <TileMatrixSet>
  239 +
  240 + <TileMatrix>
  241 + <ows:Title>{tile_title}</ows:Title>
  242 + <ows:Abstract>{tile_description}</ows:Abstract>
  243 + <ows:Identifier>{tile_name}</ows:Identifier>
  244 + <ows:SupportedCRS>{crs}</ows:SupportedCRS>
  245 +
  246 + {tile_matrix}
  247 +
  248 + </TileMatrix>
  249 +
  250 + </TileMatrixSet>
  251 +
  252 +
  253 + </Contents>
  254 + <ServiceMetadataURL xlink:href="{capabilities_url}"/>
  255 + </Capabilities>'''
  256 +
  257 +
  258 +
  259 +
  260 + tile_matrix_each = '''
  261 + <TileMatrix>
  262 + <ows:Identifier>{lev}</ows:Identifier>
  263 + <ScaleDenominator>{scale}</ScaleDenominator>
  264 + <TopLeftCorner>{top_left}</TopLeftCorner>
  265 + <TileWidth>{cols}</TileWidth>
  266 + <TileHeight>{rows}</TileHeight>
  267 + </TileMatrix>
  268 + '''
  269 +
  270 + tile_matrix = ""
  271 + top_left = tile_scheme.top_left
  272 + for level in json.loads(tile_scheme.levels):
  273 + tile_matrix = "{}{}".format(tile_matrix,tile_matrix_each.format(lev=level["level"],
  274 + scale=level["scale"],
  275 + top_left=top_left,
  276 + cols=tile_scheme.cols,
  277 + rows=tile_scheme.rows))
  278 +
  279 + extent = json.loads(image_service.extent)
  280 +
  281 + xml = xml.format(capabilities_url = "http://{}/API/Service/Image/Capabilities?guid={}".format(configure.deploy_ip_host,image_service.guid),
  282 + tile_url = "http://{}/API/Service/Image/Tile?guid={}".format(configure.deploy_ip_host,image_service.guid),
  283 + crs = tile_scheme.crs,
  284 + xmin = extent[0],
  285 + ymin = extent[1],
  286 + xmax = extent[2],
  287 + ymax = extent[3],
  288 + # TileMatrix = "{TileMatrix}",
  289 + # TileRow = "{TileRow}",
  290 + # TileCol = "{TileCol}",
  291 + guid = image_service.guid,
  292 + title = service.title,
  293 + tile_title = tile_scheme.name,
  294 + tile_name = tile_scheme.name,
  295 + tile_description = tile_scheme.description,
  296 + tile_matrix=tile_matrix
  297 + )
491 298
  299 + return xml
492 300
493 301
494 302 api_doc = {
... ...
... ... @@ -13,6 +13,7 @@ from app.modules.service.image.util.ThriftConnect import ThriftConnect
13 13 import os
14 14 from app.models import db
15 15 from app.modules.service.image.models import Image
  16 +from .util.ImageType import ImageType
16 17
17 18 class Api(ApiTemplate):
18 19
... ... @@ -50,21 +51,16 @@ class Api(ApiTemplate):
50 51 if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif") or file_path.lower().endswith("img"):
51 52
52 53 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 + size=file_info.get("real_size")).one_or_none()
54 55 file_info["exist"] = False
55 56 if exist_image:
56 57 if exist_image.server.__contains__(data_server):
57 58 file_info["exist"] = True
58 59
59   - if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif"):
60   - file_info["type"] = "tif"
61   - data_list.append(file_info)
62   - elif file_path.lower().endswith("img"):
63   - file_info["type"] = "img"
64   - data_list.append(file_info)
65   - elif os.path.isdir(file_path):
66   - file_info["type"] = "dir"
67   - data_list.append(file_info)
  60 +
  61 + file_info["type"] = ImageType.get_type(file_path)
  62 + data_list.append(file_info)
  63 +
68 64
69 65 data_list_sorted = sorted(data_list, key=lambda x: x["name"])
70 66 res["data"] = data_list_sorted
... ... @@ -76,8 +72,8 @@ class Api(ApiTemplate):
76 72
77 73 for inf in info:
78 74 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")),
  75 +
  76 + exist_image = Image.query.filter_by(path=inf.get("path"),
81 77 size=inf.get("real_size")).one_or_none()
82 78 inf["exist"] = False
83 79 if exist_image:
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/7/19
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from osgeo import gdal,ogr,osr
  8 +from osgeo.gdal import Dataset,Band
  9 +from app.util.component.ApiTemplate import ApiTemplate
  10 +from app.modules.service.image.util.ThriftConnect import ThriftConnect
  11 +import json
  12 +from .models import Image
  13 +import datetime
  14 +from app.models import db
  15 +import uuid
  16 +import os
  17 +from .models import ImageTag
  18 +import math
  19 +
  20 +class Api(ApiTemplate):
  21 +
  22 + api_name = "注册影像数据"
  23 +
  24 + def process(self):
  25 +
  26 + #可以注册一个目录
  27 + #返回结果
  28 + res = {}
  29 +
  30 + try:
  31 + data_server = self.para.get("data_server")
  32 + paths = json.loads(self.para.get("paths"))
  33 +
  34 + for path in paths:
  35 +
  36 + exist_image:Image = Image.query.filter_by(path=path.get("path"),
  37 + size=path.get("real_size")).one_or_none()
  38 + if exist_image:
  39 + servers = exist_image.server.split(",")
  40 + leave_servers = [ser for ser in servers if not ser.__eq__(data_server)]
  41 + if len(leave_servers) ==0:
  42 + db.session.delete(exist_image)
  43 + else:
  44 + Image.query.filter_by(path=path.get("path"),
  45 + size=path.get("real_size")).update({"server":",".join(leave_servers),
  46 + "update_time":datetime.datetime.now()})
  47 + else:
  48 + raise Exception("数据不存在!")
  49 +
  50 + db.session.commit()
  51 + res["result"] = True
  52 +
  53 + except Exception as e:
  54 + raise e
  55 +
  56 + return res
  57 +
  58 +
  59 + api_doc = {
  60 + "tags": ["影像接口"],
  61 + "parameters": [
  62 + {"name": "data_server",
  63 + "in": "formData",
  64 + "type": "string",
  65 + "description": "data_server"},
  66 + {"name": "paths",
  67 + "in": "formData",
  68 + "type": "string",
  69 + "description": "paths"},
  70 + ],
  71 + "responses": {
  72 + 200: {
  73 + "schema": {
  74 + "properties": {
  75 + }
  76 + }
  77 + }
  78 + }
  79 + }
  80 +
  81 +
... ...
... ... @@ -8,7 +8,7 @@
8 8 from app.util.component.ApiTemplate import ApiTemplate
9 9 from app.util.component.ModelVisitor import ModelVisitor
10 10
11   -from app.modules.service.image.models import Image,db
  11 +from app.modules.service.image.models import Image,db,ImageTag
12 12 from sqlalchemy import or_,and_
13 13 import datetime
14 14 class Api(ApiTemplate):
... ... @@ -22,10 +22,24 @@ class Api(ApiTemplate):
22 22 try:
23 23 para = self.para
24 24 guid = self.para.get("guid")
25   - image = Image.query.filter_by(guid=guid).one_or_none()
  25 + tag_guids = self.para.get("tag_guids")
  26 +
  27 + image = Image.query.filter_by(guid=guid)
  28 + this_time = datetime.datetime.now()
  29 +
26 30 del para["guid"]
27   - para["update_time"] = datetime.datetime.now()
28   - image.update(para)
  31 + del para["tag_guids"]
  32 +
  33 + if para or tag_guids:
  34 + para["update_time"] = this_time
  35 + image.update(para)
  36 +
  37 + if tag_guids:
  38 + tags = ImageTag.query.filter(ImageTag.guid.in_(tag_guids.split(","))).all()
  39 + img = Image.query.filter_by(guid=guid).one_or_none()
  40 + img.image_tags = tags
  41 +
  42 +
29 43 db.session.commit()
30 44
31 45 res["result"] = True
... ... @@ -38,6 +52,9 @@ class Api(ApiTemplate):
38 52 api_doc = {
39 53 "tags": ["影像接口"],
40 54 "parameters": [
  55 + {"name": "guid",
  56 + "in": "formData",
  57 + "type": "string"},
41 58 {"name": "alias",
42 59 "in": "formData",
43 60 "type": "string"},
... ... @@ -47,6 +64,15 @@ class Api(ApiTemplate):
47 64 {"name": "region",
48 65 "in": "formData",
49 66 "type": "string", "description": "所属区域"},
  67 + {"name": "satellite",
  68 + "in": "formData",
  69 + "type": "string", "description": "卫星类型"},
  70 + {"name": "epsg",
  71 + "in": "formData",
  72 + "type": "string", "description": "空间参考"},
  73 + {"name": "tag_guids",
  74 + "in": "formData",
  75 + "type": "string", "description": "tags"},
50 76 ],
51 77 "responses": {
52 78 200: {
... ...
... ... @@ -9,6 +9,7 @@ from app.util.component.ModelVisitor import ModelVisitor
9 9
10 10 from app.modules.service.image.models import Image,ImageTag
11 11 from sqlalchemy import or_,and_
  12 +from app.util.component.FileProcess import FileProcess
12 13 class Api(ApiTemplate):
13 14
14 15 api_name = "影像数据Info"
... ... @@ -24,11 +25,18 @@ class Api(ApiTemplate):
24 25 image = Image.query.filter_by(guid=guid).one_or_none()
25 26 if not image:
26 27 raise Exception("数据不存在!")
27   - tags:ImageTag = image.image_tags.all()
28   - tag_names = [tag.name for tag in tags]
  28 + tags:ImageTag = image.image_tags
  29 + # tag_names = [tag.name for tag in tags]
29 30
30 31 res["data"] = ModelVisitor.object_to_json(image)
31   - res["data"]["tag"] = ",".join(tag_names)
  32 +
  33 + #格式化数据
  34 +
  35 + res["data"]["size"] = FileProcess.get_text_size(res["data"]["size"])
  36 + res["data"]["cell_x_size"] = round(res["data"]["cell_x_size"],3)
  37 + res["data"]["cell_y_size"] = round(res["data"]["cell_y_size"], 3)
  38 +
  39 + res["data"]["image_tags"] = ModelVisitor.objects_to_jsonarray(tags)
32 40 res["result"] = True
33 41 except Exception as e:
34 42 raise e
... ...
... ... @@ -6,7 +6,7 @@
6 6
7 7 from app.util.component.ApiTemplate import ApiTemplate
8 8 from app.util.component.ModelVisitor import ModelVisitor
9   -
  9 +from app.util.component.FileProcess import FileProcess
10 10 from app.modules.service.image.models import Image,ImageTag
11 11 from sqlalchemy import or_,and_
12 12 class Api(ApiTemplate):
... ... @@ -23,9 +23,13 @@ class Api(ApiTemplate):
23 23
24 24 alias = self.para.get("alias")
25 25 name = self.para.get("name")
  26 + band = self.para.get("band")
  27 + region = self.para.get("region")
26 28 tag_guid = self.para.get("tag_guid")
27 29
28   - images = Image.query
  30 + type = self.para.get("type")
  31 +
  32 + images = Image.query.order_by(Image.update_time.desc())
29 33
30 34 # 并集
31 35 if alias and name:
... ... @@ -35,16 +39,33 @@ class Api(ApiTemplate):
35 39 images = images.filter(Image.alias.like("%" + alias + "%"))
36 40 if name:
37 41 images = images.filter(Image.name.like("%" + name + "%"))
  42 + if band:
  43 + images = images.filter(Image.band_view.like("%" + str(band) + "%"))
  44 +
  45 + if type:
  46 + images = images.filter_by(type=type)
  47 +
  48 + if region:
  49 + images = images.filter(Image.region.in_(region.split(",")))
  50 +
38 51 if tag_guid:
39 52 tag:ImageTag = ImageTag.query.filter_by(guid=tag_guid).one_or_none()
40 53 images_guid = [img.guid for img in tag.images.all()]
41 54 images = images.filter(Image.guid.in_(images_guid))
42 55
43 56
44   - images = images.limit(page_size).offset(page_index).all()
  57 + res["data"] = {}
  58 + res["data"]["count"] = images.count()
  59 + imgs = images.limit(page_size).offset(page_index * page_size).all()
  60 + res["data"]["list"] = ModelVisitor.objects_to_jsonarray(imgs)
45 61
46   - res["data"] = ModelVisitor.objects_to_jsonarray(images)
  62 + #格式化数据
  63 + for info in res["data"]["list"]:
  64 + info["size"] = FileProcess.get_text_size(info["size"])
  65 + info["cell_x_size"] = round(info["cell_x_size"],3)
  66 + info["cell_y_size"] = round(info["cell_y_size"], 3)
47 67 res["result"] = True
  68 +
48 69 except Exception as e:
49 70 raise e
50 71
... ... @@ -68,6 +89,18 @@ class Api(ApiTemplate):
68 89 {"name": "name",
69 90 "in": "formData",
70 91 "type": "string"},
  92 + {"name": "ym",
  93 + "in": "formData",
  94 + "type": "string"},
  95 + {"name": "region",
  96 + "in": "formData",
  97 + "type": "string"},
  98 + {"name": "type",
  99 + "in": "formData",
  100 + "type": "string"},
  101 + {"name": "band",
  102 + "in": "formData",
  103 + "type": "string"},
71 104 {"name": "tag_guid",
72 105 "in": "formData",
73 106 "type": "string"},
... ...
... ... @@ -8,9 +8,9 @@ from app.util.component.ApiTemplate import ApiTemplate
8 8 from app.util.component.StructuredPrint import StructurePrint
9 9
10 10 from app.modules.service.image.models import Image
11   -from sqlalchemy import or_
  11 +
12 12 import random
13   -from .image_wms import Api as WMSApi
  13 +
14 14 import numpy
15 15 import json
16 16 from flask import Response
... ... @@ -18,6 +18,8 @@ from kazoo.client import KazooClient
18 18 import configure
19 19 import traceback
20 20
  21 +from .util.ImageData import ImageData
  22 +from .util.Opencv import Opencv
21 23
22 24 class Api(ApiTemplate):
23 25
... ... @@ -44,6 +46,12 @@ class Api(ApiTemplate):
44 46
45 47
46 48 guid = self.para.get("guid")
  49 +
  50 +
  51 + width = int(self.para.get("width") if self.para.get("width") else 512)
  52 + height = int(self.para.get("height") if self.para.get("height") else 512)
  53 + format = self.para.get("format") if self.para.get("format") else "image/jpeg"
  54 +
47 55 image = Image.query.filter_by(guid=guid).one_or_none()
48 56 # 该影像的服务器,随机选取一个
49 57 image_servers = image.server.split(",")
... ... @@ -54,8 +62,6 @@ class Api(ApiTemplate):
54 62 else:
55 63 image_server = "None"
56 64
57   - wms_api = WMSApi()
58   -
59 65 bands = json.loads(image.band_view)
60 66
61 67 # bands = [1,2,3] if image.band_count>=3 else [1,1,1]
... ... @@ -70,18 +76,20 @@ class Api(ApiTemplate):
70 76 query_extent = [query_extent[0] - offset, query_extent[1], query_extent[2] + offset, query_extent[3]]
71 77
72 78
73   - pixel_array_t = wms_api.get_data(image_server, image, query_extent, bands, 256, 256)
  79 + image_data = ImageData(image_server, image)
  80 +
  81 + pixel_array_t = image_data.get_data(query_extent, bands, height, width)
74 82
  83 + pixel_array = numpy.zeros((height, width, 3), dtype=int)
75 84
76   - pixel_array = numpy.zeros((256, 256, 3), dtype=int)
77 85 for ii in [0, 1, 2]:
78 86 # opencv 颜色排序为GBR
79 87 pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
80 88
81 89 # 将图片生成在内存中,然后直接返回response
82   - im_data = wms_api.create_by_opencv("image/jpeg", pixel_array, 30)
  90 + im_data = Opencv.create_image(format, pixel_array, 30)
83 91
84   - return Response(im_data, mimetype="image/jpeg")
  92 + return Response(im_data, mimetype=format)
85 93
86 94 except Exception as e:
87 95 StructurePrint().print(traceback.format_exc())
... ... @@ -96,6 +104,16 @@ class Api(ApiTemplate):
96 104 {"name": "guid",
97 105 "in": "formData",
98 106 "type": "string"},
  107 + {"name": "height",
  108 + "in": "formData",
  109 + "type": "string"},
  110 + {"name": "width",
  111 + "in": "formData",
  112 + "type": "string"},
  113 + {"name": "format",
  114 + "in": "formData",
  115 + "type": "string",
  116 + "enum":["image/jpeg","image/png"]},
99 117 ],
100 118 "responses": {
101 119 200: {
... ... @@ -107,4 +125,3 @@ class Api(ApiTemplate):
107 125 }
108 126 }
109 127
110   -
... ...
... ... @@ -16,6 +16,7 @@ import uuid
16 16 import os
17 17 from .models import ImageTag
18 18 import math
  19 +from .util.ImageType import ImageType
19 20
20 21 class Api(ApiTemplate):
21 22
... ... @@ -117,7 +118,8 @@ class Api(ApiTemplate):
117 118 if exist_image.server.__contains__(data_server):
118 119 pass
119 120 else:
120   - exist_image.update({"server":"{},{}".format(exist_image.server,data_server)})
  121 + Image.query.filter_by(path=os.path.normpath(info.get("path")),
  122 + size=info.get("size")).update({"server":"{},{}".format(exist_image.server,data_server)})
121 123 else:
122 124 img:Image = Image(guid= uuid.uuid1().__str__(),
123 125 overview_count=info.get("overview_count"),
... ... @@ -136,7 +138,10 @@ class Api(ApiTemplate):
136 138 sr_wkt = info.get("sr_wkt"),
137 139 sr_proj4= info.get("sr_proj4"),
138 140 band_count=info.get("band_count"),
139   - create_time=this_time
  141 + band_view = "[1,2,3]" if info.get("band_count")>=3 else "[1,1,1]",
  142 + create_time=this_time,
  143 + update_time=this_time,
  144 + type = ImageType.get_type(info.get("path"))
140 145 )
141 146 for tag in tags:
142 147 img.image_tags.append(tag)
... ...
... ... @@ -25,8 +25,13 @@ class Api(ApiTemplate):
25 25 else :
26 26 if not zoo.connected:
27 27 zoo.start()
28   - res["data"] = zoo.get_children("/rpc")
29   - res["data"].append("本地服务器")
  28 + sers = zoo.get_children("/rpc")
  29 + res["data"] = []
  30 + for p in sers:
  31 + bl = str( zoo.get("/rpc/{}".format(p))[0] , encoding = "utf-8")
  32 + res["data"].append({"name": p, "belong": bl})
  33 +
  34 + res["data"].append({"name":"本地服务器","belong":""})
30 35 res["result"] = True
31 36 except Exception as e:
32 37 raise e
... ...
... ... @@ -8,6 +8,11 @@ from app.models import db
8 8 from app.util.component.ApiTemplate import ApiTemplate
9 9 from app.models import Service
10 10 import datetime
  11 +import json
  12 +from .image_service_register import Api as RegisterApi
  13 +import configure
  14 +
  15 +
11 16 class Api(ApiTemplate):
12 17
13 18 api_name = "修改影像服务"
... ... @@ -20,40 +25,97 @@ class Api(ApiTemplate):
20 25 try:
21 26
22 27 guid = self.para.get("guid")
23   - service = Service.query.filter_by(guid=guid).one_or_none()
  28 + service = Service.query.filter_by(guid=guid)
24 29 this_time = datetime.datetime.now()
  30 + image_guids = self.para.get("image_guids")
25 31
26   -
27   - service_update = {"upate_time":this_time}
28   - image_service = {"upate_time":this_time}
  32 + service_update = {}
  33 + image_update = {}
29 34 for key in self.para.keys():
30   - if key in ["name","alias","state","description","catalog_guid"]:
  35 + if key in ["name","title","state","description","catalog_guid"]:
31 36 service_update[key] = self.para.get(key)
32 37 if key in ["name","scheme_guid"]:
33   - image_service[key] = self.para.get(key)
  38 + image_update[key] = self.para.get(key)
  39 +
  40 +
  41 +
  42 + image_service = ImageService.query.filter_by(guid=Service.query.filter_by(guid=guid).one_or_none().service_guid)
34 43
35   - image_service = ImageService.query.filter_by(guid=service.service_guid).one_or_none()
36 44
37   - service.update(service_update)
38   - image_service.update(image_service)
  45 + #修改影像
  46 + if image_guids:
  47 + image_service_exetent = []
  48 + imgservice:ImageService = image_service.one_or_none()
  49 + imgservice.images = []
  50 +
  51 + for g in image_guids.split(","):
  52 + image = Image.query.filter_by(guid=g).one_or_none()
  53 + if image:
  54 + image_extent = json.loads(image.extent)
  55 + if not image_service_exetent:
  56 + image_service_exetent = image_extent
  57 + else:
  58 + image_service_exetent[0] = min(image_extent[0], image_service_exetent[0])
  59 + image_service_exetent[1] = min(image_extent[1], image_service_exetent[1])
  60 + image_service_exetent[2] = max(image_extent[2], image_service_exetent[2])
  61 + image_service_exetent[3] = max(image_extent[3], image_service_exetent[3])
  62 + imgservice.images.append(image)
  63 +
  64 + image_update["extent"] = json.dumps(image_service_exetent)
  65 +
  66 + if service_update or image_update:
  67 + service_update["update_time"] = this_time
  68 + if image_guids:
  69 + register_api = RegisterApi()
  70 + overview_file = register_api.get_overview(service, image_service)
  71 + service_update["overview"] = "http://{}/API/Service/Overview/{}".format(configure.deploy_ip_host, overview_file)
  72 +
  73 + service.update(service_update)
  74 + if image_update:
  75 + image_service.update(image_update)
39 76
40 77 db.session.commit()
41 78
42 79 res["result"] = True
43 80 except Exception as e:
  81 + db.session.rollback()
44 82 raise e
45 83
46 84 return res
47 85
  86 +
48 87 api_doc = {
49 88 "tags": ["影像接口"],
50 89 "parameters": [
  90 +
51 91 {"name": "guid",
52 92 "in": "formData",
53   - "type": "string"},
  93 + "type": "string",
  94 + "description": "[WMS,WMTS,影像WMS,影像WMTS,guid]"},
  95 +
54 96 {"name": "name",
55 97 "in": "formData",
56   - "type": "string"},
  98 + "type": "string",
  99 + "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
  100 +
  101 + {"name": "title",
  102 + "in": "formData",
  103 + "type": "string",
  104 + "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
  105 + {"name": "description",
  106 + "in": "formData",
  107 + "type": "string",
  108 + "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
  109 +
  110 + {"name": "catalog_guid",
  111 + "in": "formData",
  112 + "type": "string",
  113 + "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
  114 +
  115 +
  116 + {"name": "image_guids",
  117 + "in": "formData",
  118 + "type": "string","description":"修改该服务的影像,用逗号相隔"},
57 119 ],
58 120 "responses": {
59 121 200: {
... ...
... ... @@ -39,10 +39,13 @@ class Api(ApiTemplate):
39 39 if name:
40 40 services = services.filter(ImageService.name.like("%" + name + "%"))
41 41
42   - services = services.limit(page_size).offset(page_index).all()
43 42
44   - res["data"] = ModelVisitor.objects_to_jsonarray(services)
  43 + res["data"] = {}
  44 + res["data"]["count"] = services.count()
  45 + services = services.limit(page_size).offset(page_index * page_size).all()
  46 + res["data"]["list"] = ModelVisitor.objects_to_jsonarray(services)
45 47 res["result"] = True
  48 +
46 49 except Exception as e:
47 50 raise e
48 51
... ...
... ... @@ -12,7 +12,7 @@ from app.util.component.FileProcess import FileProcess
12 12 import os
13 13 import json
14 14 import datetime
15   -from .image_wms import Api as Api2
  15 +from .image_wms import Api as RealApi
16 16 import cv2
17 17 import configure
18 18
... ... @@ -62,7 +62,7 @@ class Api(ApiTemplate):
62 62 service = Service(
63 63 guid = service_guid,
64 64 name = self.para.get("name"),
65   - alias = self.para.get("alias"),
  65 + title = self.para.get("title"),
66 66 state = 1,
67 67 create_time = this_time,
68 68 update_time = this_time,
... ... @@ -93,7 +93,7 @@ class Api(ApiTemplate):
93 93
94 94 def get_overview(self,service,image_service):
95 95
96   - api = Api2()
  96 + api = RealApi()
97 97
98 98
99 99 query_extent = json.loads(image_service.extent)
... ... @@ -106,7 +106,7 @@ class Api(ApiTemplate):
106 106
107 107 bbox = ",".join([str(x) for x in query_extent])
108 108
109   - api.para = {"guid":image_service.guid,"bbox":bbox,"overview":1}
  109 + api.para = {"guid":image_service.guid,"bbox":bbox,"overview":1,"width":512,"height":512}
110 110 res = api.process()
111 111 dir_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "overview")
112 112 gid = uuid.uuid1().__str__()
... ... @@ -128,7 +128,7 @@ class Api(ApiTemplate):
128 128 "type": "string",
129 129 "required": "true",
130 130 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
131   - {"name": "alias",
  131 + {"name": "title",
132 132 "in": "formData",
133 133 "type": "string",
134 134 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
... ... @@ -139,7 +139,7 @@ class Api(ApiTemplate):
139 139 {"name": "type",
140 140 "in": "formData",
141 141 "type": "string",
142   - "enum": ["WMS/WFS","WMTS","MTS","ImageWMS","ImageWMTS"],
  142 + "enum": ["WMS/WFS","WMTS","TMS","ImageWMS","ImageWMTS"],
143 143 "required": "true",
144 144 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
145 145 {"name": "catalog_guid",
... ...
... ... @@ -19,8 +19,12 @@ class Api(ApiTemplate):
19 19 res = {}
20 20 try:
21 21 image_tags = ImageTag.query.all()
22   - res["data"] = ModelVisitor.objects_to_jsonarray(image_tags)
  22 +
  23 + res["data"] = {}
  24 + res["data"]["count"] = ImageTag.query.count()
  25 + res["data"]["list"] = ModelVisitor.objects_to_jsonarray(image_tags)
23 26 res["result"] = True
  27 +
24 28 except Exception as e:
25 29 raise e
26 30 return res
... ...
... ... @@ -10,9 +10,7 @@ from osgeo.gdal import *
10 10 from numpy import ndarray
11 11 import numpy
12 12 from flask import Response
13   -import io
14   -import os
15   -from PIL import Image
  13 +from .util.ImageData import ImageData
16 14
17 15 import time
18 16 import cv2
... ... @@ -28,8 +26,9 @@ from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPoo
28 26 import gzip
29 27 import random
30 28 import copy
31   -
32   -
  29 +from .util.Opencv import Opencv
  30 +from .util.Cache import Cache
  31 +from .util.MyThread import MyThread
33 32
34 33 class Api(ApiTemplate):
35 34
... ... @@ -51,7 +50,7 @@ class Api(ApiTemplate):
51 50 if parameter.get("guid"):
52 51 self.guid = parameter.get("guid")
53 52
54   - image_service_info, zoo, servers = self.cache_data()
  53 + image_service_info, zoo, servers = Cache.cache_data(self.guid)
55 54
56 55 # bands = [1, 2, 3]
57 56
... ... @@ -75,6 +74,11 @@ class Api(ApiTemplate):
75 74
76 75 height, width = 256,256
77 76
  77 +
  78 + re = parameter.get("request")
  79 + if re and re.__eq__("GetCapabilities"):
  80 + return self.get_capabilities(image_service_info["service"])
  81 +
78 82 # 多线程获取分布式数据
79 83
80 84 intersect_image = [im for im in image_service_info["images"] if self.determin_intersect(json.loads(im.extent),extent)]
... ... @@ -99,8 +103,10 @@ class Api(ApiTemplate):
99 103
100 104 bands = json.loads(image.band_view)
101 105
102   - thread: MyThread = MyThread(self.get_data,
103   - args=(image_server, image, extent, bands, height, width))
  106 + image_data = ImageData(image_server,image)
  107 +
  108 + thread: MyThread = MyThread(image_data.get_data,args=(extent, bands, height, width))
  109 +
104 110 thread.start()
105 111 thread_list.append(thread)
106 112
... ... @@ -139,7 +145,9 @@ class Api(ApiTemplate):
139 145 image_server = "None"
140 146 # image_server = image_servers[0]
141 147 bands = json.loads(image.band_view)
142   - pixel_array_t:numpy.ndarray = self.get_data(image_server, image, extent, bands, height, width)
  148 +
  149 + image_data = ImageData(image_server, image)
  150 + pixel_array_t: numpy.ndarray = image_data.get_data(extent, bands, height, width)
143 151 pixel_array = numpy.zeros((height, width, 3), dtype=int)
144 152
145 153 for ii in [0, 1, 2]:
... ... @@ -152,7 +160,7 @@ class Api(ApiTemplate):
152 160
153 161
154 162 # 将图片生成在内存中,然后直接返回response
155   - im_data = self.create_by_opencv(image_type, pixel_array, quality)
  163 + im_data = Opencv.create_image(image_type, pixel_array, quality)
156 164 return Response(im_data, mimetype=image_type.lower())
157 165
158 166
... ... @@ -162,382 +170,15 @@ class Api(ApiTemplate):
162 170 result["message"] = e.__str__()
163 171 return result
164 172
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   -
212   - def determine_level(self, xysize, origin_extent, extent, max_level):
213   - '''
214   - 根据范围判断调用金字塔的哪一层
215   - :param xysize:
216   - :param origin_extent:
217   - :param extent:
218   - :param max_level:
219   - :return:
220   - '''
221   - x = xysize[0]
222   - y = xysize[1]
223   - level = -1
224   - pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / (
225   - (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1])))
226   - while pixel > 100000 and level < max_level - 1:
227   - level += 1
228   - x = x / 2
229   - y = y / 2
230   - pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / (
231   - (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1])))
232   - return level
233   -
234   -
235   - def create_by_opencv(self, image_type, pixel_array, quality):
236   -
237   - if image_type.__eq__("image/jpeg") or image_type.__eq__("image/jpg"):
238   - r, buf = cv2.imencode(".jpg", pixel_array, [cv2.IMWRITE_JPEG_QUALITY, quality])
239   - # r, buf = cv2.imencode(".jpg", pixel_array)
240   - image_out = buf.tobytes()
241   - else:
242   - height, width = pixel_array[:, :, 0].shape
243   - four = numpy.zeros((height, width), dtype=int) + 255
244   - four[pixel_array[:, :, 0] == 65536] = 0
245   - r, buf = cv2.imencode(".png", numpy.dstack((pixel_array, four)))
246   - image_out = buf.tobytes()
247   - return image_out
248   -
249   - def get_data(self,image_server, image, extent, bands, height, width):
250   -
251   - if image_server.__eq__("本地服务器"):
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
255   - else:
256   - data = self.get_remote_wms_data(image_server,image, extent, bands, height, width)
257   - return data
258   -
259   - def get_remote_wms_data(self, image_server,image, extent, bands, height, width):
260   - '''
261   - 通过RPC获取远程数据
262   - :param image:
263   - :param extent:
264   - :param bands:
265   - :return:
266   - '''
267   -
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   -
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连接的缓存,连接池
293   - thrift_connect = ThriftConnect(image_server)
294   - image_extent = image.extent
295   -
296   - data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height)
297   -
298   - thrift_connect.close()
299   -
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()
323   - data = gzip.decompress(data)
324   - data = numpy.frombuffer(data, dtype='int64')
325   - data = data.reshape((height, width, 3))
326   -
327   - return data
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   -
355   - def get_local_wms_data(self, image, extent, bands, height, width):
356   - '''
357   - 获取本地数据
358   - :param image:
359   - :param extent:
360   - :param bands:
361   - :return:
362   - '''
363   - pixel_array = numpy.zeros((height, width, 3), dtype=int)
364   - ceng = 0
365   - img: Dataset = gdal.Open(image.path, 0)
366   -
367   -
368   -
369   - for band in bands:
370   -
371   - # 自决定金字塔等级
372   - xysize = [img.RasterXSize, img.RasterYSize]
373   -
374   - origin_extent = json.loads(image.extent)
375   - band_data: Band = img.GetRasterBand(band)
376   -
377   - max_level = band_data.GetOverviewCount()
378   -
379   - # 超出空间范围
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]:
381   - empty = numpy.zeros((height, width), dtype=int) + 65536
382   - # 空间范围相交
383   - else:
384   - image_level = self.determine_level(xysize, origin_extent, extent, max_level)
385   -
386   - if image_level == -1:
387   - overview = band_data
388   - else:
389   - try:
390   - overview: Band = band_data.GetOverview(image_level)
391   - except:
392   - raise Exception("该影像不存在该级别的金字塔数据!")
393   - ox = overview.XSize
394   - oy = overview.YSize
395   -
396   - # 网格大小
397   - grid_x = (origin_extent[2] - origin_extent[0]) / (ox * 1.0)
398   - grid_y = (origin_extent[3] - origin_extent[1]) / (oy * 1.0)
399   -
400   - # 完全在影像范围内
401   - if extent[0] > origin_extent[0] and extent[1] > origin_extent[1] and extent[2] < \
402   - origin_extent[2] and extent[3] < origin_extent[3]:
403   -
404   - # 网格偏移量
405   - off_x = math.floor((extent[0] - origin_extent[0]) / grid_x)
406   - off_y = math.floor((origin_extent[3] - extent[3]) / grid_y)
407   -
408   - # 截取后网格个数
409   - x_g = math.ceil((extent[2] - extent[0]) / grid_x)
410   -
411   - y_g = math.ceil((extent[3] - extent[1]) / grid_y)
412   -
413   - empty = overview.ReadAsArray(off_x, off_y, x_g, y_g, width, height)
414   -
415   -
416   - # 部分相交
417   - else:
418   -
419   - inter_extent = [0, 0, 0, 0]
420   - inter_extent[0] = origin_extent[0] if origin_extent[0] > extent[0] else extent[0]
421   - inter_extent[1] = origin_extent[1] if origin_extent[1] > extent[1] else extent[1]
422   - inter_extent[2] = origin_extent[2] if origin_extent[2] < extent[2] else extent[2]
423   - inter_extent[3] = origin_extent[3] if origin_extent[3] < extent[3] else extent[3]
424   -
425   - # 网格偏移量
426   - off_x = math.floor((inter_extent[0] - origin_extent[0]) / grid_x)
427   - off_y = math.floor((origin_extent[3] - inter_extent[3]) / grid_y)
428 173
429   - # 截取后网格个数
430   - x_g = math.floor((inter_extent[2] - inter_extent[0]) / grid_x)
431   - y_g = math.floor((inter_extent[3] - inter_extent[1]) / grid_y)
432 174
433   - # 相对于出图的偏移量
434 175
435   - # 出图的网格大小
436   - out_grid_x = (extent[2] - extent[0]) / (width * 1.0)
437   - out_grid_y = (extent[3] - extent[1]) / (height * 1.0)
438 176
439   - out_off_x = int(math.ceil((inter_extent[0] - extent[0]) / out_grid_x))
440   - out_off_y = int(math.ceil((extent[3] - inter_extent[3]) / out_grid_y))
441 177
442   - out_x_g = int(math.floor((inter_extent[2] - inter_extent[0]) / out_grid_x))
443   - out_y_g = int(math.floor((inter_extent[3] - inter_extent[1]) / out_grid_y))
  178 + def get_capabilities(self):
  179 + return {}
444 180
445   - # 相交部分在出图的哪个位置
446 181
447   - overview_raster: ndarray = overview.ReadAsArray(off_x, off_y, x_g, y_g, out_x_g,
448   - out_y_g)
449   -
450   - dat = numpy.zeros((height, width), dtype=int) + 65536
451   - dat[out_off_y:out_off_y + out_y_g, out_off_x:out_off_x + out_x_g] = overview_raster
452   -
453   - empty = dat
454   -
455   - pixel_array[:, :, ceng] = empty
456   - ceng += 1
457   - return pixel_array
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 182
542 183 def determin_intersect(self, extent1, extent2):
543 184 if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
... ... @@ -580,18 +221,5 @@ class Api(ApiTemplate):
580 221 }
581 222 }
582 223
583   -class MyThread(Thread):
584   - def __init__(self,func,args=()):
585   - super(MyThread,self).__init__()
586   - self.func = func
587   - self.args = args
588   - def run(self):
589   - self.result = self.func(*self.args)
590   - def get_result(self):
591   - try:
592   - return self.result
593   - except Exception:
594   - return None
595   -
596 224
597 225
... ...
... ... @@ -5,25 +5,17 @@
5 5
6 6 from app.util import *
7 7 import traceback
8   -from osgeo import gdal
9   -from osgeo.gdal import *
10   -from numpy import ndarray
11 8 import numpy
12 9 from flask import Response
13 10 import random
14   -import time
15   -import cv2
16 11 from app.modules.service.image.models import ImageService
17 12 from app.util.component.ApiTemplate import ApiTemplate
18   -from app.util.component.GeometryAdapter import GeometryAdapter
19   -from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPool
20 13 from app.util.component.ParameterUtil import ParameterUtil
21 14 import json
22   -from kazoo.client import KazooClient
23   -
24 15 from threading import Thread
25   -from flask import current_app
26   -import gzip
  16 +from .util.ImageData import ImageData
  17 +from .util.Cache import Cache
  18 +from .util.Opencv import Opencv
27 19
28 20 class Api(ApiTemplate):
29 21
... ... @@ -45,7 +37,7 @@ class Api(ApiTemplate):
45 37 image_type = parameter.get("format") if parameter.get("format") else "image/png"
46 38 quality = int(parameter.get("quality")) if parameter.get("quality") else 30
47 39
48   - image_service_info, zoo, servers = self.cache_data()
  40 + image_service_info, zoo, servers = Cache.cache_data(self.guid)
49 41
50 42 re = parameter.get("request")
51 43 if re and re.__eq__("GetCapabilities"):
... ... @@ -78,7 +70,10 @@ class Api(ApiTemplate):
78 70 else:
79 71 image_server = "None"
80 72 bands = json.loads(image.band_view)
81   - thread: MyThread = MyThread(self.get_data, args=(image_server,image,extent,bands,height,width))
  73 +
  74 + image_data = ImageData(image_server, image)
  75 +
  76 + thread: MyThread = MyThread(image_data.get_data, args=(extent,bands,height,width))
82 77 thread.start()
83 78 thread_list.append(thread)
84 79
... ... @@ -116,7 +111,11 @@ class Api(ApiTemplate):
116 111 image_server = "None"
117 112
118 113 bands = json.loads(image.band_view)
119   - pixel_array_t = self.get_data(image_server,image,extent,bands,height,width)
  114 +
  115 + image_data = ImageData(image_server, image)
  116 +
  117 + pixel_array_t = image_data.get_data(extent,bands,height,width)
  118 +
120 119 pixel_array = numpy.zeros((height, width, 3), dtype=int)
121 120 for ii in [0, 1, 2]:
122 121 # opencv 颜色排序为GBR
... ... @@ -126,7 +125,7 @@ class Api(ApiTemplate):
126 125 pixel_array = numpy.zeros((height, width, 3), dtype=int)+65536
127 126
128 127 # 将图片生成在内存中,然后直接返回response
129   - im_data = self.create_by_opencv(image_type, pixel_array, quality)
  128 + im_data = Opencv.create_image(image_type, pixel_array, quality)
130 129
131 130 if self.para.get("overview"):
132 131 return pixel_array
... ... @@ -139,251 +138,6 @@ class Api(ApiTemplate):
139 138 return result
140 139
141 140
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   -
190   - def determine_level(self,xysize,origin_extent,extent,max_level):
191   - '''
192   - 根据范围判断调用金字塔的哪一层
193   - :param xysize:
194   - :param origin_extent:
195   - :param extent:
196   - :param max_level:
197   - :return:
198   - '''
199   - x = xysize[0]
200   - y = xysize[1]
201   - level = -1
202   - pixel = x*y * (((extent[2]-extent[0])*(extent[3]-extent[1]))/((origin_extent[2]-origin_extent[0])*(origin_extent[3]-origin_extent[1])))
203   - while pixel>100000 and level<max_level-1:
204   - level+=1
205   - x=x/2
206   - y=y/2
207   - pixel = x * y * (((extent[2] - extent[0]) * (extent[3] - extent[1])) / (
208   - (origin_extent[2] - origin_extent[0]) * (origin_extent[3] - origin_extent[1])))
209   - return level
210   -
211   - def create_by_opencv(self,image_type, pixel_array, quality):
212   -
213   - if image_type.__eq__("image/jpeg") or image_type.__eq__("image/jpg"):
214   - r, buf = cv2.imencode(".jpg", pixel_array, [cv2.IMWRITE_JPEG_QUALITY, quality])
215   - image_out = buf.tobytes()
216   - else:
217   - height, width = pixel_array[:, :, 0].shape
218   - four = numpy.zeros((height,width), dtype=int) + 255
219   - four[pixel_array[:, :, 0] == 65536] = 0
220   - r, buf = cv2.imencode(".png", numpy.dstack((pixel_array, four)))
221   - image_out = buf.tobytes()
222   - return image_out
223   -
224   - def get_data(self,image_server, image, extent, bands, height, width):
225   -
226   - if image_server.__eq__("本地服务器"):
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
230   - else:
231   - data = self.get_remote_wms_data(image_server,image, extent, bands, height, width)
232   - return data
233   -
234   -
235   -
236   - def get_remote_wms_data(self,image_server,image,extent,bands,height,width):
237   - '''
238   - 通过RPC获取远程数据
239   - :param image:
240   - :param extent:
241   - :param bands:
242   - :return:
243   - '''
244   - thrift_connect = ThriftConnect(image_server)
245   - image_extent = image.extent
246   -
247   - data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands,width,height)
248   -
249   - thrift_connect.close()
250   - # current_app.logger.info("time {}".format(time.time() - t1))
251   - data = gzip.decompress(data)
252   - data = numpy.frombuffer(data, dtype='int64')
253   - data = data.reshape((height,width, 3))
254   -
255   - return data
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   -
284   - def get_local_wms_data(self,image,extent,bands,height,width):
285   - '''
286   - 获取本地数据
287   - :param image:
288   - :param extent:
289   - :param bands:
290   - :return:
291   - '''
292   - pixel_array = numpy.zeros((height,width, 3), dtype=int)
293   - ceng = 0
294   - img: Dataset = gdal.Open(image.path, 0)
295   - t1 = time.time()
296   - for band in bands:
297   -
298   - # 自决定金字塔等级
299   - xysize = [img.RasterXSize, img.RasterYSize]
300   -
301   - origin_extent = json.loads(image.extent)
302   - band_data: Band = img.GetRasterBand(band)
303   -
304   -
305   -
306   - max_level = band_data.GetOverviewCount()
307   -
308   - # 超出空间范围
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]:
310   - empty = numpy.zeros((height,width), dtype=int) + 65536
311   - # 空间范围相交
312   - else:
313   - image_level = self.determine_level(xysize, origin_extent, extent, max_level)
314   -
315   - if image_level == -1:
316   - overview = band_data
317   - else:
318   - try:
319   - overview: Band = band_data.GetOverview(image_level)
320   - except:
321   - raise Exception("该影像不存在该级别的金字塔数据!")
322   - ox = overview.XSize
323   - oy = overview.YSize
324   -
325   - # 网格大小
326   - grid_x = (origin_extent[2] - origin_extent[0]) / (ox * 1.0)
327   - grid_y = (origin_extent[3] - origin_extent[1]) / (oy * 1.0)
328   -
329   - # 完全在影像范围内
330   - if extent[0] > origin_extent[0] and extent[1] > origin_extent[1] and extent[2] < \
331   - origin_extent[2] and extent[3] < origin_extent[3]:
332   -
333   - # 网格偏移量
334   - off_x = math.floor((extent[0] - origin_extent[0]) / grid_x)
335   - off_y = math.floor((origin_extent[3] - extent[3]) / grid_y)
336   -
337   - # 截取后网格个数
338   - x_g = math.ceil((extent[2] - extent[0]) / grid_x)
339   -
340   - y_g = math.ceil((extent[3] - extent[1]) / grid_y)
341   -
342   - empty = overview.ReadAsArray(off_x, off_y, x_g, y_g, width,height)
343   -
344   -
345   - # 部分相交
346   - else:
347   -
348   - inter_extent = [0, 0, 0, 0]
349   - inter_extent[0] = origin_extent[0] if origin_extent[0] > extent[0] else extent[0]
350   - inter_extent[1] = origin_extent[1] if origin_extent[1] > extent[1] else extent[1]
351   - inter_extent[2] = origin_extent[2] if origin_extent[2] < extent[2] else extent[2]
352   - inter_extent[3] = origin_extent[3] if origin_extent[3] < extent[3] else extent[3]
353   -
354   - # 网格偏移量
355   - off_x = math.floor((inter_extent[0] - origin_extent[0]) / grid_x)
356   - off_y = math.floor((origin_extent[3] - inter_extent[3]) / grid_y)
357   -
358   - # 截取后网格个数
359   - x_g = math.floor((inter_extent[2] - inter_extent[0]) / grid_x)
360   - y_g = math.floor((inter_extent[3] - inter_extent[1]) / grid_y)
361   -
362   - # 相对于出图的偏移量
363   -
364   - # 出图的网格大小
365   - out_grid_x = (extent[2] - extent[0]) / (width * 1.0)
366   - out_grid_y = (extent[3] - extent[1]) / (height * 1.0)
367   -
368   - out_off_x = int(math.ceil((inter_extent[0] - extent[0]) / out_grid_x))
369   - out_off_y = int(math.ceil((extent[3] - inter_extent[3]) / out_grid_y))
370   -
371   - out_x_g = int(math.floor((inter_extent[2] - inter_extent[0]) / out_grid_x))
372   - out_y_g = int(math.floor((inter_extent[3] - inter_extent[1]) / out_grid_y))
373   -
374   - # 相交部分在出图的哪个位置
375   -
376   - overview_raster: ndarray = overview.ReadAsArray(off_x, off_y, x_g, y_g, out_x_g,
377   - out_y_g)
378   -
379   - dat = numpy.zeros((height,width), dtype=int) + 65536
380   - dat[out_off_y:out_off_y + out_y_g, out_off_x:out_off_x + out_x_g] = overview_raster
381   -
382   - empty = dat
383   -
384   - pixel_array[:, :, ceng] = empty
385   - ceng += 1
386   - return pixel_array
387 141
388 142 def determin_intersect(self, extent1, extent2):
389 143 if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
... ... @@ -478,6 +232,7 @@ class Api(ApiTemplate):
478 232 <Title>{service_title}</Title>
479 233 <CRS>{crs}</CRS>
480 234 <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>
  235 +
481 236 <Layer queryable="1">
482 237 <CRS>{crs}</CRS>
483 238 <Name>{layer_name}</Name>
... ... @@ -499,7 +254,7 @@ class Api(ApiTemplate):
499 254 maxy = extent[3],
500 255 minx = extent[0],
501 256 miny = extent[1],
502   - url="http://{}/API/Image/WMS?guid={}".format(configure.deploy_ip_host,image_service.guid))
  257 + url="http://{}/API/Service/Image/WMS?guid={}".format(configure.deploy_ip_host,image_service.guid))
503 258
504 259
505 260 r = Response(response=xml, status=200, mimetype="application/xml")
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/3/24
  4 +#email: nheweijun@sina.com
  5 +
  6 +import traceback
  7 +
  8 +import numpy
  9 +from flask import Response
  10 +import random
  11 +
  12 +from app.modules.service.image.models import ImageService,Image
  13 +from app.util.component.ApiTemplate import ApiTemplate
  14 +
  15 +from app.util.component.ParameterUtil import ParameterUtil
  16 +import json
  17 +
  18 +from .util.MyThread import MyThread
  19 +from .util.ImageData import ImageData
  20 +from .util.Opencv import Opencv
  21 +from .util.Cache import Cache
  22 +
  23 +
  24 +class Api(ApiTemplate):
  25 +
  26 + api_name = "发布服务时预览"
  27 +
  28 + def process(self):
  29 +
  30 +
  31 + result = {}
  32 + parameter: dict = self.para
  33 +
  34 + try:
  35 +
  36 + parameter = ParameterUtil.to_lower(parameter)
  37 +
  38 + image_guids = parameter.get("image_guids")
  39 +
  40 + bbox = parameter.get("bbox")
  41 + width = int(parameter.get("width")) if parameter.get("width") else 256
  42 + height = int(parameter.get("height")) if parameter.get("height") else 256
  43 + image_type = parameter.get("format") if parameter.get("format") else "image/png"
  44 + quality = int(parameter.get("quality")) if parameter.get("quality") else 30
  45 +
  46 + image_service_info ,zoo, servers = Cache.cache_data(None)
  47 +
  48 + extent = [float(x) for x in bbox.split(",")]
  49 +
  50 + images = Image.query.filter(Image.guid.in_(image_guids.split(","))).all()
  51 +
  52 + intersect_image = [im for im in images if self.determin_intersect(json.loads(im.extent),extent)]
  53 +
  54 + if len(intersect_image)>1:
  55 +
  56 + # 结果矩阵
  57 + empty_list = [numpy.zeros((height,width), dtype=int) + 65536,
  58 + numpy.zeros((height,width), dtype=int) + 65536,
  59 + numpy.zeros((height,width), dtype=int) + 65536]
  60 +
  61 + pixel_array = numpy.zeros((height,width,3), dtype=int)
  62 + thread_list = []
  63 +
  64 + for image in intersect_image:
  65 + #该影像的服务器,随机选取一个
  66 + image_servers = image.server.split(",")
  67 + image_servers = [ser for ser in image_servers if ser in servers]
  68 + if len(image_servers)>0:
  69 + indx = int(random.random() * len(image_servers))
  70 + image_server = image_servers[indx]
  71 + else:
  72 + image_server = "None"
  73 + bands = json.loads(image.band_view)
  74 +
  75 + image_data = ImageData(image_server, image)
  76 +
  77 + thread: MyThread = MyThread(image_data.get_data, args=(extent,bands,height,width))
  78 + thread.start()
  79 + thread_list.append(thread)
  80 +
  81 +
  82 + for thread in thread_list:
  83 + thread.join()
  84 + data = thread.get_result()
  85 +
  86 + # 掩膜在中央接口生成,合图
  87 + mask = numpy.zeros((height,width), dtype=int)
  88 + mask2 = numpy.zeros((height,width), dtype=int)
  89 + jizhun = data[:, :, 0]
  90 + mask[jizhun == 65536] = 1
  91 + mask[jizhun != 65536] = 0
  92 + mask2[jizhun == 65536] = 0
  93 + mask2[jizhun != 65536] = 1
  94 + # 掩膜计算
  95 + for i, d in enumerate(empty_list):
  96 + empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2
  97 +
  98 + for ii in [0, 1, 2]:
  99 + # opencv 颜色排序为GBR
  100 + pixel_array[:, :, 2 - ii] = empty_list[ii]
  101 +
  102 +
  103 + elif len(intersect_image)==1:
  104 + # 该影像的服务器,随机选取一个
  105 + image = intersect_image[0]
  106 + image_servers = image.server.split(",")
  107 + image_servers = [ser for ser in image_servers if ser in servers]
  108 + if len(image_servers) > 0:
  109 + indx = int(random.random() * len(image_servers))
  110 + image_server = image_servers[indx]
  111 + else:
  112 + image_server = "None"
  113 +
  114 + bands = json.loads(image.band_view)
  115 +
  116 + image_data = ImageData(image_server, image)
  117 +
  118 + pixel_array_t = image_data.get_data(extent,bands,height,width)
  119 + pixel_array = numpy.zeros((height, width, 3), dtype=int)
  120 + for ii in [0, 1, 2]:
  121 + # opencv 颜色排序为GBR
  122 + pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
  123 + else:
  124 + # 结果矩阵
  125 + pixel_array = numpy.zeros((height, width, 3), dtype=int)+65536
  126 +
  127 + # 将图片生成在内存中,然后直接返回response
  128 + im_data = Opencv.create_image(image_type, pixel_array, quality)
  129 +
  130 + if self.para.get("overview"):
  131 + return pixel_array
  132 + return Response(im_data, mimetype=image_type.lower())
  133 +
  134 + except Exception as e:
  135 + print(traceback.format_exc())
  136 + result["state"] = -1
  137 + result["message"] = e.__str__()
  138 + return result
  139 +
  140 + def determin_intersect(self, extent1, extent2):
  141 + if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
  142 + 3] or extent2[3] < extent1[1]:
  143 + return False
  144 + else:
  145 + return True
  146 +
  147 + api_doc = {
  148 + "tags": ["影像接口"],
  149 + "parameters": [
  150 + {"name": "guid",
  151 + "in": "query",
  152 + "type": "string"},
  153 + {"name": "bbox",
  154 + "in": "query",
  155 + "type": "string"},
  156 + {"name": "width",
  157 + "in": "query",
  158 + "type": "string"},
  159 + {"name": "height",
  160 + "in": "query",
  161 + "type": "string"},
  162 + {"name": "format",
  163 + "in": "query",
  164 + "type": "string"},
  165 + {"name": "quality",
  166 + "in": "query",
  167 + "type": "string"}
  168 + ],
  169 + "responses": {
  170 + 200: {
  171 + "schema": {
  172 + "properties": {
  173 + }
  174 + }
  175 + }
  176 + }
  177 + }
  178 +
  179 +
  180 +
  181 +
  182 +
... ...
... ... @@ -17,30 +17,34 @@ class Image(db.Model):
17 17 guid = Column(String(256), primary_key=True)
18 18 name = Column(String)
19 19 alias = Column(String)
20   - raster_y_size = Column(Integer)
21   - raster_x_size = Column(Integer)
22   - overview_count = Column(Integer)
23   - extent = Column(String)
  20 + raster_y_size = Column(Integer)#图像y 分辨率
  21 + raster_x_size = Column(Integer)#图像x 分辨率
  22 + overview_count = Column(Integer)#金字塔等级
  23 + extent = Column(String)#范围
24 24 # geo_origin_extent = Column(String)
25   - null_value = Column(Integer)
  25 + null_value = Column(Integer)#空值
26 26 available = Column(Integer)#影像是否可用,不可用可能在创建金字塔中
27   - band_count = Column(Integer)
28   - band_view = Column(String)
  27 + band_count = Column(Integer)#波段数
  28 + band_view = Column(String)#波段设置
29 29 path = Column(String)
30 30 server = Column(String)
31 31
32 32 size = Column(Float)
33 33 #坐标wkt
34   - sr_wkt = Column(Text)
35   - sr_proj4 = Column(Text)
36   - epsg = Column(Integer)
  34 + sr_wkt = Column(Text) #坐标wkt
  35 + sr_proj4 = Column(Text)#坐标proj
  36 + epsg = Column(Integer)#坐标epsg
37 37 create_time = Column(DateTime)
38 38 update_time = Column(DateTime)
39   - cell_x_size = Column(Float)
40   - cell_y_size = Column(Float)
  39 + cell_x_size = Column(Float)#像元x大小
  40 + cell_y_size = Column(Float)#像元y大小
41 41 region = Column(Text)
42   - #年份
43   - ym = Column(String(256))
  42 +
  43 + ym = Column(String(256))#时间年份
  44 +
  45 + satellite = Column(String)#卫星类型
  46 + type = Column(String(128))
  47 +
44 48
45 49 dmap_image_rel = db.Table('dmap_image_rel',
46 50 Column('image_guid',String, ForeignKey('dmap_image.guid')),
... ...
1   -# coding=utf-8
2   -#author: 4N
3   -#createtime: 2021/9/26
4   -#email: nheweijun@sina.com
5   -
6   -from app.modules.service.image.tutorial2.ttypes import RasterData
7   -
8   -from thrift.transport import TSocket
9   -from thrift.transport import TTransport
10   -from thrift.protocol import TBinaryProtocol
11   -from app.modules.service.image.ImageDataService import ImageDataService
12   -from app.modules.service.image.tutorial2 import Calculator
13   -
14   -from struct import Struct
15   -
16   -host = "192.168.184.246"
17   -port = 9090
18   -transport: TSocket = TSocket.TSocket(host, port)
19   -transport = TTransport.TBufferedTransport(transport)
20   -protocol = TBinaryProtocol.TBinaryProtocol(transport)
21   -
22   -client = Calculator.Client(protocol)
23   -
24   -
25   -transport.open()
26   -
27   -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)
28   -print(type(test))
29   -
30   -
31   -
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/18
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from kazoo.client import KazooClient
  8 +import configure
  9 +import time
  10 +from app.modules.service.image.models import ImageService,Image
  11 +from app.models import TileScheme
  12 +import json
  13 +class Cache:
  14 +
  15 + @classmethod
  16 + def cache_data(cls,guid):
  17 +
  18 + from app import GLOBAL_DIC
  19 +
  20 + # 缓存zookeeper
  21 + zoo = GLOBAL_DIC.get("zookeeper")
  22 + if zoo is None:
  23 + zoo: KazooClient = KazooClient(hosts=configure.zookeeper, timeout=100)
  24 + zoo.start()
  25 + GLOBAL_DIC["zookeeper"] = zoo
  26 + else:
  27 + if not zoo.connected:
  28 + zoo.start()
  29 +
  30 + # 缓存数据服务器
  31 + servers = GLOBAL_DIC.get("servers")
  32 + if servers is None:
  33 + servers = zoo.get_children("/rpc")
  34 + servers.append("本地服务器")
  35 + GLOBAL_DIC["servers"] = servers
  36 + GLOBAL_DIC["servers_updatetime"] = time.time()
  37 + else:
  38 + servers = GLOBAL_DIC.get("servers")
  39 +
  40 + # 更新缓存
  41 + if time.time() - GLOBAL_DIC["servers_updatetime"] > 10:
  42 + servers = zoo.get_children("/rpc")
  43 + servers.append("本地服务器")
  44 + GLOBAL_DIC["servers"] = servers
  45 + GLOBAL_DIC["servers_updatetime"] = time.time()
  46 +
  47 +
  48 + # 缓存服务信息
  49 + if guid:
  50 + image_service_info = GLOBAL_DIC.get(guid)
  51 + if image_service_info is None or time.time() - GLOBAL_DIC.get("service_updatetime") > 20:
  52 + image_service: ImageService = ImageService.query.filter_by(guid=guid).one_or_none()
  53 + images = image_service.images.all()
  54 +
  55 + if image_service.scheme_guid:
  56 + scheme: TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none()
  57 + GLOBAL_DIC[guid] = {"service": image_service, "images": images,
  58 + "scheme": json.loads(scheme.parameter)}
  59 + else:
  60 +
  61 + GLOBAL_DIC[guid] = {"service": image_service, "images": images}
  62 + GLOBAL_DIC["service_updatetime"] = time.time()
  63 + image_service_info = GLOBAL_DIC[guid]
  64 +
  65 + else:
  66 + image_service_info = GLOBAL_DIC[guid]
  67 + else:
  68 + image_service_info = None
  69 +
  70 + return image_service_info,zoo,servers
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/15
  4 +#email: nheweijun@sina.com
  5 +
  6 +from app.util import *
  7 +from osgeo import gdal
  8 +from osgeo.gdal import *
  9 +from numpy import ndarray
  10 +import numpy
  11 +from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPool
  12 +import json
  13 +import gzip
  14 +
  15 +class ImageData:
  16 +
  17 +
  18 + def __init__(self,image_server,image):
  19 + self.image_server = image_server
  20 + self.image = image
  21 +
  22 +
  23 + def get_data(self, extent, bands, height, width):
  24 + if self.image_server.__eq__("本地服务器"):
  25 + data = self.get_local_wms_data(extent, bands, height, width)
  26 + elif self.image_server.__eq__("None"):
  27 + data = numpy.zeros((height, width, 3), dtype=int) + 65536
  28 + else:
  29 + data = self.get_remote_wms_data(extent, bands, height, width)
  30 + return data
  31 +
  32 +
  33 + def get_remote_wms_data(self, extent, bands, height, width):
  34 + '''
  35 + 通过RPC获取远程数据
  36 + :param image:
  37 + :param extent:
  38 + :param bands:
  39 + :return:
  40 + '''
  41 +
  42 + # 需要做thrift连接的缓存,连接池
  43 + thrift_connect = ThriftConnect(self.image_server)
  44 + image_extent = self.image.extent
  45 +
  46 + data = thrift_connect.client.getData(self.image.path, extent, json.loads(image_extent), bands, width, height)
  47 +
  48 + thrift_connect.close()
  49 +
  50 + data = gzip.decompress(data)
  51 + data = numpy.frombuffer(data, dtype='int64')
  52 + data = data.reshape((height, width, 3))
  53 +
  54 + return data
  55 +
  56 +
  57 + def get_remote_wms_data_cpp(self, image_server, image, extent, bands, height, width):
  58 + '''
  59 + 通过RPC获取远程数据
  60 + :param image:
  61 + :param extent:
  62 + :param bands:
  63 + :return:
  64 + '''
  65 +
  66 + # 需要做thrift连接的缓存,连接池
  67 + thrift_connect = ThriftConnect(image_server)
  68 + image_extent = image.extent
  69 +
  70 + data = thrift_connect.client.getData(image.path, extent, json.loads(image_extent), bands, width, height)
  71 +
  72 + thrift_connect.close()
  73 +
  74 + return data
  75 +
  76 +
  77 + def get_local_wms_data(self, extent, bands, height, width):
  78 + '''
  79 + 获取本地数据
  80 + :param image:
  81 + :param extent:
  82 + :param bands:
  83 + :return:
  84 + '''
  85 +
  86 + img: Dataset = gdal.Open(self.image.path, 0)
  87 +
  88 + origin_extent = json.loads(self.image.extent)
  89 +
  90 + # 超出空间范围
  91 + if extent[2] < origin_extent[0] or extent[0] > origin_extent[2] or extent[1] > origin_extent[3] or extent[
  92 + 3] < origin_extent[1]:
  93 + empty = numpy.zeros((height, width, 3), dtype=int) + 65536
  94 + # 空间范围相交
  95 + else:
  96 +
  97 + ox = img.RasterXSize
  98 + oy = img.RasterYSize
  99 +
  100 + # 网格大小
  101 + grid_x = (origin_extent[2] - origin_extent[0]) / (ox * 1.0)
  102 + grid_y = (origin_extent[3] - origin_extent[1]) / (oy * 1.0)
  103 +
  104 + # 完全在影像范围内
  105 + if extent[0] > origin_extent[0] and extent[1] > origin_extent[1] and extent[2] < \
  106 + origin_extent[2] and extent[3] < origin_extent[3]:
  107 +
  108 + # 网格偏移量
  109 + off_x = math.floor((extent[0] - origin_extent[0]) / grid_x)
  110 + off_y = math.floor((origin_extent[3] - extent[3]) / grid_y)
  111 +
  112 + # 截取后网格个数
  113 + x_g = math.ceil((extent[2] - extent[0]) / grid_x)
  114 +
  115 + y_g = math.ceil((extent[3] - extent[1]) / grid_y)
  116 +
  117 + empty = img.ReadRaster(off_x, off_y, x_g, y_g, 256, 256, band_list = bands)
  118 + img.ReadAsArray()
  119 + # 部分相交
  120 + else:
  121 +
  122 + inter_extent = [0, 0, 0, 0]
  123 + inter_extent[0] = origin_extent[0] if origin_extent[0] > extent[0] else extent[0]
  124 + inter_extent[1] = origin_extent[1] if origin_extent[1] > extent[1] else extent[1]
  125 + inter_extent[2] = origin_extent[2] if origin_extent[2] < extent[2] else extent[2]
  126 + inter_extent[3] = origin_extent[3] if origin_extent[3] < extent[3] else extent[3]
  127 +
  128 + # 网格偏移量
  129 + off_x = math.floor((inter_extent[0] - origin_extent[0]) / grid_x)
  130 + off_y = math.floor((origin_extent[3] - inter_extent[3]) / grid_y)
  131 +
  132 + # 截取后网格个数
  133 + x_g = math.floor((inter_extent[2] - inter_extent[0]) / grid_x)
  134 + y_g = math.floor((inter_extent[3] - inter_extent[1]) / grid_y)
  135 +
  136 + # 相对于出图的偏移量
  137 +
  138 + # 出图的网格大小
  139 + out_grid_x = (extent[2] - extent[0]) / (width * 1.0)
  140 + out_grid_y = (extent[3] - extent[1]) / (height * 1.0)
  141 +
  142 + out_off_x = int(math.ceil((inter_extent[0] - extent[0]) / out_grid_x))
  143 + out_off_y = int(math.ceil((extent[3] - inter_extent[3]) / out_grid_y))
  144 +
  145 + out_x_g = int(math.floor((inter_extent[2] - inter_extent[0]) / out_grid_x))
  146 + out_y_g = int(math.floor((inter_extent[3] - inter_extent[1]) / out_grid_y))
  147 +
  148 + # 相交部分在出图的哪个位置
  149 +
  150 + overview_raster: ndarray = img.ReadAsArray(off_x, off_y, x_g, y_g, out_x_g,
  151 + out_y_g)
  152 +
  153 + dat = numpy.zeros((height, width, 3), dtype=int) + 65536
  154 + dat[out_off_y:out_off_y + out_y_g, out_off_x:out_off_x + out_x_g] = overview_raster
  155 + empty = dat
  156 +
  157 + return empty
  158 +
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/18
  4 +#email: nheweijun@sina.com
  5 +import os
  6 +
  7 +class ImageType:
  8 +
  9 + @classmethod
  10 + def get_type(cls,path):
  11 +
  12 + if os.path.isdir(path):
  13 + type = "dir"
  14 + elif path.lower().endswith(".tiff") or path.lower().endswith(".tif"):
  15 + type = "tif"
  16 + elif path.lower().endswith(".img"):
  17 + type = "img"
  18 + else:
  19 + type = None
  20 + return type
  21 +
  22 +
  23 +if __name__ == '__main__':
  24 + print(ImageType.get_type("/da/d/ftif"))
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/18
  4 +#email: nheweijun@sina.com
  5 +
  6 +from threading import Thread
  7 +class MyThread(Thread):
  8 + def __init__(self,func,args=()):
  9 + super(MyThread,self).__init__()
  10 + self.func = func
  11 + self.args = args
  12 + def run(self):
  13 + self.result = self.func(*self.args)
  14 + def get_result(self):
  15 + try:
  16 + return self.result
  17 + except Exception:
  18 + return None
\ No newline at end of file
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/18
  4 +#email: nheweijun@sina.com
  5 +import cv2
  6 +import numpy
  7 +
  8 +class Opencv:
  9 +
  10 + @classmethod
  11 + def create_image(cls,image_type, pixel_array, quality):
  12 +
  13 + if image_type.__eq__("image/jpeg") or image_type.__eq__("image/jpg"):
  14 + r, buf = cv2.imencode(".jpg", pixel_array, [cv2.IMWRITE_JPEG_QUALITY, quality])
  15 + image_out = buf.tobytes()
  16 + else:
  17 + height, width = pixel_array[:, :, 0].shape
  18 + four = numpy.zeros((height,width), dtype=int) + 255
  19 + four[pixel_array[:, :, 0] == 65536] = 0
  20 + r, buf = cv2.imencode(".png", numpy.dstack((pixel_array, four)))
  21 + image_out = buf.tobytes()
  22 + return image_out
\ No newline at end of file
... ...
... ... @@ -13,6 +13,7 @@ from . import scheme_delete
13 13 from . import scheme_edit
14 14 from . import scheme_list
15 15 from . import scheme_resolve
  16 +from . import scheme_info
16 17
17 18 class SchemeManager(BlueprintApi):
18 19
... ... @@ -57,6 +58,15 @@ class SchemeManager(BlueprintApi):
57 58 """
58 59 return scheme_list.Api().result
59 60
  61 + @staticmethod
  62 + @bp.route('/Info', methods=['POST'])
  63 + @swag_from(scheme_info.Api.api_doc)
  64 + def api_scheme_info():
  65 + """
  66 + 切片方案Info
  67 + """
  68 + return scheme_info.Api().result
  69 +
60 70
61 71 @staticmethod
62 72 @bp.route('/Resolve', methods=['POST'])
... ...
  1 +<?xml version="1.0" encoding="utf-8" ?>
  2 +<TileCacheInfo xmlns:typens="http://www.esri.com/schemas/ArcGIS/10.1" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="typens:TileCacheInfo">
  3 + <SpatialReference xsi:type="typens:GeographicCoordinateSystem">
  4 + <WKT>GEOGCS[&quot;GCS_China_Geodetic_Coordinate_System_2000&quot;,DATUM[&quot;D_China_2000&quot;,SPHEROID[&quot;CGCS2000&quot;,6378137.0,298.257222101]],PRIMEM[&quot;Greenwich&quot;,0.0],UNIT[&quot;Degree&quot;,0.0174532925199433],AUTHORITY[&quot;EPSG&quot;,4490]]</WKT>
  5 + <XOrigin>-400</XOrigin>
  6 + <YOrigin>-400</YOrigin>
  7 + <XYScale>11258999068426.24</XYScale>
  8 + <ZOrigin>0</ZOrigin>
  9 + <ZScale>1</ZScale>
  10 + <MOrigin>-100000</MOrigin>
  11 + <MScale>10000</MScale>
  12 + <XYTolerance>8.98315284119521e-009</XYTolerance>
  13 + <ZTolerance>2</ZTolerance>
  14 + <MTolerance>0.001</MTolerance>
  15 + <HighPrecision>true</HighPrecision>
  16 + <LeftLongitude>-180</LeftLongitude>
  17 + <WKID>4490</WKID>
  18 + <LatestWKID>4490</LatestWKID>
  19 + </SpatialReference>
  20 + <TileOrigin xsi:type="typens:PointN">
  21 + <X>-180</X>
  22 + <Y>90</Y>
  23 + </TileOrigin>
  24 + <TileCols>256</TileCols>
  25 + <TileRows>256</TileRows>
  26 + <DPI>96</DPI>
  27 + <PreciseDPI>96</PreciseDPI>
  28 + <LODInfos xsi:type="typens:ArrayOfLODInfo">
  29 + <LODInfo xsi:type="typens:LODInfo">
  30 + <LevelID>0</LevelID>
  31 + <Scale>295497593.05875003</Scale>
  32 + <Resolution>0.70312500000000022</Resolution>
  33 + </LODInfo>
  34 + <LODInfo xsi:type="typens:LODInfo">
  35 + <LevelID>1</LevelID>
  36 + <Scale>147748796.52937502</Scale>
  37 + <Resolution>0.35156250000000011</Resolution>
  38 + </LODInfo>
  39 + <LODInfo xsi:type="typens:LODInfo">
  40 + <LevelID>2</LevelID>
  41 + <Scale>73874398.264687508</Scale>
  42 + <Resolution>0.17578125000000006</Resolution>
  43 + </LODInfo>
  44 + <LODInfo xsi:type="typens:LODInfo">
  45 + <LevelID>3</LevelID>
  46 + <Scale>36937199.132343754</Scale>
  47 + <Resolution>0.087890625000000028</Resolution>
  48 + </LODInfo>
  49 + <LODInfo xsi:type="typens:LODInfo">
  50 + <LevelID>4</LevelID>
  51 + <Scale>18468599.566171877</Scale>
  52 + <Resolution>0.043945312500000014</Resolution>
  53 + </LODInfo>
  54 + <LODInfo xsi:type="typens:LODInfo">
  55 + <LevelID>5</LevelID>
  56 + <Scale>9234299.7830859385</Scale>
  57 + <Resolution>0.021972656250000007</Resolution>
  58 + </LODInfo>
  59 + <LODInfo xsi:type="typens:LODInfo">
  60 + <LevelID>6</LevelID>
  61 + <Scale>4617149.8915429693</Scale>
  62 + <Resolution>0.010986328125000003</Resolution>
  63 + </LODInfo>
  64 + <LODInfo xsi:type="typens:LODInfo">
  65 + <LevelID>7</LevelID>
  66 + <Scale>2308574.9457714846</Scale>
  67 + <Resolution>0.0054931640625000017</Resolution>
  68 + </LODInfo>
  69 + <LODInfo xsi:type="typens:LODInfo">
  70 + <LevelID>8</LevelID>
  71 + <Scale>1154287.4728857423</Scale>
  72 + <Resolution>0.0027465820312500009</Resolution>
  73 + </LODInfo>
  74 + <LODInfo xsi:type="typens:LODInfo">
  75 + <LevelID>9</LevelID>
  76 + <Scale>577143.73644287116</Scale>
  77 + <Resolution>0.0013732910156250004</Resolution>
  78 + </LODInfo>
  79 + <LODInfo xsi:type="typens:LODInfo">
  80 + <LevelID>10</LevelID>
  81 + <Scale>288571.86822143558</Scale>
  82 + <Resolution>0.00068664550781250022</Resolution>
  83 + </LODInfo>
  84 + <LODInfo xsi:type="typens:LODInfo">
  85 + <LevelID>11</LevelID>
  86 + <Scale>144285.93411071779</Scale>
  87 + <Resolution>0.00034332275390625011</Resolution>
  88 + </LODInfo>
  89 + <LODInfo xsi:type="typens:LODInfo">
  90 + <LevelID>12</LevelID>
  91 + <Scale>72142.967055358895</Scale>
  92 + <Resolution>0.00017166137695312505</Resolution>
  93 + </LODInfo>
  94 + <LODInfo xsi:type="typens:LODInfo">
  95 + <LevelID>13</LevelID>
  96 + <Scale>36071.483527679447</Scale>
  97 + <Resolution>8.5830688476562527e-005</Resolution>
  98 + </LODInfo>
  99 + <LODInfo xsi:type="typens:LODInfo">
  100 + <LevelID>14</LevelID>
  101 + <Scale>18035.741763839724</Scale>
  102 + <Resolution>4.2915344238281264e-005</Resolution>
  103 + </LODInfo>
  104 + <LODInfo xsi:type="typens:LODInfo">
  105 + <LevelID>15</LevelID>
  106 + <Scale>9017.8708819198619</Scale>
  107 + <Resolution>2.1457672119140632e-005</Resolution>
  108 + </LODInfo>
  109 + <LODInfo xsi:type="typens:LODInfo">
  110 + <LevelID>16</LevelID>
  111 + <Scale>4508.9354409599309</Scale>
  112 + <Resolution>1.0728836059570316e-005</Resolution>
  113 + </LODInfo>
  114 + <LODInfo xsi:type="typens:LODInfo">
  115 + <LevelID>17</LevelID>
  116 + <Scale>2254.4677204799655</Scale>
  117 + <Resolution>5.3644180297851579e-006</Resolution>
  118 + </LODInfo>
  119 + <LODInfo xsi:type="typens:LODInfo">
  120 + <LevelID>18</LevelID>
  121 + <Scale>1127.2338602399827</Scale>
  122 + <Resolution>2.682209014892579e-006</Resolution>
  123 + </LODInfo>
  124 + <LODInfo xsi:type="typens:LODInfo">
  125 + <LevelID>19</LevelID>
  126 + <Scale>563.61693011999137</Scale>
  127 + <Resolution>1.3411045074462895e-006</Resolution>
  128 + </LODInfo>
  129 + </LODInfos>
  130 +</TileCacheInfo>
\ No newline at end of file
... ...
... ... @@ -24,15 +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 = {}
  27 + parameter = {}
28 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])
  29 + parameter[str(l_dict["level"])] = {"resolution":l_dict["resolution"],"scale":l_dict["scale"]}
  30 + parameter["cols"] = int(data.get("cols"))
  31 + parameter["rows"] = int(data.get("rows"))
  32 + parameter["dpi"] = int(data.get("dpi"))
  33 + parameter["wkt"] = data.get("crs_wkt")
  34 + parameter["x"] = eval(data.get("top_left").split(",")[0])
  35 + parameter["y"] = eval(data.get("top_left").split(",")[1])
36 36
37 37
38 38 guid = uuid.uuid1().__str__()
... ... @@ -55,7 +55,7 @@ class Api(ApiTemplate):
55 55 rows = int(data.get("rows")),
56 56 cols = int(data.get("cols")),
57 57 update_time = datetime.datetime.now(),
58   - parameter=json.dumps(paramenter)
  58 + parameter=json.dumps(parameter)
59 59 )
60 60
61 61 db.session.add(tile_scheme)
... ... @@ -77,6 +77,9 @@ class Api(ApiTemplate):
77 77 {"name": "alias",
78 78 "in": "formData",
79 79 "type": "string"},
  80 + {"name": "description",
  81 + "in": "formData",
  82 + "type": "string"},
80 83 {"name": "crs",
81 84 "in": "formData",
82 85 "type": "string"},
... ...
... ... @@ -8,7 +8,7 @@ import uuid
8 8 from app.models import TileScheme,db
9 9 from app.util.component.ApiTemplate import ApiTemplate
10 10 import datetime
11   -
  11 +import json
12 12 class Api(ApiTemplate):
13 13 api_name = "修改方案"
14 14
... ... @@ -30,9 +30,24 @@ class Api(ApiTemplate):
30 30 update_dict = data
31 31 update_dict["update_time"] = datetime.datetime.now()
32 32 del update_dict["guid"]
  33 + if update_dict:
  34 +
  35 + TileScheme.query.filter_by(guid=guid).update(update_dict)
  36 + db.session.commit()
33 37
34   - tile_scheme.update(update_dict)
35   - db.session.commit()
  38 + #更新parameter
  39 + tile_scheme: TileScheme = TileScheme.query.filter_by(guid=guid).one_or_none()
  40 + parameter = {}
  41 + for l_dict in json.loads(tile_scheme.levels):
  42 + parameter[str(l_dict["level"])] = {"resolution": l_dict["resolution"], "scale": l_dict["scale"]}
  43 + parameter["cols"] = tile_scheme.cols
  44 + parameter["rows"] = tile_scheme.rows
  45 + parameter["dpi"] = tile_scheme.dpi
  46 + parameter["wkt"] = tile_scheme.crs_wkt
  47 + parameter["x"] = eval(tile_scheme.top_left.split(",")[0])
  48 + parameter["y"] = eval(tile_scheme.top_left.split(",")[1])
  49 + TileScheme.query.filter_by(guid=guid).update({"parameter":json.dumps(parameter)})
  50 + db.session.commit()
36 51
37 52 res["data"] = guid
38 53 res["result"] = True
... ... @@ -54,6 +69,9 @@ class Api(ApiTemplate):
54 69 {"name": "alias",
55 70 "in": "formData",
56 71 "type": "string"},
  72 + {"name": "description",
  73 + "in": "formData",
  74 + "type": "string"},
57 75 {"name": "crs",
58 76 "in": "formData",
59 77 "type": "string"},
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/9/16
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +import uuid
  8 +from app.models import TileScheme,db
  9 +from app.util.component.ApiTemplate import ApiTemplate
  10 +from app.util.component.ModelVisitor import ModelVisitor
  11 +from sqlalchemy import or_
  12 +import datetime
  13 +
  14 +class Api(ApiTemplate):
  15 + api_name = "切片方案Info"
  16 +
  17 + def process(self):
  18 +
  19 + # 返回结果
  20 + res = {}
  21 +
  22 + try:
  23 + # 业务逻辑
  24 +
  25 + guid = self.para.get("guid")
  26 + scheme = TileScheme.query.filter_by(guid=guid).one_or_none()
  27 + if not scheme:
  28 + raise Exception("数据不存在!")
  29 + res["data"] = ModelVisitor.object_to_json(scheme)
  30 + res["result"] = True
  31 +
  32 + except Exception as e:
  33 + raise e
  34 +
  35 + return res
  36 +
  37 + api_doc = {
  38 +
  39 + "tags": ["方案接口"],
  40 + "parameters": [
  41 + {"name": "guid",
  42 + "in": "formData",
  43 + "type": "string"},
  44 + ],
  45 + "responses": {
  46 + 200: {
  47 + "schema": {
  48 + "properties": {
  49 + }
  50 + }
  51 + }
  52 + }
  53 + }
\ No newline at end of file
... ...
... ... @@ -27,7 +27,7 @@ class Api(ApiTemplate):
27 27
28 28 alias = self.para.get("alias")
29 29 name = self.para.get("name")
30   - schemes = TileScheme.query
  30 + schemes = TileScheme.query.order_by(TileScheme.update_time.desc())
31 31
32 32 # 并集
33 33 if alias and name:
... ... @@ -38,9 +38,10 @@ class Api(ApiTemplate):
38 38 if name:
39 39 schemes = schemes.filter(TileScheme.name.like("%" + name + "%"))
40 40
41   - schemes = schemes.limit(page_size).offset(page_index).all()
42   -
43   - res["data"] = ModelVisitor.objects_to_jsonarray(schemes)
  41 + res["data"] = {}
  42 + res["data"]["count"] = schemes.count()
  43 + schemes = schemes.limit(page_size).offset(page_index * page_size).all()
  44 + res["data"]["list"] = ModelVisitor.objects_to_jsonarray(schemes)
44 45 res["result"] = True
45 46
46 47 except Exception as e:
... ...
... ... @@ -7,22 +7,26 @@
7 7
8 8
9 9 from app.util.component.ApiTemplate import ApiTemplate
  10 +from app.models import Service
10 11
11 12 class Api(ApiTemplate):
12 13 api_name = "修改服务"
13 14 def process(self):
14 15 res = {}
15 16 try:
  17 + service = Service.query.filter_by(guid=self.para.get("guid")).one_or_none()
  18 + if not service:
  19 + raise Exception("服务不存在!")
16 20
17   - if self.para.get("type")in ["ImageWMTS","ImageWMS"]:
18   - from app.modules.service.image.image_service_edit import Api as Api2
19   - elif self.para.get("type").__eq__("WMS/WFS"):
20   - from app.modules.service.wms.wms_edit import Api as Api2
21   - elif self.para.get("type") in ["WMTS","MTS"]:
22   - from app.modules.service.wmts.wmts_edit import Api as Api2
  21 + if service.type in ["ImageWMTS","ImageWMS"]:
  22 + from app.modules.service.image.image_service_edit import Api as RealApi
  23 + elif service.type in ["WMS/WFS"]:
  24 + from app.modules.service.wms.wms_edit import Api as RealApi
  25 + elif service.type in ["WMTS","TMS"]:
  26 + from app.modules.service.wmts.wmts_edit import Api as RealApi
23 27 else:
24 28 return res
25   - api = Api2()
  29 + api = RealApi()
26 30 api.para = self.para
27 31 res = api.process()
28 32
... ... @@ -35,13 +39,23 @@ class Api(ApiTemplate):
35 39 "tags": ["服务接口"],
36 40 "parameters": [
37 41
  42 + {"name": "guid",
  43 + "in": "formData",
  44 + "type": "string",
  45 + "description": "[WMS,WMTS,影像WMS,影像WMTS,guid]"},
  46 +
  47 + # {"name": "type",
  48 + # "in": "formData",
  49 + # "type": "string",
  50 + # "enum": ["WMS/WFS", "WMTS", "TMS", "ImageWMS", "ImageWMTS"],
  51 + # "required": "true",
  52 + # "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
38 53
39 54 {"name": "name",
40 55 "in": "formData",
41 56 "type": "string",
42   - "required": "true",
43 57 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
44   - {"name": "alias",
  58 + {"name": "title",
45 59 "in": "formData",
46 60 "type": "string",
47 61 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
... ... @@ -56,7 +70,7 @@ class Api(ApiTemplate):
56 70 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
57 71
58 72 # 影像参数
59   - {"name": "guids",
  73 + {"name": "image_guids",
60 74 "in": "formData",
61 75 "type": "string",
62 76 "description": "[影像WMS,影像WMTS]影像guids,以英文逗号相隔"},
... ...
... ... @@ -15,19 +15,34 @@ class Api(ApiTemplate):
15 15 try:
16 16 guid = self.para.get("guid")
17 17 service = Service.query.filter_by(guid=guid).one_or_none()
  18 + if not service:
  19 + raise Exception("服务不存在!")
  20 + res["data"] = {}
18 21
19 22 if service.type in ["ImageWMS","ImageWMTS"]:
20 23 from app.modules.service.image.models import ImageService
21   - speci_service = ImageService.query.filter_by(guid=guid).one_or_none()
22   - elif service.type.__eq__("WMTS") or service.type.__eq__("MTS"):
  24 + speci_service = ImageService.query.filter_by(guid=service.service_guid).one_or_none()
  25 + relate_images = speci_service.images.all()
  26 + res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service)
  27 +
  28 + res["data"]["speci_service"]["images"] = [{"name":im["name"],"guid":im["guid"]} for im in ModelVisitor.objects_to_jsonarray(relate_images)]
  29 + res["data"]["speci_service"]["images"] = sorted(res["data"]["speci_service"]["images"], key=lambda x: x["name"])
  30 +
  31 + elif service.type.__eq__("WMTS") or service.type.__eq__("TMS"):
23 32 from app.modules.service.wmts.models import WMTS
24   - speci_service = WMTS.query.filter_by(guid=guid).one_or_none()
  33 + speci_service = WMTS.query.filter_by(guid=service.service_guid).one_or_none()
  34 +
  35 + res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service)
  36 +
25 37 elif service.type.__eq__("WMS/WFS"):
26 38 from app.modules.service.wms.models import WMS
27   - speci_service = WMS.query.filter_by(guid=guid).one_or_none()
  39 + speci_service = WMS.query.filter_by(guid=service.service_guid).one_or_none()
  40 + res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service)
28 41 else:
29   - speci_service = {}
30   - res["data"] = ModelVisitor.object_to_json(speci_service)
  42 + res["data"] = {}
  43 +
  44 + res["data"]["service"] = ModelVisitor.object_to_json(service)
  45 +
31 46 except Exception as e:
32 47 raise e
33 48 return res
... ...
... ... @@ -22,31 +22,31 @@ class Api(ApiTemplate):
22 22 page_index = int(self.para.get("page_index", "0"))
23 23 page_size = int(self.para.get("page_size", "10"))
24 24
25   - alias = self.para.get("alias")
  25 + title = self.para.get("title")
26 26 name = self.para.get("name")
27 27 type = self.para.get("type")
28 28
29 29 catalog_guid = self.para.get("catalog_guid")
30 30
31   - services = Service.query
  31 + services = Service.query.order_by(Service.update_time.desc())
32 32 if type:
33 33 services = services.filter_by(type=type)
34 34
35 35 if catalog_guid:
36 36 services = services.filter_by(catalog_guid=catalog_guid)
37 37 # 并集
38   - if alias and name:
  38 + if title and name:
39 39 services = services.filter(
40   - or_(Service.alias.like("%" + alias + "%"), Service.name.like("%" + name + "%")))
  40 + or_(Service.title.like("%" + title + "%"), Service.name.like("%" + name + "%")))
41 41 else:
42   - if alias:
43   - services = services.filter(Service.alias.like("%" + alias + "%"))
  42 + if title:
  43 + services = services.filter(Service.title.like("%" + title + "%"))
44 44 if name:
45 45 services = services.filter(Service.name.like("%" + name + "%"))
46   -
47   - services = services.limit(page_size).offset(page_index).all()
48   -
49   - res["data"] = ModelVisitor.objects_to_jsonarray(services)
  46 + res["data"] = {}
  47 + res["data"]["count"] = services.count()
  48 + services = services.limit(page_size).offset(page_index * page_size).all()
  49 + res["data"]["list"] = ModelVisitor.objects_to_jsonarray(services)
50 50 res["result"] = True
51 51
52 52
... ... @@ -66,10 +66,10 @@ class Api(ApiTemplate):
66 66 "in": "formData",
67 67 "type": "int",
68 68 "description": "页大小"},
69   - {"name": "alias",
  69 + {"name": "title",
70 70 "in": "formData",
71 71 "type": "string",
72   - "description": "服务别名"},
  72 + "description": "服务标题"},
73 73 {"name": "name",
74 74 "in": "formData",
75 75 "type": "string",
... ...
... ... @@ -14,18 +14,15 @@ class Api(ApiTemplate):
14 14 service = Service.query.filter_by(name=self.para.get("name")).one_or_none()
15 15 if service:
16 16 raise Exception("服务已存在!")
17   -
18   - if self.para.get("type").__eq__("ImageWMS"):
19   - from app.modules.service.image.image_service_register import Api as Api2
20   - elif self.para.get("type").__eq__("ImageWMTS"):
21   - from app.modules.service.image.image_service_register import Api as Api2
  17 + if self.para.get("type").__eq__("ImageWMS") or self.para.get("type").__eq__("ImageWMTS"):
  18 + from app.modules.service.image.image_service_register import Api as RealApi
22 19 elif self.para.get("type").__eq__("WMS"):
23   - from app.modules.service.wms.wms_register import Api as Api2
24   - elif self.para.get("type").__eq__("WMTS") or self.para.get("type").__eq__("MTS"):
25   - from app.modules.service.wmts.wmts_register import Api as Api2
  20 + from app.modules.service.wms.wms_register import Api as RealApi
  21 + elif self.para.get("type").__eq__("WMTS") or self.para.get("type").__eq__("TMS"):
  22 + from app.modules.service.wmts.wmts_register import Api as RealApi
26 23 else:
27 24 return res
28   - api = Api2()
  25 + api = RealApi()
29 26 api.para = self.para
30 27 res = api.process()
31 28 except Exception as e:
... ... @@ -43,7 +40,7 @@ class Api(ApiTemplate):
43 40 "type": "string",
44 41 "required": "true",
45 42 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
46   - {"name": "alias",
  43 + {"name": "title",
47 44 "in": "formData",
48 45 "type": "string",
49 46 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
... ... @@ -54,7 +51,7 @@ class Api(ApiTemplate):
54 51 {"name": "type",
55 52 "in": "formData",
56 53 "type": "string",
57   - "enum":["WMS/WFS","WMTS","MTS","ImageWMS","ImageWMTS"],
  54 + "enum":["WMS/WFS","WMTS","TMS","ImageWMS","ImageWMTS"],
58 55 "required": "true",
59 56 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
60 57 {"name": "catalog_guid",
... ...
... ... @@ -17,12 +17,8 @@ class Api(ApiTemplate):
17 17 state = int(self.para.get("state"))
18 18 Service.query.filter_by(guid=guid).update({"state":state})
19 19
20   -
21   - #更新缓存
22   -
23   -
24   -
25 20 db.session.commit()
  21 + res["result"] = True
26 22 except Exception as e:
27 23 raise e
28 24 return res
... ... @@ -35,7 +31,7 @@ class Api(ApiTemplate):
35 31 "in": "formData",
36 32 "type": "string",
37 33 "description": "guid"},
38   - {"name": "stat",
  34 + {"name": "state",
39 35 "in": "formData",
40 36 "type": "int",
41 37 "description": "state"},
... ...
注册登录 后发表评论