Skip to content
This repository was archived by the owner on Jul 20, 2020. It is now read-only.

Commit b71a831

Browse files
committed
Merge remote-tracking branch 'refs/remotes/project-open-data/master'
2 parents 6f58b80 + 1d7b2cc commit b71a831

25 files changed

Lines changed: 973 additions & 40 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.c9revisions
22
*~
33
node_modules
4+
*.pyc

Install/esri2open/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
from esri2open import toOpen, writeFile, closeUp, closeJSON
2-
from prepare import prepareFile, prepareGeoJSON
1+
from esri2open import toOpen, writeFile, closeUp, closeJSON,closeTOPOJSON
2+
from prepare import prepareFile, prepareGeoJSON,prepareTOPO
3+
from utilities import getExt,getName

Install/esri2open/esri2open.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,27 @@ def closeCSV(out):
3333
out[1].close()
3434
return True
3535

36+
def closeTOPOJSON(out):
37+
file = open(out['out'],'w')
38+
out['topo'].dump(file)
39+
file.close()
40+
return True
41+
3642
def closeUp(out,fileType):
3743
if fileType == "geojson":
3844
return closeJSON(out)
3945
elif fileType == "csv":
4046
return closeCSV(out)
41-
if fileType == "json":
47+
elif fileType == "json":
4248
return closeJSON(out)
49+
elif fileType == "topojson":
50+
return closeTOPOJSON(out)
4351
else:
4452
return False
4553

4654
#this is the meat of the function, we could put it into a seperate file if we wanted
47-
def writeFile(outArray,featureClass,fileType,includeGeometry, first=True):
48-
parser = parse(outArray,featureClass,fileType,includeGeometry,first)
55+
def writeFile(outArray,featureClass,fileType,includeGeometry, first=True, outName = False):
56+
parser = parse(outArray,featureClass,fileType,includeGeometry,first,outName)
4957
#wrap it in a try so we don't lock the database
5058
try:
5159
for row in parser.rows:
@@ -71,7 +79,7 @@ def toOpen(featureClass, outJSON, includeGeometry="geojson"):
7179
AddMessage("this filetype doesn't make sense")
7280
return
7381
#geojson needs geometry
74-
if fileType=="geojson":
82+
if fileType in ("geojson", "topojson"):
7583
includeGeometry="geojson"
7684
elif fileType=="sqlite":
7785
includeGeometry="well known binary"

Install/esri2open/parseGeometry.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ def getParseFunc(shpType, geo):
206206
fun = parseMultiPolygon
207207
else:
208208
fun = parseMultiPatch
209-
if geo=="geojson":
210-
return fun
211-
elif geo=="well known text":
212-
return getWKTFunc(fun)
209+
210+
if geo=="well known text":
211+
return getWKTFunc(fun)
212+
else:
213+
return fun

Install/esri2open/parseRow.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from utilities import listFields, getShp, getOID, statusMessage, parseProp, makeInter
1+
from utilities import listFields, getShp, getOID, statusMessage, parseProp, makeInter,getName
22
from arcpy import SpatialReference, SearchCursor
33
from parseGeometry import getParseFunc
44
from json import dump
@@ -7,7 +7,7 @@
77
wgs84="GEOGCS['GCS_WGS_1984',DATUM['D_WGS_1984',SPHEROID['WGS_1984',6378137.0,298.257223563]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]];-400 -400 1000000000;-100000 10000;-100000 10000;8.98315284119522E-09;0.001;0.001;IsHighPrecision"
88

99
class parse:
10-
def __init__(self,outFile,featureClass,fileType,includeGeometry, first=True):
10+
def __init__(self,outFile,featureClass,fileType,includeGeometry, first=True, outName=False):
1111
self.outFile = outFile
1212
self.fileType = fileType
1313
#first we set put the local variables we'll need
@@ -33,6 +33,13 @@ def __init__(self,outFile,featureClass,fileType,includeGeometry, first=True):
3333
self.parse = self.parseJSON
3434
elif fileType=="sqlite":
3535
self.parse = self.parseSqlite
36+
elif fileType=="topojson":
37+
self.parse = self.parseTOPOJSON
38+
if outName:
39+
self.oName=outName
40+
else:
41+
self.oName = getName(featureClass)
42+
self.topo = self.outFile['topo'].object_factory(self.oName)
3643

3744
def cleanUp(self,row):
3845
del row
@@ -48,6 +55,9 @@ def parseCSV(self,row):
4855
fc["geometry"]=self.parseGeo(row.getValue(self.shp))
4956
except:
5057
return
58+
for key in fc:
59+
if isinstance(fc[key],unicode):
60+
fc[key] = fc[key].encode('utf_8')
5161
self.outFile[0].writerow(fc)
5262

5363
def parseGeoJSON(self,row):
@@ -73,6 +83,23 @@ def parseGeoJSON(self,row):
7383
self.outFile.write(",")
7484
dump(fc,self.outFile)
7585

86+
def parseTOPOJSON(self,row):
87+
#more messages
88+
self.status.update()
89+
fc={"type": "Feature"}
90+
if self.parseGeo:
91+
try:
92+
fc["geometry"]=self.parseGeo(row.getValue(self.shp))
93+
except:
94+
return
95+
else:
96+
raise NameError("we need geometry for topojson")
97+
fc["id"]=row.getValue(self.oid)
98+
fc["properties"]=parseProp(row,self.fields, self.shp)
99+
if fc["geometry"]=={}:
100+
return
101+
self.topo(fc)
102+
76103
def parseJSON(self,row):
77104
#more messages
78105
self.status.update()

Install/esri2open/prepare.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from utilities import listFields,getShp, parseFieldType
33
from sqlite3 import Connection
44
from os.path import splitext, split
5+
from topojson import Topology
56

67
def prepareCSV(outJSON,featureClass,fileType,includeGeometry):
78
shp=getShp(featureClass)[0]
@@ -58,6 +59,10 @@ def prepareJSON(outJSON,*args):
5859
out.write("""{"docs":[""")
5960
return out
6061

62+
def prepareTOPO(outJSON,*args):
63+
topo = Topology()
64+
return {"topo":topo,'out':outJSON}
65+
6166
def prepareFile(outJSON,featureClass,fileType,includeGeometry):
6267
if fileType == "geojson":
6368
return prepareGeoJSON(outJSON,featureClass,fileType,includeGeometry)
@@ -67,5 +72,7 @@ def prepareFile(outJSON,featureClass,fileType,includeGeometry):
6772
return prepareJSON(outJSON,featureClass,fileType,includeGeometry)
6873
elif fileType == "sqlite":
6974
return prepareSqlite(outJSON,featureClass,fileType,includeGeometry)
75+
elif fileType == "topojson":
76+
return prepareTOPO(outJSON,featureClass,fileType,includeGeometry)
7077
else:
7178
return False
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from topology import Topology

Install/esri2open/topojson/arcs.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from hashtable import Hashtable
2+
from os import remove
3+
import shelve
4+
from tempfile import mkdtemp
5+
from hashlib import sha1
6+
from utils import point_compare
7+
class Arcs:
8+
def __init__(self,Q):
9+
self.coincidences = Hashtable(Q * 10)
10+
self.arcsByPoint = Hashtable(Q * 10)
11+
self.pointsByPoint = Hashtable(Q * 10)
12+
self.arc_db_path=mkdtemp()+'/arc_db'
13+
self.arcs= shelve.open(self.arc_db_path)
14+
#self.arcs={}
15+
self.length=0
16+
self.storage_path = mkdtemp()+'/db'
17+
self.db = shelve.open(self.storage_path)
18+
#self.db={}
19+
def get_index(self,point):
20+
return self.pointsByPoint.get(point)
21+
def get_point_arcs(self,point):
22+
return self.arcsByPoint.get(point)
23+
def coincidence_lines(self,point):
24+
return self.coincidences.get(point)
25+
def peak(self,point):
26+
return self.coincidences.peak(point)
27+
def push(self,arc):
28+
self.arcs[str(self.length)]=arc
29+
self.length+=1
30+
return self.length
31+
def close(self):
32+
#pass
33+
self.db.close()
34+
remove(self.storage_path)
35+
self.arcs.close()
36+
remove(self.arc_db_path)
37+
def get_hash(self,arc):
38+
ourhash = sha1()
39+
ourhash.update(str(arc))
40+
return ourhash.hexdigest()
41+
def check(self,arcs):
42+
a0 = arcs[0]
43+
a1 = arcs[-1]
44+
point = a0 if point_compare(a0, a1) < 0 else a1
45+
point_arcs = self.get_point_arcs(point)
46+
h = self.get_hash(arcs)
47+
if h in self.db:
48+
return int(self.db[h])
49+
else:
50+
index = self.length
51+
point_arcs.append(arcs)
52+
self.db[h]=index
53+
self.db[self.get_hash(list(reversed(arcs)))]=~index
54+
self.push(arcs)
55+
return index
56+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from mytypes import Types
2+
class Bounds(Types):
3+
def __init__(self):
4+
self.x0=self.y0=float('inf')
5+
self.x1=self.y1=-float('inf')
6+
def point (self,point):
7+
x = point[0]
8+
y = point[1]
9+
if x < self.x0:
10+
self.x0 = x
11+
if x > self.x1:
12+
self.x1 = x
13+
if y < self.y0:
14+
self.y0 = y
15+
if y > self.y1:
16+
self.y1 = y
17+
def bound(objects):
18+
b=Bounds()
19+
b.obj(objects)
20+
return b
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Clock:
2+
def __init__(self,area):
3+
self.area=area
4+
def clock(self,feature):
5+
if 'geometries' in feature:
6+
feature['geometries'] = map(self.clock_geometry,feature['geometries'])
7+
elif 'geometry' in feature:
8+
feature['geometry']=self.clock_geometry(feature['geometry'])
9+
return feature
10+
def clock_geometry(self,geo):
11+
if 'type' in geo:
12+
if geo['type']=='Polygon' or geo['type']=='MultiLineString':
13+
geo['coordinates'] = self.clockwise_polygon(geo['coordinates'])
14+
elif geo['type']=='MultiPolygon':
15+
geo['coordinates'] = map(lambda x:self.clockwise_polygon(x),geo['coordinates'])
16+
elif geo['type']=='LineString':
17+
geo['coordinates'] = self.clockwise_ring(geo['coordinates'])
18+
return geo
19+
def clockwise_polygon(self,rings):
20+
return map(lambda x:self.clockwise_ring(x),rings)
21+
def clockwise_ring(self,ring):
22+
if self.area(ring) > 0:
23+
return list(reversed(ring))
24+
else:
25+
return ring

0 commit comments

Comments
 (0)