正在显示
100 个修改的文件
包含
1974 行增加
和
1546 行删除
| ... | ... | @@ -8,7 +8,7 @@ from sqlalchemy.sql.expression import true |
| 8 | 8 | import configure |
| 9 | 9 | from app.util import BlueprintApi |
| 10 | 10 | from app.util import find_class |
| 11 | -from app.models import db, Table, InsertingLayerName, Database, DES, Task | |
| 11 | +from app.models import db | |
| 12 | 12 | from app.modules.auth.oauth2 import config_oauth, myCodeIDToken |
| 13 | 13 | from flasgger import Swagger |
| 14 | 14 | import logging | ... | ... |
| 1 | 1 | # coding=utf-8 |
| 2 | -import base64 | |
| 3 | -import os | |
| 4 | -from flask_sqlalchemy import SQLAlchemy,Model | |
| 5 | -import importlib | |
| 6 | -from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time,Float,Binary | |
| 7 | -from sqlalchemy.orm import relationship | |
| 8 | -import base64 | |
| 9 | -from pyDes import * | |
| 10 | -import datetime | |
| 11 | 2 | |
| 12 | -from app.util.component.PGUtil import PGUtil | |
| 3 | +import os | |
| 4 | +from flask_sqlalchemy import SQLAlchemy | |
| 13 | 5 | import glob |
| 14 | 6 | import traceback |
| 7 | +from pyDes import des,PAD_PKCS5,ECB | |
| 8 | + | |
| 9 | +import base64 | |
| 15 | 10 | class DES(): |
| 16 | 11 | ''' |
| 17 | 12 | DES密码加解密 |
| ... | ... | @@ -33,232 +28,6 @@ class DES(): |
| 33 | 28 | |
| 34 | 29 | db = SQLAlchemy() |
| 35 | 30 | |
| 36 | - | |
| 37 | -class Table(db.Model): | |
| 38 | - ''' | |
| 39 | - 数据表元数据 | |
| 40 | - ''' | |
| 41 | - __tablename__ = 'dmap_table' | |
| 42 | - guid = Column(String(256), primary_key=True) | |
| 43 | - # 数据源外键 | |
| 44 | - database_guid = Column(String(256), ForeignKey('dmap_database.guid')) | |
| 45 | - | |
| 46 | - # 点线面123 | |
| 47 | - table_type = Column(Integer) | |
| 48 | - | |
| 49 | - name = Column(String(256)) | |
| 50 | - alias = Column(Text) | |
| 51 | - create_time = Column(DateTime) | |
| 52 | - update_time = Column(DateTime) | |
| 53 | - | |
| 54 | - feature_count = Column(Integer) | |
| 55 | - | |
| 56 | - description = Column(Text) | |
| 57 | - extent = Column(Text) | |
| 58 | - | |
| 59 | - #用户 | |
| 60 | - creator = Column(Text) | |
| 61 | - #是否已抽稀 | |
| 62 | - is_vacuate=Column(Integer,default=0) | |
| 63 | - | |
| 64 | - # 目录外键 | |
| 65 | - catalog_guid = Column(String(256), ForeignKey('dmap_catalog.guid')) | |
| 66 | - | |
| 67 | - relate_columns = relationship('Columns', backref='relate_table', lazy='dynamic') | |
| 68 | - relate_table_vacuates = relationship('TableVacuate', backref='relate_table', lazy='dynamic') | |
| 69 | - | |
| 70 | - | |
| 71 | -class TableVacuate(db.Model): | |
| 72 | - ''' | |
| 73 | - sub数据表元数据 | |
| 74 | - ''' | |
| 75 | - __tablename__ = 'dmap_table_vacuate' | |
| 76 | - guid = Column(String(256), primary_key=True) | |
| 77 | - name = Column(String(256)) | |
| 78 | - level = Column(Integer) | |
| 79 | - pixel_distance = Column(Float) | |
| 80 | - table_guid = Column(String(256), ForeignKey('dmap_table.guid')) | |
| 81 | - | |
| 82 | - #所在的库 | |
| 83 | - connectstr= Column(Text) | |
| 84 | - | |
| 85 | -class Columns(db.Model): | |
| 86 | - ''' | |
| 87 | - 数据表的列 | |
| 88 | - ''' | |
| 89 | - __tablename__ = 'dmap_column' | |
| 90 | - guid = Column(String(256), primary_key=True) | |
| 91 | - # 表外键 | |
| 92 | - table_guid= Column(String(256), ForeignKey('dmap_table.guid')) | |
| 93 | - name=Column(String(256)) | |
| 94 | - alias = Column(String(256)) | |
| 95 | - create_time = Column(DateTime) | |
| 96 | - update_time = Column(DateTime) | |
| 97 | - | |
| 98 | -class Task(db.Model): | |
| 99 | - ''' | |
| 100 | - 任务表 | |
| 101 | - ''' | |
| 102 | - __tablename__ = 'dmap_task' | |
| 103 | - guid = Column(String(256), primary_key=True) | |
| 104 | - name = Column(Text) | |
| 105 | - process = Column(Text) | |
| 106 | - create_time = Column(DateTime) | |
| 107 | - update_time = Column(DateTime) | |
| 108 | - state = Column(Integer) | |
| 109 | - #数据源外键 | |
| 110 | - database_guid = Column(String(256), ForeignKey('dmap_database.guid')) | |
| 111 | - #目录外键 | |
| 112 | - catalog_guid = Column(String(256), ForeignKey('dmap_catalog.guid')) | |
| 113 | - #抽稀任务指定表的guid | |
| 114 | - table_guid = Column(String(256)) | |
| 115 | - #任务类型 | |
| 116 | - #1:入库任务 | |
| 117 | - #2:抽稀任务 | |
| 118 | - #3:数据库刷新任务 | |
| 119 | - #4:影像金字塔任务 | |
| 120 | - #5:数据下载任务 | |
| 121 | - task_type=Column(Integer) | |
| 122 | - creator = Column(Text) | |
| 123 | - file_name = Column(Text) | |
| 124 | - relate_processes = relationship('Process', backref='relate_task', lazy='dynamic') | |
| 125 | - # 入库参数 | |
| 126 | - parameter= Column(Text) | |
| 127 | - | |
| 128 | - | |
| 129 | - | |
| 130 | -class Process(db.Model): | |
| 131 | - ''' | |
| 132 | - 过程信息表 | |
| 133 | - ''' | |
| 134 | - __tablename__ = 'dmap_process' | |
| 135 | - guid = Column(String(256), primary_key=True) | |
| 136 | - # 任务外键 | |
| 137 | - task_guid = Column(String(256), ForeignKey('dmap_task.guid')) | |
| 138 | - time = Column(DateTime) | |
| 139 | - message = Column(Text) | |
| 140 | - | |
| 141 | - | |
| 142 | -class Catalog(db.Model): | |
| 143 | - ''' | |
| 144 | - 目录表 | |
| 145 | - ''' | |
| 146 | - __tablename__ = 'dmap_catalog' | |
| 147 | - guid = Column(String(256), primary_key=True) | |
| 148 | - database_guid = Column(String(256), ForeignKey('dmap_database.guid')) | |
| 149 | - pguid = Column(String(256)) | |
| 150 | - path = Column(Text) | |
| 151 | - name = Column(String(256)) | |
| 152 | - sort = Column(Integer) | |
| 153 | - description = Column(Text) | |
| 154 | - relate_tables = relationship('Table', backref='relate_catalog', lazy='dynamic') | |
| 155 | - relate_tasks = relationship('Task', backref='relate_catalog', lazy='dynamic') | |
| 156 | - | |
| 157 | - | |
| 158 | -class Database(db.Model): | |
| 159 | - ''' | |
| 160 | - 数据源表 | |
| 161 | - ''' | |
| 162 | - __tablename__ = 'dmap_database' | |
| 163 | - guid = Column(String(256), primary_key=True) | |
| 164 | - name = Column(String(256)) | |
| 165 | - alias = Column(String(256)) | |
| 166 | - sqlalchemy_uri = Column(String(256)) | |
| 167 | - description = Column(Text) | |
| 168 | - # 唯一性约束,不能注册相同连接的库 | |
| 169 | - connectstr= Column(Text,unique=True) | |
| 170 | - creator = Column(String(256)) | |
| 171 | - create_time = Column(DateTime) | |
| 172 | - update_time = Column(DateTime) | |
| 173 | - relate_catalogs = relationship('Catalog', backref='relate_database', lazy='dynamic') | |
| 174 | - relate_tables = relationship('Table', backref='relate_database', lazy='dynamic') | |
| 175 | - relate_tasks = relationship('Task', backref='relate_database', lazy='dynamic') | |
| 176 | - | |
| 177 | - | |
| 178 | - | |
| 179 | -class InsertingLayerName(db.Model): | |
| 180 | - ''' | |
| 181 | - 正在入库的数据 | |
| 182 | - ''' | |
| 183 | - __tablename__ = 'dmap_iln' | |
| 184 | - guid = Column(String(256), primary_key=True) | |
| 185 | - task_guid = Column(String(256)) | |
| 186 | - name = Column(String(256)) | |
| 187 | - | |
| 188 | - | |
| 189 | -class Service(db.Model): | |
| 190 | - ''' | |
| 191 | - ''' | |
| 192 | - __tablename__ = 'dmap_service' | |
| 193 | - guid = Column(String(256), primary_key=True) | |
| 194 | - name = Column(String(256)) | |
| 195 | - # alias = Column(String(256)) | |
| 196 | - | |
| 197 | - title = Column(String(256)) | |
| 198 | - | |
| 199 | - #服务状态 | |
| 200 | - state= Column(Integer) | |
| 201 | - create_time = Column(DateTime) | |
| 202 | - update_time = Column(DateTime) | |
| 203 | - #服务描述 | |
| 204 | - description = Column(Text) | |
| 205 | - #服务节点 | |
| 206 | - node = Column(Integer) | |
| 207 | - #服务缩略图 | |
| 208 | - overview = Column(Text) | |
| 209 | - #服务类型 | |
| 210 | - type = Column(String(256)) | |
| 211 | - #具体服务id | |
| 212 | - service_guid = Column(String(256)) | |
| 213 | - # 目录外键 | |
| 214 | - catalog_guid = Column(String(256), ForeignKey('dmap_service_catalog.guid')) | |
| 215 | - | |
| 216 | - | |
| 217 | -class ServiceCatalog(db.Model): | |
| 218 | - ''' | |
| 219 | - 目录表 | |
| 220 | - ''' | |
| 221 | - __tablename__ = 'dmap_service_catalog' | |
| 222 | - guid = Column(String(256), primary_key=True) | |
| 223 | - pguid = Column(String(256)) | |
| 224 | - path = Column(Text) | |
| 225 | - name = Column(String(256)) | |
| 226 | - sort = Column(Integer) | |
| 227 | - description = Column(Text) | |
| 228 | - relate_services = relationship('Service', backref='relate_catalog', lazy='dynamic') | |
| 229 | - | |
| 230 | - | |
| 231 | - | |
| 232 | -class TileScheme(db.Model): | |
| 233 | - ''' | |
| 234 | - 切片方案表 | |
| 235 | - ''' | |
| 236 | - __tablename__ = 'dmap_tile_scheme' | |
| 237 | - guid = Column(String(256), primary_key=True) | |
| 238 | - name = Column(String(256)) | |
| 239 | - alias = Column(String(256)) | |
| 240 | - description = Column(Text) | |
| 241 | - crs = Column(String(256)) | |
| 242 | - crs_wkt = Column(Text) | |
| 243 | - | |
| 244 | - extent = Column(Text) | |
| 245 | - top_left = Column(String(256)) | |
| 246 | - | |
| 247 | - # xmin = Column(Float) | |
| 248 | - # ymin = Column(Float) | |
| 249 | - # xmax = Column(Float) | |
| 250 | - # ymax = Column(Float) | |
| 251 | - # origin_x = Column(Float) | |
| 252 | - # origin_y = Column(Float) | |
| 253 | - | |
| 254 | - levels = Column(Text) | |
| 255 | - dpi = Column(Integer) | |
| 256 | - rows = Column(Integer) | |
| 257 | - cols = Column(Integer) | |
| 258 | - update_time = Column(DateTime) | |
| 259 | - | |
| 260 | - parameter = Column(Text) | |
| 261 | - | |
| 262 | 31 | # 动态加载Model |
| 263 | 32 | current_dir = os.path.abspath(os.path.dirname(__file__)) |
| 264 | 33 | pkgs = list(glob.glob('%s/modules/*/models' % (current_dir))) | ... | ... |
| ... | ... | @@ -3,12 +3,11 @@ |
| 3 | 3 | #createtime: 2021/3/9 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from app.models import Database,db | |
| 6 | +from ..models import Database,db,DES | |
| 7 | 7 | from contextlib import closing |
| 8 | 8 | |
| 9 | 9 | from sqlalchemy import create_engine |
| 10 | 10 | |
| 11 | -from app.models import DES | |
| 12 | 11 | import datetime |
| 13 | 12 | from . import database_alias_check |
| 14 | 13 | ... | ... |
| ... | ... | @@ -2,11 +2,9 @@ |
| 2 | 2 | #author: 4N |
| 3 | 3 | #createtime: 2021/3/9 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | -from app.models import Database,DES | |
| 6 | -from contextlib import closing | |
| 7 | -from sqlalchemy import create_engine,or_ | |
| 8 | 5 | |
| 9 | -from app.models import Database,Catalog,Table | |
| 6 | + | |
| 7 | +from ..models import Database,Catalog,Table | |
| 10 | 8 | |
| 11 | 9 | |
| 12 | 10 | from app.util.component.ApiTemplate import ApiTemplate | ... | ... |
| ... | ... | @@ -2,11 +2,11 @@ |
| 2 | 2 | #author: 4N |
| 3 | 3 | #createtime: 2021/3/9 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | -from app.models import Database,DES | |
| 5 | + | |
| 6 | 6 | from contextlib import closing |
| 7 | 7 | from sqlalchemy import create_engine |
| 8 | 8 | |
| 9 | -from app.models import Database | |
| 9 | +from ..models import Database,DES | |
| 10 | 10 | |
| 11 | 11 | |
| 12 | 12 | from app.util.component.ApiTemplate import ApiTemplate | ... | ... |
| ... | ... | @@ -3,11 +3,10 @@ |
| 3 | 3 | #createtime: 2021/3/9 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | import datetime |
| 6 | -from app.models import Database,db,DES,Table,Columns,TableVacuate | |
| 7 | -# from app.util import get_db_session,get_info_from_sqlachemy_uri | |
| 6 | +from ..models import Database,db,Table,Columns,TableVacuate,DES | |
| 7 | + | |
| 8 | 8 | import uuid |
| 9 | 9 | from . import database_test |
| 10 | -# from app.util import open_pg_data_source | |
| 11 | 10 | from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn |
| 12 | 11 | from sqlalchemy.orm import Session |
| 13 | 12 | from sqlalchemy import create_engine | ... | ... |
| ... | ... | @@ -6,7 +6,8 @@ from contextlib import closing |
| 6 | 6 | |
| 7 | 7 | from sqlalchemy import create_engine |
| 8 | 8 | |
| 9 | -from app.models import DES,Database,db | |
| 9 | +from ..models import Database,db,DES | |
| 10 | + | |
| 10 | 11 | |
| 11 | 12 | from sqlalchemy.orm import sessionmaker |
| 12 | 13 | from app.util.component.ApiTemplate import ApiTemplate | ... | ... |
| ... | ... | @@ -6,7 +6,7 @@ import datetime |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | |
| 9 | -from app.models import Table,Database | |
| 9 | +from app.modules.data.models import Table,Database | |
| 10 | 10 | from app.util.component.ApiTemplate import ApiTemplate |
| 11 | 11 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 12 | 12 | from app.util.component.LayerUtil import LayerUtil |
| ... | ... | @@ -14,6 +14,7 @@ from app.util.component.PGUtil import PGUtil |
| 14 | 14 | from osgeo.ogr import Geometry,Layer,DataSource,Feature |
| 15 | 15 | from app.models import DES |
| 16 | 16 | from osgeo import ogr |
| 17 | +import json | |
| 17 | 18 | import gzip |
| 18 | 19 | from flask import make_response |
| 19 | 20 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # author: 4N |
| 3 | 3 | # createtime: 2021/8/4 |
| 4 | 4 | # email: nheweijun@sina.com |
| 5 | -from app.models import Table,Database | |
| 5 | +from app.modules.data.models import Table,Database | |
| 6 | 6 | from app.util.component.ApiTemplate import ApiTemplate |
| 7 | 7 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 8 | 8 | from app.util.component.LayerUtil import LayerUtil | ... | ... |
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | # email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | 6 | |
| 7 | -from app.models import Table,Database | |
| 7 | +from app.modules.data.models import Table,Database | |
| 8 | 8 | from app.util.component.ApiTemplate import ApiTemplate |
| 9 | 9 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 10 | 10 | from app.util.component.LayerUtil import LayerUtil | ... | ... |
| ... | ... | @@ -6,7 +6,7 @@ import datetime |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | |
| 9 | -from app.models import Table,Database | |
| 9 | +from app.modules.data.models import Table,Database | |
| 10 | 10 | from app.util.component.ApiTemplate import ApiTemplate |
| 11 | 11 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 12 | 12 | from app.util.component.LayerUtil import LayerUtil | ... | ... |
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | # email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | 6 | |
| 7 | -from app.models import Table,Database | |
| 7 | +from app.modules.data.models import Table,Database | |
| 8 | 8 | from app.util.component.ApiTemplate import ApiTemplate |
| 9 | 9 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 10 | 10 | from app.util.component.LayerUtil import LayerUtil | ... | ... |
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | 6 | |
| 7 | -from app.models import * | |
| 7 | +from ..models import * | |
| 8 | 8 | |
| 9 | 9 | import traceback |
| 10 | 10 | |
| ... | ... | @@ -17,6 +17,7 @@ from app.util.component.ApiTemplate import ApiTemplate |
| 17 | 17 | from app.util.component.PGUtil import PGUtil |
| 18 | 18 | from app.util.component.ZipUtil import ZipUtil |
| 19 | 19 | import multiprocessing |
| 20 | +import datetime | |
| 20 | 21 | |
| 21 | 22 | class Api(ApiTemplate): |
| 22 | 23 | ... | ... |
| ... | ... | @@ -7,12 +7,13 @@ from osgeo.ogr import * |
| 7 | 7 | import uuid |
| 8 | 8 | |
| 9 | 9 | import time |
| 10 | -from app.models import * | |
| 10 | +from ..models import * | |
| 11 | + | |
| 11 | 12 | import json |
| 12 | 13 | import re |
| 13 | 14 | from app.util.component.ApiTemplate import ApiTemplate |
| 14 | 15 | from app.util.component.PGUtil import PGUtil |
| 15 | - | |
| 16 | +import datetime | |
| 16 | 17 | |
| 17 | 18 | |
| 18 | 19 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -4,7 +4,8 @@ |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | 6 | import configure |
| 7 | -from app.models import InsertingLayerName, Database, DES, Task | |
| 7 | +from ..models import InsertingLayerName, Database, Task,DES | |
| 8 | + | |
| 8 | 9 | from sqlalchemy.orm import Session |
| 9 | 10 | import multiprocessing |
| 10 | 11 | from app.util.component.EntryDataVacuate import EntryDataVacuate | ... | ... |
| ... | ... | @@ -7,11 +7,10 @@ from osgeo.ogr import * |
| 7 | 7 | import uuid |
| 8 | 8 | |
| 9 | 9 | import time |
| 10 | -from app.models import * | |
| 10 | +from ..models import * | |
| 11 | +import datetime | |
| 11 | 12 | import json |
| 12 | -import re | |
| 13 | 13 | from app.util.component.ApiTemplate import ApiTemplate |
| 14 | -from app.util.component.PGUtil import PGUtil | |
| 15 | 14 | from .get_meta import Api as MetaApi |
| 16 | 15 | from threading import Thread |
| 17 | 16 | from app.util.component.EntryDataVacuate import EntryDataVacuate | ... | ... |
| ... | ... | @@ -3,20 +3,12 @@ |
| 3 | 3 | # createtime: 2020/9/4 |
| 4 | 4 | # email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -import traceback | |
| 7 | -from osgeo.ogr import * | |
| 8 | -from osgeo import ogr | |
| 9 | 6 | |
| 10 | -from flask import request | |
| 11 | 7 | import os |
| 12 | -import uuid | |
| 13 | - | |
| 14 | -import json | |
| 15 | 8 | from app.util.component.ApiTemplate import ApiTemplate |
| 16 | -from app.util.component.ZipUtil import ZipUtil | |
| 17 | 9 | from app.util.component.FileProcess import FileProcess |
| 18 | 10 | import datetime |
| 19 | -import time | |
| 11 | + | |
| 20 | 12 | class Api(ApiTemplate): |
| 21 | 13 | api_name = "本地数据list" |
| 22 | 14 | def process(self): | ... | ... |
| ... | ... | @@ -2,7 +2,8 @@ |
| 2 | 2 | #createtime: 2021/1/27 |
| 3 | 3 | #email: nheweijun@sina.com |
| 4 | 4 | |
| 5 | -from app.models import Table,Columns,DES | |
| 5 | +from ..models import Table,Columns,DES | |
| 6 | + | |
| 6 | 7 | |
| 7 | 8 | from app.util.component.ApiTemplate import ApiTemplate |
| 8 | 9 | from app.util.component.ModelVisitor import ModelVisitor | ... | ... |
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | import datetime |
| 7 | 7 | import traceback |
| 8 | -from app.models import Table, Database, DES,Task,db,TableVacuate,Process | |
| 8 | +from ..models import Table, Database, Task,db,TableVacuate,Process,DES | |
| 9 | 9 | |
| 10 | 10 | from sqlalchemy.engine import ResultProxy |
| 11 | 11 | from app.util.component.ApiTemplate import ApiTemplate | ... | ... |
| ... | ... | @@ -3,21 +3,11 @@ |
| 3 | 3 | # email: nheweijun@sina.com |
| 4 | 4 | |
| 5 | 5 | |
| 6 | -import datetime | |
| 7 | -import traceback | |
| 8 | -from app.models import Table, Database, DES,Task,db,TableVacuate | |
| 9 | - | |
| 10 | -from sqlalchemy.engine import ResultProxy | |
| 6 | +from ..models import Table,DES,db,TableVacuate | |
| 11 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 12 | 8 | from app.util.component.PGUtil import PGUtil |
| 13 | -from app.util.component.EntryDataVacuate import Process | |
| 14 | -from app.util.component.GeometryAdapter import GeometryAdapter | |
| 15 | -from app.util.component.StructuredPrint import StructurePrint | |
| 16 | -import multiprocessing | |
| 17 | -import uuid | |
| 18 | 9 | import configure |
| 19 | -from osgeo.ogr import DataSource,Layer,Geometry | |
| 20 | -from osgeo import ogr | |
| 10 | +from osgeo.ogr import DataSource | |
| 21 | 11 | from flask import current_app |
| 22 | 12 | |
| 23 | 13 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -3,11 +3,10 @@ |
| 3 | 3 | # email: nheweijun@sina.com |
| 4 | 4 | |
| 5 | 5 | |
| 6 | -from app.models import Table,TableVacuate,Task | |
| 6 | +from ..models import Table,TableVacuate,Task | |
| 7 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 8 | 8 | from app.util.component.VacuateConf import VacuateConf |
| 9 | -import collections | |
| 10 | -import json | |
| 9 | + | |
| 11 | 10 | |
| 12 | 11 | import copy |
| 13 | 12 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | import datetime |
| 7 | 7 | import traceback |
| 8 | -from app.models import Table, Database, DES,Task,db,TableVacuate | |
| 8 | +from ..models import Table, Database, DES,Task,db,TableVacuate | |
| 9 | 9 | from app.util.component.ApiTemplate import ApiTemplate |
| 10 | 10 | from app.util.component.PGUtil import PGUtil |
| 11 | 11 | from app.util.component.EntryDataVacuate import Process |
| ... | ... | @@ -14,7 +14,7 @@ import uuid |
| 14 | 14 | import configure |
| 15 | 15 | from osgeo.ogr import DataSource,Layer,Geometry |
| 16 | 16 | from osgeo import ogr |
| 17 | -from app.util.component.StructuredPrint import StructurePrint | |
| 17 | + | |
| 18 | 18 | from app.util.component.VacuateConf import VacuateConf |
| 19 | 19 | |
| 20 | 20 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -3,21 +3,17 @@ |
| 3 | 3 | # email: nheweijun@sina.com |
| 4 | 4 | |
| 5 | 5 | |
| 6 | -import datetime | |
| 7 | -import traceback | |
| 8 | -from app.models import Table, Database, DES,Task,db,TableVacuate | |
| 6 | +from ..models import Table, DES | |
| 7 | + | |
| 9 | 8 | |
| 10 | -from sqlalchemy.engine import ResultProxy | |
| 11 | 9 | from app.util.component.ApiTemplate import ApiTemplate |
| 12 | 10 | from app.util.component.PGUtil import PGUtil |
| 13 | -from app.util.component.EntryDataVacuate import Process | |
| 11 | + | |
| 14 | 12 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 15 | 13 | from app.util.component.StructuredPrint import StructurePrint |
| 16 | -import multiprocessing | |
| 17 | -import uuid | |
| 18 | -import configure | |
| 19 | -from osgeo.ogr import DataSource,Layer,Geometry | |
| 20 | -from osgeo import ogr | |
| 14 | + | |
| 15 | +from osgeo.ogr import DataSource | |
| 16 | + | |
| 21 | 17 | from app.util.component.VacuateConf import VacuateConf |
| 22 | 18 | import copy |
| 23 | 19 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -4,9 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | import datetime |
| 7 | -import traceback | |
| 8 | -from app.models import Table,Database,DES | |
| 9 | - | |
| 7 | +from ..models import Table,Database,DES | |
| 10 | 8 | from sqlalchemy.engine import ResultProxy |
| 11 | 9 | from app.util.component.ApiTemplate import ApiTemplate |
| 12 | 10 | from app.util.component.PGUtil import PGUtil | ... | ... |
app/modules/data/models/__init__.py
0 → 100644
| 1 | +# coding=utf-8 | |
| 2 | +#author: 4N | |
| 3 | +#createtime: 2021/10/26 | |
| 4 | +#email: nheweijun@sina.com | |
| 5 | + | |
| 6 | +from app.models import db | |
| 7 | +from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time,Float,Binary | |
| 8 | +from sqlalchemy.orm import relationship | |
| 9 | +import base64 | |
| 10 | +from pyDes import * | |
| 11 | + | |
| 12 | + | |
| 13 | +class DES(): | |
| 14 | + ''' | |
| 15 | + DES密码加解密 | |
| 16 | + ''' | |
| 17 | + Des: des = des("Chinadci", ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5) | |
| 18 | + | |
| 19 | + @classmethod | |
| 20 | + def encode(cls, data): | |
| 21 | + return str(base64.b64encode(cls.Des.encrypt(data)), encoding="utf8") | |
| 22 | + | |
| 23 | + | |
| 24 | + @classmethod | |
| 25 | + def decode(cls, data): | |
| 26 | + if data: | |
| 27 | + return str(cls.Des.decrypt(base64.b64decode(data.encode("utf-8"))), encoding="utf8") | |
| 28 | + | |
| 29 | + else: | |
| 30 | + return data | |
| 31 | + | |
| 32 | +class Table(db.Model): | |
| 33 | + ''' | |
| 34 | + 数据表元数据 | |
| 35 | + ''' | |
| 36 | + __tablename__ = 'dmap_table' | |
| 37 | + guid = Column(String(256), primary_key=True) | |
| 38 | + # 数据源外键 | |
| 39 | + database_guid = Column(String(256), ForeignKey('dmap_database.guid')) | |
| 40 | + | |
| 41 | + # 点线面123 | |
| 42 | + table_type = Column(Integer) | |
| 43 | + | |
| 44 | + name = Column(String(256)) | |
| 45 | + alias = Column(Text) | |
| 46 | + create_time = Column(DateTime) | |
| 47 | + update_time = Column(DateTime) | |
| 48 | + | |
| 49 | + feature_count = Column(Integer) | |
| 50 | + | |
| 51 | + description = Column(Text) | |
| 52 | + extent = Column(Text) | |
| 53 | + | |
| 54 | + #用户 | |
| 55 | + creator = Column(Text) | |
| 56 | + #是否已抽稀 | |
| 57 | + is_vacuate=Column(Integer,default=0) | |
| 58 | + | |
| 59 | + # 目录外键 | |
| 60 | + catalog_guid = Column(String(256), ForeignKey('dmap_catalog.guid')) | |
| 61 | + | |
| 62 | + relate_columns = relationship('Columns', backref='relate_table', lazy='dynamic') | |
| 63 | + relate_table_vacuates = relationship('TableVacuate', backref='relate_table', lazy='dynamic') | |
| 64 | + | |
| 65 | + | |
| 66 | +class TableVacuate(db.Model): | |
| 67 | + ''' | |
| 68 | + sub数据表元数据 | |
| 69 | + ''' | |
| 70 | + __tablename__ = 'dmap_table_vacuate' | |
| 71 | + guid = Column(String(256), primary_key=True) | |
| 72 | + name = Column(String(256)) | |
| 73 | + level = Column(Integer) | |
| 74 | + pixel_distance = Column(Float) | |
| 75 | + table_guid = Column(String(256), ForeignKey('dmap_table.guid')) | |
| 76 | + | |
| 77 | + #所在的库 | |
| 78 | + connectstr= Column(Text) | |
| 79 | + | |
| 80 | +class Columns(db.Model): | |
| 81 | + ''' | |
| 82 | + 数据表的列 | |
| 83 | + ''' | |
| 84 | + __tablename__ = 'dmap_column' | |
| 85 | + guid = Column(String(256), primary_key=True) | |
| 86 | + # 表外键 | |
| 87 | + table_guid= Column(String(256), ForeignKey('dmap_table.guid')) | |
| 88 | + name=Column(String(256)) | |
| 89 | + alias = Column(String(256)) | |
| 90 | + create_time = Column(DateTime) | |
| 91 | + update_time = Column(DateTime) | |
| 92 | + | |
| 93 | +class Task(db.Model): | |
| 94 | + ''' | |
| 95 | + 任务表 | |
| 96 | + ''' | |
| 97 | + __tablename__ = 'dmap_task' | |
| 98 | + guid = Column(String(256), primary_key=True) | |
| 99 | + name = Column(Text) | |
| 100 | + process = Column(Text) | |
| 101 | + create_time = Column(DateTime) | |
| 102 | + update_time = Column(DateTime) | |
| 103 | + state = Column(Integer) | |
| 104 | + #数据源外键 | |
| 105 | + database_guid = Column(String(256), ForeignKey('dmap_database.guid')) | |
| 106 | + #目录外键 | |
| 107 | + catalog_guid = Column(String(256), ForeignKey('dmap_catalog.guid')) | |
| 108 | + #抽稀任务指定表的guid | |
| 109 | + table_guid = Column(String(256)) | |
| 110 | + #任务类型 | |
| 111 | + #1:入库任务 | |
| 112 | + #2:抽稀任务 | |
| 113 | + #3:数据库刷新任务 | |
| 114 | + #4:影像金字塔任务 | |
| 115 | + #5:数据下载任务 | |
| 116 | + task_type=Column(Integer) | |
| 117 | + creator = Column(Text) | |
| 118 | + file_name = Column(Text) | |
| 119 | + relate_processes = relationship('Process', backref='relate_task', lazy='dynamic') | |
| 120 | + # 入库参数 | |
| 121 | + parameter= Column(Text) | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | +class Process(db.Model): | |
| 126 | + ''' | |
| 127 | + 过程信息表 | |
| 128 | + ''' | |
| 129 | + __tablename__ = 'dmap_process' | |
| 130 | + guid = Column(String(256), primary_key=True) | |
| 131 | + # 任务外键 | |
| 132 | + task_guid = Column(String(256), ForeignKey('dmap_task.guid')) | |
| 133 | + time = Column(DateTime) | |
| 134 | + message = Column(Text) | |
| 135 | + | |
| 136 | + | |
| 137 | +class Catalog(db.Model): | |
| 138 | + ''' | |
| 139 | + 目录表 | |
| 140 | + ''' | |
| 141 | + __tablename__ = 'dmap_catalog' | |
| 142 | + guid = Column(String(256), primary_key=True) | |
| 143 | + database_guid = Column(String(256), ForeignKey('dmap_database.guid')) | |
| 144 | + pguid = Column(String(256)) | |
| 145 | + path = Column(Text) | |
| 146 | + name = Column(String(256)) | |
| 147 | + sort = Column(Integer) | |
| 148 | + description = Column(Text) | |
| 149 | + relate_tables = relationship('Table', backref='relate_catalog', lazy='dynamic') | |
| 150 | + relate_tasks = relationship('Task', backref='relate_catalog', lazy='dynamic') | |
| 151 | + | |
| 152 | + | |
| 153 | +class Database(db.Model): | |
| 154 | + ''' | |
| 155 | + 数据源表 | |
| 156 | + ''' | |
| 157 | + __tablename__ = 'dmap_database' | |
| 158 | + guid = Column(String(256), primary_key=True) | |
| 159 | + name = Column(String(256)) | |
| 160 | + alias = Column(String(256)) | |
| 161 | + sqlalchemy_uri = Column(String(256)) | |
| 162 | + description = Column(Text) | |
| 163 | + # 唯一性约束,不能注册相同连接的库 | |
| 164 | + connectstr= Column(Text,unique=True) | |
| 165 | + creator = Column(String(256)) | |
| 166 | + create_time = Column(DateTime) | |
| 167 | + update_time = Column(DateTime) | |
| 168 | + relate_catalogs = relationship('Catalog', backref='relate_database', lazy='dynamic') | |
| 169 | + relate_tables = relationship('Table', backref='relate_database', lazy='dynamic') | |
| 170 | + relate_tasks = relationship('Task', backref='relate_database', lazy='dynamic') | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | +class InsertingLayerName(db.Model): | |
| 175 | + ''' | |
| 176 | + 正在入库的数据 | |
| 177 | + ''' | |
| 178 | + __tablename__ = 'dmap_iln' | |
| 179 | + guid = Column(String(256), primary_key=True) | |
| 180 | + task_guid = Column(String(256)) | |
| 181 | + name = Column(String(256)) | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | ... | ... |
| ... | ... | @@ -3,65 +3,41 @@ |
| 3 | 3 | #createtime: 2021/10/11 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from app.models import Task | |
| 7 | -import configure | |
| 8 | -from app.models import InsertingLayerName, Database, DES, Task,Columns | |
| 6 | + | |
| 7 | +from ..models import InsertingLayerName,Columns | |
| 9 | 8 | from sqlalchemy.orm import Session |
| 10 | -import multiprocessing | |
| 9 | + | |
| 11 | 10 | from app.util.component.EntryDataVacuate import EntryDataVacuate |
| 12 | 11 | import json |
| 13 | 12 | 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 | |
| 13 | + | |
| 18 | 14 | 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 | |
| 15 | + | |
| 25 | 16 | 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 | |
| 17 | + | |
| 33 | 18 | import datetime |
| 34 | -import traceback | |
| 35 | -from app.models import Table, Database, DES,Task,db,TableVacuate,Process | |
| 36 | 19 | |
| 37 | -from sqlalchemy.engine import ResultProxy | |
| 38 | -from app.util.component.ApiTemplate import ApiTemplate | |
| 20 | +from ..models import Table, Database, DES,Task,db,TableVacuate,Process | |
| 39 | 21 | |
| 40 | 22 | from app.util.component.StructuredPrint import StructurePrint |
| 41 | -from app.util.component.PGUtil import PGUtil | |
| 42 | -import multiprocessing | |
| 43 | -import uuid | |
| 44 | -import configure | |
| 23 | + | |
| 45 | 24 | from osgeo.ogr import DataSource,Layer,Geometry |
| 46 | -from osgeo import ogr | |
| 25 | + | |
| 47 | 26 | from app.util.component.VacuateConf import VacuateConf |
| 48 | 27 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 49 | -from app.models import * | |
| 50 | 28 | |
| 51 | 29 | import traceback |
| 52 | - | |
| 53 | 30 | from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature |
| 54 | 31 | from osgeo import gdal,ogr |
| 55 | 32 | import os |
| 56 | 33 | import uuid |
| 57 | 34 | import configure |
| 58 | -from app.util.component.ApiTemplate import ApiTemplate | |
| 35 | + | |
| 59 | 36 | from app.util.component.PGUtil import PGUtil |
| 60 | 37 | from app.util.component.ZipUtil import ZipUtil |
| 61 | 38 | import multiprocessing |
| 62 | 39 | |
| 63 | 40 | |
| 64 | - | |
| 65 | 41 | def task_consumer(): |
| 66 | 42 | |
| 67 | 43 | running_dict = {} | ... | ... |
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | #createtime: 2020/9/4 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from app.models import db,Task,Process | |
| 6 | +from ..models import db,Task,Process | |
| 7 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 8 | 8 | from app.util.component.ModelVisitor import ModelVisitor |
| 9 | 9 | class Api(ApiTemplate): | ... | ... |
app/modules/data/util/EntryDataVacuate.py
0 → 100644
| 1 | + | |
| 2 | +from osgeo.ogr import * | |
| 3 | +from osgeo import ogr | |
| 4 | +from osgeo import gdal | |
| 5 | +import os | |
| 6 | +import uuid | |
| 7 | +import shutil | |
| 8 | +import time | |
| 9 | +from app.modules.data.models import * | |
| 10 | +from app.util.component.PGUtil import PGUtil | |
| 11 | +from app.util.component.StructuredPrint import StructurePrint | |
| 12 | +from sqlalchemy.orm import Session | |
| 13 | +import configure | |
| 14 | +import math | |
| 15 | +from functools import lru_cache | |
| 16 | +import traceback | |
| 17 | +import copy | |
| 18 | +from app.util.component.GeometryAdapter import GeometryAdapter | |
| 19 | +from app.util.component.VacuateConf import VacuateConf | |
| 20 | +import datetime | |
| 21 | +class EntryDataVacuate: | |
| 22 | + | |
| 23 | + def entry(self,parameter): | |
| 24 | + # meta:dict = parameter.get("meta") | |
| 25 | + | |
| 26 | + # 初始化任务 | |
| 27 | + this_task = ThisTask(parameter) | |
| 28 | + this_task.write_process("入库任务初始化...") | |
| 29 | + | |
| 30 | + # 数据路径,用作删除 | |
| 31 | + _data_path=None | |
| 32 | + try: | |
| 33 | + metas: list = parameter.get("meta") | |
| 34 | + # 总的入库是否成功 | |
| 35 | + is_success=True | |
| 36 | + | |
| 37 | + this_task.update({"process": "入库中"}) | |
| 38 | + | |
| 39 | + # 开始入库事务 | |
| 40 | + this_task.start() | |
| 41 | + | |
| 42 | + # 多个文件依次入库 | |
| 43 | + for meta in metas: | |
| 44 | + #设置编码 | |
| 45 | + encoding = parameter.get("encoding") | |
| 46 | + if encoding: | |
| 47 | + gdal.SetConfigOption("SHAPE_ENCODING",encoding) | |
| 48 | + else: | |
| 49 | + gdal.SetConfigOption("SHAPE_ENCODING", "GBK") | |
| 50 | + | |
| 51 | + #如果包含cpg文件,优先使用cpg文件中声明的编码 | |
| 52 | + encoding_cpg = meta.get("encoding") | |
| 53 | + if encoding_cpg: | |
| 54 | + gdal.SetConfigOption("SHAPE_ENCODING", encoding_cpg) | |
| 55 | + | |
| 56 | + data_path = meta.get("data_path") | |
| 57 | + | |
| 58 | + #设定删除路径 | |
| 59 | + if not _data_path: | |
| 60 | + _data_path=data_path | |
| 61 | + | |
| 62 | + | |
| 63 | + if not data_path: | |
| 64 | + raise Exception("数据错误!") | |
| 65 | + # 分为shp和gdb 2种录入形式 | |
| 66 | + | |
| 67 | + if data_path.endswith("shp"): | |
| 68 | + is_success_one,new_layer_name = self.entry_shp(data_path,this_task,meta) | |
| 69 | + else: | |
| 70 | + is_success_one,new_layer_names = self.entry_gdb(data_path,this_task,meta) | |
| 71 | + | |
| 72 | + #如果其中一个失败,总的入库就失败 | |
| 73 | + if not is_success_one: | |
| 74 | + is_success=False | |
| 75 | + | |
| 76 | + this_task.write_process("数据入库结束。") | |
| 77 | + | |
| 78 | + if is_success: | |
| 79 | + # 更新任务为成功任务 | |
| 80 | + this_task.update({"state": 1,"process":"入库完成","update_time": datetime.datetime.now()}) | |
| 81 | + this_task.commit() | |
| 82 | + else: | |
| 83 | + # 更新任务为失败任务 | |
| 84 | + this_task.update({"state": -1, "process": "入库失败", "update_time": datetime.datetime.now()}) | |
| 85 | + # rollback | |
| 86 | + this_task.rollback() | |
| 87 | + | |
| 88 | + except Exception as e: | |
| 89 | + this_task.write_process("{} 任务结束!".format(e.__str__())) | |
| 90 | + this_task.update({"state": -1, "process": "入库失败", "update_time": datetime.datetime.now()}) | |
| 91 | + StructurePrint().print(e.__str__(),"ERROR") | |
| 92 | + # rollback | |
| 93 | + this_task.rollback() | |
| 94 | + finally: | |
| 95 | + this_task.end() | |
| 96 | + try: | |
| 97 | + file_tmp_path = os.path.join(_data_path.split("file_tmp")[0],"file_tmp") | |
| 98 | + dir_path = os.path.dirname(_data_path) | |
| 99 | + i=0 | |
| 100 | + while not os.path.dirname(dir_path).__eq__(file_tmp_path) and i<30: | |
| 101 | + dir_path = os.path.dirname(dir_path) | |
| 102 | + i+=1 | |
| 103 | + if i<30: | |
| 104 | + shutil.rmtree(dir_path,True) | |
| 105 | + StructurePrint().print("删除文件成功!") | |
| 106 | + else: | |
| 107 | + raise Exception("找不到文件!") | |
| 108 | + | |
| 109 | + except Exception as e: | |
| 110 | + StructurePrint().print(e.__str__(), "ERROR") | |
| 111 | + StructurePrint().print("删除文件失败!","ERROR") | |
| 112 | + | |
| 113 | + | |
| 114 | + def entry_shp(self,data_path,this_task,meta): | |
| 115 | + ''' | |
| 116 | + 录入shp | |
| 117 | + :param data_path: | |
| 118 | + :return: | |
| 119 | + ''' | |
| 120 | + | |
| 121 | + driver: Driver = ogr.GetDriverByName("ESRI Shapefile") | |
| 122 | + ds: DataSource = driver.Open(data_path, 1) | |
| 123 | + if not ds: | |
| 124 | + raise Exception("打开数据失败!") | |
| 125 | + layer: Layer = ds.GetLayer(0) | |
| 126 | + | |
| 127 | + is_success_one, new_layer_name =self.entry_one_layer(layer, this_task,meta) | |
| 128 | + ds.Destroy() | |
| 129 | + return is_success_one, new_layer_name | |
| 130 | + | |
| 131 | + def entry_gdb(self,data_path,this_task,meta): | |
| 132 | + ''' | |
| 133 | + 录入gdb | |
| 134 | + :param data_path: | |
| 135 | + :return: | |
| 136 | + ''' | |
| 137 | + | |
| 138 | + is_successes = [] | |
| 139 | + new_layer_names=[] | |
| 140 | + driver: Driver = ogr.GetDriverByName("OpenFileGDB") | |
| 141 | + ds: DataSource = driver.Open(data_path, 0) | |
| 142 | + if not ds: | |
| 143 | + raise Exception("打开数据失败!") | |
| 144 | + | |
| 145 | + | |
| 146 | + for i in range(ds.GetLayerCount()): | |
| 147 | + layer: Layer = ds.GetLayer(i) | |
| 148 | + is_success, new_layer_name = self.entry_one_layer(layer,this_task,meta) | |
| 149 | + new_layer_names.append(new_layer_name) | |
| 150 | + is_successes.append(is_success) | |
| 151 | + ds.Destroy() | |
| 152 | + if is_successes.__contains__(False): | |
| 153 | + return False,new_layer_names | |
| 154 | + else: | |
| 155 | + return True,new_layer_names | |
| 156 | + | |
| 157 | + def entry_one_layer(self,layer: Layer,this_task,meta): | |
| 158 | + | |
| 159 | + # this_task.pg_ds.StartTransaction() | |
| 160 | + new_layer_name = None | |
| 161 | + # vacuate_process= None | |
| 162 | + success = True | |
| 163 | + table_guid = uuid.uuid1().__str__() | |
| 164 | + try: | |
| 165 | + # 图层设置 | |
| 166 | + parameter = this_task.parameter | |
| 167 | + | |
| 168 | + overwrite = parameter.get("overwrite") if parameter.get("overwrite") is not None and parameter.get("overwrite")=="yes" else "no" | |
| 169 | + geom_name = parameter.get("geom_name") if parameter.get("geom_name") is not None else "geom" | |
| 170 | + fid = parameter.get("fid") if parameter.get("fid") is not None else "fid" | |
| 171 | + options = ["OVERWRITE={}".format(overwrite), "FID={}".format(fid), "GEOMETRY_NAME={}".format(geom_name),"PRECISION=NO"] | |
| 172 | + | |
| 173 | + | |
| 174 | + # 将线/面转多线多面 | |
| 175 | + geom_type = GeometryAdapter.change_geom_type(layer.GetGeomType()) | |
| 176 | + | |
| 177 | + # 更改图层名 | |
| 178 | + change_name = False | |
| 179 | + origin_name = layer.GetName().lower() | |
| 180 | + | |
| 181 | + # 新图层名 | |
| 182 | + new_layer_name: str = meta.get("layer").get(origin_name) | |
| 183 | + origin_name = new_layer_name | |
| 184 | + no = 1 | |
| 185 | + while overwrite.__eq__("no") and this_task.pg_ds.GetLayerByName(new_layer_name) : | |
| 186 | + change_name=True | |
| 187 | + new_layer_name = origin_name+"_{}".format(no) | |
| 188 | + no+=1 | |
| 189 | + | |
| 190 | + if change_name: | |
| 191 | + this_task.write_process("{}图层已存在,更名为{}入库".format(origin_name, new_layer_name)) | |
| 192 | + | |
| 193 | + | |
| 194 | + this_task.write_process("{}图层正在入库...".format(new_layer_name)) | |
| 195 | + | |
| 196 | + pg_layer: Layer = this_task.pg_ds.CreateLayer(new_layer_name, layer.GetSpatialRef(), geom_type, options) | |
| 197 | + | |
| 198 | + # 复制原图层的属性 | |
| 199 | + # 去掉fid的属性 | |
| 200 | + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)] | |
| 201 | + pg_layer.CreateFields(schema) | |
| 202 | + | |
| 203 | + #创建抽稀过程 | |
| 204 | + # vacuate_process = VacuateProcess(layer,table_guid,options) | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + count =0 | |
| 209 | + | |
| 210 | + for feature in layer: | |
| 211 | + count+=1 | |
| 212 | + if count%10000==0: | |
| 213 | + StructurePrint().print("{}图层已入库{}个对象".format(new_layer_name,count)) | |
| 214 | + # print(time.time()-this_time) | |
| 215 | + #this_time=time.time() | |
| 216 | + geo :Geometry = feature.GetGeometryRef() | |
| 217 | + # 如果是空对象不录入 | |
| 218 | + if geo is not None: | |
| 219 | + if geo.IsEmpty(): | |
| 220 | + this_task.write_process("FID:{}要素的空间字段为空,跳过该要素!".format(feature.GetFID())) | |
| 221 | + StructurePrint().print("FID:{}要素的空间字段为空,跳过该要素!".format(feature.GetFID()),"WARN") | |
| 222 | + continue | |
| 223 | + | |
| 224 | + out_feature: Feature = copy.copy(feature) | |
| 225 | + out_geom = None | |
| 226 | + if geo is not None: | |
| 227 | + out_geom:Geometry = GeometryAdapter.change_geom(geo, geom_type) | |
| 228 | + out_feature.SetGeometry(out_geom) | |
| 229 | + # 出现fid为0经常有问题 | |
| 230 | + out_feature.SetFID(out_feature.GetFID() + 1) | |
| 231 | + pg_layer.CreateFeature(out_feature) | |
| 232 | + | |
| 233 | + #插入抽稀图层 | |
| 234 | + # if out_geom is not None: | |
| 235 | + # vacuate_process.vacuate(out_geom) | |
| 236 | + | |
| 237 | + # 注册图层信息 | |
| 238 | + # 是否抽吸过 | |
| 239 | + # is_vacuate = 1 if vacuate_process.max_level>0 else 0 | |
| 240 | + is_vacuate = 0 | |
| 241 | + | |
| 242 | + this_task.register_table(pg_layer,new_layer_name,overwrite,parameter.get("creator"),is_vacuate,table_guid) | |
| 243 | + | |
| 244 | + # 注册抽稀表 | |
| 245 | + # this_task.register_table_vacuate(table_guid,vacuate_process.vacuate_layers) | |
| 246 | + | |
| 247 | + this_task.write_process("{}图层入库成功。".format(new_layer_name)) | |
| 248 | + | |
| 249 | + except Exception as e: | |
| 250 | + | |
| 251 | + this_task.write_process("{}入库失败,数据回滚!原因:{}".format(new_layer_name,e.__str__())) | |
| 252 | + StructurePrint().print("{}入库失败,数据回滚!原因:{}".format(new_layer_name,e.__str__()), "error") | |
| 253 | + print(traceback.format_exc()) | |
| 254 | + # 抽稀回滚 | |
| 255 | + # vacuate_process.rollback() | |
| 256 | + success =False | |
| 257 | + | |
| 258 | + finally: | |
| 259 | + # vacuate_process.end() | |
| 260 | + pass | |
| 261 | + return success,new_layer_name | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | +class ThisTask: | |
| 266 | + | |
| 267 | + def __init__(self, parameter): | |
| 268 | + try: | |
| 269 | + # 该任务事务的连接 | |
| 270 | + self.sys_session: Session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) | |
| 271 | + # 专门的写过程的连接 | |
| 272 | + self.process_session: Session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) | |
| 273 | + | |
| 274 | + except Exception as e: | |
| 275 | + raise Exception("打开数据库失败!") | |
| 276 | + self.parameter = parameter | |
| 277 | + | |
| 278 | + self.task = self.process_session.query(Task).filter_by(guid=parameter.get("task_guid")) | |
| 279 | + | |
| 280 | + self.database = self.sys_session.query(Database).filter_by( | |
| 281 | + guid=parameter.get("database_guid")).one_or_none() | |
| 282 | + | |
| 283 | + self.catalog_guid = parameter.get("catalog_guid") | |
| 284 | + | |
| 285 | + self.pg_ds: DataSource = PGUtil.open_pg_data_source(1, DES.decode(self.database.sqlalchemy_uri)) | |
| 286 | + | |
| 287 | + | |
| 288 | + def start(self): | |
| 289 | + self.pg_ds.StartTransaction() | |
| 290 | + | |
| 291 | + def update(self, update_dict): | |
| 292 | + self.task.update(update_dict) | |
| 293 | + self.process_session.commit() | |
| 294 | + | |
| 295 | + def write_process(self, message): | |
| 296 | + message = "{} {}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), message) | |
| 297 | + task_process_guid = uuid.uuid1().__str__() | |
| 298 | + task_process = Process(guid=task_process_guid, message=message, time=datetime.datetime.now(), | |
| 299 | + task_guid=self.parameter.get("task_guid")) | |
| 300 | + self.process_session.add(task_process) | |
| 301 | + self.process_session.commit() | |
| 302 | + | |
| 303 | + def register_table(self, layer: Layer, new_layer_name, overwrite, creator,is_vacuate,table_guid): | |
| 304 | + ''' | |
| 305 | + 注册表 | |
| 306 | + :param layer: 图层 | |
| 307 | + :param new_layer_name: 图层名 | |
| 308 | + :return: 表名 | |
| 309 | + ''' | |
| 310 | + | |
| 311 | + this_time = datetime.datetime.now() | |
| 312 | + | |
| 313 | + ext = layer.GetExtent() | |
| 314 | + if ext[0] < 360: | |
| 315 | + ext = [round(e, 6) for e in ext] | |
| 316 | + else: | |
| 317 | + ext = [round(e, 2) for e in ext] | |
| 318 | + | |
| 319 | + geom_type = GeometryAdapter.get_geometry_type(layer) | |
| 320 | + | |
| 321 | + extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3]) | |
| 322 | + | |
| 323 | + table = Table(guid=table_guid, | |
| 324 | + database_guid=self.database.guid, | |
| 325 | + creator=creator, | |
| 326 | + name=new_layer_name, create_time=this_time, update_time=this_time, | |
| 327 | + catalog_guid=self.catalog_guid, table_type=GeometryAdapter.get_table_type(geom_type), | |
| 328 | + extent=extent, | |
| 329 | + feature_count=layer.GetFeatureCount(), | |
| 330 | + is_vacuate=is_vacuate | |
| 331 | + ) | |
| 332 | + # 删除遗留业务数据 | |
| 333 | + history_table = self.sys_session.query(Table).filter_by(name=new_layer_name,database_guid=self.database.guid).all() | |
| 334 | + if history_table: | |
| 335 | + for ht in history_table: | |
| 336 | + self.sys_session.delete(ht) | |
| 337 | + self.sys_session.add(table) | |
| 338 | + | |
| 339 | + feature_defn: FeatureDefn = layer.GetLayerDefn() | |
| 340 | + | |
| 341 | + for i in range(feature_defn.GetFieldCount()): | |
| 342 | + field_defn: FieldDefn = feature_defn.GetFieldDefn(i) | |
| 343 | + field_name = field_defn.GetName().lower() | |
| 344 | + field_alias = field_name if field_defn.GetAlternativeName() is None or field_defn.GetAlternativeName().__eq__( | |
| 345 | + "") else field_defn.GetAlternativeName() | |
| 346 | + column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid, | |
| 347 | + name=field_name, alias=field_alias, create_time=this_time, update_time=this_time) | |
| 348 | + self.sys_session.add(column) | |
| 349 | + return table_guid | |
| 350 | + | |
| 351 | + | |
| 352 | + def register_table_vacuate(self,table_guid,vacuate_layers:dict): | |
| 353 | + | |
| 354 | + # 抽稀表有固定的命名规则 | |
| 355 | + for level,layer in vacuate_layers.items(): | |
| 356 | + pixel_distance_str:str=layer.GetName().split("_")[-1] | |
| 357 | + lev = layer.GetName().split("_")[-2] | |
| 358 | + | |
| 359 | + if pixel_distance_str.startswith("0"): | |
| 360 | + pixel_distance_str="0.{}".format(pixel_distance_str) | |
| 361 | + | |
| 362 | + pixel_distance = float(pixel_distance_str) | |
| 363 | + | |
| 364 | + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), | |
| 365 | + table_guid=table_guid, | |
| 366 | + level=int(lev), | |
| 367 | + name=layer.GetName(), | |
| 368 | + pixel_distance=pixel_distance) | |
| 369 | + self.sys_session.add(table_vacuate) | |
| 370 | + | |
| 371 | + | |
| 372 | + def commit(self): | |
| 373 | + if self.sys_session: | |
| 374 | + self.sys_session.commit() | |
| 375 | + if self.pg_ds: | |
| 376 | + self.pg_ds.CommitTransaction() | |
| 377 | + if self.process_session: | |
| 378 | + self.process_session.commit() | |
| 379 | + | |
| 380 | + | |
| 381 | + def end(self): | |
| 382 | + if self.sys_session: | |
| 383 | + self.sys_session.close() | |
| 384 | + if self.pg_ds: | |
| 385 | + self.pg_ds.Destroy() | |
| 386 | + if self.process_session: | |
| 387 | + self.process_session.close() | |
| 388 | + | |
| 389 | + def rollback(self): | |
| 390 | + if self.sys_session: | |
| 391 | + self.sys_session.rollback() | |
| 392 | + if self.pg_ds: | |
| 393 | + self.pg_ds.RollbackTransaction() | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | +class VacuateProcess: | |
| 398 | + | |
| 399 | + max_level=0 | |
| 400 | + fill_dict={} | |
| 401 | + vacuate_layers={} | |
| 402 | + vacuate_layers_gridsize={} | |
| 403 | + pg_ds_dict = {} | |
| 404 | + # 图层要素大于5W才抽稀 | |
| 405 | + least_vacuate_count = VacuateConf.least_vacuate_count | |
| 406 | + | |
| 407 | + extent=[] | |
| 408 | + is_spatial=False | |
| 409 | + | |
| 410 | + lonlat_gridsize = VacuateConf.lonlat_gridsize | |
| 411 | + project_gridsize = VacuateConf.project_gridsize | |
| 412 | + | |
| 413 | + # 该抽稀过程使用的grid_size | |
| 414 | + t_grid_size = [] | |
| 415 | + | |
| 416 | + # 该抽稀过程的抽稀网格 | |
| 417 | + this_gridsize=[] | |
| 418 | + | |
| 419 | + | |
| 420 | + def __init__(self,layer:Layer,table_guid, options,sqlalchemy_uri): | |
| 421 | + | |
| 422 | + #是空间图层才初始化 | |
| 423 | + if layer.GetExtent()[0] > 0 or layer.GetExtent()[0] < 0: | |
| 424 | + | |
| 425 | + self.is_spatial=True | |
| 426 | + | |
| 427 | + # 判断需要抽稀多少级 | |
| 428 | + | |
| 429 | + lc = layer.GetFeatureCount() | |
| 430 | + extent = layer.GetExtent() | |
| 431 | + self.extent=extent | |
| 432 | + | |
| 433 | + #判断疏密程度 | |
| 434 | + p_x = (extent[1]-extent[0])/10.0 | |
| 435 | + p_y = (extent[3] - extent[2]) / 10.0 | |
| 436 | + fill_precent=0 | |
| 437 | + StructurePrint().print("判断疏密") | |
| 438 | + for ix in range(10): | |
| 439 | + for iy in range(10): | |
| 440 | + 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] | |
| 441 | + poly = GeometryAdapter.envelop_2_polygon(grid_extent) | |
| 442 | + | |
| 443 | + layer.SetSpatialFilter(None) | |
| 444 | + layer.SetSpatialFilter(poly) | |
| 445 | + layer.ResetReading() | |
| 446 | + if layer.GetNextFeature(): | |
| 447 | + fill_precent += 1 | |
| 448 | + | |
| 449 | + print(fill_precent) | |
| 450 | + StructurePrint().print("判断疏密结束") | |
| 451 | + | |
| 452 | + layer.SetSpatialFilter(None) | |
| 453 | + layer.ResetReading() | |
| 454 | + # 固有疏密程度 | |
| 455 | + original_density=8 | |
| 456 | + | |
| 457 | + | |
| 458 | + # 额外一层 | |
| 459 | + # self.this_gridsize.append(0.000075) | |
| 460 | + # self.max_level += 1 | |
| 461 | + ###### | |
| 462 | + | |
| 463 | + if extent[0]>180: | |
| 464 | + self.t_grid_size=self.project_gridsize | |
| 465 | + else: | |
| 466 | + self.t_grid_size = self.lonlat_gridsize | |
| 467 | + | |
| 468 | + for grid_size in self.t_grid_size: | |
| 469 | + # 最少抽稀个数 | |
| 470 | + if lc > self.least_vacuate_count: | |
| 471 | + # 网格数至少大于 | |
| 472 | + if ((extent[1] - extent[0]) * (extent[3] - extent[2])) / (grid_size**2)>self.least_vacuate_count: | |
| 473 | + # 要素数量大于网格数量 | |
| 474 | + # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数 | |
| 475 | + if lc * original_density * (100.0/fill_precent)>((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2) : | |
| 476 | + print(grid_size) | |
| 477 | + self.this_gridsize.append(grid_size) | |
| 478 | + self.max_level += 1 | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + # 创建抽稀ds | |
| 483 | + for l in range(self.max_level): | |
| 484 | + # pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, DES.decode(sqlalchemy_uri)) | |
| 485 | + if configure.VACUATE_DB_URI: | |
| 486 | + pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, configure.VACUATE_DB_URI) | |
| 487 | + else: | |
| 488 | + pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, DES.decode(sqlalchemy_uri)) | |
| 489 | + pg_ds_l.StartTransaction() | |
| 490 | + self.pg_ds_dict[l] = pg_ds_l | |
| 491 | + | |
| 492 | + # 生成抽稀图层 | |
| 493 | + options = options[1:] | |
| 494 | + options.append("OVERWRITE=yes") | |
| 495 | + options.append("LAUNDER=no") | |
| 496 | + | |
| 497 | + schema = layer.schema | |
| 498 | + # 增加统计字段 | |
| 499 | + schema.append(ogr.FieldDefn("_dcigrid_count_", ogr.OFTInteger)) | |
| 500 | + schema.append(ogr.FieldDefn("_dcigrid_name_", ogr.OFTString)) | |
| 501 | + | |
| 502 | + for l in range(self.max_level): | |
| 503 | + this_grid_len = self.this_gridsize[l] | |
| 504 | + | |
| 505 | + self.vacuate_layers_gridsize[l] = this_grid_len | |
| 506 | + | |
| 507 | + pg = self.pg_ds_dict[l] | |
| 508 | + | |
| 509 | + grid_name = str(this_grid_len) | |
| 510 | + if this_grid_len<1: | |
| 511 | + grid_name = str(this_grid_len).split(".")[-1] | |
| 512 | + if this_grid_len.__eq__(0.00008): | |
| 513 | + grid_name = "00008" | |
| 514 | + | |
| 515 | + # 抽稀图层是点面混合的 | |
| 516 | + # 抽稀表有固定的命名规则 | |
| 517 | + # 抽稀表一定要覆盖 | |
| 518 | + | |
| 519 | + | |
| 520 | + print("{}:{}".format(self.t_grid_size.index(this_grid_len),this_grid_len)) | |
| 521 | + | |
| 522 | + | |
| 523 | + v_ln = "z{}_vacuate_{}_{}".format(table_guid, self.t_grid_size.index(this_grid_len), grid_name) | |
| 524 | + vl = pg.CreateLayer(v_ln, layer.GetSpatialRef(),ogr.wkbUnknown, options) | |
| 525 | + # 抽稀表需要属性 | |
| 526 | + vl.CreateFields(schema) | |
| 527 | + self.vacuate_layers[l] = vl | |
| 528 | + | |
| 529 | + else: | |
| 530 | + pass | |
| 531 | + | |
| 532 | + | |
| 533 | + def vacuate(self,g,feature): | |
| 534 | + | |
| 535 | + if self.is_spatial: | |
| 536 | + | |
| 537 | + # 插入到所有抽稀图层中 | |
| 538 | + for level in range(self.max_level): | |
| 539 | + | |
| 540 | + center: Geometry = g.Centroid() | |
| 541 | + | |
| 542 | + extent = g.GetEnvelope() | |
| 543 | + long_extent= extent[1]-extent[0] | |
| 544 | + lat_extent = extent[3]-extent[2] | |
| 545 | + | |
| 546 | + this_grid_len =self.vacuate_layers_gridsize[level] | |
| 547 | + #超大的直接加入 | |
| 548 | + # if long_extent > 10*this_grid_len or lat_extent >10*this_grid_len: | |
| 549 | + # vacuate_layer: Layer = self.vacuate_layers.get(level) | |
| 550 | + # feat = ogr.Feature(vacuate_layer.GetLayerDefn()) | |
| 551 | + # feat.SetGeometry(g) | |
| 552 | + # vacuate_layer.CreateFeature(feat) | |
| 553 | + # else: | |
| 554 | + | |
| 555 | + row = int((center.GetY() - self.extent[2]) / this_grid_len) | |
| 556 | + col = int((center.GetX() - self.extent[0]) / this_grid_len) | |
| 557 | + key = "{}.{}.{}".format(level, row, col) | |
| 558 | + | |
| 559 | + if not self.fill_dict.get(key): | |
| 560 | + self.fill_dict[key] = 0 | |
| 561 | + if self.fill_dict[key] == 0: | |
| 562 | + | |
| 563 | + vacuate_layer: Layer = self.vacuate_layers.get(level) | |
| 564 | + feat = ogr.Feature(vacuate_layer.GetLayerDefn()) | |
| 565 | + # 如果图形比网格小,直接存储其中心点 | |
| 566 | + if this_grid_len>long_extent and this_grid_len>lat_extent: | |
| 567 | + feat.SetGeometry(center) | |
| 568 | + else: | |
| 569 | + feat.SetGeometry(g) | |
| 570 | + | |
| 571 | + # 复制旧feature属性 | |
| 572 | + field_dict = feature.items() | |
| 573 | + for field_name in field_dict: | |
| 574 | + feat.SetField(field_name, field_dict[field_name]) | |
| 575 | + feat.SetField("_dcigrid_name_",".".join(key.split(".")[1:])) | |
| 576 | + | |
| 577 | + vacuate_layer.CreateFeature(feat) | |
| 578 | + self.fill_dict[key] += 1 | |
| 579 | + #超大的还有机会 | |
| 580 | + elif (long_extent > 10*this_grid_len or lat_extent >10*this_grid_len) and self.fill_dict[key]<5: | |
| 581 | + vacuate_layer: Layer = self.vacuate_layers.get(level) | |
| 582 | + feat = ogr.Feature(vacuate_layer.GetLayerDefn()) | |
| 583 | + feat.SetGeometry(g) | |
| 584 | + | |
| 585 | + # 复制旧feature属性 | |
| 586 | + field_dict = feature.items() | |
| 587 | + for field_name in field_dict: | |
| 588 | + feat.SetField(field_name, field_dict[field_name]) | |
| 589 | + feat.SetField("_dcigrid_name_",".".join(key.split(".")[1:])) | |
| 590 | + | |
| 591 | + vacuate_layer.CreateFeature(feat) | |
| 592 | + self.fill_dict[key] += 1 | |
| 593 | + else: | |
| 594 | + self.fill_dict[key] += 1 | |
| 595 | + | |
| 596 | + def set_vacuate_count(self): | |
| 597 | + if self.is_spatial: | |
| 598 | + # 插入到所有抽稀图层中 | |
| 599 | + for level in range(self.max_level): | |
| 600 | + vacuate_layer: Layer = self.vacuate_layers.get(level) | |
| 601 | + for feat in vacuate_layer: | |
| 602 | + key = "{}.{}".format(level,feat.GetField("_dcigrid_name_")) | |
| 603 | + feat.SetField("_dcigrid_count_",self.fill_dict.get(key)) | |
| 604 | + vacuate_layer.SetFeature(feat) | |
| 605 | + | |
| 606 | + def end(self): | |
| 607 | + for pg in self.pg_ds_dict.values(): | |
| 608 | + pg.Destroy() | |
| 609 | + | |
| 610 | + def rollback(self): | |
| 611 | + for pg in self.pg_ds_dict.values(): | |
| 612 | + pg.RollbackTransaction() | ... | ... |
app/modules/data/util/__init__.py
0 → 100644
| ... | ... | @@ -7,7 +7,7 @@ from flask import current_app as app |
| 7 | 7 | import socket |
| 8 | 8 | |
| 9 | 9 | from app.util.component.ApiTemplate import ApiTemplate |
| 10 | -from app.models import Task,InsertingLayerName,db | |
| 10 | +from app.modules.data.models import Task,InsertingLayerName,db | |
| 11 | 11 | import datetime |
| 12 | 12 | import traceback |
| 13 | 13 | from sqlalchemy import or_ | ... | ... |
| ... | ... | @@ -12,10 +12,8 @@ from . import image_server_list |
| 12 | 12 | from . import data_list |
| 13 | 13 | from . import capabilities |
| 14 | 14 | from . import image_tile,image_wms |
| 15 | -from . import image_service_list | |
| 16 | 15 | from . import image_tile_mask |
| 17 | 16 | from . import image_wmts |
| 18 | - | |
| 19 | 17 | from . import image_delete |
| 20 | 18 | from . import image_cancle |
| 21 | 19 | from . import image_register,image_list,image_info,image_edit,image_overview |
| ... | ... | @@ -23,10 +21,14 @@ from . import image_tag_create,image_tag_delete,image_tag_list |
| 23 | 21 | from . import image_wms_temporary |
| 24 | 22 | from . import image_wms_kv |
| 25 | 23 | |
| 26 | -class DataManager(BlueprintApi): | |
| 27 | 24 | |
| 28 | - bp = Blueprint("Image", __name__, url_prefix="/API/Service/Image") | |
| 29 | - service_type = ["ImageWMS","ImageWMTS"] | |
| 25 | +class ImageServerInstance: | |
| 26 | + pass | |
| 27 | + | |
| 28 | +class ImageManager(BlueprintApi): | |
| 29 | + | |
| 30 | + bp = Blueprint("ImageService", __name__, url_prefix="/API/Service/Image") | |
| 31 | + service_type = ["影像服务"] | |
| 30 | 32 | |
| 31 | 33 | @staticmethod |
| 32 | 34 | @bp.route('/Register', methods=['POST']) |
| ... | ... | @@ -122,14 +124,7 @@ class DataManager(BlueprintApi): |
| 122 | 124 | """ |
| 123 | 125 | return image_service_register.Api().result |
| 124 | 126 | |
| 125 | - @staticmethod | |
| 126 | - @bp.route('/ServiceList', methods=['GET']) | |
| 127 | - @swag_from(image_service_list.Api.api_doc) | |
| 128 | - def api_image_service_list(): | |
| 129 | - """ | |
| 130 | - 服务列表 | |
| 131 | - """ | |
| 132 | - return image_service_list.Api().result | |
| 127 | + | |
| 133 | 128 | |
| 134 | 129 | @staticmethod |
| 135 | 130 | @bp.route('/ServerList', methods=['GET']) | ... | ... |
| ... | ... | @@ -6,8 +6,8 @@ |
| 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 | |
| 9 | +from ..models import ImageService | |
| 10 | +from ..models import Service,TileScheme | |
| 11 | 11 | import json |
| 12 | 12 | import configure |
| 13 | 13 | ... | ... |
| ... | ... | @@ -12,7 +12,7 @@ import datetime |
| 12 | 12 | from app.modules.service.image.util.ThriftConnect import ThriftConnect |
| 13 | 13 | import os |
| 14 | 14 | from app.models import db |
| 15 | -from app.modules.service.image.models import Image | |
| 15 | +from app.modules.service.models import Image | |
| 16 | 16 | from .util.ImageType import ImageType |
| 17 | 17 | |
| 18 | 18 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 8 | 8 | from app.util.component.ModelVisitor import ModelVisitor |
| 9 | 9 | |
| 10 | -from app.modules.service.image.models import Image,ImageTag | |
| 10 | +from app.modules.service.models import Image,ImageTag | |
| 11 | 11 | from app.util.component.FileProcess import FileProcess |
| 12 | 12 | |
| 13 | 13 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -7,7 +7,7 @@ |
| 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 | -from app.modules.service.image.models import Image,ImageTag | |
| 10 | +from app.modules.service.models import Image,ImageTag | |
| 11 | 11 | from sqlalchemy import or_ |
| 12 | 12 | import datetime |
| 13 | 13 | |
| ... | ... | @@ -27,7 +27,7 @@ class Api(ApiTemplate): |
| 27 | 27 | name = self.para.get("name") |
| 28 | 28 | band = self.para.get("band") |
| 29 | 29 | region = self.para.get("region") |
| 30 | - tag_guid = self.para.get("tag_guid") | |
| 30 | + tag_guids = self.para.get("tag_guids") | |
| 31 | 31 | collect_time = self.para.get("collect_time") |
| 32 | 32 | |
| 33 | 33 | type = self.para.get("type") |
| ... | ... | @@ -53,13 +53,17 @@ class Api(ApiTemplate): |
| 53 | 53 | |
| 54 | 54 | if collect_time: |
| 55 | 55 | begin,end = collect_time.split(",") |
| 56 | - begin = datetime.datetime.strptime(begin,"%Y-%m-%d %H:%M:%S") | |
| 57 | - end = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S") | |
| 58 | - images.filter(Image.collect_time>=begin).filter(Image.collect_time<=end) | |
| 56 | + begin:datetime.datetime= datetime.datetime.strptime(begin,"%Y-%m-%d") | |
| 59 | 57 | |
| 60 | - if tag_guid: | |
| 61 | - tag:ImageTag = ImageTag.query.filter_by(guid=tag_guid).one_or_none() | |
| 62 | - images_guid = [img.guid for img in tag.images.all()] | |
| 58 | + end = datetime.datetime.strptime(end, "%Y-%m-%d") | |
| 59 | + images = images.filter(Image.collect_time.__ge__(begin)).filter(Image.collect_time.__le__(end)) | |
| 60 | + | |
| 61 | + if tag_guids: | |
| 62 | + tag_guids = tag_guids.split(",") | |
| 63 | + tags = ImageTag.query.filter(ImageTag.guid.in_(tag_guids)).all() | |
| 64 | + images_guid = [] | |
| 65 | + for tag in tags: | |
| 66 | + images_guid.extend([img.guid for img in tag.images.all()]) | |
| 63 | 67 | images = images.filter(Image.guid.in_(images_guid)) |
| 64 | 68 | |
| 65 | 69 | |
| ... | ... | @@ -112,7 +116,7 @@ class Api(ApiTemplate): |
| 112 | 116 | {"name": "band", |
| 113 | 117 | "in": "formData", |
| 114 | 118 | "type": "string"}, |
| 115 | - {"name": "tag_guid", | |
| 119 | + {"name": "tag_guids", | |
| 116 | 120 | "in": "formData", |
| 117 | 121 | "type": "string"}, |
| 118 | 122 | ], | ... | ... |
| ... | ... | @@ -9,12 +9,12 @@ from osgeo.gdal import Dataset,Band |
| 9 | 9 | from app.util.component.ApiTemplate import ApiTemplate |
| 10 | 10 | from app.modules.service.image.util.ThriftConnect import ThriftConnect |
| 11 | 11 | import json |
| 12 | -from .models import Image | |
| 12 | +from ..models import Image | |
| 13 | 13 | import datetime |
| 14 | 14 | from app.models import db |
| 15 | 15 | import uuid |
| 16 | 16 | import os |
| 17 | -from .models import ImageTag | |
| 17 | +from ..models import ImageTag | |
| 18 | 18 | from .util.ImageType import ImageType |
| 19 | 19 | |
| 20 | 20 | class Api(ApiTemplate): | ... | ... |
| ... | ... | @@ -3,15 +3,15 @@ |
| 3 | 3 | #createtime: 2021/7/19 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from app.modules.service.image.models import ImageService,Image | |
| 7 | -from app.models import db | |
| 6 | + | |
| 7 | + | |
| 8 | 8 | from app.util.component.ApiTemplate import ApiTemplate |
| 9 | -from app.models import Service | |
| 9 | +from ..models import Service,ImageService,Image,db,ServiceFunction | |
| 10 | 10 | import datetime |
| 11 | 11 | import json |
| 12 | 12 | from .image_service_register import Api as RegisterApi |
| 13 | 13 | import configure |
| 14 | - | |
| 14 | +import uuid | |
| 15 | 15 | |
| 16 | 16 | class Api(ApiTemplate): |
| 17 | 17 | |
| ... | ... | @@ -28,19 +28,30 @@ class Api(ApiTemplate): |
| 28 | 28 | service = Service.query.filter_by(guid=guid) |
| 29 | 29 | this_time = datetime.datetime.now() |
| 30 | 30 | image_guids = self.para.get("image_guids") |
| 31 | + function_types = self.para.get("function_types") | |
| 31 | 32 | |
| 32 | 33 | service_update = {} |
| 33 | 34 | image_update = {} |
| 35 | + | |
| 34 | 36 | for key in self.para.keys(): |
| 35 | - if key in ["name","title","state","description","catalog_guid","type"]: | |
| 37 | + if key in ["name","title","state","description","catalog_guid"]: | |
| 36 | 38 | service_update[key] = self.para.get(key) |
| 37 | 39 | if key in ["name","scheme_guid"]: |
| 38 | 40 | image_update[key] = self.para.get(key) |
| 39 | 41 | |
| 42 | + image_service = ImageService.query.filter_by(service_guid=guid) | |
| 40 | 43 | |
| 41 | - | |
| 42 | - image_service = ImageService.query.filter_by(guid=Service.query.filter_by(guid=guid).one_or_none().service_guid) | |
| 43 | - | |
| 44 | + # 修改功能 | |
| 45 | + if function_types: | |
| 46 | + new_types = function_types.split(",") | |
| 47 | + old_functions = ServiceFunction.query.filter_by(service_guid=guid).all() | |
| 48 | + for function in old_functions: | |
| 49 | + if function.type not in new_types: | |
| 50 | + db.session.delete(function) | |
| 51 | + for new_type in new_types: | |
| 52 | + if new_type not in [fun.type for fun in old_functions]: | |
| 53 | + service_function = ServiceFunction(guid=uuid.uuid1().__str__()) | |
| 54 | + db.session.add(service_function) | |
| 44 | 55 | |
| 45 | 56 | #修改影像 |
| 46 | 57 | if image_guids: |
| ... | ... | @@ -63,7 +74,7 @@ class Api(ApiTemplate): |
| 63 | 74 | |
| 64 | 75 | image_update["extent"] = json.dumps(image_service_exetent) |
| 65 | 76 | |
| 66 | - if service_update or image_update: | |
| 77 | + if service_update or image_update or function_types: | |
| 67 | 78 | service_update["update_time"] = this_time |
| 68 | 79 | if image_guids: |
| 69 | 80 | register_api = RegisterApi() |
| ... | ... | @@ -71,6 +82,7 @@ class Api(ApiTemplate): |
| 71 | 82 | service_update["overview"] = "http://{}/API/Service/Overview/{}".format(configure.deploy_ip_host, overview_file) |
| 72 | 83 | |
| 73 | 84 | service.update(service_update) |
| 85 | + | |
| 74 | 86 | if image_update: |
| 75 | 87 | image_service.update(image_update) |
| 76 | 88 | |
| ... | ... | @@ -91,31 +103,32 @@ class Api(ApiTemplate): |
| 91 | 103 | {"name": "guid", |
| 92 | 104 | "in": "formData", |
| 93 | 105 | "type": "string", |
| 94 | - "description": "[WMS,WMTS,影像WMS,影像WMTS,guid]"}, | |
| 106 | + "description": "[地图服务,切片服务,影像服务]guid"}, | |
| 95 | 107 | |
| 96 | 108 | {"name": "name", |
| 97 | 109 | "in": "formData", |
| 98 | 110 | "type": "string", |
| 99 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 111 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 100 | 112 | |
| 101 | - {"name": "type", | |
| 102 | - "in": "formData", | |
| 103 | - "type": "string", | |
| 104 | - "description": "修改服务类型"}, | |
| 105 | 113 | |
| 106 | 114 | {"name": "title", |
| 107 | 115 | "in": "formData", |
| 108 | 116 | "type": "string", |
| 109 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 117 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 110 | 118 | {"name": "description", |
| 111 | 119 | "in": "formData", |
| 112 | 120 | "type": "string", |
| 113 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 121 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 114 | 122 | |
| 115 | 123 | {"name": "catalog_guid", |
| 116 | 124 | "in": "formData", |
| 117 | 125 | "type": "string", |
| 118 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 126 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 127 | + | |
| 128 | + {"name": "function_types", | |
| 129 | + "in": "formData", | |
| 130 | + "type": "string", | |
| 131 | + "description": "[地图服务,切片服务,影像服务]以逗号相隔,可选WMTS,WMS"}, | |
| 119 | 132 | |
| 120 | 133 | |
| 121 | 134 | {"name": "image_guids", | ... | ... |
| 1 | -# coding=utf-8 | |
| 2 | -#author: 4N | |
| 3 | -#createtime: 2021/7/19 | |
| 4 | -#email: nheweijun@sina.com | |
| 5 | - | |
| 6 | -from app.modules.service.image.models import ImageService | |
| 7 | - | |
| 8 | -from app.util.component.ApiTemplate import ApiTemplate | |
| 9 | -from app.util.component.ModelVisitor import ModelVisitor | |
| 10 | -from sqlalchemy import or_ | |
| 11 | -class Api(ApiTemplate): | |
| 12 | - | |
| 13 | - api_name = "影像服务List" | |
| 14 | - | |
| 15 | - def process(self): | |
| 16 | - | |
| 17 | - # 返回结果 | |
| 18 | - res = {} | |
| 19 | - | |
| 20 | - try: | |
| 21 | - page_index = int(self.para.get("page_index", "0")) | |
| 22 | - page_size = int(self.para.get("page_size", "10")) | |
| 23 | - | |
| 24 | - alias = self.para.get("alias") | |
| 25 | - name = self.para.get("name") | |
| 26 | - type = self.para.get("type") | |
| 27 | - | |
| 28 | - services = ImageService.query | |
| 29 | - if type: | |
| 30 | - services = services.filter_by(type=type) | |
| 31 | - # 并集 | |
| 32 | - if alias and name: | |
| 33 | - services = services.filter( | |
| 34 | - or_(ImageService.alias.like("%" + alias + "%"), ImageService.name.like("%" + name + "%"))) | |
| 35 | - else: | |
| 36 | - if alias: | |
| 37 | - services = services.filter(ImageService.alias.like("%" + alias + "%")) | |
| 38 | - if name: | |
| 39 | - services = services.filter(ImageService.name.like("%" + name + "%")) | |
| 40 | - | |
| 41 | - | |
| 42 | - res["data"] = {} | |
| 43 | - res["data"]["count"] = services.count() | |
| 44 | - services = services.limit(page_size).offset(page_index * page_size).all() | |
| 45 | - res["data"]["list"] = ModelVisitor.objects_to_jsonarray(services) | |
| 46 | - res["result"] = True | |
| 47 | - | |
| 48 | - except Exception as e: | |
| 49 | - raise e | |
| 50 | - | |
| 51 | - return res | |
| 52 | - | |
| 53 | - api_doc = { | |
| 54 | - "tags": ["影像接口"], | |
| 55 | - "parameters": [ | |
| 56 | - {"name": "page_index", | |
| 57 | - "in": "formData", | |
| 58 | - "type": "int", | |
| 59 | - "description": "页"}, | |
| 60 | - {"name": "page_size", | |
| 61 | - "in": "formData", | |
| 62 | - "type": "int", | |
| 63 | - "description": "页大小"}, | |
| 64 | - {"name": "alias", | |
| 65 | - "in": "formData", | |
| 66 | - "type": "string", | |
| 67 | - "description": "服务别名"}, | |
| 68 | - {"name": "name", | |
| 69 | - "in": "formData", | |
| 70 | - "type": "string", | |
| 71 | - "description": "服务名"}, | |
| 72 | - ], | |
| 73 | - "responses": { | |
| 74 | - 200: { | |
| 75 | - "schema": { | |
| 76 | - "properties": { | |
| 77 | - } | |
| 78 | - } | |
| 79 | - } | |
| 80 | - } | |
| 81 | - } | |
| \ No newline at end of file |
| ... | ... | @@ -3,8 +3,8 @@ |
| 3 | 3 | #createtime: 2021/7/19 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from .models import ImageService,Image | |
| 7 | -from app.models import db,Service | |
| 6 | + | |
| 7 | +from ..models import db,Service,ImageService,Image,ServiceFunction | |
| 8 | 8 | from app.util.component.ApiTemplate import ApiTemplate |
| 9 | 9 | import uuid |
| 10 | 10 | |
| ... | ... | @@ -19,9 +19,14 @@ class Api(ApiTemplate): |
| 19 | 19 | |
| 20 | 20 | api_name = "注册影像服务" |
| 21 | 21 | |
| 22 | - def process(self): | |
| 22 | + def para_check(self): | |
| 23 | + if not self.para.get("function_types"): | |
| 24 | + raise Exception("缺乏影像服务类型!") | |
| 25 | + if self.para.get("function_types").__contains__("WMTS") and (not self.para.get("scheme_guid")): | |
| 26 | + raise Exception("选择WMTS功能,但是缺乏切片方案!") | |
| 23 | 27 | |
| 24 | 28 | |
| 29 | + def process(self): | |
| 25 | 30 | |
| 26 | 31 | # 返回结果 |
| 27 | 32 | res = {} |
| ... | ... | @@ -29,11 +34,15 @@ class Api(ApiTemplate): |
| 29 | 34 | try: |
| 30 | 35 | guids = self.para.get("guids").split(",") |
| 31 | 36 | name = self.para.get("name") |
| 37 | + function_types = self.para.get("function_types") | |
| 38 | + | |
| 32 | 39 | |
| 33 | 40 | image_service_guid = uuid.uuid1().__str__() |
| 41 | + service_guid = uuid.uuid1().__str__() | |
| 42 | + service_function_guid = uuid.uuid1().__str__() | |
| 43 | + | |
| 34 | 44 | |
| 35 | 45 | this_time = datetime.datetime.now() |
| 36 | - service_guid = uuid.uuid1().__str__() | |
| 37 | 46 | image_service = ImageService(guid=image_service_guid, |
| 38 | 47 | name=name, |
| 39 | 48 | create_time=this_time, |
| ... | ... | @@ -60,7 +69,7 @@ class Api(ApiTemplate): |
| 60 | 69 | |
| 61 | 70 | service = Service( |
| 62 | 71 | guid = service_guid, |
| 63 | - name = self.para.get("name"), | |
| 72 | + name = name, | |
| 64 | 73 | title = self.para.get("title"), |
| 65 | 74 | state = 1, |
| 66 | 75 | create_time = this_time, |
| ... | ... | @@ -68,10 +77,17 @@ class Api(ApiTemplate): |
| 68 | 77 | description = self.para.get("description"), |
| 69 | 78 | #node = Column(Integer), |
| 70 | 79 | type = self.para.get("type"), |
| 71 | - service_guid = image_service_guid, | |
| 72 | 80 | catalog_guid = self.para.get("catalog_guid") |
| 73 | 81 | ) |
| 74 | 82 | |
| 83 | + | |
| 84 | + | |
| 85 | + for type in function_types.split(","): | |
| 86 | + service_function = ServiceFunction(guid=service_function_guid, | |
| 87 | + service_guid=service_guid, | |
| 88 | + type=type) | |
| 89 | + db.session.add(service_function) | |
| 90 | + | |
| 75 | 91 | db.session.add(service) |
| 76 | 92 | db.session.add(image_service) |
| 77 | 93 | |
| ... | ... | @@ -80,8 +96,8 @@ class Api(ApiTemplate): |
| 80 | 96 | overview_file = self.get_overview(service,image_service) |
| 81 | 97 | service.overview="http://{}/API/Service/Overview/{}".format( |
| 82 | 98 | configure.deploy_ip_host,overview_file) |
| 83 | - db.session.commit() | |
| 84 | 99 | |
| 100 | + db.session.commit() | |
| 85 | 101 | res["data"] = image_service_guid |
| 86 | 102 | res["result"] = True |
| 87 | 103 | except Exception as e: |
| ... | ... | @@ -126,35 +142,39 @@ class Api(ApiTemplate): |
| 126 | 142 | "in": "formData", |
| 127 | 143 | "type": "string", |
| 128 | 144 | "required": "true", |
| 129 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 145 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 130 | 146 | {"name": "title", |
| 131 | 147 | "in": "formData", |
| 132 | 148 | "type": "string", |
| 133 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 149 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 134 | 150 | {"name": "description", |
| 135 | 151 | "in": "formData", |
| 136 | 152 | "type": "string", |
| 137 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 153 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 138 | 154 | {"name": "type", |
| 139 | 155 | "in": "formData", |
| 140 | 156 | "type": "string", |
| 141 | - "enum": ["WMS/WFS","WMTS","TMS","ImageWMS","ImageWMTS"], | |
| 157 | + "enum": ["地图服务","切片服务","影像服务"], | |
| 142 | 158 | "required": "true", |
| 143 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 159 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 144 | 160 | {"name": "catalog_guid", |
| 145 | 161 | "in": "formData", |
| 146 | 162 | "type": "string", |
| 147 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 163 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 148 | 164 | |
| 149 | 165 | # 影像参数 |
| 150 | 166 | {"name": "guids", |
| 151 | 167 | "in": "formData", |
| 152 | 168 | "type": "string", |
| 153 | - "description": "[影像WMS,影像WMTS]影像guids,以英文逗号相隔"}, | |
| 169 | + "description": "[影像服务]影像guids,以英文逗号相隔"}, | |
| 154 | 170 | {"name": "scheme_guid", |
| 155 | 171 | "in": "formData", |
| 156 | 172 | "type": "string", |
| 157 | - "description": "[WMTS,影像WMTS]切片方案"}, | |
| 173 | + "description": "[影像服务]切片方案"}, | |
| 174 | + {"name": "function_types", | |
| 175 | + "in": "formData", | |
| 176 | + "type": "string", | |
| 177 | + "description": "[影像服务]功能类型,以逗号相隔,可选WMTS,WMS"}, | |
| 158 | 178 | |
| 159 | 179 | ], |
| 160 | 180 | "responses": { |
| ... | ... | @@ -166,6 +186,3 @@ class Api(ApiTemplate): |
| 166 | 186 | } |
| 167 | 187 | } |
| 168 | 188 | } |
| 169 | - | |
| 170 | -if __name__ == '__main__': | |
| 171 | - pass | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -13,8 +13,8 @@ from flask import Response |
| 13 | 13 | |
| 14 | 14 | import time |
| 15 | 15 | import cv2 |
| 16 | -from app.modules.service.image.models import ImageService,Image | |
| 17 | -from app.models import db,TileScheme | |
| 16 | +from app.modules.service.models import ImageService,Image | |
| 17 | +from ..models import db,TileScheme | |
| 18 | 18 | from app.util.component.ApiTemplate import ApiTemplate |
| 19 | 19 | |
| 20 | 20 | from app.util.component.SliceScheme import SliceScheme |
| ... | ... | @@ -211,7 +211,7 @@ class Api(ApiTemplate): |
| 211 | 211 | |
| 212 | 212 | except Exception as e: |
| 213 | 213 | print(traceback.format_exc()) |
| 214 | - result["state"] = -1 | |
| 214 | + result["result"] = False | |
| 215 | 215 | result["message"] = e.__str__() |
| 216 | 216 | return result |
| 217 | 217 | ... | ... |
| ... | ... | @@ -3,19 +3,11 @@ |
| 3 | 3 | #createtime: 2021/3/24 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from app.util import * | |
| 7 | -import traceback | |
| 8 | -import numpy | |
| 9 | -from flask import Response | |
| 10 | -import random | |
| 11 | -from app.modules.service.image.models import ImageService | |
| 6 | + | |
| 12 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 13 | -from app.util.component.ParameterUtil import ParameterUtil | |
| 14 | -import json | |
| 8 | + | |
| 15 | 9 | from threading import Thread |
| 16 | -from .util.ImageData import ImageData | |
| 17 | -from .util.Cache import Cache | |
| 18 | -from .util.Opencv import Opencv | |
| 10 | +from .util.ImageWMSServer import ImageWMSServer | |
| 19 | 11 | |
| 20 | 12 | class Api(ApiTemplate): |
| 21 | 13 | |
| ... | ... | @@ -27,251 +19,19 @@ class Api(ApiTemplate): |
| 27 | 19 | self.service_name = service_name |
| 28 | 20 | |
| 29 | 21 | def process(self): |
| 30 | - | |
| 31 | - | |
| 32 | - result = {} | |
| 33 | - parameter: dict = self.para | |
| 34 | - | |
| 35 | 22 | try: |
| 36 | - | |
| 37 | - parameter = ParameterUtil.to_lower(parameter) | |
| 38 | - if parameter.get("service_name"): | |
| 39 | - self.service_name = parameter.get("service_name") | |
| 40 | - | |
| 41 | - #获取缓存信息 | |
| 42 | - image_service_info, zoo, servers = Cache.cache_data(self.service_name, type="name") | |
| 43 | - | |
| 44 | - re = parameter.get("request") | |
| 45 | - if re and re.__eq__("GetCapabilities"): | |
| 46 | - return self.get_capabilities(image_service_info["service"]) | |
| 47 | - | |
| 48 | - bbox = parameter.get("bbox") | |
| 49 | - width = int(parameter.get("width")) if parameter.get("width") else 256 | |
| 50 | - height = int(parameter.get("height")) if parameter.get("height") else 256 | |
| 51 | - image_type = parameter.get("format") if parameter.get("format") else "image/png" | |
| 52 | - quality = int(parameter.get("quality")) if parameter.get("quality") else 30 | |
| 53 | - | |
| 54 | - extent = [float(x) for x in bbox.split(",")] | |
| 55 | - | |
| 56 | - intersect_image = [im for im in image_service_info["images"] if self.determin_intersect(json.loads(im.extent),extent)] | |
| 57 | - | |
| 58 | - if len(intersect_image)>1: | |
| 59 | - | |
| 60 | - # 结果矩阵 | |
| 61 | - empty_list = [numpy.zeros((height,width), dtype=int) + 65536, | |
| 62 | - numpy.zeros((height,width), dtype=int) + 65536, | |
| 63 | - numpy.zeros((height,width), dtype=int) + 65536] | |
| 64 | - | |
| 65 | - pixel_array = numpy.zeros((height,width,3), dtype=int) | |
| 66 | - thread_list = [] | |
| 67 | - | |
| 68 | - for image in intersect_image: | |
| 69 | - #该影像的服务器,随机选取一个 | |
| 70 | - image_servers = image.server.split(",") | |
| 71 | - image_servers = [ser for ser in image_servers if ser in servers] | |
| 72 | - if len(image_servers)>0: | |
| 73 | - indx = int(random.random() * len(image_servers)) | |
| 74 | - image_server = image_servers[indx] | |
| 75 | - else: | |
| 76 | - image_server = "None" | |
| 77 | - bands = json.loads(image.band_view) | |
| 78 | - | |
| 79 | - image_data = ImageData(image_server, image) | |
| 80 | - | |
| 81 | - thread: MyThread = MyThread(image_data.get_data, args=(extent,bands,height,width)) | |
| 82 | - thread.start() | |
| 83 | - thread_list.append(thread) | |
| 84 | - | |
| 85 | - | |
| 86 | - for thread in thread_list: | |
| 87 | - thread.join() | |
| 88 | - data = thread.get_result() | |
| 89 | - | |
| 90 | - # 掩膜在中央接口生成,合图 | |
| 91 | - mask = numpy.zeros((height,width), dtype=int) | |
| 92 | - mask2 = numpy.zeros((height,width), dtype=int) | |
| 93 | - jizhun = data[:, :, 0] | |
| 94 | - mask[jizhun == 65536] = 1 | |
| 95 | - mask[jizhun != 65536] = 0 | |
| 96 | - mask2[jizhun == 65536] = 0 | |
| 97 | - mask2[jizhun != 65536] = 1 | |
| 98 | - # 掩膜计算 | |
| 99 | - for i, d in enumerate(empty_list): | |
| 100 | - empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2 | |
| 101 | - | |
| 102 | - for ii in [0, 1, 2]: | |
| 103 | - # opencv 颜色排序为GBR | |
| 104 | - pixel_array[:, :, 2 - ii] = empty_list[ii] | |
| 105 | - | |
| 106 | - | |
| 107 | - elif len(intersect_image)==1: | |
| 108 | - # 该影像的服务器,随机选取一个 | |
| 109 | - image = intersect_image[0] | |
| 110 | - image_servers = image.server.split(",") | |
| 111 | - image_servers = [ser for ser in image_servers if ser in servers] | |
| 112 | - if len(image_servers) > 0: | |
| 113 | - indx = int(random.random() * len(image_servers)) | |
| 114 | - image_server = image_servers[indx] | |
| 115 | - else: | |
| 116 | - image_server = "None" | |
| 117 | - | |
| 118 | - bands = json.loads(image.band_view) | |
| 119 | - | |
| 120 | - image_data = ImageData(image_server, image) | |
| 121 | - | |
| 122 | - pixel_array_t = image_data.get_data(extent,bands,height,width) | |
| 123 | - | |
| 124 | - pixel_array = numpy.zeros((height, width, 3), dtype=int) | |
| 125 | - for ii in [0, 1, 2]: | |
| 126 | - # opencv 颜色排序为GBR | |
| 127 | - pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] | |
| 128 | - else: | |
| 129 | - # 结果矩阵 | |
| 130 | - pixel_array = numpy.zeros((height, width, 3), dtype=int)+65536 | |
| 131 | - | |
| 132 | - # 将图片生成在内存中,然后直接返回response | |
| 133 | - im_data = Opencv.create_image(image_type, pixel_array, quality) | |
| 134 | - | |
| 135 | - if self.para.get("overview"): | |
| 136 | - return pixel_array | |
| 137 | - return Response(im_data, mimetype=image_type.lower()) | |
| 23 | + instance = ImageWMSServer() | |
| 24 | + response = instance.wms(self.service_name,self.para) | |
| 138 | 25 | |
| 139 | 26 | except Exception as e: |
| 140 | - print(traceback.format_exc()) | |
| 141 | - result["state"] = -1 | |
| 142 | - result["message"] = e.__str__() | |
| 143 | - return result | |
| 144 | - | |
| 145 | - | |
| 146 | - | |
| 147 | - def determin_intersect(self, extent1, extent2): | |
| 148 | - if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ | |
| 149 | - 3] or extent2[3] < extent1[1]: | |
| 150 | - return False | |
| 151 | - else: | |
| 152 | - return True | |
| 153 | - | |
| 154 | - def get_capabilities(self,image_service:ImageService): | |
| 27 | + raise e | |
| 28 | + return response | |
| 155 | 29 | |
| 156 | - xml = '''<?xml version="1.0" encoding="utf-8" ?> | |
| 157 | - <WMS_Capabilities version="1.2.0"> | |
| 158 | - <Service> | |
| 159 | - <Name>WMS</Name> | |
| 160 | - <Title>{service_title}</Title> | |
| 161 | - <Abstract>{abstract}</Abstract> | |
| 162 | - <Keywords>GIMS</Keywords> | |
| 163 | - <OnlineResource/> | |
| 164 | - <Fees>none</Fees> | |
| 165 | - <AccessConstraints>none</AccessConstraints> | |
| 166 | - </Service> | |
| 167 | - <Capability> | |
| 168 | - <Request> | |
| 169 | - <GetCapabilities> | |
| 170 | - <Format>text/xml</Format> | |
| 171 | - <DCPType> | |
| 172 | - <HTTP> | |
| 173 | - <Get> | |
| 174 | - <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/> | |
| 175 | - </Get> | |
| 176 | - </HTTP> | |
| 177 | - </DCPType> | |
| 178 | - </GetCapabilities> | |
| 179 | - <GetMap> | |
| 180 | - <Format>png</Format> | |
| 181 | - <Format>jpeg</Format> | |
| 182 | - <Format>gif</Format> | |
| 183 | - <Format>image/png</Format> | |
| 184 | - <Format>image/jpeg</Format> | |
| 185 | - <Format>image/gif</Format> | |
| 186 | - <DCPType> | |
| 187 | - <HTTP> | |
| 188 | - <Get> | |
| 189 | - <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/> | |
| 190 | - </Get> | |
| 191 | - </HTTP> | |
| 192 | - </DCPType> | |
| 193 | - </GetMap> | |
| 194 | - <Map> | |
| 195 | - <Format> | |
| 196 | - <PNG/> | |
| 197 | - <GIF/> | |
| 198 | - <JPG/> | |
| 199 | - </Format> | |
| 200 | - <DCPType> | |
| 201 | - <HTTP> | |
| 202 | - <Get onlineResource="{url}"/> | |
| 203 | - </HTTP> | |
| 204 | - </DCPType> | |
| 205 | - </Map> | |
| 206 | - <Capabilities> | |
| 207 | - <Format> | |
| 208 | - <WMS_XML/> | |
| 209 | - </Format> | |
| 210 | - <DCPType> | |
| 211 | - <HTTP> | |
| 212 | - <Get onlineResource="{url}"/> | |
| 213 | - </HTTP> | |
| 214 | - </DCPType> | |
| 215 | - </Capabilities> | |
| 216 | - <FeatureInfo> | |
| 217 | - <Format> | |
| 218 | - <XML/> | |
| 219 | - <MIME/> | |
| 220 | - </Format> | |
| 221 | - <DCPType> | |
| 222 | - <HTTP> | |
| 223 | - <Get onlineResource="{url}"/> | |
| 224 | - </HTTP> | |
| 225 | - </DCPType> | |
| 226 | - </FeatureInfo> | |
| 227 | - </Request> | |
| 228 | - <Exception> | |
| 229 | - <Format> | |
| 230 | - <WMS_XML/> | |
| 231 | - <INIMAGE/> | |
| 232 | - <BLANK/> | |
| 233 | - </Format> | |
| 234 | - </Exception> | |
| 235 | - <Layer> | |
| 236 | - <Name>{service_name}</Name> | |
| 237 | - <Title>{service_title}</Title> | |
| 238 | - <CRS>{crs}</CRS> | |
| 239 | - <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/> | |
| 240 | - | |
| 241 | - <Layer queryable="1"> | |
| 242 | - <CRS>{crs}</CRS> | |
| 243 | - <Name>{layer_name}</Name> | |
| 244 | - <Title>{layer_title}</Title> | |
| 245 | - <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/> | |
| 246 | - </Layer> | |
| 247 | - </Layer> | |
| 248 | - </Capability> | |
| 249 | - </WMS_Capabilities>''' | |
| 250 | 30 | |
| 251 | - extent = json.loads(image_service.extent) | |
| 252 | - xml = xml.format(service_title=image_service.name, | |
| 253 | - service_name=image_service.name, | |
| 254 | - abstract= "None" , | |
| 255 | - crs="ESPG:4326", | |
| 256 | - layer_name=image_service.name, | |
| 257 | - layer_title=image_service.name, | |
| 258 | - maxx=extent[2], | |
| 259 | - maxy = extent[3], | |
| 260 | - minx = extent[0], | |
| 261 | - miny = extent[1], | |
| 262 | - url="http://{}/API/Service/Image/WMS?guid={}".format(configure.deploy_ip_host,image_service.guid)) | |
| 263 | - | |
| 264 | - | |
| 265 | - r = Response(response=xml, status=200, mimetype="application/xml") | |
| 266 | - r.headers["Content-Type"] = "text/xml; charset=utf-8" | |
| 267 | - return r | |
| 268 | 31 | |
| 269 | 32 | api_doc = { |
| 270 | 33 | "tags": ["影像接口"], |
| 271 | 34 | "parameters": [ |
| 272 | - {"name": "guid", | |
| 273 | - "in": "query", | |
| 274 | - "type": "string"}, | |
| 275 | 35 | {"name": "request", |
| 276 | 36 | "in": "query", |
| 277 | 37 | "type": "string", | ... | ... |
| ... | ... | @@ -3,269 +3,24 @@ |
| 3 | 3 | #createtime: 2021/3/24 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from app.util import * | |
| 7 | -import traceback | |
| 8 | -import numpy | |
| 9 | -from flask import Response | |
| 10 | -import random | |
| 11 | -from app.modules.service.image.models import ImageService | |
| 12 | 6 | from app.util.component.ApiTemplate import ApiTemplate |
| 13 | -from app.util.component.ParameterUtil import ParameterUtil | |
| 14 | -import json | |
| 15 | 7 | from threading import Thread |
| 16 | -from .util.ImageData import ImageData | |
| 17 | -from .util.Cache import Cache | |
| 18 | -from .util.Opencv import Opencv | |
| 19 | 8 | |
| 9 | +from .util.ImageWMSServer import ImageWMSServer | |
| 20 | 10 | class Api(ApiTemplate): |
| 21 | 11 | |
| 22 | 12 | api_name = "WMS" |
| 23 | 13 | |
| 24 | 14 | def process(self): |
| 25 | - | |
| 26 | - | |
| 27 | - result = {} | |
| 28 | - parameter: dict = self.para | |
| 29 | - | |
| 30 | 15 | try: |
| 31 | - | |
| 32 | - parameter = ParameterUtil.to_lower(parameter) | |
| 33 | - if parameter.get("guid"): | |
| 34 | - self.guid = parameter.get("guid") | |
| 35 | - | |
| 36 | - #获取缓存信息 | |
| 37 | - if parameter.get("guid"): | |
| 38 | - | |
| 39 | - image_service_info, zoo, servers = Cache.cache_data(self.guid, type="guid") | |
| 40 | - else: | |
| 41 | - image_service_info, zoo, servers = Cache.cache_data(parameter.get("service_name"), type="name") | |
| 42 | - | |
| 43 | - re = parameter.get("request") | |
| 44 | - if re and re.__eq__("GetCapabilities"): | |
| 45 | - return self.get_capabilities(image_service_info["service"]) | |
| 46 | - | |
| 47 | - bbox = parameter.get("bbox") | |
| 48 | - width = int(parameter.get("width")) if parameter.get("width") else 256 | |
| 49 | - height = int(parameter.get("height")) if parameter.get("height") else 256 | |
| 50 | - image_type = parameter.get("format") if parameter.get("format") else "image/png" | |
| 51 | - quality = int(parameter.get("quality")) if parameter.get("quality") else 30 | |
| 52 | - | |
| 53 | - | |
| 54 | - | |
| 55 | - extent = [float(x) for x in bbox.split(",")] | |
| 56 | - | |
| 57 | - intersect_image = [im for im in image_service_info["images"] if self.determin_intersect(json.loads(im.extent),extent)] | |
| 58 | - | |
| 59 | - if len(intersect_image)>1: | |
| 60 | - | |
| 61 | - # 结果矩阵 | |
| 62 | - empty_list = [numpy.zeros((height,width), dtype=int) + 65536, | |
| 63 | - numpy.zeros((height,width), dtype=int) + 65536, | |
| 64 | - numpy.zeros((height,width), dtype=int) + 65536] | |
| 65 | - | |
| 66 | - pixel_array = numpy.zeros((height,width,3), dtype=int) | |
| 67 | - thread_list = [] | |
| 68 | - | |
| 69 | - for image in intersect_image: | |
| 70 | - #该影像的服务器,随机选取一个 | |
| 71 | - image_servers = image.server.split(",") | |
| 72 | - image_servers = [ser for ser in image_servers if ser in servers] | |
| 73 | - if len(image_servers)>0: | |
| 74 | - indx = int(random.random() * len(image_servers)) | |
| 75 | - image_server = image_servers[indx] | |
| 76 | - else: | |
| 77 | - image_server = "None" | |
| 78 | - bands = json.loads(image.band_view) | |
| 79 | - | |
| 80 | - image_data = ImageData(image_server, image) | |
| 81 | - | |
| 82 | - thread: MyThread = MyThread(image_data.get_data, args=(extent,bands,height,width)) | |
| 83 | - thread.start() | |
| 84 | - thread_list.append(thread) | |
| 85 | - | |
| 86 | - | |
| 87 | - for thread in thread_list: | |
| 88 | - thread.join() | |
| 89 | - data = thread.get_result() | |
| 90 | - | |
| 91 | - # 掩膜在中央接口生成,合图 | |
| 92 | - mask = numpy.zeros((height,width), dtype=int) | |
| 93 | - mask2 = numpy.zeros((height,width), dtype=int) | |
| 94 | - jizhun = data[:, :, 0] | |
| 95 | - mask[jizhun == 65536] = 1 | |
| 96 | - mask[jizhun != 65536] = 0 | |
| 97 | - mask2[jizhun == 65536] = 0 | |
| 98 | - mask2[jizhun != 65536] = 1 | |
| 99 | - # 掩膜计算 | |
| 100 | - for i, d in enumerate(empty_list): | |
| 101 | - empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2 | |
| 102 | - | |
| 103 | - for ii in [0, 1, 2]: | |
| 104 | - # opencv 颜色排序为GBR | |
| 105 | - pixel_array[:, :, 2 - ii] = empty_list[ii] | |
| 106 | - | |
| 107 | - | |
| 108 | - elif len(intersect_image)==1: | |
| 109 | - # 该影像的服务器,随机选取一个 | |
| 110 | - image = intersect_image[0] | |
| 111 | - image_servers = image.server.split(",") | |
| 112 | - image_servers = [ser for ser in image_servers if ser in servers] | |
| 113 | - if len(image_servers) > 0: | |
| 114 | - indx = int(random.random() * len(image_servers)) | |
| 115 | - image_server = image_servers[indx] | |
| 116 | - else: | |
| 117 | - image_server = "None" | |
| 118 | - | |
| 119 | - bands = json.loads(image.band_view) | |
| 120 | - | |
| 121 | - image_data = ImageData(image_server, image) | |
| 122 | - | |
| 123 | - pixel_array_t = image_data.get_data(extent,bands,height,width) | |
| 124 | - | |
| 125 | - pixel_array = numpy.zeros((height, width, 3), dtype=int) | |
| 126 | - for ii in [0, 1, 2]: | |
| 127 | - # opencv 颜色排序为GBR | |
| 128 | - pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] | |
| 16 | + instance = ImageWMSServer() | |
| 17 | + if self.para.get("guid"): | |
| 18 | + response = instance.wms(self.para.get("service_name"),self.para) | |
| 129 | 19 | else: |
| 130 | - # 结果矩阵 | |
| 131 | - pixel_array = numpy.zeros((height, width, 3), dtype=int)+65536 | |
| 132 | - | |
| 133 | - # 将图片生成在内存中,然后直接返回response | |
| 134 | - im_data = Opencv.create_image(image_type, pixel_array, quality) | |
| 135 | - | |
| 136 | - if self.para.get("overview"): | |
| 137 | - return pixel_array | |
| 138 | - return Response(im_data, mimetype=image_type.lower()) | |
| 139 | - | |
| 20 | + response = instance.wms(self.para.get("guid"), self.para,type="guid") | |
| 140 | 21 | except Exception as e: |
| 141 | - print(traceback.format_exc()) | |
| 142 | - result["state"] = -1 | |
| 143 | - result["message"] = e.__str__() | |
| 144 | - return result | |
| 145 | - | |
| 146 | - | |
| 147 | - | |
| 148 | - def determin_intersect(self, extent1, extent2): | |
| 149 | - if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ | |
| 150 | - 3] or extent2[3] < extent1[1]: | |
| 151 | - return False | |
| 152 | - else: | |
| 153 | - return True | |
| 154 | - | |
| 155 | - def get_capabilities(self,image_service:ImageService): | |
| 156 | - | |
| 157 | - xml = '''<?xml version="1.0" encoding="utf-8" ?> | |
| 158 | - <WMS_Capabilities version="1.2.0"> | |
| 159 | - <Service> | |
| 160 | - <Name>WMS</Name> | |
| 161 | - <Title>{service_title}</Title> | |
| 162 | - <Abstract>{abstract}</Abstract> | |
| 163 | - <Keywords>GIMS</Keywords> | |
| 164 | - <OnlineResource/> | |
| 165 | - <Fees>none</Fees> | |
| 166 | - <AccessConstraints>none</AccessConstraints> | |
| 167 | - </Service> | |
| 168 | - <Capability> | |
| 169 | - <Request> | |
| 170 | - <GetCapabilities> | |
| 171 | - <Format>text/xml</Format> | |
| 172 | - <DCPType> | |
| 173 | - <HTTP> | |
| 174 | - <Get> | |
| 175 | - <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/> | |
| 176 | - </Get> | |
| 177 | - </HTTP> | |
| 178 | - </DCPType> | |
| 179 | - </GetCapabilities> | |
| 180 | - <GetMap> | |
| 181 | - <Format>png</Format> | |
| 182 | - <Format>jpeg</Format> | |
| 183 | - <Format>gif</Format> | |
| 184 | - <Format>image/png</Format> | |
| 185 | - <Format>image/jpeg</Format> | |
| 186 | - <Format>image/gif</Format> | |
| 187 | - <DCPType> | |
| 188 | - <HTTP> | |
| 189 | - <Get> | |
| 190 | - <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/> | |
| 191 | - </Get> | |
| 192 | - </HTTP> | |
| 193 | - </DCPType> | |
| 194 | - </GetMap> | |
| 195 | - <Map> | |
| 196 | - <Format> | |
| 197 | - <PNG/> | |
| 198 | - <GIF/> | |
| 199 | - <JPG/> | |
| 200 | - </Format> | |
| 201 | - <DCPType> | |
| 202 | - <HTTP> | |
| 203 | - <Get onlineResource="{url}"/> | |
| 204 | - </HTTP> | |
| 205 | - </DCPType> | |
| 206 | - </Map> | |
| 207 | - <Capabilities> | |
| 208 | - <Format> | |
| 209 | - <WMS_XML/> | |
| 210 | - </Format> | |
| 211 | - <DCPType> | |
| 212 | - <HTTP> | |
| 213 | - <Get onlineResource="{url}"/> | |
| 214 | - </HTTP> | |
| 215 | - </DCPType> | |
| 216 | - </Capabilities> | |
| 217 | - <FeatureInfo> | |
| 218 | - <Format> | |
| 219 | - <XML/> | |
| 220 | - <MIME/> | |
| 221 | - </Format> | |
| 222 | - <DCPType> | |
| 223 | - <HTTP> | |
| 224 | - <Get onlineResource="{url}"/> | |
| 225 | - </HTTP> | |
| 226 | - </DCPType> | |
| 227 | - </FeatureInfo> | |
| 228 | - </Request> | |
| 229 | - <Exception> | |
| 230 | - <Format> | |
| 231 | - <WMS_XML/> | |
| 232 | - <INIMAGE/> | |
| 233 | - <BLANK/> | |
| 234 | - </Format> | |
| 235 | - </Exception> | |
| 236 | - <Layer> | |
| 237 | - <Name>{service_name}</Name> | |
| 238 | - <Title>{service_title}</Title> | |
| 239 | - <CRS>{crs}</CRS> | |
| 240 | - <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/> | |
| 241 | - | |
| 242 | - <Layer queryable="1"> | |
| 243 | - <CRS>{crs}</CRS> | |
| 244 | - <Name>{layer_name}</Name> | |
| 245 | - <Title>{layer_title}</Title> | |
| 246 | - <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/> | |
| 247 | - </Layer> | |
| 248 | - </Layer> | |
| 249 | - </Capability> | |
| 250 | - </WMS_Capabilities>''' | |
| 251 | - | |
| 252 | - extent = json.loads(image_service.extent) | |
| 253 | - xml = xml.format(service_title=image_service.name, | |
| 254 | - service_name=image_service.name, | |
| 255 | - abstract= "None" , | |
| 256 | - crs="ESPG:4326", | |
| 257 | - layer_name=image_service.name, | |
| 258 | - layer_title=image_service.name, | |
| 259 | - maxx=extent[2], | |
| 260 | - maxy = extent[3], | |
| 261 | - minx = extent[0], | |
| 262 | - miny = extent[1], | |
| 263 | - url="http://{}/API/Service/Image/WMS?guid={}".format(configure.deploy_ip_host,image_service.guid)) | |
| 264 | - | |
| 265 | - | |
| 266 | - r = Response(response=xml, status=200, mimetype="application/xml") | |
| 267 | - r.headers["Content-Type"] = "text/xml; charset=utf-8" | |
| 268 | - return r | |
| 22 | + raise e | |
| 23 | + return response | |
| 269 | 24 | |
| 270 | 25 | api_doc = { |
| 271 | 26 | "tags": ["影像接口"], |
| ... | ... | @@ -273,6 +28,9 @@ class Api(ApiTemplate): |
| 273 | 28 | {"name": "guid", |
| 274 | 29 | "in": "query", |
| 275 | 30 | "type": "string"}, |
| 31 | + {"name": "service_name", | |
| 32 | + "in": "query", | |
| 33 | + "type": "string"}, | |
| 276 | 34 | {"name": "bbox", |
| 277 | 35 | "in": "query", |
| 278 | 36 | "type": "string"}, | ... | ... |
| ... | ... | @@ -9,7 +9,7 @@ import numpy |
| 9 | 9 | from flask import Response |
| 10 | 10 | import random |
| 11 | 11 | |
| 12 | -from app.modules.service.image.models import Image | |
| 12 | +from app.modules.service.models import Image | |
| 13 | 13 | from app.util.component.ApiTemplate import ApiTemplate |
| 14 | 14 | |
| 15 | 15 | from app.util.component.ParameterUtil import ParameterUtil |
| ... | ... | @@ -152,7 +152,7 @@ class Api(ApiTemplate): |
| 152 | 152 | |
| 153 | 153 | except Exception as e: |
| 154 | 154 | print(traceback.format_exc()) |
| 155 | - result["state"] = -1 | |
| 155 | + result["result"] = False | |
| 156 | 156 | result["message"] = e.__str__() |
| 157 | 157 | return result |
| 158 | 158 | ... | ... |
| ... | ... | @@ -3,331 +3,29 @@ |
| 3 | 3 | #createtime: 2021/3/24 |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | |
| 6 | -from app.util import * | |
| 7 | 6 | import traceback |
| 8 | -import numpy | |
| 9 | -from flask import Response | |
| 10 | -from .util.ImageData import ImageData | |
| 11 | - | |
| 12 | -from app.modules.service.image.models import ImageService | |
| 13 | -from app.models import TileScheme,Service | |
| 14 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 15 | -from app.util.component.SliceScheme import SliceScheme | |
| 16 | -from app.util.component.ParameterUtil import ParameterUtil | |
| 17 | -import json | |
| 18 | -import random | |
| 19 | -import copy | |
| 20 | -from .util.Opencv import Opencv | |
| 21 | -from .util.Cache import Cache | |
| 22 | -from .util.MyThread import MyThread | |
| 23 | 8 | |
| 9 | +from .util.ImageWMTSServer import ImageWMTSServer | |
| 24 | 10 | class Api(ApiTemplate): |
| 25 | - | |
| 26 | 11 | api_name = "切片" |
| 27 | - | |
| 28 | 12 | def __init__(self,service_name): |
| 29 | 13 | super().__init__() |
| 30 | 14 | self.service_name = service_name |
| 31 | 15 | |
| 32 | 16 | def process(self): |
| 33 | - | |
| 34 | - result = {} | |
| 35 | - parameter: dict = self.para | |
| 36 | - | |
| 37 | 17 | try: |
| 38 | - if parameter.get("service_name"): | |
| 39 | - self.service_name = parameter.get("service_name") | |
| 40 | - | |
| 41 | - #获取缓存数据 | |
| 42 | - image_service_info, zoo, servers = Cache.cache_data(self.service_name,type="name") | |
| 43 | - | |
| 44 | - # 转换参数 | |
| 45 | - parameter = ParameterUtil.to_lower(parameter) | |
| 46 | - | |
| 47 | - re = parameter.get("request") | |
| 48 | - if re and re.__eq__("GetCapabilities"): | |
| 49 | - service = Service.query.filter_by(guid=image_service_info["service"].service_guid).one_or_none() | |
| 50 | - return self.get_capabilities(image_service_info["service"],service) | |
| 51 | - | |
| 52 | - if parameter.get("tilematrix"): | |
| 53 | - if parameter.get("tilematrix").__contains__(":"): | |
| 54 | - self.level = int(parameter.get("tilematrix").split(":")[-1]) | |
| 55 | - else: | |
| 56 | - self.level = int(parameter.get("tilematrix")) | |
| 57 | - if parameter.get("tilerow"): | |
| 58 | - self.row = int(parameter.get("tilerow")) | |
| 59 | - if parameter.get("tilecol"): | |
| 60 | - self.col = int(parameter.get("tilecol")) | |
| 61 | - | |
| 62 | - image_type = parameter.get("format") if parameter.get("format") else "image/png" | |
| 63 | - quality = int(parameter.get("quality")) if parameter.get("quality") else 30 | |
| 64 | - slice_para = image_service_info["scheme"] | |
| 65 | - extent = SliceScheme.get_polygon(slice_para, self.level, self.row, self.col) | |
| 66 | - | |
| 67 | - height, width = 256,256 | |
| 68 | - | |
| 69 | - # 多线程获取分布式数据 | |
| 70 | - | |
| 71 | - intersect_image = [im for im in image_service_info["images"] if self.determin_intersect(json.loads(im.extent),extent)] | |
| 72 | - | |
| 73 | - if len(intersect_image) > 1: | |
| 74 | - | |
| 75 | - # 结果矩阵 | |
| 76 | - pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 | |
| 77 | - | |
| 78 | - thread_list = [] | |
| 79 | - | |
| 80 | - for image in intersect_image: | |
| 81 | - | |
| 82 | - # 该影像的服务器,随机选取一个 | |
| 83 | - image_servers = image.server.split(",") | |
| 84 | - image_servers = [ser for ser in image_servers if ser in servers] | |
| 85 | - if len(image_servers)>0: | |
| 86 | - indx = int(random.random() * len(image_servers)) | |
| 87 | - image_server = image_servers[indx] | |
| 88 | - else: | |
| 89 | - image_server = "None" | |
| 90 | - | |
| 91 | - bands = json.loads(image.band_view) | |
| 92 | - | |
| 93 | - image_data = ImageData(image_server,image) | |
| 94 | - | |
| 95 | - thread: MyThread = MyThread(image_data.get_data,args=(extent, bands, height, width)) | |
| 96 | - | |
| 97 | - thread.start() | |
| 98 | - thread_list.append(thread) | |
| 99 | - | |
| 100 | - for thread in thread_list: | |
| 101 | - thread.join() | |
| 102 | - data = thread.get_result() | |
| 103 | - | |
| 104 | - # 掩膜在中央接口生成,合图 | |
| 105 | - mask = numpy.zeros((height, width, 3), dtype=int) | |
| 106 | - mask_data = numpy.zeros((height, width, 3), dtype=int) | |
| 107 | - | |
| 108 | - mask[data == 65536] = 1 | |
| 109 | - mask[data != 65536] = 0 | |
| 110 | - mask_data[data == 65536] = 0 | |
| 111 | - mask_data[data != 65536] = 1 | |
| 112 | - | |
| 113 | - # # 掩膜计算 | |
| 114 | - pixel_array = pixel_array * mask + data * mask_data | |
| 115 | - | |
| 116 | - # opencv 颜色排序为GBR | |
| 117 | - d1 = copy.copy(pixel_array[:,:,0]) | |
| 118 | - pixel_array[:, :, 0] = pixel_array[:,:,2] | |
| 119 | - pixel_array[:, :, 2] = d1 | |
| 120 | - | |
| 121 | - | |
| 122 | - elif len(intersect_image) == 1: | |
| 123 | - # 该影像的服务器,随机选取一个 | |
| 124 | - image = intersect_image[0] | |
| 125 | - image_servers = image.server.split(",") | |
| 126 | - #判断可用服务器 | |
| 127 | - image_servers = [ser for ser in image_servers if ser in servers] | |
| 128 | - if len(image_servers) > 0: | |
| 129 | - indx = int(random.random() * len(image_servers)) | |
| 130 | - image_server = image_servers[indx] | |
| 131 | - else: | |
| 132 | - image_server = "None" | |
| 133 | - # image_server = image_servers[0] | |
| 134 | - bands = json.loads(image.band_view) | |
| 135 | - | |
| 136 | - image_data = ImageData(image_server, image) | |
| 137 | - pixel_array_t: numpy.ndarray = image_data.get_data(extent, bands, height, width) | |
| 138 | - pixel_array = numpy.zeros((height, width, 3), dtype=int) | |
| 139 | - | |
| 140 | - for ii in [0, 1, 2]: | |
| 141 | - # opencv 颜色排序为GBR | |
| 142 | - pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] | |
| 143 | - | |
| 144 | - else: | |
| 145 | - # 结果矩阵 | |
| 146 | - pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 | |
| 147 | - | |
| 148 | - | |
| 149 | - | |
| 150 | - | |
| 151 | - # 将图片生成在内存中,然后直接返回response | |
| 152 | - im_data = Opencv.create_image(image_type, pixel_array, quality) | |
| 153 | - return Response(im_data, mimetype=image_type.lower()) | |
| 154 | - | |
| 155 | - | |
| 18 | + instance = ImageWMTSServer() | |
| 19 | + response = instance.wmts(self.service_name,self.para) | |
| 156 | 20 | except Exception as e: |
| 157 | 21 | print(traceback.format_exc()) |
| 158 | - result["state"] = -1 | |
| 159 | - result["message"] = e.__str__() | |
| 160 | - return result | |
| 161 | - | |
| 162 | - def get_capabilities(self, image_service: ImageService, service: Service): | |
| 163 | - tile_scheme: TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none() | |
| 164 | - if not tile_scheme: | |
| 165 | - raise Exception("切片方案不存在!") | |
| 166 | - | |
| 167 | - 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"> | |
| 168 | - <!-- Service Identification --> | |
| 169 | - <ows:ServiceIdentification> | |
| 170 | - <ows:Title>{title}</ows:Title> | |
| 171 | - <ows:ServiceType>OGC WMTS</ows:ServiceType> | |
| 172 | - <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion> | |
| 173 | - </ows:ServiceIdentification> | |
| 174 | - | |
| 175 | - <!-- Operations Metadata --> | |
| 176 | - <ows:OperationsMetadata> | |
| 177 | - <ows:Operation name="GetCapabilities"> | |
| 178 | - <ows:DCP> | |
| 179 | - <ows:HTTP> | |
| 180 | - <ows:Get xlink:href="{capabilities_url}"> | |
| 181 | - <ows:Constraint name="GetEncoding"> | |
| 182 | - <ows:AllowedValues> | |
| 183 | - <ows:Value>RESTful</ows:Value> | |
| 184 | - </ows:AllowedValues> | |
| 185 | - </ows:Constraint> | |
| 186 | - </ows:Get> | |
| 187 | - | |
| 188 | - <!-- add KVP binding in 10.1 --> | |
| 189 | - <ows:Get xlink:href="{tile_url}?"> | |
| 190 | - <ows:Constraint name="GetEncoding"> | |
| 191 | - <ows:AllowedValues> | |
| 192 | - <ows:Value>KVP</ows:Value> | |
| 193 | - </ows:AllowedValues> | |
| 194 | - </ows:Constraint> | |
| 195 | - </ows:Get> | |
| 196 | - </ows:HTTP> | |
| 197 | - </ows:DCP> | |
| 198 | - </ows:Operation> | |
| 199 | - <ows:Operation name="GetTile"> | |
| 200 | - <ows:DCP> | |
| 201 | - <ows:HTTP> | |
| 202 | - <ows:Get xlink:href="{tile_url}"> | |
| 203 | - <ows:Constraint name="GetEncoding"> | |
| 204 | - <ows:AllowedValues> | |
| 205 | - <ows:Value>RESTful</ows:Value> | |
| 206 | - </ows:AllowedValues> | |
| 207 | - </ows:Constraint> | |
| 208 | - </ows:Get> | |
| 209 | - <ows:Get xlink:href="{tile_url}?"> | |
| 210 | - <ows:Constraint name="GetEncoding"> | |
| 211 | - <ows:AllowedValues> | |
| 212 | - <ows:Value>KVP</ows:Value> | |
| 213 | - </ows:AllowedValues> | |
| 214 | - </ows:Constraint> | |
| 215 | - </ows:Get> | |
| 216 | - </ows:HTTP> | |
| 217 | - </ows:DCP> | |
| 218 | - </ows:Operation> | |
| 219 | - </ows:OperationsMetadata> | |
| 220 | - | |
| 221 | - <Contents> | |
| 222 | - | |
| 223 | - <!-- Layer --> | |
| 224 | - | |
| 225 | - | |
| 226 | - <Layer> | |
| 227 | - <ows:Title>{title}</ows:Title> | |
| 228 | - <ows:Identifier>{title}</ows:Identifier> | |
| 229 | - <ows:BoundingBox crs="{crs}"> | |
| 230 | - <ows:LowerCorner>{xmin} {ymin}</ows:LowerCorner> | |
| 231 | - <ows:UpperCorner>{xmax} {ymax}</ows:UpperCorner> | |
| 232 | - </ows:BoundingBox> | |
| 233 | - | |
| 234 | - <Style isDefault="true"> | |
| 235 | - <ows:Title>Default Style</ows:Title> | |
| 236 | - <ows:Identifier>default</ows:Identifier> | |
| 237 | - </Style> | |
| 238 | - <Format>image/png</Format> | |
| 239 | - <TileMatrixSetLink> | |
| 240 | - <TileMatrixSet>{tile_name}</TileMatrixSet> | |
| 241 | - </TileMatrixSetLink> | |
| 242 | - | |
| 243 | - <ResourceURL format="image/png" resourceType="tile" template="{tile_url}"/> | |
| 244 | - | |
| 245 | - </Layer> | |
| 246 | - | |
| 247 | - <!-- TileMatrixSet --> | |
| 248 | - | |
| 249 | - | |
| 250 | - <TileMatrixSet> | |
| 251 | - | |
| 252 | - <TileMatrix> | |
| 253 | - <ows:Title>{tile_title}</ows:Title> | |
| 254 | - <ows:Abstract>{tile_description}</ows:Abstract> | |
| 255 | - <ows:Identifier>{tile_name}</ows:Identifier> | |
| 256 | - <ows:SupportedCRS>{crs}</ows:SupportedCRS> | |
| 257 | - | |
| 258 | - {tile_matrix} | |
| 259 | - | |
| 260 | - </TileMatrix> | |
| 261 | - | |
| 262 | - </TileMatrixSet> | |
| 263 | - | |
| 264 | - | |
| 265 | - </Contents> | |
| 266 | - <ServiceMetadataURL xlink:href="{capabilities_url}"/> | |
| 267 | - </Capabilities>''' | |
| 268 | - | |
| 269 | - tile_matrix_each = ''' | |
| 270 | - <TileMatrix> | |
| 271 | - <ows:Identifier>{lev}</ows:Identifier> | |
| 272 | - <ScaleDenominator>{scale}</ScaleDenominator> | |
| 273 | - <TopLeftCorner>{top_left}</TopLeftCorner> | |
| 274 | - <TileWidth>{cols}</TileWidth> | |
| 275 | - <TileHeight>{rows}</TileHeight> | |
| 276 | - </TileMatrix> | |
| 277 | - ''' | |
| 278 | - | |
| 279 | - tile_matrix = "" | |
| 280 | - top_left = tile_scheme.top_left | |
| 281 | - for level in json.loads(tile_scheme.levels): | |
| 282 | - tile_matrix = "{}{}".format(tile_matrix, tile_matrix_each.format(lev=level["level"], | |
| 283 | - scale=level["scale"], | |
| 284 | - top_left=top_left, | |
| 285 | - cols=tile_scheme.cols, | |
| 286 | - rows=tile_scheme.rows)) | |
| 287 | - | |
| 288 | - extent = json.loads(image_service.extent) | |
| 289 | - | |
| 290 | - xml = xml.format( | |
| 291 | - capabilities_url="http://{}/API/Service/Image/Capabilities?guid={}".format(configure.deploy_ip_host, | |
| 292 | - image_service.guid), | |
| 293 | - tile_url="http://{}/API/Service/Image/Tile?guid={}".format(configure.deploy_ip_host, image_service.guid), | |
| 294 | - crs=tile_scheme.crs, | |
| 295 | - xmin=extent[0], | |
| 296 | - ymin=extent[1], | |
| 297 | - xmax=extent[2], | |
| 298 | - ymax=extent[3], | |
| 299 | - # TileMatrix = "{TileMatrix}", | |
| 300 | - # TileRow = "{TileRow}", | |
| 301 | - # TileCol = "{TileCol}", | |
| 302 | - guid=image_service.guid, | |
| 303 | - title=service.title, | |
| 304 | - tile_title=tile_scheme.name, | |
| 305 | - tile_name=tile_scheme.name, | |
| 306 | - tile_description=tile_scheme.description, | |
| 307 | - tile_matrix=tile_matrix | |
| 308 | - ) | |
| 309 | - | |
| 310 | - r = Response(response=xml, status=200, mimetype="application/xml") | |
| 311 | - r.headers["Content-Type"] = "text/xml; charset=utf-8" | |
| 312 | - | |
| 313 | - return r | |
| 314 | - | |
| 315 | - | |
| 316 | - | |
| 317 | - def determin_intersect(self, extent1, extent2): | |
| 318 | - if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ | |
| 319 | - 3] or extent2[3] < extent1[1]: | |
| 320 | - return False | |
| 321 | - else: | |
| 322 | - return True | |
| 22 | + raise e | |
| 23 | + return response | |
| 323 | 24 | |
| 324 | 25 | |
| 325 | 26 | api_doc = { |
| 326 | 27 | "tags": ["影像接口"], |
| 327 | 28 | "parameters": [ |
| 328 | - {"name": "guid", | |
| 329 | - "in": "formData", | |
| 330 | - "type": "string"}, | |
| 331 | 29 | {"name": "request", |
| 332 | 30 | "in": "formData", |
| 333 | 31 | "type": "string", | ... | ... |
| 1 | -# coding=utf-8 | |
| 2 | -#author: 4N | |
| 3 | -#createtime: 2021/6/11 | |
| 4 | -#email: nheweijun@sina.com | |
| 5 | - | |
| 6 | - | |
| 7 | -from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time,Binary,Float | |
| 8 | -from app.models import db | |
| 9 | - | |
| 10 | - | |
| 11 | - | |
| 12 | -class Image(db.Model): | |
| 13 | - ''' | |
| 14 | - 影像元数据 | |
| 15 | - ''' | |
| 16 | - __tablename__ = 'dmap_image' | |
| 17 | - guid = Column(String(256), primary_key=True) | |
| 18 | - name = Column(String) | |
| 19 | - alias = Column(String) | |
| 20 | - raster_y_size = Column(Integer)#图像y 分辨率 | |
| 21 | - raster_x_size = Column(Integer)#图像x 分辨率 | |
| 22 | - overview_count = Column(Integer)#金字塔等级 | |
| 23 | - extent = Column(String)#范围 | |
| 24 | - # geo_origin_extent = Column(String) | |
| 25 | - null_value = Column(Integer)#空值 | |
| 26 | - available = Column(Integer)#影像是否可用,不可用可能在创建金字塔中 | |
| 27 | - band_count = Column(Integer)#波段数 | |
| 28 | - band_view = Column(String)#波段设置 | |
| 29 | - path = Column(String) | |
| 30 | - server = Column(String) | |
| 31 | - | |
| 32 | - size = Column(Float) | |
| 33 | - #坐标wkt | |
| 34 | - crs_wkt = Column(Text) #坐标wkt | |
| 35 | - crs_proj4 = Column(Text)#坐标proj | |
| 36 | - crs = Column(String)#坐标 | |
| 37 | - create_time = Column(DateTime) | |
| 38 | - update_time = Column(DateTime) | |
| 39 | - cell_x_size = Column(Float)#像元x大小 | |
| 40 | - cell_y_size = Column(Float)#像元y大小 | |
| 41 | - region = Column(Text) | |
| 42 | - | |
| 43 | - collect_time = Column(DateTime) #成像时间年份 | |
| 44 | - | |
| 45 | - satellite = Column(String)#卫星类型 | |
| 46 | - type = Column(String(128)) | |
| 47 | - | |
| 48 | - | |
| 49 | -dmap_image_rel = db.Table('dmap_image_rel', | |
| 50 | - Column('image_guid',String, ForeignKey('dmap_image.guid')), | |
| 51 | - Column('service_guid', String, ForeignKey('dmap_image_service.guid')) | |
| 52 | - ) | |
| 53 | - | |
| 54 | - | |
| 55 | - | |
| 56 | -class ImageService(db.Model): | |
| 57 | - ''' | |
| 58 | - 影像服务 | |
| 59 | - ''' | |
| 60 | - __tablename__ = 'dmap_image_service' | |
| 61 | - guid = Column(String(256), primary_key=True) | |
| 62 | - name = Column(String) | |
| 63 | - scheme_guid = Column(String) | |
| 64 | - extent = Column(String(256)) | |
| 65 | - # node = Column(Integer) | |
| 66 | - #可视范围geojson | |
| 67 | - visual_region = Column(Text) | |
| 68 | - crs = Column(String(256)) | |
| 69 | - create_time = Column(DateTime) | |
| 70 | - # service_guid = Column(String, ForeignKey('dmap_service.guid')) | |
| 71 | - | |
| 72 | - service_guid = Column(String) | |
| 73 | - | |
| 74 | - images = db.relationship('Image', | |
| 75 | - secondary=dmap_image_rel, | |
| 76 | - backref='image_services', | |
| 77 | - lazy='dynamic' | |
| 78 | - ) | |
| 79 | - | |
| 80 | - | |
| 81 | -dmap_image_tag_rel = db.Table('dmap_image_tag_rel', | |
| 82 | - Column('image_guid',String, ForeignKey('dmap_image.guid')), | |
| 83 | - Column('tag_guid', String, ForeignKey('dmap_image_tag.guid')) | |
| 84 | - ) | |
| 85 | - | |
| 86 | -class ImageTag(db.Model): | |
| 87 | - ''' | |
| 88 | - 影像标签 | |
| 89 | - ''' | |
| 90 | - __tablename__ = 'dmap_image_tag' | |
| 91 | - guid = Column(String(256), primary_key=True) | |
| 92 | - name=Column(String(256)) | |
| 93 | - alias = Column(String(256)) | |
| 94 | - images = db.relationship('Image', | |
| 95 | - secondary=dmap_image_tag_rel, | |
| 96 | - backref='image_tags', | |
| 97 | - lazy='dynamic' | |
| 98 | - ) |
| ... | ... | @@ -7,8 +7,8 @@ |
| 7 | 7 | from kazoo.client import KazooClient |
| 8 | 8 | import configure |
| 9 | 9 | import time |
| 10 | -from app.modules.service.image.models import ImageService | |
| 11 | -from app.models import TileScheme,Service | |
| 10 | +from app.modules.service.models import ImageService | |
| 11 | +from app.modules.service.models import TileScheme,Service | |
| 12 | 12 | import json |
| 13 | 13 | |
| 14 | 14 | class Cache: | ... | ... |
| 1 | +# coding=utf-8 | |
| 2 | +#author: 4N | |
| 3 | +#createtime: 2021/10/26 | |
| 4 | +#email: nheweijun@sina.com | |
| 5 | + | |
| 6 | + | |
| 7 | +import numpy | |
| 8 | +from app.util.component.ParameterUtil import ParameterUtil | |
| 9 | +from .Cache import Cache | |
| 10 | +from app.modules.service.models import ImageService | |
| 11 | +from flask import Response | |
| 12 | +from .ImageData import ImageData | |
| 13 | +from .MyThread import MyThread | |
| 14 | +from .Opencv import Opencv | |
| 15 | +import json | |
| 16 | +import random | |
| 17 | +import configure | |
| 18 | +import threading | |
| 19 | +from .ImageServer import ImageServer | |
| 20 | + | |
| 21 | + | |
| 22 | +class ImageWMSServer(ImageServer): | |
| 23 | + | |
| 24 | + _instance_lock = threading.Lock() | |
| 25 | + singleton = None | |
| 26 | + | |
| 27 | + def __init__(self): | |
| 28 | + pass | |
| 29 | + | |
| 30 | + def __new__(cls, *args, **kwargs): | |
| 31 | + if not cls.singleton: | |
| 32 | + with ImageWMSServer._instance_lock: | |
| 33 | + cls.singleton = super().__new__(cls) | |
| 34 | + return cls.singleton | |
| 35 | + | |
| 36 | + def wms(self,service_name,parameter,type="name"): | |
| 37 | + | |
| 38 | + # 获取缓存信息 | |
| 39 | + image_service_info, zoo, servers = Cache.cache_data(service_name, type=type) | |
| 40 | + # 转换参数 | |
| 41 | + parameter = ParameterUtil.to_lower(parameter) | |
| 42 | + re = parameter.get("request") | |
| 43 | + if re and re.__eq__("GetCapabilities"): | |
| 44 | + return self.get_wms_capabilities(image_service_info["service"]) | |
| 45 | + | |
| 46 | + bbox = parameter.get("bbox") | |
| 47 | + width = int(parameter.get("width")) if parameter.get("width") else 256 | |
| 48 | + height = int(parameter.get("height")) if parameter.get("height") else 256 | |
| 49 | + image_type = parameter.get("format") if parameter.get("format") else "image/png" | |
| 50 | + quality = int(parameter.get("quality")) if parameter.get("quality") else 30 | |
| 51 | + | |
| 52 | + extent = [float(x) for x in bbox.split(",")] | |
| 53 | + | |
| 54 | + intersect_image = [im for im in image_service_info["images"] if | |
| 55 | + self.determin_intersect(json.loads(im.extent), extent)] | |
| 56 | + | |
| 57 | + if len(intersect_image) > 1: | |
| 58 | + | |
| 59 | + # 结果矩阵 | |
| 60 | + empty_list = [numpy.zeros((height, width), dtype=int) + 65536, | |
| 61 | + numpy.zeros((height, width), dtype=int) + 65536, | |
| 62 | + numpy.zeros((height, width), dtype=int) + 65536] | |
| 63 | + | |
| 64 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) | |
| 65 | + thread_list = [] | |
| 66 | + | |
| 67 | + for image in intersect_image: | |
| 68 | + # 该影像的服务器,随机选取一个 | |
| 69 | + image_servers = image.server.split(",") | |
| 70 | + image_servers = [ser for ser in image_servers if ser in servers] | |
| 71 | + if len(image_servers) > 0: | |
| 72 | + indx = int(random.random() * len(image_servers)) | |
| 73 | + image_server = image_servers[indx] | |
| 74 | + else: | |
| 75 | + image_server = "None" | |
| 76 | + bands = json.loads(image.band_view) | |
| 77 | + | |
| 78 | + image_data = ImageData(image_server, image) | |
| 79 | + | |
| 80 | + thread: MyThread = MyThread(image_data.get_data, args=(extent, bands, height, width)) | |
| 81 | + thread.start() | |
| 82 | + thread_list.append(thread) | |
| 83 | + | |
| 84 | + for thread in thread_list: | |
| 85 | + thread.join() | |
| 86 | + data = thread.get_result() | |
| 87 | + | |
| 88 | + # 掩膜在中央接口生成,合图 | |
| 89 | + mask = numpy.zeros((height, width), dtype=int) | |
| 90 | + mask2 = numpy.zeros((height, width), dtype=int) | |
| 91 | + jizhun = data[:, :, 0] | |
| 92 | + mask[jizhun == 65536] = 1 | |
| 93 | + mask[jizhun != 65536] = 0 | |
| 94 | + mask2[jizhun == 65536] = 0 | |
| 95 | + mask2[jizhun != 65536] = 1 | |
| 96 | + # 掩膜计算 | |
| 97 | + for i, d in enumerate(empty_list): | |
| 98 | + empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2 | |
| 99 | + | |
| 100 | + for ii in [0, 1, 2]: | |
| 101 | + # opencv 颜色排序为GBR | |
| 102 | + pixel_array[:, :, 2 - ii] = empty_list[ii] | |
| 103 | + | |
| 104 | + | |
| 105 | + elif len(intersect_image) == 1: | |
| 106 | + # 该影像的服务器,随机选取一个 | |
| 107 | + image = intersect_image[0] | |
| 108 | + image_servers = image.server.split(",") | |
| 109 | + image_servers = [ser for ser in image_servers if ser in servers] | |
| 110 | + if len(image_servers) > 0: | |
| 111 | + indx = int(random.random() * len(image_servers)) | |
| 112 | + image_server = image_servers[indx] | |
| 113 | + else: | |
| 114 | + image_server = "None" | |
| 115 | + | |
| 116 | + bands = json.loads(image.band_view) | |
| 117 | + | |
| 118 | + image_data = ImageData(image_server, image) | |
| 119 | + | |
| 120 | + pixel_array_t = image_data.get_data(extent, bands, height, width) | |
| 121 | + | |
| 122 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) | |
| 123 | + for ii in [0, 1, 2]: | |
| 124 | + # opencv 颜色排序为GBR | |
| 125 | + pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] | |
| 126 | + else: | |
| 127 | + # 结果矩阵 | |
| 128 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 | |
| 129 | + | |
| 130 | + # 将图片生成在内存中,然后直接返回response | |
| 131 | + im_data = Opencv.create_image(image_type, pixel_array, quality) | |
| 132 | + | |
| 133 | + if parameter.get("overview"): | |
| 134 | + return pixel_array | |
| 135 | + return Response(im_data, mimetype=image_type.lower()) | |
| 136 | + | |
| 137 | + | |
| 138 | + def get_wms_capabilities(self, image_service: ImageService): | |
| 139 | + | |
| 140 | + xml = '''<?xml version="1.0" encoding="utf-8" ?> | |
| 141 | + <WMS_Capabilities version="1.2.0"> | |
| 142 | + <Service> | |
| 143 | + <Name>WMS</Name> | |
| 144 | + <Title>{service_title}</Title> | |
| 145 | + <Abstract>{abstract}</Abstract> | |
| 146 | + <Keywords>GIMS</Keywords> | |
| 147 | + <OnlineResource/> | |
| 148 | + <Fees>none</Fees> | |
| 149 | + <AccessConstraints>none</AccessConstraints> | |
| 150 | + </Service> | |
| 151 | + <Capability> | |
| 152 | + <Request> | |
| 153 | + <GetCapabilities> | |
| 154 | + <Format>text/xml</Format> | |
| 155 | + <DCPType> | |
| 156 | + <HTTP> | |
| 157 | + <Get> | |
| 158 | + <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/> | |
| 159 | + </Get> | |
| 160 | + </HTTP> | |
| 161 | + </DCPType> | |
| 162 | + </GetCapabilities> | |
| 163 | + <GetMap> | |
| 164 | + <Format>png</Format> | |
| 165 | + <Format>jpeg</Format> | |
| 166 | + <Format>gif</Format> | |
| 167 | + <Format>image/png</Format> | |
| 168 | + <Format>image/jpeg</Format> | |
| 169 | + <Format>image/gif</Format> | |
| 170 | + <DCPType> | |
| 171 | + <HTTP> | |
| 172 | + <Get> | |
| 173 | + <OnlineResource xlink:href="{url}" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/> | |
| 174 | + </Get> | |
| 175 | + </HTTP> | |
| 176 | + </DCPType> | |
| 177 | + </GetMap> | |
| 178 | + <Map> | |
| 179 | + <Format> | |
| 180 | + <PNG/> | |
| 181 | + <GIF/> | |
| 182 | + <JPG/> | |
| 183 | + </Format> | |
| 184 | + <DCPType> | |
| 185 | + <HTTP> | |
| 186 | + <Get onlineResource="{url}"/> | |
| 187 | + </HTTP> | |
| 188 | + </DCPType> | |
| 189 | + </Map> | |
| 190 | + <Capabilities> | |
| 191 | + <Format> | |
| 192 | + <WMS_XML/> | |
| 193 | + </Format> | |
| 194 | + <DCPType> | |
| 195 | + <HTTP> | |
| 196 | + <Get onlineResource="{url}"/> | |
| 197 | + </HTTP> | |
| 198 | + </DCPType> | |
| 199 | + </Capabilities> | |
| 200 | + <FeatureInfo> | |
| 201 | + <Format> | |
| 202 | + <XML/> | |
| 203 | + <MIME/> | |
| 204 | + </Format> | |
| 205 | + <DCPType> | |
| 206 | + <HTTP> | |
| 207 | + <Get onlineResource="{url}"/> | |
| 208 | + </HTTP> | |
| 209 | + </DCPType> | |
| 210 | + </FeatureInfo> | |
| 211 | + </Request> | |
| 212 | + <Exception> | |
| 213 | + <Format> | |
| 214 | + <WMS_XML/> | |
| 215 | + <INIMAGE/> | |
| 216 | + <BLANK/> | |
| 217 | + </Format> | |
| 218 | + </Exception> | |
| 219 | + <Layer> | |
| 220 | + <Name>{service_name}</Name> | |
| 221 | + <Title>{service_title}</Title> | |
| 222 | + <CRS>{crs}</CRS> | |
| 223 | + <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/> | |
| 224 | + | |
| 225 | + <Layer queryable="1"> | |
| 226 | + <CRS>{crs}</CRS> | |
| 227 | + <Name>{layer_name}</Name> | |
| 228 | + <Title>{layer_title}</Title> | |
| 229 | + <BoundingBox CRS="{crs}" maxx="{maxx}" maxy="{maxy}" minx="{minx}" miny="{miny}"/> | |
| 230 | + </Layer> | |
| 231 | + </Layer> | |
| 232 | + </Capability> | |
| 233 | + </WMS_Capabilities>''' | |
| 234 | + | |
| 235 | + extent = json.loads(image_service.extent) | |
| 236 | + xml = xml.format(service_title=image_service.name, | |
| 237 | + service_name=image_service.name, | |
| 238 | + abstract="None", | |
| 239 | + crs="ESPG:4326", | |
| 240 | + layer_name=image_service.name, | |
| 241 | + layer_title=image_service.name, | |
| 242 | + maxx=extent[2], | |
| 243 | + maxy=extent[3], | |
| 244 | + minx=extent[0], | |
| 245 | + miny=extent[1], | |
| 246 | + url="http://{}/API/Service/Image/WMS?guid={}".format(configure.deploy_ip_host, | |
| 247 | + image_service.guid)) | |
| 248 | + | |
| 249 | + r = Response(response=xml, status=200, mimetype="application/xml") | |
| 250 | + r.headers["Content-Type"] = "text/xml; charset=utf-8" | |
| 251 | + return r | |
| 252 | + | |
| 253 | + def determin_intersect(self, extent1, extent2): | |
| 254 | + if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ | |
| 255 | + 3] or extent2[3] < extent1[1]: | |
| 256 | + return False | |
| 257 | + else: | |
| 258 | + return True | |
| \ No newline at end of file | ... | ... |
| 1 | +# coding=utf-8 | |
| 2 | +#author: 4N | |
| 3 | +#createtime: 2021/10/26 | |
| 4 | +#email: nheweijun@sina.com | |
| 5 | + | |
| 6 | + | |
| 7 | +import numpy | |
| 8 | +from app.util.component.ParameterUtil import ParameterUtil | |
| 9 | +from .Cache import Cache | |
| 10 | +from app.modules.service.models import ImageService | |
| 11 | +from flask import Response | |
| 12 | +from .ImageData import ImageData | |
| 13 | +from .MyThread import MyThread | |
| 14 | +from .Opencv import Opencv | |
| 15 | +from app.modules.service.models import Service,TileScheme | |
| 16 | +import json | |
| 17 | +import random | |
| 18 | +import copy | |
| 19 | +import configure | |
| 20 | +from app.util.component.SliceScheme import SliceScheme | |
| 21 | +import threading | |
| 22 | +from .ImageServer import ImageServer | |
| 23 | + | |
| 24 | +class ImageWMTSServer(ImageServer): | |
| 25 | + _instance_lock = threading.Lock() | |
| 26 | + singleton = None | |
| 27 | + | |
| 28 | + def __init__(self): | |
| 29 | + pass | |
| 30 | + | |
| 31 | + def __new__(cls, *args, **kwargs): | |
| 32 | + if not cls.singleton: | |
| 33 | + with ImageWMTSServer._instance_lock: | |
| 34 | + cls.singleton = super().__new__(cls) | |
| 35 | + return cls.singleton | |
| 36 | + | |
| 37 | + | |
| 38 | + def wmts(self,service_name,parameter,type="name"): | |
| 39 | + | |
| 40 | + image_service_info, zoo, servers = Cache.cache_data(service_name, type=type) | |
| 41 | + | |
| 42 | + # 转换参数 | |
| 43 | + parameter = ParameterUtil.to_lower(parameter) | |
| 44 | + | |
| 45 | + re = parameter.get("request") | |
| 46 | + if re and re.__eq__("GetCapabilities"): | |
| 47 | + service = Service.query.filter_by(guid=image_service_info["service"].service_guid).one_or_none() | |
| 48 | + return self.get_wmts_capabilities(image_service_info["service"], service) | |
| 49 | + | |
| 50 | + if parameter.get("tilematrix"): | |
| 51 | + if parameter.get("tilematrix").__contains__(":"): | |
| 52 | + self.level = int(parameter.get("tilematrix").split(":")[-1]) | |
| 53 | + else: | |
| 54 | + self.level = int(parameter.get("tilematrix")) | |
| 55 | + if parameter.get("tilerow"): | |
| 56 | + self.row = int(parameter.get("tilerow")) | |
| 57 | + if parameter.get("tilecol"): | |
| 58 | + self.col = int(parameter.get("tilecol")) | |
| 59 | + | |
| 60 | + image_type = parameter.get("format") if parameter.get("format") else "image/png" | |
| 61 | + quality = int(parameter.get("quality")) if parameter.get("quality") else 30 | |
| 62 | + slice_para = image_service_info["scheme"] | |
| 63 | + extent = SliceScheme.get_polygon(slice_para, self.level, self.row, self.col) | |
| 64 | + | |
| 65 | + height, width = 256, 256 | |
| 66 | + | |
| 67 | + # 多线程获取分布式数据 | |
| 68 | + | |
| 69 | + intersect_image = [im for im in image_service_info["images"] if | |
| 70 | + self.determin_intersect(json.loads(im.extent), extent)] | |
| 71 | + | |
| 72 | + if len(intersect_image) > 1: | |
| 73 | + | |
| 74 | + # 结果矩阵 | |
| 75 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 | |
| 76 | + | |
| 77 | + thread_list = [] | |
| 78 | + | |
| 79 | + for image in intersect_image: | |
| 80 | + | |
| 81 | + # 该影像的服务器,随机选取一个 | |
| 82 | + image_servers = image.server.split(",") | |
| 83 | + image_servers = [ser for ser in image_servers if ser in servers] | |
| 84 | + if len(image_servers) > 0: | |
| 85 | + indx = int(random.random() * len(image_servers)) | |
| 86 | + image_server = image_servers[indx] | |
| 87 | + else: | |
| 88 | + image_server = "None" | |
| 89 | + | |
| 90 | + bands = json.loads(image.band_view) | |
| 91 | + | |
| 92 | + image_data = ImageData(image_server, image) | |
| 93 | + | |
| 94 | + thread: MyThread = MyThread(image_data.get_data, args=(extent, bands, height, width)) | |
| 95 | + | |
| 96 | + thread.start() | |
| 97 | + thread_list.append(thread) | |
| 98 | + | |
| 99 | + for thread in thread_list: | |
| 100 | + thread.join() | |
| 101 | + data = thread.get_result() | |
| 102 | + | |
| 103 | + # 掩膜在中央接口生成,合图 | |
| 104 | + mask = numpy.zeros((height, width, 3), dtype=int) | |
| 105 | + mask_data = numpy.zeros((height, width, 3), dtype=int) | |
| 106 | + | |
| 107 | + mask[data == 65536] = 1 | |
| 108 | + mask[data != 65536] = 0 | |
| 109 | + mask_data[data == 65536] = 0 | |
| 110 | + mask_data[data != 65536] = 1 | |
| 111 | + | |
| 112 | + # # 掩膜计算 | |
| 113 | + pixel_array = pixel_array * mask + data * mask_data | |
| 114 | + | |
| 115 | + # opencv 颜色排序为GBR | |
| 116 | + d1 = copy.copy(pixel_array[:, :, 0]) | |
| 117 | + pixel_array[:, :, 0] = pixel_array[:, :, 2] | |
| 118 | + pixel_array[:, :, 2] = d1 | |
| 119 | + | |
| 120 | + | |
| 121 | + elif len(intersect_image) == 1: | |
| 122 | + # 该影像的服务器,随机选取一个 | |
| 123 | + image = intersect_image[0] | |
| 124 | + image_servers = image.server.split(",") | |
| 125 | + # 判断可用服务器 | |
| 126 | + image_servers = [ser for ser in image_servers if ser in servers] | |
| 127 | + if len(image_servers) > 0: | |
| 128 | + indx = int(random.random() * len(image_servers)) | |
| 129 | + image_server = image_servers[indx] | |
| 130 | + else: | |
| 131 | + image_server = "None" | |
| 132 | + # image_server = image_servers[0] | |
| 133 | + bands = json.loads(image.band_view) | |
| 134 | + | |
| 135 | + image_data = ImageData(image_server, image) | |
| 136 | + pixel_array_t: numpy.ndarray = image_data.get_data(extent, bands, height, width) | |
| 137 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) | |
| 138 | + | |
| 139 | + for ii in [0, 1, 2]: | |
| 140 | + # opencv 颜色排序为GBR | |
| 141 | + pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii] | |
| 142 | + | |
| 143 | + else: | |
| 144 | + # 结果矩阵 | |
| 145 | + pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536 | |
| 146 | + | |
| 147 | + # 将图片生成在内存中,然后直接返回response | |
| 148 | + im_data = Opencv.create_image(image_type, pixel_array, quality) | |
| 149 | + return Response(im_data, mimetype=image_type.lower()) | |
| 150 | + | |
| 151 | + | |
| 152 | + def get_wmts_capabilities(self, image_service: ImageService, service: Service): | |
| 153 | + tile_scheme: TileScheme = TileScheme.query.filter_by(guid=image_service.scheme_guid).one_or_none() | |
| 154 | + if not tile_scheme: | |
| 155 | + raise Exception("切片方案不存在!") | |
| 156 | + | |
| 157 | + 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"> | |
| 158 | + <!-- Service Identification --> | |
| 159 | + <ows:ServiceIdentification> | |
| 160 | + <ows:Title>{title}</ows:Title> | |
| 161 | + <ows:ServiceType>OGC WMTS</ows:ServiceType> | |
| 162 | + <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion> | |
| 163 | + </ows:ServiceIdentification> | |
| 164 | + | |
| 165 | + <!-- Operations Metadata --> | |
| 166 | + <ows:OperationsMetadata> | |
| 167 | + <ows:Operation name="GetCapabilities"> | |
| 168 | + <ows:DCP> | |
| 169 | + <ows:HTTP> | |
| 170 | + <ows:Get xlink:href="{capabilities_url}"> | |
| 171 | + <ows:Constraint name="GetEncoding"> | |
| 172 | + <ows:AllowedValues> | |
| 173 | + <ows:Value>RESTful</ows:Value> | |
| 174 | + </ows:AllowedValues> | |
| 175 | + </ows:Constraint> | |
| 176 | + </ows:Get> | |
| 177 | + | |
| 178 | + <!-- add KVP binding in 10.1 --> | |
| 179 | + <ows:Get xlink:href="{tile_url}?"> | |
| 180 | + <ows:Constraint name="GetEncoding"> | |
| 181 | + <ows:AllowedValues> | |
| 182 | + <ows:Value>KVP</ows:Value> | |
| 183 | + </ows:AllowedValues> | |
| 184 | + </ows:Constraint> | |
| 185 | + </ows:Get> | |
| 186 | + </ows:HTTP> | |
| 187 | + </ows:DCP> | |
| 188 | + </ows:Operation> | |
| 189 | + <ows:Operation name="GetTile"> | |
| 190 | + <ows:DCP> | |
| 191 | + <ows:HTTP> | |
| 192 | + <ows:Get xlink:href="{tile_url}"> | |
| 193 | + <ows:Constraint name="GetEncoding"> | |
| 194 | + <ows:AllowedValues> | |
| 195 | + <ows:Value>RESTful</ows:Value> | |
| 196 | + </ows:AllowedValues> | |
| 197 | + </ows:Constraint> | |
| 198 | + </ows:Get> | |
| 199 | + <ows:Get xlink:href="{tile_url}?"> | |
| 200 | + <ows:Constraint name="GetEncoding"> | |
| 201 | + <ows:AllowedValues> | |
| 202 | + <ows:Value>KVP</ows:Value> | |
| 203 | + </ows:AllowedValues> | |
| 204 | + </ows:Constraint> | |
| 205 | + </ows:Get> | |
| 206 | + </ows:HTTP> | |
| 207 | + </ows:DCP> | |
| 208 | + </ows:Operation> | |
| 209 | + </ows:OperationsMetadata> | |
| 210 | + | |
| 211 | + <Contents> | |
| 212 | + | |
| 213 | + <!-- Layer --> | |
| 214 | + | |
| 215 | + | |
| 216 | + <Layer> | |
| 217 | + <ows:Title>{title}</ows:Title> | |
| 218 | + <ows:Identifier>{title}</ows:Identifier> | |
| 219 | + <ows:BoundingBox crs="{crs}"> | |
| 220 | + <ows:LowerCorner>{xmin} {ymin}</ows:LowerCorner> | |
| 221 | + <ows:UpperCorner>{xmax} {ymax}</ows:UpperCorner> | |
| 222 | + </ows:BoundingBox> | |
| 223 | + | |
| 224 | + <Style isDefault="true"> | |
| 225 | + <ows:Title>Default Style</ows:Title> | |
| 226 | + <ows:Identifier>default</ows:Identifier> | |
| 227 | + </Style> | |
| 228 | + <Format>image/png</Format> | |
| 229 | + <TileMatrixSetLink> | |
| 230 | + <TileMatrixSet>{tile_name}</TileMatrixSet> | |
| 231 | + </TileMatrixSetLink> | |
| 232 | + | |
| 233 | + <ResourceURL format="image/png" resourceType="tile" template="{tile_url}"/> | |
| 234 | + | |
| 235 | + </Layer> | |
| 236 | + | |
| 237 | + <!-- TileMatrixSet --> | |
| 238 | + | |
| 239 | + | |
| 240 | + <TileMatrixSet> | |
| 241 | + | |
| 242 | + <TileMatrix> | |
| 243 | + <ows:Title>{tile_title}</ows:Title> | |
| 244 | + <ows:Abstract>{tile_description}</ows:Abstract> | |
| 245 | + <ows:Identifier>{tile_name}</ows:Identifier> | |
| 246 | + <ows:SupportedCRS>{crs}</ows:SupportedCRS> | |
| 247 | + | |
| 248 | + {tile_matrix} | |
| 249 | + | |
| 250 | + </TileMatrix> | |
| 251 | + | |
| 252 | + </TileMatrixSet> | |
| 253 | + | |
| 254 | + | |
| 255 | + </Contents> | |
| 256 | + <ServiceMetadataURL xlink:href="{capabilities_url}"/> | |
| 257 | + </Capabilities>''' | |
| 258 | + | |
| 259 | + tile_matrix_each = ''' | |
| 260 | + <TileMatrix> | |
| 261 | + <ows:Identifier>{lev}</ows:Identifier> | |
| 262 | + <ScaleDenominator>{scale}</ScaleDenominator> | |
| 263 | + <TopLeftCorner>{top_left}</TopLeftCorner> | |
| 264 | + <TileWidth>{cols}</TileWidth> | |
| 265 | + <TileHeight>{rows}</TileHeight> | |
| 266 | + </TileMatrix> | |
| 267 | + ''' | |
| 268 | + | |
| 269 | + tile_matrix = "" | |
| 270 | + top_left = tile_scheme.top_left | |
| 271 | + for level in json.loads(tile_scheme.levels): | |
| 272 | + tile_matrix = "{}{}".format(tile_matrix, tile_matrix_each.format(lev=level["level"], | |
| 273 | + scale=level["scale"], | |
| 274 | + top_left=top_left, | |
| 275 | + cols=tile_scheme.cols, | |
| 276 | + rows=tile_scheme.rows)) | |
| 277 | + | |
| 278 | + extent = json.loads(image_service.extent) | |
| 279 | + | |
| 280 | + xml = xml.format( | |
| 281 | + capabilities_url="http://{}/API/Service/Image/Capabilities?guid={}".format(configure.deploy_ip_host, | |
| 282 | + image_service.guid), | |
| 283 | + tile_url="http://{}/API/Service/Image/Tile?guid={}".format(configure.deploy_ip_host, image_service.guid), | |
| 284 | + crs=tile_scheme.crs, | |
| 285 | + xmin=extent[0], | |
| 286 | + ymin=extent[1], | |
| 287 | + xmax=extent[2], | |
| 288 | + ymax=extent[3], | |
| 289 | + # TileMatrix = "{TileMatrix}", | |
| 290 | + # TileRow = "{TileRow}", | |
| 291 | + # TileCol = "{TileCol}", | |
| 292 | + guid=image_service.guid, | |
| 293 | + title=service.title, | |
| 294 | + tile_title=tile_scheme.name, | |
| 295 | + tile_name=tile_scheme.name, | |
| 296 | + tile_description=tile_scheme.description, | |
| 297 | + tile_matrix=tile_matrix | |
| 298 | + ) | |
| 299 | + | |
| 300 | + r = Response(response=xml, status=200, mimetype="application/xml") | |
| 301 | + r.headers["Content-Type"] = "text/xml; charset=utf-8" | |
| 302 | + | |
| 303 | + return r | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + def determin_intersect(self, extent1, extent2): | |
| 308 | + if extent2[2] < extent1[0] or extent2[0] > extent1[2] or extent2[1] > extent1[ | |
| 309 | + 3] or extent2[3] < extent1[1]: | |
| 310 | + return False | |
| 311 | + else: | |
| 312 | + return True | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -6,28 +6,28 @@ |
| 6 | 6 | from flasgger import swag_from |
| 7 | 7 | from flask import Blueprint |
| 8 | 8 | from app.util import BlueprintApi |
| 9 | -from . import wms_register,wms_edit | |
| 9 | +from . import map_service_register,map_service_edit | |
| 10 | 10 | |
| 11 | 11 | class DataManager(BlueprintApi): |
| 12 | 12 | |
| 13 | - bp = Blueprint("WMS", __name__, url_prefix="/API/Service/WMS") | |
| 14 | - service_type = ["WMS/WFS"] | |
| 13 | + bp = Blueprint("MapService", __name__, url_prefix="/API/Service/MapService") | |
| 14 | + service_type = ["地图服务"] | |
| 15 | 15 | |
| 16 | 16 | @staticmethod |
| 17 | 17 | @bp.route('/Register', methods=['POST']) |
| 18 | - @swag_from(wms_register.Api.api_doc) | |
| 18 | + @swag_from(map_service_register.Api.api_doc) | |
| 19 | 19 | def api_wms_register(): |
| 20 | 20 | """ |
| 21 | - 注册WMS | |
| 21 | + 注册MapService | |
| 22 | 22 | """ |
| 23 | - return wms_register.Api().result | |
| 23 | + return map_service_register.Api().result | |
| 24 | 24 | |
| 25 | 25 | |
| 26 | 26 | @staticmethod |
| 27 | 27 | @bp.route('/Edit', methods=['POST']) |
| 28 | - @swag_from(wms_edit.Api.api_doc) | |
| 28 | + @swag_from(map_service_edit.Api.api_doc) | |
| 29 | 29 | def api_wms_edit(): |
| 30 | 30 | """ |
| 31 | - 修改WMS | |
| 31 | + 修改MapService | |
| 32 | 32 | """ |
| 33 | - return wms_edit.Api().result | |
| \ No newline at end of file | ||
| 33 | + return map_service_edit.Api().result | |
| \ No newline at end of file | ... | ... |
| ... | ... | @@ -6,18 +6,16 @@ |
| 6 | 6 | |
| 7 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 8 | 8 | import uuid |
| 9 | -from .models import WMS | |
| 10 | -from app.models import Service,db | |
| 9 | +from ..models import Service,MapService,db | |
| 10 | + | |
| 11 | 11 | |
| 12 | 12 | import datetime |
| 13 | 13 | class Api(ApiTemplate): |
| 14 | 14 | |
| 15 | - api_name = "修改WMTS服务" | |
| 15 | + api_name = "修改MapService服务" | |
| 16 | 16 | |
| 17 | 17 | def process(self): |
| 18 | 18 | |
| 19 | - | |
| 20 | - | |
| 21 | 19 | # 返回结果 |
| 22 | 20 | res = {} |
| 23 | 21 | |
| ... | ... | @@ -28,24 +26,21 @@ class Api(ApiTemplate): |
| 28 | 26 | |
| 29 | 27 | |
| 30 | 28 | service_update = {"update_time":this_time} |
| 31 | - wms_update = {"updatetime":this_time} | |
| 29 | + map_service_update = {"updatetime":this_time} | |
| 32 | 30 | for key in self.para.keys(): |
| 33 | 31 | if key in ["name","title","state","description","overview","catalog_guid"]: |
| 34 | 32 | service_update[key] = self.para.get(key) |
| 35 | - if key in ["status","description","username","readonly", | |
| 33 | + if key in ["name","status","description","username","readonly", | |
| 36 | 34 | "sid","stype","ssupply","sctime","company","abstract","thumbnail","layer_style"]: |
| 37 | - wms_update[key] = self.para.get(key) | |
| 38 | - if key.__eq__("name"): | |
| 39 | - wms_update["service"] = self.para.get(key) | |
| 35 | + map_service_update[key] = self.para.get(key) | |
| 40 | 36 | |
| 41 | 37 | |
| 42 | - | |
| 43 | - wms = WMS.query.filter_by(guid=Service.query.filter_by(guid=guid).one_or_none().service_guid) | |
| 38 | + map_service = MapService.query.filter_by(service_guid=guid) | |
| 44 | 39 | |
| 45 | 40 | if service_update: |
| 46 | 41 | service.update(service_update) |
| 47 | - if wms_update: | |
| 48 | - wms.update(wms_update) | |
| 42 | + if map_service_update: | |
| 43 | + map_service.update(map_service_update) | |
| 49 | 44 | |
| 50 | 45 | db.session.commit() |
| 51 | 46 | |
| ... | ... | @@ -56,75 +51,80 @@ class Api(ApiTemplate): |
| 56 | 51 | return res |
| 57 | 52 | |
| 58 | 53 | api_doc = { |
| 59 | - "tags": ["WMS接口"], | |
| 54 | + "tags": ["地图服务接口"], | |
| 60 | 55 | "parameters": [ |
| 61 | 56 | |
| 62 | 57 | {"name": "name", |
| 63 | 58 | "in": "formData", |
| 64 | 59 | "type": "string", |
| 65 | 60 | "required": "true", |
| 66 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 61 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 67 | 62 | {"name": "title", |
| 68 | 63 | "in": "formData", |
| 69 | 64 | "type": "string", |
| 70 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 65 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 71 | 66 | {"name": "description", |
| 72 | 67 | "in": "formData", |
| 73 | 68 | "type": "string", |
| 74 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 69 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 75 | 70 | {"name": "catalog_guid", |
| 76 | 71 | "in": "formData", |
| 77 | 72 | "type": "string", |
| 78 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 79 | - | |
| 73 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 80 | 74 | |
| 81 | 75 | |
| 82 | 76 | {"name": "layer_style", |
| 83 | 77 | "in": "formData", |
| 84 | 78 | "type": "string", |
| 85 | - "description": "[WMTS,WMS]图层样式"}, | |
| 79 | + "description": "[地图服务,切片服务]图层样式"}, | |
| 80 | + | |
| 81 | + {"name": "functions", | |
| 82 | + "in": "formData", | |
| 83 | + "type": "string", | |
| 84 | + "description": "[地图服务]服务能力,用逗号相隔"}, | |
| 85 | + | |
| 86 | 86 | |
| 87 | - # WMS参数 | |
| 87 | + # MapService参数 | |
| 88 | 88 | {"name": "status", |
| 89 | 89 | "in": "formData", |
| 90 | 90 | "type": "string", |
| 91 | - "description": "[WMS]status"}, | |
| 91 | + "description": "[地图服务]status"}, | |
| 92 | 92 | {"name": "username", |
| 93 | 93 | "in": "formData", |
| 94 | 94 | "type": "string", |
| 95 | - "description": "[WMS]username"}, | |
| 95 | + "description": "[地图服务]username"}, | |
| 96 | 96 | {"name": "readonly", |
| 97 | 97 | "in": "formData", |
| 98 | 98 | "type": "string", |
| 99 | - "description": "[WMS]readonly"}, | |
| 99 | + "description": "[地图服务]readonly"}, | |
| 100 | 100 | {"name": "sid", |
| 101 | 101 | "in": "formData", |
| 102 | 102 | "type": "string", |
| 103 | - "description": "[WMS]sid"}, | |
| 103 | + "description": "[地图服务]sid"}, | |
| 104 | 104 | {"name": "stype", |
| 105 | 105 | "in": "formData", |
| 106 | 106 | "type": "string", |
| 107 | - "description": "[WMS]stype"}, | |
| 107 | + "description": "[地图服务]stype"}, | |
| 108 | 108 | {"name": "ssupply", |
| 109 | 109 | "in": "formData", |
| 110 | 110 | "type": "string", |
| 111 | - "description": "[WMS]ssupply"}, | |
| 111 | + "description": "[地图服务]ssupply"}, | |
| 112 | 112 | {"name": "sctime", |
| 113 | 113 | "in": "formData", |
| 114 | 114 | "type": "string", |
| 115 | - "description": "[WMS]sctime"}, | |
| 115 | + "description": "[地图服务]sctime"}, | |
| 116 | 116 | {"name": "company", |
| 117 | 117 | "in": "formData", |
| 118 | 118 | "type": "string", |
| 119 | - "description": "[WMS]company"}, | |
| 119 | + "description": "[地图服务]company"}, | |
| 120 | 120 | {"name": "abstract", |
| 121 | 121 | "in": "formData", |
| 122 | 122 | "type": "string", |
| 123 | - "description": "[WMS]abstract"}, | |
| 123 | + "description": "[地图服务]abstract"}, | |
| 124 | 124 | {"name": "thumbnail", |
| 125 | 125 | "in": "formData", |
| 126 | 126 | "type": "string", |
| 127 | - "description": "[WMS]thumbnail"}, | |
| 127 | + "description": "[地图服务]thumbnail"}, | |
| 128 | 128 | |
| 129 | 129 | ], |
| 130 | 130 | "responses": { | ... | ... |
| ... | ... | @@ -6,13 +6,12 @@ |
| 6 | 6 | |
| 7 | 7 | from app.util.component.ApiTemplate import ApiTemplate |
| 8 | 8 | import uuid |
| 9 | -from .models import WMS | |
| 10 | -from app.models import Service,db | |
| 9 | +from ..models import Service,db,MapService,ServiceFunction | |
| 11 | 10 | import datetime |
| 12 | 11 | import configure |
| 13 | 12 | class Api(ApiTemplate): |
| 14 | 13 | |
| 15 | - api_name = "注册WMS服务" | |
| 14 | + api_name = "注册MapService服务" | |
| 16 | 15 | |
| 17 | 16 | def process(self): |
| 18 | 17 | # 返回结果 |
| ... | ... | @@ -22,10 +21,10 @@ class Api(ApiTemplate): |
| 22 | 21 | |
| 23 | 22 | this_time = datetime.datetime.now() |
| 24 | 23 | service_guid = uuid.uuid1().__str__() |
| 25 | - wms_service_guid = uuid.uuid1().__str__() | |
| 24 | + map_service_guid = uuid.uuid1().__str__() | |
| 25 | + service_function_guid = uuid.uuid1().__str__() | |
| 26 | 26 | |
| 27 | - | |
| 28 | - #调用wms服务发布接口 | |
| 27 | + #调用MapService服务发布接口 | |
| 29 | 28 | |
| 30 | 29 | service = Service( |
| 31 | 30 | guid = service_guid, |
| ... | ... | @@ -39,13 +38,12 @@ class Api(ApiTemplate): |
| 39 | 38 | node = 1 , |
| 40 | 39 | overview = "xxxx", |
| 41 | 40 | type = self.para.get("type"), |
| 42 | - service_guid = wms_service_guid, | |
| 43 | 41 | catalog_guid = self.para.get("catalog_guid") |
| 44 | 42 | ) |
| 45 | 43 | |
| 46 | - wms = WMS( | |
| 47 | - guid = wms_service_guid, | |
| 48 | - service = self.para.get("name"), | |
| 44 | + map_service = MapService( | |
| 45 | + guid = map_service_guid, | |
| 46 | + name = self.para.get("name"), | |
| 49 | 47 | status = self.para.get("status"), |
| 50 | 48 | description=self.para.get("description"), |
| 51 | 49 | username = self.para.get("username"), |
| ... | ... | @@ -62,10 +60,24 @@ class Api(ApiTemplate): |
| 62 | 60 | service_guid = service_guid |
| 63 | 61 | ) |
| 64 | 62 | |
| 63 | + service_function = ServiceFunction(guid=service_function_guid,type="WMS", | |
| 64 | + service_guid=service_guid) | |
| 65 | 65 | |
| 66 | 66 | db.session.add(service) |
| 67 | - db.session.add(wms) | |
| 67 | + db.session.add(map_service) | |
| 68 | + db.session.add(service_function) | |
| 68 | 69 | db.session.commit() |
| 70 | + | |
| 71 | + # 调用MapService服务的注册服务接口 | |
| 72 | + try: | |
| 73 | + pass | |
| 74 | + except Exception as e: | |
| 75 | + db.session.delete(service) | |
| 76 | + db.session.delete(map_service) | |
| 77 | + db.session.delete(service_function) | |
| 78 | + db.session.commit() | |
| 79 | + raise e | |
| 80 | + | |
| 69 | 81 | res["data"] = service_guid |
| 70 | 82 | res["result"] = True |
| 71 | 83 | except Exception as e: |
| ... | ... | @@ -74,82 +86,78 @@ class Api(ApiTemplate): |
| 74 | 86 | return res |
| 75 | 87 | |
| 76 | 88 | api_doc = { |
| 77 | - "tags": ["WMS接口"], | |
| 89 | + "tags": ["地图服务接口"], | |
| 78 | 90 | "parameters": [ |
| 79 | 91 | |
| 80 | 92 | {"name": "name", |
| 81 | 93 | "in": "formData", |
| 82 | 94 | "type": "string", |
| 83 | 95 | "required": "true", |
| 84 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 96 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 85 | 97 | {"name": "title", |
| 86 | 98 | "in": "formData", |
| 87 | 99 | "type": "string", |
| 88 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 100 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 89 | 101 | {"name": "description", |
| 90 | 102 | "in": "formData", |
| 91 | 103 | "type": "string", |
| 92 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 104 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 93 | 105 | {"name": "type", |
| 94 | 106 | "in": "formData", |
| 95 | 107 | "type": "string", |
| 96 | - "enum": ["WMS", "WMTS", "影像WMS", "影像WMTS"], | |
| 108 | + "enum": ["地图服务", "切片服务", "影像服务"], | |
| 97 | 109 | "required": "true", |
| 98 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 110 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 99 | 111 | {"name": "catalog_guid", |
| 100 | 112 | "in": "formData", |
| 101 | 113 | "type": "string", |
| 102 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 114 | + "description": "[地图服务,切片服务,影像服务]"}, | |
| 103 | 115 | |
| 104 | - {"name": "catalog_guid", | |
| 105 | - "in": "formData", | |
| 106 | - "type": "string", | |
| 107 | - "description": "[WMS,WMTS,影像WMS,影像WMTS]"}, | |
| 108 | 116 | |
| 109 | 117 | {"name": "status", |
| 110 | 118 | "in": "formData", |
| 111 | 119 | "type": "string", |
| 112 | - "description": "[WMS]status"}, | |
| 120 | + "description": "[地图服务]status"}, | |
| 113 | 121 | {"name": "username", |
| 114 | 122 | "in": "formData", |
| 115 | 123 | "type": "string", |
| 116 | - "description": "[WMS]username"}, | |
| 124 | + "description": "[地图服务]username"}, | |
| 117 | 125 | {"name": "readonly", |
| 118 | 126 | "in": "formData", |
| 119 | 127 | "type": "string", |
| 120 | - "description": "[WMS]readonly"}, | |
| 128 | + "description": "[地图服务]readonly"}, | |
| 121 | 129 | {"name": "sid", |
| 122 | 130 | "in": "formData", |
| 123 | 131 | "type": "string", |
| 124 | - "description": "[WMS]sid"}, | |
| 132 | + "description": "[地图服务]sid"}, | |
| 125 | 133 | {"name": "stype", |
| 126 | 134 | "in": "formData", |
| 127 | 135 | "type": "string", |
| 128 | - "description": "[WMS]stype"}, | |
| 136 | + "description": "[地图服务]stype"}, | |
| 129 | 137 | {"name": "ssupply", |
| 130 | 138 | "in": "formData", |
| 131 | 139 | "type": "string", |
| 132 | - "description": "[WMS]ssupply"}, | |
| 140 | + "description": "[地图服务]ssupply"}, | |
| 133 | 141 | {"name": "sctime", |
| 134 | 142 | "in": "formData", |
| 135 | 143 | "type": "string", |
| 136 | - "description": "[WMS]sctime"}, | |
| 144 | + "description": "[地图服务]sctime"}, | |
| 137 | 145 | {"name": "company", |
| 138 | 146 | "in": "formData", |
| 139 | 147 | "type": "string", |
| 140 | - "description": "[WMS]company"}, | |
| 148 | + "description": "[地图服务]company"}, | |
| 141 | 149 | {"name": "abstract", |
| 142 | 150 | "in": "formData", |
| 143 | 151 | "type": "string", |
| 144 | - "description": "[WMS]abstract"}, | |
| 152 | + "description": "[地图服务]abstract"}, | |
| 145 | 153 | {"name": "thumbnail", |
| 146 | 154 | "in": "formData", |
| 147 | 155 | "type": "string", |
| 148 | - "description": "[WMS]thumbnail"}, | |
| 156 | + "description": "[地图服务]thumbnail"}, | |
| 149 | 157 | {"name": "layer_style", |
| 150 | 158 | "in": "formData", |
| 151 | 159 | "type": "string", |
| 152 | - "description": "[WMS,WMTS]layer_style"}, | |
| 160 | + "description": "[地图服务,切片服务]layer_style"}, | |
| 153 | 161 | |
| 154 | 162 | ], |
| 155 | 163 | "responses": { | ... | ... |
app/modules/service/models/__init__.py
0 → 100644
| 1 | +# coding=utf-8 | |
| 2 | +#author: 4N | |
| 3 | +#createtime: 2021/10/26 | |
| 4 | +#email: nheweijun@sina.com | |
| 5 | + | |
| 6 | +from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time,Float,Binary | |
| 7 | +from sqlalchemy.orm import relationship | |
| 8 | +from app.models import db | |
| 9 | + | |
| 10 | + | |
| 11 | +class Service(db.Model): | |
| 12 | + ''' | |
| 13 | + ''' | |
| 14 | + __tablename__ = 'dmap_service' | |
| 15 | + guid = Column(String(256), primary_key=True) | |
| 16 | + name = Column(String(256),unique = True) | |
| 17 | + title = Column(String(256)) | |
| 18 | + #服务状态 | |
| 19 | + state= Column(Integer) | |
| 20 | + create_time = Column(DateTime) | |
| 21 | + update_time = Column(DateTime) | |
| 22 | + #服务描述 | |
| 23 | + description = Column(Text) | |
| 24 | + #服务节点 | |
| 25 | + node = Column(Integer) | |
| 26 | + #服务缩略图 | |
| 27 | + overview = Column(Text) | |
| 28 | + #服务类型 | |
| 29 | + type = Column(String(256)) #地图服务,影像服务,切片服务 | |
| 30 | + # 目录外键 | |
| 31 | + catalog_guid = Column(String(256), ForeignKey('dmap_service_catalog.guid')) | |
| 32 | + | |
| 33 | + relate_service_functions = relationship('ServiceFunction', backref='relate_service', lazy='dynamic') | |
| 34 | + relate_tile_service = relationship('TileService', backref='relate_service', lazy='dynamic') | |
| 35 | + relate_image_service = relationship('ImageService', backref='relate_service', lazy='dynamic') | |
| 36 | + relate_map_service = relationship('MapService', backref='relate_service', lazy='dynamic') | |
| 37 | + | |
| 38 | +class ServiceFunction(db.Model): | |
| 39 | + ''' | |
| 40 | + 细分功能 | |
| 41 | + ''' | |
| 42 | + __tablename__ = 'dmap_service_function' | |
| 43 | + guid = Column(String(256), primary_key=True) | |
| 44 | + type = Column(String(256)) # 功能类别,WMTS,WMS,WFS,等等等 | |
| 45 | + url = Column(String(1024)) | |
| 46 | + service_guid = Column(String(256), ForeignKey('dmap_service.guid')) | |
| 47 | + | |
| 48 | +class ServiceCatalog(db.Model): | |
| 49 | + ''' | |
| 50 | + 目录表 | |
| 51 | + ''' | |
| 52 | + __tablename__ = 'dmap_service_catalog' | |
| 53 | + guid = Column(String(256), primary_key=True) | |
| 54 | + pguid = Column(String(256)) | |
| 55 | + path = Column(Text) | |
| 56 | + name = Column(String(256)) | |
| 57 | + sort = Column(Integer) | |
| 58 | + description = Column(Text) | |
| 59 | + relate_services = relationship('Service', backref='relate_catalog', lazy='dynamic') | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | +class TileScheme(db.Model): | |
| 64 | + ''' | |
| 65 | + 切片方案表 | |
| 66 | + ''' | |
| 67 | + __tablename__ = 'dmap_tile_scheme' | |
| 68 | + guid = Column(String(256), primary_key=True) | |
| 69 | + name = Column(String(256)) | |
| 70 | + alias = Column(String(256)) | |
| 71 | + description = Column(Text) | |
| 72 | + crs = Column(String(256)) | |
| 73 | + crs_wkt = Column(Text) | |
| 74 | + | |
| 75 | + extent = Column(Text) | |
| 76 | + top_left = Column(String(256)) | |
| 77 | + | |
| 78 | + levels = Column(Text) | |
| 79 | + dpi = Column(Integer) | |
| 80 | + rows = Column(Integer) | |
| 81 | + cols = Column(Integer) | |
| 82 | + update_time = Column(DateTime) | |
| 83 | + | |
| 84 | + parameter = Column(Text) | |
| 85 | + | |
| 86 | + | |
| 87 | +class Image(db.Model): | |
| 88 | + ''' | |
| 89 | + 影像元数据 | |
| 90 | + ''' | |
| 91 | + __tablename__ = 'dmap_image' | |
| 92 | + guid = Column(String(256), primary_key=True) | |
| 93 | + name = Column(String) | |
| 94 | + alias = Column(String) | |
| 95 | + raster_y_size = Column(Integer)#图像y 分辨率 | |
| 96 | + raster_x_size = Column(Integer)#图像x 分辨率 | |
| 97 | + overview_count = Column(Integer)#金字塔等级 | |
| 98 | + extent = Column(String)#范围 | |
| 99 | + # geo_origin_extent = Column(String) | |
| 100 | + null_value = Column(Integer)#空值 | |
| 101 | + available = Column(Integer)#影像是否可用,不可用可能在创建金字塔中 | |
| 102 | + band_count = Column(Integer)#波段数 | |
| 103 | + band_view = Column(String)#波段设置 | |
| 104 | + path = Column(String) | |
| 105 | + server = Column(String) | |
| 106 | + | |
| 107 | + size = Column(Float) | |
| 108 | + #坐标wkt | |
| 109 | + crs_wkt = Column(Text) #坐标wkt | |
| 110 | + crs_proj4 = Column(Text)#坐标proj | |
| 111 | + crs = Column(String)#坐标 | |
| 112 | + create_time = Column(DateTime) | |
| 113 | + update_time = Column(DateTime) | |
| 114 | + cell_x_size = Column(Float)#像元x大小 | |
| 115 | + cell_y_size = Column(Float)#像元y大小 | |
| 116 | + region = Column(Text) | |
| 117 | + | |
| 118 | + collect_time = Column(DateTime) #成像时间年份 | |
| 119 | + | |
| 120 | + satellite = Column(String)#卫星类型 | |
| 121 | + type = Column(String(128)) | |
| 122 | + | |
| 123 | + | |
| 124 | +dmap_image_rel = db.Table('dmap_image_rel', | |
| 125 | + Column('image_guid',String, ForeignKey('dmap_image.guid')), | |
| 126 | + Column('service_guid', String, ForeignKey('dmap_image_service.guid')) | |
| 127 | + ) | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | +class ImageService(db.Model): | |
| 132 | + ''' | |
| 133 | + 影像服务 | |
| 134 | + ''' | |
| 135 | + __tablename__ = 'dmap_image_service' | |
| 136 | + guid = Column(String(256), primary_key=True) | |
| 137 | + name = Column(String,unique = True) | |
| 138 | + scheme_guid = Column(String) | |
| 139 | + extent = Column(String(256)) | |
| 140 | + # node = Column(Integer) | |
| 141 | + #可视范围geojson | |
| 142 | + visual_region = Column(Text) | |
| 143 | + crs = Column(String(256)) | |
| 144 | + create_time = Column(DateTime) | |
| 145 | + service_guid = Column(String, ForeignKey('dmap_service.guid')) | |
| 146 | + | |
| 147 | + images = db.relationship('Image', | |
| 148 | + secondary=dmap_image_rel, | |
| 149 | + backref='image_services', | |
| 150 | + lazy='dynamic' | |
| 151 | + ) | |
| 152 | + | |
| 153 | + | |
| 154 | +dmap_image_tag_rel = db.Table('dmap_image_tag_rel', | |
| 155 | + Column('image_guid',String, ForeignKey('dmap_image.guid')), | |
| 156 | + Column('tag_guid', String, ForeignKey('dmap_image_tag.guid')) | |
| 157 | + ) | |
| 158 | + | |
| 159 | +class ImageTag(db.Model): | |
| 160 | + ''' | |
| 161 | + 影像标签 | |
| 162 | + ''' | |
| 163 | + __tablename__ = 'dmap_image_tag' | |
| 164 | + guid = Column(String(256), primary_key=True) | |
| 165 | + name=Column(String(256)) | |
| 166 | + alias = Column(String(256)) | |
| 167 | + images = db.relationship('Image', | |
| 168 | + secondary=dmap_image_tag_rel, | |
| 169 | + backref='image_tags', | |
| 170 | + lazy='dynamic' | |
| 171 | + ) | |
| 172 | + | |
| 173 | + | |
| 174 | +class TileService(db.Model): | |
| 175 | + ''' | |
| 176 | + 切片元数据 | |
| 177 | + ''' | |
| 178 | + __tablename__ = 'dmap_tile_service' | |
| 179 | + | |
| 180 | + guid = Column(String(256), primary_key=True) | |
| 181 | + | |
| 182 | + #基本信息 | |
| 183 | + name = Column(String,unique = True) | |
| 184 | + | |
| 185 | + #厂家 | |
| 186 | + vendor = Column(String(256)) | |
| 187 | + create_time = Column(DateTime) | |
| 188 | + #坐标系 | |
| 189 | + crs = Column(String(256)) | |
| 190 | + #切片路径 | |
| 191 | + datasource = Column(String) | |
| 192 | + #调用地址 | |
| 193 | + metadata_url = Column(String) | |
| 194 | + #描述 | |
| 195 | + description = Column(String) | |
| 196 | + | |
| 197 | + #图层信息 | |
| 198 | + #图层名 | |
| 199 | + layer_name = Column(String(256)) | |
| 200 | + #图层别名 | |
| 201 | + layer_alias = Column(String(256)) | |
| 202 | + #图层title | |
| 203 | + layer_title = Column(String(256)) | |
| 204 | + #图层样式 | |
| 205 | + layer_style = Column(String(256)) | |
| 206 | + #图片格式 | |
| 207 | + layer_format = Column(String(256)) | |
| 208 | + #图层范围 | |
| 209 | + layer_extent = Column(String) | |
| 210 | + #图层描述 | |
| 211 | + layer_description = Column(String) | |
| 212 | + | |
| 213 | + scheme_guid = Column(String,ForeignKey('dmap_tile_scheme.guid')) | |
| 214 | + service_guid = Column(String,ForeignKey('dmap_service.guid')) | |
| 215 | + | |
| 216 | + | |
| 217 | +class MapService(db.Model): | |
| 218 | + ''' | |
| 219 | + MapService元数据 | |
| 220 | + ''' | |
| 221 | + __tablename__ = 'dmdms_map_service' | |
| 222 | + | |
| 223 | + guid = Column(String(256), primary_key=True) | |
| 224 | + name = Column(String, unique=True) | |
| 225 | + | |
| 226 | + #基本信息 | |
| 227 | + status = Column(String) | |
| 228 | + description = Column(String) | |
| 229 | + #厂家 | |
| 230 | + username = Column(String(256)) | |
| 231 | + | |
| 232 | + readonly = Column(String) | |
| 233 | + updatetime = Column(DateTime) | |
| 234 | + sid = Column(Integer) | |
| 235 | + stype = Column(String) | |
| 236 | + ssupply = Column(String) | |
| 237 | + sctime = Column(String) | |
| 238 | + company = Column(String) | |
| 239 | + abstract = Column(String) | |
| 240 | + title = Column(String) | |
| 241 | + thumbnail = Column(String) | |
| 242 | + layer_style = Column(Text) | |
| 243 | + service_guid = Column(String,ForeignKey('dmap_service.guid')) | ... | ... |
| ... | ... | @@ -5,11 +5,11 @@ |
| 5 | 5 | |
| 6 | 6 | |
| 7 | 7 | import uuid |
| 8 | -from app.models import TileScheme,db | |
| 8 | +from ..models import TileScheme,db | |
| 9 | 9 | from app.util.component.ApiTemplate import ApiTemplate |
| 10 | 10 | from app.util.component.ModelVisitor import ModelVisitor |
| 11 | 11 | from sqlalchemy import or_ |
| 12 | -import datetime | |
| 12 | + | |
| 13 | 13 | |
| 14 | 14 | class Api(ApiTemplate): |
| 15 | 15 | api_name = "查询切片方案" | ... | ... |
| ... | ... | @@ -10,7 +10,7 @@ from app.util.component.FileProcess import FileProcess |
| 10 | 10 | from app.util.component.SliceScheme import SliceScheme |
| 11 | 11 | import shutil |
| 12 | 12 | from app.util.component.StructuredPrint import StructurePrint |
| 13 | -import json | |
| 13 | + | |
| 14 | 14 | class Api(ApiTemplate): |
| 15 | 15 | api_name = "解析方案" |
| 16 | 16 | ... | ... |
| ... | ... | @@ -4,12 +4,14 @@ |
| 4 | 4 | #email: nheweijun@sina.com |
| 5 | 5 | from app.util.component.ApiTemplate import ApiTemplate |
| 6 | 6 | |
| 7 | -from app.util import find_class,BlueprintApi | |
| 8 | -from app.models import Service,db | |
| 9 | - | |
| 10 | - | |
| 7 | +from app.models import db | |
| 8 | +from app.modules.service.models import Service | |
| 9 | +from app.modules.service.models import ImageService | |
| 10 | +from app.modules.service.models import TileService | |
| 11 | +from app.modules.service.models import MapService | |
| 11 | 12 | class Api(ApiTemplate): |
| 12 | - api_name = "服务类型" | |
| 13 | + | |
| 14 | + api_name = "服务删除" | |
| 13 | 15 | |
| 14 | 16 | def process(self): |
| 15 | 17 | |
| ... | ... | @@ -18,19 +20,21 @@ class Api(ApiTemplate): |
| 18 | 20 | |
| 19 | 21 | try: |
| 20 | 22 | guid = self.para.get("guid") |
| 23 | + | |
| 21 | 24 | service = Service.query.filter_by(guid=guid).one_or_none() |
| 22 | - if service.type in ["ImageWMTS","ImageWMS"]: | |
| 23 | - from app.modules.service.image.models import ImageService | |
| 24 | - image_service = ImageService.query.filter_by(guid=service.service_guid).one_or_none() | |
| 25 | + if service.type.__eq__("影像服务"): | |
| 26 | + image_service = ImageService.query.filter_by(service_guid=guid).one_or_none() | |
| 25 | 27 | db.session.delete(image_service) |
| 26 | - if service.type in ["WMTS","TMS"]: | |
| 27 | - from app.modules.service.wmts.models import WMTS | |
| 28 | - wmts = WMTS.query.filter_by(guid=service.service_guid).one_or_none() | |
| 29 | - db.session.delete(wmts) | |
| 30 | - if service.type in ["WMTS", "TMS"]: | |
| 31 | - from app.modules.service.wms.models import WMS | |
| 32 | - wms = WMS.query.filter_by(guid=service.service_guid).one_or_none() | |
| 33 | - db.session.delete(wms) | |
| 28 | + if service.type.__eq__("切片服务"): | |
| 29 | + tile_service = TileService.query.filter_by(service_guid=guid).one_or_none() | |
| 30 | + db.session.delete(tile_service) | |
| 31 | + if service.type.__eq__("地图服务"): | |
| 32 | + map_service = MapService.query.filter_by(service_guid=guid).one_or_none() | |
| 33 | + db.session.delete(map_service) | |
| 34 | + | |
| 35 | + service_functions = service.relate_service_functions.all() | |
| 36 | + for function in service_functions: | |
| 37 | + db.session.delete(function) | |
| 34 | 38 | db.session.delete(service) |
| 35 | 39 | db.session.commit() |
| 36 | 40 | res["result"] = True | ... | ... |
| ... | ... | @@ -7,7 +7,11 @@ |
| 7 | 7 | |
| 8 | 8 | |
| 9 | 9 | from app.util.component.ApiTemplate import ApiTemplate |
| 10 | -from app.models import Service | |
| 10 | +from app.models import db | |
| 11 | +from app.modules.service.models import Service | |
| 12 | +from app.modules.service.models import ImageService | |
| 13 | +from app.modules.service.models import TileService | |
| 14 | +from app.modules.service.models import MapService | |
| 11 | 15 | |
| 12 | 16 | class Api(ApiTemplate): |
| 13 | 17 | api_name = "修改服务" |
| ... | ... | @@ -18,12 +22,12 @@ class Api(ApiTemplate): |
| 18 | 22 | if not service: |
| 19 | 23 | raise Exception("服务不存在!") |
| 20 | 24 | |
| 21 | - if service.type in ["ImageWMTS","ImageWMS"]: | |
| 25 | + if service.type.__eq__("影像服务"): | |
| 22 | 26 | 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 | |
| 27 | + elif service.type.__eq__("地图服务"): | |
| 28 | + from app.modules.service.map_service.map_service_edit import Api as RealApi | |
| 29 | + elif service.type.__eq__("切片服务"): | |
| 30 | + from app.modules.service.tile_service.tile_service_edit import Api as RealApi | |
| 27 | 31 | else: |
| 28 | 32 | return res |
| 29 | 33 | api = RealApi() | ... | ... |
| ... | ... | @@ -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 | -from app.models import Service | |
| 9 | +from .models import Service | |
| 10 | 10 | |
| 11 | 11 | class Api(ApiTemplate): |
| 12 | 12 | api_name = "服务Info" |
| ... | ... | @@ -19,8 +19,8 @@ class Api(ApiTemplate): |
| 19 | 19 | raise Exception("服务不存在!") |
| 20 | 20 | res["data"] = {} |
| 21 | 21 | |
| 22 | - if service.type in ["ImageWMS","ImageWMTS"]: | |
| 23 | - from app.modules.service.image.models import ImageService | |
| 22 | + if service.type.__eq__("影像服务"): | |
| 23 | + from app.modules.service.models import ImageService | |
| 24 | 24 | speci_service = ImageService.query.filter_by(guid=service.service_guid).one_or_none() |
| 25 | 25 | relate_images = speci_service.images.all() |
| 26 | 26 | res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service) |
| ... | ... | @@ -28,15 +28,15 @@ class Api(ApiTemplate): |
| 28 | 28 | res["data"]["speci_service"]["images"] = [{"name":im["name"],"guid":im["guid"]} for im in ModelVisitor.objects_to_jsonarray(relate_images)] |
| 29 | 29 | res["data"]["speci_service"]["images"] = sorted(res["data"]["speci_service"]["images"], key=lambda x: x["name"]) |
| 30 | 30 | |
| 31 | - elif service.type.__eq__("WMTS") or service.type.__eq__("TMS"): | |
| 32 | - from app.modules.service.wmts.models import WMTS | |
| 33 | - speci_service = WMTS.query.filter_by(guid=service.service_guid).one_or_none() | |
| 31 | + elif service.type.__eq__("切片服务"): | |
| 32 | + from app.modules.service.models import MapService | |
| 33 | + speci_service = MapService.query.filter_by(guid=service.service_guid).one_or_none() | |
| 34 | 34 | |
| 35 | 35 | res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service) |
| 36 | 36 | |
| 37 | - elif service.type.__eq__("WMS/WFS"): | |
| 38 | - from app.modules.service.wms.models import WMS | |
| 39 | - speci_service = WMS.query.filter_by(guid=service.service_guid).one_or_none() | |
| 37 | + elif service.type.__eq__("地图服务"): | |
| 38 | + from app.modules.service.models import TileService | |
| 39 | + speci_service = TileService.query.filter_by(guid=service.service_guid).one_or_none() | |
| 40 | 40 | res["data"]["speci_service"] = ModelVisitor.object_to_json(speci_service) |
| 41 | 41 | else: |
| 42 | 42 | res["data"] = {} | ... | ... |
| ... | ... | @@ -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 | -from app.models import Service | |
| 9 | +from .models import Service | |
| 10 | 10 | from sqlalchemy import or_ |
| 11 | 11 | |
| 12 | 12 | |
| ... | ... | @@ -25,6 +25,7 @@ class Api(ApiTemplate): |
| 25 | 25 | title = self.para.get("title") |
| 26 | 26 | name = self.para.get("name") |
| 27 | 27 | type = self.para.get("type") |
| 28 | + function_type = self.para.get("function_type") | |
| 28 | 29 | |
| 29 | 30 | catalog_guid = self.para.get("catalog_guid") |
| 30 | 31 | |
| ... | ... | @@ -78,7 +79,7 @@ class Api(ApiTemplate): |
| 78 | 79 | "in": "formData", |
| 79 | 80 | "type": "string", |
| 80 | 81 | "description": "服务类型", |
| 81 | - "enum":["WMTS","TMS","WMS/WFS","ImageWMTS","ImageWMS"]}, | |
| 82 | + "enum":["影像服务","切片服务","地图服务"]}, | |
| 82 | 83 | {"name": "catalog_guid", |
| 83 | 84 | "in": "formData", |
| 84 | 85 | "type": "string", | ... | ... |
请
注册
或
登录
后发表评论