Project > Exchange
IFC Exporter
Writes the selected objects to an IFC4 file with storeys from their levels, IFC classes from their categories, colours, GlobalIds and property sets. Shift+Click to change which IFC class a category becomes.
Status
Untested Never executed inside Navisworks. Passed the headless checks only.
Related asks to confirm
No quote is on record yet. These threads look related, but a person still has to open and read them.
Events it listens to
None. It runs only when you click it.
Files
Paths are relative to the Playground.extension folder.
Project.tab/Exchange.panel/IFC_Exporter.pushbutton/bundle.yamlProject.tab/Exchange.panel/IFC_Exporter.pushbutton/config.pyProject.tab/Exchange.panel/IFC_Exporter.pushbutton/icon.dark.pngProject.tab/Exchange.panel/IFC_Exporter.pushbutton/icon.pngProject.tab/Exchange.panel/IFC_Exporter.pushbutton/icon.small.dark.pngProject.tab/Exchange.panel/IFC_Exporter.pushbutton/icon.small.pngProject.tab/Exchange.panel/IFC_Exporter.pushbutton/script.py
Install
- Only this tool. In Navisworks, click pyNavis > Playground, search for IFC Exporter, tick it and click Install.
- The whole extension. Download
Playground.extension.zip, unzip it, put thePlayground.extensionfolder in%APPDATA%\pyNavis\extensions\, and click pyNavis > Reload. IFC Exporter is on the Project tab, Exchange panel.
You need pyNavis 1.3.0 or later.
Tried it? Tell us whether it worked or not. That report is what moves a tool up the status ladder.
ReportSource
The tool's own files, word for word as published in pynavis/Playground. Paths are relative to the Playground.extension folder.
script.py
The script that runs on a click.
Project.tab/Exchange.panel/IFC_Exporter.pushbutton/script.py View on GitHub# -*- coding: utf-8 -*-
"""Writes the selected objects to an IFC4 file with storeys, classes, colours, GlobalIds and property sets."""
import os
from pynavis import doc as nwdoc
from pynavis import script, toast
from namo import config, ifc, ifcexport, items, progress, store, ui, xchg_common
NAME_TEMPLATE = '{file} - {date}'
IFC_FILTER = 'IFC files (*.ifc)|*.ifc'
def class_overrides():
"""The team's category -> IFC class overrides (Shift+Click to edit)."""
return ifcexport.stored_overrides(store.Store('ifc-class-map', scope='global').load({}))
def run():
if xchg_common.under_runner():
return
document = nwdoc.get_doc()
selected = items.selected(document)
if not selected:
toast.info('Nothing selected', 'Select the objects to export, then run IFC Exporter again.')
return
values = dict(ifcexport.DEFAULT_OPTIONS)
values.update(script.get_config(ifcexport.DEFAULT_OPTIONS))
stem = os.path.splitext(xchg_common.doc_title(document))[0]
fields = ifcexport.form_fields(values, config.get('project_name') or stem, stem)
answer = ui.form('IFC exporter', fields, ok='Export', width=560, intro=ifcexport.FORM_INTRO)
if answer is None:
return
values.update(answer)
script.save_config(dict((k, values[k]) for k in ifcexport.DEFAULT_OPTIONS))
path = xchg_common.ask_save(document, NAME_TEMPLATE, '.ifc', IFC_FILTER, 'Export IFC')
if path is None:
return
overrides = class_overrides()
seed = (xchg_common.doc_path(document) or xchg_common.doc_title(document)).lower()
def work(report):
read = ifcexport.collect(selected, document, values, progress=lambda f, label: report(f * 0.6, label))
if not read['records']:
return read, None, []
report(0.62, 'Placing objects on storeys')
model, dropped = ifcexport.model_for(read, document, values, os.path.basename(path), seed, overrides)
if not model['elements']:
return read, model, dropped
ifc.write(path, model, progress=lambda f, label: report(0.65 + 0.35 * f, label))
return read, model, dropped
try:
outcome = progress.run('Exporting IFC', work)
except (IOError, OSError) as error:
toast.error('Could not write the IFC file', '%s. Close it in any program that has it open, then try again.'
% error)
return
if outcome is progress.CANCELLED:
return
read, model, dropped = outcome
xchg_common.show_skipped('IFC exporter', read['skipped'], dropped)
written = len(model['elements']) if model else 0
storeys = len(set(e['storey'] for e in model['elements'])) if written else 0
level, message, detail = ifcexport.summary(written, len(read['skipped']) + len(dropped), read['sampled'],
storeys)
if written:
detail = xchg_common.where_text(detail, path)
toast.show(level, message, detail)
if written:
xchg_common.reveal(path)
run()
config.py
The Shift+Click action.
Project.tab/Exchange.panel/IFC_Exporter.pushbutton/config.py View on GitHub# -*- coding: utf-8 -*-
"""Sets which IFC class a category becomes in IFC Exporter, for the whole team."""
from pynavis import output, toast
from namo import ifcexport, store, ui, xchg_common
def run():
if xchg_common.under_runner():
return
holder = store.Store('ifc-class-map', scope='global')
current = ifcexport.stored_overrides(holder.load({}))
answer = ui.form('IFC classes', ifcexport.override_fields(current), ok='Save', width=600,
intro='These lines win over the built-in mapping for everyone who shares your '
'Playground team folder.')
if answer is None:
return
mapping, _errors = ifcexport.parse_overrides(answer['map'])
try:
holder.save(dict((category, list(mapping[category])) for category in mapping))
except (IOError, OSError) as error:
toast.error('Could not save the IFC classes', str(error))
return
if answer['show']:
output.set_title('IFC classes')
output.print_md('### Built-in IFC classes')
output.print_table(ifcexport.builtin_rows(), ['Category', 'IFC class', 'Predefined type'])
if mapping:
toast.success('Saved %d IFC class %s' % (len(mapping), 'rule' if len(mapping) == 1 else 'rules'),
holder.note or None)
else:
toast.success('Using the built-in IFC classes', holder.note or None)
run()
Library modules this tool uses
From the shared namo library, which installs with every tool. Each name opens the module on GitHub.
namo.configPlayground-wide settings: one JSON file shared by every Playground tool.namo.ifcA pure IFC4 (ISO 10303-21 STEP) writer for the IFC Exporter, plus the reader its tests use.namo.ifcexportIFC Exporter: which IFC class each object becomes, which storey it sits on, its property sets, and the walk that turns a Navisworks selection into a namo.ifc model.namo.itemsModel items: walking, collecting, identifying, measuring and showing them.namo.progressGlue between pyNavis' cancellable progress window and Playground's progress callbacks.namo.storePer-document and global JSON stores, in one of three places.namo.uiWPF building blocks for Playground tools, themed from the pyNavis design system.namo.xchg_commonSmall pieces the Geometry and IFC exporters share: where files go, default names, and the list of skipped objects in the output window.
bundle.yaml
The bundle contract: the keys pyNavis reads for this tool.
Project.tab/Exchange.panel/IFC_Exporter.pushbutton/bundle.yaml View on GitHubtitle: IFC\nExporter
tooltip: Writes the selected objects to an IFC4 file with storeys from their levels, IFC classes from their categories, colours, GlobalIds and property sets. Shift+Click to change which IFC class a category becomes.
context: selection