Implement lod2

This commit is contained in:
Guille Gutierrez 2020-06-22 13:26:50 -04:00
parent 523c96216a
commit 366551cf38
16 changed files with 781249 additions and 89 deletions

View File

@ -10,10 +10,10 @@ class BixiFeature(CityObject):
""" """
BixiFeature(CityObject) class BixiFeature(CityObject) class
""" """
def __init__(self, lod, surfaces, name, feature_type, length): def __init__(self, lod, surfaces, name, feature_type, coordinates):
super().__init__(lod, surfaces, name) super().__init__(lod, surfaces, name)
self._feature_type = feature_type self._feature_type = feature_type
self._length = length self._coordinates = coordinates
@property @property
def feature_type(self): def feature_type(self):
@ -24,9 +24,9 @@ class BixiFeature(CityObject):
return self._feature_type return self._feature_type
@property @property
def length(self): def gps_coordinates(self):
""" """
Get length of bixi feature in meters Get bixi feature coordinates
:return: length :return: length
""" """
return self._length return self._coordinates

View File

@ -4,12 +4,12 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
from __future__ import annotations from __future__ import annotations
from typing import Union from typing import Union
import numpy as np import numpy as np
import pyny3d.geoms as pn import pyny3d.geoms as pn
from helpers.geometry_helper import GeometryHelper from helpers.geometry_helper import GeometryHelper
@ -418,6 +418,7 @@ class Surface:
intersect_surface = Surface(coordinates, remove_last=False) intersect_surface = Surface(coordinates, remove_last=False)
if intersect_surface.polygon is None: if intersect_surface.polygon is None:
return None return None
return Surface(coordinates, remove_last=False) return Surface(coordinates, remove_last=False)
except Exception as err: except Exception as err:
print('Error', err) print('Error', err)

Binary file not shown.

Binary file not shown.

View File

@ -492,7 +492,7 @@
</li> </li>
<li><a href="index.html#city_model_structure.layer.Layer.material">material() (city_model_structure.layer.Layer property)</a> <li><a href="index.html#city_model_structure.layer.Layer.material">material() (city_model_structure.layer.Layer property)</a>
</li> </li>
<li><a href="index.html#city_model_structure.building.Building.max_height">max_height() (city_model_structure.building.Building property)</a> <li><a href="index.html#city_model_structure.city_object.CityObject.max_height">max_height() (city_model_structure.city_object.CityObject property)</a>
</li> </li>
<li><a href="index.html#city_model_structure.polyhedron.Polyhedron.max_z">max_z() (city_model_structure.polyhedron.Polyhedron property)</a> <li><a href="index.html#city_model_structure.polyhedron.Polyhedron.max_z">max_z() (city_model_structure.polyhedron.Polyhedron property)</a>
</li> </li>
@ -640,7 +640,7 @@
</li> </li>
</ul></td> </ul></td>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="index.html#city_model_structure.building.Building.stl_export">stl_export() (city_model_structure.building.Building method)</a> <li><a href="index.html#city_model_structure.city_object.CityObject.stl_export">stl_export() (city_model_structure.city_object.CityObject method)</a>
</li> </li>
<li><a href="index.html#city_model_structure.building.Building.storeys_above_ground">storeys_above_ground() (city_model_structure.building.Building property)</a> <li><a href="index.html#city_model_structure.building.Building.storeys_above_ground">storeys_above_ground() (city_model_structure.building.Building property)</a>
</li> </li>

View File

@ -215,7 +215,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p> Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p>
<dl class="py class"> <dl class="py class">
<dt id="city_model_structure.city_object.CityObject"> <dt id="city_model_structure.city_object.CityObject">
<em class="property">class </em><code class="sig-prename descclassname">city_model_structure.city_object.</code><code class="sig-name descname">CityObject</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/city_object.html#CityObject"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.city_object.CityObject" title="Permalink to this definition"></a></dt> <em class="property">class </em><code class="sig-prename descclassname">city_model_structure.city_object.</code><code class="sig-name descname">CityObject</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em>, <em class="sig-param"><span class="n">name</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/city_object.html#CityObject"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.city_object.CityObject" title="Permalink to this definition"></a></dt>
<dd><p>class CityObject</p> <dd><p>class CityObject</p>
<dl class="py method"> <dl class="py method">
<dt id="city_model_structure.city_object.CityObject.location"> <dt id="city_model_structure.city_object.CityObject.location">
@ -231,6 +231,21 @@ Copyright © 2020 Project Author Guille Gutierrez <a class="reference external"
:return: int</p> :return: int</p>
</dd></dl> </dd></dl>
<dl class="py method">
<dt id="city_model_structure.city_object.CityObject.max_height">
<em class="property">property </em><code class="sig-name descname">max_height</code><a class="headerlink" href="#city_model_structure.city_object.CityObject.max_height" title="Permalink to this definition"></a></dt>
<dd><p>City object maximal height in meters
:return: float</p>
</dd></dl>
<dl class="py method">
<dt id="city_model_structure.city_object.CityObject.stl_export">
<code class="sig-name descname">stl_export</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">path</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/city_object.html#CityObject.stl_export"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.city_object.CityObject.stl_export" title="Permalink to this definition"></a></dt>
<dd><p>Export the city object to stl file (city_object_name.stl) to the given path
:param path: str
:return: None</p>
</dd></dl>
<dl class="py method"> <dl class="py method">
<dt id="city_model_structure.city_object.CityObject.surface"> <dt id="city_model_structure.city_object.CityObject.surface">
<code class="sig-name descname">surface</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">name</span></em><span class="sig-paren">)</span> &#x2192; Optional<span class="p">[</span><a class="reference internal" href="#city_model_structure.surface.Surface" title="city_model_structure.surface.Surface">city_model_structure.surface.Surface</a><span class="p">]</span><a class="reference internal" href="_modules/city_model_structure/city_object.html#CityObject.surface"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.city_object.CityObject.surface" title="Permalink to this definition"></a></dt> <code class="sig-name descname">surface</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">name</span></em><span class="sig-paren">)</span> &#x2192; Optional<span class="p">[</span><a class="reference internal" href="#city_model_structure.surface.Surface" title="city_model_structure.surface.Surface">city_model_structure.surface.Surface</a><span class="p">]</span><a class="reference internal" href="_modules/city_model_structure/city_object.html#CityObject.surface"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.city_object.CityObject.surface" title="Permalink to this definition"></a></dt>
@ -263,7 +278,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p> Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p>
<dl class="py class"> <dl class="py class">
<dt id="city_model_structure.bixi_feature.BixiFeature"> <dt id="city_model_structure.bixi_feature.BixiFeature">
<em class="property">class </em><code class="sig-prename descclassname">city_model_structure.bixi_feature.</code><code class="sig-name descname">BixiFeature</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em>, <em class="sig-param"><span class="n">feature_type</span></em>, <em class="sig-param"><span class="n">length</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/bixi_feature.html#BixiFeature"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.bixi_feature.BixiFeature" title="Permalink to this definition"></a></dt> <em class="property">class </em><code class="sig-prename descclassname">city_model_structure.bixi_feature.</code><code class="sig-name descname">BixiFeature</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em>, <em class="sig-param"><span class="n">name</span></em>, <em class="sig-param"><span class="n">feature_type</span></em>, <em class="sig-param"><span class="n">length</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/bixi_feature.html#BixiFeature"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.bixi_feature.BixiFeature" title="Permalink to this definition"></a></dt>
<dd><p>BixiFeature(CityObject) class</p> <dd><p>BixiFeature(CityObject) class</p>
<dl class="py method"> <dl class="py method">
<dt id="city_model_structure.bixi_feature.BixiFeature.feature_type"> <dt id="city_model_structure.bixi_feature.BixiFeature.feature_type">
@ -333,13 +348,6 @@ Copyright © 2020 Project Author Guille Gutierrez <a class="reference external"
:return: float</p> :return: float</p>
</dd></dl> </dd></dl>
<dl class="py method">
<dt id="city_model_structure.building.Building.max_height">
<em class="property">property </em><code class="sig-name descname">max_height</code><a class="headerlink" href="#city_model_structure.building.Building.max_height" title="Permalink to this definition"></a></dt>
<dd><p>City object maximal height in meters
:return: float</p>
</dd></dl>
<dl class="py method"> <dl class="py method">
<dt id="city_model_structure.building.Building.name"> <dt id="city_model_structure.building.Building.name">
<em class="property">property </em><code class="sig-name descname">name</code><a class="headerlink" href="#city_model_structure.building.Building.name" title="Permalink to this definition"></a></dt> <em class="property">property </em><code class="sig-name descname">name</code><a class="headerlink" href="#city_model_structure.building.Building.name" title="Permalink to this definition"></a></dt>
@ -347,14 +355,6 @@ Copyright © 2020 Project Author Guille Gutierrez <a class="reference external"
:return: str</p> :return: str</p>
</dd></dl> </dd></dl>
<dl class="py method">
<dt id="city_model_structure.building.Building.stl_export">
<code class="sig-name descname">stl_export</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">path</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/building.html#Building.stl_export"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.building.Building.stl_export" title="Permalink to this definition"></a></dt>
<dd><p>Export the city object to stl file (city_object_name.stl) to the given path
:param path: str
:return: None</p>
</dd></dl>
<dl class="py method"> <dl class="py method">
<dt id="city_model_structure.building.Building.storeys_above_ground"> <dt id="city_model_structure.building.Building.storeys_above_ground">
<em class="property">property </em><code class="sig-name descname">storeys_above_ground</code><a class="headerlink" href="#city_model_structure.building.Building.storeys_above_ground" title="Permalink to this definition"></a></dt> <em class="property">property </em><code class="sig-name descname">storeys_above_ground</code><a class="headerlink" href="#city_model_structure.building.Building.storeys_above_ground" title="Permalink to this definition"></a></dt>
@ -407,7 +407,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p> Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p>
<dl class="py class"> <dl class="py class">
<dt id="city_model_structure.composting_plant.CompostingPlant"> <dt id="city_model_structure.composting_plant.CompostingPlant">
<em class="property">class </em><code class="sig-prename descclassname">city_model_structure.composting_plant.</code><code class="sig-name descname">CompostingPlant</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em>, <em class="sig-param"><span class="n">waste_type</span></em>, <em class="sig-param"><span class="n">capacity</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/composting_plant.html#CompostingPlant"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.composting_plant.CompostingPlant" title="Permalink to this definition"></a></dt> <em class="property">class </em><code class="sig-prename descclassname">city_model_structure.composting_plant.</code><code class="sig-name descname">CompostingPlant</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em>, <em class="sig-param"><span class="n">name</span></em>, <em class="sig-param"><span class="n">waste_type</span></em>, <em class="sig-param"><span class="n">capacity</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/composting_plant.html#CompostingPlant"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.composting_plant.CompostingPlant" title="Permalink to this definition"></a></dt>
<dd><p>CompostingPlant(CityObject) class</p> <dd><p>CompostingPlant(CityObject) class</p>
<dl class="py method"> <dl class="py method">
<dt id="city_model_structure.composting_plant.CompostingPlant.capacity"> <dt id="city_model_structure.composting_plant.CompostingPlant.capacity">
@ -433,7 +433,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p> Copyright © 2020 Project Author Guille Gutierrez <a class="reference external" href="mailto:guillermo&#46;gutierrezmorote&#37;&#52;&#48;concordia&#46;ca">guillermo<span>&#46;</span>gutierrezmorote<span>&#64;</span>concordia<span>&#46;</span>ca</a></p>
<dl class="py class"> <dl class="py class">
<dt id="city_model_structure.tree.Tree"> <dt id="city_model_structure.tree.Tree">
<em class="property">class </em><code class="sig-prename descclassname">city_model_structure.tree.</code><code class="sig-name descname">Tree</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em>, <em class="sig-param"><span class="n">height</span></em>, <em class="sig-param"><span class="n">canopy</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/tree.html#Tree"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.tree.Tree" title="Permalink to this definition"></a></dt> <em class="property">class </em><code class="sig-prename descclassname">city_model_structure.tree.</code><code class="sig-name descname">Tree</code><span class="sig-paren">(</span><em class="sig-param"><span class="n">lod</span></em>, <em class="sig-param"><span class="n">surfaces</span></em>, <em class="sig-param"><span class="n">name</span></em>, <em class="sig-param"><span class="n">height</span></em>, <em class="sig-param"><span class="n">canopy</span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/city_model_structure/tree.html#Tree"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#city_model_structure.tree.Tree" title="Permalink to this definition"></a></dt>
<dd><p>Tree(CityObject) class</p> <dd><p>Tree(CityObject) class</p>
<dl class="py method"> <dl class="py method">
<dt id="city_model_structure.tree.Tree.canopy"> <dt id="city_model_structure.tree.Tree.canopy">

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -10,6 +10,7 @@ from city_model_structure.city import City
from city_model_structure.building import Building from city_model_structure.building import Building
from city_model_structure.surface import Surface from city_model_structure.surface import Surface
from helpers.geometry_helper import GeometryHelper from helpers.geometry_helper import GeometryHelper
from datetime import datetime
class CityGml: class CityGml:
@ -17,11 +18,20 @@ class CityGml:
CityGml class CityGml class
""" """
def __init__(self, path): def __init__(self, path):
start = datetime.utcnow()
self._city = None self._city = None
with open(path) as gml: with open(path) as gml:
# Clean the namespaces is an important task to prevent wrong ns:field due poor citygml implementations # Clean the namespaces is an important task to prevent wrong ns:field due poor citygml implementations
self._gml = xmltodict.parse(gml.read(), process_namespaces=True, xml_attribs=True, namespaces={ self._gml = xmltodict.parse(gml.read(), process_namespaces=True, xml_attribs=True, namespaces={
'http://www.opengis.net/gml': None, 'http://www.opengis.net/gml': None,
'http://www.opengis.net/citygml/1.0': None,
'http://www.opengis.net/citygml/building/1.0': None,
'http://schemas.opengis.net/citygml/building/1.0/building.xsd': None,
'http://www.opengis.net/citygml/appearance/1.0': None,
'http://schemas.opengis.net/citygml/appearance/1.0/appearance.xsd': None,
'http://www.opengis.net/citygml/relief/1.0': None,
'http://schemas.opengis.net/citygml/relief/1.0/relief.xsd': None,
'http://www.opengis.net/citygml/generics/1.0': None,
'http://www.w3.org/2001/XMLSchema-instance': None, 'http://www.w3.org/2001/XMLSchema-instance': None,
'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0': None, 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0': None,
'http://www.w3.org/1999/xlink': None, 'http://www.w3.org/1999/xlink': None,
@ -31,18 +41,20 @@ class CityGml:
'http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd" ' 'http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd" '
'xmlns="http://www.opengis.net/citygml/2.0': None, 'xmlns="http://www.opengis.net/citygml/2.0': None,
'http://www.opengis.net/citygml/2.0': None 'http://www.opengis.net/citygml/2.0': None
}, force_list=('cityObjectMember', 'curveMember')) }, force_list=('cityObjectMember', 'curveMember', 'boundedBy', 'surfaceMember'))
self._city_objects = None self._city_objects = None
self._geometry = GeometryHelper() self._geometry = GeometryHelper()
envelope = self._gml['CityModel']['boundedBy']['Envelope'] for bound in self._gml['CityModel']['boundedBy']:
if '#text' in envelope['lowerCorner']: envelope = bound['Envelope']
self._lower_corner = np.fromstring(envelope['lowerCorner']['#text'], dtype=float, sep=' ') if '#text' in envelope['lowerCorner']:
self._upper_corner = np.fromstring(envelope['upperCorner']['#text'], dtype=float, sep=' ') self._lower_corner = np.fromstring(envelope['lowerCorner']['#text'], dtype=float, sep=' ')
else: self._upper_corner = np.fromstring(envelope['upperCorner']['#text'], dtype=float, sep=' ')
self._lower_corner = np.fromstring(envelope['lowerCorner'], dtype=float, sep=' ') else:
self._upper_corner = np.fromstring(envelope['upperCorner'], dtype=float, sep=' ') self._lower_corner = np.fromstring(envelope['lowerCorner'], dtype=float, sep=' ')
self._upper_corner = np.fromstring(envelope['upperCorner'], dtype=float, sep=' ')
self._srs_name = envelope['@srsName'] self._srs_name = envelope['@srsName']
print('city_gml constructor', datetime.utcnow() - start)
@property @property
def content(self): def content(self):
@ -60,55 +72,35 @@ class CityGml:
""" """
if self._city is None: if self._city is None:
self._city = City(self._lower_corner, self._upper_corner, self._srs_name) self._city = City(self._lower_corner, self._upper_corner, self._srs_name)
i = 0
for o in self._gml['CityModel']['cityObjectMember']: for o in self._gml['CityModel']['cityObjectMember']:
i += 1
print('add city object', i)
lod = 0 lod = 0
surfaces = []
if 'lod1Solid' in o['Building']: if 'lod1Solid' in o['Building']:
lod += 1 lod += 1
if 'lod2Solid' in o['Building']: surfaces = self._lod1(o)
lod += 2
if 'lod3Solid' in o['Building']: for bound in o['Building']['boundedBy']:
lod += 4 surface_type = next(iter(bound))
if 'lod4Solid' in o['Building']: if 'lod2MultiSurface' in bound[surface_type]:
lod += 8 start = datetime.utcnow()
# ToDo: this is specific for Lod1 need to be modeled for higher lod's and lod combinations lod = 2
surfaces = CityGml._lod2(bound)
print('lod2 ', surface_type, datetime.utcnow() - start)
if 'lod3Solid' in o['Building']:
lod += 4
if 'lod4Solid' in o['Building']:
lod += 8
name = o['Building']['@id'] name = o['Building']['@id']
lod_str = 'lod' + str(lod) + 'Solid'
lod_terrain_str = 'lod' + str(lod) + 'TerrainIntersection' lod_terrain_str = 'lod' + str(lod) + 'TerrainIntersection'
try: terrains = []
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList']['#text'])
for s in o['Building'][lod_str]['Solid']['exterior']['CompositeSurface']['surfaceMember']]
except TypeError:
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList'])
for s in o['Building'][lod_str]['Solid']['exterior']['CompositeSurface']['surfaceMember']]
if lod_terrain_str in o['Building']: if lod_terrain_str in o['Building']:
try: terrains = self._terrains(o, lod_terrain_str)
curves = [c['LineString']['posList']['#text']
for c in o['Building'][lod_terrain_str]['MultiCurve']['curveMember']]
except TypeError:
curves = [c['LineString']['posList']
for c in o['Building'][lod_terrain_str]['MultiCurve']['curveMember']]
terrains = []
for curve in curves:
curve_points = np.fromstring(curve, dtype=float, sep=' ')
curve_points = self._geometry.to_points_matrix(curve_points, True)
terrains.append(curve_points)
else:
terrains = []
for s in surfaces:
ground = True
ground_points = []
for row in s.points:
# all surface vertex are in the lower z
ground_point = [row[0], row[1], self._lower_corner[2]]
ground_points = np.concatenate((ground_points, ground_point), axis=None)
ground = ground and self._geometry.almost_equal(row, ground_point)
if ground:
ground_points = self._geometry.to_points_matrix(ground_points)
# Do i need to remove the duplicated?
terrains.append(ground_points)
year_of_construction = None year_of_construction = None
function = None function = None
if 'yearOfConstruction' in o['Building']: if 'yearOfConstruction' in o['Building']:
@ -118,3 +110,56 @@ class CityGml:
self._city.add_city_object(Building(name, lod, surfaces, terrains, year_of_construction, function, self._city.add_city_object(Building(name, lod, surfaces, terrains, year_of_construction, function,
self._lower_corner)) self._lower_corner))
return self._city return self._city
def _terrains(self, city_object, lod_terrain_str):
try:
curves = [c['LineString']['posList']['#text']
for c in city_object['Building'][lod_terrain_str]['MultiCurve']['curveMember']]
except TypeError:
curves = [c['LineString']['posList']
for c in city_object['Building'][lod_terrain_str]['MultiCurve']['curveMember']]
terrains = []
for curve in curves:
curve_points = np.fromstring(curve, dtype=float, sep=' ')
curve_points = self._geometry.to_points_matrix(curve_points, True)
terrains.append(curve_points)
return terrains
def _lod1(self, o):
try:
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList']['#text'])
for s in o['Building']['lod1Solid']['Solid']['exterior']['CompositeSurface']['surfaceMember']]
except TypeError:
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList'])
for s in o['Building']['lod1Solid']['Solid']['exterior']['CompositeSurface']['surfaceMember']]
terrains = []
for s in surfaces:
ground = True
ground_points = []
for row in s.points:
# all surface vertex are in the lower z
ground_point = [row[0], row[1], self._lower_corner[2]]
ground_points = np.concatenate((ground_points, ground_point), axis=None)
ground = ground and self._geometry.almost_equal(row, ground_point)
if ground:
ground_points = self._geometry.to_points_matrix(ground_points)
# Do i need to remove the duplicated?
terrains.append(ground_points)
return surfaces
@staticmethod
def _lod2(bound):
surfaces = []
for surface_type in iter(bound):
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']:
try:
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList']['#text'],
surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']]
except TypeError:
surfaces = [Surface(s['Polygon']['exterior']['LinearRing']['posList'],
surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
for s in bound[surface_type]['lod2MultiSurface']['MultiSurface']['surfaceMember']]
print(len(surfaces), 'surfaces')
return surfaces

View File

@ -4,6 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
import math import math
from datetime import datetime
import numpy as np import numpy as np
import open3d as o3d import open3d as o3d
@ -35,6 +36,8 @@ class GeometryHelper:
:param s2: Surface :param s2: Surface
:return: Boolean :return: Boolean
""" """
start = datetime.utcnow()
# delta is grads an need to be converted into radians # delta is grads an need to be converted into radians
delta = np.rad2deg(self._delta) delta = np.rad2deg(self._delta)
difference = (s1.inclination - s2.inclination) % math.pi difference = (s1.inclination - s2.inclination) % math.pi
@ -58,6 +61,7 @@ class GeometryHelper:
minimum_distance = distance minimum_distance = distance
if minimum_distance <= self._delta: if minimum_distance <= self._delta:
break break
print('intersect', datetime.utcnow() - start)
if minimum_distance > self._delta or s1.intersect(s2) is None: if minimum_distance > self._delta or s1.intersect(s2) is None:
return False return False
else: else:
@ -163,3 +167,12 @@ class GeometryHelper:
mesh_final.append(GeometryHelper._merge_meshes(mesh_1, mesh_2)) mesh_final.append(GeometryHelper._merge_meshes(mesh_1, mesh_2))
return mesh_final return mesh_final
@staticmethod
def gml_surface_to_libs(surface):
if surface == 'WallSurface':
return 'Wall'
elif surface == 'GroundSurface':
return 'Ground'
else:
return 'Roof'

View File

@ -24,7 +24,7 @@ class TestGeometryFactory(TestCase):
def _get_citygml(self): def _get_citygml(self):
if self._city_gml is None: if self._city_gml is None:
file_path = (self._example_path / 'buildings.gml').resolve() file_path = (self._example_path / 'lod2_buildings.gml').resolve()
self._city_gml = GeometryFactory('citygml', file_path).city self._city_gml = GeometryFactory('citygml', file_path).city
self.assertIsNotNone(self._city_gml, 'city is none') self.assertIsNotNone(self._city_gml, 'city is none')
return self._city_gml return self._city_gml
@ -35,8 +35,8 @@ class TestGeometryFactory(TestCase):
:return: None :return: None
""" """
city = self._get_citygml() city = self._get_citygml()
self.assertIsNotNone(city.buildings, 'city_objects is none') self.assertIsNotNone(city.city_objects, 'city_objects is none')
for city_object in city.buildings: for city_object in city.city_objects:
self.assertIsNotNone(city.city_object(city_object.name), 'city_object return none') self.assertIsNotNone(city.city_object(city_object.name), 'city_object return none')
self.assertIsNotNone(city.srs_name, 'srs_name is none') self.assertIsNotNone(city.srs_name, 'srs_name is none')
self.assertIsNotNone(city.lower_corner, 'lower_corner is none') self.assertIsNotNone(city.lower_corner, 'lower_corner is none')

View File

@ -25,7 +25,7 @@ class TestPhysicsFactory(TestCase):
def _get_citygml(self): def _get_citygml(self):
if self._city_gml is None: if self._city_gml is None:
file_path = (self._example_path / 'buildings.gml').resolve() file_path = (self._example_path / 'lod2_buildings.gml').resolve()
self._city_gml = GeometryFactory('citygml', file_path).city self._city_gml = GeometryFactory('citygml', file_path).city
self.assertIsNotNone(self._city_gml, 'city is none') self.assertIsNotNone(self._city_gml, 'city is none')
return self._city_gml return self._city_gml

781101
tests_data/lod2_buildings.gml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1713,7 +1713,7 @@ class LightSource:
completely in shadow and 1 is completely illuminated. completely in shadow and 1 is completely illuminated.
""" """
# Because most image and raster GIS data has the first row in the array # Because most image and raster gis data has the first row in the array
# as the "top" of the image, dy is implicitly negative. This is # as the "top" of the image, dy is implicitly negative. This is
# consistent to what `imshow` assumes, as well. # consistent to what `imshow` assumes, as well.
dy = -dy dy = -dy

View File

@ -62,7 +62,7 @@ class TransformerGroup(_TransformerGroup):
projections are equivalent. Default is false. projections are equivalent. Default is false.
always_xy: bool, optional always_xy: bool, optional
If true, the transform method will accept as input and return as output If true, the transform method will accept as input and return as output
coordinates using the traditional GIS order, that is longitude, latitude coordinates using the traditional gis order, that is longitude, latitude
for geographic CRS and easting, northing for most projected CRS. for geographic CRS and easting, northing for most projected CRS.
Default is false. Default is false.
area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional
@ -246,7 +246,7 @@ class Transformer:
projections are equivalent. Default is false. projections are equivalent. Default is false.
always_xy: bool, optional always_xy: bool, optional
If true, the transform method will accept as input and return as output If true, the transform method will accept as input and return as output
coordinates using the traditional GIS order, that is longitude, latitude coordinates using the traditional gis order, that is longitude, latitude
for geographic CRS and easting, northing for most projected CRS. for geographic CRS and easting, northing for most projected CRS.
Default is false. Default is false.
area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional
@ -295,7 +295,7 @@ class Transformer:
projections are equivalent. Default is false. projections are equivalent. Default is false.
always_xy: bool, optional always_xy: bool, optional
If true, the transform method will accept as input and return as output If true, the transform method will accept as input and return as output
coordinates using the traditional GIS order, that is longitude, latitude coordinates using the traditional gis order, that is longitude, latitude
for geographic CRS and easting, northing for most projected CRS. for geographic CRS and easting, northing for most projected CRS.
Default is false. Default is false.
area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional
@ -699,7 +699,7 @@ def transform(
it will skip the transformation operation if input and output it will skip the transformation operation if input and output
projections are equivalent. If `always_xy` is toggled, the projections are equivalent. If `always_xy` is toggled, the
transform method will accept as input and return as output transform method will accept as input and return as output
coordinates using the traditional GIS order, that is longitude, latitude coordinates using the traditional gis order, that is longitude, latitude
for geographic CRS and easting, northing for most projected CRS. for geographic CRS and easting, northing for most projected CRS.
In addition to converting between cartographic and geographic In addition to converting between cartographic and geographic
@ -807,7 +807,7 @@ def itransform(
it will skip the transformation operation if input and output it will skip the transformation operation if input and output
projections are equivalent. If `always_xy` is toggled, the projections are equivalent. If `always_xy` is toggled, the
transform method will accept as input and return as output transform method will accept as input and return as output
coordinates using the traditional GIS order, that is longitude, latitude coordinates using the traditional gis order, that is longitude, latitude
for geographic CRS and easting, northing for most projected CRS. for geographic CRS and easting, northing for most projected CRS.

View File

@ -5391,7 +5391,7 @@ class kappa3_gen(rv_continuous):
References References
---------- ----------
P.W. Mielke and E.S. Johnson, "Three-Parameter Kappa Distribution Maximum P.W. Mielke and E.S. Johnson, "Three-Parameter Kappa Distribution Maximum
Likelihood and Likelihood Ratio Tests", Methods in Weather Research, Likelihood and Likelihood Ratio Tests", Methods in weather Research,
701-707, (September, 1973), 701-707, (September, 1973),
https://doi.org/10.1175/1520-0493(1973)101<0701:TKDMLE>2.3.CO;2 https://doi.org/10.1175/1520-0493(1973)101<0701:TKDMLE>2.3.CO;2