提交 c39bdbc1612fde43b8322a43755c1f73312f1fb2

作者 nheweijun
1 个父辈 e29795f6

面向对象优化

正在显示 60 个修改的文件 包含 2998 行增加1345 行删除
@@ -192,7 +192,10 @@ class Service(db.Model): @@ -192,7 +192,10 @@ class Service(db.Model):
192 __tablename__ = 'dmap_service' 192 __tablename__ = 'dmap_service'
193 guid = Column(String(256), primary_key=True) 193 guid = Column(String(256), primary_key=True)
194 name = Column(String(256)) 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 state= Column(Integer) 200 state= Column(Integer)
198 create_time = Column(DateTime) 201 create_time = Column(DateTime)
@@ -217,7 +220,6 @@ class ServiceCatalog(db.Model): @@ -217,7 +220,6 @@ class ServiceCatalog(db.Model):
217 ''' 220 '''
218 __tablename__ = 'dmap_service_catalog' 221 __tablename__ = 'dmap_service_catalog'
219 guid = Column(String(256), primary_key=True) 222 guid = Column(String(256), primary_key=True)
220 - database_guid = Column(String(256), ForeignKey('dmap_database.guid'))  
221 pguid = Column(String(256)) 223 pguid = Column(String(256))
222 path = Column(Text) 224 path = Column(Text)
223 name = Column(String(256)) 225 name = Column(String(256))
@@ -8,7 +8,7 @@ from app.util import BlueprintApi @@ -8,7 +8,7 @@ from app.util import BlueprintApi
8 8
9 from flask import send_from_directory 9 from flask import send_from_directory
10 import os 10 import os
11 -from . import data_download 11 +from . import data_download,data_download_task
12 from . import get_meta 12 from . import get_meta
13 from . import data_entry_by_meta 13 from . import data_entry_by_meta
14 from . import get_data_list 14 from . import get_data_list
@@ -64,6 +64,15 @@ class DataManager(BlueprintApi): @@ -64,6 +64,15 @@ class DataManager(BlueprintApi):
64 """ 64 """
65 return data_download.Api().result 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 @staticmethod 77 @staticmethod
69 @bp.route('/GetMeta', methods=['POST']) 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 +}
  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,6 +11,8 @@ from . import service_exist_type
11 from . import service_list 11 from . import service_list
12 from . import service_delete 12 from . import service_delete
13 from . import service_state 13 from . import service_state
  14 +from . import service_info
  15 +from . import service_edit
14 import os 16 import os
15 from flask import send_from_directory 17 from flask import send_from_directory
16 18
@@ -40,7 +42,7 @@ class DataManager(BlueprintApi): @@ -40,7 +42,7 @@ class DataManager(BlueprintApi):
40 return service_exist_type.Api().result 42 return service_exist_type.Api().result
41 43
42 @staticmethod 44 @staticmethod
43 - @bp.route('/State', methods=['GET']) 45 + @bp.route('/State', methods=['POST'])
44 @swag_from(service_state.Api.api_doc) 46 @swag_from(service_state.Api.api_doc)
45 def api_service_state(): 47 def api_service_state():
46 """ 48 """
@@ -57,6 +59,25 @@ class DataManager(BlueprintApi): @@ -57,6 +59,25 @@ class DataManager(BlueprintApi):
57 """ 59 """
58 return service_list.Api().result 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 @staticmethod 82 @staticmethod
62 @bp.route('/Delete', methods=['POST']) 83 @bp.route('/Delete', methods=['POST'])
@@ -19,8 +19,7 @@ class Api(ApiTemplate): @@ -19,8 +19,7 @@ class Api(ApiTemplate):
19 19
20 20
21 if ServiceCatalog.query.filter_by(name=self.para.get("name"), 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 res["msg"]="目录已经存在!" 23 res["msg"]="目录已经存在!"
25 return res 24 return res
26 25
@@ -38,11 +38,6 @@ class Api(ApiTemplate): @@ -38,11 +38,6 @@ class Api(ApiTemplate):
38 "in": "formData", 38 "in": "formData",
39 "type": "string", 39 "type": "string",
40 "description":"目录guid","required": "true"}, 40 "description":"目录guid","required": "true"},
41 - {"name": "database_guid",  
42 - "in": "formData",  
43 - "type": "string",  
44 - "description": "数据库guid", "required": "true"},  
45 -  
46 ], 41 ],
47 "responses":{ 42 "responses":{
48 200:{ 43 200:{
@@ -52,11 +52,6 @@ class Api(ApiTemplate): @@ -52,11 +52,6 @@ class Api(ApiTemplate):
52 52
53 "tags":["服务目录接口"], 53 "tags":["服务目录接口"],
54 "parameters":[ 54 "parameters":[
55 - {"name": "database_guid",  
56 - "in": "formData",  
57 - "type": "string",  
58 - "description": "数据库guid", "required": "true"},  
59 -  
60 ], 55 ],
61 "responses":{ 56 "responses":{
62 200:{ 57 200:{
@@ -21,7 +21,6 @@ class Api(ApiTemplate): @@ -21,7 +21,6 @@ class Api(ApiTemplate):
21 catalog_guids = [c.guid for c in ServiceCatalog.query.filter(ServiceCatalog.path.like("%" + cata.guid + "%")).all()] 21 catalog_guids = [c.guid for c in ServiceCatalog.query.filter(ServiceCatalog.path.like("%" + cata.guid + "%")).all()]
22 service_count = Service.query.filter(Service.catalog_guid.in_(catalog_guids)).count() 22 service_count = Service.query.filter(Service.catalog_guid.in_(catalog_guids)).count()
23 cata_json ={} 23 cata_json ={}
24 - cata_json["database_guid"]=cata.database_guid  
25 cata_json["description"] = cata.description 24 cata_json["description"] = cata.description
26 cata_json["guid"] = cata.guid 25 cata_json["guid"] = cata.guid
27 cata_json["name"] = cata.name 26 cata_json["name"] = cata.name
@@ -41,11 +40,6 @@ class Api(ApiTemplate): @@ -41,11 +40,6 @@ class Api(ApiTemplate):
41 40
42 "tags":["服务目录接口"], 41 "tags":["服务目录接口"],
43 "parameters":[ 42 "parameters":[
44 - {"name": "database_guid",  
45 - "in": "formData",  
46 - "type": "string",  
47 - "description": "数据库guid", "required": "true"},  
48 -  
49 ], 43 ],
50 "responses":{ 44 "responses":{
51 200:{ 45 200:{
@@ -15,7 +15,8 @@ from . import image_tile,image_wms @@ -15,7 +15,8 @@ from . import image_tile,image_wms
15 from . import image_service_list 15 from . import image_service_list
16 from . import image_tile_mask 16 from . import image_tile_mask
17 17
18 - 18 +from . import image_delete
  19 +from . import image_cancle
19 from . import image_register,image_list,image_info,image_edit,image_overview 20 from . import image_register,image_list,image_info,image_edit,image_overview
20 from . import image_tag_create,image_tag_delete,image_tag_list 21 from . import image_tag_create,image_tag_delete,image_tag_list
21 22
@@ -34,12 +35,31 @@ class DataManager(BlueprintApi): @@ -34,12 +35,31 @@ class DataManager(BlueprintApi):
34 """ 35 """
35 return image_register.Api().result 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 @staticmethod 57 @staticmethod
38 @bp.route('/Edit', methods=['POST']) 58 @bp.route('/Edit', methods=['POST'])
39 @swag_from(image_edit.Api.api_doc) 59 @swag_from(image_edit.Api.api_doc)
40 def api_image_edit(): 60 def api_image_edit():
41 """ 61 """
42 - 影像Info 62 + 影像Edit
43 """ 63 """
44 return image_edit.Api().result 64 return image_edit.Api().result
45 65
@@ -129,7 +149,7 @@ class DataManager(BlueprintApi): @@ -129,7 +149,7 @@ class DataManager(BlueprintApi):
129 return data_list.Api().result 149 return data_list.Api().result
130 150
131 @staticmethod 151 @staticmethod
132 - @bp.route('/Capabilities', methods=['POST']) 152 + @bp.route('/Capabilities', methods=['GET','POST'])
133 @swag_from(capabilities.Api.api_doc) 153 @swag_from(capabilities.Api.api_doc)
134 def capabilities(): 154 def capabilities():
135 """ 155 """
@@ -156,6 +176,17 @@ class DataManager(BlueprintApi): @@ -156,6 +176,17 @@ class DataManager(BlueprintApi):
156 """ 176 """
157 return image_tile.Api(guid,l,y,z).result 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 @staticmethod 190 @staticmethod
160 @bp.route('/Tile', methods=['GET','POST']) 191 @bp.route('/Tile', methods=['GET','POST'])
161 @swag_from(image_tile.Api.api_doc) 192 @swag_from(image_tile.Api.api_doc)
@@ -6,489 +6,297 @@ @@ -6,489 +6,297 @@
6 6
7 from flask import Response 7 from flask import Response
8 from app.util.component.ApiTemplate import ApiTemplate 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 class Api(ApiTemplate): 15 class Api(ApiTemplate):
10 16
11 - api_name = "影像数据列表" 17 + api_name = "影像能力文档"
12 18
13 def process(self): 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 r.headers["Content-Type"] = "text/xml; charset=utf-8" 37 r.headers["Content-Type"] = "text/xml; charset=utf-8"
489 return r 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 api_doc = { 302 api_doc = {
@@ -13,6 +13,7 @@ from app.modules.service.image.util.ThriftConnect import ThriftConnect @@ -13,6 +13,7 @@ from app.modules.service.image.util.ThriftConnect import ThriftConnect
13 import os 13 import os
14 from app.models import db 14 from app.models import db
15 from app.modules.service.image.models import Image 15 from app.modules.service.image.models import Image
  16 +from .util.ImageType import ImageType
16 17
17 class Api(ApiTemplate): 18 class Api(ApiTemplate):
18 19
@@ -50,21 +51,16 @@ class Api(ApiTemplate): @@ -50,21 +51,16 @@ class Api(ApiTemplate):
50 if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif") or file_path.lower().endswith("img"): 51 if file_path.lower().endswith("tiff") or file_path.lower().endswith("tif") or file_path.lower().endswith("img"):
51 52
52 exist_image: Image = Image.query.filter_by(path=os.path.normpath(file_info.get("path")), 53 exist_image: Image = Image.query.filter_by(path=os.path.normpath(file_info.get("path")),
53 - size=file_info.get("size")).one_or_none() 54 + size=file_info.get("real_size")).one_or_none()
54 file_info["exist"] = False 55 file_info["exist"] = False
55 if exist_image: 56 if exist_image:
56 if exist_image.server.__contains__(data_server): 57 if exist_image.server.__contains__(data_server):
57 file_info["exist"] = True 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 data_list_sorted = sorted(data_list, key=lambda x: x["name"]) 65 data_list_sorted = sorted(data_list, key=lambda x: x["name"])
70 res["data"] = data_list_sorted 66 res["data"] = data_list_sorted
@@ -76,8 +72,8 @@ class Api(ApiTemplate): @@ -76,8 +72,8 @@ class Api(ApiTemplate):
76 72
77 for inf in info: 73 for inf in info:
78 if inf["path"].lower().endswith("tiff") or inf["path"].lower().endswith("tif") or inf["path"].lower().endswith("img"): 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 size=inf.get("real_size")).one_or_none() 77 size=inf.get("real_size")).one_or_none()
82 inf["exist"] = False 78 inf["exist"] = False
83 if exist_image: 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,7 +8,7 @@
8 from app.util.component.ApiTemplate import ApiTemplate 8 from app.util.component.ApiTemplate import ApiTemplate
9 from app.util.component.ModelVisitor import ModelVisitor 9 from app.util.component.ModelVisitor import ModelVisitor
10 10
11 -from app.modules.service.image.models import Image,db 11 +from app.modules.service.image.models import Image,db,ImageTag
12 from sqlalchemy import or_,and_ 12 from sqlalchemy import or_,and_
13 import datetime 13 import datetime
14 class Api(ApiTemplate): 14 class Api(ApiTemplate):
@@ -22,10 +22,24 @@ class Api(ApiTemplate): @@ -22,10 +22,24 @@ class Api(ApiTemplate):
22 try: 22 try:
23 para = self.para 23 para = self.para
24 guid = self.para.get("guid") 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 del para["guid"] 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 db.session.commit() 43 db.session.commit()
30 44
31 res["result"] = True 45 res["result"] = True
@@ -38,6 +52,9 @@ class Api(ApiTemplate): @@ -38,6 +52,9 @@ class Api(ApiTemplate):
38 api_doc = { 52 api_doc = {
39 "tags": ["影像接口"], 53 "tags": ["影像接口"],
40 "parameters": [ 54 "parameters": [
  55 + {"name": "guid",
  56 + "in": "formData",
  57 + "type": "string"},
41 {"name": "alias", 58 {"name": "alias",
42 "in": "formData", 59 "in": "formData",
43 "type": "string"}, 60 "type": "string"},
@@ -47,6 +64,15 @@ class Api(ApiTemplate): @@ -47,6 +64,15 @@ class Api(ApiTemplate):
47 {"name": "region", 64 {"name": "region",
48 "in": "formData", 65 "in": "formData",
49 "type": "string", "description": "所属区域"}, 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 "responses": { 77 "responses": {
52 200: { 78 200: {
@@ -9,6 +9,7 @@ from app.util.component.ModelVisitor import ModelVisitor @@ -9,6 +9,7 @@ from app.util.component.ModelVisitor import ModelVisitor
9 9
10 from app.modules.service.image.models import Image,ImageTag 10 from app.modules.service.image.models import Image,ImageTag
11 from sqlalchemy import or_,and_ 11 from sqlalchemy import or_,and_
  12 +from app.util.component.FileProcess import FileProcess
12 class Api(ApiTemplate): 13 class Api(ApiTemplate):
13 14
14 api_name = "影像数据Info" 15 api_name = "影像数据Info"
@@ -24,11 +25,18 @@ class Api(ApiTemplate): @@ -24,11 +25,18 @@ class Api(ApiTemplate):
24 image = Image.query.filter_by(guid=guid).one_or_none() 25 image = Image.query.filter_by(guid=guid).one_or_none()
25 if not image: 26 if not image:
26 raise Exception("数据不存在!") 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 res["data"] = ModelVisitor.object_to_json(image) 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 res["result"] = True 40 res["result"] = True
33 except Exception as e: 41 except Exception as e:
34 raise e 42 raise e
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 6
7 from app.util.component.ApiTemplate import ApiTemplate 7 from app.util.component.ApiTemplate import ApiTemplate
8 from app.util.component.ModelVisitor import ModelVisitor 8 from app.util.component.ModelVisitor import ModelVisitor
9 - 9 +from app.util.component.FileProcess import FileProcess
10 from app.modules.service.image.models import Image,ImageTag 10 from app.modules.service.image.models import Image,ImageTag
11 from sqlalchemy import or_,and_ 11 from sqlalchemy import or_,and_
12 class Api(ApiTemplate): 12 class Api(ApiTemplate):
@@ -23,9 +23,13 @@ class Api(ApiTemplate): @@ -23,9 +23,13 @@ class Api(ApiTemplate):
23 23
24 alias = self.para.get("alias") 24 alias = self.para.get("alias")
25 name = self.para.get("name") 25 name = self.para.get("name")
  26 + band = self.para.get("band")
  27 + region = self.para.get("region")
26 tag_guid = self.para.get("tag_guid") 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 if alias and name: 35 if alias and name:
@@ -35,16 +39,33 @@ class Api(ApiTemplate): @@ -35,16 +39,33 @@ class Api(ApiTemplate):
35 images = images.filter(Image.alias.like("%" + alias + "%")) 39 images = images.filter(Image.alias.like("%" + alias + "%"))
36 if name: 40 if name:
37 images = images.filter(Image.name.like("%" + name + "%")) 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 if tag_guid: 51 if tag_guid:
39 tag:ImageTag = ImageTag.query.filter_by(guid=tag_guid).one_or_none() 52 tag:ImageTag = ImageTag.query.filter_by(guid=tag_guid).one_or_none()
40 images_guid = [img.guid for img in tag.images.all()] 53 images_guid = [img.guid for img in tag.images.all()]
41 images = images.filter(Image.guid.in_(images_guid)) 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 res["result"] = True 67 res["result"] = True
  68 +
48 except Exception as e: 69 except Exception as e:
49 raise e 70 raise e
50 71
@@ -68,6 +89,18 @@ class Api(ApiTemplate): @@ -68,6 +89,18 @@ class Api(ApiTemplate):
68 {"name": "name", 89 {"name": "name",
69 "in": "formData", 90 "in": "formData",
70 "type": "string"}, 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 {"name": "tag_guid", 104 {"name": "tag_guid",
72 "in": "formData", 105 "in": "formData",
73 "type": "string"}, 106 "type": "string"},
@@ -8,9 +8,9 @@ from app.util.component.ApiTemplate import ApiTemplate @@ -8,9 +8,9 @@ from app.util.component.ApiTemplate import ApiTemplate
8 from app.util.component.StructuredPrint import StructurePrint 8 from app.util.component.StructuredPrint import StructurePrint
9 9
10 from app.modules.service.image.models import Image 10 from app.modules.service.image.models import Image
11 -from sqlalchemy import or_ 11 +
12 import random 12 import random
13 -from .image_wms import Api as WMSApi 13 +
14 import numpy 14 import numpy
15 import json 15 import json
16 from flask import Response 16 from flask import Response
@@ -18,6 +18,8 @@ from kazoo.client import KazooClient @@ -18,6 +18,8 @@ from kazoo.client import KazooClient
18 import configure 18 import configure
19 import traceback 19 import traceback
20 20
  21 +from .util.ImageData import ImageData
  22 +from .util.Opencv import Opencv
21 23
22 class Api(ApiTemplate): 24 class Api(ApiTemplate):
23 25
@@ -44,6 +46,12 @@ class Api(ApiTemplate): @@ -44,6 +46,12 @@ class Api(ApiTemplate):
44 46
45 47
46 guid = self.para.get("guid") 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 image = Image.query.filter_by(guid=guid).one_or_none() 55 image = Image.query.filter_by(guid=guid).one_or_none()
48 # 该影像的服务器,随机选取一个 56 # 该影像的服务器,随机选取一个
49 image_servers = image.server.split(",") 57 image_servers = image.server.split(",")
@@ -54,8 +62,6 @@ class Api(ApiTemplate): @@ -54,8 +62,6 @@ class Api(ApiTemplate):
54 else: 62 else:
55 image_server = "None" 63 image_server = "None"
56 64
57 - wms_api = WMSApi()  
58 -  
59 bands = json.loads(image.band_view) 65 bands = json.loads(image.band_view)
60 66
61 # bands = [1,2,3] if image.band_count>=3 else [1,1,1] 67 # bands = [1,2,3] if image.band_count>=3 else [1,1,1]
@@ -70,18 +76,20 @@ class Api(ApiTemplate): @@ -70,18 +76,20 @@ class Api(ApiTemplate):
70 query_extent = [query_extent[0] - offset, query_extent[1], query_extent[2] + offset, query_extent[3]] 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 for ii in [0, 1, 2]: 85 for ii in [0, 1, 2]:
78 # opencv 颜色排序为GBR 86 # opencv 颜色排序为GBR
79 pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] 87 pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
80 88
81 # 将图片生成在内存中,然后直接返回response 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 except Exception as e: 94 except Exception as e:
87 StructurePrint().print(traceback.format_exc()) 95 StructurePrint().print(traceback.format_exc())
@@ -96,6 +104,16 @@ class Api(ApiTemplate): @@ -96,6 +104,16 @@ class Api(ApiTemplate):
96 {"name": "guid", 104 {"name": "guid",
97 "in": "formData", 105 "in": "formData",
98 "type": "string"}, 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 "responses": { 118 "responses": {
101 200: { 119 200: {
@@ -107,4 +125,3 @@ class Api(ApiTemplate): @@ -107,4 +125,3 @@ class Api(ApiTemplate):
107 } 125 }
108 } 126 }
109 127
110 -  
@@ -16,6 +16,7 @@ import uuid @@ -16,6 +16,7 @@ import uuid
16 import os 16 import os
17 from .models import ImageTag 17 from .models import ImageTag
18 import math 18 import math
  19 +from .util.ImageType import ImageType
19 20
20 class Api(ApiTemplate): 21 class Api(ApiTemplate):
21 22
@@ -117,7 +118,8 @@ class Api(ApiTemplate): @@ -117,7 +118,8 @@ class Api(ApiTemplate):
117 if exist_image.server.__contains__(data_server): 118 if exist_image.server.__contains__(data_server):
118 pass 119 pass
119 else: 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 else: 123 else:
122 img:Image = Image(guid= uuid.uuid1().__str__(), 124 img:Image = Image(guid= uuid.uuid1().__str__(),
123 overview_count=info.get("overview_count"), 125 overview_count=info.get("overview_count"),
@@ -136,7 +138,10 @@ class Api(ApiTemplate): @@ -136,7 +138,10 @@ class Api(ApiTemplate):
136 sr_wkt = info.get("sr_wkt"), 138 sr_wkt = info.get("sr_wkt"),
137 sr_proj4= info.get("sr_proj4"), 139 sr_proj4= info.get("sr_proj4"),
138 band_count=info.get("band_count"), 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 for tag in tags: 146 for tag in tags:
142 img.image_tags.append(tag) 147 img.image_tags.append(tag)
@@ -25,8 +25,13 @@ class Api(ApiTemplate): @@ -25,8 +25,13 @@ class Api(ApiTemplate):
25 else : 25 else :
26 if not zoo.connected: 26 if not zoo.connected:
27 zoo.start() 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 res["result"] = True 35 res["result"] = True
31 except Exception as e: 36 except Exception as e:
32 raise e 37 raise e
@@ -8,6 +8,11 @@ from app.models import db @@ -8,6 +8,11 @@ from app.models import db
8 from app.util.component.ApiTemplate import ApiTemplate 8 from app.util.component.ApiTemplate import ApiTemplate
9 from app.models import Service 9 from app.models import Service
10 import datetime 10 import datetime
  11 +import json
  12 +from .image_service_register import Api as RegisterApi
  13 +import configure
  14 +
  15 +
11 class Api(ApiTemplate): 16 class Api(ApiTemplate):
12 17
13 api_name = "修改影像服务" 18 api_name = "修改影像服务"
@@ -20,40 +25,97 @@ class Api(ApiTemplate): @@ -20,40 +25,97 @@ class Api(ApiTemplate):
20 try: 25 try:
21 26
22 guid = self.para.get("guid") 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 this_time = datetime.datetime.now() 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 for key in self.para.keys(): 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 service_update[key] = self.para.get(key) 36 service_update[key] = self.para.get(key)
32 if key in ["name","scheme_guid"]: 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 db.session.commit() 77 db.session.commit()
41 78
42 res["result"] = True 79 res["result"] = True
43 except Exception as e: 80 except Exception as e:
  81 + db.session.rollback()
44 raise e 82 raise e
45 83
46 return res 84 return res
47 85
  86 +
48 api_doc = { 87 api_doc = {
49 "tags": ["影像接口"], 88 "tags": ["影像接口"],
50 "parameters": [ 89 "parameters": [
  90 +
51 {"name": "guid", 91 {"name": "guid",
52 "in": "formData", 92 "in": "formData",
53 - "type": "string"}, 93 + "type": "string",
  94 + "description": "[WMS,WMTS,影像WMS,影像WMTS,guid]"},
  95 +
54 {"name": "name", 96 {"name": "name",
55 "in": "formData", 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 "responses": { 120 "responses": {
59 200: { 121 200: {
@@ -39,10 +39,13 @@ class Api(ApiTemplate): @@ -39,10 +39,13 @@ class Api(ApiTemplate):
39 if name: 39 if name:
40 services = services.filter(ImageService.name.like("%" + name + "%")) 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 res["result"] = True 47 res["result"] = True
  48 +
46 except Exception as e: 49 except Exception as e:
47 raise e 50 raise e
48 51
@@ -12,7 +12,7 @@ from app.util.component.FileProcess import FileProcess @@ -12,7 +12,7 @@ from app.util.component.FileProcess import FileProcess
12 import os 12 import os
13 import json 13 import json
14 import datetime 14 import datetime
15 -from .image_wms import Api as Api2 15 +from .image_wms import Api as RealApi
16 import cv2 16 import cv2
17 import configure 17 import configure
18 18
@@ -62,7 +62,7 @@ class Api(ApiTemplate): @@ -62,7 +62,7 @@ class Api(ApiTemplate):
62 service = Service( 62 service = Service(
63 guid = service_guid, 63 guid = service_guid,
64 name = self.para.get("name"), 64 name = self.para.get("name"),
65 - alias = self.para.get("alias"), 65 + title = self.para.get("title"),
66 state = 1, 66 state = 1,
67 create_time = this_time, 67 create_time = this_time,
68 update_time = this_time, 68 update_time = this_time,
@@ -93,7 +93,7 @@ class Api(ApiTemplate): @@ -93,7 +93,7 @@ class Api(ApiTemplate):
93 93
94 def get_overview(self,service,image_service): 94 def get_overview(self,service,image_service):
95 95
96 - api = Api2() 96 + api = RealApi()
97 97
98 98
99 query_extent = json.loads(image_service.extent) 99 query_extent = json.loads(image_service.extent)
@@ -106,7 +106,7 @@ class Api(ApiTemplate): @@ -106,7 +106,7 @@ class Api(ApiTemplate):
106 106
107 bbox = ",".join([str(x) for x in query_extent]) 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 res = api.process() 110 res = api.process()
111 dir_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "overview") 111 dir_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "overview")
112 gid = uuid.uuid1().__str__() 112 gid = uuid.uuid1().__str__()
@@ -128,7 +128,7 @@ class Api(ApiTemplate): @@ -128,7 +128,7 @@ class Api(ApiTemplate):
128 "type": "string", 128 "type": "string",
129 "required": "true", 129 "required": "true",
130 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 130 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
131 - {"name": "alias", 131 + {"name": "title",
132 "in": "formData", 132 "in": "formData",
133 "type": "string", 133 "type": "string",
134 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 134 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
@@ -139,7 +139,7 @@ class Api(ApiTemplate): @@ -139,7 +139,7 @@ class Api(ApiTemplate):
139 {"name": "type", 139 {"name": "type",
140 "in": "formData", 140 "in": "formData",
141 "type": "string", 141 "type": "string",
142 - "enum": ["WMS/WFS","WMTS","MTS","ImageWMS","ImageWMTS"], 142 + "enum": ["WMS/WFS","WMTS","TMS","ImageWMS","ImageWMTS"],
143 "required": "true", 143 "required": "true",
144 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 144 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
145 {"name": "catalog_guid", 145 {"name": "catalog_guid",
@@ -19,8 +19,12 @@ class Api(ApiTemplate): @@ -19,8 +19,12 @@ class Api(ApiTemplate):
19 res = {} 19 res = {}
20 try: 20 try:
21 image_tags = ImageTag.query.all() 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 res["result"] = True 26 res["result"] = True
  27 +
24 except Exception as e: 28 except Exception as e:
25 raise e 29 raise e
26 return res 30 return res
@@ -10,9 +10,7 @@ from osgeo.gdal import * @@ -10,9 +10,7 @@ from osgeo.gdal import *
10 from numpy import ndarray 10 from numpy import ndarray
11 import numpy 11 import numpy
12 from flask import Response 12 from flask import Response
13 -import io  
14 -import os  
15 -from PIL import Image 13 +from .util.ImageData import ImageData
16 14
17 import time 15 import time
18 import cv2 16 import cv2
@@ -28,8 +26,9 @@ from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPoo @@ -28,8 +26,9 @@ from app.modules.service.image.util.ThriftConnect import ThriftConnect,ThriftPoo
28 import gzip 26 import gzip
29 import random 27 import random
30 import copy 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 class Api(ApiTemplate): 33 class Api(ApiTemplate):
35 34
@@ -51,7 +50,7 @@ class Api(ApiTemplate): @@ -51,7 +50,7 @@ class Api(ApiTemplate):
51 if parameter.get("guid"): 50 if parameter.get("guid"):
52 self.guid = parameter.get("guid") 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 # bands = [1, 2, 3] 55 # bands = [1, 2, 3]
57 56
@@ -75,6 +74,11 @@ class Api(ApiTemplate): @@ -75,6 +74,11 @@ class Api(ApiTemplate):
75 74
76 height, width = 256,256 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 intersect_image = [im for im in image_service_info["images"] if self.determin_intersect(json.loads(im.extent),extent)] 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,8 +103,10 @@ class Api(ApiTemplate):
99 103
100 bands = json.loads(image.band_view) 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 thread.start() 110 thread.start()
105 thread_list.append(thread) 111 thread_list.append(thread)
106 112
@@ -139,7 +145,9 @@ class Api(ApiTemplate): @@ -139,7 +145,9 @@ class Api(ApiTemplate):
139 image_server = "None" 145 image_server = "None"
140 # image_server = image_servers[0] 146 # image_server = image_servers[0]
141 bands = json.loads(image.band_view) 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 pixel_array = numpy.zeros((height, width, 3), dtype=int) 151 pixel_array = numpy.zeros((height, width, 3), dtype=int)
144 152
145 for ii in [0, 1, 2]: 153 for ii in [0, 1, 2]:
@@ -152,7 +160,7 @@ class Api(ApiTemplate): @@ -152,7 +160,7 @@ class Api(ApiTemplate):
152 160
153 161
154 # 将图片生成在内存中,然后直接返回response 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 return Response(im_data, mimetype=image_type.lower()) 164 return Response(im_data, mimetype=image_type.lower())
157 165
158 166
@@ -162,382 +170,15 @@ class Api(ApiTemplate): @@ -162,382 +170,15 @@ class Api(ApiTemplate):
162 result["message"] = e.__str__() 170 result["message"] = e.__str__()
163 return result 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 def determin_intersect(self, extent1, extent2): 183 def determin_intersect(self, extent1, extent2):
543 if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ 184 if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
@@ -580,18 +221,5 @@ class Api(ApiTemplate): @@ -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,25 +5,17 @@
5 5
6 from app.util import * 6 from app.util import *
7 import traceback 7 import traceback
8 -from osgeo import gdal  
9 -from osgeo.gdal import *  
10 -from numpy import ndarray  
11 import numpy 8 import numpy
12 from flask import Response 9 from flask import Response
13 import random 10 import random
14 -import time  
15 -import cv2  
16 from app.modules.service.image.models import ImageService 11 from app.modules.service.image.models import ImageService
17 from app.util.component.ApiTemplate import ApiTemplate 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 from app.util.component.ParameterUtil import ParameterUtil 13 from app.util.component.ParameterUtil import ParameterUtil
21 import json 14 import json
22 -from kazoo.client import KazooClient  
23 -  
24 from threading import Thread 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 class Api(ApiTemplate): 20 class Api(ApiTemplate):
29 21
@@ -45,7 +37,7 @@ class Api(ApiTemplate): @@ -45,7 +37,7 @@ class Api(ApiTemplate):
45 image_type = parameter.get("format") if parameter.get("format") else "image/png" 37 image_type = parameter.get("format") if parameter.get("format") else "image/png"
46 quality = int(parameter.get("quality")) if parameter.get("quality") else 30 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 re = parameter.get("request") 42 re = parameter.get("request")
51 if re and re.__eq__("GetCapabilities"): 43 if re and re.__eq__("GetCapabilities"):
@@ -78,7 +70,10 @@ class Api(ApiTemplate): @@ -78,7 +70,10 @@ class Api(ApiTemplate):
78 else: 70 else:
79 image_server = "None" 71 image_server = "None"
80 bands = json.loads(image.band_view) 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 thread.start() 77 thread.start()
83 thread_list.append(thread) 78 thread_list.append(thread)
84 79
@@ -116,7 +111,11 @@ class Api(ApiTemplate): @@ -116,7 +111,11 @@ class Api(ApiTemplate):
116 image_server = "None" 111 image_server = "None"
117 112
118 bands = json.loads(image.band_view) 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 pixel_array = numpy.zeros((height, width, 3), dtype=int) 119 pixel_array = numpy.zeros((height, width, 3), dtype=int)
121 for ii in [0, 1, 2]: 120 for ii in [0, 1, 2]:
122 # opencv 颜色排序为GBR 121 # opencv 颜色排序为GBR
@@ -126,7 +125,7 @@ class Api(ApiTemplate): @@ -126,7 +125,7 @@ class Api(ApiTemplate):
126 pixel_array = numpy.zeros((height, width, 3), dtype=int)+65536 125 pixel_array = numpy.zeros((height, width, 3), dtype=int)+65536
127 126
128 # 将图片生成在内存中,然后直接返回response 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 if self.para.get("overview"): 130 if self.para.get("overview"):
132 return pixel_array 131 return pixel_array
@@ -139,251 +138,6 @@ class Api(ApiTemplate): @@ -139,251 +138,6 @@ class Api(ApiTemplate):
139 return result 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 def determin_intersect(self, extent1, extent2): 142 def determin_intersect(self, extent1, extent2):
389 if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ 143 if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[
@@ -478,6 +232,7 @@ class Api(ApiTemplate): @@ -478,6 +232,7 @@ class Api(ApiTemplate):
478 <Title>{service_title}</Title> 232 <Title>{service_title}</Title>
479 <CRS>{crs}</CRS> 233 <CRS>{crs}</CRS>
480 <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/> 234 <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/>
  235 +
481 <Layer queryable="1"> 236 <Layer queryable="1">
482 <CRS>{crs}</CRS> 237 <CRS>{crs}</CRS>
483 <Name>{layer_name}</Name> 238 <Name>{layer_name}</Name>
@@ -499,7 +254,7 @@ class Api(ApiTemplate): @@ -499,7 +254,7 @@ class Api(ApiTemplate):
499 maxy = extent[3], 254 maxy = extent[3],
500 minx = extent[0], 255 minx = extent[0],
501 miny = extent[1], 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 r = Response(response=xml, status=200, mimetype="application/xml") 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,30 +17,34 @@ class Image(db.Model):
17 guid = Column(String(256), primary_key=True) 17 guid = Column(String(256), primary_key=True)
18 name = Column(String) 18 name = Column(String)
19 alias = Column(String) 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 # geo_origin_extent = Column(String) 24 # geo_origin_extent = Column(String)
25 - null_value = Column(Integer) 25 + null_value = Column(Integer)#空值
26 available = Column(Integer)#影像是否可用,不可用可能在创建金字塔中 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 path = Column(String) 29 path = Column(String)
30 server = Column(String) 30 server = Column(String)
31 31
32 size = Column(Float) 32 size = Column(Float)
33 #坐标wkt 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 create_time = Column(DateTime) 37 create_time = Column(DateTime)
38 update_time = Column(DateTime) 38 update_time = Column(DateTime)
39 - cell_x_size = Column(Float)  
40 - cell_y_size = Column(Float) 39 + cell_x_size = Column(Float)#像元x大小
  40 + cell_y_size = Column(Float)#像元y大小
41 region = Column(Text) 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 dmap_image_rel = db.Table('dmap_image_rel', 49 dmap_image_rel = db.Table('dmap_image_rel',
46 Column('image_guid',String, ForeignKey('dmap_image.guid')), 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
  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"))
  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
  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
@@ -13,6 +13,7 @@ from . import scheme_delete @@ -13,6 +13,7 @@ from . import scheme_delete
13 from . import scheme_edit 13 from . import scheme_edit
14 from . import scheme_list 14 from . import scheme_list
15 from . import scheme_resolve 15 from . import scheme_resolve
  16 +from . import scheme_info
16 17
17 class SchemeManager(BlueprintApi): 18 class SchemeManager(BlueprintApi):
18 19
@@ -57,6 +58,15 @@ class SchemeManager(BlueprintApi): @@ -57,6 +58,15 @@ class SchemeManager(BlueprintApi):
57 """ 58 """
58 return scheme_list.Api().result 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 @staticmethod 71 @staticmethod
62 @bp.route('/Resolve', methods=['POST']) 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>
@@ -24,15 +24,15 @@ class Api(ApiTemplate): @@ -24,15 +24,15 @@ class Api(ApiTemplate):
24 # extent = [float(x) for x in data.get("extent").split(",")] if data.get("extent") else [0,0,0,0] 24 # extent = [float(x) for x in data.get("extent").split(",")] if data.get("extent") else [0,0,0,0]
25 # top_left = [float(x) for x in data.get("top_left").split(",")] if data.get("top_left") else [0, 0] 25 # top_left = [float(x) for x in data.get("top_left").split(",")] if data.get("top_left") else [0, 0]
26 26
27 - paramenter = {} 27 + parameter = {}
28 for l_dict in json.loads(data.get("levels")): 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 guid = uuid.uuid1().__str__() 38 guid = uuid.uuid1().__str__()
@@ -55,7 +55,7 @@ class Api(ApiTemplate): @@ -55,7 +55,7 @@ class Api(ApiTemplate):
55 rows = int(data.get("rows")), 55 rows = int(data.get("rows")),
56 cols = int(data.get("cols")), 56 cols = int(data.get("cols")),
57 update_time = datetime.datetime.now(), 57 update_time = datetime.datetime.now(),
58 - parameter=json.dumps(paramenter) 58 + parameter=json.dumps(parameter)
59 ) 59 )
60 60
61 db.session.add(tile_scheme) 61 db.session.add(tile_scheme)
@@ -77,6 +77,9 @@ class Api(ApiTemplate): @@ -77,6 +77,9 @@ class Api(ApiTemplate):
77 {"name": "alias", 77 {"name": "alias",
78 "in": "formData", 78 "in": "formData",
79 "type": "string"}, 79 "type": "string"},
  80 + {"name": "description",
  81 + "in": "formData",
  82 + "type": "string"},
80 {"name": "crs", 83 {"name": "crs",
81 "in": "formData", 84 "in": "formData",
82 "type": "string"}, 85 "type": "string"},
@@ -8,7 +8,7 @@ import uuid @@ -8,7 +8,7 @@ import uuid
8 from app.models import TileScheme,db 8 from app.models import TileScheme,db
9 from app.util.component.ApiTemplate import ApiTemplate 9 from app.util.component.ApiTemplate import ApiTemplate
10 import datetime 10 import datetime
11 - 11 +import json
12 class Api(ApiTemplate): 12 class Api(ApiTemplate):
13 api_name = "修改方案" 13 api_name = "修改方案"
14 14
@@ -30,9 +30,24 @@ class Api(ApiTemplate): @@ -30,9 +30,24 @@ class Api(ApiTemplate):
30 update_dict = data 30 update_dict = data
31 update_dict["update_time"] = datetime.datetime.now() 31 update_dict["update_time"] = datetime.datetime.now()
32 del update_dict["guid"] 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 res["data"] = guid 52 res["data"] = guid
38 res["result"] = True 53 res["result"] = True
@@ -54,6 +69,9 @@ class Api(ApiTemplate): @@ -54,6 +69,9 @@ class Api(ApiTemplate):
54 {"name": "alias", 69 {"name": "alias",
55 "in": "formData", 70 "in": "formData",
56 "type": "string"}, 71 "type": "string"},
  72 + {"name": "description",
  73 + "in": "formData",
  74 + "type": "string"},
57 {"name": "crs", 75 {"name": "crs",
58 "in": "formData", 76 "in": "formData",
59 "type": "string"}, 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 + }
@@ -27,7 +27,7 @@ class Api(ApiTemplate): @@ -27,7 +27,7 @@ class Api(ApiTemplate):
27 27
28 alias = self.para.get("alias") 28 alias = self.para.get("alias")
29 name = self.para.get("name") 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 if alias and name: 33 if alias and name:
@@ -38,9 +38,10 @@ class Api(ApiTemplate): @@ -38,9 +38,10 @@ class Api(ApiTemplate):
38 if name: 38 if name:
39 schemes = schemes.filter(TileScheme.name.like("%" + name + "%")) 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 res["result"] = True 45 res["result"] = True
45 46
46 except Exception as e: 47 except Exception as e:
@@ -7,22 +7,26 @@ @@ -7,22 +7,26 @@
7 7
8 8
9 from app.util.component.ApiTemplate import ApiTemplate 9 from app.util.component.ApiTemplate import ApiTemplate
  10 +from app.models import Service
10 11
11 class Api(ApiTemplate): 12 class Api(ApiTemplate):
12 api_name = "修改服务" 13 api_name = "修改服务"
13 def process(self): 14 def process(self):
14 res = {} 15 res = {}
15 try: 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 else: 27 else:
24 return res 28 return res
25 - api = Api2() 29 + api = RealApi()
26 api.para = self.para 30 api.para = self.para
27 res = api.process() 31 res = api.process()
28 32
@@ -35,13 +39,23 @@ class Api(ApiTemplate): @@ -35,13 +39,23 @@ class Api(ApiTemplate):
35 "tags": ["服务接口"], 39 "tags": ["服务接口"],
36 "parameters": [ 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 {"name": "name", 54 {"name": "name",
40 "in": "formData", 55 "in": "formData",
41 "type": "string", 56 "type": "string",
42 - "required": "true",  
43 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 57 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
44 - {"name": "alias", 58 + {"name": "title",
45 "in": "formData", 59 "in": "formData",
46 "type": "string", 60 "type": "string",
47 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 61 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
@@ -56,7 +70,7 @@ class Api(ApiTemplate): @@ -56,7 +70,7 @@ class Api(ApiTemplate):
56 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 70 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
57 71
58 # 影像参数 72 # 影像参数
59 - {"name": "guids", 73 + {"name": "image_guids",
60 "in": "formData", 74 "in": "formData",
61 "type": "string", 75 "type": "string",
62 "description": "[影像WMS,影像WMTS]影像guids,以英文逗号相隔"}, 76 "description": "[影像WMS,影像WMTS]影像guids,以英文逗号相隔"},
@@ -15,19 +15,34 @@ class Api(ApiTemplate): @@ -15,19 +15,34 @@ class Api(ApiTemplate):
15 try: 15 try:
16 guid = self.para.get("guid") 16 guid = self.para.get("guid")
17 service = Service.query.filter_by(guid=guid).one_or_none() 17 service = Service.query.filter_by(guid=guid).one_or_none()
  18 + if not service:
  19 + raise Exception("服务不存在!")
  20 + res["data"] = {}
18 21
19 if service.type in ["ImageWMS","ImageWMTS"]: 22 if service.type in ["ImageWMS","ImageWMTS"]:
20 from app.modules.service.image.models import ImageService 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 from app.modules.service.wmts.models import WMTS 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 elif service.type.__eq__("WMS/WFS"): 37 elif service.type.__eq__("WMS/WFS"):
26 from app.modules.service.wms.models import WMS 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 else: 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 except Exception as e: 46 except Exception as e:
32 raise e 47 raise e
33 return res 48 return res
@@ -22,31 +22,31 @@ class Api(ApiTemplate): @@ -22,31 +22,31 @@ class Api(ApiTemplate):
22 page_index = int(self.para.get("page_index", "0")) 22 page_index = int(self.para.get("page_index", "0"))
23 page_size = int(self.para.get("page_size", "10")) 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 name = self.para.get("name") 26 name = self.para.get("name")
27 type = self.para.get("type") 27 type = self.para.get("type")
28 28
29 catalog_guid = self.para.get("catalog_guid") 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 if type: 32 if type:
33 services = services.filter_by(type=type) 33 services = services.filter_by(type=type)
34 34
35 if catalog_guid: 35 if catalog_guid:
36 services = services.filter_by(catalog_guid=catalog_guid) 36 services = services.filter_by(catalog_guid=catalog_guid)
37 # 并集 37 # 并集
38 - if alias and name: 38 + if title and name:
39 services = services.filter( 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 else: 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 if name: 44 if name:
45 services = services.filter(Service.name.like("%" + name + "%")) 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 res["result"] = True 50 res["result"] = True
51 51
52 52
@@ -66,10 +66,10 @@ class Api(ApiTemplate): @@ -66,10 +66,10 @@ class Api(ApiTemplate):
66 "in": "formData", 66 "in": "formData",
67 "type": "int", 67 "type": "int",
68 "description": "页大小"}, 68 "description": "页大小"},
69 - {"name": "alias", 69 + {"name": "title",
70 "in": "formData", 70 "in": "formData",
71 "type": "string", 71 "type": "string",
72 - "description": "服务别名"}, 72 + "description": "服务标题"},
73 {"name": "name", 73 {"name": "name",
74 "in": "formData", 74 "in": "formData",
75 "type": "string", 75 "type": "string",
@@ -14,18 +14,15 @@ class Api(ApiTemplate): @@ -14,18 +14,15 @@ class Api(ApiTemplate):
14 service = Service.query.filter_by(name=self.para.get("name")).one_or_none() 14 service = Service.query.filter_by(name=self.para.get("name")).one_or_none()
15 if service: 15 if service:
16 raise Exception("服务已存在!") 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 elif self.para.get("type").__eq__("WMS"): 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 else: 23 else:
27 return res 24 return res
28 - api = Api2() 25 + api = RealApi()
29 api.para = self.para 26 api.para = self.para
30 res = api.process() 27 res = api.process()
31 except Exception as e: 28 except Exception as e:
@@ -43,7 +40,7 @@ class Api(ApiTemplate): @@ -43,7 +40,7 @@ class Api(ApiTemplate):
43 "type": "string", 40 "type": "string",
44 "required": "true", 41 "required": "true",
45 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 42 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
46 - {"name": "alias", 43 + {"name": "title",
47 "in": "formData", 44 "in": "formData",
48 "type": "string", 45 "type": "string",
49 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 46 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
@@ -54,7 +51,7 @@ class Api(ApiTemplate): @@ -54,7 +51,7 @@ class Api(ApiTemplate):
54 {"name": "type", 51 {"name": "type",
55 "in": "formData", 52 "in": "formData",
56 "type": "string", 53 "type": "string",
57 - "enum":["WMS/WFS","WMTS","MTS","ImageWMS","ImageWMTS"], 54 + "enum":["WMS/WFS","WMTS","TMS","ImageWMS","ImageWMTS"],
58 "required": "true", 55 "required": "true",
59 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 56 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
60 {"name": "catalog_guid", 57 {"name": "catalog_guid",
@@ -17,12 +17,8 @@ class Api(ApiTemplate): @@ -17,12 +17,8 @@ class Api(ApiTemplate):
17 state = int(self.para.get("state")) 17 state = int(self.para.get("state"))
18 Service.query.filter_by(guid=guid).update({"state":state}) 18 Service.query.filter_by(guid=guid).update({"state":state})
19 19
20 -  
21 - #更新缓存  
22 -  
23 -  
24 -  
25 db.session.commit() 20 db.session.commit()
  21 + res["result"] = True
26 except Exception as e: 22 except Exception as e:
27 raise e 23 raise e
28 return res 24 return res
@@ -35,7 +31,7 @@ class Api(ApiTemplate): @@ -35,7 +31,7 @@ class Api(ApiTemplate):
35 "in": "formData", 31 "in": "formData",
36 "type": "string", 32 "type": "string",
37 "description": "guid"}, 33 "description": "guid"},
38 - {"name": "stat", 34 + {"name": "state",
39 "in": "formData", 35 "in": "formData",
40 "type": "int", 36 "type": "int",
41 "description": "state"}, 37 "description": "state"},
@@ -23,14 +23,14 @@ class Api(ApiTemplate): @@ -23,14 +23,14 @@ class Api(ApiTemplate):
23 23
24 try: 24 try:
25 guid = self.para.get("guid") 25 guid = self.para.get("guid")
26 - service = Service.query.filter_by(guid=guid).one_or_none() 26 + service = Service.query.filter_by(guid=guid)
27 this_time = datetime.datetime.now() 27 this_time = datetime.datetime.now()
28 28
29 29
30 - service_update = {"upate_time":this_time}  
31 - wms_update = {"upatetime":this_time} 30 + service_update = {"update_time":this_time}
  31 + wms_update = {"updatetime":this_time}
32 for key in self.para.keys(): 32 for key in self.para.keys():
33 - if key in ["name","alias","state","description","overview","catalog_guid"]: 33 + if key in ["name","title","state","description","overview","catalog_guid"]:
34 service_update[key] = self.para.get(key) 34 service_update[key] = self.para.get(key)
35 if key in ["status","description","username","readonly", 35 if key in ["status","description","username","readonly",
36 "sid","stype","ssupply","sctime","company","abstract","thumbnail","layer_style"]: 36 "sid","stype","ssupply","sctime","company","abstract","thumbnail","layer_style"]:
@@ -40,9 +40,12 @@ class Api(ApiTemplate): @@ -40,9 +40,12 @@ class Api(ApiTemplate):
40 40
41 41
42 42
43 - wms = WMS.query.filter_by(guid=service.service_guid).one_or_none()  
44 - service.update(service_update)  
45 - wms.update(wms_update) 43 + wms = WMS.query.filter_by(guid=Service.query.filter_by(guid=guid).one_or_none().service_guid)
  44 +
  45 + if service_update:
  46 + service.update(service_update)
  47 + if wms_update:
  48 + wms.update(wms_update)
46 49
47 db.session.commit() 50 db.session.commit()
48 51
@@ -61,7 +64,7 @@ class Api(ApiTemplate): @@ -61,7 +64,7 @@ class Api(ApiTemplate):
61 "type": "string", 64 "type": "string",
62 "required": "true", 65 "required": "true",
63 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 66 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
64 - {"name": "alias", 67 + {"name": "title",
65 "in": "formData", 68 "in": "formData",
66 "type": "string", 69 "type": "string",
67 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 70 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
@@ -30,7 +30,7 @@ class Api(ApiTemplate): @@ -30,7 +30,7 @@ class Api(ApiTemplate):
30 service = Service( 30 service = Service(
31 guid = service_guid, 31 guid = service_guid,
32 name = self.para.get("name"), 32 name = self.para.get("name"),
33 - alias = self.para.get("alias"), 33 + title = self.para.get("title"),
34 state = int(self.para.get("state")) if self.para.get("state") else None, 34 state = int(self.para.get("state")) if self.para.get("state") else None,
35 create_time = this_time, 35 create_time = this_time,
36 update_time = this_time, 36 update_time = this_time,
@@ -82,7 +82,7 @@ class Api(ApiTemplate): @@ -82,7 +82,7 @@ class Api(ApiTemplate):
82 "type": "string", 82 "type": "string",
83 "required": "true", 83 "required": "true",
84 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 84 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
85 - {"name": "alias", 85 + {"name": "title",
86 "in": "formData", 86 "in": "formData",
87 "type": "string", 87 "type": "string",
88 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 88 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
@@ -15,7 +15,7 @@ class DataManager(BlueprintApi): @@ -15,7 +15,7 @@ class DataManager(BlueprintApi):
15 15
16 bp = Blueprint("WMTS", __name__, url_prefix="/API/Service/WMTS") 16 bp = Blueprint("WMTS", __name__, url_prefix="/API/Service/WMTS")
17 17
18 - service_type = ["WMTS","MTS"] 18 + service_type = ["WMTS","TMS"]
19 19
20 @staticmethod 20 @staticmethod
21 @bp.route('/UploadOverview', methods=['POST']) 21 @bp.route('/UploadOverview', methods=['POST'])
@@ -38,7 +38,7 @@ class WMTS(db.Model): @@ -38,7 +38,7 @@ class WMTS(db.Model):
38 #图层别名 38 #图层别名
39 layer_alias = Column(String(256)) 39 layer_alias = Column(String(256))
40 #图层title 40 #图层title
41 - layer_tile = Column(String(256)) 41 + layer_title = Column(String(256))
42 #图层样式 42 #图层样式
43 layer_style = Column(String(256)) 43 layer_style = Column(String(256))
44 #图片格式 44 #图片格式
@@ -22,25 +22,26 @@ class Api(ApiTemplate): @@ -22,25 +22,26 @@ class Api(ApiTemplate):
22 22
23 try: 23 try:
24 guid = self.para.get("guid") 24 guid = self.para.get("guid")
25 - service = Service.query.filter_by(guid=guid).one_or_none() 25 + service = Service.query.filter_by(guid=guid)
26 this_time = datetime.datetime.now() 26 this_time = datetime.datetime.now()
27 27
28 28
29 - service_update = {"upate_time":this_time}  
30 - wmts_update = {"upate_time":this_time} 29 + service_update = {"update_time":this_time}
  30 + wmts_update = {}
31 for key in self.para.keys(): 31 for key in self.para.keys():
32 - if key in ["name","alias","state","description","overview","catalog_guid"]: 32 + if key in ["name","title","state","description","overview","catalog_guid"]:
33 service_update[key] = self.para.get(key) 33 service_update[key] = self.para.get(key)
34 if key in ["name","wmts_type","vendor","crs","datasource","description", 34 if key in ["name","wmts_type","vendor","crs","datasource","description",
35 - "layer_name","layer_alias","layer_tile","layer_style","layer_format", 35 + "layer_name","layer_alias","layer_title","layer_style","layer_format",
36 "layer_extent","layer_description","scheme_guid"]: 36 "layer_extent","layer_description","scheme_guid"]:
37 wmts_update[key] = self.para.get(key) 37 wmts_update[key] = self.para.get(key)
38 38
39 39
40 - wmts = WMTS.query.filter_by(guid=service.service_guid).one_or_none()  
41 -  
42 - service.update(service_update)  
43 - wmts.update(wmts_update) 40 + wmts = WMTS.query.filter_by(guid=Service.query.filter_by(guid=guid).one_or_none().service_guid)
  41 + if service_update:
  42 + service.update(service_update)
  43 + if wmts_update:
  44 + wmts.update(wmts_update)
44 45
45 db.session.commit() 46 db.session.commit()
46 47
@@ -59,7 +60,7 @@ class Api(ApiTemplate): @@ -59,7 +60,7 @@ class Api(ApiTemplate):
59 "type": "string", 60 "type": "string",
60 "required": "true", 61 "required": "true",
61 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 62 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
62 - {"name": "alias", 63 + {"name": "title",
63 "in": "formData", 64 "in": "formData",
64 "type": "string", 65 "type": "string",
65 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 66 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
@@ -30,7 +30,7 @@ class Api(ApiTemplate): @@ -30,7 +30,7 @@ class Api(ApiTemplate):
30 service = Service( 30 service = Service(
31 guid = service_guid, 31 guid = service_guid,
32 name = self.para.get("name"), 32 name = self.para.get("name"),
33 - alias = self.para.get("alias"), 33 + title = self.para.get("title"),
34 state = 1, 34 state = 1,
35 create_time = this_time, 35 create_time = this_time,
36 update_time = this_time, 36 update_time = this_time,
@@ -60,7 +60,7 @@ class Api(ApiTemplate): @@ -60,7 +60,7 @@ class Api(ApiTemplate):
60 description = self.para.get("description"), 60 description = self.para.get("description"),
61 layer_name = self.para.get("layer_name"), 61 layer_name = self.para.get("layer_name"),
62 layer_alias = self.para.get("layer_alias"), 62 layer_alias = self.para.get("layer_alias"),
63 - layer_tile = self.para.get("layer_title"), 63 + layer_title = self.para.get("layer_title"),
64 layer_style = self.para.get("layer_style"), 64 layer_style = self.para.get("layer_style"),
65 layer_format = self.para.get("layer_format"), 65 layer_format = self.para.get("layer_format"),
66 layer_extent = self.para.get("layer_extent"), 66 layer_extent = self.para.get("layer_extent"),
@@ -99,7 +99,7 @@ class Api(ApiTemplate): @@ -99,7 +99,7 @@ class Api(ApiTemplate):
99 "in": "formData", 99 "in": "formData",
100 "type": "string", 100 "type": "string",
101 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 101 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
102 - {"name": "alias", 102 + {"name": "title",
103 "in": "formData", 103 "in": "formData",
104 "type": "string", 104 "type": "string",
105 "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, 105 "description": "[WMS,WMTS,影像WMS,影像WMTS]"},
@@ -77,6 +77,18 @@ class FileProcess: @@ -77,6 +77,18 @@ class FileProcess:
77 text_size = "{}B".format(round(fsize / float(1), 1)) 77 text_size = "{}B".format(round(fsize / float(1), 1))
78 return text_size,fsize 78 return text_size,fsize
79 79
  80 + @classmethod
  81 + def get_text_size(cls,fsize):
  82 +
  83 + if fsize>1024**3:
  84 + text_size= "{}GB".format(round(fsize/float(1024 **3), 1))
  85 + elif fsize>1024**2:
  86 + text_size = "{}MB".format(round(fsize / float(1024 ** 2), 1))
  87 + elif fsize>1024:
  88 + text_size = "{}KB".format(round(fsize / float(1024), 1))
  89 + else:
  90 + text_size = "{}B".format(round(fsize / float(1), 1))
  91 + return text_size
80 92
81 93
82 @classmethod 94 @classmethod
@@ -11,9 +11,10 @@ import math @@ -11,9 +11,10 @@ import math
11 11
12 class SliceScheme: 12 class SliceScheme:
13 13
14 - parameter={}  
15 - levels = [] 14 + #这里的 多对象共享的
16 def __init__(self,slice_scheme_path): 15 def __init__(self,slice_scheme_path):
  16 + self.parameter = {}
  17 + self.levels = []
17 tree = ET.parse(slice_scheme_path) 18 tree = ET.parse(slice_scheme_path)
18 root:Element = tree.getroot() 19 root:Element = tree.getroot()
19 if root.tag.__eq__("TileCacheInfo"): 20 if root.tag.__eq__("TileCacheInfo"):
@@ -2,3 +2,142 @@ @@ -2,3 +2,142 @@
2 #author: 4N 2 #author: 4N
3 #createtime: 2021/8/18 3 #createtime: 2021/8/18
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
  5 +
  6 +
  7 +import random
  8 +from .SliceScheme import SliceScheme
  9 +import random
  10 +from osgeo.ogr import *
  11 +from osgeo import ogr
  12 +
  13 +
  14 +def create(slice_para,extent,level,output,check_shp=None):
  15 +
  16 +
  17 +
  18 + file = open(output, 'w')
  19 + lxy_extent={}
  20 +
  21 + for l in range(level[0],level[1]+1):
  22 + row = 0
  23 + col = 0
  24 + minx, miny, maxx, maxy = SliceScheme.get_polygon(slice_para, l, row, col)
  25 +
  26 + min_row = 0
  27 +
  28 + while miny > extent[3]:
  29 + row += 1
  30 + minx, miny, maxx, maxy = SliceScheme.get_polygon(slice_para,l, row, col)
  31 + min_row = row
  32 +
  33 + max_row = min_row
  34 + while maxy >extent[1]:
  35 + max_row = row
  36 + row += 1
  37 + minx, miny, maxx, maxy = SliceScheme.get_polygon(slice_para,l, row, col)
  38 +
  39 +
  40 + min_col=0
  41 + while maxx < extent[0]:
  42 + min_col = col
  43 + col += 1
  44 + minx, miny, maxx, maxy = SliceScheme.get_polygon(slice_para,l, row, col)
  45 +
  46 + max_col=min_col
  47 + while minx < extent[2]:
  48 + max_col = col
  49 +
  50 + col += 1
  51 + minx, miny, maxx, maxy = SliceScheme.get_polygon(slice_para,l, row, col)
  52 +
  53 + lxy_extent[l]=[min_row,max_row,min_col,max_col]
  54 + print(lxy_extent)
  55 +
  56 + count = 0
  57 +
  58 + while count<10000:
  59 + l = random.choice(range(level[0],level[1]+1))
  60 + y = random.choice(range(lxy_extent[l][0],lxy_extent[l][1]+1))
  61 + x = random.choice(range(lxy_extent[l][2], lxy_extent[l][3] + 1))
  62 +
  63 + minx, miny, maxx, maxy = SliceScheme.get_polygon(slice_para, l,y, x)
  64 +
  65 + if check_shp:
  66 + driver: Driver = ogr.GetDriverByName("ESRI Shapefile")
  67 + ds: DataSource = driver.Open(check_shp, 1)
  68 + if not ds:
  69 + raise Exception("打开数据失败!")
  70 + layer: Layer = ds.GetLayer(0)
  71 + feature:Feature = layer.GetFeature(0)
  72 + geo:Geometry = feature.GetGeometryRef()
  73 +
  74 + ring = ogr.Geometry(ogr.wkbLinearRing)
  75 + ring.AddPoint(minx, miny)
  76 + ring.AddPoint(minx, maxy)
  77 + ring.AddPoint(maxx, maxy)
  78 + ring.AddPoint(maxx, miny)
  79 + ring.AddPoint(minx, miny)
  80 +
  81 + # Create polygon
  82 + poly = ogr.Geometry(ogr.wkbPolygon)
  83 + poly.AddGeometry(ring)
  84 + if geo.Intersect(poly):
  85 + file.write("{},{},{}\n".format(l, y, x))
  86 + count+=1
  87 + else:
  88 + file.write("{},{},{}\n".format(l,y,x))
  89 + count += 1
  90 +
  91 +if __name__ == '__main__':
  92 + slice_para = {'rows': 256.0, 'cols': 256.0, 'x': -180.0, 'y': 90.0, 'dpi': 96.0,
  93 + '0': {'scale': 295497593.05875003, 'resolution': 0.7031250000000002},
  94 + '1': {'scale': 147748796.52937502, 'resolution': 0.3515625000000001},
  95 + '2': {'scale': 73874398.26468751, 'resolution': 0.17578125000000006},
  96 + '3': {'scale': 36937199.132343754, 'resolution': 0.08789062500000003},
  97 + '4': {'scale': 18468599.566171877, 'resolution': 0.043945312500000014},
  98 + '5': {'scale': 9234299.783085939, 'resolution': 0.021972656250000007},
  99 + '6': {'scale': 4617149.891542969, 'resolution': 0.010986328125000003},
  100 + '7': {'scale': 2308574.9457714846, 'resolution': 0.005493164062500002},
  101 + '8': {'scale': 1154287.4728857423, 'resolution': 0.002746582031250001},
  102 + '9': {'scale': 577143.7364428712, 'resolution': 0.0013732910156250004},
  103 + '10': {'scale': 288571.8682214356, 'resolution': 0.0006866455078125002},
  104 + '11': {'scale': 144285.9341107178, 'resolution': 0.0003433227539062501},
  105 + '12': {'scale': 72142.9670553589, 'resolution': 0.00017166137695312505},
  106 + '13': {'scale': 36071.48352767945, 'resolution': 8.583068847656253e-05},
  107 + '14': {'scale': 18035.741763839724, 'resolution': 4.2915344238281264e-05},
  108 + '15': {'scale': 9017.870881919862, 'resolution': 2.1457672119140632e-05},
  109 + '16': {'scale': 4508.935440959931, 'resolution': 1.0728836059570316e-05},
  110 + '17': {'scale': 2254.4677204799655, 'resolution': 5.364418029785158e-06},
  111 + '18': {'scale': 1127.2338602399827, 'resolution': 2.682209014892579e-06},
  112 + '19': {'scale': 563.6169301199914, 'resolution': 1.3411045074462895e-06}}
  113 +
  114 + # slice_para = {'rows': 256.0, 'cols': 256.0, 'x': -400.0, 'y': 400.0, 'dpi': 96.0,
  115 + # '0': {'scale': 590995186.11750006, 'resolution': 1.4062500000000004},
  116 + # '1': {'scale': 295497593.05875003, 'resolution': 0.7031250000000002},
  117 + # '2': {'scale': 147748796.52937502, 'resolution': 0.3515625000000001},
  118 + # '3': {'scale': 73874398.26468751, 'resolution': 0.17578125000000006},
  119 + # '4': {'scale': 36937199.132343754, 'resolution': 0.08789062500000003},
  120 + # '5': {'scale': 18468599.566171877, 'resolution': 0.043945312500000014},
  121 + # '6': {'scale': 9234299.783085939, 'resolution': 0.021972656250000007},
  122 + # '7': {'scale': 4617149.891542969, 'resolution': 0.010986328125000003},
  123 + # '8': {'scale': 2308574.9457714846, 'resolution': 0.005493164062500002},
  124 + # '9': {'scale': 1154287.4728857423, 'resolution': 0.002746582031250001},
  125 + # '10': {'scale': 577143.7364428712, 'resolution': 0.0013732910156250004},
  126 + # '11': {'scale': 288571.8682214356, 'resolution': 0.0006866455078125002},
  127 + # '12': {'scale': 144285.9341107178, 'resolution': 0.0003433227539062501},
  128 + # '13': {'scale': 72142.9670553589, 'resolution': 0.00017166137695312505},
  129 + # '14': {'scale': 36071.48352767945, 'resolution': 8.583068847656253e-05},
  130 + # '15': {'scale': 18035.741763839724, 'resolution': 4.2915344238281264e-05},
  131 + # '16': {'scale': 9017.870881919862, 'resolution': 2.1457672119140632e-05},
  132 + # '17': {'scale': 4508.935440959931, 'resolution': 1.0728836059570316e-05},
  133 + # '18': {'scale': 2254.4677204799655, 'resolution': 5.364418029785158e-06},
  134 + # '19': {'scale': 1127.2338602399827, 'resolution': 2.682209014892579e-06},
  135 + # '20': {'scale': 563.6169301199914, 'resolution': 1.3411045074462895e-06}}
  136 +
  137 + # level = [8,15]
  138 + # extent = [112, 22.7, 115, 24.03]
  139 +
  140 + level = [12, 17]
  141 + extent = [111.644, 28.989, 111.7, 29.027]
  142 + output = "wmts.bat"
  143 + create(slice_para,extent,level,output)
@@ -11,9 +11,9 @@ SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.60.100:5432/dma @@ -11,9 +11,9 @@ SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.60.100:5432/dma
11 VACUATE_DB_URI = SQLALCHEMY_DATABASE_URI 11 VACUATE_DB_URI = SQLALCHEMY_DATABASE_URI
12 12
13 # 部署模式cluster,standalone 13 # 部署模式cluster,standalone
14 -deployment_mode = "cluster" 14 +# deployment_mode = "cluster"
15 # 部署模式味cluster时有用,master,slave 15 # 部署模式味cluster时有用,master,slave
16 -application_name = "master" 16 +# application_name = "master"
17 17
18 zookeeper = "172.26.99.168:2181" 18 zookeeper = "172.26.99.168:2181"
19 19
@@ -20,10 +20,10 @@ source_srs = source_layer.GetSpatialRef() @@ -20,10 +20,10 @@ source_srs = source_layer.GetSpatialRef()
20 x_min, x_max, y_min, y_max = source_layer.GetExtent() 20 x_min, x_max, y_min, y_max = source_layer.GetExtent()
21 21
22 # Create the destination data source 22 # Create the destination data source
23 -x_res = int((x_max - (x_min-2)) / pixel_size) 23 +x_res = int((x_max - (x_min)) / pixel_size)
24 y_res = int((y_max - y_min) / pixel_size) 24 y_res = int((y_max - y_min) / pixel_size)
25 -target_ds = gdal.GetDriverByName('GTiff').Create('t.tiff', x_res, y_res, gdal.GDT_Byte)  
26 -target_ds.SetGeoTransform((x_min-2, pixel_size, 0, y_max, 0, -pixel_size)) 25 +target_ds = gdal.GetDriverByName('GTiff').Create('t.tiff', 50, 50, gdal.GDT_Byte)
  26 +target_ds.SetGeoTransform((x_min, pixel_size, 0, y_max, 0, -pixel_size))
27 band = target_ds.GetRasterBand(1) 27 band = target_ds.GetRasterBand(1)
28 band.SetNoDataValue(NoData_value) 28 band.SetNoDataValue(NoData_value)
29 29
不能预览此文件类型
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/10/15
  4 +#email: nheweijun@sina.com
  5 +
  1 +#增加table_vacuate connectstr
注册登录 后发表评论