diff --git a/src/ifcopenshell-python/docs/_static/custom.css b/src/ifcopenshell-python/docs/_static/custom.css new file mode 100644 index 0000000000..4ecfae2065 --- /dev/null +++ b/src/ifcopenshell-python/docs/_static/custom.css @@ -0,0 +1,17 @@ +.blockbutton { + border: 1px solid var(--color-admonition-title--seealso); + background-color: var(--color-admonition-title-background--seealso); + padding: 5px; + text-align: center; + border-radius: 5px; + max-width: 500px; + margin-left: auto; + margin-right: auto; +} +section img { + display: block; + margin-left: auto; + margin-right: auto; + box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; + border-radius: 5px; +} diff --git a/src/ifcopenshell-python/docs/conf.py b/src/ifcopenshell-python/docs/conf.py index e632b18838..c4df1f62d3 100644 --- a/src/ifcopenshell-python/docs/conf.py +++ b/src/ifcopenshell-python/docs/conf.py @@ -97,3 +97,5 @@ html_theme = "furo" # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] + +html_css_files = ["custom.css"] diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python.rst b/src/ifcopenshell-python/docs/ifcopenshell-python.rst index 4902bc9157..2a6169fefa 100644 --- a/src/ifcopenshell-python/docs/ifcopenshell-python.rst +++ b/src/ifcopenshell-python/docs/ifcopenshell-python.rst @@ -1,19 +1,15 @@ IfcOpenShell-Python =================== -This documentation is free software! You are free to contribute and help write -this document. +IfcOpenShell-Python provides Python bindings to the core IfcOpenShell C++ +system, as well as high level analysis and authoring functions. .. toctree:: + :hidden: :maxdepth: 1 :caption: Contents: + ifcopenshell-python/installation ifcopenshell-python/hello_world + ifcopenshell-python/code_examples ifcopenshell-python/developer_guide - -Indices and tables ------------------- - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-python-console-1.png b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-python-console-1.png new file mode 100644 index 0000000000..5dc44b5a07 Binary files /dev/null and b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-python-console-1.png differ diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-python-console-2.png b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-python-console-2.png new file mode 100644 index 0000000000..47b6cddd71 Binary files /dev/null and b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-python-console-2.png differ diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-text-editor-1.png b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-text-editor-1.png new file mode 100644 index 0000000000..252f18faf0 Binary files /dev/null and b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-text-editor-1.png differ diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-text-editor-2.png b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-text-editor-2.png new file mode 100644 index 0000000000..7240cfd220 Binary files /dev/null and b/src/ifcopenshell-python/docs/ifcopenshell-python/blenderbim-text-editor-2.png differ diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/code_examples.rst b/src/ifcopenshell-python/docs/ifcopenshell-python/code_examples.rst new file mode 100644 index 0000000000..72102bdd58 --- /dev/null +++ b/src/ifcopenshell-python/docs/ifcopenshell-python/code_examples.rst @@ -0,0 +1,4 @@ +Code examples +============= + +TODO diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/hello_world.rst b/src/ifcopenshell-python/docs/ifcopenshell-python/hello_world.rst index 333020cfa8..34e2a0fa7d 100644 --- a/src/ifcopenshell-python/docs/ifcopenshell-python/hello_world.rst +++ b/src/ifcopenshell-python/docs/ifcopenshell-python/hello_world.rst @@ -1,7 +1,219 @@ Hello, world! ============= -For starters, you can read `Using IfcOpenShell to parse IFC files with Python -`_ +What's inside an IFC? +--------------------- TODO + +Core functionality crash course +------------------------------- + +This crash course guides you through basic code snippets that give you a general +idea of the low-level functionality that IfcOpenShell-python provides. You'll +need to have IfcOpenShell installed and a sample IFC model. To get the most out +of it, try out the code yourself and see what results you get! + +If you don't have an IFC model available, here's a small one for your +convenience provided by the Institute for Automation and Applied Informatics +(IAI) / Karlsruhe Institute of Technology. It's in German, so you may need to +use some creativity when reading the data :) + +.. container:: blockbutton + + `Download sample IFC `__ + +.. seealso:: + + You can find more sample models online in the `OSArch Open Data Directory + `__ + +Let's start with loading the model. Import the IfcOpenShell module, then use the +``open`` function to load the model into a variable called ``model``. + +.. code-block:: python + + import ifcopenshell + model = ifcopenshell.open('/path/to/your/model.ifc') + +Let's see what IFC schema we are using: + +.. code-block:: python + + print(model.schema) # May return IFC2X3 or IFC4 + +Let's get the first piece of data in our IFC file: + +.. code-block:: python + + print(model.by_id(1)) + +But getting data from beginning to end isn't too meaningful to humans. What if we knew a ``GlobalId`` value instead? + +.. code-block:: python + + print(model.by_guid('0EI0MSHbX9gg8Fxwar7lL8')) + +If we're not looking specifically for a single element, perhaps let's see how many walls are in our file, and count them: + +.. code-block:: python + + walls = model.by_type('IfcWall') + print(len(walls)) + +Once we have an element, we can see what IFC class it is: + +.. code-block:: python + + wall = model.by_type('IfcWall')[0] + print(wall.is_a()) # Returns 'IfcWall' + +You can also test if it is a certain class, as well as check for parent classes too: + +.. code-block:: python + + print(wall.is_a('IfcWall')) # Returns True + print(wall.is_a('IfcElement')) # Returns True + print(wall.is_a('IfcWindow')) # Returns False + +Let's quickly check the STEP ID of our element: + +.. code-block:: python + + print(wall.id()) + +Let's get some attributes of an element. IFC attributes have a particular order. We can access it just like a list, so let's get the first and third attribute: + +.. code-block:: python + + print(wall[0]) # The first attribute is the GlobalId + print(wall[2]) # The third attribute is the Name + +Knowing the order of attributes is boring and technical. We can access them by name too: + +.. code-block:: python + + print(wall.GlobalId) + print(wall.Name) + +Getting attributes one by one is tedious. Let's grab them all: + +.. code-block:: python + + # Gives us a dictionary of attributes, such as: + # {'id': 8, 'type': 'IfcWall', 'GlobalId': '2_qMTAIHrEYu0vYcqK8cBX', ... } + print(wall.get_info()) + +Let's see all the properties and quantities associated with this wall: + +.. code-block:: python + + import ifcopenshell.util + import ifcopenshell.util.element + print(ifcopenshell.util.element.get_psets(wall)) + +Some attributes are special, called "inverse attributes". They happen when another element is referencing our element. They can reference it for many reasons, like to define a relationship, such as if they create a void in our wall, join our wall, or define a quantity take-off value for our wall, among others. Just treat them like regular attributes: + +.. code-block:: python + + print(wall.IsDefinedBy) + +Perhaps we want to see all elements which are referencing our wall? + +.. code-block:: python + + print(model.get_inverse(wall)) + +Let's do the opposite, let's see all the elements which our wall references instead: + +.. code-block:: python + + print(model.traverse(wall)) + # Or, let's just go down one level deep + print(model.traverse(wall, max_levels=1)) + +If you want to modify data, just assign it to the relevant attribute: + +.. code-block:: python + + wall.Name = 'My new wall name' + +You can also generate a new ``GlobalId``: + +.. code-block:: python + + wall.GlobalId = ifcopenshell.guid.new() + +After modifying some IFC data, you can save it to a new IFC-SPF file: + +.. code-block:: python + + model.write('/path/to/a/new.ifc') + +You can generate a new IFC from scratch too, instead of reading an existing one: + +.. code-block:: python + + ifc = ifcopenshell.file() + # Or if you want a particular schema: + ifc = ifcopenshell.file(schema='IFC4') + +You can create new IFC elements, and add it either to an existing or newly created IFC file object: + +.. code-block:: python + + # Will return #1=IfcWall($,$,$,$,$,$,$,$,$) - notice all of the attributes are blank! + new_wall = model.createIfcWall() + # Will return a list with our wall in it: [#1=IfcWall($,$,$,$,$,$,$,$,$)] + print(model.by_type('IfcWall')) + +Alternatively, you can also use this way to create new elements: + +.. code-block:: python + + model.create_entity('IfcWall') + +Specifying more arguments lets you fill in attributes while creating the element instead of assigning them separately. You specify them in the order of the attributes. + +.. code-block:: python + + # Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,$,$,$,$,$,$,$) + model.create_entity('IfcWall', ifcopenshell.guid.new()) + +Again, knowing the order of attributes is difficult, so you can use keyword arguments instead: + +.. code-block:: python + + # Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,'Wall Name',$,$,$,$,$,$) + model.create_entity('IfcWall', GlobalId=ifcopenshell.guid.new(), Name='Wall Name') + +Sometimes, it's easier to expand a dictionary: + +.. code-block:: python + + data = { + 'GlobalId': ifcopenshell.guid.new(), + 'Name': 'Wall Name' + } + model.create_entity('IfcWall', **data) + +Some attributes of an element aren't just text, they may be a reference to another element. Easy: + +.. code-block:: python + + wall = model.createIfcWall() + wall.OwnerHistory = model.createIfcOwnerHistory() + +What if we already have an element from one IFC file and want to add it to another? + +.. code-block:: python + + wall = model.by_type('IfcWall')[0] + new_model = ifcopenshell.file() + new_model.add(wall) + +Fed up with an object? Let's delete it: + +.. code-block:: python + + model.remove(wall) diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/installation.rst b/src/ifcopenshell-python/docs/ifcopenshell-python/installation.rst new file mode 100644 index 0000000000..1f7eb8b5ce --- /dev/null +++ b/src/ifcopenshell-python/docs/ifcopenshell-python/installation.rst @@ -0,0 +1,139 @@ +Installation +============ + +There are different methods of installation, depending on your situation. + +1. **Pre-built packages** is recommended for users wanting to use the latest IfcOpenShell builds. +2. **Pip** is recommended for managing a more stable IfcOpenShell version. +3. **Conda** is recommended for developers using Anaconda. +4. **Using the BlenderBIM Add-on** is recommended for non-developers wanting a graphical interface. +5. **Compiling from source** is recommended for developers actively working with the C++ core. + +Pre-built packages +------------------ + +1. Choose which version to download based on your operating system, Python + version, and computer architecture. + + +-------------+----------------+----------------+----------------+----------------+ + | | Linux 64bit | Windows 32bit | Windows 64bit | MacOS 64bit | + +=============+================+================+================+================+ + | Python 3.6 | py36-linux64_ | py36-win32_ | py36-win64_ | py36-macos64_ | + +-------------+----------------+----------------+----------------+----------------+ + | Python 3.7 | py37-linux64_ | py37-win32_ | py37-win64_ | py37-macos64_ | + +-------------+----------------+----------------+----------------+----------------+ + | Python 3.8 | py38-linux64_ | py38-win32_ | py38-win64_ | py38-macos64_ | + +-------------+----------------+----------------+----------------+----------------+ + | Python 3.9 | py39-linux64_ | py39-win32_ | py39-win64_ | py39-macos64_ | + +-------------+----------------+----------------+----------------+----------------+ + | Python 3.10 | py31-linux64_ | py31-win32_ | py31-win64_ | py31-macos64_ | + +-------------+----------------+----------------+----------------+----------------+ + +.. _py36-linux64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-36-v0.7.0-1b1fd1e-linux64.zip +.. _py37-linux64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-37-v0.7.0-1b1fd1e-linux64.zip +.. _py38-linux64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-38-v0.7.0-1b1fd1e-linux64.zip +.. _py39-linux64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-39-v0.7.0-1b1fd1e-linux64.zip +.. _py31-linux64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-31-v0.7.0-1b1fd1e-linux64.zip +.. _py36-win32: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-36-v0.7.0-1b1fd1e-win64.zip +.. _py37-win32: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-37-v0.7.0-1b1fd1e-win64.zip +.. _py38-win32: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-38-v0.7.0-1b1fd1e-win64.zip +.. _py39-win32: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-39-v0.7.0-1b1fd1e-win64.zip +.. _py31-win32: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-31-v0.7.0-1b1fd1e-win64.zip +.. _py36-win64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-36-v0.7.0-1b1fd1e-win64.zip +.. _py37-win64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-37-v0.7.0-1b1fd1e-win64.zip +.. _py38-win64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-38-v0.7.0-1b1fd1e-win64.zip +.. _py39-win64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-39-v0.7.0-1b1fd1e-win64.zip +.. _py31-win64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-31-v0.7.0-1b1fd1e-win64.zip +.. _py36-macos64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-36-v0.7.0-1b1fd1e-macos64.zip +.. _py37-macos64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-37-v0.7.0-1b1fd1e-macos64.zip +.. _py38-macos64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-38-v0.7.0-1b1fd1e-macos64.zip +.. _py39-macos64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-39-v0.7.0-1b1fd1e-macos64.zip +.. _py31-macos64: https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-31-v0.7.0-1b1fd1e-macos64.zip + +.. warning:: + + Versions for Mac ARM devices (M1 chip) are not yet available. You are free to + compile it yourself manually, but this requires a level of technical + expertise. + +2. Copy the ``ifcopenshell`` directory into your Python path. If you're not sure + where your Python path is, run the following code in Python: + + .. code-block:: python + + import sys + print(sys.path) + + This will give you a list of possible directories that you can install the + IfcOpenShell module into. Most commonly, you will want to copy the + ``ifcopenshell`` directory into one of these called ``site-packages``. + +3. Test importing the module in a Python session or script to make sure it works. + + .. code-block:: python + + import ifcopenshell + print(ifcopenshell.version) + model = ifcopenshell.file() + +Pip +--- + +TODO + +Conda +----- + +TODO + +Using the BlenderBIM Add-on +--------------------------- + +The BlenderBIM Add-on is a Blender based graphical interface to IfcOpenShell. +Other than providing a graphical IFC authoring platform, it also comes with +IfcOpenShell and a Python shell built-in. This means you don't need to install +Python first, and you also can compare your IfcOpenShell scripting to what you +see with a visual model viewer. + +1. Install the BlenderBIM Add-on by following the `BlenderBIM Add-on + installation documentation + `_. + +2. Launch Blender. On the top left of the Viewport panel, click the **Editor + Type** icon to change the viewport into a **Python Console**. + + .. image:: blenderbim-python-console-1.png + +3. Make sure you can import IfcOpenShell successfully with the following script. + + .. image:: blenderbim-python-console-2.png + +.. tip:: + + Before changing the **Editor Type** to a **Python Console**, you can click on + the ``View > Area > Vertical Split`` menu which will divide your viewport. + This allows you to write scripts next to the 3D view of a model. + +Blender also comes with a text editor so you can write longer scripts. Instead +of choosing the **Python Console**, choose the **Text Editor**. + +.. image:: blenderbim-text-editor-1.png + +You can now create a new text file for your script by clicking ``Text > New``, +and run your script using the **Text > Run Script** menu or by clicking on the +**Play Icon**. + +.. image:: blenderbim-text-editor-2.png + +.. seealso:: + + You may be interested in learning how to graphically explore an IFC model in + Blender. This can help when learning how to write scripts as you can double + check the results of your scripts with what you see in the graphical + interface. `Read more + `_. + +Compiling from source +--------------------- + +TODO