From 5d48dc15c14ad27b37bcb2d9ff9d3b9fe5085885 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 23 Jul 2023 23:03:53 +1000 Subject: [PATCH] Finish writing documentation on geometry creation --- .../ifcopenshell-python/geometry_creation.rst | 234 +++++++++++++++++- .../images/custom-representation.png | Bin 0 -> 16669 bytes .../images/manual-representation.png | Bin 0 -> 8839 bytes 3 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 src/ifcopenshell-python/docs/ifcopenshell-python/images/custom-representation.png create mode 100644 src/ifcopenshell-python/docs/ifcopenshell-python/images/manual-representation.png diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_creation.rst b/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_creation.rst index c1f5fc2343..20f25deeb1 100644 --- a/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_creation.rst +++ b/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_creation.rst @@ -45,6 +45,12 @@ is intended to be viewed. For example, a "2D Plan View" might be a **Representation Context**. This allows the user to choose to see the appropriate **Representation**. +A **Representation** contains one or more **Representation Items**. Each +**Representation Item** could be an extrusion, a mesh, a surface, a curve, and +so on depending on the type of geometric modeling technique. Techniques cannot +be mixed, so a single **Representation** may be made out of multiple extrusion +**Items** but cannot have both extrusions and meshes. + Objects may also have the concept of **Types** and **Material Sets** that inform their shape. For example, if a light fixture **Type** has a **Representation**, all occurrences of that light fixture must have the exact @@ -56,11 +62,15 @@ column **Type** has a **Material Set** defining a cross sectional profile, then all occurrences of that column type must have the same cross section (although the height of the column may vary). -The vast majority of objects in the built environment use **Types** and -**Material Sets**, such as slabs, walls, columns, beams, doors, windows, -and furniture. For this reason, it is highly recommended to not just create -**Representations** for individual objects, but first consider creating a -**Type**. +.. seealso:: + + The vast majority of objects in the built environment use **Types** and + **Material Sets**, such as slabs, walls, columns, beams, doors, windows, + and furniture. For this reason, it is highly recommended to not just create + **Representations** for individual objects, but first consider creating a + **Type**. After you get a general understanding of **Representations**, + please read the section on `Types and mapped representations`_, `Material + layer sets`_, and `Material profile sets`_. Project units ------------- @@ -459,14 +469,228 @@ Placement** to place the element on its side. Custom representations ---------------------- +You may also create your own solid by creating multiple custom profiles, +extruding them into solids, then combining the solids into your own shapes. For +example, a table may be formed by 5 rectangular extrusions: one for the table +top, and 4 table legs. This can be done using the shape builder utility module. + +The standard approach is: + +1. Define at least one 2D outer curve and optional inner curves (for holes). +2. Optionally convert your outer and optional inner curves into a profile. This + is only necessary if you want to give your profile a name (so that you may + reuse it and manage it in a profile library) or if you have inner curves. +3. Optionally extrude your profile into a solid. If you are creating 2D + representations, then extrusion is not necessary. +4. Optionally move your extruded solid into your desired location through + translation, rotation, or mirroring. +5. Convert all your extruded solids (or just curves, if 2D) into a + **Representation** with a **Representation Context**. + +Here is an example which generates a parametric table. + +.. code-block:: python + + # The shape_builder module depends on mathutils + from ifcopenshell.util.shape_builder import V + + builder = ifcopenshell.util.shape_builder.ShapeBuilder(model) + + # Parameters to define our table + width = 1200 + depth = 700 + height = 750 + leg_size = 50.0 + thickness = 50.0 + + # Extrude a rectangle profile for the tabletop + rectangle = builder.rectangle(size=V(width, depth)) + tabletop = builder.extrude(builder.profile(rectangle), thickness, V(0, 0, height - thickness)) + + # Create a table leg curve, mirror it along two axes, and extrude. + leg_curve = builder.rectangle(size=V(leg_size, leg_size)) + legs_curves = [leg_curve] + builder.mirror( + leg_curve, + mirror_axes=[V(1, 0), V(0, 1), V(1, 1)], + mirror_point=V(width / 2, depth / 2), + create_copy=True, + ) + legs_profiles = [builder.profile(leg) for leg in legs_curves] + legs = [builder.extrude(leg, height - thickness) for leg in legs_profiles] + + # Shift our table such that the object origin is in the center. + items = [tabletop] + legs + shift_to_center = V(-width / 2, -depth / 2) + builder.translate(items, shift_to_center.to_3d()) + + # Create a body representation + body = ifcopenshell.util.representation.get_context(model, "Model", "Body", "MODEL_VIEW") + representation = builder.get_representation(context=body, items=items) + +.. image:: images/custom-representation.png + +For more information, consult the :doc:`shape builder documentation +`. + Manual representations ---------------------- +Although IfcOpenShell provides many convenience functions and utility modules, +you may wish to disregard this and manually create each IFC class yourself. +This is generally not recommended but is useful as an educational exercise or +if you want to create a particularly bespoke shape that IfcOpenShell does not +have a convenience function for yet. You will be required to have a detailed +understanding of IFC geometry which is explained in the IFC documentation. + +Here is an example of manually creating a simple extruded rectangle. + +.. code-block:: python + + rectangle = model.createIfcRectangleProfileDef(ProfileType="AREA", XDim=500, YDim=250) + direction = model.createIfcDirection((0., 0., 1.)) + extrusion = model.createIfcExtrudedAreaSolid(SweptArea=rectangle, ExtrudedDirection=direction, Depth=1000) + body = ifcopenshell.util.representation.get_context(model, "Model", "Body", "MODEL_VIEW") + representation = model.createIfcShapeRepresentation( + ContextOfItems=body, RepresentationIdentifier="Body", RepresentationType="SweptSolid", Items=[extrusion]) + +.. image:: images/manual-representation.png + Types and mapped representations -------------------------------- +Very often, the **Representation** of a type is exactly the same for all of its +occurrences. For example, all furniture, equipment (pumps, valves, dampers, +etc) occurrences will be exactly the same. + +In this scenario, the **Representation** should be assigned to the type. Each +of the occurrences will then use a **Mapped Representation**. This is both +efficient and implies that the type is interchangable (e.g. for maintenance). + +.. code-block:: python + + # Create our element type. Types do not have an object placement. + element_type = run("root.create_entity", model, ifc_class="IfcFurnitureType") + + # Let's create our representation! + # See above sections for examples on how to create representations. + representation = ... + + # Assign our representation to the element type. + run("geometry.assign_representation", model, product=element_type, representation=representation) + + # Create our element occurrence with an object placement. + element = run("root.create_entity", model, ifc_class="IfcFurniture") + run("geometry.edit_object_placement", model, product=element) + + # Assign our furniture occurrence to the type. + # That's it! The representation will automatically be mapped! + run("type.assign_type", model, related_object=element, relating_type=element_type) + Material layer sets ------------------- +If a type has a material layer set, it implies that all occurrences of that +type must use the same material layer set. For example, if a wall type has +multiple material layers adding up to a thickness of 100mm, then all walls of +that wall type must be exactly 100mm thick. The height, length, angle or +curvature of the wall may vary, but the thickness may not. + +Because only the thickness is fixed, you are still responsible for creating the +representation of walls yourself. IfcOpenShell will not check whether or not +your representation complies with the thickness constraint, so it is your +responsibility to make sure the geometry is correct. + +.. code-block:: python + + # Let's imagine a wall type called WAL01 using a material layer set. + wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01") + + # First, let's create a material set. This will later be assigned to our wall type element. + material_set = ifcopenshell.api.run("material.add_material_set", model, + name="GYP-ST-GYP", set_type="IfcMaterialLayerSet") + + # Let's create a few materials. + gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum") + steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel") + + # Create 3 layers for a steel studded plasterboard wall. + layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum) + ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13}) + layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel) + ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 92}) + layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum) + ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13}) + + # Great! Let's assign our material set to our wall type. + ifcopenshell.api.run("material.assign_material", model, product=wall_type, material=material_set) + + # Now, let's create a wall at the origin. + wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall") + ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall) + + # The wall is a WAL01 wall type. The material layer set is inherited. + ifcopenshell.api.run("type.assign_type", model, related_object=wall, relating_type=wall_type) + + # It's now our responsibility to create a compatible representation. + # Notice how our thickness of 0.118 must equal .013 + .092 + .013 from our type + body = ifcopenshell.util.representation.get_representation(element, "Model", "Body") + representation = ifcopenshell.api.run("geometry.add_wall_representation", model, + context=body, length=5, height=3, thickness=0.118) + + # Assign our new body geometry back to our wall + ifcopenshell.api.run("geometry.assign_representation", model, product=wall, representation=representation) + Material profile sets --------------------- + +If a type has a material profile set, it implies that all occurrences of that +type must use the same material profile set. For example, if a beam type has a +material profile of an "I-shape", then all beams of that beam type must use +that exact same I-shape profile. The length, angle or curvature of the beam may +vary, but the cross sectional profile may not. + +Because only the profile is fixed, you are still responsible for creating the +representation of walls yourself. IfcOpenShell will not check whether or not +your representation complies with the profile constraint, so it is your +responsibility to make sure the geometry is correct. + +.. code-block:: python + + # Let's imagine we have a steel I-beam type called B1. + beam_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeamType", name="B1") + + # First, let's create a material set. This will later be assigned to our beam type element. + material_set = ifcopenshell.api.run("material.add_profile_set", model, + name="B1", set_type="IfcMaterialProfileSet") + + # Create a steel material. + steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel") + + # Create an I-beam profile curve. Notice how we use standardised steel profile names. + hea100 = self.file.create_entity( + "IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA", + OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12, + ) + + # Define that steel material and cross section as a single profile item. If + # this were a composite beam, we might add multiple profile items instead, + # but this is rarely the case in most construction. + ifcopenshell.api.run("material.add_profile", model, profile_set=material_set, material=steel, profile=hea100) + + # Great! Let's assign our material set to our beam type. + ifcopenshell.api.run("material.assign_material", model, product=beam_type, material=material_set) + + # Now, let's create a beam at the origin. + beam = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeam") + ifcopenshell.api.run("geometry.edit_object_placement", model, product=beam) + + # The beam is a B1 beam type. The material profile set is inherited. + ifcopenshell.api.run("type.assign_type", model, related_object=beam, relating_type=beam_type) + + # It's now our responsibility to create a compatible representation. + # Notice how we reuse our profile instead of creating a new profile. + body = ifcopenshell.util.representation.get_representation(element, "Model", "Body") + representation = run("geometry.add_profile_representation", model, context=body, profile=hea100, depth=1) + + # Assign our new body geometry back to our beam + ifcopenshell.api.run("geometry.assign_representation", model, product=beam, representation=representation) diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/images/custom-representation.png b/src/ifcopenshell-python/docs/ifcopenshell-python/images/custom-representation.png new file mode 100644 index 0000000000000000000000000000000000000000..07bcff2cc05b643d2387e12cd70fe645f2e0b863 GIT binary patch literal 16669 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 JPDHLkV1m0A?I!>L literal 0 HcmV?d00001