Export IFC/NWC with saved config

Does anyone know if it’s possible to use the Export IFC/NWC nodes but instead of filling in all the export options, i simply choose a saved export setup, like with the Export DWG node?

Tagging @Alban_de_Chasteigner since im using your nodes :slight_smile:

Hi @Garbage_Collector,

There is a ExportDWGSettings class in the API but I can’t see a ExportIfcSettings or a ExportNWCSettings.
You could store your settings in a text format and read them when needed on the fly.

1 Like

Ahh ok ill try that then :slight_smile:
While i have you here,
Is there a reason why the IFC export node doesnt have a runIt input? Can i toggle this node another way to prevent it from running?

This class might be relevant, but I am not sure it has what you need.

As the content doesn’t save to the file (as best I know) you likely will want to serialize the settings into an external data source (perhaps even into the .dyn itself), or perhaps save it into extensible storage somewhere.

Edit: the NWC export settings class is here: NavisworksExportOptions Class

2 Likes

I was looking for these:
NWC
image

IFC:
image

Especially the IFC settings have so many variables… I was hoping for a way to let the user manually export these settings once for a project and then target the export settings with a filepath input. Ill look into the classes, although i fear it is over my head since i’d have to change Alban’s node a lot…

Yes - I don’t believe the saved settings are available via the API. They may be in a class that isn’t readily exposed, but getting the ‘right one’ once saved is tough.

The good thing with the external file is you can read say a JSON with the input values (strongly json to format a list as a JSON before writing to a text document, and parse json to read the string into a usable format) which can then be fed directly into Alban’s nodes. No changes required. :blush:

1 Like

Thank you very much :slight_smile: I’ll try this out and hopefully end up with a good batch IFC/DWG/NWC 3D view exporter :sunglasses:
Will report back!

1 Like

Hi,

for IFC, here is a workaround with BIM.IFC.Export.UI namespace to retrieve project user configurations

see here (use the translation widget on my blog)

for Navisworks I didn’t study yet to know if it was possible

5 Likes

This is awesome!

Only when using Albans node, it still skips a ton of settings defined in the preconfigured settings no? A bunch of settings have been hard coded/omitted in his Python script if i fecal correctly (not at computer now).

If I wanted to use every variable in the saved settings I’d have to change the code for Albans node right?

1 Like

HI,

Yes you can edit the python node to add other inputs.
I prefer to avoid custom nodes with too many inputs.

3 Likes

Not really related but im having trouble displaying whatever comes out of the python script for some reason…

Im unable to see whats inside the dict and cant scale my watch nodes (im on revit 2023, dynamo 2.16


@jacob.small Do you know why my nodes arent displaying the data correctly?

Usually because the data in the node doesnt have a wrapper to a Dynamo type or is otherwise un-watchable. Outputting some types of Python dictionaries, or Revit elements without converting to a Dynamo element can cause this.

1 Like

Hi @Alban_de_Chasteigner

I have altered your node to also accept an IFC config extracted from the current document with the help of @c.poupin 's post.

Perhaps you could absorb it into your version if you agree with the changes… I’ve added comments wherever i made changes.

It accepts an optional ifcExportConfig, if it’s provided, it will set all the options based on the config instead of the hard coded and optional user input.

#Based on a Nicklas Verdier Østergaard's script, nvo@niras.dk
#https://github.com/Autodesk/revit-ifc/tree/2810c479e27819da97656759a1dda28cbdde0538/Source
#Revised by Alban de Chasteigner

import clr
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

def tolist(obj1):
    if hasattr(obj1,"__iter__"): return obj1
    else: return [obj1]
#REMARK: Added this function to find IFC versions instead of if checks
def get_ifc_version(version_str):
    return {
        "IFC4": IFCVersion.IFC4,
        "IFC4RV": IFCVersion.IFC4RV,
        "IFC4DTV": IFCVersion.IFC4DTV,
        "IFC2x2": IFCVersion.IFC2x2,
        "IFC2x3": IFCVersion.IFC2x3,
        "IFC2x3CV2": IFCVersion.IFC2x3CV2,
        "IFC2x3BFM": IFCVersion.IFC2x3BFM,
        "IFC2x3FM": IFCVersion.IFC2x3FM,
        "IFCBCA": IFCVersion.IFCBCA,
        "IFCCOBIE": IFCVersion.IFCCOBIE,
        "": IFCVersion.Default
    }.get(version_str, IFCVersion.Default)
    
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

folder=UnwrapElement(IN[0])
view = tolist(UnwrapElement(IN[1]))
name=tolist(UnwrapElement(IN[2]))
fileversion = IN[3]
Projectorigin = IN[4]
inputPhase = UnwrapElement(IN[5])
userDefinedPset = IN[6]
revitInternalPset = IN[7]
wallandcolumnsplitting = IN[8]
exportbasequantities = IN[9]
config = IN[10]
test = ""

if inputPhase != None:
    phaseString=str(inputPhase.Id)
else:
    pass

if userDefinedPset != "":
    userDefPsetBool= "true"
else:
    userDefPsetBool= "false"

if revitInternalPset ==True:
    revitInternalPset= "true"
else:
    revitInternalPset= "false"

TransactionManager.Instance.EnsureInTransaction(doc)
result = []

for i,v in enumerate(view):
    options=IFCExportOptions()
    #REMARK: Added if check to pass this part if a config is provided.
    if config == None:
    	
    	#REMARK: Removed IF checks for IFC version and moved it to the get_ifc_version function
        options.FileVersion = get_ifc_version(fileversion)
            
        options.WallAndColumnSplitting = wallandcolumnsplitting
        options.ExportBaseQuantities = exportbasequantities
        options.FilterViewId = v.Id
        options.AddOption("ExportInternalRevitPropertySets",revitInternalPset)
        options.AddOption("ExportIFCCommonPropertySets","true")    
        options.AddOption("ExportAnnotations ","true")
        options.AddOption("SpaceBoundaries ", "0")
        options.AddOption("ExportRoomsInView", "false")    
        options.AddOption("Use2DRoomBoundaryForVolume ", "true")
        options.AddOption("UseFamilyAndTypeNameForReference ", "true")
        options.AddOption("Export2DElements", "false")
        options.AddOption("ExportPartsAsBuildingElements", "false")
        options.AddOption("ExportBoundingBox", "false")
        options.AddOption("ExportSolidModelRep", "true")
        options.AddOption("ExportSchedulesAsPsets", "false")
        options.AddOption("ExportSpecificSchedules", "false")
        
        #True doesn't work. It would be necessary to use OpenInBackground method.
        options.AddOption("ExportLinkedFiles", "false")
        
        options.AddOption("IncludeSiteElevation","true")
        options.AddOption("StoreIFCGUID", "true")
        options.AddOption("VisibleElementsOfCurrentView ", "true")
        options.AddOption("UseActiveViewGeometry", "true")
        options.AddOption("TessellationLevelOfDetail", "0,5")
        options.AddOption("ExportUserDefinedPsets",userDefPsetBool)
        if userDefinedPset != "":
            options.AddOption("ExportUserDefinedPsetsFileName",userDefinedPset)    
        else:
            pass
        if inputPhase != None:
            options.AddOption("ActivePhase", phaseString)
        else:
            pass
        options.AddOption("SitePlacement", IN[4])    
    #    options.AddOption("ClassificationName","x")
    #    options.AddOption("ClassificationFieldName","x")
#REMARK: Added this part. If config exists, we set all values based on the config. The standard options are set first, and then all additional options in the dict are added.
    if config:
    	options.FilterViewId = v.Id

    	for key, value in config.items():
			if key == "IFC_Version_str":
				options.FileVersion = get_ifc_version(value)
			elif key == "ExportBaseQuantities":
				options.ExportBaseQuantities = value
			elif key == "WallAndColumnSplitting":
				options.WallAndColumnSplitting = value
			else:
				options.AddOption(key, str(value))

    c=doc.Export(folder, name[i], options)
    result.append(c)

# End Transaction
TransactionManager.Instance.TransactionTaskDone()

if fileversion == "":
    OUT="Default settings used"
else:
    OUT= "Success"

Perhaps you or @c.poupin could also create a custom node to get an IFC export setting by name, im currently just letting the user select the name and then use that key to get its values with data shapes which then get fed into the ifc export node.

2 Likes