forked from s_ranjbar/city_retrofit
Add unit tests and requirements for geopandas factory.
Geopandas factory now can receive a geojson file or a pandas data frame by using the optional variable data_frame in the constructor to be consistent with the rest of the factories So from: ConstructionFactory('gpandas', dataframe) to: ConstructionFactory('gpandas, '', dataframe)
This commit is contained in:
parent
d91da411fd
commit
a617f598ff
|
@ -8,6 +8,8 @@ Project Coder: Milad Aghamohamadnia --- milad.aghamohamadnia@concordia.ca
|
|||
import trimesh
|
||||
import trimesh.exchange.load
|
||||
import trimesh.geometry
|
||||
import trimesh.creation
|
||||
import trimesh.repair
|
||||
from shapely.geometry import Point
|
||||
from shapely.geometry import Polygon as ShapelyPoly
|
||||
from trimesh import Scene
|
||||
|
@ -25,16 +27,17 @@ class GPandas:
|
|||
GeoPandas class
|
||||
"""
|
||||
|
||||
def __init__(self, gdataframe, srs_name='EPSG:26911'):
|
||||
def __init__(self, dataframe, srs_name='EPSG:26911'):
|
||||
"""_summary_
|
||||
Arguments:
|
||||
gdataframe {Geopandas.Dataframe} -- input geometry data in geopandas table
|
||||
dataframe {Geopandas.Dataframe} -- input geometry data in geopandas table
|
||||
Keyword Arguments:
|
||||
srs_name {str} -- coordinate system of coordinate system (default: {'EPSG:26911'})
|
||||
"""
|
||||
|
||||
self._srs_name = srs_name
|
||||
self._city = None
|
||||
self._scene = gdataframe
|
||||
self._scene = dataframe
|
||||
self._scene = self._scene.to_crs(self._srs_name)
|
||||
min_x, min_y, max_x, max_y = self._scene.total_bounds
|
||||
self._lower_corner = [min_x, min_y, 0]
|
||||
|
@ -70,15 +73,13 @@ class GPandas:
|
|||
function = cte.INDUSTRY
|
||||
|
||||
surfaces = []
|
||||
face_normal = building_mesh.face_normals
|
||||
for face_index, face in enumerate(building_mesh.faces):
|
||||
points = []
|
||||
for vertex_index in face:
|
||||
points.append(building_mesh.vertices[vertex_index])
|
||||
solid_polygon = Polygon(points)
|
||||
perimeter_polygon = solid_polygon
|
||||
s_type = cte.GROUND if face_normal[face_index][2] == -1 else (cte.ROOF if face_normal[face_index][2] == 1 else cte.WALL)
|
||||
surface = Surface(solid_polygon, perimeter_polygon, surface_type=s_type)
|
||||
surface = Surface(solid_polygon, perimeter_polygon)
|
||||
surfaces.append(surface)
|
||||
building = Building(name, lod, surfaces, year_of_construction, function, self._lower_corner, terrains=None)
|
||||
self._city.add_city_object(building)
|
||||
|
|
|
@ -11,15 +11,16 @@ from imports.geometry.obj import Obj
|
|||
from imports.geometry.osm_subway import OsmSubway
|
||||
from imports.geometry.rhino import Rhino
|
||||
from imports.geometry.gpandas import GPandas
|
||||
|
||||
import geopandas
|
||||
|
||||
class GeometryFactory:
|
||||
"""
|
||||
GeometryFactory class
|
||||
"""
|
||||
def __init__(self, file_type, path):
|
||||
def __init__(self, file_type, path, data_frame=None):
|
||||
self._file_type = '_' + file_type.lower()
|
||||
self._path = path
|
||||
self._data_frame = data_frame
|
||||
|
||||
@property
|
||||
def _citygml(self) -> City:
|
||||
|
@ -44,7 +45,9 @@ class GeometryFactory:
|
|||
Enrich the city by using GeoPandas information as data source
|
||||
:return: City
|
||||
"""
|
||||
return GPandas(self._path).city
|
||||
if self._data_frame is None:
|
||||
self._data_frame = geopandas.read_file(self._path)
|
||||
return GPandas(self._data_frame).city
|
||||
|
||||
@property
|
||||
def _osm_subway(self) -> City:
|
||||
|
@ -76,4 +79,4 @@ class GeometryFactory:
|
|||
Enrich the city given to the class using the class given handler
|
||||
:return: City
|
||||
"""
|
||||
return CityGml(self._path).city
|
||||
return GPandas(geopandas.read_file(self._path)).city
|
||||
|
|
|
@ -16,4 +16,6 @@ rhino3dm==7.7.0
|
|||
scipy
|
||||
PyYAML
|
||||
pyecore==0.12.2
|
||||
shapely
|
||||
shapely
|
||||
geopandas
|
||||
triangle
|
|
@ -93,9 +93,7 @@ class TestGeometryFactory(TestCase):
|
|||
_construction_keys = ['nrel']
|
||||
_usage_keys = ['comnet', 'hft']
|
||||
for construction_key in _construction_keys:
|
||||
print('construction key: ', construction_key)
|
||||
for usage_key in _usage_keys:
|
||||
print('usage key: ', usage_key)
|
||||
# construction factory called first
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
|
|
|
@ -8,9 +8,11 @@ from pathlib import Path
|
|||
from unittest import TestCase
|
||||
|
||||
from numpy import inf
|
||||
from pyproj import Proj, transform
|
||||
|
||||
from imports.geometry_factory import GeometryFactory
|
||||
from imports.construction_factory import ConstructionFactory
|
||||
import geopandas
|
||||
|
||||
|
||||
class TestGeometryFactory(TestCase):
|
||||
|
@ -32,6 +34,12 @@ class TestGeometryFactory(TestCase):
|
|||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _get_geojson(self, file):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('gpandas', file_path).city_debug
|
||||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _get_obj(self, file):
|
||||
# todo: solve the incongruities between city and city_debug
|
||||
file_path = (self._example_path / file).resolve()
|
||||
|
@ -151,13 +159,16 @@ class TestGeometryFactory(TestCase):
|
|||
"""
|
||||
Test geopandas import
|
||||
"""
|
||||
file = 'kelowna.obj'
|
||||
city = self._get_obj(file)
|
||||
file = 'sample.geojson'
|
||||
city = self._get_geojson(file)
|
||||
self.assertIsNotNone(city, 'city is none')
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._check_buildings(city)
|
||||
|
||||
for building in city.buildings:
|
||||
self._check_surfaces(building)
|
||||
self.assertEqual(1912.0898135701814, building.volume)
|
||||
self.assertEqual(146.19493345171213, building.floor_area)
|
||||
|
||||
# osm
|
||||
def test_subway(self):
|
||||
|
|
18
unittests/tests_data/sample.geojson
Normal file
18
unittests/tests_data/sample.geojson
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ "type": "FeatureCollection",
|
||||
"features": [
|
||||
{ "type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[ [[-73.5027962600162, 45.6572759731914], [-73.5027463586105, 45.6572669735158], [-73.5027513584185, 45.6572530729948], [-73.5026715592026, 45.6572412737672], [-73.5026410593539, 45.6573430727752], [-73.5027703584728, 45.6573621728624], [-73.5027962600162, 45.6572759731914]] ]
|
||||
]
|
||||
|
||||
},
|
||||
"properties": {
|
||||
"geom": {"type": "Polygon", "crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4326"}}, "coordinates": [[[3849322.0855625975, 6060583.24800576], [3849326.3956304314, 6060584.796717078], [3849327.0180495544, 6060583.089519385], [3849333.725799462, 6060585.837955164], [3849328.71788522, 6060598.03498192], [3849317.850609142, 6060593.57976506], [3849322.0855625975, 6060583.24800576]]]},
|
||||
"height_mean": 13.0790429485,
|
||||
"year_built": 2000
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user