Repackage BlenderBIM Add-on in single add-on dir thanks to Stephen Leger from Archipack

This commit is contained in:
Dion Moult
2020-04-07 12:02:44 +10:00
parent df14ab57bf
commit 4c3051267e
51 changed files with 226 additions and 236 deletions
@@ -0,0 +1,187 @@
# Check if we are running in Blender before loading, to allow for multiprocessing
import sys
import os
bpy = sys.modules.get('bpy')
if bpy is not None:
import bpy
from . import ui, prop, operator
classes = (
operator.AssignClass,
operator.SelectClass,
operator.SelectType,
operator.SelectBcfFile,
operator.GetBcfTopics,
operator.ViewBcfTopic,
operator.ActivateBcfViewpoint,
operator.OpenBcfFileReference,
operator.OpenBcfReferenceLink,
operator.OpenBcfBimSnippetSchema,
operator.OpenBcfBimSnippetReference,
operator.OpenBcfDocumentReference,
operator.SelectFeaturesDir,
operator.SelectDiffJsonFile,
operator.SelectDiffNewFile,
operator.SelectDiffOldFile,
operator.SelectDataDir,
operator.SelectSchemaDir,
operator.SelectIfcFile,
operator.ValidateIfcFile,
operator.ExportIFC,
operator.ImportIFC,
operator.ColourByClass,
operator.ColourByAttribute,
operator.ColourByPset,
operator.ResetObjectColours,
operator.ApproveClass,
operator.RejectClass,
operator.SelectAudited,
operator.RejectElement,
operator.SelectExternalMaterialDir,
operator.AddSweptSolid,
operator.RemoveSweptSolid,
operator.AssignSweptSolidOuterCurve,
operator.SelectSweptSolidOuterCurve,
operator.AddSweptSolidInnerCurve,
operator.SelectSweptSolidInnerCurves,
operator.AssignSweptSolidExtrusion,
operator.SelectSweptSolidExtrusion,
operator.AssignPset,
operator.UnassignPset,
operator.AddPset,
operator.RemovePset,
operator.AddOverridePset,
operator.RemoveOverridePset,
operator.AddQto,
operator.RemoveQto,
operator.AddMaterialPset,
operator.RemoveMaterialPset,
operator.AddDocument,
operator.RemoveDocument,
operator.GenerateGlobalId,
operator.AddAttribute,
operator.RemoveAttribute,
operator.AddMaterialAttribute,
operator.RemoveMaterialAttribute,
operator.QuickProjectSetup,
operator.SelectGlobalId,
operator.SelectAttribute,
operator.SelectPset,
operator.CreateAggregate,
operator.EditAggregate,
operator.SaveAggregate,
operator.ExplodeAggregate,
operator.AssignClassification,
operator.UnassignClassification,
operator.RemoveClassification,
operator.FetchLibraryInformation,
operator.FetchExternalMaterial,
operator.FetchObjectPassport,
operator.AddSubcontext,
operator.RemoveSubcontext,
operator.CutSection,
operator.CreateSheet,
operator.OpenSheet,
operator.OpenCompiledSheet,
operator.AddViewToSheet,
operator.CreateSheets,
operator.GenerateDigitalTwin,
operator.CreateView,
operator.OpenView,
operator.ActivateView,
operator.ExecuteIfcDiff,
operator.AssignContext,
operator.SetViewPreset1,
operator.OpenUpstream,
operator.Uninstall,
prop.BcfTopic,
prop.BcfTopicLabel,
prop.BcfTopicFile,
prop.BcfTopicLink,
prop.BcfTopicDocumentReference,
prop.BcfTopicRelatedTopic,
prop.Subcontext,
prop.BIMProperties,
prop.BCFProperties,
prop.DocProperties,
prop.BIMLibrary,
prop.MapConversion,
prop.TargetCRS,
prop.Attribute,
prop.BoundaryCondition,
prop.PsetQto,
prop.Document,
prop.Classification,
prop.GlobalId,
prop.BIMObjectProperties,
prop.BIMMaterialProperties,
prop.SweptSolid,
prop.BIMMeshProperties,
prop.BIMCameraProperties,
ui.BIM_PT_documentation,
ui.BIM_PT_bim,
ui.BIM_PT_search,
ui.BIM_PT_bcf,
ui.BIM_PT_owner,
ui.BIM_PT_context,
ui.BIM_PT_qa,
ui.BIM_PT_library,
ui.BIM_PT_gis,
ui.BIM_PT_diff,
ui.BIM_PT_mvd,
ui.BIM_PT_material,
ui.BIM_PT_mesh,
ui.BIM_PT_object,
ui.BIM_PT_camera,
ui.BIM_UL_topics,
ui.BIM_ADDON_preferences,
)
def menu_func_export(self, context):
self.layout.operator(operator.ExportIFC.bl_idname,
text="Industry Foundation Classes (.ifc)")
def menu_func_import(self, context):
self.layout.operator(operator.ImportIFC.bl_idname,
text="Industry Foundation Classes (.ifc)")
def on_register(scene):
prop.setDefaultProperties(scene)
bpy.app.handlers.scene_update_post.remove(on_register)
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.app.handlers.depsgraph_update_post.append(on_register)
bpy.app.handlers.load_post.append(prop.setDefaultProperties)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties)
bpy.types.Scene.BCFProperties = bpy.props.PointerProperty(type=prop.BCFProperties)
bpy.types.Scene.DocProperties = bpy.props.PointerProperty(type=prop.DocProperties)
bpy.types.Scene.BIMLibrary = bpy.props.PointerProperty(type=prop.BIMLibrary)
bpy.types.Scene.MapConversion = bpy.props.PointerProperty(type=prop.MapConversion)
bpy.types.Scene.TargetCRS = bpy.props.PointerProperty(type=prop.TargetCRS)
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Collection.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Material.BIMMaterialProperties = bpy.props.PointerProperty(type=prop.BIMMaterialProperties)
bpy.types.Mesh.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
bpy.types.Camera.BIMCameraProperties = bpy.props.PointerProperty(type=prop.BIMCameraProperties)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
bpy.app.handlers.load_post.remove(prop.setDefaultProperties)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
del(bpy.types.Scene.BIMProperties)
del(bpy.types.Scene.BCFProperties)
del(bpy.types.Scene.DocProperties)
del(bpy.types.Scene.MapConversion)
del(bpy.types.Scene.TargetCRS)
del(bpy.types.Object.BIMObjectProperties)
del(bpy.types.Collection.BIMObjectProperties)
del(bpy.types.Material.BIMMaterialProperties)
del(bpy.types.Mesh.BIMMeshProperties)
del(bpy.types.Camera.BIMCameraProperties)
@@ -0,0 +1,4 @@
class BcfStore():
topics = []
viewpoints = []
comments = []
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,3 @@
Source,Edition,EditionDate,Name,Description,Location,ReferenceTokens
RIBA Enterprises Ltd,2015,Aug-19,Uniclass 2015,Uniclass2015 is a unified classification for the UK industry covering all construction sectors.,https://www.thenbs.com/our-tools/uniclass-2015,"[""_""]"
OmniClass,2.1,May-12,OmniClass,The OmniClass Construction Classification System is a classification system for the construction industry.,https://www.csiresources.org/standards/omniclass,"[""-"","" ""]"
1 Source Edition EditionDate Name Description Location ReferenceTokens
2 RIBA Enterprises Ltd 2015 Aug-19 Uniclass 2015 Uniclass2015 is a unified classification for the UK industry covering all construction sectors. https://www.thenbs.com/our-tools/uniclass-2015 ["_"]
3 OmniClass 2.1 May-12 OmniClass The OmniClass Construction Classification System is a classification system for the construction industry. https://www.csiresources.org/standards/omniclass ["-"," "]
@@ -0,0 +1,2 @@
Identification,Name,ReferencedSource
Pr_20_85_14_16,Concrete solid slabs,0
1 Identification Name ReferencedSource
2 Pr_20_85_14_16 Concrete solid slabs 0
@@ -0,0 +1,3 @@
Name,Description,ConstraintGrade,ObjectiveQualifier
Beauty,The built form should be beautiful,HARD,DESIGNINTENT
Safety,No facilities exist to generate killer artificial intelligence,HARD,HEALTHANDSAFETY
1 Name Description ConstraintGrade ObjectiveQualifier
2 Beauty The built form should be beautiful HARD DESIGNINTENT
3 Safety No facilities exist to generate killer artificial intelligence HARD HEALTHANDSAFETY
@@ -0,0 +1,6 @@
{
"blender": {
"uri": "high-res.blend",
"identification": "high-res"
}
}
@@ -0,0 +1 @@
MassDensity,7.8
1 MassDensity 7.8
@@ -0,0 +1,2 @@
YoungModulus,210000000
PoissonRatio,0.2
1 YoungModulus 210000000
2 PoissonRatio 0.2
@@ -0,0 +1,8 @@
{
"eevee": {
"uri": "mpass/shader.blend"
},
"cycles": {
"uri": "mpass/shader.blend"
}
}
@@ -0,0 +1,30 @@
[
{
"Name": "IfcOpenShell",
"Description": "IfcOpenShell is an open source (LGPL) software library that helps users and software developers to work with the IFC file format.",
"Roles": [{
"Role": "USERDEFINED",
"UserDefinedRole": "CONTRIBUTOR"
}],
"Addresses": [
{
"Purpose": "USERDEFINED",
"UserDefinedPurpose": "WEBPAGE",
"Description": "The main webpage of the software collection.",
"WWWHomePageURL": "https://ifcopenshell.org"
},
{
"Purpose": "USERDEFINED",
"UserDefinedPurpose": "WEBPAGE",
"Description": "The BlenderBIM webpage of the software collection.",
"WWWHomePageURL": "https://blenderbim.org"
},
{
"Purpose": "USERDEFINED",
"UserDefinedPurpose": "REPOSITORY",
"Description": "The source code repository of the software collection.",
"WWWHomePageURL": "https://github.com/IfcOpenShell/IfcOpenShell.git"
}
]
}
]
@@ -0,0 +1,35 @@
[
{
"Identification": "Moult",
"FamilyName": "Moult",
"GivenName": "Dion",
"MiddleNames": ["Sebastian", "Isan", "Tan"],
"PrefixTitles": ["Mr"],
"SuffixTitles": ["UE"],
"Roles": [{
"Role": "ARCHITECT",
"UserDefinedRole": null,
"Description": "Draws the pretty pictures"
}],
"Addresses": [{
"Purpose": "OFFICE",
"Description": "Headquarters",
"UserDefinedPurpose": null,
"InternalLocation": "Cupboard under the stairs",
"AddressLines": [ "221B Baker Street" ],
"PostalBox": null,
"Town": "MyTown",
"Region": "Middle-Earth",
"PostalCode": "42",
"Country": "Narnia"
}, {
"Purpose": "OFFICE",
"Description": "Headquarters",
"UserDefinedPurpose": null,
"TelephoneNumbers": ["0123456789"],
"ElectronicMailAddresses": ["dion@thinkmoult.com"],
"WWWHomePageURL": "https://thinkmoult.com",
"MessagingIDs": ["irc://irc.freenode.net##architect"]
}]
}
]
@@ -0,0 +1,5 @@
Reference,myref
Status,TEMPORARY
FireRating,2HR
AcousticRating,0.5R
IsExternal,True
1 Reference myref
2 Status TEMPORARY
3 FireRating 2HR
4 AcousticRating 0.5R
5 IsExternal True
@@ -0,0 +1,8 @@
Reference,Some reference
Status,EXISTING
Style,Some style
NominalHeight,1.2
NominalLength,1.3
NominalDepth,1.5
MainColor,Blue
IsBuiltIn,Uh-huh
1 Reference Some reference
2 Status EXISTING
3 Style Some style
4 NominalHeight 1.2
5 NominalLength 1.3
6 NominalDepth 1.5
7 MainColor Blue
8 IsBuiltIn Uh-huh
@@ -0,0 +1 @@
MainColor,Red
1 MainColor Red
@@ -0,0 +1,4 @@
<?xml version="1.0" ?>
<svg height="594mm" id="root" version="1.1" width="841mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image height="594mm" width="841mm" x="0" xlink:href="../templates/titleblock.svg" y="0"/>
</svg>

After

Width:  |  Height:  |  Size: 262 B

@@ -0,0 +1,3 @@
.cut { fill: black; stroke: black; stroke-linecap: 'round'; stroke-width: 0.35; }
.background { fill: white; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
.annotation { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<marker id="eng-dimension-marker-start" markerHeight="14" markerWidth="11" orient="auto" refX="1" refY="7">
<g>
<path d="M 11 3.5 L 11 10.5 L 1 7" class="annotation" style="fill:black;" />
<path d="M 1 0 L 1 14" class="annotation" style="stroke-width:1;" />
</g>
</marker>
<marker id="eng-dimension-marker-end" markerHeight="14" markerWidth="11" orient="auto" refX="10" refY="7">
<g>
<path d="M 0 3.5 L 0 10.5 L 10 7" class="annotation" style="fill:black;" />
<path d="M 10 0 L 10 14" class="annotation" style="stroke-width:1;" />
</g>
</marker>
<marker id="dimension-marker-start" markerHeight="30" markerWidth="20" refX="10" refY="15" orient="auto">
<g>
<path d="M 0 15 L 20 15" class="annotation" style="stroke-width:1;" />
<path d="M 10 0 L 10 30" class="annotation" style="stroke-width:1;" />
<path d="M 5 20 L 15 10" class="annotation" style="stroke-width:3;" />
</g>
</marker>
<marker id="dimension-marker-end" markerHeight="30" markerWidth="20" refX="10" refY="15" orient="auto">
<g>
<path d="M 0 15 L 20 15" class="annotation" style="stroke-width:1;" />
<path d="M 10 0 L 10 30" class="annotation" style="stroke-width:1;" />
<path d="M 5 20 L 15 10" class="annotation" style="stroke-width:3;" />
</g>
</marker>
<marker id="grid-marker" markerHeight="35" markerWidth="35" orient="auto" refX="17.5" refY="17.5">
<circle cx="17.5" cy="17.5" fill="white" stroke="black" r="15" style="stroke-width: 2"/>
</marker>
<marker id="leader-marker" markerHeight="7" markerWidth="10" orient="auto" refX="10" refY="3.5">
<path d="M 0 0 L 0 7 L 10 3.5" class="annotation" style="fill:black;" />
</marker>
<marker id="stair-marker-start" markerHeight="10" markerWidth="10" orient="auto" refX="5" refY="5">
<circle cx="5" cy="5" fill="black" stroke="none" r="5"/>
</marker>
<marker id="stair-marker-end" markerHeight="42" markerWidth="21" orient="auto" refX="21" refY="21">
<path d="M 0 0 L 21 21 L 0 42" class="annotation stair" style="stroke-width:2" />
</marker>
<marker id="plan-level-marker" markerHeight="30" markerWidth="30" refX="15" refY="15">
<g>
<path d="M 15 0 L 15 30" class="annotation" style="stroke-width:1;" />
<path d="M 0 15 L 30 15" class="annotation" style="stroke-width:1;" />
<circle cx="15" cy="15" fill="white" stroke="black" r="7.5" style="stroke-width: 2"/>
<path d="M 15 15 L 7.5 15 A 7.5 7.5 0 0 1 15 7.5 Z" fill="black"/>
<path d="M 15 15 L 22.5 15 A 7.5 7.5 0 0 1 15 22.5 Z" fill="black"/>
</g>
</marker>
<marker id="section-level-marker" markerHeight="11" markerWidth="90" refX="20" refY="10">
<g>
<path d="M 0 1 L 20 1 L 10 11 Z" fill="black" />
<path d="M 0 1 L 90 1" class="annotation" style="stroke-width:1;" />
</g>
</marker>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 821 KiB

@@ -0,0 +1,194 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="root"
version="1.1"
height="594mm"
width="841mm">
<defs
id="defs901" />
<metadata
id="metadata90683">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<desc
id="desc89610">/home/dion/Projects/IfcOpenShell/src/ifcblenderexport/titleblock.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual</desc>
<g
transform="translate(0,1122.5197)"
id="g90667">
<rect
y="-1046.7792"
x="75.740562"
height="2093.5583"
width="3027.1016"
id="rect116616"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.88976383;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
id="text116526"
y="909.15491"
x="113.70713"
style="font-style:normal;font-weight:normal;font-size:15.15362644px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.15362644px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:1px"
y="909.15491"
x="113.70713"
id="tspan116524">REV. NO.</tspan></text>
<path
id="path116530"
d="M 75.590564,895.24802 H 3102.9921"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path116532"
d="M 151.6811,895.24802 V 1046.9291"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 454.04331,895.24802 V 1046.9291"
id="path116534" />
<path
id="path116536"
d="M 529.63386,895.24802 V 1046.4302"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 605.22441,895.24802 V 1046.9291"
id="path116538" />
<path
id="path116540"
d="M 75.590564,914.14565 H 605.22441"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 75.590564,933.04329 H 605.22441"
id="path116542" />
<path
id="path116544"
d="M 75.590564,951.94093 H 605.22441"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 75.590564,970.83857 H 605.22441"
id="path116546" />
<path
id="path116548"
d="M 75.590564,989.73621 H 605.22441"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 75.590564,1008.6338 H 605.22441"
id="path116550" />
<path
id="path116552"
d="M 75.590564,1027.5315 H 605.22441"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path116576"
d="M 2800.5,895.24802 V 1046.9291"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path116578"
d="m 2800.5,1008.6338 h 302.4921"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path116598"
d="m 3027.4027,1008.6338 v 38.2953"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75590551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.15362644px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="302.86591"
y="909.15491"
id="text1395"><tspan
id="tspan1393"
x="302.86591"
y="909.15491"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.15362644px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:1px">DESCRIPTION</tspan></text>
<text
id="text1399"
y="909.15491"
x="491.97513"
style="font-style:normal;font-weight:normal;font-size:15.15362644px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.15362644px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:1px"
y="909.15491"
x="491.97513"
id="tspan1397">AUTHOR</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:16.05907059px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="568.05585"
y="909.15485"
id="text1403"><tspan
id="tspan1401"
x="568.05585"
y="909.15485"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.05907059px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.99999994px">DATE</tspan></text>
<text
id="text1417"
y="1037.4314"
x="2829.6274"
style="font-style:normal;font-weight:normal;font-size:13.39182091px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.39182091px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:1px"
y="1037.4314"
x="2829.6274"
id="tspan1415">{{number}}</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:11.22711563px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="2839.5081"
y="1020.4988"
id="text1421"><tspan
id="tspan1419"
x="2839.5081"
y="1020.4988"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.22711563px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.99999994px">DRAWING NUMBER</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:13.39182091px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="3056.6086"
y="1037.4314"
id="text1425"><tspan
id="tspan1423"
x="3056.6086"
y="1037.4314"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.39182091px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:1px">{{revision}}</tspan></text>
<text
id="text1429"
y="1020.4988"
x="3038.5586"
style="font-style:normal;font-weight:normal;font-size:11.22711563px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.22711563px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.99999994px"
y="1020.4988"
x="3038.5586"
id="tspan1427">REV</tspan></text>
</g>
<g
transform="translate(0,1122.5197)"
id="g90669" />
<g
transform="translate(0,1122.5197)"
id="g90671" />
<g
transform="translate(0,1122.5197)"
id="g90673" />
<g
transform="translate(0,1122.5197)"
id="g90675" />
<g
transform="translate(0,1122.5197)"
id="g90677" />
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="root"
version="1.1"
viewBox="0 0 50.222462 10"
height="10mm"
width="50.222462mm"
sodipodi:docname="view-title.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview14"
showgrid="false"
inkscape:zoom="4.2318262"
inkscape:cx="61.584312"
inkscape:cy="26.339719"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-27.82024,-96.649986)"
id="layer1">
<circle
r="4.8499999"
cy="101.64999"
cx="32.82024"
id="path853"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path855"
d="m 37.67024,101.64999 40.37246,-1e-5"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<text
id="text859"
y="103.10933"
x="32.822662"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:24.80276871px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.96055365px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.26458332px"
y="103.10933"
x="32.822662"
id="tspan857">{{no}}</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.71626091px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="39.12896"
y="100.19173"
id="text863"><tspan
id="tspan861"
x="39.12896"
y="100.19173"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325247px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:start;text-anchor:start;stroke-width:0.26458329px">{{name}}</tspan></text>
<text
id="text867"
y="105.0553"
x="39.285267"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.71626282px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325247px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:start;text-anchor:start;stroke-width:0.26458332px"
y="105.0553"
x="39.285267"
id="tspan865">{{scale}}</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -0,0 +1,2 @@
Name,foo
TransomThickness,500
1 Name foo
2 TransomThickness 500
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,66 @@
import math
class SIUnitHelper:
prefixes = {"EXA": 1e18, "PETA": 1e15, "TERA": 1e12, "GIGA": 1e9, "MEGA":
1e6, "KILO": 1e3, "HECTO": 1e2, "DECA": 1e1, "DECI": 1e-1, "CENTI":
1e-2, "MILLI": 1e-3, "MICRO": 1e-6, "NANO": 1e-9, "PICO": 1e-12,
"FEMTO": 1e-15, "ATTO": 1e-18}
unit_names = ["AMPERE", "BECQUEREL", "CANDELA", "COULOMB",
"CUBIC_METRE", "DEGREE CELSIUS", "FARAD", "GRAM", "GRAY", "HENRY",
"HERTZ", "JOULE", "KELVIN", "LUMEN", "LUX", "MOLE", "NEWTON", "OHM",
"PASCAL", "RADIAN", "SECOND", "SIEMENS", "SIEVERT", "SQUARE METRE",
"METRE", "STERADIAN", "TESLA", "VOLT", "WATT", "WEBER"]
si_conversions = {
'inch': 0.0254,
'foot': 0.3048,
'yard': 0.914,
'mile': 1609,
'square inch': 0.0006452,
'square foot': 0.09290,
'square yard': 0.83612736,
'acre': 4046.86,
'square mile': 2588881,
'cubic inch': 0.00001639,
'cubic foot': 0.02832,
'cubic yard': 0.7636,
'litre': 0.001,
'fluid ounce UK': 0.0000284130625,
'fluid ounce US': 0.00002957353,
'pint UK': 0.000568,
'pint US': 0.000473,
'gallon UK': 0.004546,
'gallon US': 0.003785,
'degree': math.pi/180,
'ounce': 0.02835,
'pound': 0.454,
'ton UK': 1016.0469088,
'ton US': 907.18474,
'lbf': 4.4482216153,
'kip': 4448.2216153,
'psi': 6894.7572932,
'ksi': 6894757.2932,
'minute': 60,
'hour': 3600,
'day': 86400,
'btu': 1055.056}
@staticmethod
def get_prefix(text):
for prefix in SIUnitHelper.prefixes.keys():
if prefix in text.upper():
return prefix
@staticmethod
def get_prefix_multiplier(text):
if not text:
return 1
prefix = SIUnitHelper.get_prefix(text)
if prefix:
return SIUnitHelper.prefixes[prefix]
return 1
@staticmethod
def get_unit_name(text):
for name in SIUnitHelper.unit_names:
if name in text.upper().replace('METER', 'METRE'):
return name
@@ -0,0 +1,3 @@
class IfcStore():
path = ''
file = None
@@ -0,0 +1,832 @@
import ifcopenshell
import ifcopenshell.geom
import bpy
import os
import json
import time
import mathutils
import multiprocessing
from .helper import SIUnitHelper
from . import schema
from . import ifc
class MaterialCreator():
def __init__(self, ifc_import_settings):
self.mesh = None
self.materials = {}
self.parsed_meshes = []
self.ifc_import_settings = ifc_import_settings
def create(self, element, obj, mesh):
self.obj = obj
self.mesh = mesh
if not element.Representation:
return
if self.ifc_import_settings.should_treat_styled_item_as_material \
and self.mesh.name in self.parsed_meshes:
return
if self.parse_representations(element):
self.assign_material_slots_to_faces(obj, self.mesh)
self.parsed_meshes.append(self.mesh.name)
return # styled items override material styles
self.parse_material(element)
self.parsed_meshes.append(self.mesh.name)
def parse_representations(self, element):
has_parsed = False
for representation in element.Representation.Representations:
if self.parse_representation(representation):
has_parsed = True
return has_parsed
def parse_representation(self, representation):
has_parsed = False
representation = self.resolve_mapped_representation(representation)
for item in representation.Items:
if self.parse_representation_item(item):
has_parsed = True
return has_parsed
def parse_representation_item(self, item):
if not item.StyledByItem:
return
styled_item = item.StyledByItem[0]
material_name = self.get_material_name(styled_item)
if material_name not in self.materials:
self.materials[material_name] = bpy.data.materials.new(material_name)
self.parse_styled_item(styled_item, self.materials[material_name])
if self.ifc_import_settings.should_treat_styled_item_as_material:
# Revit workaround: since Revit exports all material
# assignments as individual object styled items. Treating
# them as reusable materials makes things much more
# efficient in Blender.
self.assign_material_to_mesh(self.materials[material_name])
else:
# Proper behaviour
self.assign_material_to_mesh(self.materials[material_name], is_styled_item=True)
return True
def assign_material_slots_to_faces(self, obj, mesh):
if not mesh['ios_materials']:
return
slots = [s.name for s in obj.material_slots]
for index, polygon in enumerate(mesh.polygons):
material = mesh['ios_materials'][mesh['ios_material_ids'][index]]
if 'surface-style-' in material:
material = material[len('surface-style-'):]
try:
polygon.material_index = slots.index(material)
except:
self.ifc_import_settings.logger.error(
'Failed to assign material {} to object {}'.format(material, obj.name))
def parse_material(self, element):
for association in element.HasAssociations:
if association.is_a('IfcRelAssociatesMaterial'):
material_select = association.RelatingMaterial
if material_select.is_a('IfcMaterialDefinition'):
self.create_definition(material_select)
def create_definition(self, material):
if material.is_a('IfcMaterial'):
self.create_single(material)
def create_single(self, material):
if material.Name not in self.materials:
self.create_new_single(material)
return self.assign_material_to_mesh(self.materials[material.Name])
def create_new_single(self, material):
self.materials[material.Name] = bpy.data.materials.new(material.Name)
if not material.HasRepresentation \
or not material.HasRepresentation[0].Representations:
return
for representation in material.HasRepresentation[0].Representations:
if not representation.Items:
continue
for item in representation.Items:
if not item.is_a('IfcStyledItem'):
continue
self.parse_styled_item(item, self.materials[material.Name])
def get_material_name(self, styled_item):
if styled_item.Name:
return styled_item.Name
styled_item = self.resolve_presentation_style_assignment(styled_item)
for style in styled_item.Styles:
if not style.is_a('IfcSurfaceStyle'):
continue
if style.Name:
return style.Name
return str(style.id())
return str(styled_item.id())
def parse_styled_item(self, styled_item, material):
styled_item = self.resolve_presentation_style_assignment(styled_item)
for style in styled_item.Styles:
if not style.is_a('IfcSurfaceStyle'):
continue
external_style = None
for surface_style in style.Styles:
if surface_style.is_a('IfcSurfaceStyleShading'):
alpha = 1.
# Transparency was added in IFC4
if hasattr(surface_style, 'Transparency') \
and surface_style.Transparency:
alpha = 1 - surface_style.Transparency
material.diffuse_color = (
surface_style.SurfaceColour.Red,
surface_style.SurfaceColour.Green,
surface_style.SurfaceColour.Blue,
alpha)
elif surface_style.is_a('IfcExternallyDefinedSurfaceStyle'):
external_style = surface_style
if external_style:
material.BIMMaterialProperties.is_external = True
material.BIMMaterialProperties.location = external_style.Location
material.BIMMaterialProperties.identification = external_style.Identification
material.BIMMaterialProperties.name = external_style.Name
# IfcPresentationStyleAssignment is deprecated as of IFC4
# However it is still widely used thanks to Revit :(
def resolve_presentation_style_assignment(self, styled_item):
for style in styled_item.Styles:
if style.is_a('IfcPresentationStyleAssignment'):
return style
return styled_item
def resolve_mapped_representation(self, representation):
for item in representation.Items:
if item.is_a('IfcMappedItem'):
return item.MappingSource.MappedRepresentation
return representation
def assign_material_to_mesh(self, material, is_styled_item=False):
self.mesh.materials.append(material)
if is_styled_item:
index = len(self.obj.material_slots) - 1
self.obj.material_slots[index].link = 'OBJECT'
self.obj.material_slots[index].material = material
class IfcImporter():
def __init__(self, ifc_import_settings):
self.ifc_import_settings = ifc_import_settings
self.diff = None
self.file = None
self.settings = ifcopenshell.geom.settings()
if self.ifc_import_settings.should_import_curves:
self.settings.set(self.settings.INCLUDE_CURVES, True)
self.settings_2d = ifcopenshell.geom.settings()
self.settings_2d.set(self.settings_2d.INCLUDE_CURVES, True)
self.project = None
self.spatial_structure_elements = {}
self.elements = {}
self.type_products = {}
self.meshes = {}
self.mesh_shapes = {}
self.time = 0
self.unit_scale = 1
self.added_data = {}
self.material_creator = MaterialCreator(ifc_import_settings)
def execute(self):
self.load_diff()
self.load_file()
self.set_ifc_file()
if self.ifc_import_settings.should_auto_set_workarounds:
self.auto_set_workarounds()
self.calculate_unit_scale()
self.create_project()
self.create_spatial_hierarchy()
if self.ifc_import_settings.should_import_aggregates:
self.create_aggregates()
if self.ifc_import_settings.should_import_opening_elements:
self.create_openings_collection()
self.purge_diff()
self.patch_ifc()
self.create_type_products()
self.create_grids()
# TODO: Deprecate after bug #682 is fixed and the new importer is stable
if self.ifc_import_settings.should_use_legacy or self.diff:
self.create_products_legacy()
else:
self.create_products()
self.place_objects_in_spatial_tree()
if self.ifc_import_settings.should_merge_by_class:
self.merge_by_class()
elif self.ifc_import_settings.should_merge_by_material:
self.merge_by_material()
if self.ifc_import_settings.should_clean_mesh:
self.clean_mesh()
def auto_set_workarounds(self):
applications = self.file.by_type('IfcApplication')
if not applications:
return
if applications[0].ApplicationIdentifier == 'Revit':
self.ifc_import_settings.should_treat_styled_item_as_material = True
if self.is_ifc_class_far_away('IfcSite'):
self.ifc_import_settings.should_ignore_site_coordinates = True
if self.is_ifc_class_far_away('IfcBuilding'):
self.ifc_import_settings.should_ignore_building_coordinates = True
elif applications[0].ApplicationFullName == '12D Model':
self.ifc_import_settings.should_reset_absolute_coordinates = True
elif applications[0].ApplicationFullName == 'Tekla Structures':
if self.is_ifc_class_far_away('IfcSite'):
self.ifc_import_settings.should_ignore_site_coordinates = True
def is_ifc_class_far_away(self, ifc_class):
for site in self.file.by_type(ifc_class):
if not site.ObjectPlacement \
or not site.ObjectPlacement.RelativePlacement \
or not site.ObjectPlacement.RelativePlacement.Location:
continue
if self.is_point_far_away(site.ObjectPlacement.RelativePlacement.Location):
return True
def is_point_far_away(self, point):
# Arbitrary threshold based on experience
return abs(point.Coordinates[0]) > 1000000 \
or abs(point.Coordinates[1]) > 1000000 \
or abs(point.Coordinates[2]) > 1000000
def patch_ifc(self):
project = self.file.by_type('IfcProject')[0]
if self.ifc_import_settings.should_ignore_site_coordinates:
sites = self.find_decomposed_ifc_class(project, 'IfcSite')
for site in sites:
self.patch_placement_to_origin(site)
if self.ifc_import_settings.should_ignore_building_coordinates:
buildings = self.find_decomposed_ifc_class(project, 'IfcBuilding')
for building in buildings:
self.patch_placement_to_origin(building)
if self.ifc_import_settings.should_reset_absolute_coordinates:
self.reset_absolute_coordinates()
def reset_absolute_coordinates(self):
# 12D can have some funky coordinates out of any sensible range. This
# method will not work all the time, but will catch most issues.
offset_point = None
for point in self.file.by_type('IfcCartesianPoint'):
if len(point.Coordinates) == 2 or not self.is_point_far_away(point):
continue
if not offset_point:
offset_point = (point.Coordinates[0], point.Coordinates[1], point.Coordinates[2])
self.ifc_import_settings.logger.info(f'Resetting absolute coordinates by {point}')
point.Coordinates = (
point.Coordinates[0] - offset_point[0],
point.Coordinates[1] - offset_point[1],
point.Coordinates[2] - offset_point[2]
)
def find_decomposed_ifc_class(self, element, ifc_class):
results = []
rel_aggregates = element.IsDecomposedBy
if not rel_aggregates:
return results
for rel_aggregate in rel_aggregates:
for part in rel_aggregate.RelatedObjects:
if part.is_a(ifc_class):
results.append(part)
results.extend(self.find_decomposed_ifc_class(part, ifc_class))
return results
def patch_placement_to_origin(self, element):
element.ObjectPlacement.RelativePlacement.Location.Coordinates = (0., 0., 0.)
if element.ObjectPlacement.RelativePlacement.Axis:
element.ObjectPlacement.RelativePlacement.Axis.DirectionRatios = (0., 0., 1.)
if element.ObjectPlacement.RelativePlacement.RefDirection:
element.ObjectPlacement.RelativePlacement.RefDirection.DirectionRatios = (1., 0., 0.)
def create_grids(self):
grids = self.file.by_type('IfcGrid')
for grid in grids:
collection = bpy.data.collections.new(self.get_name(grid))
self.project['blender'].children.link(collection)
self.create_grid_axes(grid.UAxes, collection)
self.create_grid_axes(grid.VAxes, collection)
def create_grid_axes(self, axes, grid):
for axis in axes:
shape = ifcopenshell.geom.create_shape(self.settings_2d, axis.AxisCurve)
mesh = self.create_mesh(axis, shape)
obj = bpy.data.objects.new(f'IfcGrisAxis/{axis.AxisTag}', mesh)
grid.objects.link(obj)
def create_type_products(self):
type_products = self.file.by_type('IfcTypeProduct')
for type_product in type_products:
self.create_type_product(type_product)
def create_type_product(self, type_product):
obj = bpy.data.objects.new(self.get_name(type_product), None)
self.add_element_attributes(type_product, obj)
self.add_element_document_relations(type_product, obj)
self.add_type_product_psets(type_product, obj)
self.project['blender'].objects.link(obj)
self.type_products[type_product.GlobalId] = obj
def create_products_legacy(self):
elements = self.file.by_type('IfcElement') + self.file.by_type('IfcSpace')
for element in elements:
self.create_product_legacy(element)
def create_products(self):
if self.ifc_import_settings.should_use_cpu_multiprocessing:
iterator = ifcopenshell.geom.iterator(self.settings, self.file, multiprocessing.cpu_count())
else:
iterator = ifcopenshell.geom.iterator(self.settings, self.file)
valid_file = iterator.initialize()
if not valid_file:
self.create_products_legacy() # Sometimes, this can still work, not 100% sure why yet
return False
old_progress = -1
while True:
progress = iterator.progress() // 2
if progress > old_progress:
print("\r[" + "#" * progress + " " * (50 - progress) + "]", end="")
old_progress = progress
self.create_product(iterator.get())
if not iterator.next():
break
print("\rDone creating geometry" + " " * 30)
def create_product(self, shape):
if shape is None:
return
element = self.file.by_id(shape.guid)
if not self.ifc_import_settings.should_import_opening_elements \
and element.is_a('IfcOpeningElement'):
return
if not self.ifc_import_settings.should_import_spaces \
and element.is_a('IfcSpace'):
return
self.ifc_import_settings.logger.info('Creating object {}'.format(element))
# TODO: make names more meaningful
mesh_name = f'mesh-{shape.geometry.id}'
mesh = self.meshes.get(mesh_name)
if mesh is None:
mesh = self.create_mesh(element, shape)
self.meshes[mesh_name] = mesh
obj = bpy.data.objects.new(self.get_name(element), mesh)
m = shape.transformation.matrix.data
mat = mathutils.Matrix(([m[0], m[1], m[2], 0],
[m[3], m[4], m[5], 0],
[m[6], m[7], m[8], 0],
[m[9], m[10], m[11], 1]))
mat.transpose()
obj.matrix_world = mat
self.material_creator.create(element, obj, mesh)
self.add_element_attributes(element, obj)
self.add_element_document_relations(element, obj)
self.add_defines_by_type_relation(element, obj)
self.add_product_definitions(element, obj)
self.added_data[element.GlobalId] = obj
def merge_by_class(self):
merge_set = {}
for obj in self.added_data.values():
if '/' in obj.name:
merge_set.setdefault(obj.name.split('/')[0], []).append(obj)
self.merge_objects(merge_set)
def merge_by_material(self):
merge_set = {}
for obj in self.added_data.values():
if not obj.material_slots:
merge_set.setdefault('no-material', []).append(obj)
else:
merge_set.setdefault(obj.material_slots[0].name, []).append(obj)
self.merge_objects(merge_set)
def merge_objects(self, merge_set):
for ifc_class, objs in merge_set.items():
context_override = {}
context_override['object'] = context_override['active_object'] = objs[0]
context_override['selected_objects'] = context_override['selected_editable_objects'] = objs
bpy.ops.object.join(context_override)
def clean_mesh(self):
for obj in self.added_data.values():
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
context_override = {}
bpy.ops.object.editmode_toggle(context_override)
bpy.ops.mesh.remove_doubles(context_override)
bpy.ops.mesh.tris_convert_to_quads(context_override)
bpy.ops.mesh.dissolve_limited(context_override)
bpy.ops.mesh.normals_make_consistent(context_override)
bpy.ops.object.editmode_toggle(context_override)
def add_product_definitions(self, element, obj):
if not hasattr(element, 'IsDefinedBy') or not element.IsDefinedBy:
return
for definition in element.IsDefinedBy:
if not definition.is_a('IfcRelDefinesByProperties'):
continue
if definition.RelatingPropertyDefinition.is_a('IfcPropertySet'):
self.add_pset(definition.RelatingPropertyDefinition, obj)
elif definition.RelatingPropertyDefinition.is_a('IfcElementQuantity'):
self.add_qto(definition.RelatingPropertyDefinition, obj)
def add_type_product_psets(self, element, obj):
if not hasattr(element, 'HasPropertySets') or not element.HasPropertySets:
return
for definition in element.HasPropertySets:
if definition.is_a('IfcPropertySet'):
self.add_pset(definition, obj)
def add_pset(self, pset, obj):
new_pset = obj.BIMObjectProperties.override_psets.add()
new_pset.name = pset.Name
if new_pset.name in schema.ifc.psets:
for prop_name in schema.ifc.psets[new_pset.name]['HasPropertyTemplates'].keys():
prop = new_pset.properties.add()
prop.name = prop_name
for prop in pset.HasProperties:
if prop.is_a('IfcPropertySingleValue') and prop.NominalValue:
index = new_pset.properties.find(prop.Name)
if index >= 0:
new_pset.properties[index].string_value = str(prop.NominalValue.wrappedValue)
else:
new_prop = new_pset.properties.add()
new_prop.name = prop.Name
new_prop.string_value = str(prop.NominalValue.wrappedValue)
def add_qto(self, qto, obj):
new_qto = obj.BIMObjectProperties.qtos.add()
new_qto.name = qto.Name
if new_qto.name in schema.ifc.qtos:
for prop_name in schema.ifc.qtos[new_qto.name]['HasPropertyTemplates'].keys():
prop = new_qto.properties.add()
prop.name = prop_name
for prop in qto.Quantities:
if prop.is_a('IfcPhysicalSimpleQuantity'):
value = getattr(prop, '{}Value'.format(prop.is_a()[len('IfcQuantity'):]))
if not value:
continue
index = new_qto.properties.find(prop.Name)
if index >= 0:
new_qto.properties[index].string_value = str(value)
else:
new_prop = new_qto.properties.add()
new_prop.name = prop.Name
new_prop.string_value = str(value)
def add_defines_by_type_relation(self, element, obj):
related_type = None
if self.file.schema == 'IFC2X3':
if not hasattr(element, 'IsDefinedBy') or not element.IsDefinedBy:
return
for relationship in element.IsDefinedBy:
if relationship.is_a('IfcRelDefinesByType'):
related_type = relationship.RelatingType
break
else:
if not hasattr(element, 'IsTypedBy') or not element.IsTypedBy:
return
related_type = element.IsTypedBy[0].RelatingType
if related_type:
obj.BIMObjectProperties.relating_type = self.type_products[related_type.GlobalId]
def load_diff(self):
if not self.ifc_import_settings.diff_file:
return
with open(self.ifc_import_settings.diff_file, 'r') as file:
self.diff = json.load(file)
def load_file(self):
self.ifc_import_settings.logger.info('loading file {}'.format(self.ifc_import_settings.input_file))
self.file = ifcopenshell.open(self.ifc_import_settings.input_file)
ifc.IfcStore.file = self.file
def set_ifc_file(self):
bpy.context.scene.BIMProperties.ifc_file = self.ifc_import_settings.input_file
ifc.IfcStore.path = 'self.ifc_import_settings.input_file'
def calculate_unit_scale(self):
units = self.file.by_type('IfcUnitAssignment')[0]
for unit in units.Units:
if not hasattr(unit, 'UnitType') \
or unit.UnitType != 'LENGTHUNIT':
continue
while unit.is_a('IfcConversionBasedUnit'):
self.unit_scale *= unit.ConversionFactor.ValueComponent.wrappedValue
unit = unit.ConversionFactor.UnitComponent
if unit.is_a('IfcSIUnit'):
self.unit_scale *= SIUnitHelper.get_prefix_multiplier(unit.Prefix)
def create_project(self):
self.project = { 'ifc': self.file.by_type('IfcProject')[0] }
self.project['blender'] = bpy.data.collections.new('IfcProject/{}'.format(self.project['ifc'].Name))
bpy.context.scene.collection.children.link(self.project['blender'])
def create_spatial_hierarchy(self):
elements = self.file.by_type('IfcSpatialStructureElement')
attempts = 0
while len(self.spatial_structure_elements) < len(elements) \
and attempts <= len(elements):
for element in elements:
name = self.get_name(element)
global_id = element.GlobalId
if global_id in self.spatial_structure_elements:
continue
# Occurs when some naughty programs export IFC site objects
if not element.Decomposes:
continue
parent = element.Decomposes[0].RelatingObject
parent_name = self.get_name(parent)
parent_global_id = parent.GlobalId
if parent.is_a('IfcProject'):
self.spatial_structure_elements[global_id] = {
'blender': bpy.data.collections.new(name)}
self.project['blender'].children.link(self.spatial_structure_elements[global_id]['blender'])
elif element.is_a('IfcSpace'):
# Spaces are treated specially as objects
continue
elif parent_global_id in self.spatial_structure_elements:
self.spatial_structure_elements[global_id] = {
'blender': bpy.data.collections.new(name)}
self.spatial_structure_elements[parent_global_id]['blender'].children.link(
self.spatial_structure_elements[global_id]['blender'])
attempts += 1
def create_aggregates(self):
rel_aggregates = [a for a in self.file.by_type('IfcRelAggregates')
if a.RelatingObject.is_a('IfcElement')]
for rel_aggregate in rel_aggregates:
self.create_aggregate(rel_aggregate)
def create_aggregate(self, rel_aggregate):
collection = bpy.data.collections.new(f'IfcRelAggregates/{rel_aggregate.id()}')
bpy.context.scene.collection.children.link(collection)
bpy.context.view_layer.layer_collection.children[collection.name].hide_viewport = True
instance = bpy.data.objects.new('{}/{}'.format(
rel_aggregate.RelatingObject.is_a(),
rel_aggregate.RelatingObject.Name),
None)
instance.instance_type = 'COLLECTION'
instance.instance_collection = collection
self.place_object_in_spatial_tree(rel_aggregate.RelatingObject, instance)
def create_openings_collection(self):
collection = bpy.data.collections.new('IfcOpeningElements')
bpy.context.scene.collection.children.link(collection)
def get_name(self, element):
return '{}/{}'.format(element.is_a(), element.Name)
def purge_diff(self):
if not self.diff:
return
objects_to_purge = []
for obj in bpy.data.objects:
if 'GlobalId' not in obj.BIMObjectProperties.attributes:
continue
global_id = obj.BIMObjectProperties.attributes['GlobalId'].string_value
if global_id in self.diff['deleted'] \
or global_id in self.diff['changed'].keys():
objects_to_purge.append(obj)
bpy.ops.object.delete({'selected_objects': objects_to_purge})
def create_product_legacy(self, element):
if self.diff \
and element.GlobalId not in self.diff['added'] \
and element.GlobalId not in self.diff['changed'].keys():
return
self.ifc_import_settings.logger.info('Creating object {}'.format(element))
self.time = time.time()
if element.is_a('IfcOpeningElement'):
return
try:
representation_id = self.get_representation_id(element)
mesh_name = 'mesh-{}'.format(representation_id)
mesh = self.meshes.get(mesh_name)
if mesh is None \
or representation_id is None:
shape = ifcopenshell.geom.create_shape(self.settings, element)
self.ifc_import_settings.logger.info('Shape was generated in {:.2f}'.format(time.time() - self.time))
self.time = time.time()
mesh = self.create_mesh(element, shape)
self.meshes[mesh_name] = mesh
self.mesh_shapes[mesh_name] = shape
else:
self.ifc_import_settings.logger.info('Mesh reused.')
except:
self.ifc_import_settings.logger.error('Failed to generate shape for {}'.format(element))
return
obj = bpy.data.objects.new(self.get_name(element), mesh)
self.material_creator.create(element, obj, mesh)
obj.matrix_world = self.get_element_matrix(element, mesh_name)
self.add_element_attributes(element, obj)
self.add_element_document_relations(element, obj)
def add_element_document_relations(self, element, obj):
for association in element.HasAssociations:
if association.is_a('IfcRelAssociatesDocument'):
document_reference = association.RelatingDocument
document = obj.BIMObjectProperties.documents.add()
document.file = document_reference.Location
def place_objects_in_spatial_tree(self):
for global_id, obj in self.added_data.items():
self.place_object_in_spatial_tree(self.file.by_guid(global_id), obj)
def place_object_in_spatial_tree(self, element, obj):
if hasattr(element, 'ContainedInStructure') \
and element.ContainedInStructure \
and element.ContainedInStructure[0].RelatingStructure:
container = element.ContainedInStructure[0].RelatingStructure
if container.is_a('IfcSpace'):
if container.GlobalId in self.added_data:
obj.BIMObjectProperties.relating_structure = self.added_data[container.GlobalId]
return self.place_object_in_spatial_tree(container, obj)
relating_structure_global_id = container.GlobalId
if relating_structure_global_id in self.spatial_structure_elements:
self.spatial_structure_elements[relating_structure_global_id]['blender'].objects.link(obj)
elif hasattr(element, 'Decomposes') \
and element.Decomposes:
if element.Decomposes[0].RelatingObject.is_a('IfcProject'):
collection = bpy.data.collections.get(f'IfcProject/{element.Decomposes[0].RelatingObject.Name}')
elif element.Decomposes[0].RelatingObject.is_a('IfcSpatialStructureElement'):
global_id = element.Decomposes[0].RelatingObject.GlobalId
if global_id in self.spatial_structure_elements:
collection = self.spatial_structure_elements[global_id]['blender']
elif self.ifc_import_settings.should_import_aggregates:
collection = bpy.data.collections.get(f'IfcRelAggregates/{element.Decomposes[0].id()}')
else:
return self.place_object_in_spatial_tree(element.Decomposes[0].RelatingObject, obj)
if collection:
collection.objects.link(obj)
elif hasattr(element, 'HasFillings') \
and element.HasFillings:
bpy.data.collections.get('IfcOpeningElements').objects.link(obj)
else:
self.ifc_import_settings.logger.warning('Warning: this object is outside the spatial hierarchy')
bpy.context.scene.collection.objects.link(obj)
def add_element_attributes(self, element, obj):
attributes = element.get_info()
if element.is_a() in schema.ifc.elements:
applicable_attributes = [a['name'] for a in schema.ifc.elements[element.is_a()]['attributes']]
for key, value in attributes.items():
if key not in applicable_attributes \
or value is None:
continue
attribute = obj.BIMObjectProperties.attributes.add()
attribute.name = key
attribute.data_type = 'string'
attribute.string_value = str(value)
def get_element_matrix(self, element, mesh_name):
element_matrix = self.get_local_placement(element.ObjectPlacement)
# Blender supports reusing a mesh with a different transformation
# applied at the object level. In contrast, IFC supports reusing a mesh
# with a different transformation applied at the mesh level _as well as_
# the object level. For this reason, if the end-goal is to re-use mesh
# data, we must combine IFC's mesh-level transformation into Blender's
# object level transformation.
# The first step to do this is to _undo_ the mesh-level transformation
# from whatever shared mesh we are using, as it is not necessarily the
# same as the current mesh.
shared_shape_transformation = self.get_representation_cartesian_transformation(
self.file.by_id(self.mesh_shapes[mesh_name].product.id()))
if shared_shape_transformation:
shared_transform = self.get_cartesiantransformationoperator(shared_shape_transformation)
shared_transform.invert()
element_matrix = element_matrix @ shared_transform
# The next step is to apply the current element's mesh level
# transformation to our current element's object transformation
transformation = self.get_representation_cartesian_transformation(element)
if transformation:
element_matrix = self.get_cartesiantransformationoperator(transformation) @ element_matrix
element_matrix[0][3] *= self.unit_scale
element_matrix[1][3] *= self.unit_scale
element_matrix[2][3] *= self.unit_scale
return element_matrix
def get_representation_id(self, element):
if not element.Representation:
return None
for representation in element.Representation.Representations:
if not representation.is_a('IfcShapeRepresentation'):
continue
if representation.RepresentationIdentifier == 'Body' \
and representation.RepresentationType != 'MappedRepresentation':
return representation.id()
elif representation.RepresentationIdentifier == 'Body':
return representation.Items[0].MappingSource.MappedRepresentation.id()
def get_representation_cartesian_transformation(self, element):
if not element.Representation:
return None
for representation in element.Representation.Representations:
if not representation.is_a('IfcShapeRepresentation'):
continue
if representation.RepresentationIdentifier == 'Body' \
and representation.RepresentationType == 'MappedRepresentation':
return representation.Items[0].MappingTarget
def create_mesh(self, element, shape):
try:
if hasattr(shape, 'geometry'):
geometry = shape.geometry
else:
geometry = shape
mesh = bpy.data.meshes.new(geometry.id)
f = geometry.faces
e = geometry.edges
v = geometry.verts
vertices = [[v[i], v[i + 1], v[i + 2]]
for i in range(0, len(v), 3)]
faces = [[f[i], f[i + 1], f[i + 2]]
for i in range(0, len(f), 3)]
if faces:
edges = []
else:
edges = [[e[i], e[i + 1]]
for i in range(0, len(e), 2)]
mesh.from_pydata(vertices, edges, faces)
ios_materials = []
for mat in geometry.materials:
if mat.original_name():
ios_materials.append(mat.original_name())
else:
ios_materials.append(mat.name)
mesh['ios_materials'] = ios_materials
mesh['ios_material_ids'] = geometry.material_ids
return mesh
except:
self.ifc_import_settings.logger.error('Could not create mesh for {}: {}/{}'.format(element.GlobalId, self.get_name(element)))
def a2p(self, o, z, x):
y = z.cross(x)
r = mathutils.Matrix((x, y, z, o))
r.resize_4x4()
r.transpose()
return r
def get_axis2placement(self, plc):
z = mathutils.Vector(plc.Axis.DirectionRatios if plc.Axis else (0,0,1))
x = mathutils.Vector(plc.RefDirection.DirectionRatios if plc.RefDirection else (1,0,0))
o = plc.Location.Coordinates
return self.a2p(o,z,x)
def get_cartesiantransformationoperator(self, plc):
x = mathutils.Vector(plc.Axis1.DirectionRatios if plc.Axis1 else (1,0,0))
z = x.cross(mathutils.Vector(plc.Axis2.DirectionRatios if plc.Axis2 else (0,1,0)))
o = plc.LocalOrigin.Coordinates
return self.a2p(o,z,x)
def get_local_placement(self, plc):
if plc.PlacementRelTo is None:
parent = mathutils.Matrix()
else:
parent = self.get_local_placement(plc.PlacementRelTo)
if self.ifc_import_settings.should_ignore_site_coordinates \
and 'IfcSite' in [o.is_a() for o in plc.PlacesObject]:
return parent
return parent @ self.get_axis2placement(plc.RelativePlacement)
class IfcImportSettings:
def __init__(self):
self.logger = None
self.input_file = None
self.should_auto_set_workarounds = True
self.should_ignore_site_coordinates = False
self.should_ignore_building_coordinates = False
self.should_reset_absolute_coordinates = False
self.should_import_curves = False
self.should_import_opening_elements = False
self.should_import_spaces = False
self.should_treat_styled_item_as_material = False
self.should_use_cpu_multiprocessing = False
self.should_use_legacy = False
self.should_merge_by_class = False
self.should_merge_by_material = False
self.should_import_aggregates = True
self.should_clean_mesh = True
self.diff_file = None
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,752 @@
import json
import os
import csv
from pathlib import Path
from . import export_ifc
from . import schema
from . import bcf
import bpy
from bpy.types import PropertyGroup
from bpy.app.handlers import persistent
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
CollectionProperty
)
cwd = os.path.dirname(os.path.realpath(__file__))
diagram_scales_enum = []
products_enum = []
profiledef_enum = []
classes_enum = []
types_enum = []
availablematerialpsets_enum = []
featuresfiles_enum = []
scenarios_enum = []
psetnames_enum = []
psetfiles_enum = []
classification_enum = []
reference_enum = []
attributes_enum = []
materialattributes_enum = []
documents_enum = []
materialtypes_enum = []
contexts_enum = []
subcontexts_enum = []
target_views_enum = []
persons_enum = []
organisations_enum = []
views_enum = []
sheets_enum = []
bcfviewpoints_enum = []
@persistent
def setDefaultProperties(scene):
if bpy.context.scene.BIMProperties.has_model_context \
and len(bpy.context.scene.BIMProperties.model_subcontexts) == 0:
subcontext = bpy.context.scene.BIMProperties.model_subcontexts.add()
subcontext.name = 'Body'
subcontext.target_view = 'MODEL_VIEW'
def getIfcPredefinedTypes(self, context):
global types_enum
if len(types_enum) < 1:
for name, data in schema.ifc.elements.items():
if name != self.ifc_class.strip():
continue
for attribute in data['attributes']:
if attribute['name'] != 'PredefinedType':
continue
types_enum.extend([(e, e, '') for e in attribute['enum_values']])
return types_enum
def refreshClasses(self, context):
global classes_enum
classes_enum.clear()
enum = getIfcClasses(self, context)
context.scene.BIMProperties.ifc_class = enum[0][0]
def refreshPredefinedTypes(self, context):
global types_enum
types_enum.clear()
enum = getIfcPredefinedTypes(self, context)
context.scene.BIMProperties.ifc_predefined_type = enum[0][0]
def getDiagramScales(self, context):
global diagram_scales_enum
if len(diagram_scales_enum) < 1:
diagram_scales_enum.extend([
('1:5000', '1:5000', ''),
('1:2000', '1:2000', ''),
('1:1000', '1:1000', ''),
('1:500', '1:500', ''),
('1:200', '1:200', ''),
('1:100', '1:100', ''),
('1:50', '1:50', ''),
('1:20', '1:20', ''),
('1:10', '1:10', ''),
('1:5', '1:5', ''),
('1:2', '1:2', ''),
('1:1', '1:1', '')
])
return diagram_scales_enum
def getBoundaryConditionClasses(self, context):
return [(c, c, '') for c in
['IfcBoundaryEdgeCondition', 'IfcBoundaryFaceCondition',
'IfcBoundaryNodeCondition', 'IfcBoundaryNodeConditionWarping']]
def refreshBoundaryConditionAttributes(self, context):
while len(context.active_object.BIMObjectProperties.boundary_condition.attributes) > 0:
context.active_object.BIMObjectProperties.boundary_condition.attributes.remove(0)
for attribute in schema.ifc.elements[context.active_object.BIMObjectProperties.boundary_condition.name]['complex_attributes']:
new_attribute = context.active_object.BIMObjectProperties.boundary_condition.attributes.add()
new_attribute.name = attribute['name']
def getIfcProducts(self, context):
global products_enum
if len(products_enum) < 1:
products_enum.extend([(e, e, '') for e in
['IfcElement', 'IfcElementType', 'IfcSpatialElement', 'IfcStructural', 'IfcContext']])
return products_enum
def getIfcClasses(self, context):
global classes_enum
if len(classes_enum) < 1:
classes_enum.extend([(e, e, '') for e in getattr(schema.ifc, self.ifc_product)])
return classes_enum
def getProfileDef(self, context):
global profiledef_enum
if len(profiledef_enum) < 1:
profiledef_enum.extend([(e, e, '') for e in getattr(schema.ifc, 'IfcParameterizedProfileDef')])
return profiledef_enum
def getPersons(self, context):
global persons_enum
if len(persons_enum) < 1:
persons_enum.clear()
with open(os.path.join(self.data_dir, 'owner', 'person.json'), 'r') as f:
persons = json.load(f)
persons_enum.extend([(p['Identification'], p['Identification'], '') for p in persons])
return persons_enum
def getOrganisations(self, context):
global organisations_enum
if len(organisations_enum) < 1:
organisations_enum.clear()
with open(os.path.join(self.data_dir, 'owner', 'organisation.json'), 'r') as f:
organisations = json.load(f)
organisations_enum.extend([(o['Name'], o['Name'], '') for o in organisations])
return organisations_enum
def getAvailableMaterialPsets(self, context):
global availablematerialpsets_enum
if len(availablematerialpsets_enum) < 1:
availablematerialpsets_enum.clear()
files = os.listdir(os.path.join(context.scene.BIMProperties.data_dir, 'material'))
availablematerialpsets_enum.extend([(f, f, '') for f in files])
return availablematerialpsets_enum
def getFeaturesFiles(self, context):
global featuresfiles_enum
if len(featuresfiles_enum) < 1:
featuresfiles_enum.clear()
for filename in Path(context.scene.BIMProperties.features_dir).glob('*.feature'):
f = str(filename.stem)
featuresfiles_enum.append((f, f, ''))
return featuresfiles_enum
def refreshFeaturesFiles(self, context):
global featuresfiles_enum
featuresfiles_enum.clear()
getFeaturesFiles(self, context)
def getScenarios(self, context):
global scenarios_enum
if len(scenarios_enum) < 1:
scenarios_enum.clear()
filename = os.path.join(
context.scene.BIMProperties.features_dir,
context.scene.BIMProperties.features_file + '.feature')
with open(filename, 'r') as feature_file:
lines = feature_file.readlines()
for line in lines:
if 'Scenario:' in line:
s = line.strip()[len('Scenario: '):]
scenarios_enum.append((s, s, ''))
return scenarios_enum
def refreshScenarios(self, context):
global scenarios_enum
scenarios_enum.clear()
getScenarios(self, context)
def getPsetNames(self, context):
global psetnames_enum
if len(psetnames_enum) < 1:
psetnames_enum.clear()
files = os.listdir(os.path.join(self.data_dir, 'pset'))
psetnames_enum.extend([(f, f, '') for f in files])
return psetnames_enum
def refreshPsetFiles(self, context):
global psetfiles_enum
psetfiles_enum.clear()
getPsetFiles(self, context)
def getPsetFiles(self, context):
global psetfiles_enum
if len(psetfiles_enum) < 1:
if not self.pset_name.strip():
return psetfiles_enum
files = os.listdir(os.path.join(self.data_dir, 'pset', self.pset_name.strip()))
psetfiles_enum.extend([(f.replace('.csv', ''), f.replace('.csv', ''), '') for f in files])
return psetfiles_enum
def getClassifications(self, context):
global classification_enum
if len(classification_enum) < 1:
classification_enum.clear()
with open(os.path.join(self.data_dir, 'class', 'classifications.csv'), 'r') as f:
data = list(csv.reader(f))
keys = data.pop(0)
index = keys.index('Name')
classification_enum.extend([(str(i), d[index], '') for i, d in enumerate(data)])
return classification_enum
def refreshReferences(self, context):
global reference_enum
reference_enum.clear()
getReferences(self, context)
def getReferences(self, context):
global reference_enum
if len(reference_enum) < 1:
if not self.classification.strip():
return reference_enum
with open(os.path.join(self.data_dir, 'class', 'references.csv'), 'r') as f:
data = list(csv.reader(f))
keys = data.pop(0)
reference_enum.extend([(d[0], '{} - {}'.format(d[0], d[1]), '') for d in data if
d[2] == self.classification.strip()])
return reference_enum
def getApplicableAttributes(self, context):
global attributes_enum
attributes_enum.clear()
if '/' in context.active_object.name \
and context.active_object.name.split('/')[0] in schema.ifc.elements:
attributes_enum.extend([(a['name'], a['name'], '') for a in
schema.ifc.elements[context.active_object.name.split('/')[0]]['attributes']
if self.attributes.find(a['name']) == -1])
return attributes_enum
def getApplicableMaterialAttributes(self, context):
global materialattributes_enum
materialattributes_enum.clear()
if '/' in context.active_object.name \
and context.active_object.name.split('/')[0] in schema.ifc.elements:
material_type = context.active_object.BIMObjectProperties.material_type
if material_type[-3:] == 'Set':
material_type = material_type[0:-3]
materialattributes_enum.extend([(a['name'], a['name'], '') for a in
schema.ifc.IfcMaterialDefinition[material_type]['attributes']
if self.attributes.find(a['name']) == -1])
return materialattributes_enum
def refreshProfileAttributes(self, context):
while len(context.active_object.active_material.BIMMaterialProperties.profile_attributes) > 0:
context.active_object.active_material.BIMMaterialProperties.profile_attributes.remove(0)
for attribute in schema.ifc.IfcParameterizedProfileDef[self.profile_def]['attributes']:
profile_attribute = context.active_object.active_material.BIMMaterialProperties.profile_attributes.add()
profile_attribute.name = attribute['name']
def getApplicableDocuments(self, context):
global documents_enum
documents_enum.clear()
doc_path = os.path.join(context.scene.BIMProperties.data_dir, 'doc')
for filename in Path(doc_path).glob('**/*'):
uri = str(filename.relative_to(doc_path).as_posix())
documents_enum.append((uri, uri, ''))
return documents_enum
def getMaterialTypes(self, context):
global materialtypes_enum
materialtypes_enum.clear()
materialtypes_enum = [(m, m, '') for m in [
'IfcMaterial',
'IfcMaterialConstituentSet',
'IfcMaterialLayerSet',
'IfcMaterialProfileSet']]
return materialtypes_enum
def getSubcontexts(self, context):
global subcontexts_enum
subcontexts_enum.clear()
# TODO: allow override of generated subcontexts?
subcontexts = export_ifc.IfcExportSettings().subcontexts
for subcontext in subcontexts:
subcontexts_enum.append((subcontext, subcontext, ''))
return subcontexts_enum
def getTargetViews(self, context):
global target_views_enum
target_views_enum.clear()
for target_view in export_ifc.IfcExportSettings().target_views:
target_views_enum.append((target_view, target_view, ''))
return target_views_enum
def getViews(self, context):
global views_enum
views_enum.clear()
views_collection = bpy.data.collections.get('Views')
if not views_collection:
return views_enum
for collection in views_collection.children:
for obj in collection.objects:
if obj.type == 'CAMERA':
views_enum.append((obj.name, obj.name, ''))
return views_enum
def refreshSheets(self, context):
global sheets_enum
sheets_enum.clear()
getSheets(self, context)
def getSheets(self, context):
global sheets_enum
if len(sheets_enum) < 1:
sheets_enum.clear()
for filename in Path(os.path.join(context.scene.BIMProperties.data_dir, 'sheets')).glob('*.svg'):
f = str(filename.stem)
sheets_enum.append((f, f, ''))
return sheets_enum
class Subcontext(PropertyGroup):
name: StringProperty(name='Name')
target_view: StringProperty(name='Target View')
class DocProperties(PropertyGroup):
should_recut: BoolProperty(name="Should Recut", default=True)
view_name: StringProperty(name="View Name")
available_views: EnumProperty(items=getViews, name="Available Views")
sheet_name: StringProperty(name="Sheet Name", update=refreshSheets)
available_sheets: EnumProperty(items=getSheets, name="Available Sheets")
class BIMCameraProperties(PropertyGroup):
view_name: StringProperty(name="View Name")
diagram_scale: EnumProperty(items=getDiagramScales, name='Diagram Scale')
is_nts: BoolProperty(name='Is NTS')
class BcfTopic(PropertyGroup):
name: StringProperty(name='Name')
class BcfTopicLabel(PropertyGroup):
name: StringProperty(name='Name')
class BcfTopicLink(PropertyGroup):
name: StringProperty(name='Name')
class BcfTopicFile(PropertyGroup):
name: StringProperty(name='Name')
reference: StringProperty(name='Reference')
date: StringProperty(name='Date')
is_external: BoolProperty(name='Is External')
ifc_project: StringProperty(name='IFC Project')
ifc_spatial: StringProperty(name='IFC Spatial')
class BcfTopicDocumentReference(PropertyGroup):
name: StringProperty(name='Reference')
description: StringProperty(name='Description')
guid: StringProperty(name='GUID')
is_external: BoolProperty(name='Is External')
class BcfTopicRelatedTopic(PropertyGroup):
name: StringProperty(name='Name')
guid: StringProperty(name='GUID')
def refreshBcfTopic(self, context):
RefreshBcfTopic.refresh(context)
class RefreshBcfTopic():
props: None
topic: None
@classmethod
def refresh(cls, context):
import bcfplugin
global bcfviewpoints_enum
cls.props = bpy.context.scene.BCFProperties
cls.topic = bcf.BcfStore.topics[cls.props.active_topic_index][1]
cls.load_topic_metadata()
cls.load_topic_labels()
cls.load_topic_files()
cls.load_topic_links()
cls.load_snippet()
cls.load_document_references()
cls.load_related_topics()
cls.load_viewpoints()
cls.load_comments()
@classmethod
def load_topic_metadata(cls):
cls.props.topic_guid = str(cls.topic.xmlId)
cls.props.topic_type = cls.topic.type
cls.props.topic_status = cls.topic.status
cls.props.topic_priority = cls.topic.priority
cls.props.topic_stage = cls.topic.stage
if cls.topic.date:
cls.props.topic_creation_date = cls.topic.date.strftime('%a %Y-%m-%d %H:%S')
else:
cls.props.topic_creation_date = ''
cls.props.topic_creation_author = cls.topic.author
if cls.topic.modDate:
cls.props.topic_modified_date = cls.topic.modDate.strftime('%a %Y-%m-%d %H:%S')
else:
cls.props.topic_modified_date = ''
cls.props.topic_modified_author = cls.topic.modAuthor
cls.props.topic_assigned_to = cls.topic.assignee
if cls.topic.dueDate:
cls.props.topic_due_date = cls.topic.dueDate.strftime('%a %Y-%m-%d %H:%S')
else:
cls.props.topic_due_date = ''
cls.props.topic_description = cls.topic.description
@classmethod
def load_topic_labels(cls):
while len(cls.props.topic_labels) > 0:
cls.props.topic_labels.remove(0)
for label in cls.topic.labels:
new = cls.props.topic_labels.add()
new.name = label.value
@classmethod
def load_topic_files(cls):
import bcfplugin
while len(cls.props.topic_files) > 0:
cls.props.topic_files.remove(0)
files = bcfplugin.getRelevantIfcFiles(cls.topic)
for f in files:
new = cls.props.topic_files.add()
new.name = f.filename
new.date = f.time.strftime('%a %Y-%m-%d %H:%S')
new.reference = f.reference.uri
new.ifc_project = f.ifcProjectId
new.ifc_spatial = f.ifcSpatialStructureElement
new.is_external = f.external
@classmethod
def load_topic_links(cls):
while len(cls.props.topic_links) > 0:
cls.props.topic_links.remove(0)
for link in cls.topic.referenceLinks:
new = cls.props.topic_links.add()
new.name = link.value
@classmethod
def load_snippet(cls):
cls.props.topic_has_snippet = bool(cls.topic.bimSnippet)
if cls.topic.bimSnippet:
cls.props.topic_snippet_reference = cls.topic.bimSnippet.reference.uri
if cls.topic.bimSnippet.schema.uri:
cls.props.topic_snippet_schema = cls.topic.bimSnippet.schema.uri
cls.props.topic_snippet_type = cls.topic.bimSnippet.type
if cls.topic.bimSnippet.external:
cls.props.topic_snippet_is_external = cls.topic.bimSnippet.external
else:
cls.props.topic_snippet_is_external = False
@classmethod
def load_document_references(cls):
while len(cls.props.topic_document_references) > 0:
cls.props.topic_document_references.remove(0)
for doc in cls.topic.docRefs:
new = cls.props.topic_document_references.add()
new.name = doc.reference.uri
new.description = doc.description
new.guid = str(doc.guid)
new.is_external = doc.external
@classmethod
def load_related_topics(cls):
import bcfplugin
while len(cls.props.topic_related_topics) > 0:
cls.props.topic_related_topics.remove(0)
for t in cls.topic.relatedTopics:
new = cls.props.topic_related_topics.add()
new.name = bcfplugin.getTopicFromUUID(t.value).title
new.guid = str(t.value)
@classmethod
def load_viewpoints(cls):
import bcfplugin
bcfviewpoints_enum.clear()
bcf.BcfStore.viewpoints = bcfplugin.getViewpoints(cls.topic, realViewpoint=False)
for i, viewpoint in enumerate(bcf.BcfStore.viewpoints):
bcfviewpoints_enum.append((str(i), 'View {}'.format(i+1), ''))
@classmethod
def load_comments(cls):
import bcfplugin
bcf.BcfStore.comments = bcfplugin.getComments(cls.topic)
comments = bpy.data.texts.get('BCF Comments')
if comments:
comments.clear()
else:
comments = bpy.data.texts.new('BCF Comments')
for i, comment in enumerate(bcf.BcfStore.comments):
comments.write('# Comment {} - {}\n'.format(i + 1, comment[1].xmlId))
comments.write('# From: {} on {}\n'.format(comment[1].author, comment[1].date))
if comment[1].modDate:
comments.write('# Modified by {} on {}\n'.format(comment[1].modAuthor, comment[1].modDate))
comments.write(comment[1].comment)
comments.write('\n\n-----\n\n')
def getBcfViewpoints(self, context):
global bcfviewpoints_enum
return bcfviewpoints_enum
class BIMProperties(PropertyGroup):
schema_dir: StringProperty(default=os.path.join(cwd ,'schema') + os.path.sep, name="Schema Directory")
data_dir: StringProperty(default=os.path.join(cwd, 'data') + os.path.sep, name="Data Directory")
ifc_file: StringProperty(name="IFC File")
audit_ifc_class: EnumProperty(items=getIfcClasses, name="Audit Class")
ifc_product: EnumProperty(items=getIfcProducts, name="Products", update=refreshClasses)
ifc_class: EnumProperty(items=getIfcClasses, name="Class", update=refreshPredefinedTypes)
ifc_predefined_type: EnumProperty(
items = getIfcPredefinedTypes,
name="Predefined Type", default=None)
ifc_userdefined_type: StringProperty(name="Userdefined Type")
export_has_representations: BoolProperty(name="Export Representations", default=True)
export_should_export_all_materials_as_styled_items: BoolProperty(name="Export All Materials as Styled Items", default=False)
export_should_use_presentation_style_assignment: BoolProperty(name="Export with Presentation Style Assignment", default=False)
import_should_ignore_site_coordinates: BoolProperty(name="Import Ignoring Site Coordinates", default=False)
import_should_ignore_building_coordinates: BoolProperty(name="Import Ignoring Building Coordinates", default=False)
import_should_reset_absolute_coordinates: BoolProperty(name="Import Resetting Absolute Coordinates", default=False)
import_should_import_curves: BoolProperty(name="Import Curves", default=False)
import_should_import_opening_elements: BoolProperty(name="Import Opening Elements", default=False)
import_should_import_spaces: BoolProperty(name="Import Spaces", default=False)
import_should_auto_set_workarounds: BoolProperty(name="Automatically Set Vendor Workarounds", default=True)
import_should_treat_styled_item_as_material: BoolProperty(name="Import Treating Styled Item as Material", default=False)
import_should_use_legacy: BoolProperty(name="Import with Legacy Importer", default=False)
import_should_use_cpu_multiprocessing: BoolProperty(name="Import with CPU Multiprocessing", default=False)
import_should_import_aggregates: BoolProperty(name="Import Aggregates", default=True)
import_should_merge_by_class: BoolProperty(name="Import and Merge by Class", default=False)
import_should_merge_by_material: BoolProperty(name="Import and Merge by Material", default=False)
import_should_clean_mesh: BoolProperty(name="Import and Clean Mesh", default=True)
qa_reject_element_reason: StringProperty(name="Element Rejection Reason")
person: EnumProperty(items=getPersons, name="Person")
organisation: EnumProperty(items=getOrganisations, name="Organisation")
pset_name: EnumProperty(items=getPsetNames, name="Pset Name", update=refreshPsetFiles)
pset_file: EnumProperty(items=getPsetFiles, name="Pset File")
has_georeferencing: BoolProperty(name="Has Georeferencing", default=False)
has_library: BoolProperty(name="Has Project Library", default=False)
search_regex: BoolProperty(name="Search With Regex", default=False)
search_ignorecase: BoolProperty(name="Search Ignoring Case", default=True)
global_id: StringProperty(name="GlobalId")
search_attribute_name: StringProperty(name="Search Attribute Name")
search_attribute_value: StringProperty(name="Search Attribute Value")
search_pset_name: StringProperty(name="Search Pset Name")
search_prop_name: StringProperty(name="Search Prop Name")
search_pset_value: StringProperty(name="Search Pset Value")
features_dir: StringProperty(default='', name="Features Directory", update=refreshFeaturesFiles)
features_file: EnumProperty(items=getFeaturesFiles, name="Features File", update=refreshScenarios)
scenario: EnumProperty(items=getScenarios, name="Scenario")
diff_json_file: StringProperty(default='', name="Diff JSON File")
diff_old_file: StringProperty(default='', name="Diff Old IFC File")
diff_new_file: StringProperty(default='', name="Diff New IFC File")
aggregate_class: EnumProperty(items=getIfcClasses, name="Aggregate Class")
aggregate_name: StringProperty(name="Aggregate Name")
classification: EnumProperty(items=getClassifications, name="Classification", update=refreshReferences)
reference: EnumProperty(items=getReferences, name="Reference")
has_model_context: BoolProperty(name="Has Model Context", default=True)
has_plan_context: BoolProperty(name="Has Plan Context", default=False)
model_subcontexts: CollectionProperty(name='Model Subcontexts', type=Subcontext)
plan_subcontexts: CollectionProperty(name='Plan Subcontexts', type=Subcontext)
available_contexts: EnumProperty(items=[('Model', 'Model', ''), ('Plan', 'Plan', '')], name="Available Contexts")
available_subcontexts: EnumProperty(items=getSubcontexts, name="Available Subcontexts")
available_target_views: EnumProperty(items=getTargetViews, name="Available Target Views")
class BCFProperties(PropertyGroup):
bcf_file: StringProperty(default='', name='BCF File')
topics: CollectionProperty(name='BCF Topics', type=BcfTopic)
active_topic_index: IntProperty(name='Active BCF Topic Index', update=refreshBcfTopic)
viewpoints: EnumProperty(items=getBcfViewpoints, name='BCF Viewpoints')
topic_guid: StringProperty(default='', name='Topic GUID')
topic_type: StringProperty(default='', name='Topic Type')
topic_status: StringProperty(default='', name='Topic Status')
topic_priority: StringProperty(default='', name='Topic Priority')
topic_stage: StringProperty(default='', name='Topic Stage')
topic_creation_date: StringProperty(default='', name='Topic Date')
topic_creation_author: StringProperty(default='', name='Topic Author')
topic_modified_date: StringProperty(default='', name='Topic Modified Date')
topic_modified_author: StringProperty(default='', name='Topic Modified By')
topic_assigned_to: StringProperty(default='', name='Topic Assigned To')
topic_due_date: StringProperty(default='', name='Topic Due Date')
topic_description: StringProperty(default='', name='Topic Description')
topic_labels: CollectionProperty(name='BCF Topic Labels', type=BcfTopicLabel)
topic_files: CollectionProperty(name='BCF Topic Files', type=BcfTopicFile)
topic_links: CollectionProperty(name='BCF Topic Links', type=BcfTopicLink)
topic_has_snippet: BoolProperty(name='BCF Topic Has Snippet', default=False)
topic_snippet_reference: StringProperty(name='BIM Snippet Reference')
topic_snippet_schema: StringProperty(name='BIM Snippet Schema')
topic_snippet_type: StringProperty(name='BIM Snippet Type')
topic_snippet_is_external: BoolProperty(name='Is BIM Snippet External')
topic_document_references: CollectionProperty(name='BCF Topic Document References', type=BcfTopicDocumentReference)
topic_related_topics: CollectionProperty(name='BCF Topic Related Topics', type=BcfTopicRelatedTopic)
class MapConversion(PropertyGroup):
eastings: StringProperty(name="Eastings")
northings: StringProperty(name="Northings")
orthogonal_height: StringProperty(name="Orthogonal Height")
x_axis_abscissa: StringProperty(name="X Axis Abscissa")
x_axis_ordinate: StringProperty(name="X Axis Ordinate")
scale: StringProperty(name="Scale")
class TargetCRS(PropertyGroup):
name: StringProperty(name="Name")
description: StringProperty(name="Description")
geodetic_datum: StringProperty(name="Geodetic Datum")
vertical_datum: StringProperty(name="Vertical Datum")
map_projection: StringProperty(name="Map Projection")
map_zone: StringProperty(name="Map Zone")
map_unit: StringProperty(name="Map Unit")
class BIMLibrary(PropertyGroup):
name: StringProperty(name="Name")
version: StringProperty(name="Version")
publisher: StringProperty(name="Publisher")
version_date: StringProperty(name="Version Date")
location: StringProperty(name="Location")
description: StringProperty(name="Description")
class Attribute(PropertyGroup):
name: StringProperty(name="Name")
data_type: StringProperty(name="Data Type")
string_value: StringProperty(name="Value")
bool_value: BoolProperty(name="Value")
int_value: IntProperty(name="Value")
float_value: FloatProperty(name="Value")
class PsetQto(PropertyGroup):
name: StringProperty(name="Name")
file: StringProperty(name="File")
properties: CollectionProperty(name="Properties", type=Attribute)
class Document(PropertyGroup):
file: StringProperty(name="File")
class Classification(PropertyGroup):
name: StringProperty(name="Name")
identification: StringProperty(name="Identification")
class GlobalId(PropertyGroup):
name: StringProperty(name="Name")
class BoundaryCondition(PropertyGroup):
name: EnumProperty(items=getBoundaryConditionClasses, name='Boundary Type', update=refreshBoundaryConditionAttributes)
attributes: CollectionProperty(name="Attributes", type=Attribute)
class BIMObjectProperties(PropertyGroup):
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
attributes: CollectionProperty(name="Attributes", type=Attribute)
relating_type: PointerProperty(name='Type Product', type=bpy.types.Object)
relating_structure: PointerProperty(name='Spatial Container', type=bpy.types.Object)
psets: CollectionProperty(name="Psets", type=PsetQto)
qtos: CollectionProperty(name="Qtos", type=PsetQto)
applicable_attributes: EnumProperty(items=getApplicableAttributes, name="Attribute Names")
documents: CollectionProperty(name="Documents", type=Document)
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
classifications: CollectionProperty(name="Classifications", type=Classification)
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
override_psets: CollectionProperty(name="Override Psets", type=PsetQto)
override_pset_name: StringProperty(name="Override Pset Name")
qto_name: StringProperty(name="Qto Name")
has_boundary_condition: BoolProperty(name='Has Boundary Condition')
boundary_condition: PointerProperty(name='Boundary Condition', type=BoundaryCondition)
structural_member_connection: PointerProperty(name='Structural Member Connection', type=bpy.types.Object)
class BIMMaterialProperties(PropertyGroup):
is_external: BoolProperty(name="Has External Definition")
location: StringProperty(name="Location")
identification: StringProperty(name="Identification")
name: StringProperty(name="Name")
available_material_psets: EnumProperty(items=getAvailableMaterialPsets, name="Material Pset")
psets: CollectionProperty(name="Psets", type=PsetQto)
attributes: CollectionProperty(name="Attributes", type=Attribute)
applicable_attributes: EnumProperty(items=getApplicableMaterialAttributes, name="Attribute Names")
profile_def: EnumProperty(items=getProfileDef, name='Parameterized Profile Def', update=refreshProfileAttributes)
profile_attributes: CollectionProperty(name='Profile Attributes', type=Attribute)
class SweptSolid(PropertyGroup):
name: StringProperty(name="Name")
outer_curve: StringProperty(name="Outer Curve")
inner_curves: StringProperty(name="Inner Curves")
extrusion: StringProperty(name="Extrusion")
class BIMMeshProperties(PropertyGroup):
is_wireframe: BoolProperty(name="Is Wireframe")
is_swept_solid: BoolProperty(name="Is Swept Solid")
swept_solids: CollectionProperty(name="Swept Solids", type=SweptSolid)
is_parametric: BoolProperty(name='Is Parametric', default=False)
@@ -0,0 +1,49 @@
import os
import json
import ifcopenshell
from pathlib import Path
cwd = os.path.dirname(os.path.realpath(__file__))
class IfcSchema():
def __init__(self):
self.schema_dir = os.path.join(cwd, 'schema') # TODO: make configurable
# TODO: Make it less troublesome
self.products = [
'IfcContext',
'IfcElement',
'IfcSpatialElement',
'IfcStructural',
'IfcMaterialDefinition',
'IfcParameterizedProfileDef',
'IfcBoundaryCondition',
'IfcElementType'
]
self.elements = {}
self.property_files = []
property_paths = Path(self.schema_dir).glob('Pset_*.ifc')
for path in property_paths:
self.property_files.append(ifcopenshell.open(path))
self.psets = {}
self.qtos = {}
self.load()
def load(self):
for product in self.products:
with open(os.path.join(self.schema_dir, f'{product}_IFC4.json')) as f:
setattr(self, product, json.load(f))
self.elements.update(getattr(self, product))
with open(os.path.join(self.schema_dir, 'ifc_types_IFC4.json')) as f:
self.type_map = json.load(f)
for property_file in self.property_files:
for prop in property_file.by_type('IfcPropertySetTemplate'):
if prop.Name[0:4] == 'Qto_':
self.qtos[prop.Name] = {
'HasPropertyTemplates': {p.Name: p for p in prop.HasPropertyTemplates}}
else:
self.psets[prop.Name] = {
'HasPropertyTemplates': {p.Name: p for p in prop.HasPropertyTemplates}}
ifc = IfcSchema()
@@ -0,0 +1,256 @@
{
"IfcBoundaryEdgeCondition": {
"is_abstract": false,
"parent": "IfcBoundaryCondition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "TranslationalStiffnessByLengthX",
"type": "IfcModulusOfTranslationalSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfLinearSubgradeReactionMeasure"
]
},
{
"name": "TranslationalStiffnessByLengthY",
"type": "IfcModulusOfTranslationalSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfLinearSubgradeReactionMeasure"
]
},
{
"name": "TranslationalStiffnessByLengthZ",
"type": "IfcModulusOfTranslationalSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfLinearSubgradeReactionMeasure"
]
},
{
"name": "RotationalStiffnessByLengthX",
"type": "IfcModulusOfRotationalSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfRotationalSubgradeReactionMeasure"
]
},
{
"name": "RotationalStiffnessByLengthY",
"type": "IfcModulusOfRotationalSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfRotationalSubgradeReactionMeasure"
]
},
{
"name": "RotationalStiffnessByLengthZ",
"type": "IfcModulusOfRotationalSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfRotationalSubgradeReactionMeasure"
]
}
]
},
"IfcBoundaryFaceCondition": {
"is_abstract": false,
"parent": "IfcBoundaryCondition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "TranslationalStiffnessByAreaX",
"type": "IfcModulusOfSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfSubgradeReactionMeasure"
]
},
{
"name": "TranslationalStiffnessByAreaY",
"type": "IfcModulusOfSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfSubgradeReactionMeasure"
]
},
{
"name": "TranslationalStiffnessByAreaZ",
"type": "IfcModulusOfSubgradeReactionSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcModulusOfSubgradeReactionMeasure"
]
}
]
},
"IfcBoundaryNodeCondition": {
"is_abstract": false,
"parent": "IfcBoundaryCondition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "TranslationalStiffnessX",
"type": "IfcTranslationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcLinearStiffnessMeasure"
]
},
{
"name": "TranslationalStiffnessY",
"type": "IfcTranslationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcLinearStiffnessMeasure"
]
},
{
"name": "TranslationalStiffnessZ",
"type": "IfcTranslationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcLinearStiffnessMeasure"
]
},
{
"name": "RotationalStiffnessX",
"type": "IfcRotationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcRotationalStiffnessMeasure"
]
},
{
"name": "RotationalStiffnessY",
"type": "IfcRotationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcRotationalStiffnessMeasure"
]
},
{
"name": "RotationalStiffnessZ",
"type": "IfcRotationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcRotationalStiffnessMeasure"
]
}
]
},
"IfcBoundaryNodeConditionWarping": {
"is_abstract": false,
"parent": "IfcBoundaryNodeCondition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "TranslationalStiffnessX",
"type": "IfcTranslationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcLinearStiffnessMeasure"
]
},
{
"name": "TranslationalStiffnessY",
"type": "IfcTranslationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcLinearStiffnessMeasure"
]
},
{
"name": "TranslationalStiffnessZ",
"type": "IfcTranslationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcLinearStiffnessMeasure"
]
},
{
"name": "RotationalStiffnessX",
"type": "IfcRotationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcRotationalStiffnessMeasure"
]
},
{
"name": "RotationalStiffnessY",
"type": "IfcRotationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcRotationalStiffnessMeasure"
]
},
{
"name": "RotationalStiffnessZ",
"type": "IfcRotationalStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcRotationalStiffnessMeasure"
]
},
{
"name": "WarpingStiffness",
"type": "IfcWarpingStiffnessSelect",
"is_select": true,
"select_types": [
"IfcBoolean",
"IfcWarpingMomentMeasure"
]
}
]
}
}
@@ -0,0 +1,114 @@
{
"IfcProject": {
"is_abstract": false,
"parent": "IfcContext",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Phase",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "UnitsInContext",
"type": "IfcUnitAssignment",
"is_select": false,
"select_types": []
}
]
},
"IfcProjectLibrary": {
"is_abstract": false,
"parent": "IfcContext",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Phase",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "UnitsInContext",
"type": "IfcUnitAssignment",
"is_select": false,
"select_types": []
}
]
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,334 @@
{
"IfcMaterial": {
"is_abstract": false,
"parent": "IfcMaterialDefinition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "Category",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "HasRepresentation",
"type": "IfcMaterialDefinitionRepresentation",
"is_select": false,
"select_types": []
}
]
},
"IfcMaterialConstituent": {
"is_abstract": false,
"parent": "IfcMaterialDefinition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "Fraction",
"type": "IfcNormalisedRatioMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "Category",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Material",
"type": "IfcMaterial",
"is_select": false,
"select_types": []
}
]
},
"IfcMaterialConstituentSet": {
"is_abstract": false,
"parent": "IfcMaterialDefinition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": []
},
"IfcMaterialLayer": {
"is_abstract": false,
"parent": "IfcMaterialDefinition",
"attributes": [
{
"name": "LayerThickness",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "IsVentilated",
"type": "IfcLogical",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "Category",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Priority",
"type": "IfcInteger",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Material",
"type": "IfcMaterial",
"is_select": false,
"select_types": []
}
]
},
"IfcMaterialLayerSet": {
"is_abstract": false,
"parent": "IfcMaterialDefinition",
"attributes": [
{
"name": "LayerSetName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": []
},
"IfcMaterialLayerWithOffsets": {
"is_abstract": false,
"parent": "IfcMaterialLayer",
"attributes": [
{
"name": "LayerThickness",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "IsVentilated",
"type": "IfcLogical",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "Category",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Priority",
"type": "IfcInteger",
"is_enum": false,
"enum_values": []
},
{
"name": "OffsetDirection",
"type": "IfcLayerSetDirectionEnum",
"is_enum": true,
"enum_values": [
"AXIS1",
"AXIS2",
"AXIS3"
]
}
],
"complex_attributes": [
{
"name": "Material",
"type": "IfcMaterial",
"is_select": false,
"select_types": []
}
]
},
"IfcMaterialProfile": {
"is_abstract": false,
"parent": "IfcMaterialDefinition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "Priority",
"type": "IfcInteger",
"is_enum": false,
"enum_values": []
},
{
"name": "Category",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Material",
"type": "IfcMaterial",
"is_select": false,
"select_types": []
},
{
"name": "Profile",
"type": "IfcProfileDef",
"is_select": false,
"select_types": []
}
]
},
"IfcMaterialProfileSet": {
"is_abstract": false,
"parent": "IfcMaterialDefinition",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "CompositeProfile",
"type": "IfcCompositeProfileDef",
"is_select": false,
"select_types": []
}
]
},
"IfcMaterialProfileWithOffsets": {
"is_abstract": false,
"parent": "IfcMaterialProfile",
"attributes": [
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "Priority",
"type": "IfcInteger",
"is_enum": false,
"enum_values": []
},
{
"name": "Category",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Material",
"type": "IfcMaterial",
"is_select": false,
"select_types": []
},
{
"name": "Profile",
"type": "IfcProfileDef",
"is_select": false,
"select_types": []
}
]
}
}
@@ -0,0 +1,834 @@
{
"IfcAsymmetricIShapeProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "BottomFlangeWidth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "OverallDepth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WebThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "BottomFlangeThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "BottomFlangeFilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "TopFlangeWidth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "TopFlangeThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "TopFlangeFilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "BottomFlangeEdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "BottomFlangeSlope",
"type": "IfcPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "TopFlangeEdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "TopFlangeSlope",
"type": "IfcPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcCShapeProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Depth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "Width",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WallThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "Girth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "InternalFilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcCircleHollowProfileDef": {
"is_abstract": false,
"parent": "IfcCircleProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Radius",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WallThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcCircleProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Radius",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcEllipseProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "SemiAxis1",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "SemiAxis2",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcIShapeProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "OverallWidth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "OverallDepth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WebThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeEdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeSlope",
"type": "IfcPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcLShapeProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Depth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "Width",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "Thickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "EdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "LegSlope",
"type": "IfcPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcRectangleHollowProfileDef": {
"is_abstract": false,
"parent": "IfcRectangleProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "XDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "YDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WallThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "InnerFilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "OuterFilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcRectangleProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "XDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "YDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcRoundedRectangleProfileDef": {
"is_abstract": false,
"parent": "IfcRectangleProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "XDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "YDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "RoundingRadius",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcTShapeProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Depth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeWidth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WebThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeEdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WebEdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WebSlope",
"type": "IfcPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeSlope",
"type": "IfcPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcTrapeziumProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "BottomXDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "TopXDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "YDim",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "TopXOffset",
"type": "IfcLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcUShapeProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Depth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeWidth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WebThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "EdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeSlope",
"type": "IfcPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
},
"IfcZShapeProfileDef": {
"is_abstract": false,
"parent": "IfcParameterizedProfileDef",
"attributes": [
{
"name": "ProfileType",
"type": "IfcProfileTypeEnum",
"is_enum": true,
"enum_values": [
"CURVE",
"AREA"
]
},
{
"name": "ProfileName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Depth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeWidth",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "WebThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FlangeThickness",
"type": "IfcPositiveLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "FilletRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "EdgeRadius",
"type": "IfcNonNegativeLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "Position",
"type": "IfcAxis2Placement2D",
"is_select": false,
"select_types": []
}
]
}
}
@@ -0,0 +1,554 @@
{
"IfcBuilding": {
"is_abstract": false,
"parent": "IfcSpatialStructureElement",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "CompositionType",
"type": "IfcElementCompositionEnum",
"is_enum": true,
"enum_values": [
"COMPLEX",
"ELEMENT",
"PARTIAL"
]
},
{
"name": "ElevationOfRefHeight",
"type": "IfcLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "ElevationOfTerrain",
"type": "IfcLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "IsDeclaredBy",
"type": "IfcRelDefinesByObject",
"is_select": false,
"select_types": []
},
{
"name": "IsTypedBy",
"type": "IfcRelDefinesByType",
"is_select": false,
"select_types": []
},
{
"name": "ObjectPlacement",
"type": "IfcObjectPlacement",
"is_select": false,
"select_types": []
},
{
"name": "Representation",
"type": "IfcProductRepresentation",
"is_select": false,
"select_types": []
},
{
"name": "BuildingAddress",
"type": "IfcPostalAddress",
"is_select": false,
"select_types": []
}
]
},
"IfcBuildingStorey": {
"is_abstract": false,
"parent": "IfcSpatialStructureElement",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "CompositionType",
"type": "IfcElementCompositionEnum",
"is_enum": true,
"enum_values": [
"COMPLEX",
"ELEMENT",
"PARTIAL"
]
},
{
"name": "Elevation",
"type": "IfcLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "IsDeclaredBy",
"type": "IfcRelDefinesByObject",
"is_select": false,
"select_types": []
},
{
"name": "IsTypedBy",
"type": "IfcRelDefinesByType",
"is_select": false,
"select_types": []
},
{
"name": "ObjectPlacement",
"type": "IfcObjectPlacement",
"is_select": false,
"select_types": []
},
{
"name": "Representation",
"type": "IfcProductRepresentation",
"is_select": false,
"select_types": []
}
]
},
"IfcExternalSpatialElement": {
"is_abstract": false,
"parent": "IfcExternalSpatialStructureElement",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "PredefinedType",
"type": "IfcExternalSpatialElementTypeEnum",
"is_enum": true,
"enum_values": [
"EXTERNAL",
"EXTERNAL_EARTH",
"EXTERNAL_WATER",
"EXTERNAL_FIRE",
"USERDEFINED",
"NOTDEFINED"
]
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "IsDeclaredBy",
"type": "IfcRelDefinesByObject",
"is_select": false,
"select_types": []
},
{
"name": "IsTypedBy",
"type": "IfcRelDefinesByType",
"is_select": false,
"select_types": []
},
{
"name": "ObjectPlacement",
"type": "IfcObjectPlacement",
"is_select": false,
"select_types": []
},
{
"name": "Representation",
"type": "IfcProductRepresentation",
"is_select": false,
"select_types": []
}
]
},
"IfcSite": {
"is_abstract": false,
"parent": "IfcSpatialStructureElement",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "CompositionType",
"type": "IfcElementCompositionEnum",
"is_enum": true,
"enum_values": [
"COMPLEX",
"ELEMENT",
"PARTIAL"
]
},
{
"name": "RefLatitude",
"type": "List-IfcCompoundPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "RefLongitude",
"type": "List-IfcCompoundPlaneAngleMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "RefElevation",
"type": "IfcLengthMeasure",
"is_enum": false,
"enum_values": []
},
{
"name": "LandTitleNumber",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "IsDeclaredBy",
"type": "IfcRelDefinesByObject",
"is_select": false,
"select_types": []
},
{
"name": "IsTypedBy",
"type": "IfcRelDefinesByType",
"is_select": false,
"select_types": []
},
{
"name": "ObjectPlacement",
"type": "IfcObjectPlacement",
"is_select": false,
"select_types": []
},
{
"name": "Representation",
"type": "IfcProductRepresentation",
"is_select": false,
"select_types": []
},
{
"name": "SiteAddress",
"type": "IfcPostalAddress",
"is_select": false,
"select_types": []
}
]
},
"IfcSpace": {
"is_abstract": false,
"parent": "IfcSpatialStructureElement",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "CompositionType",
"type": "IfcElementCompositionEnum",
"is_enum": true,
"enum_values": [
"COMPLEX",
"ELEMENT",
"PARTIAL"
]
},
{
"name": "PredefinedType",
"type": "IfcSpaceTypeEnum",
"is_enum": true,
"enum_values": [
"SPACE",
"PARKING",
"GFA",
"INTERNAL",
"EXTERNAL",
"USERDEFINED",
"NOTDEFINED"
]
},
{
"name": "ElevationWithFlooring",
"type": "IfcLengthMeasure",
"is_enum": false,
"enum_values": []
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "IsDeclaredBy",
"type": "IfcRelDefinesByObject",
"is_select": false,
"select_types": []
},
{
"name": "IsTypedBy",
"type": "IfcRelDefinesByType",
"is_select": false,
"select_types": []
},
{
"name": "ObjectPlacement",
"type": "IfcObjectPlacement",
"is_select": false,
"select_types": []
},
{
"name": "Representation",
"type": "IfcProductRepresentation",
"is_select": false,
"select_types": []
}
]
},
"IfcSpatialZone": {
"is_abstract": false,
"parent": "IfcSpatialElement",
"attributes": [
{
"name": "GlobalId",
"type": "IfcGloballyUniqueId",
"is_enum": false,
"enum_values": []
},
{
"name": "Name",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "Description",
"type": "IfcText",
"is_enum": false,
"enum_values": []
},
{
"name": "ObjectType",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "LongName",
"type": "IfcLabel",
"is_enum": false,
"enum_values": []
},
{
"name": "PredefinedType",
"type": "IfcSpatialZoneTypeEnum",
"is_enum": true,
"enum_values": [
"CONSTRUCTION",
"FIRESAFETY",
"LIGHTING",
"OCCUPANCY",
"SECURITY",
"THERMAL",
"TRANSPORT",
"VENTILATION",
"USERDEFINED",
"NOTDEFINED"
]
}
],
"complex_attributes": [
{
"name": "OwnerHistory",
"type": "IfcOwnerHistory",
"is_select": false,
"select_types": []
},
{
"name": "IsDeclaredBy",
"type": "IfcRelDefinesByObject",
"is_select": false,
"select_types": []
},
{
"name": "IsTypedBy",
"type": "IfcRelDefinesByType",
"is_select": false,
"select_types": []
},
{
"name": "ObjectPlacement",
"type": "IfcObjectPlacement",
"is_select": false,
"select_types": []
},
{
"name": "Representation",
"type": "IfcProductRepresentation",
"is_select": false,
"select_types": []
}
]
}
}
@@ -0,0 +1,14 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION((),'2;1');
FILE_NAME('Pset_Custom.ifc','2020-01-01T00:00:00',(),(),'Sample','Sample',$);
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1= IFCPROPERTYSETTEMPLATE('05N2Dhepb9ouTCSmWBh22D',$,'Custom_Pset','An example custom pset.',.PSET_TYPEDRIVENOVERRIDE.,'IfcObject',(#2,#3));
#2= IFCSIMPLEPROPERTYTEMPLATE('37EpTDq4v96gTZh196BBXQ',$,'NumericProperty','An example numeric property',.P_SINGLEVALUE.,'IfcCountMeasure','',$,$,$,$,.READWRITE.);
#3= IFCSIMPLEPROPERTYTEMPLATE('22H7CzDvz1XfVHKkGWoYUK',$,'StringProperty','An example string property',.P_SINGLEVALUE.,'IfcLabel','',$,$,$,$,.READWRITE.);
ENDSEC;
END-ISO-10303-21;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,141 @@
{
"IfcBSplineCurveForm": "string",
"IfcBSplineSurfaceForm": "string",
"IfcBooleanOperator": "string",
"IfcKnotType": "string",
"IfcNullStyle": "string",
"IfcPreferredSurfaceCurveRepresentation": "string",
"IfcSIPrefix": "string",
"IfcSIUnitName": "string",
"IfcSurfaceSide": "string",
"IfcTextPath": "string",
"IfcTransitionCode": "string",
"IfcTrimmingPreference": "string",
"IfcAbsorbedDoseMeasure": "float",
"IfcAccelerationMeasure": "float",
"IfcAmountOfSubstanceMeasure": "float",
"IfcAngularVelocityMeasure": "float",
"IfcAreaDensityMeasure": "float",
"IfcAreaMeasure": "float",
"IfcBoolean": "bool",
"IfcBoxAlignment": "string",
"IfcCardinalPointReference": "float",
"IfcContextDependentMeasure": "float",
"IfcCountMeasure": "float",
"IfcCurvatureMeasure": "float",
"IfcDate": "string",
"IfcDateTime": "string",
"IfcDayInMonthNumber": "float",
"IfcDayInWeekNumber": "float",
"IfcDescriptiveMeasure": "string",
"IfcDimensionCount": "float",
"IfcDoseEquivalentMeasure": "float",
"IfcDuration": "string",
"IfcDynamicViscosityMeasure": "float",
"IfcElectricCapacitanceMeasure": "float",
"IfcElectricChargeMeasure": "float",
"IfcElectricConductanceMeasure": "float",
"IfcElectricCurrentMeasure": "float",
"IfcElectricResistanceMeasure": "float",
"IfcElectricVoltageMeasure": "float",
"IfcEnergyMeasure": "float",
"IfcFontStyle": "string",
"IfcFontVariant": "string",
"IfcFontWeight": "string",
"IfcForceMeasure": "float",
"IfcFrequencyMeasure": "float",
"IfcGloballyUniqueId": "string",
"IfcHeatFluxDensityMeasure": "float",
"IfcHeatingValueMeasure": "float",
"IfcIdentifier": "string",
"IfcIlluminanceMeasure": "float",
"IfcInductanceMeasure": "float",
"IfcInteger": "integer",
"IfcIntegerCountRateMeasure": "integer",
"IfcIonConcentrationMeasure": "float",
"IfcIsothermalMoistureCapacityMeasure": "float",
"IfcKinematicViscosityMeasure": "float",
"IfcLabel": "string",
"IfcLanguageId": "string",
"IfcLengthMeasure": "float",
"IfcLinearForceMeasure": "float",
"IfcLinearMomentMeasure": "float",
"IfcLinearStiffnessMeasure": "float",
"IfcLinearVelocityMeasure": "float",
"IfcLogical": "bool",
"IfcLuminousFluxMeasure": "float",
"IfcLuminousIntensityDistributionMeasure": "float",
"IfcLuminousIntensityMeasure": "float",
"IfcMagneticFluxDensityMeasure": "float",
"IfcMagneticFluxMeasure": "float",
"IfcMassDensityMeasure": "float",
"IfcMassFlowRateMeasure": "float",
"IfcMassMeasure": "float",
"IfcMassPerLengthMeasure": "float",
"IfcModulusOfElasticityMeasure": "float",
"IfcModulusOfLinearSubgradeReactionMeasure": "float",
"IfcModulusOfRotationalSubgradeReactionMeasure": "float",
"IfcModulusOfSubgradeReactionMeasure": "float",
"IfcMoistureDiffusivityMeasure": "float",
"IfcMolecularWeightMeasure": "float",
"IfcMomentOfInertiaMeasure": "float",
"IfcMonetaryMeasure": "float",
"IfcMonthInYearNumber": "float",
"IfcNonNegativeLengthMeasure": "float",
"IfcNormalisedRatioMeasure": "float",
"IfcNumericMeasure": "float",
"IfcPHMeasure": "float",
"IfcParameterValue": "float",
"IfcPlanarForceMeasure": "float",
"IfcPlaneAngleMeasure": "float",
"IfcPositiveInteger": "integer",
"IfcPositiveLengthMeasure": "float",
"IfcPositivePlaneAngleMeasure": "float",
"IfcPositiveRatioMeasure": "float",
"IfcPowerMeasure": "float",
"IfcPresentableText": "string",
"IfcPressureMeasure": "float",
"IfcRadioActivityMeasure": "float",
"IfcRatioMeasure": "float",
"IfcReal": "float",
"IfcRotationalFrequencyMeasure": "float",
"IfcRotationalMassMeasure": "float",
"IfcRotationalStiffnessMeasure": "float",
"IfcSectionModulusMeasure": "float",
"IfcSectionalAreaIntegralMeasure": "float",
"IfcShearModulusMeasure": "float",
"IfcSolidAngleMeasure": "float",
"IfcSoundPowerLevelMeasure": "float",
"IfcSoundPowerMeasure": "float",
"IfcSoundPressureLevelMeasure": "float",
"IfcSoundPressureMeasure": "float",
"IfcSpecificHeatCapacityMeasure": "float",
"IfcSpecularExponent": "float",
"IfcSpecularRoughness": "float",
"IfcTemperatureGradientMeasure": "float",
"IfcTemperatureRateOfChangeMeasure": "float",
"IfcText": "string",
"IfcTextAlignment": "string",
"IfcTextDecoration": "string",
"IfcTextFontName": "string",
"IfcTextTransformation": "string",
"IfcThermalAdmittanceMeasure": "float",
"IfcThermalConductivityMeasure": "float",
"IfcThermalExpansionCoefficientMeasure": "float",
"IfcThermalResistanceMeasure": "float",
"IfcThermalTransmittanceMeasure": "float",
"IfcThermodynamicTemperatureMeasure": "float",
"IfcTime": "string",
"IfcTimeMeasure": "float",
"IfcTimeStamp": "float",
"IfcTorqueMeasure": "float",
"IfcURIReference": "string",
"IfcVaporPermeabilityMeasure": "float",
"IfcVolumeMeasure": "float",
"IfcVolumetricFlowRateMeasure": "float",
"IfcWarpingConstantMeasure": "float",
"IfcWarpingMomentMeasure": "float",
"aggregateType": "string",
"logical": "string",
"List-IfcCompoundPlaneAngleMeasure": "string"
}
@@ -0,0 +1,15 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('$filename','2019-05-12T12:33:45',('$owner','$email'),('$company'),'IfcOpenShell','IfcOpenShell','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCDIRECTION((1.,0.,0.));
#2=IFCDIRECTION((0.,0.,1.));
#3=IFCCARTESIANPOINT((0.,0.,0.));
#4=IFCAXIS2PLACEMENT3D(#3,#2,#1);
#5=IFCDIRECTION((0.,1.,0.));
#6=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1,139 @@
import xml.etree.ElementTree as ET
import urllib.parse
import pystache
import ntpath
import os
from shutil import copy
from xml.dom import minidom
class SheetBuilder:
def __init__(self):
self.data_dir = None
self.scale = 'NTS'
def create(self, name):
sheet_path = '{}sheets/{}.svg'.format(self.data_dir, name)
root = ET.Element('svg')
root.attrib['xmlns'] = 'http://www.w3.org/2000/svg'
root.attrib['xmlns:xlink'] = 'http://www.w3.org/1999/xlink'
root.attrib['id'] = 'root'
root.attrib['version'] = '1.1'
root.attrib['width'] = '841mm'
root.attrib['height'] = '594mm'
titleblock = ET.SubElement(root, 'image')
titleblock.attrib['xlink:href'] = '../templates/titleblock.svg'
titleblock.attrib['x'] = '0'
titleblock.attrib['y'] = '0'
titleblock.attrib['width'] = '841mm'
titleblock.attrib['height'] = '594mm'
with open(sheet_path, 'w') as f:
f.write(minidom.parseString(ET.tostring(root)).toprettyxml(indent=' '))
def add_view(self, view_name, sheet_name):
sheet_path = '{}sheets/{}.svg'.format(self.data_dir, sheet_name)
view_path = '{}diagrams/{}.svg'.format(self.data_dir, view_name)
ET.register_namespace('', 'http://www.w3.org/2000/svg')
ET.register_namespace('xlink', 'http://www.w3.org/1999/xlink')
sheet_tree = ET.parse(sheet_path)
sheet_root = sheet_tree.getroot()
view_tree = ET.parse(view_path)
view_root = view_tree.getroot()
# The view is placed into a group with a background image element.
# Although the foreground SVG already has a background, it is duplicated
# here to accommodate browsers which do not nest images.
view = ET.SubElement(sheet_root, 'g')
background = ET.SubElement(view, 'image')
background.attrib['xlink:href'] = '../diagrams/{}.png'.format(view_name)
background.attrib['x'] = '0'
background.attrib['y'] = '0'
background.attrib['width'] = view_root.attrib.get('width')
background.attrib['height'] = view_root.attrib.get('height')
foreground = ET.SubElement(view, 'image')
foreground.attrib['xlink:href'] = '../diagrams/{}.svg'.format(view_name)
foreground.attrib['x'] = '0'
foreground.attrib['y'] = '0'
foreground.attrib['width'] = view_root.attrib.get('width')
foreground.attrib['height'] = view_root.attrib.get('height')
title = ET.SubElement(view, 'image')
title.attrib['xlink:href'] = '../templates/view-title.svg'
title.attrib['x'] = '0'
title.attrib['y'] = view_root.attrib.get('height')
sheet_tree.write(sheet_path)
def build(self, sheet_name):
os.makedirs('{}build/{}/'.format(self.data_dir, sheet_name), exist_ok=True)
sheet_path = '{}sheets/{}.svg'.format(self.data_dir, sheet_name)
ET.register_namespace('', 'http://www.w3.org/2000/svg')
ET.register_namespace('xlink', 'http://www.w3.org/1999/xlink')
tree = ET.parse(sheet_path)
root = tree.getroot()
titleblock = root.findall('{http://www.w3.org/2000/svg}image')[0]
root.append(self.parse_embedded_svg(titleblock, {
'number': sheet_name,
'revision': 'A'
}))
root.remove(titleblock)
views = root.findall('{http://www.w3.org/2000/svg}g')
view_number = 1
for view in views:
images = view.findall('{http://www.w3.org/2000/svg}image')
background = images[0]
foreground = images[1]
view_title = images[2]
self.scale = 'NTS'
# Add foreground
view.append(self.parse_embedded_svg(foreground, {}))
# Add background
background_path = '{}sheets/{}'.format(self.data_dir, self.get_href(background))
copy(background_path, '{}build/{}/'.format(self.data_dir, sheet_name))
# Add view title
foreground_path = self.get_href(foreground)
view.append(self.parse_embedded_svg(view_title, {
'no' : view_number,
'name': ntpath.basename(foreground_path)[0:-4],
'scale': self.scale
}))
for image in images:
view.remove(image)
view_number += 1
with open('{}build/{}/{}.svg'.format(self.data_dir, sheet_name, sheet_name), 'wb') as output:
tree.write(output)
def get_href(self, element):
return urllib.parse.unquote(element.attrib.get('{http://www.w3.org/1999/xlink}href'))
def parse_embedded_svg(self, image, data):
group = ET.Element('g')
group.attrib['transform'] = 'translate({},{})'.format(image.attrib.get('x'), image.attrib.get('y'))
svg_path = self.get_href(image)
with open('{}sheets/{}'.format(self.data_dir, svg_path), 'r') as template:
embedded = ET.fromstring(pystache.render(template.read(), data))
self.scale = embedded.attrib.get('data-scale')
images = embedded.findall('{http://www.w3.org/2000/svg}image')
for image in images:
new_href = ntpath.basename(image.attrib.get('{http://www.w3.org/1999/xlink}href'))
image.attrib['{http://www.w3.org/1999/xlink}href'] = new_href
group.append(embedded)
return group
@@ -0,0 +1,856 @@
import bpy
from bpy.types import Panel
class BIM_PT_object(Panel):
bl_label = 'IFC Object'
bl_idname = 'BIM_PT_object'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'object'
@classmethod
def poll(cls, context):
return context.active_object is not None and hasattr(context.active_object, "BIMObjectProperties")
def draw(self, context):
if context.active_object is None:
return
layout = self.layout
props = context.active_object.BIMObjectProperties
layout.label(text="Software Identity:")
row = layout.row()
row.operator('bim.generate_global_id')
layout.label(text="Attributes:")
row = layout.row(align=True)
row.prop(props, 'applicable_attributes', text='')
row.operator('bim.add_attribute')
for index, attribute in enumerate(props.attributes):
row = layout.row(align=True)
row.prop(attribute, 'name', text='')
row.prop(attribute, 'string_value', text='')
row.operator('bim.remove_attribute', icon='X', text='').attribute_index = index
row = layout.row()
row.prop(props, 'attributes')
row = layout.row()
row.prop(props, 'relating_type')
row = layout.row()
row.prop(props, 'relating_structure')
layout.label(text="Property Sets:")
row = layout.row()
row.prop(context.scene.BIMProperties, "pset_name")
row = layout.row()
row.prop(context.scene.BIMProperties, "pset_file")
row = layout.row()
row.operator('bim.add_pset')
for index, pset in enumerate(props.psets):
row = layout.row(align=True)
row.prop(pset, 'name', text='')
row.prop(pset, 'file', text='')
row.operator('bim.remove_pset', icon='X', text='').pset_index = index
row = layout.row()
row.prop(props, 'psets')
row = layout.row(align=True)
row.prop(props, 'override_pset_name', text='')
row.operator('bim.add_override_pset')
for index, pset in enumerate(props.override_psets):
row = layout.row(align=True)
row.prop(pset, 'name', text='')
row.operator('bim.remove_override_pset', icon='X', text='').pset_index = index
for prop in pset.properties:
row = layout.row(align=True)
row.prop(prop, 'name', text='')
row.prop(prop, 'string_value', text='')
layout.label(text="Quantities:")
row = layout.row(align=True)
row.prop(props, 'qto_name', text='')
row.operator('bim.add_qto')
for index, qto in enumerate(props.qtos):
row = layout.row(align=True)
row.prop(qto, 'name', text='')
row.operator('bim.remove_qto', icon='X', text='').index = index
for prop in qto.properties:
row = layout.row(align=True)
row.prop(prop, 'name', text='')
row.prop(prop, 'string_value', text='')
layout.label(text="Documents:")
row = layout.row(align=True)
row.prop(props, 'applicable_documents', text='')
row.operator('bim.add_document')
row = layout.row()
row.operator('bim.fetch_object_passport')
for index, document in enumerate(props.documents):
row = layout.row(align=True)
row.prop(document, 'file', text='')
row.operator('bim.remove_document', icon='X', text='').document_index = index
row = layout.row()
row.prop(props, 'documents')
layout.label(text="Classification:")
for index, classification in enumerate(props.classifications):
row = layout.row(align=True)
row.prop(classification, 'identification', text='')
row.prop(classification, 'name', text='')
row.operator('bim.remove_classification', icon='X', text='').classification_index = index
row = layout.row()
row.prop(props, 'classifications')
row = layout.row()
row.prop(props, 'material_type')
layout.label(text='Structural Boundary Condition:')
row = layout.row()
row.prop(props, 'has_boundary_condition')
if bpy.context.active_object.BIMObjectProperties.has_boundary_condition:
row = layout.row()
row.prop(props.boundary_condition, 'name')
for index, attribute in enumerate(props.boundary_condition.attributes):
row = layout.row(align=True)
row.prop(attribute, 'name', text='')
row.prop(attribute, 'string_value', text='')
row = layout.row()
row.prop(props, 'structural_member_connection')
class BIM_PT_mesh(Panel):
bl_label = 'IFC Representations'
bl_idname = 'BIM_PT_mesh'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'data'
@classmethod
def poll(cls, context):
return context.active_object is not None and context.active_object.type == "MESH" and \
hasattr(context.active_object.data, "BIMMeshProperties")
def draw(self, context):
if not context.active_object.data:
return
layout = self.layout
props = context.active_object.data.BIMMeshProperties
row = layout.row(align=True)
row.prop(bpy.context.scene.BIMProperties, 'available_contexts', text='')
row.prop(bpy.context.scene.BIMProperties, 'available_subcontexts', text='')
row.prop(bpy.context.scene.BIMProperties, 'available_target_views', text='')
row = layout.row()
row.operator('bim.assign_context')
row = layout.row()
row.prop(props, 'is_parametric')
row = layout.row()
row.prop(props, 'is_wireframe')
row = layout.row()
row.prop(props, 'is_swept_solid')
row = layout.row()
row.operator('bim.add_swept_solid')
for index, swept_solid in enumerate(props.swept_solids):
row = layout.row(align=True)
row.prop(swept_solid, 'name', text='')
row.operator('bim.remove_swept_solid', icon='X', text='').index = index
row = layout.row()
sub = row.row(align=True)
sub.operator('bim.assign_swept_solid_outer_curve').index = index
sub.operator('bim.select_swept_solid_outer_curve', icon='RESTRICT_SELECT_OFF', text='').index = index
sub = row.row(align=True)
sub.operator('bim.add_swept_solid_inner_curve').index = index
sub.operator('bim.select_swept_solid_inner_curves', icon='RESTRICT_SELECT_OFF', text='').index = index
row = layout.row(align=True)
row.operator('bim.assign_swept_solid_extrusion').index = index
row.operator('bim.select_swept_solid_extrusion', icon='RESTRICT_SELECT_OFF', text='').index = index
row = layout.row()
row.prop(props, 'swept_solids')
class BIM_PT_material(Panel):
bl_label = 'IFC Materials'
bl_idname = 'BIM_PT_material'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'material'
@classmethod
def poll(cls, context):
return context.active_object is not None and context.active_object.active_material is not None
def draw(self, context):
if not bpy.context.active_object.active_material:
return
props = context.active_object.active_material.BIMMaterialProperties
layout = self.layout
row = layout.row()
row.prop(props, 'is_external')
row = layout.row(align=True)
row.prop(props, 'location')
row.operator('bim.select_external_material_dir', icon="FILE_FOLDER", text="")
row = layout.row()
row.prop(props, 'identification')
row = layout.row()
row.prop(props, 'name')
row = layout.row()
row.operator('bim.fetch_external_material')
layout.label(text="Attributes:")
row = layout.row(align=True)
row.prop(props, 'applicable_attributes', text='')
row.operator('bim.add_material_attribute')
for index, attribute in enumerate(props.attributes):
row = layout.row(align=True)
row.prop(attribute, 'name', text='')
row.prop(attribute, 'string_value', text='')
row.operator('bim.remove_material_attribute', icon='X', text='').attribute_index = index
row = layout.row()
row.prop(props, 'attributes')
layout.label(text="Property Sets:")
row = layout.row(align=True)
row.prop(props, 'available_material_psets', text='')
row.operator('bim.add_material_pset')
for index, pset in enumerate(props.psets):
row = layout.row(align=True)
row.prop(pset, 'name', text='')
row.operator('bim.remove_material_pset', icon='X', text='').pset_index = index
row = layout.row()
row.prop(props, 'psets', text='')
if context.active_object.BIMObjectProperties.material_type == 'IfcMaterialProfileSet':
layout.label(text="Profile Definition:")
row = layout.row()
row.prop(props, 'profile_def')
for index, attribute in enumerate(props.profile_attributes):
row = layout.row(align=True)
row.prop(attribute, 'name', text='')
row.prop(attribute, 'string_value', text='')
class BIM_PT_gis(Panel):
bl_label = 'IFC Georeferencing'
bl_idname = "BIM_PT_gis"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
layout.row().prop(scene.BIMProperties, 'has_georeferencing')
layout.label(text="Map Conversion:")
layout.row().prop(scene.MapConversion, 'eastings')
layout.row().prop(scene.MapConversion, 'northings')
layout.row().prop(scene.MapConversion, 'orthogonal_height')
layout.row().prop(scene.MapConversion, 'x_axis_abscissa')
layout.row().prop(scene.MapConversion, 'x_axis_ordinate')
layout.row().prop(scene.MapConversion, 'scale')
layout.label(text="Target CRS:")
layout.row().prop(scene.TargetCRS, 'name')
layout.row().prop(scene.TargetCRS, 'description')
layout.row().prop(scene.TargetCRS, 'geodetic_datum')
layout.row().prop(scene.TargetCRS, 'vertical_datum')
layout.row().prop(scene.TargetCRS, 'map_projection')
layout.row().prop(scene.TargetCRS, 'map_zone')
layout.row().prop(scene.TargetCRS, 'map_unit')
class BIM_PT_documentation(Panel):
bl_label = "Diagrammatic Documentation"
bl_idname = "BIM_PT_documentation"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'output'
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = bpy.context.scene.DocProperties
row = layout.row()
row.operator('bim.set_view_preset_1')
row = layout.row()
row.prop(props, 'view_name')
row.operator('bim.create_view', icon='ADD', text='')
row = layout.row()
row.prop(props, 'sheet_name')
row.operator('bim.create_sheet', icon='ADD', text='')
row = layout.row()
row.prop(props, 'available_views')
row.operator('bim.open_view', icon='URL', text='')
row.operator('bim.activate_view', icon='SCENE', text='')
row = layout.row()
row.prop(props, 'available_sheets')
row.operator('bim.open_sheet', icon='URL', text='')
row.operator('bim.open_compiled_sheet', icon='OUTPUT', text='')
row = layout.row()
row.operator('bim.add_view_to_sheet')
row = layout.row()
row.operator('bim.create_sheets')
row = layout.row()
row.operator('bim.generate_digital_twin')
class BIM_PT_camera(Panel):
bl_label = "Diagrams and Documentation"
bl_idname = "BIM_PT_camera"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'data'
@classmethod
def poll(cls, context):
engine = context.engine
return context.camera and \
hasattr(context.active_object.data, "BIMCameraProperties")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
dprops = bpy.context.scene.DocProperties
props = context.active_object.data.BIMCameraProperties
row = layout.row()
row.prop(dprops, 'should_recut')
row = layout.row()
row.prop(props, 'is_nts')
row = layout.row(align=True)
row.prop(props, 'diagram_scale', text='')
row.operator('bim.cut_section')
class BIM_PT_owner(Panel):
bl_label = "Owner History"
bl_idname = "BIM_PT_owner"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
props = scene.BIMProperties
row = layout.row()
row.prop(props, 'person')
row = layout.row()
row.prop(props, 'organisation')
class BIM_PT_context(Panel):
bl_label = "Geometric Representation Contexts"
bl_idname = "BIM_PT_context"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
scene = context.scene
props = scene.BIMProperties
for context in ['model', 'plan']:
row = layout.row(align=True)
row.prop(props, f'has_{context}_context')
if not getattr(props, f'has_{context}_context'):
continue
layout.label(text="Geometric Representation Subcontexts:")
row = layout.row(align=True)
row.prop(props, 'available_subcontexts', text='')
row.prop(props, 'available_target_views', text='')
row.operator('bim.add_subcontext', icon='ADD', text='').context = context
for subcontext_index, subcontext in enumerate(getattr(props, '{}_subcontexts'.format(context))):
row = layout.row(align=True)
row.prop(subcontext, 'name', text='')
row.prop(subcontext, 'target_view', text='')
row.operator('bim.remove_subcontext', icon='X', text='').indexes = '{}-{}'.format(context, subcontext_index)
class BIM_PT_bim(Panel):
bl_label = "Building Information Modeling"
bl_idname = "BIM_PT_bim"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
bim_properties = scene.BIMProperties
layout.label(text="System Setup:")
row = layout.row()
row.operator('bim.quick_project_setup')
row = layout.row(align=True)
row.prop(bim_properties, "schema_dir")
row.operator("bim.select_schema_dir", icon="FILE_FOLDER", text="")
row = layout.row(align=True)
row.prop(bim_properties, "data_dir")
row.operator("bim.select_data_dir", icon="FILE_FOLDER", text="")
row = layout.row(align=True)
row.prop(bim_properties, 'ifc_file')
row.operator('bim.validate_ifc_file', icon='CHECKMARK', text='')
row.operator('bim.select_ifc_file', icon='FILE_FOLDER', text='')
layout.label(text="IFC Categorisation:")
row = layout.row()
row.prop(bim_properties, "ifc_product")
row = layout.row()
row.prop(bim_properties, "ifc_class")
if bim_properties.ifc_predefined_type:
row = layout.row()
row.prop(bim_properties, "ifc_predefined_type")
if bim_properties.ifc_predefined_type == 'USERDEFINED':
row = layout.row()
row.prop(bim_properties, "ifc_userdefined_type")
row = layout.row()
row.operator("bim.assign_class")
row = layout.row(align=True)
row.operator("bim.select_class")
row.operator("bim.select_type")
layout.label(text="Property Sets:")
row = layout.row()
row.prop(bim_properties, "pset_name")
row = layout.row()
row.prop(bim_properties, "pset_file")
row = layout.row(align=True)
row.operator("bim.assign_pset")
row.operator("bim.unassign_pset")
layout.label(text="Aggregates:")
row = layout.row()
row.prop(bim_properties, "aggregate_class")
row = layout.row()
row.prop(bim_properties, "aggregate_name")
row = layout.row(align=True)
row.operator("bim.create_aggregate")
row.operator("bim.explode_aggregate")
row = layout.row(align=True)
row.operator("bim.edit_aggregate")
row.operator("bim.save_aggregate")
layout.label(text="Classifications:")
row = layout.row()
row.prop(bim_properties, "classification")
row = layout.row()
row.prop(bim_properties, "reference")
row = layout.row(align=True)
row.operator("bim.assign_classification")
row.operator("bim.unassign_classification")
class BIM_PT_search(Panel):
bl_label = "BIM Search"
bl_idname = "BIM_PT_search"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
scene = context.scene
props = scene.BIMProperties
row = layout.row()
row.prop(props, 'search_regex')
row = layout.row()
row.prop(props, 'search_ignorecase')
layout.label(text="Global ID:")
row = layout.row(align=True)
row.prop(props, 'global_id', text='')
row.operator('bim.select_global_id', text='', icon='VIEWZOOM')
layout.label(text="Attribute:")
row = layout.row(align=True)
row.prop(props, 'search_attribute_name', text='')
row.prop(props, 'search_attribute_value', text='')
row.operator('bim.select_attribute', text='', icon='VIEWZOOM')
row.operator('bim.colour_by_attribute', text='', icon='BRUSH_DATA')
layout.label(text="Pset:")
row = layout.row(align=True)
row.prop(props, 'search_pset_name', text='')
row.prop(props, 'search_prop_name', text='')
row.prop(props, 'search_pset_value', text='')
row.operator('bim.select_pset', text='', icon='VIEWZOOM')
row.operator('bim.colour_by_pset', text='', icon='BRUSH_DATA')
class BIM_PT_bcf(Panel):
bl_label = "BIM Collaboration Format"
bl_idname = "BIM_PT_bcf"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
props = bpy.context.scene.BCFProperties
row = layout.row(align=True)
row.prop(props, "bcf_file")
row.operator("bim.select_bcf_file", icon="FILE_FOLDER", text="")
row = layout.row()
row.operator("bim.get_bcf_topics")
props = bpy.context.scene.BCFProperties
layout.template_list('BIM_UL_topics', '', props, 'topics', props, 'active_topic_index')
row = layout.row()
row.prop(props, 'topic_description', text='')
row = layout.row()
row.prop(props, 'viewpoints')
row.operator('bim.activate_bcf_viewpoint', icon='SCENE', text='')
row = layout.row()
row.prop(props, 'topic_type', text='Type')
row = layout.row()
row.prop(props, 'topic_status', text='Status')
row = layout.row()
row.prop(props, 'topic_priority', text='Priority')
row = layout.row()
row.prop(props, 'topic_stage', text='Stage')
row = layout.row()
row.prop(props, 'topic_creation_date', text='Date')
row = layout.row()
row.prop(props, 'topic_creation_author', text='Author')
row = layout.row()
row.prop(props, 'topic_modified_date', text='Modified On')
row = layout.row()
row.prop(props, 'topic_modified_author', text='Modified By')
row = layout.row()
row.prop(props, 'topic_assigned_to', text='Assigned To')
row = layout.row()
row.prop(props, 'topic_due_date', text='Due Date')
layout.label(text="Header Files:")
for index, f in enumerate(props.topic_files):
row = layout.row()
row.prop(f, 'name', text='File {} Name'.format(index + 1))
row = layout.row()
row.prop(f, 'reference', text='File {} URI'.format(index + 1))
if f.is_external:
row.operator('bim.open_bcf_file_reference', icon='URL', text='').data = index
else:
row.operator('bim.open_bcf_file_reference', icon='FILE_FOLDER', text='').data = '{}/{}'.format(
props.topic_guid, index)
row = layout.row()
row.prop(f, 'date', text='File {} Date'.format(index + 1))
row = layout.row()
row.prop(f, 'ifc_project', text='File {} Project'.format(index + 1))
row = layout.row()
row.prop(f, 'ifc_spatial', text='File {} Spatial'.format(index + 1))
layout.label(text="Reference Links:")
for index, label in enumerate(props.topic_links):
row = layout.row()
row.prop(label, 'name', text='Link {}'.format(index + 1))
row.operator('bim.open_bcf_reference_link', icon='URL', text='').index = index
layout.label(text="Labels:")
for index, label in enumerate(props.topic_labels):
row = layout.row(align=True)
row.prop(label, 'name', text='')
layout.label(text="BIM Snippet:")
if props.topic_has_snippet:
row = layout.row(align=True)
row.prop(props, 'topic_snippet_type')
if props.topic_snippet_schema:
row.operator('bim.open_bcf_bim_snippet_schema', icon='URL', text='')
row = layout.row(align=True)
row.prop(props, 'topic_snippet_reference')
if props.topic_snippet_is_external:
row.operator('bim.open_bcf_bim_snippet_reference', icon='URL', text='')
else:
row.operator('bim.open_bcf_bim_snippet_reference', icon='FILE_FOLDER', text='').topic_guid = props.topic_guid
layout.label(text="Document References:")
for index, doc in enumerate(props.topic_document_references):
row = layout.row(align=True)
row.prop(doc, 'name', text=f'File {index+1} URI')
if doc.is_external:
row.operator('bim.open_bcf_document_reference', icon='URL', text='').data = '{}/{}'.format(
props.topic_guid, index)
else:
row.operator('bim.open_bcf_document_reference', icon='FILE_FOLDER', text='').data = '{}/{}'.format(
props.topic_guid, index)
row = layout.row(align=True)
row.prop(doc, 'description', text=f'File {index+1} Description:')
layout.label(text="Related Topics:")
for topic in props.topic_related_topics:
row = layout.row(align=True)
row.operator('bim.view_bcf_topic', text=topic.name).topic_guid = topic.guid
class BIM_PT_qa(Panel):
bl_label = "BIMTester Quality Auditing"
bl_idname = "BIM_PT_qa"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
bim_properties = bpy.context.scene.BIMProperties
layout.label(text="Gherkin Setup:")
row = layout.row(align=True)
row.prop(bim_properties, "features_dir")
row.operator("bim.select_features_dir", icon="FILE_FOLDER", text="")
if bim_properties.features_dir:
row = layout.row(align=True)
row.prop(bim_properties, "features_file")
row = layout.row(align=True)
row.prop(bim_properties, "scenario")
layout.label(text="Quality Auditing:")
row = layout.row()
row.prop(bim_properties, "qa_reject_element_reason")
row = layout.row()
row.operator("bim.reject_element")
row = layout.row(align=True)
row.operator("bim.colour_by_class")
row.operator("bim.reset_object_colours")
row = layout.row()
row.prop(bim_properties, "audit_ifc_class")
row = layout.row(align=True)
row.operator("bim.approve_class")
row.operator("bim.reject_class")
row = layout.row()
row.operator("bim.select_audited")
class BIM_PT_library(Panel):
bl_label = "BIM Server Library"
bl_idname = "BIM_PT_library"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
bim_properties = scene.BIMProperties
layout.row().prop(scene.BIMProperties, 'has_library')
layout.label(text="Project Library:")
layout.row().prop(scene.BIMLibrary, 'location')
layout.row().operator("bim.fetch_library_information")
layout.row().prop(scene.BIMLibrary, 'name')
layout.row().prop(scene.BIMLibrary, 'version')
layout.row().prop(scene.BIMLibrary, 'version_date')
layout.row().prop(scene.BIMLibrary, 'description')
class BIM_PT_diff(Panel):
bl_label = "IFC Diff"
bl_idname = "BIM_PT_diff"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
bim_properties = scene.BIMProperties
layout.label(text="IFC Diff Setup:")
row = layout.row(align=True)
row.prop(bim_properties, "diff_json_file")
row.operator("bim.select_diff_json_file", icon="FILE_FOLDER", text="")
row = layout.row(align=True)
row.prop(bim_properties, "diff_old_file")
row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="")
row = layout.row(align=True)
row.prop(bim_properties, "diff_new_file")
row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="")
row = layout.row()
row.operator('bim.execute_ifc_diff')
class BIM_PT_mvd(Panel):
bl_label = "Model View Definitions"
bl_idname = "BIM_PT_mvd"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
scene = context.scene
bim_properties = scene.BIMProperties
layout.label(text='Custom MVD:')
row = layout.row()
row.prop(bim_properties, 'export_has_representations')
row = layout.row()
row.prop(bim_properties, 'import_should_import_curves')
row = layout.row()
row.prop(bim_properties, 'import_should_import_opening_elements')
row = layout.row()
row.prop(bim_properties, 'import_should_import_spaces')
layout.label(text='Experimental Modes:')
row = layout.row()
row.prop(bim_properties, 'import_should_use_legacy')
row = layout.row()
row.prop(bim_properties, 'import_should_use_cpu_multiprocessing')
layout.label(text='Simplifications:')
row = layout.row()
row.prop(bim_properties, 'import_should_import_aggregates')
row = layout.row()
row.prop(bim_properties, 'import_should_merge_by_class')
row = layout.row()
row.prop(bim_properties, 'import_should_merge_by_material')
row = layout.row()
row.prop(bim_properties, 'import_should_clean_mesh')
layout.label(text='Vendor Workarounds:')
row = layout.row()
row.prop(bim_properties, 'import_should_auto_set_workarounds')
layout.label(text='Tekla Workarounds:')
row = layout.row()
row.prop(bim_properties, 'import_should_ignore_site_coordinates')
layout.label(text='12D Workarounds:')
row = layout.row()
row.prop(bim_properties, 'import_should_reset_absolute_coordinates')
layout.label(text='Revit Workarounds:')
row = layout.row()
row.prop(bim_properties, 'export_should_export_all_materials_as_styled_items')
row = layout.row()
row.prop(bim_properties, 'export_should_use_presentation_style_assignment')
row = layout.row()
row.prop(bim_properties, 'import_should_ignore_site_coordinates')
row = layout.row()
row.prop(bim_properties, 'import_should_ignore_building_coordinates')
row = layout.row()
row.prop(bim_properties, 'import_should_treat_styled_item_as_material')
class BIM_UL_topics(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
if item:
layout.prop(item, 'name', text='', emboss=False)
else:
layout.label(text="", translate=False)
class BIM_ADDON_preferences(bpy.types.AddonPreferences):
bl_idname = __package__
def draw(self, context):
layout = self.layout
row = layout.row()
row.operator('bim.open_upstream', text='Visit Homepage').page = 'home'
row.operator('bim.open_upstream', text='Visit Documentation').page = 'docs'
row = layout.row()
row.operator('bim.open_upstream', text='Visit Wiki').page = 'wiki'
row.operator('bim.open_upstream', text='Visit Community').page = 'community'
row = layout.row()
row.operator('bim.uninstall')