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