Generate functions for all API usecases for better static code features. See #2693.

This commit is contained in:
Dion Moult
2024-05-06 14:35:39 +10:00
parent 10f894e2ea
commit d11ec67129
330 changed files with 13283 additions and 13751 deletions
@@ -15,3 +15,7 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
from .add_georeferencing import add_georeferencing
from .edit_georeferencing import edit_georeferencing
from .remove_georeferencing import remove_georeferencing
@@ -17,48 +17,45 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file):
"""Add empty georeferencing entities to a model
def add_georeferencing(file) -> None:
"""Add empty georeferencing entities to a model
By default, models are not georeferenced. Georeferencing requires two
entities: a definition of the projected coordinated reference system
(CRS) used, and the transformation parameters between any local coordinate
system and that projected CRS if any.
By default, models are not georeferenced. Georeferencing requires two
entities: a definition of the projected coordinated reference system
(CRS) used, and the transformation parameters between any local coordinate
system and that projected CRS if any.
This function will create the entities to store the projected CRS and
map conversion transformation, but will leave all the parameters blank.
It is this the users responsibility to specify the correct
georeferencing parameters. See
ifcopenshell.api.georeference.edit_georeferencing.
This function will create the entities to store the projected CRS and
map conversion transformation, but will leave all the parameters blank.
It is this the users responsibility to specify the correct
georeferencing parameters. See
ifcopenshell.api.georeference.edit_georeferencing.
:return: None
:rtype: None
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
ifcopenshell.api.run("georeference.add_georeferencing", model)
"""
self.file = file
ifcopenshell.api.run("georeference.add_georeferencing", model)
"""
def execute(self):
source_crs = None
for context in self.file.by_type("IfcGeometricRepresentationContext", include_subtypes=False):
if context.ContextType == "Model":
source_crs = context
break
if not source_crs:
return
projected_crs = self.file.create_entity("IfcProjectedCRS", **{"Name": ""})
self.file.create_entity(
"IfcMapConversion",
**{
"SourceCRS": source_crs,
"TargetCRS": projected_crs,
"Eastings": 0,
"Northings": 0,
"OrthogonalHeight": 0,
}
)
source_crs = None
for context in file.by_type("IfcGeometricRepresentationContext", include_subtypes=False):
if context.ContextType == "Model":
source_crs = context
break
if not source_crs:
return
projected_crs = file.create_entity("IfcProjectedCRS", **{"Name": ""})
file.create_entity(
"IfcMapConversion",
**{
"SourceCRS": source_crs,
"TargetCRS": projected_crs,
"Eastings": 0,
"Northings": 0,
"OrthogonalHeight": 0,
}
)
@@ -17,77 +17,80 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
def edit_georeferencing(file, map_conversion=None, projected_crs=None, true_north=None) -> None:
"""Edits the attributes of a map conversion, projected CRS, and true north
Setting the correct georeferencing parameters is a complex topic and
should ideally be done with three parties present: the lead architect,
surveyor, and a third-party digital engineer with expertise in IFC to
moderate. For more information, read the BlenderBIM Add-on documentation
for Georeferencing:
https://docs.blenderbim.org/users/georeferencing.html
For more information about the attributes and data types of an
IfcMapConversion, consult the IFC documentation.
For more information about the attributes and data types of an
IfcProjectedCRS, consult the IFC documentation.
True north is defined as a unitised 2D vector pointing to true north.
Note that true north is not part of georeferencing, and is only
optionally provided as a reference value, typically for solar analysis.
See ifcopenshell.util.geolocation for more utilities to convert to and
from local and map coordinates to check your results.
:param map_conversion: The IfcMapConversion dictionary of attribute
names and values you want to edit.
:type map_conversion: dict, optional
:param projected_crs: The IfcProjectedCRS dictionary of attribute
names and values you want to edit.
:type projected_crs: dict, optional
:param true_north: A unitised 2D vector, where each ordinate is a float
:type true_north: list[float]
:return: None
:rtype: None
Example:
.. code:: python
ifcopenshell.api.run("georeference.add_georeferencing", model)
# This is the simplest scenario, a defined CRS (GDA2020 / MGA Zone
# 56, typically used in Sydney, Australia) but with no local
# coordinates. This is only recommended for horizontal construction
# projects, not for vertical construction (such as buildings).
ifcopenshell.api.run("georeference.edit_georeferencing", model,
projected_crs={"Name": "EPSG:7856"})
# For buildings, it is almost always recommended to specify map
# conversion parameters to a false origin and orientation to project
# north. See the diagram in the BlenderBIM Add-on Georeferencing
# documentation for correct calculation of the X Axis Abcissa and
# Ordinate.
ifcopenshell.api.run("georeference.edit_georeferencing", model,
projected_crs={"Name": "EPSG:7856"},
map_conversion={
"Eastings": 335087.17, # The architect nominates a false origin
"Northings": 6251635.41, # The architect nominates a false origin
# Note: this is the angle difference between Project North
# and Grid North. Remember: True North should never be used!
"XAxisAbscissa": cos(radians(-30)), # The architect nominates a project north
"XAxisOrdinate": sin(radians(-30)), # The architect nominates a project north
"Scale": 0.99956, # Ask your surveyor for your site's average combined scale factor!
})
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {
"map_conversion": map_conversion or {},
"projected_crs": projected_crs or {},
"true_north": true_north or [],
}
return usecase.execute()
class Usecase:
def __init__(self, file, map_conversion=None, projected_crs=None, true_north=None):
"""Edits the attributes of a map conversion, projected CRS, and true north
Setting the correct georeferencing parameters is a complex topic and
should ideally be done with three parties present: the lead architect,
surveyor, and a third-party digital engineer with expertise in IFC to
moderate. For more information, read the BlenderBIM Add-on documentation
for Georeferencing:
https://docs.blenderbim.org/users/georeferencing.html
For more information about the attributes and data types of an
IfcMapConversion, consult the IFC documentation.
For more information about the attributes and data types of an
IfcProjectedCRS, consult the IFC documentation.
True north is defined as a unitised 2D vector pointing to true north.
Note that true north is not part of georeferencing, and is only
optionally provided as a reference value, typically for solar analysis.
See ifcopenshell.util.geolocation for more utilities to convert to and
from local and map coordinates to check your results.
:param map_conversion: The IfcMapConversion dictionary of attribute
names and values you want to edit.
:type map_conversion: dict, optional
:param projected_crs: The IfcProjectedCRS dictionary of attribute
names and values you want to edit.
:type projected_crs: dict, optional
:param true_north: A unitised 2D vector, where each ordinate is a float
:type true_north: list[float]
:return: None
:rtype: None
Example:
.. code:: python
ifcopenshell.api.run("georeference.add_georeferencing", model)
# This is the simplest scenario, a defined CRS (GDA2020 / MGA Zone
# 56, typically used in Sydney, Australia) but with no local
# coordinates. This is only recommended for horizontal construction
# projects, not for vertical construction (such as buildings).
ifcopenshell.api.run("georeference.edit_georeferencing", model,
projected_crs={"Name": "EPSG:7856"})
# For buildings, it is almost always recommended to specify map
# conversion parameters to a false origin and orientation to project
# north. See the diagram in the BlenderBIM Add-on Georeferencing
# documentation for correct calculation of the X Axis Abcissa and
# Ordinate.
ifcopenshell.api.run("georeference.edit_georeferencing", model,
projected_crs={"Name": "EPSG:7856"},
map_conversion={
"Eastings": 335087.17, # The architect nominates a false origin
"Northings": 6251635.41, # The architect nominates a false origin
# Note: this is the angle difference between Project North
# and Grid North. Remember: True North should never be used!
"XAxisAbscissa": cos(radians(-30)), # The architect nominates a project north
"XAxisOrdinate": sin(radians(-30)), # The architect nominates a project north
"Scale": 0.99956, # Ask your surveyor for your site's average combined scale factor!
})
"""
self.file = file
self.settings = {
"map_conversion": map_conversion or {},
"projected_crs": projected_crs or {},
"true_north": true_north or [],
}
def execute(self):
map_conversion = self.file.by_type("IfcMapConversion")[0]
projected_crs = self.file.by_type("IfcProjectedCRS")[0]
@@ -17,29 +17,26 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file):
"""Remove georeferencing data
def remove_georeferencing(file) -> None:
"""Remove georeferencing data
All georeferencing parameters such as projected CRS and map conversion
data will be lost.
All georeferencing parameters such as projected CRS and map conversion
data will be lost.
:return: None
:rtype: None
:return: None
:rtype: None
Example:
Example:
ifcopenshell.api.run("georeference.add_georeferencing", model)
# Let's change our mind
ifcopenshell.api.run("georeference.remove_georeferencing", model)
"""
self.file = file
ifcopenshell.api.run("georeference.add_georeferencing", model)
# Let's change our mind
ifcopenshell.api.run("georeference.remove_georeferencing", model)
"""
def execute(self):
map_conversion = self.file.by_type("IfcMapConversion")[0]
projected_crs = self.file.by_type("IfcProjectedCRS")[0]
if projected_crs.MapUnit and len(self.file.get_inverse(projected_crs.MapUnit)) == 1:
# TODO: go deeper for conversion units
self.file.remove(projected_crs.MapUnit)
self.file.remove(projected_crs)
self.file.remove(map_conversion)
map_conversion = file.by_type("IfcMapConversion")[0]
projected_crs = file.by_type("IfcProjectedCRS")[0]
if projected_crs.MapUnit and len(file.get_inverse(projected_crs.MapUnit)) == 1:
# TODO: go deeper for conversion units
file.remove(projected_crs.MapUnit)
file.remove(projected_crs)
file.remove(map_conversion)