diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py index 826e48494e..7e4941215c 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py @@ -20,14 +20,57 @@ import ifcopenshell.util.unit class Usecase: - def __init__(self, file, **settings): + def __init__(self, file, context=None, axis=None): + """Adds a new axis representation + + Certain objects are typically "axis-based", such as walls, beams, + and columns. This means you can represent them abstractly by simply + drawing a single line either in 2D (such as for walls) or 3D (for beams + and columns). Humans can understand this axis-based representation as + being a simplification of a layered extrusion or a profile that is being + extruded along that axis and joined to other elements. + + Using an axis-based representation makes it easy for users and computers + to analyse connectivity and spatial relationships, as well as makes it + easy to parametrically edit these objects by simply stretching the start + or end of the axis. + + For now, only simple straight line axes are supported, represented by a + start and end coordinate. The order is important. For walls, the start + must be at the minimum local X ordinate, and the end at the maximum + local X ordinate. For beams and columns, the start is at the minimum + local Z ordinate, and the end of the maximum local Z ordinate. The first + coordinate is the "start" and the second coordinate is the "end". This + stat and end is then used to determine any parametric junctions with + other elements. + + Using an axis-representation is optional, but highly recommended for + "standard" representations of walls, beams, columns, and other + structural members. A rule of thumb is that if you can draw it as a line + on paper, you can probably represent it using an axis. + + :param context: The IfcGeometricRepresentationContext that the + representation is part of. This must be either a + Model/Axis/GRAPH_VIEW (3D) or Plan/Axis/GRAPH_VIEW (2D). + :type context: ifcopenshell.entity_instance.entity_instance + :param axis: The axis, as a list of two coordinates, the coordinates + being either a list of 2 or 3 float coordinates depending on whether + the axis is 2D or 3D. + :type axis: list[list[float]] + :return: The newly created IfcShapeRepresentation entity + :rtype: ifcopenshell.entity_instance.entity_instance + + Example:: + + context = ifcopenshell.util.representation.get_context(model, "Plan", "Axis", "GRAPH_VIEW") + axis = ifcopenshell.api.run("geometry.add_axis_representation", model, + context=context, axis=[(0.0, 0.0), (1.0, 0.0)]) + """ self.file = file self.settings = { - "context": None, # IfcGeometricRepresentationContext - "axis": [], # A list of ordered coordinates for the axis + "context": context, + "axis": axis or [], } - for key, value in settings.items(): - self.settings[key] = value def execute(self): self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file) diff --git a/src/ifcopenshell-python/ifcopenshell/api/georeference/add_georeferencing.py b/src/ifcopenshell-python/ifcopenshell/api/georeference/add_georeferencing.py index db7946c153..cb3d68afb2 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/georeference/add_georeferencing.py +++ b/src/ifcopenshell-python/ifcopenshell/api/georeference/add_georeferencing.py @@ -18,7 +18,27 @@ class Usecase: - def __init__(self, file, **settings): + def __init__(self, file): + """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. + + 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 + + Example:: + + ifcopenshell.api.run("georeference.add_georeferencing", model) + """ self.file = file def execute(self): diff --git a/src/ifcopenshell-python/ifcopenshell/api/georeference/edit_georeferencing.py b/src/ifcopenshell-python/ifcopenshell/api/georeference/edit_georeferencing.py index 62728d59ff..62fa266891 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/georeference/edit_georeferencing.py +++ b/src/ifcopenshell-python/ifcopenshell/api/georeference/edit_georeferencing.py @@ -18,15 +18,73 @@ class Usecase: - def __init__(self, file, **settings): + 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://blenderbim.org/docs/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:: + + 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": {}, - "projected_crs": {}, - "true_north": [], + "map_conversion": map_conversion or {}, + "projected_crs": projected_crs or {}, + "true_north": true_north or [], } - for key, value in settings.items(): - self.settings[key] = value def execute(self): map_conversion = self.file.by_type("IfcMapConversion")[0] diff --git a/src/ifcopenshell-python/ifcopenshell/api/georeference/remove_georeferencing.py b/src/ifcopenshell-python/ifcopenshell/api/georeference/remove_georeferencing.py index bdad937812..2ac32a0c6e 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/georeference/remove_georeferencing.py +++ b/src/ifcopenshell-python/ifcopenshell/api/georeference/remove_georeferencing.py @@ -18,7 +18,21 @@ class Usecase: - def __init__(self, file, **settings): + def __init__(self, file): + """Remove georeferencing data + + All georeferencing parameters such as projected CRS and map conversion + data will be lost. + + :return: None + :rtype: None + + Example: + + ifcopenshell.api.run("georeference.add_georeferencing", model) + # Let's change our mind + ifcopenshell.api.run("georeference.remove_georeferencing", model) + """ self.file = file def execute(self):