diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/code_examples.rst b/src/ifcopenshell-python/docs/ifcopenshell-python/code_examples.rst index 81b2e576f5..93700e9985 100644 --- a/src/ifcopenshell-python/docs/ifcopenshell-python/code_examples.rst +++ b/src/ifcopenshell-python/docs/ifcopenshell-python/code_examples.rst @@ -174,7 +174,7 @@ Get the distribution system of an element Copy an entity instance ----------------------------------------- -Copy an entity instance is possible in different ways, depending on the task. +Copy an entity instance is possible in different ways, depending on the task. .. code-block:: python @@ -192,7 +192,7 @@ This is for shallow copies. That is, associated things like the element's type, wall_deepgraph_copy = ifcopenshell.util.element.copy_deep(model, wall, exclude = None) -This is for deep graph copy. Like shallow copy, it does not copy over things like associated type/properties/quantities, but it does copy the representation and placement. +This is for deep graph copy. Like shallow copy, it does not copy over things like associated type/properties/quantities, but it does copy the representation and placement. Also note that ifcopenshell.file.add() can be used to copy instances from one file to the other. @@ -202,7 +202,7 @@ Also note that ifcopenshell.file.add() can be used to copy instances from one fi g = ifcopenshell.file(schema=f.schema) g.add(f.by_type(...)[0]) -Note that, in this case, it does copy over recursively, however, it does not make any other attempts at resulting in a valid file. Factor in things like length unit conversion if both files (f and g) have project length unit defined. +Note that, in this case, it does copy over recursively, however, it does not make any other attempts at resulting in a valid file. Factor in things like length unit conversion if both files (f and g) have project length unit defined. Create a simple model from scratch ---------------------------------- @@ -256,3 +256,73 @@ Create a simple model from scratch Here is the result: .. image:: images/simple-model.png + + +Create a work schedule constructing a building floor by floor +------------------------------------------------------------- + +.. code-block:: python + + import datetime + import ifcopenshell + from ifcopenshell.api import run + from ifcopenshell.util.element import get_decomposition + from ifcopenshell.util.placement import get_storey_elevation + + # Define a convenience function to add a task chained to a predecessor + def add_task(model, name, predecessor, work_schedule): + # Add a construction task + task = run("sequence.add_task", model, + work_schedule=work_schedule, name=name, predefined_type="CONSTRUCTION") + + # Give it a time + task_time = run("sequence.add_task_time", model, task=task) + + # Arbitrarily set the task's scheduled time duration to be 1 week + run("sequence.edit_task_time", model, task_time=task_time, + attributes={"ScheduleStart": datetime.date(2000, 1, 1), "ScheduleDuration": "P1W"}) + + # If a predecessor exists, create a finish to start relationship + if predecessor: + run("sequence.assign_sequence", model, relating_process=predecessor, related_process=task) + + return task + + # Open an existing IFC4 model you have of a building + model = ifcopenshell.open("/path/to/existing/model.ifc") + + # Create a new construction schedule + schedule = run("sequence.add_work_schedule", model, name="Construction") + + # Let's imagine a starting task for site establishment. + task = add_task(model, "Site establishment", None, schedule) + start_task = task + + # Get all our storeys sorted by elevation ascending. + storeys = sorted(model.by_type("IfcBuildingStorey"), key=lambda s: get_storey_elevation(s)) + + # For each storey ... + for storey in storeys: + + # Add a construction task to construct that storey, using our convenience function + task = add_task(model, f"Construct {storey.Name}", task, schedule) + + # Assign all the products in that storey to the task as construction outputs. + for product in get_decomposition(storey): + run("sequence.assign_product", model, relating_product=product, related_object=task) + + # Ask the computer to calculate all the dates for us from the start task. + # For example, if the first task started on the 1st of January and took a + # week, the next task will start on the 8th of January. This saves us + # manually doing date calculations. + run("sequence.cascade_schedule", model, task=start_task) + + # Calculate the critical path and floats. + run("sequence.recalculate_schedule", model, work_schedule=schedule) + + # Write out to a file + model.write("/home/dion/model.ifc") + +Here is the result: + +.. image:: images/simple-work-schedule.png diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/images/simple-work-schedule.png b/src/ifcopenshell-python/docs/ifcopenshell-python/images/simple-work-schedule.png new file mode 100644 index 0000000000..3e4779024c Binary files /dev/null and b/src/ifcopenshell-python/docs/ifcopenshell-python/images/simple-work-schedule.png differ