def testTopologyTwoVertices(self): topology = TerrainTopology() topology.addVertices(vertices_1) topology.addVertices(vertices_2) topology.create() self.assertTrue(len(topology.vertices) == 5) self.assertTrue(len(topology.faces) == 2) # Make sure no extra vertice is inserted self.assertTrue(topology.vertices[1][0] == vertices_2[0][0]) self.assertTrue(topology.vertices[1][1] == vertices_2[0][1]) self.assertTrue(topology.vertices[1][2] == vertices_2[0][2]) self.assertTrue(topology.faces[1][0] == 1) self.assertTrue(topology.faces[1][1] == 3) self.assertTrue(topology.faces[1][2] == 4) self.assertTrue(len(topology.indexData) == 6) self.assertTrue(len(topology.uVertex) == 5) self.assertTrue(len(topology.vVertex) == 5) self.assertTrue(len(topology.hVertex) == 5) self.assertTrue(topology.minLon == 1.2) self.assertTrue(topology.minLat == 1.1) self.assertTrue(topology.minHeight == 1.1) self.assertTrue(topology.maxLon == 3.2) self.assertTrue(topology.maxLat == 3.1) self.assertTrue(topology.maxHeight == 4.5)
def testTopologyOneVertex(self): topology = TerrainTopology() topology.addVertices(vertices_1) topology.create() self.assertTrue(len(topology.vertices) == 3) self.assertTrue(len(topology.faces) == 1) self.assertTrue(topology.vertices[0][0] == vertices_1[0][0]) self.assertTrue(topology.vertices[0][1] == vertices_1[0][1]) self.assertTrue(topology.vertices[0][2] == vertices_1[0][2]) self.assertTrue(topology.vertices[1][0] == vertices_1[1][0]) self.assertTrue(topology.vertices[1][1] == vertices_1[1][1]) self.assertTrue(topology.vertices[1][2] == vertices_1[1][2])
from forge.terrain import TerrainTile from forge.terrain.topology import TerrainTopology from forge.lib.shapefile_utils import ShpToGDALFeatures from forge.lib.global_geodetic import GlobalGeodetic basename = '7_133_98' directory = '.tmp' extension = '.terrain' curDir = os.getcwd() filePathSource = '%s/forge/data/shapefile-features/%s.shp' % (curDir, basename) filePathTarget = '%s/%s%s' % (directory, basename, extension) shapefile = ShpToGDALFeatures(shpFilePath=filePathSource) features = shapefile.__read__() terrainTopo = TerrainTopology(features=features) terrainTopo.fromGDALFeatures() terrainFormat = TerrainTile() geodetic = GlobalGeodetic(True) zxy = basename.split('_') bounds = geodetic.TileBounds(float(zxy[1]), float(zxy[2]), float(zxy[0])) terrainFormat.fromTerrainTopology(terrainTopo, bounds) terrainFormat.toFile(filePathTarget) # Display SwissCoordinates terrainFormat.computeVerticesCoordinates(epsg=21781) print terrainFormat
from forge.terrain.topology import TerrainTopology from forge.lib.shapefile_utils import ShpToGDALFeatures from forge.lib.global_geodetic import GlobalGeodetic basename = '7_133_98' directory = '.tmp' extension = '.terrain' curDir = os.getcwd() filePathSource = '%s/forge/data/shapefile-features/%s.shp' % (curDir, basename) filePathTarget = '%s/%s%s' % (directory, basename, extension) shapefile = ShpToGDALFeatures(shpFilePath=filePathSource) features = shapefile.__read__() terrainTopo = TerrainTopology(features=features) terrainTopo.fromGDALFeatures() terrainFormat = TerrainTile() geodetic = GlobalGeodetic(True) zxy = basename.split('_') bounds = geodetic.TileBounds(float(zxy[1]), float(zxy[2]), float(zxy[0])) terrainFormat.fromTerrainTopology(terrainTopo, bounds) terrainFormat.toFile(filePathTarget) # Display SwissCoordinates terrainFormat.computeVerticesCoordinates(epsg=21781) print terrainFormat
def createTile(tile): session = None pid = os.getpid() try: (bounds, tileXYZ, t0, dbConfigFile, bucketBasePath, hasLighting, hasWatermask) = tile db = DB(dbConfigFile) with db.userSession() as session: bucket = getBucket() # Get the model according to the zoom level model = modelsPyramid.getModelByZoom(tileXYZ[2]) watermask = [] if hasWatermask: lakeModel = modelsPyramid.getLakeModelByZoom(tileXYZ[2]) query = session.query( lakeModel.watermaskRasterize(bounds).label('watermask') ) for q in query: watermask = q.watermask # Get the interpolated point at the 4 corners # 0: (minX, minY), 1: (minX, maxY), 2: (maxX, maxY), 3: (maxX, minY) pts = [ (bounds[0], bounds[1], 0), (bounds[0], bounds[3], 0), (bounds[2], bounds[3], 0), (bounds[2], bounds[1], 0) ] def toSubQuery(x): return session.query( model.id, model.interpolateHeightOnPlane(pts[x]) ).filter( and_( model.bboxIntersects(createBBox(pts[x], 0.01)), model.pointIntersects(pts[x]) ) ).subquery('p%s' % x) subqueries = [toSubQuery(i) for i in range(0, len(pts))] # Get the height of the corner points as postgis cannot properly # clip a polygon cornerPts = {} step = 2 j = step query = session.query(*subqueries) for q in query: for i in range(0, len(q), step): sub = q[i:j] j += step cornerPts[sub[0]] = list( to_shape(WKBElement(sub[1])).coords ) # Clip using the bounds clippedGeometry = model.bboxClippedGeom(bounds) query = session.query( model.id, clippedGeometry.label('clip') ).filter(model.bboxIntersects(bounds)) terrainTopo = TerrainTopology(hasLighting=hasLighting) for q in query: coords = list(to_shape(q.clip).exterior.coords) if q.id in cornerPts: pt = cornerPts[q.id][0] for i in range(0, len(coords)): c = coords[i] if c[0] == pt[0] and c[1] == pt[1]: coords[i] = [c[0], c[1], pt[2]] try: rings = processRingCoordinates(coords) except Exception as e: msg = '[%s] --------- ERROR ------- occured while ' \ 'collapsing non triangular shapes\n' % pid msg += '[%s]: %s' % (pid, e) logger.error(msg, exc_info=True) raise Exception(e) # Redundant coord has been remove already for vertices in rings: terrainTopo.addVertices(vertices) bucketKey = '%s/%s/%s.terrain' % ( tileXYZ[2], tileXYZ[0], tileXYZ[1]) verticesLength = len(terrainTopo.vertices) if verticesLength > 0: terrainTopo.create() # Prepare terrain tile terrainFormat = TerrainTile(watermask=watermask) terrainFormat.fromTerrainTopology(terrainTopo, bounds=bounds) # Bytes manipulation and compression fileObject = terrainFormat.toStringIO() compressedFile = gzipFileObject(fileObject) writeToS3( bucket, bucketKey, compressedFile, model.__tablename__, bucketBasePath, contentType=terrainFormat.getContentType() ) tend = time.time() tilecount.value += 1 val = tilecount.value total = val + skipcount.value if val % 10 == 0: logger.info('[%s] Last tile %s (%s rings). ' '%s to write %s tiles. (total processed: %s)' % ( pid, bucketKey, verticesLength, str(datetime.timedelta(seconds=tend - t0)), val, total ) ) else: skipcount.value += 1 val = skipcount.value total = val + tilecount.value # One should write an empyt tile logger.info('[%s] Skipping %s %s because no features found ' 'for this tile (%s skipped from %s total)' % ( pid, bucketKey, bounds, val, total ) ) except Exception as e: logger.error(e, exc_info=True) raise Exception(e) finally: db.userEngine.dispose() return 0
from forge.terrain.topology import TerrainTopology from forge.lib.shapefile_utils import ShpToGDALFeatures from forge.lib.global_geodetic import GlobalGeodetic basename = '228_91_10' directory = '.tmp' extension = '.terrain' curDir = os.getcwd() filePathSource = '%s/forge/data/dem/%s.shp' % (curDir, basename) filePathTarget = '%s/%s%s' % (directory, basename, extension) shapefile = ShpToGDALFeatures(shpFilePath=filePathSource) features = shapefile.__read__() terrainTopo = TerrainTopology(features=features) terrainTopo.fromGDALFeatures("DN") terrainFormat = TerrainTile() geodetic = GlobalGeodetic(True) zxy = basename.split('_') bounds = geodetic.TileBounds(float(zxy[1]), float(zxy[2]), float(zxy[0])) terrainFormat.fromTerrainTopology(terrainTopo, bounds) terrainFormat.toFile(filePathTarget) # Display SwissCoordinates terrainFormat.computeVerticesCoordinates(epsg=21781) print terrainFormat
def createTile(tile): session = None pid = os.getpid() try: (bounds, tileXYZ, t0, dbConfigFile, bucketBasePath, hasLighting, hasWatermask) = tile db = DB(dbConfigFile) with db.userSession() as session: # bucket = getBucket() # Get the model according to the zoom level model = modelsPyramid.getModelByZoom(tileXYZ[2]) watermask = [] if hasWatermask: lakeModel = modelsPyramid.getLakeModelByZoom(tileXYZ[2]) query = session.query( lakeModel.watermaskRasterize(bounds).label('watermask')) for q in query: watermask = q.watermask # Get the interpolated point at the 4 corners # 0: (minX, minY), 1: (minX, maxY), 2: (maxX, maxY), 3: (maxX, minY) pts = [(bounds[0], bounds[1], 0), (bounds[0], bounds[3], 0), (bounds[2], bounds[3], 0), (bounds[2], bounds[1], 0)] def toSubQuery(x): return session.query( model.id, model.interpolateHeightOnPlane(pts[x])).filter( and_(model.bboxIntersects(createBBox(pts[x], 0.01)), model.pointIntersects(pts[x]))).subquery('p%s' % x) subqueries = [toSubQuery(i) for i in range(0, len(pts))] # Get the height of the corner points as postgis cannot properly # clip a polygon cornerPts = {} step = 2 j = step query = session.query(*subqueries) for q in query: for i in range(0, len(q), step): sub = q[i:j] j += step cornerPts[sub[0]] = list( to_shape(WKBElement(sub[1])).coords) # Clip using the bounds clippedGeometry = model.bboxClippedGeom(bounds) query = session.query(model.id, clippedGeometry.label('clip')).filter( model.bboxIntersects(bounds)) terrainTopo = TerrainTopology(hasLighting=hasLighting) for q in query: if to_shape(q.clip).geom_type == "GeometryCollection": continue if to_shape(q.clip).geom_type == "LineString" or to_shape( q.clip).geom_type == "Point": continue coords = list(to_shape(q.clip).exterior.coords) if q.id in cornerPts: pt = cornerPts[q.id][0] for i in range(0, len(coords)): c = coords[i] if c[0] == pt[0] and c[1] == pt[1]: coords[i] = [c[0], c[1], pt[2]] try: rings = processRingCoordinates(coords) except Exception as e: msg = '[%s] --------- ERROR ------- occured while ' \ 'collapsing non triangular shapes\n' % pid msg += '[%s]: %s' % (pid, e) logger.error(msg, exc_info=True) raise Exception(e) # Redundant coord has been remove already for vertices in rings: terrainTopo.addVertices(vertices) baseDir = '/Users/liberostelios/3d_forge_geodata/output' terrainDir = '%s/%s/%s' % (baseDir, tileXYZ[2], tileXYZ[0]) bucketKey = '%s/%s.terrain' % (terrainDir, tileXYZ[1]) verticesLength = len(terrainTopo.vertices) if verticesLength > 0: terrainTopo.create() # Prepare terrain tile terrainFormat = TerrainTile(watermask=watermask) terrainFormat.fromTerrainTopology(terrainTopo, bounds=bounds) # STELIOS: We want this in a file, instead if not os.path.isdir(terrainDir): os.makedirs(terrainDir) terrainFormat.toFile(bucketKey) logger.info('[%s] Just did %s %s' % (pid, bucketKey, bounds)) # Bytes manipulation and compression # fileObject = terrainFormat.toStringIO() # compressedFile = gzipFileObject(fileObject) # writeToS3( # bucket, bucketKey, compressedFile, model.__tablename__, # bucketBasePath, contentType=terrainFormat.getContentType() # ) tend = time.time() tilecount.value += 1 val = tilecount.value total = val + skipcount.value if val % 10 == 0: logger.info('[%s] Last tile %s (%s rings). ' '%s to write %s tiles. (total processed: %s)' % (pid, bucketKey, verticesLength, str(datetime.timedelta(seconds=tend - t0)), val, total)) else: skipcount.value += 1 val = skipcount.value total = val + tilecount.value # One should write an empyt tile logger.info('[%s] Skipping %s %s because no features found ' 'for this tile (%s skipped from %s total)' % (pid, bucketKey, bounds, val, total)) except Exception as e: logger.error(e, exc_info=True) raise Exception(e) finally: db.userEngine.dispose() return 0