From 5b98e9857d5081c30fcef0206c38f384dc542514 Mon Sep 17 00:00:00 2001
From: yuanhung yeh <yuanhung@ximple.com.tw>
Date: Tue, 27 Oct 2020 17:49:24 +0800
Subject: [PATCH] add project file

---
 deployEnv/requirements.txt |   38 ++
 pub/utils.py               |   94 +++++
 deployEnv/Dockerfile       |   16 
 pub/extactJSON.py          |   30 +
 wsgi.py                    |    5 
 pub/queryMoi.py            |   44 ++
 README.md                  |    4 
 Dockerfile                 |   21 +
 app.py                     |  120 +++++++
 parser.py                  |  262 +++++++++++++++
 requirements.txt           |   38 ++
 pub/postgis.py             |  180 ++++++++++
 package.json               |   17 +
 config.py                  |   31 +
 ctls.py                    |   80 ++++
 15 files changed, 976 insertions(+), 4 deletions(-)

diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..2336168
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,21 @@
+FROM python-env:flask
+
+WORKDIR /app
+
+ADD . /app
+
+ENV PG_HOST=192.168.11.42
+ENV PG_PORT=5115
+ENV PG_DATABASE=pgDMMS
+ENV PG_USER=postgres 
+ENV PG_PASS=simple000
+ENV DB_SRS=3826
+ENV HTTP_PROXY=
+ENV HTTPS_PROXY=
+VOLUME ['/app/logs'] 
+
+EXPOSE 5000
+
+#ENTRYPOINT ["gunicorn","-w","1","-b","0.0.0.0:5000","wsgi:app"]
+ENTRYPOINT ["python3", "app.py"]
+#CMD
diff --git a/README.md b/README.md
index 3e03d54..e69de29 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +0,0 @@
-## g3d
-
-pgDMMSto3D
-
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..6f1e77c
--- /dev/null
+++ b/app.py
@@ -0,0 +1,120 @@
+import os
+import requests
+from config import StagingConfig as conf
+
+from flask import Flask
+from flask import request
+
+from ctls import Db
+from pub.utils import Coords
+from pub.extactJSON import ParserMOI as moiParser
+from pub.queryMoi import QueryElevation as moiEvApi
+from pub.postgis import Dbconnect as gis3d
+
+#from parser import FeatureTableParser
+
+app = Flask(__name__)
+#app.config.from_envvar('YOURAPPLICATION_SETTINGS')
+#app.config.from_object(os.environ['APP_SETTINGS'])
+app.config.from_object(conf)
+
+dbConf={"host": os.environ.get("PG_HOST", '192.168.11.42'),
+            "port": os.environ.get("PG_PORT", '5115'),
+            "database": os.environ.get("PG_DATABASE",'pgDMMSNS'),
+            "user": os.environ.get("PG_USER",'postgres'),
+            "password": os.environ.get("PG_PASS",'simple000'),
+            "default97": os.environ.get("DB_SRS",'3826')
+    }
+
+dbSRS=os.environ.get("DB_SRS",'3826')
+
+#dbConf= { "host":"192.168.11.42" ,
+#    "port":"5115",
+#    "database":"pgDMMSNS",
+#    "user":"postgres",
+#    "password":"simple000"
+#}
+
+def printcol(col):
+    print(col)
+
+
+@app.route('/')
+def hello():
+    return '?1/2/' 
+
+@app.route('/testPostgis')
+def testdb():
+    gis3d.testSelect();
+    return 'done'
+
+@app.route('/resetEv/<string:tablename>')
+def resetTableEv(tablename):
+    print('running resetEv')
+    colgeom= request.args.get('geom',default='geom')
+
+    #poi=  Updateev0 (self.updDB)
+    #gis3d.fetchTable(dbConf,
+    #      poi.sql_sel() ,
+    #      poi)
+    procSetTableEv= Db(dbConf)
+    procSetTableEv.resetTabelEv(tablename,dbSRS=dbSRS,srcgeom=colgeom,desgeom=colgeom)
+
+    return 'done'
+          
+@app.route('/getEv/<string:tablename>')
+def featureEvby84(tablename):
+   
+    limit= request.args.get('limit',default=100,type=int)
+    colgeom= request.args.get('geom',default='geom')
+    print('running getEv')
+    print(request.query_string) 
+    procGetTableEv=Db(dbConf)
+    procGetTableEv.getTableEv(tablename,limit=limit,dbSRS=dbSRS,srcgeom=colgeom,desgeom=colgeom)
+
+    return 'table={}({}-{}),limit={}'.format(tablename,colgeom,dbSRS,(limit))
+
+
+@app.route('/test') #/<string:name>')
+def hello_name():
+    proj= request.args.get('proj', default =3857 , type = int)
+    
+    print( "proj={}".format(proj))
+    moiApi= moiEvApi()
+    (result, urltext)= moiApi.test()
+    if(result.status_code == requests.codes.ok):
+         resultjs=moiParser.toJSON(result.text)
+
+
+    return "testmoi={},\n url={}".format(resultjs,urltext)
+
+@app.route('/transform')
+def transformCoord():
+    src_proj= request.args.get('src',default=3826,type=int)
+    des_proj= request.args.get('des',default=4326,type=int)
+    dx = request.args.get('x',default=0,type=float)
+    dy = request.args.get('y',default=0,type=float) 
+    result=[]
+    ret_json ={'message':'input format GET/POST ','src':3826,'des':4326,'x':0,'y':0}
+    #print( src_proj,des_proj,dx,dy)
+    trans=Coords()
+    if(src_proj == 3826 and des_proj==4326):
+         result= trans.crs_t97tow84(dx,dy) 
+         ret_json= {'x':result[0],'y':result[1],'srid':4326}
+    if(src_proj == 4326 and des_proj==3826):
+         result= trans.crs_w84tot97(dx,dy)  
+         ret_json= {'x':result[0],'y':result[1],'srid':3826} 
+    if(src_proj == des_proj):
+         ret_json= {'x':dx,'y':dy,'srid':src_proj}
+    return ret_json
+
+
+if __name__ == '__main__':
+    print (dbConf)
+    moiapi=os.environ.get("MOI_API","TW_DLA_2001084_20061226_20M_3826_DEM")
+    moikey=os.environ.get("MOI_KEY","43da4f4a-e2e0-43b0-a432-8b7975f43d9e")
+
+    print('moikey=',moikey)
+    print('moiapi=',moiapi)
+    app.run(host='0.0.0.0',port=5000)
+
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..23e965d
--- /dev/null
+++ b/config.py
@@ -0,0 +1,31 @@
+import os
+basedir = os.path.abspath(os.path.dirname(__file__))
+
+class Config(object):
+    DEBUG = False
+    TESTING = False
+    CSRF_ENABLED = True
+    SECRET_KEY = 'this-really-needs-to-be-changed'
+#    dbConf={"host": os.environ["PG_HOST"],
+#            "port": os.environ["PG_PORT"],
+#            "database": os.environ["PG_DATABASE"],
+#            "user": os.environ["PG_USER"],
+#            "password": os.environ["PG_PASS"] 
+#    }
+
+
+class ProductionConfig(Config):
+    DEBUG = False
+
+
+class StagingConfig(Config):
+    DEVELOPMENT = True
+    DEBUG = True
+
+class DevelopmentConfig(Config):
+    DEVELOPMENT = True
+    DEBUG = True
+
+
+class TestingConfig(Config):
+    TESTING = True
diff --git a/ctls.py b/ctls.py
new file mode 100644
index 0000000..68315d3
--- /dev/null
+++ b/ctls.py
@@ -0,0 +1,80 @@
+import datetime
+
+from pub.extactJSON import ParserMOI as moiParser
+from pub.queryMoi import QueryElevation as moiEvApi
+from pub.postgis import Dbconnect 
+
+from parser import Updateev0
+from parser import GetMoiEvBy84
+
+class Db():
+
+    def __init__(self,dbConf):
+        self.dbConf=dbConf
+        self.updateid=0
+        self.dtStart=datetime.datetime.now()
+        self.dtNext=datetime.datetime.now()
+
+    def resetTabelEv(self,tablename,dbSRS='3826',srcgeom='geom',desgeom='geom'):
+        #print (self.dbConf)
+        self.gis3d= Dbconnect() 
+        print('setEv') 
+        self.gis3d.tryConn(self.dbConf)
+
+        print('db ok')
+        poi=  Updateev0 (tablename,self.updDB,dbSRS=dbSRS,srcgeom=srcgeom,desgeom=desgeom) #self.writeFile)
+        
+        #other connection
+        self.gis3d.fetchTable( self.dbConf,   
+         poi.sql_sel() ,
+         fnProc=poi
+        )
+        self.gis3d.destroyConn()
+
+    def getTableEv(self,tablename,limit=100,dbSRS='3826',srcgeom='geom',desgeom='geom'):
+        
+        self.gis3d= Dbconnect()
+        print('getEv')
+
+        self.gis3d.tryConn(self.dbConf)
+
+        print('db ok,limit={},srs={}'.format(limit,dbSRS))
+        
+        poi=  GetMoiEvBy84 (tablename,self.updDB,limit=limit,fnErr=self.writeFile,dbSRS=dbSRS,srcgeom=srcgeom,desgeom=desgeom) #self.writeFile) #self.updDB) #self.writeFile)
+        #poi=  GetMoiEvBy84 (tablename,self.writeFile,limit=limit,fnErr=self.writeFile,dbSRS=dbSRS,srcgeom=srcgeom,desgeom=desgeom) #self.writeFile) #self.updDB) #self.writeFile)
+ 
+        self.dtStart=datetime.datetime.now()
+        #other connection
+        self.gis3d.fetchTable( self.dbConf,
+         poi.sql_sel() ,
+         fnProc=poi
+        )
+        print ('total {}'.format(datetime.datetime.now()-self.dtStart))
+        self.gis3d.destroyConn()
+    
+    
+    def updDB(self,sql_upd,wkt,id,table):
+        
+        #print('update id',id)
+        #self.updateid=self.updateid+1
+        if(self.updateid % 100 == 0):
+           dtnow= datetime.datetime.now()
+           print('count:',self.updateid,'{}({})({} @ {})'.format(table,id,dtnow-self.dtNext, dtnow-self.dtStart))
+           self.dtNext=datetime.datetime.now()
+        
+        self.updateid=self.updateid+1   
+        #print ('update!{}'.format(id,wkt))
+        self.gis3d.executeWithConn(sql_upd.format(wkt,id))
+#       #  print('nothing')
+
+    def writeFile(self,sql_upd,wkt,id,table):
+        #print('writefile',id)
+        print(id)
+        fname='logs/{}.{}.log'.format(table,self.dtStart.strftime('%Y%m%d_%H%M%S') )
+        print ('error@({})-->{}'.format(id,fname ) )
+        fp = open(fname, "a")
+        lines =[sql_upd.format(wkt,id),";\n"]
+        # ["One\n", "Two\n", "Three\n", "Four\n", "Five\n"]
+        fp.writelines(lines)
+        fp.close()
+
diff --git a/deployEnv/Dockerfile b/deployEnv/Dockerfile
new file mode 100644
index 0000000..bddd82e
--- /dev/null
+++ b/deployEnv/Dockerfile
@@ -0,0 +1,16 @@
+FROM python:3.8.5-buster
+
+RUN apt update && apt-get install -y python3-setuptools
+
+RUN apt install -y gdal-bin python3-gdal libgdal-dev
+
+RUN python3 -m pip install Flask==1.1.1 --user &&  python3 -m pip install autoenv==1.0.0
+RUN pip3 install --upgrade pip setuptools==45.2.0
+
+RUN pip3 install numpy pyproj MarkupSafe python-dotenv psycopg2-binary
+RUN pip3 install gdal==2.4.0 
+ADD requirements.txt .
+RUN pip3 install -r requirements.txt
+
+RUN pip3 install gunicorn
+
diff --git a/deployEnv/requirements.txt b/deployEnv/requirements.txt
new file mode 100644
index 0000000..a2a3566
--- /dev/null
+++ b/deployEnv/requirements.txt
@@ -0,0 +1,38 @@
+astroid==2.4.2
+autoenv==1.0.0
+certifi==2018.10.15
+chardet==3.0.4
+click==7.1.2
+decorator==4.3.0
+Flask==1.1.1
+idna==2.7
+ipython-genutils==0.2.0
+isort==5.4.2
+itsdangerous==1.1.0
+Jinja2==2.11.2
+jsonschema==2.6.0
+jupyter-core==4.4.0
+kafka-python==2.0.1
+lazy-object-proxy==1.4.3
+MarkupSafe==1.0
+mccabe==0.6.1
+nbformat==4.4.0
+numpy==1.15.3
+OWSLib==0.17.0
+plotly==3.3.0
+Pygments==2.2.0
+pylint==2.6.0
+pyproj==2.6.1
+python-dateutil==2.7.5
+pytz==2018.6
+PyYAML==3.13
+requests==2.20.0
+retrying==1.3.3
+Shapely==1.6.4.post2
+six==1.15.0
+toml==0.10.1
+traitlets==4.3.2
+typed-ast==1.4.1
+urllib3==1.24
+Werkzeug==1.0.1
+wrapt==1.12.1
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..5c9ca17
--- /dev/null
+++ b/package.json
@@ -0,0 +1,17 @@
+{
+  "name": "webapi",
+  "version": "1.0.0",
+  "description": "newbie",
+  "main": "index.js",
+  "scripts": {
+    "initproj": "touch app/app.py .gitignore README.md requirements.txt",
+    "install": "python3 -m pip install Flask==1.1.1 --user &&  python3 -m pip install autoenv==1.0.0",
+    "pack": "python3 -m pip freeze > requirements.txt",
+    "service":"gunicorn --bind 0.0.0.0:5000 wsgi:app",
+    "docker": "docker build -t g3d .",
+    "app": "python3 app.py",
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}
diff --git a/parser.py b/parser.py
new file mode 100644
index 0000000..876d859
--- /dev/null
+++ b/parser.py
@@ -0,0 +1,262 @@
+import requests
+
+from pub.utils import Coords
+from pub.utils import Geotext
+from pub.queryMoi import QueryElevation #as httpMoi
+from pub.extactJSON import ParserMOI as moiParser
+
+class FeatureTableParser():
+
+     def sql_sel(self):
+         sqlWhere=''
+   
+         #gid >=1000 and gid <=5000
+         if(len(self.where)):
+            sqlWhere=' where {}'.format(self.where)
+         
+         sqlGid= (
+	  'select gid from '+
+	  '( select gid,count(*) numofPoint from ( '+
+			' select gid,(dp).path[2] SN,ST_Z((dp).geom) zpoint'+
+			' from (select gid,ST_DumpPoints({}) dp from {}."{}") allpoint '.format(self.geom,self.schema,self.table)+
+		 ') allzero {} group by gid '.format(sqlWhere)+
+	  ') numofzero {} '.format(self.limit) )
+
+	  
+
+#            'select gid from ( '+
+#            'select gid,count(*) numofPoint from ( '+
+#            'select gid,ST_Z(ST_PointN( {}, generate_series(1, ST_NPoints({})))) zpoint '.format(self.geom,self.geom)+
+#            ' from {}."{}"'.format(self.schema,self.table)+
+#	    ') allzero {} group by gid '.format(sqlWhere)+
+#            ') numofzero {}'.format(self.limit) )
+         
+         sqlQuery=(
+            'SELECT gid, did, tid, oid,gtype, pt,ST_X(geom3) x,ST_Y(geom3) y,ST_Z(geom3) z '+
+            'from (   select gid,did,tid,oid,gtype,numpt, COALESCE((alldp).path[2],1) pt,(alldp).geom geom3 from ('+
+            '   select gid,did,tid,oid ,GeometryType({}) gtype,ST_NPoints({}) numpt,'.format(self.geom,self.geom) +
+            '   ST_DumpPoints({}) alldp from {}."{}"'.format(self.geom,self.schema,self.table)+
+            ' ) atpoint where gid in ( {} )) allpt order by gid ,pt '.format(sqlGid))
+ 
+
+
+#            'SELECT gid, did, tid, oid,gtype, pt,ST_X(geom3) x,ST_Y(geom3) y,ST_Z(geom3) z '+ 
+#            ' from ( SELECT gid, did, tid, oid, GeometryType({}) gtype, '.format(self.geom) +
+#            ' ST_NumPoints({})  , generate_series(1, ST_NPoints({})) pt, '.format(self.geom,self.geom)+
+#            ' ST_PointN( {}, generate_series(1, ST_NPoints({}))) geom3 '.format(self.geom,self.geom)+
+#            ' FROM {}."{}" where gid in ( '.format(self.schema,self.table)+
+#            sqlGid+
+#            ' )) allpt order by gid ,pt ')
+
+         print(sqlQuery)
+         return sqlQuery
+         #(
+         #'SELECT gid, did, tid, oid,gtype, pt,ST_X(geom3) x,ST_Y(geom3) y,ST_Z(geom3) z ' +
+         #'from ( SELECT gid, did, tid, oid, GeometryType(geom) gtype, '+
+         #'ST_NumPoints(geom)  , generate_series(1, ST_NPoints(geom)) pt, '+
+         #'ST_PointN( geom, generate_series(1, ST_NPoints(geom))) geom3 '+
+         #' FROM {}."{}" where gid in (select gid from {}."{}" {} ) ) allpt order by gid ,pt '.format(self.schema,self.table,self.schema,self.table,sqlwhere)  )
+
+     def sql_upd(self,col_geom='geom'):
+         return 'UPDATE {}."{}" set {}=ST_GeomFromEWKT(\'SRID={};{}\') where gid={}'.format(self.schema,self.table,col_geom,self.dbSRS,'{}','{}') #wkt,id)
+
+     def colnames(self):
+         return 'gid, did, tid, oid, gtype, pt, x, y, z'
+
+     def colforgeotext(self,clos):
+         return [(cols[0],cols[4],cols[5],cols[6],cols[7],cols[8])]
+
+     def __init__(self,tablename,schema='gis3d',limit=100,where='zpoint=0',dbSRS='3826',geom='geom'):
+         self.geom=geom
+         self.schema=schema
+         self.table=tablename
+         self.where=where
+         self.limit=''
+         self.dbSRS=dbSRS
+
+         if(limit>0):
+             self.limit=' limit {}'.format(limit)
+           
+
+
+class Updateev0():
+     
+     def add(self,cols):
+         
+         self.geotext.add(cols[0],cols[4],cols[5],cols[6],cols[7],cols[8])
+    
+     #update DB 
+     def done(self,msg):
+         self.geotext.done(msg)
+
+     def updateto0(self,allpts):
+         newpts=[];
+         for onept in allpts:
+             newpts.append([onept[0],onept[1],0])
+         return newpts
+    
+     def upDb(self,pp4):
+         #call ext
+         #print(pp4[0],pp4[2])
+         #print(pp4)
+         if(self.fnAfter != None):
+             self.fnAfter(self.sql_upd(), self.buildWKT(pp4[1],pp4[2]),pp4[0],self.table)
+ 
+     def buildWKT(self,gtype,wktpt):
+         resultwkt=''
+         if(gtype=='POINT'):
+             resultwkt='POINT({})'.format(wktpt)
+         if(gtype=='POLYGON'):
+             resultwkt='POLYGON(({}))'.format(wktpt)
+         if(gtype=='LINESTRING'):
+             resultwkt='LINESTRING({})'.format(wktpt)
+         
+         return resultwkt
+     def sql_sel(self):
+         return self.ft.sql_sel()
+
+     def sql_upd(self):
+         return self.ft.sql_upd(self.desgeom)
+
+
+     def __init__(self,tablename,fnAfter=None,fnErr=None,limit=100,dbSRS='3826',desgeom='geom',srcgeom='geom'):    
+         print('init')
+         self.table=tablename
+         self.fnAfter=fnAfter
+         self.fnErr=fnErr
+         self.geotext=Geotext(self.updateto0,self.upDb)
+         self.ft=FeatureTableParser(tablename,limit=limit,dbSRS=dbSRS,geom=srcgeom)
+         self.desgeom=desgeom
+
+
+class GetMoiEvBy84():
+
+     def add(self,cols):
+
+         self.geotext.add(cols[0],cols[4],cols[5],cols[6],cols[7],cols[8])
+     
+     #updatedb 
+     def done(self,msg):
+         self.geotext.done(msg)
+
+     #querybyimoi
+     def procmoi(self,allpts):
+         newpts=[];
+         #print('coming',allpts)
+         for onept in allpts:
+             if(len(onept)>2):
+                    newpts.append(self.towgs84(onept[0],onept[1],onept[2]))
+             else:
+                    if(self.fnErr!=None):
+                         resultTxt='moi->{}  / {}'.format(onept,allpts)
+
+                         self.fnErr('[error] {}, id->{}',resultTxt,'?','moi')
+
+                    print('error@moi@{},row={}'.format(onept,allpts) )
+
+         #print(self.makempoint(newpts))
+         
+         return newpts
+     #parsertoWgs84
+     def towgs84(self,dx,dy,dz):
+         return self.coords.crs_t97tow84(dx,dy,dz)
+
+     def makempoint(self,allpts):
+         resultText='MULTIPOINT(({}))'
+         resultOne=''
+         for onept in allpts:
+             if ( len(resultOne)>0):
+                  resultOne+=','
+             resultOne+= ' '.join ('%s' %id for id in onept)
+         return resultText.format(resultOne)
+     
+     def printit(self,pp4):
+         print(pp4)
+
+     def queryBy(self,pp4):
+         
+         #queryMoi
+         result=self.httpMoi.fromMoi("MULTIPOINT({})".format(pp4[2]))
+         if(result.status_code == requests.codes.ok):
+             resultjs=moiParser.toJSON(result.text)
+             resultmoiarray=moiParser.moiJsonToArray(resultjs)
+             #print('moi=',resultmoiarray)
+             #print('org=',pp4)
+
+             if (len(resultmoiarray)==0):
+                    if(self.fnErr!=None):
+                         resultTxt='moi->{},our->{}'.format(resultjs,'gid:{},to84:({}),from97:({})'.format(pp4[0],pp4[2], pp4[3]))
+
+                         self.fnErr('[error] {}, id->{}',resultTxt,pp4[0],self.table)
+                    
+                    print('error@parser@{},id={}'.format(self.table,pp4[0]) )
+                    
+
+                    return
+
+             if (self.fnAfter != None):
+                    self.fnAfter(self.sql_upd(),
+                         self.buildWKT(  pp4[1], self.makeSqlWktWithEv(pp4[3],resultmoiarray)) , pp4[0 ],self.table)
+
+     def checkDistinctSquare(self,x0,y0,x1,y1):
+         return (x0-x1)*(x0-x1)+(y0-y1)*(y0-y1)
+
+     def makeSqlWktWithEv(self,xyorg,xymoi):
+         lenOfxyorg=len(xyorg)
+         #print('len',lenOfxyorg)
+         newPts=[]
+
+         for idxPt in range(lenOfxyorg):
+             diff= self.checkDistinctSquare(
+                    float(xyorg[idxPt][0]),float(xyorg[idxPt][1]),
+                    float(xymoi[idxPt][0]),float(xymoi[idxPt][1]))
+             if(diff>1):
+                    print( 'diff xy({}> 1m)'.format( diff ))
+
+             newPts.append([xyorg[idxPt][0],xyorg[idxPt][1],xymoi[idxPt][2]])
+         resultText=''
+         for pt in newPts:
+             if(len(resultText)>0):
+                 resultText+=','
+             thisrow= ' '.join ('%s' %id for id in pt)
+             resultText+= thisrow
+         #print('wkt->',resultText)
+         return (resultText)
+             
+
+     def upDb(self,pp4):
+         #call ext
+         #print(pp4[0],pp4[2])
+         if(self.fnAfter != None):
+             self.fnAfter(self.sql_upd(), self.buildWKT(pp4[1],pp4[2]),pp4[0])
+
+     def buildWKT(self,gtype,wktpt):
+         resultwkt=''
+         if(gtype=='POINT'):
+             resultwkt='POINTZ({})'.format(wktpt)
+         if(gtype=='POLYGON'):
+             resultwkt='POLYGONZ(({}))'.format(wktpt)
+         if(gtype=='LINESTRING'):
+             resultwkt='LINESTRINGZ({})'.format(wktpt)
+
+         return resultwkt
+     def sql_sel(self):
+         return self.ft.sql_sel()
+
+     def sql_upd(self):
+         return self.ft.sql_upd(self.desgeom)
+
+
+
+     def __init__(self,tablename,fnAfter=None,fnErr=None,limit=100,dbSRS='3826',desgeom='geom',srcgeom='geom'):   
+         print('init')
+         self.coords=Coords(default97=dbSRS)
+         self.httpMoi=QueryElevation()
+         #
+         self.geotext=Geotext(self.procmoi,self.queryBy)
+         self.table=tablename
+         self.fnAfter=fnAfter
+         self.fnErr=fnErr
+         self.ft=FeatureTableParser(tablename,limit=limit,dbSRS=dbSRS,geom=srcgeom)
+         self.desgeom=desgeom
+
diff --git a/pub/extactJSON.py b/pub/extactJSON.py
new file mode 100644
index 0000000..f6d6760
--- /dev/null
+++ b/pub/extactJSON.py
@@ -0,0 +1,30 @@
+import xml.etree.ElementTree as ET
+import json
+
+class ParserMOI:
+      """ A funny format convert """
+      def findbyelement():
+          return './string'
+
+      def toJSON(xmlFromAPI):
+          xmlelm= ET.fromstring(xmlFromAPI)
+          #print('-------')
+          #print(xmlelm)
+          #print('->->') 
+          result=xmlelm
+          #print(result.text)
+          return json.loads(result.text)
+      # ss='{"count": "2", "pointArray": [{"x": "300431.466453", "y": "2765416.019419", "z": "13.650453"}, {"x": "300428.019514", "y": "2765415.408211", "z": "13.498476"}]}'
+      def moiJsonToArray(moijson):
+          resultArray=[]
+          if 'pointArray' not in moijson:
+              print('error!',moijson)
+              return []
+
+          allxyz=moijson.get('pointArray')
+          
+           
+          for row in allxyz:
+              resultArray.append([row['x'],row['y'],row['z']])
+          return resultArray
+          
diff --git a/pub/postgis.py b/pub/postgis.py
new file mode 100644
index 0000000..53d8cc6
--- /dev/null
+++ b/pub/postgis.py
@@ -0,0 +1,180 @@
+
+import psycopg2
+
+
+class Dbconnect():
+
+      def testSelect(self):
+          conn = psycopg2.connect(host='192.168.11.42',port='5115',database='pgDMMSNS', user='postgres',password='simple000')
+          print('connected')
+#SELECT gid, did, tid, oid, cid, lid, level, symcolor, symweight, symstyle, geom FROM gis3d."fsc-401-c-0";
+
+          cursor = conn.cursor()
+          cursor.execute('SELECT gid, did, tid, oid, geom FROM gis3d."fsc-401-c-0"')
+          rows =cursor.fetchall()
+          for row in rows:
+              print ('id=',row[0], ',gid=',row[1],',tid=',row[2],',oid=',row[3],'\n')
+          cursor.close()
+          conn.close()
+      #select must offline
+      def fetchTableWithConn(self,dbQuery,fnProc=None):
+          arrayRow=[]
+          try:
+             cursor = self.dbConn.cursor()
+             cursor.execute(dbQuery)
+             rows = cursor.fetchall()
+             
+             arrayRow=rows
+             #for row in rows:
+             #     #print(row)
+             #     #print(fnProc)
+             #     if(fnProc!=None):
+             #         if(fnProc.add !=None):
+             #             fnProc.add( (row) )
+
+          except(Exception, psycopg2.Error) as error:
+             print("error connect",error)
+             #conn =None
+          finally:
+             #if(fnProc!=None):
+             #    if(fnProc.done !=None):
+             #        fnProc.done( (dbQuery) )
+             cursor.close()
+             #read it
+          print('close cursor')
+          for row in arrayRow:
+             if(fnProc!=None):
+                  if(fnProc.add != None):
+                       fnProc.add ( (row) )
+                  lastrw=row
+          if(fnProc !=None):
+             if(fnProc.done != None):
+                  fnProc.done({'sql':dbQuery,'row':lastrw} )         
+
+      def fetchTable(self,dbConf,dbQuery,fnProc=None):
+          print('try database')
+          #print('sqlis->',dbQuery)
+          
+          try:
+             conn = psycopg2.connect(
+                 host=dbConf['host'], 
+                 port=dbConf['port'], 
+                 database=dbConf['database'], 
+                 user=dbConf['user'], 
+                 password=dbConf['password']
+             )
+             cursor = conn.cursor()
+             cursor.execute(dbQuery)
+             rows = cursor.fetchall()
+             lastrw={}
+             for row in rows: 
+                 #print(row)
+                 #print(fnProc)
+                 if(fnProc!=None):
+                     if(fnProc.add !=None):
+                         fnProc.add( (row) )
+                 lastrw=row
+
+          except(Exception, psycopg2.Error) as error:
+             print("error connect",error)
+             conn =None
+          finally:
+             if(fnProc!=None):
+                 if(fnProc.done !=None):
+                     fnProc.done( ({'sql':dbQuery,'row':lastrw}) )
+
+             if( conn != None):
+                 cursor.close()
+                 conn.close()
+
+      def executeWithConn(self,dbSql,fnProc=None):
+          try:
+             cursor = self.dbConn.cursor()
+
+             cursor.execute(dbSql)
+             #record = cursor.fetchone()
+
+             if(fnProc!=None):
+                 if(fnProc.add !=None):
+                     fnProc.add ( {} )
+
+             #self.dbConn.commit()
+
+          except(Exception, psycopg2.Error) as error:
+             print("error connect",error,dbSql)
+          finally:
+             if(fnProc!=None):
+                 if(fnProc.done !=None):
+                     fnProc.done( (dbSql) )
+             cursor.close()
+
+      def execute(self,dbConf,dbSql,fnProc=None):
+          print('try exec-database')
+          #print('sqlis->',dbQuery)
+
+          try:
+             conn = psycopg2.connect(
+                 host=dbConf['host'],
+                 port=dbConf['port'],
+                 database=dbConf['database'],
+                 user=dbConf['user'],
+                 password=dbConf['password']
+             )
+
+             cursor = conn.cursor()
+
+             cursor.execute(dbSql)
+             #record = cursor.fetchone()
+
+             if(fnProc!=None):
+                 if(fnProc.add !=None):
+                     fnProc.add ( {} )
+ 
+             conn.commit()
+             print('commit')
+          except(Exception, psycopg2.Error) as error:
+             print("error connect",error)
+             conn =None
+          finally:
+             if(fnProc!=None):
+                 if(fnProc.done !=None):
+                     fnProc.done( (dbSql) )
+             if( conn != None):
+                 cursor.close()
+                 conn.close()
+
+      def tryConn(self, dbConf):
+          print('try database')
+          print(dbConf)
+          print(self)
+
+          try:
+             if (self.dbConn != None):
+                 self.destroyConn()
+
+             self.dbConn = psycopg2.connect(
+                 host=dbConf['host'],
+                 port=dbConf['port'],
+                 database=dbConf['database'],
+                 user=dbConf['user'],
+                 password=dbConf['password'],
+                
+             )
+             self.dbConn.set_session(autocommit=True)
+
+          except(Exception, psycopg2.Error) as error:
+             print("error connect",error)
+             self.dbConn=None
+
+      def destroyConn(self):
+          try:
+             if( self.dbConn != None):
+                self.dbConn.close()
+
+          except(Exception, psycopg2.Error) as error:
+             print('close connect')
+          finally:
+             self.dbConn = None
+
+      def __init__(self): 
+          self.dbConn=None
diff --git a/pub/queryMoi.py b/pub/queryMoi.py
new file mode 100644
index 0000000..68f6603
--- /dev/null
+++ b/pub/queryMoi.py
@@ -0,0 +1,44 @@
+import os
+import requests
+
+class QueryElevation():
+#      urlPattern='https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey=&wkt=MULTIPOINT(121.54%2024.44,121.54%2024.43,121.541%2024.43)&data=TW_DLA_20010814_20061226_20M_3826_DEM'
+      
+      def test(self):
+          moitest='https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey=&wkt=MULTIPOINT(121.54%2024.44,121.54%2024.43,121.541%2024.43)&data=TW_DLA_20010814_20061226_20M_3826_DEM'
+          #s=requests.get(moitest)
+          proxy=self.getProxy()
+          if (proxy == None):
+             s= requests.get(moitest)
+          else:
+             s= requires.get(moitest,proxies=proxy)
+
+          return (s , moitest)
+
+      def fromMoi(self,wkt):
+          #print('getwkt',wkt)
+          urlExec=self.urlPattern.format(self.moi_key,wkt,self.moi_api)
+          #print('url:',urlExec)
+          proxy=self.getProxy()
+          if (proxy == None):
+             s= requests.get(urlExec)
+          else:
+             s= requests.get(urlExec,proxies=proxy)
+
+
+          return s
+      def getProxy(self):
+          if (len(self.httpproxy)+len(self.httpsproxy)>0):
+             return {"http":self.httpproxy,"https":self.httpsproxy}
+          return None
+
+      def __init__(self):
+          self.httpproxy=os.environ.get("HTTP_PROXY","")
+          self.httpsproxy=os.environ.get("HTTPS_PROXY","")
+          self.moi_api=os.environ.get("MOI_API","TW_DLA_2001084_20061226_20M_3826_DEM")
+          self.moi_key=os.environ.get("MOI_KEY","43da4f4a-e2e0-43b0-a432-8b7975f43d9e")
+
+          #https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey=43da4f4a-e2e0-43b0-a432-8b7975f43d9e&wkt=MULTIPOINT((121.58364097028957 25.010770192742356))&data=TW_DLA_20110101_20161101_1M_3826_DEM
+
+          self.urlPattern='https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey={}&wkt={}&data={}' 
+#TW_DLA_2001084_20061226_20M_3826_DEM' 
diff --git a/pub/utils.py b/pub/utils.py
new file mode 100644
index 0000000..4156a3e
--- /dev/null
+++ b/pub/utils.py
@@ -0,0 +1,94 @@
+import datetime
+
+from pyproj.crs import CRS
+from pyproj import Transformer
+
+#wgs84=CRS.from_epsg(4326)
+#twd97=CRS.from_epsg(3826)
+
+#trans97to84=Transformer.from_crs(twd97,wgs84)
+#trans84to97=Transformer.from_crs(wgs84,twd97)
+
+class Coords():
+
+     def crs_t97tow84(self,dx,dy,dz=0,in3d=False):
+         xyz= self.trans97to84.transform(dx,dy)
+         if( in3d ):
+           return [xyz[1] ,xyz[0],dz]
+         return [xyz[1] ,xyz[0]]
+
+     def crs_w84tot97(self,dx,dy,dz=0,in3d=False):
+         xyz=  self.trans84to97.transform(dy,dx)
+         if( in3d ): 
+           return [xyz[0] ,xyz[1],dz]
+         return [xyz[0] ,xyz[1]]
+     
+     def __init__(self,default97='3826'):
+         self.wgs84=CRS.from_epsg(4326)
+         self.twd97=CRS.from_epsg(int(default97))
+
+         self.trans97to84=Transformer.from_crs(self.twd97,self.wgs84)
+         self.trans84to97=Transformer.from_crs(self.wgs84,self.twd97)
+
+class Geotext():
+ 
+     def add(self,id,gtype,sn,dx,dy,dz):
+         #print(id,':',sn)
+         #print(dx,dy,dz)
+         if(id != self.id):
+            if(self.sn !=0):
+               self.done()
+         self.id=id
+         self.gtype=gtype
+         self.sn=sn
+         if(len(self.points)>=sn ):
+            print('something wrong!!! sn < point!({})'.format(id))
+        
+         self.points.append([dx,dy,dz])
+         self.dtStart=datetime.datetime.now()
+
+     def clearpoint(self):
+         self.id=''
+         self.gtype=''
+         self.points.clear()
+         self.org.clear()
+
+     def done(self,msg={}):
+         self.org=self.points
+         if (self.fnReady !=None):
+            self.points=self.fnReady(self.points)
+         #print(self.makewkt())
+         #print('id={}'.format(self.id))
+         if (self.fnNext !=None):
+            self.fnNext(self.makewktpt())
+         print('id={},({})'.format(self.id,datetime.datetime.now()-self.dtStart))
+         if(len(self.points) != self.sn):
+            print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') 
+            print(msg)
+         self.sn=0
+         self.points.clear()
+         self.org.clear()
+
+     def makewktpt(self):
+         resultText=''
+         for pt in self.points:
+             if(len(resultText)>0):
+                 resultText+=','
+             thisrow= ' '.join ('%s' %id for id in pt)
+             resultText+= thisrow
+         #print('wkt->',resultText)
+         return (self.id,self.gtype,resultText,self.org)
+
+     def __init__(self,fnReady=None,fnNext=None):
+         print('try init')
+         self.gtype=''
+         self.points=[]
+         self.org=[]
+         self.id=''
+         self.sn=0
+         self.fnNext=fnNext
+         self.fnReady=fnReady
+         self.dtStart=datetime.datetime.now()
+    
+
+
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..a2a3566
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,38 @@
+astroid==2.4.2
+autoenv==1.0.0
+certifi==2018.10.15
+chardet==3.0.4
+click==7.1.2
+decorator==4.3.0
+Flask==1.1.1
+idna==2.7
+ipython-genutils==0.2.0
+isort==5.4.2
+itsdangerous==1.1.0
+Jinja2==2.11.2
+jsonschema==2.6.0
+jupyter-core==4.4.0
+kafka-python==2.0.1
+lazy-object-proxy==1.4.3
+MarkupSafe==1.0
+mccabe==0.6.1
+nbformat==4.4.0
+numpy==1.15.3
+OWSLib==0.17.0
+plotly==3.3.0
+Pygments==2.2.0
+pylint==2.6.0
+pyproj==2.6.1
+python-dateutil==2.7.5
+pytz==2018.6
+PyYAML==3.13
+requests==2.20.0
+retrying==1.3.3
+Shapely==1.6.4.post2
+six==1.15.0
+toml==0.10.1
+traitlets==4.3.2
+typed-ast==1.4.1
+urllib3==1.24
+Werkzeug==1.0.1
+wrapt==1.12.1
diff --git a/wsgi.py b/wsgi.py
new file mode 100644
index 0000000..d89957f
--- /dev/null
+++ b/wsgi.py
@@ -0,0 +1,5 @@
+from app import app
+
+if __name__ == '__main__':
+    app.run()
+

--
Gitblit v0.0.0-SNAPSHOT