First Commit
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
## python-mvdxml
|
||||
|
||||
A mvdXML checker and w3c SPARQL converter, as an IfcOpenShell submodule or stand-alone.
|
||||
|
||||
WARNING: While this repository has many useful building blocks to build software around mvdXML and IFC, there are many mvdXML dialects and not all variants are likely to be fully supported.
|
||||
|
||||
### Quickstart
|
||||
|
||||
#### Extraction
|
||||
|
||||
```python
|
||||
import ifcopenshell
|
||||
from ifcopenshell.mvd import mvd
|
||||
|
||||
mvd_concept = mvd.open_mvd("examples/wall_extraction.mvdxml")
|
||||
file = ifcopenshell.open("Duplex_A_20110505.ifc")
|
||||
|
||||
all_data = mvd.get_data(mvd_concept, file, spreadsheet_export=True)
|
||||
|
||||
non_respecting_entities = mvd.get_non_respecting_entities(file, all_data[1])
|
||||
respecting_entities = mvd.get_respecting_entities(file, all_data[1])
|
||||
|
||||
|
||||
```
|
||||
|
||||
```python
|
||||
# Create a new file
|
||||
new_file = ifcopenshell.file(schema=file.schema)
|
||||
proj = file.by_type("IfcProject")[0]
|
||||
new_file.add(proj)
|
||||
|
||||
for e in respecting_entities:
|
||||
new_file.add(e)
|
||||
|
||||
new_file.write("new_file.ifc")
|
||||
```
|
||||
|
||||
```python
|
||||
# Visualize results
|
||||
mvd.visualize(file, non_respecting_entities)
|
||||
```
|
||||
|
||||
##### Validation
|
||||
|
||||
~~~py
|
||||
import ifcopenshell
|
||||
|
||||
from ifcopenshell.mvd import mvd
|
||||
from colorama import Fore
|
||||
from colorama import Style
|
||||
|
||||
concept_roots = list(ifcopenshell.mvd.concept_root.parse(MVDXML_FILENAME))
|
||||
file = ifcopenshell.open(IFC_FILENAME)
|
||||
|
||||
tt = 0 # total number of tests
|
||||
ts = 0 # total number of successful tests
|
||||
|
||||
for concept_root in concept_roots:
|
||||
print("ConceptRoot: ", concept_root.entity)
|
||||
for concept in concept_root.concepts():
|
||||
tt = tt + 1
|
||||
print("Concept: ", concept.name)
|
||||
try:
|
||||
|
||||
if len(concept.template().rules) > 1:
|
||||
attribute_rules = []
|
||||
for rule in concept.template().rules:
|
||||
attribute_rules.append(rule)
|
||||
rules_root = ifcopenshell.mvd.rule("EntityRule", concept_root.entity, attribute_rules)
|
||||
else:
|
||||
rules_root = concept.template().rules[0]
|
||||
ts = ts + 1
|
||||
finst = 0 #failed instances
|
||||
|
||||
for inst in file.by_type(concept_root.entity):
|
||||
try:
|
||||
data = mvd.extract_data(rules_root, inst)
|
||||
valid, output = mvd.validate_data(concept, data)
|
||||
if not valid:
|
||||
finst = finst + 1
|
||||
print("[VALID]" if valid else Fore.RED +"[failure]"+Style.RESET_ALL, inst)
|
||||
print(output)
|
||||
except Exception as e:
|
||||
print(Fore.RED+"EXCEPTION: ", e, Style.RESET_ALL,inst)
|
||||
print ()
|
||||
print (int(finst), "out of", int(len(file.by_type(concept_root.entity))), "instances failed the check")
|
||||
print ("---------------------------------")
|
||||
except Exception as e:
|
||||
print("EXCEPTION: "+Fore.RED,e,Style.RESET_ALL)
|
||||
print("---------------------------------")
|
||||
print("---------------------------------")
|
||||
print("---------------------------------")
|
||||
|
||||
tf = tt-ts # total number of failed tests
|
||||
|
||||
print ("\nRESULTS OVERVIEW")
|
||||
print ("Total number of tests: ",tt)
|
||||
print ("Total number of executed tests: ", ts)
|
||||
print ("Total number of failed tests: ", tf)
|
||||
~~~
|
||||
@@ -0,0 +1,199 @@
|
||||
from . import mvdxml_expression
|
||||
|
||||
from xml.dom.minidom import parse, Element
|
||||
|
||||
class rule(object):
|
||||
"""
|
||||
A class for representing an mvdXML EntityRule or AttributeRule
|
||||
"""
|
||||
|
||||
def __init__(self, tag, attribute, nodes, bind=None, optional=False):
|
||||
self.tag, self.attribute, self.nodes, self.bind = tag, attribute, nodes, bind
|
||||
self.optional = optional
|
||||
|
||||
def to_string(self, indent=0):
|
||||
# return "%s%s%s[%s](%s%s)%s" % ("\n" if indent else "", " "*indent, self.tag, self.attribute, "".join(n.to_string(indent+2) for n in self.nodes), ("\n" + " "*indent) if len(self.nodes) else "", (" -> %s" % self.bind) if self.bind else "")
|
||||
return "<%s %s%s>" % (self.tag, f"{self.bind}=" if self.bind else "", self.attribute)
|
||||
|
||||
def __repr__(self):
|
||||
return self.to_string()
|
||||
|
||||
class template(object):
|
||||
"""
|
||||
Representation of an mvdXML template
|
||||
"""
|
||||
|
||||
def __init__(self, concept, root, constraints=None, rules=None, parent=None):
|
||||
self.concept, self.root, self.constraints, self.parent = concept, root, (constraints or []), parent
|
||||
self.rules = rules or []
|
||||
self.entity = str(root.attributes['applicableEntity'].value)
|
||||
try:
|
||||
self.name = root.attributes['name'].value
|
||||
except:
|
||||
self.name = None
|
||||
|
||||
def bind(self, constraints):
|
||||
return template(self.concept, self.root, constraints, self.rules)
|
||||
|
||||
def parse(self, visited=None):
|
||||
for rules in self.root.getElementsByTagNameNS("*", "Rules"):
|
||||
for r in rules.childNodes:
|
||||
if not isinstance(r, Element): continue
|
||||
self.rules.append(self.parse_rule(r, visited=visited))
|
||||
|
||||
def traverse(self, fn, root=None, with_parents=False):
|
||||
def visit(n, p=root, ps=[root]):
|
||||
if with_parents:
|
||||
close = fn(rule=n, parents=ps)
|
||||
else:
|
||||
close = fn(rule=n, parent=p)
|
||||
|
||||
for s in n.nodes:
|
||||
visit(s, n, ps + [n])
|
||||
|
||||
if close:
|
||||
close()
|
||||
|
||||
for r in self.rules:
|
||||
visit(r)
|
||||
|
||||
def parse_rule(self, root, visited=None):
|
||||
def visit(node, prefix="", visited=None, parent=None):
|
||||
r = None
|
||||
n = node
|
||||
nm = None
|
||||
p = prefix
|
||||
optional = False
|
||||
visited = set() if visited is None else visited
|
||||
|
||||
if node.localName == "AttributeRule":
|
||||
r = node.attributes["AttributeName"].value
|
||||
try:
|
||||
nm = node.attributes["RuleID"].value
|
||||
except:
|
||||
# without binding, it's wrapped in a SPARQL OPTIONAL {} clause
|
||||
# Aim is to insert this clause once as high in the stack as possible
|
||||
# All topmost attribute rules are optional anyway as in the binding requirements on existence is specified
|
||||
|
||||
def child_has_ruleid_or_prefix(node):
|
||||
if type(node).__name__ == "Element":
|
||||
if "RuleID" in node.attributes or "IdPrefix" in node.attributes:
|
||||
return True
|
||||
for n in node.childNodes:
|
||||
if child_has_ruleid_or_prefix(n): return True
|
||||
|
||||
optional = node.parentNode.localName == "Rules" or not child_has_ruleid_or_prefix(node)
|
||||
elif node.localName == "EntityRule":
|
||||
r = node.attributes["EntityName"].value
|
||||
elif node.localName == "Template":
|
||||
ref = node.attributes['ref'].value
|
||||
# we break infinite recursion using this set
|
||||
if ref not in visited:
|
||||
n = self.concept.template(ref, visited=visited | {ref}).root
|
||||
try:
|
||||
p = p + node.attributes["IdPrefix"].value
|
||||
except:
|
||||
pass
|
||||
elif node.localName == "Constraint":
|
||||
r = mvdxml_expression.parse(node.attributes["Expression"].value)
|
||||
elif node.localName == "EntityRules": pass
|
||||
elif node.localName == "AttributeRules": pass
|
||||
elif node.localName == "Rules": pass
|
||||
elif node.localName == "Constraints": pass
|
||||
elif node.localName == "References": pass
|
||||
elif node.localName == "Definitions": return
|
||||
elif node.localName == "SubTemplates": return # @todo perhaps just traverse them?
|
||||
else:
|
||||
raise ValueError(node.localName)
|
||||
|
||||
def _(n):
|
||||
for subnode in n.childNodes:
|
||||
if not isinstance(subnode, Element): continue
|
||||
for x in visit(subnode, p, visited=visited): yield x
|
||||
|
||||
if r:
|
||||
R = rule(node.localName, r, list(_(n)), (p + nm) if nm else nm, optional=optional)
|
||||
for rr in R.nodes:
|
||||
rr.parent = R
|
||||
yield R
|
||||
else:
|
||||
for subnode in n.childNodes:
|
||||
if not isinstance(subnode, Element): continue
|
||||
for x in visit(subnode, p, visited=visited): yield x
|
||||
|
||||
return list(visit(root, visited=visited))[0]
|
||||
|
||||
class concept_or_applicability(object):
|
||||
"""
|
||||
Representation of either a mvdXML Concept or the Applicability node. Basically a structure
|
||||
for the hierarchical TemplateRule
|
||||
"""
|
||||
|
||||
def __init__(self, root, c):
|
||||
self.root = root
|
||||
self.concept_node = c
|
||||
try:
|
||||
self.name = c.attributes["name"].value
|
||||
except:
|
||||
# probably applicability and not concept
|
||||
self.name = "Applicability"
|
||||
|
||||
def template(self, id=None, visited=None):
|
||||
if id is None:
|
||||
id = self.concept_node.getElementsByTagNameNS("*","Template")[0].attributes['ref'].value
|
||||
|
||||
for node in self.root.dom.getElementsByTagNameNS('*',"ConceptTemplate"):
|
||||
if node.attributes["uuid"].value == id:
|
||||
t = template(self, node)
|
||||
t.parse(visited=visited)
|
||||
t_with_rules = t.bind(self.rules())
|
||||
return t_with_rules
|
||||
|
||||
def rules(self):
|
||||
# Get the top most TemplateRule and traverse
|
||||
try:
|
||||
rules = self.concept_node.getElementsByTagNameNS("*","TemplateRules")[0]
|
||||
except:
|
||||
return []
|
||||
|
||||
def visit(rules):
|
||||
def _():
|
||||
for i, r in enumerate([c for c in rules.childNodes if isinstance(c, Element)]):
|
||||
if i:
|
||||
yield rules.attributes["operator"].value
|
||||
if r.localName == "TemplateRules":
|
||||
yield visit(r)
|
||||
elif r.localName == "TemplateRule":
|
||||
yield mvdxml_expression.parse(r.attributes["Parameters"].value)
|
||||
else:
|
||||
raise Exception()
|
||||
|
||||
return list(_())
|
||||
|
||||
return visit(rules)
|
||||
|
||||
class concept_root(object):
|
||||
def __init__(self, dom, root):
|
||||
self.dom, self.root = dom, root
|
||||
self.name = root.attributes['name'].value
|
||||
self.entity = str(root.attributes['applicableRootEntity'].value)
|
||||
|
||||
def applicability(self):
|
||||
return concept_or_applicability(self, self.root.getElementsByTagNameNS("*","Applicability")[0])
|
||||
|
||||
def concepts(self):
|
||||
for c in self.root.getElementsByTagNameNS("*","Concept"):
|
||||
yield concept_or_applicability(self, c)
|
||||
|
||||
@staticmethod
|
||||
def parse(fn):
|
||||
dom = parse(fn)
|
||||
if len(dom.getElementsByTagNameNS("*","ConceptRoot")):
|
||||
for root in dom.getElementsByTagNameNS("*","ConceptRoot"):
|
||||
CR = concept_root(dom, root)
|
||||
yield CR
|
||||
else:
|
||||
for templ in dom.getElementsByTagNameNS("*","ConceptTemplate"):
|
||||
t = template(None, templ)
|
||||
t.parse()
|
||||
yield t
|
||||
@@ -0,0 +1,35 @@
|
||||
from __future__ import print_function
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from . import concept_root
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
mvdfn = sys.argv[1]
|
||||
for mvd in concept_root.parse(mvdfn):
|
||||
|
||||
def dump(rule, parents):
|
||||
print(" " * len(parents), rule.tag, rule.attribute)
|
||||
|
||||
for c in mvd.concepts():
|
||||
print(c.name)
|
||||
print()
|
||||
|
||||
t = c.template()
|
||||
print("RootEntity", t.entity)
|
||||
t.traverse(dump, with_parents=True)
|
||||
print(" ".join(map(str, t.constraints)))
|
||||
|
||||
print()
|
||||
|
||||
elif len(sys.argv) == 3:
|
||||
from . import sparql
|
||||
mvdfn,ttlfn = sys.argv[1:]
|
||||
sparql.derive_prefix(ttlfn)
|
||||
ttlfn = sparql.infer_subtypes(ttlfn)
|
||||
for mvd in concept_root.parse(mvdfn):
|
||||
sparql.executor.run(mvd, mvdfn, ttlfn)
|
||||
|
||||
else:
|
||||
print(sys.executable, "ifcopenshell.mvd", "<.mvdxml>")
|
||||
print(sys.executable, "ifcopenshell.mvd", "<.mvdxml>", "<.ifc>")
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,489 @@
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
|
||||
import itertools
|
||||
import os
|
||||
|
||||
import xlsxwriter
|
||||
import csv
|
||||
|
||||
|
||||
def is_applicability(concept):
|
||||
"""
|
||||
Check whether the Concept created has a filtering purpose.
|
||||
Actually, MvdXML has a specific Applicability node.
|
||||
|
||||
:param concept: mvdXML Concept object
|
||||
"""
|
||||
return concept.name.startswith("AP")
|
||||
|
||||
|
||||
def merge_dictionaries(dicts):
|
||||
d = {}
|
||||
for e in dicts:
|
||||
d.update(e)
|
||||
return d
|
||||
|
||||
|
||||
def extract_data(mvd_node, ifc_data):
|
||||
"""
|
||||
Recursively traverses mvdXML Concept tree structure.
|
||||
This tree is made of different mvdXML Rule nodes: AttributesRule
|
||||
and EntityRule.
|
||||
|
||||
:param mvd_node: an mvdXML Concept
|
||||
:param ifc_data: an IFC instance or an IFC value
|
||||
|
||||
|
||||
"""
|
||||
to_combine = []
|
||||
return_value = []
|
||||
|
||||
if len(mvd_node.nodes) == 0:
|
||||
if mvd_node.tag == "AttributeRule":
|
||||
try:
|
||||
values_from_attribute = getattr(ifc_data, mvd_node.attribute)
|
||||
return [{mvd_node: values_from_attribute}]
|
||||
except:
|
||||
return [{mvd_node: "Invalid Attribute"}]
|
||||
|
||||
else:
|
||||
return [{mvd_node: ifc_data}]
|
||||
|
||||
if mvd_node.tag == 'AttributeRule':
|
||||
data_from_attribute = []
|
||||
try:
|
||||
values_from_attribute = getattr(ifc_data, mvd_node.attribute)
|
||||
if values_from_attribute is None:
|
||||
return [{mvd_node:"Nonexistent value"}]
|
||||
|
||||
except:
|
||||
return [{mvd_node:"Invalid attribute rule"}]
|
||||
|
||||
|
||||
if isinstance(values_from_attribute, (list, tuple)):
|
||||
if len(values_from_attribute) == 0:
|
||||
return [{mvd_node: 'empty data structure'}]
|
||||
data_from_attribute.extend(values_from_attribute)
|
||||
|
||||
else:
|
||||
data_from_attribute.append(values_from_attribute)
|
||||
|
||||
for child in mvd_node.nodes:
|
||||
for data in data_from_attribute:
|
||||
child_values = extract_data(child, data)
|
||||
if isinstance(child_values, (list, tuple)):
|
||||
return_value.extend(child_values)
|
||||
else:
|
||||
return_value.append(child_values)
|
||||
return return_value
|
||||
|
||||
elif mvd_node.tag == 'EntityRule':
|
||||
# Avoid things like Quantities on Psets
|
||||
if len(mvd_node.nodes):
|
||||
if isinstance(ifc_data, ifcopenshell.entity_instance) and not ifc_data.is_a(mvd_node.attribute):
|
||||
return []
|
||||
|
||||
for child in mvd_node.nodes:
|
||||
if child.tag == "Constraint":
|
||||
on_node = child.attribute[0].c
|
||||
on_node = on_node.replace("'", "")
|
||||
if isinstance(ifc_data, ifcopenshell.entity_instance):
|
||||
ifc_type = type(ifc_data[0])
|
||||
typed_node = (ifc_type)(on_node)
|
||||
|
||||
if ifc_data[0] == typed_node:
|
||||
return [{mvd_node: ifc_data}]
|
||||
|
||||
elif ifc_data == on_node:
|
||||
return [{mvd_node: ifc_data}]
|
||||
else:
|
||||
to_combine.append(extract_data(child, ifc_data))
|
||||
|
||||
if len(to_combine):
|
||||
return_value = list(map(merge_dictionaries, itertools.product(*to_combine)))
|
||||
|
||||
return return_value
|
||||
|
||||
|
||||
def open_mvd(filename):
|
||||
"""
|
||||
Open an mvdXML file.
|
||||
|
||||
:param filename: Path of the mvdXML file.
|
||||
:return: mvdXML Concept instance.
|
||||
"""
|
||||
my_concept_object = list(ifcopenshell.mvd.concept_root.parse(filename))[0]
|
||||
return my_concept_object
|
||||
|
||||
|
||||
def format_data_from_nodes(recurse_output):
|
||||
"""
|
||||
Enable to format data collected such that the value to be exported is extracted.
|
||||
|
||||
:param recurse_output: Data extracted from the recursive function
|
||||
|
||||
"""
|
||||
if len(recurse_output) > 1:
|
||||
output = []
|
||||
for resulting_dict in recurse_output:
|
||||
intermediate_storing = []
|
||||
for value in resulting_dict.values():
|
||||
intermediate_storing.append(value)
|
||||
output.extend(intermediate_storing)
|
||||
return output
|
||||
|
||||
elif len(recurse_output) == 1:
|
||||
return_list = []
|
||||
intermediate_list = list(recurse_output[0].values())
|
||||
if len(intermediate_list) > 1:
|
||||
returned_value = intermediate_list
|
||||
for element in intermediate_list:
|
||||
# In case of a property that comes with all its path
|
||||
# (like ['PSet_WallCommon, 'IsExternal', IfcBoolean(.F.)
|
||||
# return only the list element which is not of string type
|
||||
# todo: check above condition with ifcopenshell type
|
||||
if not isinstance(element, str):
|
||||
returned_value = element
|
||||
if returned_value != intermediate_list:
|
||||
return returned_value
|
||||
else:
|
||||
return intermediate_list
|
||||
else:
|
||||
return intermediate_list[0]
|
||||
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def get_data_from_mvd(entities, tree, filtering=False):
|
||||
"""
|
||||
Apply the recursive function on the entities to return
|
||||
the values extracted.
|
||||
|
||||
:param entities: IFC instances to be processed.
|
||||
:param tree: mvdXML Concept instance tree root.
|
||||
:param filtering: Indicates whether the mvdXML tree is an applicability.
|
||||
|
||||
"""
|
||||
filtered_entities = []
|
||||
extracted_entities_data = {}
|
||||
|
||||
for entity in entities:
|
||||
entity_id = entity.GlobalId
|
||||
combinations = extract_data(tree, entity)
|
||||
desired_results = []
|
||||
|
||||
for dictionary in combinations:
|
||||
desired_results.append(dictionary)
|
||||
|
||||
output = format_data_from_nodes(desired_results)
|
||||
|
||||
if filtering:
|
||||
if len(output):
|
||||
extracted_entities_data[entity_id] = output
|
||||
else:
|
||||
extracted_entities_data[entity_id] = output
|
||||
|
||||
return extracted_entities_data
|
||||
|
||||
|
||||
def correct_for_export(all_data):
|
||||
"""
|
||||
Process the data for spreadsheet export.
|
||||
"""
|
||||
for d in all_data:
|
||||
for k, v in d.items():
|
||||
if isinstance(v, list) or isinstance(v, tuple):
|
||||
if len(v):
|
||||
new_list = []
|
||||
for data in v:
|
||||
new_list.append(str(data))
|
||||
d[k] = ','.join(new_list)
|
||||
if len(v) == 0:
|
||||
d[k] = 0
|
||||
|
||||
elif isinstance(v, ifcopenshell.entity_instance):
|
||||
d[k] = v[0]
|
||||
return all_data
|
||||
|
||||
|
||||
def export_to_xlsx(xlsx_name, concepts, all_data):
|
||||
"""
|
||||
Export data towards XLSX spreadsheet format.
|
||||
|
||||
:param xlsx_name: Name of the outputted file.
|
||||
:param concepts: List of mvdXML Concept instances.
|
||||
:param all_data: Data extracted.
|
||||
|
||||
"""
|
||||
|
||||
if not os.path.isdir("spreadsheet_output/"):
|
||||
os.mkdir("spreadsheet_output/")
|
||||
|
||||
workbook = xlsxwriter.Workbook("spreadsheet_output/" + xlsx_name)
|
||||
worksheet = workbook.add_worksheet()
|
||||
# Formats
|
||||
bold_format = workbook.add_format()
|
||||
bold_format.set_bold()
|
||||
bold_format.set_center_across()
|
||||
# Write first row
|
||||
column_index = 0
|
||||
for concept in concepts:
|
||||
worksheet.write(0, column_index, concept.name, bold_format)
|
||||
column_index += 1
|
||||
|
||||
col = 0
|
||||
for feature in all_data:
|
||||
row = 1
|
||||
for d in feature.values():
|
||||
worksheet.write(row, col, d)
|
||||
row += 1
|
||||
col += 1
|
||||
|
||||
workbook.close()
|
||||
|
||||
|
||||
def export_to_csv(csv_name, concepts, all_data):
|
||||
"""
|
||||
Export data towards CSV spreadsheet format.
|
||||
|
||||
:param csv_name: Name of the file outputted file.
|
||||
:param concepts: List of mvdXML Concept instances.
|
||||
:param all_data: Data extracted.
|
||||
"""
|
||||
|
||||
if not os.path.isdir("spreadsheet_output/"):
|
||||
os.mkdir("spreadsheet_output/")
|
||||
|
||||
with open('spreadsheet_output/' + csv_name, 'w', newline='') as f:
|
||||
writer = csv.writer(f)
|
||||
header = [concept.name for concept in concepts]
|
||||
first_row = writer.writerow(header)
|
||||
|
||||
values_by_row = []
|
||||
for val in all_data:
|
||||
values_by_row.append(list(val.values()))
|
||||
entities_number = len(all_data[0].keys())
|
||||
for i in range(0, entities_number):
|
||||
row_to_write = []
|
||||
for r in values_by_row:
|
||||
row_to_write.append(r[i])
|
||||
|
||||
f = writer.writerow(row_to_write)
|
||||
|
||||
|
||||
def get_data(mvd_concept, ifc_file, spreadsheet_export=True):
|
||||
"""
|
||||
Use the majority of all the other functions to return the data
|
||||
queried by the mvdXML file in python format.
|
||||
|
||||
:param mvd_concept: mvdXML Concept instance.
|
||||
:param ifc_file: IFC file from any schema.
|
||||
:param spreadsheet_export: The spreadsheet export is carried out when set to True.
|
||||
|
||||
|
||||
|
||||
"""
|
||||
|
||||
# Check if IFC entities have been filtered at least once
|
||||
filtered = 0
|
||||
|
||||
entities = ifc_file.by_type(mvd_concept.entity)
|
||||
selected_entities = entities
|
||||
verification_matrix = {}
|
||||
for entity in selected_entities:
|
||||
verification = dict()
|
||||
verification_matrix[entity.GlobalId] = verification
|
||||
|
||||
# For each Concept(ConceptTemplate) in the ConceptRoot
|
||||
concepts = sorted(mvd_concept.concepts(), key=is_applicability, reverse=True)
|
||||
all_data = []
|
||||
counter = 0
|
||||
for concept in concepts:
|
||||
if is_applicability(concept):
|
||||
filtering = True
|
||||
else:
|
||||
filtering = False
|
||||
|
||||
# Access all the Rules of the ConceptTemplate
|
||||
if len(concept.template().rules) > 1:
|
||||
attribute_rules = []
|
||||
for rule in concept.template().rules:
|
||||
attribute_rules.append(rule)
|
||||
rules_root = ifcopenshell.mvd.rule("EntityRule", mvd_concept.entity, attribute_rules)
|
||||
else:
|
||||
rules_root = concept.template().rules[0]
|
||||
|
||||
|
||||
extracted_data = get_data_from_mvd(selected_entities, rules_root, filtering=filtering)
|
||||
all_data.append(extracted_data)
|
||||
|
||||
if filtering:
|
||||
filtered = 1
|
||||
new_entities = []
|
||||
for entity_id in all_data[counter].keys():
|
||||
if len(all_data[counter][entity_id]) != 0:
|
||||
entity = ifc_file.by_id(entity_id)
|
||||
new_entities.append(entity)
|
||||
|
||||
selected_entities = new_entities
|
||||
not_respecting_entities = [item for item in entities if item not in selected_entities]
|
||||
for entity in entities:
|
||||
val = 0
|
||||
if entity in not_respecting_entities:
|
||||
val = 1
|
||||
verification_matrix[entity.GlobalId].update({concept.name: val})
|
||||
counter += 1
|
||||
|
||||
all_data = correct_for_export(all_data)
|
||||
|
||||
if spreadsheet_export:
|
||||
if filtered != 0:
|
||||
export_name = "output_filtered"
|
||||
else:
|
||||
export_name = "output_non_filtered"
|
||||
export_to_xlsx(export_name + '.xlsx', concepts, all_data)
|
||||
export_to_csv(export_name + '.csv', concepts, all_data)
|
||||
|
||||
|
||||
return all_data, verification_matrix
|
||||
|
||||
|
||||
def get_non_respecting_entities(file, verification_matrix):
|
||||
non_respecting = []
|
||||
for k, v in verification_matrix.items():
|
||||
entity = file.by_id(k)
|
||||
print(list(v.values()))
|
||||
if sum(v.values()) != 0:
|
||||
non_respecting.append(entity)
|
||||
|
||||
return non_respecting
|
||||
|
||||
|
||||
|
||||
|
||||
def get_respecting_entities(file, verification_matrix):
|
||||
respecting = []
|
||||
for k, v in verification_matrix.items():
|
||||
entity = file.by_id(k)
|
||||
print(list(v.values()))
|
||||
if sum(v.values()) == 0:
|
||||
respecting.append(entity)
|
||||
|
||||
return respecting
|
||||
|
||||
|
||||
def visualize(file, not_respecting_entities):
|
||||
"""
|
||||
Visualize the instances of the entity type targeted by the mvdXML ConceptRoot.
|
||||
At display, a color differentiation is made between the entities which comply with
|
||||
mvdXML requirements and the ones which don't.
|
||||
|
||||
:param file: IFC file from any schema.
|
||||
:param not_respecting_entities: Entities which don't comply with mvdXML requirements.
|
||||
|
||||
"""
|
||||
|
||||
s = ifcopenshell.geom.main.settings()
|
||||
s.set(s.USE_PYTHON_OPENCASCADE, True)
|
||||
s.set(s.DISABLE_OPENING_SUBTRACTIONS, False)
|
||||
|
||||
viewer = ifcopenshell.geom.utils.initialize_display()
|
||||
|
||||
entity_type = not_respecting_entities[0].is_a()
|
||||
|
||||
other_entities = [x for x in file.by_type("IfcBuildingElement") if x.is_a() != str(entity_type)]
|
||||
|
||||
set_of_entities = set(not_respecting_entities) | set(file.by_type(entity_type))
|
||||
set_to_display = set_of_entities.union(set(other_entities))
|
||||
|
||||
for el in set_to_display:
|
||||
if el in not_respecting_entities:
|
||||
c = (1, 0, 0, 1)
|
||||
elif el in other_entities:
|
||||
c = (1, 1, 1, 0)
|
||||
else:
|
||||
c = (0, 1, 0.5, 1)
|
||||
|
||||
try:
|
||||
shape = ifcopenshell.geom.create_shape(s, el)
|
||||
# OCC.BRepTools.breptools_Write(shape.geometry, "test.brep")
|
||||
ds = ifcopenshell.geom.utils.display_shape(shape, clr=c)
|
||||
except:
|
||||
pass
|
||||
|
||||
viewer.FitAll()
|
||||
|
||||
ifcopenshell.geom.utils.main_loop()
|
||||
|
||||
|
||||
def validate_data(concept, data):
|
||||
import io
|
||||
import ast
|
||||
import operator
|
||||
from functools import reduce, partial
|
||||
|
||||
rules = [x[0] for x in concept.rules() if not isinstance(x, str)]
|
||||
|
||||
def transform_data(d):
|
||||
"""
|
||||
Transform dictionary keys from tree nodes to rule ids
|
||||
"""
|
||||
|
||||
return {(k.parent if k.bind is None and k.parent.bind is not None else k).bind: v for k, v in d.items()}
|
||||
|
||||
|
||||
def parse_mvdxml_token(v):
|
||||
# @todo make more permissive and tolerant
|
||||
return ast.literal_eval(v)
|
||||
|
||||
|
||||
data = list(map(transform_data, data))
|
||||
|
||||
output = io.StringIO()
|
||||
|
||||
# https://stackoverflow.com/a/70227259
|
||||
def operation_reduce(x, y):
|
||||
"""
|
||||
Takes alternating value and function as input and
|
||||
reduces while applying function
|
||||
"""
|
||||
|
||||
if callable(x):
|
||||
return x(y)
|
||||
else:
|
||||
return partial(y, x)
|
||||
|
||||
|
||||
def apply_rules():
|
||||
|
||||
for r in rules:
|
||||
|
||||
def apply_data():
|
||||
|
||||
for d in data:
|
||||
|
||||
def translate(v):
|
||||
if isinstance(v, str):
|
||||
return getattr(operator, v.lower() + "_")
|
||||
else:
|
||||
if v.b == "Value":
|
||||
return d.get(v.a) == parse_mvdxml_token(v.c)
|
||||
elif v.b == "Type":
|
||||
return d.get(v.a) and d.get(v.a).is_a(parse_mvdxml_token(v.c))
|
||||
|
||||
r2 = list(map(translate, r))
|
||||
yield reduce(operation_reduce, r2)
|
||||
|
||||
v = any(list(apply_data()))
|
||||
print(("Met:" if v else "Not met:"), r, file=output)
|
||||
yield v
|
||||
|
||||
|
||||
valid = all(list(apply_rules()))
|
||||
return valid, output.getvalue()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('functions to parse MVD rules and extract IFC data/filter IFC entities from them')
|
||||
@@ -0,0 +1,190 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mvdXML name="mvdXML examples" uuid="4afb1a8b-0b61-4ff8-9863-c10690fe06f2" xmlns="http://buildingsmart-tech.org/mvdXML/mvdXML1-1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://buildingsmart-tech.org/mvdXML/mvdXML1-1 ../xsd/mvdXML_V1-1_draft.xsd">
|
||||
<Templates>
|
||||
<ConceptTemplate uuid="4b385464-b99a-42bc-a17a-a0a647a1ab5b" name="Association" code="" status="" applicableSchema="IFC4" applicableEntity="IfcObjectDefinition">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="ea2a63be-fd0d-426d-863b-52c3970ca585" name="Material" code="" status="" applicableSchema="IFC4" applicableEntity="IfcObjectDefinition">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p class="std">
|
||||
|
||||
Any product or product type can have associated materials indicating the physical composition of an object.
|
||||
|
||||
Materials can have representations for surface styles indicating colors, textures, and light reflectance for 3D
|
||||
|
||||
rendering. Materials can have representations for fill styles indicating colors, tiles, and hatch patterns for
|
||||
|
||||
2D rendering. Materials can have properties such as density, elasticity, thermal resistance, and others as
|
||||
|
||||
defined in this specification. Materials can also be classified according to a referenced industry standard.
|
||||
|
||||
</p>
|
||||
|
||||
<p class="std">
|
||||
|
||||
An object can be comprised of a single material or a set of materials with a particular layout. Several
|
||||
|
||||
examples include:
|
||||
|
||||
</p>
|
||||
|
||||
<ul class="std">
|
||||
|
||||
<li class="std">a slab may have an associated layer of concrete;
|
||||
|
||||
</li>
|
||||
|
||||
<li class="std">a beam may have an associated I-Shape profile of steel;
|
||||
|
||||
</li>
|
||||
|
||||
<li class="std">a door may have associated constituents for framing and glazing;
|
||||
|
||||
</li>
|
||||
|
||||
<li class="std">a port may have an associated profile and/or material flowing through it such as hot water.
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="6d5fb86f-3f2d-49fb-9528-077855ddcc47" name="Material Layer Set Usage" code="" status="" applicableSchema="IFC4" applicableEntity="IfcProduct">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>Material layer set usage defines layout at occurrences to indicate a direction and offset from the 'Axis' reference curve, and a reference extent such as for a default wall height. </p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="HasAssociations" Cardinality="One">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelAssociatesMaterial" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="RelatingMaterial" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMaterialLayerSetUsage" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="ForLayerSet" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMaterialLayerSet" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="MaterialLayers" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMaterialLayer" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="Name" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Material" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMaterial" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="Name" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Category" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="" AttributeName="LayerThickness" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcNonNegativeLengthMeasure" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="LayerSetName" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="DirectionSense" AttributeName="DirectionSense" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcDirectionSenseEnum" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="LayerSetDirection" AttributeName="LayerSetDirection" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLayerSetDirectionEnum" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
</Templates>
|
||||
<Views>
|
||||
<ModelView uuid="f935ce4c-b52e-4175-ac7f-cca0dc638871" name="CoordinationView" version="2014" applicableSchema="IFC4">
|
||||
<ExchangeRequirements>
|
||||
<ExchangeRequirement uuid="9a71e977-a156-426b-8599-c7cf6dc463c1" name="Examples" applicability="export">
|
||||
</ExchangeRequirement>
|
||||
</ExchangeRequirements>
|
||||
<Roots>
|
||||
<ConceptRoot uuid="30188bbe-5eea-4cd6-a8ee-3414148d3a50" name= "Slab" applicableRootEntity="IfcSlab">
|
||||
<Concepts>
|
||||
<Concept uuid="59b515d0-d057-45c3-acbb-851dd9ba14a2" name="Material Layer Set Usage" Override="false">
|
||||
<Template ref="6d5fb86f-3f2d-49fb-9528-077855ddcc47" />
|
||||
<Requirements>
|
||||
<Requirement applicability="export" requirement="mandatory" exchangeRequirement="9a71e977-a156-426b-8599-c7cf6dc463c1" />
|
||||
</Requirements>
|
||||
<Rules>
|
||||
<TemplateRule Parameters="DirectionSense[Value]='POSITIVE' AND LayerSetDirection[Value]='AXIS3' " />
|
||||
</Rules>
|
||||
</Concept>
|
||||
</Concepts>
|
||||
</ConceptRoot>
|
||||
</Roots>
|
||||
</ModelView>
|
||||
</Views>
|
||||
</mvdXML>
|
||||
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mvdXML name="mvdXML examples" uuid="4afb1a8b-0b61-4ff8-9863-c10690fe06f2" xmlns="http://buildingsmart-tech.org/mvdXML/mvdXML1-1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://buildingsmart-tech.org/mvdXML/mvdXML1-1 ../xsd/mvdXML_V1-1_draft.xsd">
|
||||
<Templates>
|
||||
<ConceptTemplate uuid="252a5fa6-cc5b-4d30-bd0c-35e22e336499" name="Connectivity" code="" status="" applicableSchema="IFC4" applicableEntity="IfcObject">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p class="std">
|
||||
Objects may participate in various connectivity
|
||||
relationships with other objects.
|
||||
</p>
|
||||
]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="06674893-7a2c-493b-8eb5-e85a058707b3" name="Filling" status="" applicableSchema="IFC4" applicableEntity="IfcElement">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>Elements such as doors and windows may be placed inside openings of walls, slabs, or other elements.</p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="FillsVoids" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelFillsElement" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="RelatingOpeningElement" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcOpeningElement" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="VoidsElements" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelVoidsElement" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule RuleID="Type" AttributeName="RelatingElement" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcElement" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="HasFillings" Cardinality="ZeroToOne">
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
</Templates>
|
||||
<Views>
|
||||
<ModelView uuid="f935ce4c-b52e-4175-ac7f-cca0dc638871" name="CoordinationView" version="2014" applicableSchema="IFC4">
|
||||
<ExchangeRequirements>
|
||||
<ExchangeRequirement uuid="9a71e977-a156-426b-8599-c7cf6dc463c1" name="Examples" applicability="export">
|
||||
</ExchangeRequirement>
|
||||
</ExchangeRequirements>
|
||||
<Roots>
|
||||
<ConceptRoot uuid="d2b8f47b-36b7-48a2-b248-f9d7a921f6e1" name="Door" applicableRootEntity="IfcDoor">
|
||||
<Concepts>
|
||||
<Concept uuid="8329cb90-1062-401f-b965-8fa07202225a" name="Filling">
|
||||
<Template ref="06674893-7a2c-493b-8eb5-e85a058707b3" />
|
||||
<Requirements>
|
||||
<Requirement applicability="export" requirement="optional" exchangeRequirement="9a71e977-a156-426b-8599-c7cf6dc463c1" />
|
||||
</Requirements>
|
||||
</Concept>
|
||||
</Concepts>
|
||||
</ConceptRoot>
|
||||
<ConceptRoot uuid="f1013c14-f631-4a05-99f7-73f772025997" name="Window" applicableRootEntity="IfcWindow">
|
||||
<Concepts>
|
||||
<Concept uuid="7dca33ea-2faf-43b3-9f09-4bf8aa06d43d" name="Filling">
|
||||
<Template ref="06674893-7a2c-493b-8eb5-e85a058707b3" />
|
||||
<Requirements>
|
||||
<Requirement applicability="export" requirement="optional" exchangeRequirement="9a71e977-a156-426b-8599-c7cf6dc463c1" />
|
||||
</Requirements>
|
||||
</Concept>
|
||||
</Concepts>
|
||||
</ConceptRoot>
|
||||
</Roots>
|
||||
</ModelView>
|
||||
</Views>
|
||||
</mvdXML>
|
||||
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mvdXML name="mvdXML examples" uuid="4afb1a8b-0b61-4ff8-9863-c10690fe06f2" xmlns="http://buildingsmart-tech.org/mvdXML/mvdXML1-1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://buildingsmart-tech.org/mvdXML/mvdXML1-1 ../xsd/mvdXML_V1-1_draft.xsd">
|
||||
<Templates>
|
||||
<ConceptTemplate uuid="805deb96-2684-4bc5-a9ad-3a29199dc023" name="Project" status="" applicableSchema="IFC4" applicableEntity="IfcContext">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>All files contain a single <i>IfcProject</i> instance indicating overall context and a directory of objects contained within.</p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="38dac6f0-997c-4544-9bca-b6326b9a3e4b" name="Project Context" status="" applicableSchema="IFC4" applicableEntity="IfcContext">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[ <p class="std">
|
||||
|
||||
A project representation context indicates the coordinate system orientation, direction of true north,
|
||||
|
||||
precision, and other values that apply to all geometry within a project or project library.
|
||||
|
||||
</p>
|
||||
]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<Rules>
|
||||
<AttributeRule RuleID="RepresentationContext" AttributeName="RepresentationContexts" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcGeometricRepresentationContext" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="ContextIdentifier" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="ContextType" AttributeName="ContextType" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="CoordinateSpaceDimension" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcDimensionCount" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="WorldCoordinateSystem" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcAxis2Placement3D" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="TrueNorth" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcDirection" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="HasSubContexts" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcGeometricRepresentationSubContext" Cardinality="_asSchema">
|
||||
<AttributeRules>
|
||||
<AttributeRule RuleID="SubContextIdentifier" AttributeName="ContextIdentifier" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="ContextType" Cardinality="_asSchema">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" Cardinality="_asSchema">
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
</Templates>
|
||||
<Views>
|
||||
<ModelView uuid="f935ce4c-b52e-4175-ac7f-cca0dc638871" name="CoordinationView" version="2014" applicableSchema="IFC4">
|
||||
<ExchangeRequirements>
|
||||
<ExchangeRequirement uuid="9a71e977-a156-426b-8599-c7cf6dc463c1" name="Examples" applicability="export">
|
||||
</ExchangeRequirement>
|
||||
</ExchangeRequirements>
|
||||
<Roots>
|
||||
<ConceptRoot uuid="dc78525e-b86d-45e1-a3fc-aaf15d1624f9" name="Project" applicableRootEntity="IfcProject">
|
||||
<Concepts>
|
||||
<Concept uuid="2f343b21-7a22-4674-af0b-48144a075fc9" name="Project Context">
|
||||
<Template ref="38dac6f0-997c-4544-9bca-b6326b9a3e4b" />
|
||||
<Requirements>
|
||||
<Requirement applicability="export" requirement="mandatory" exchangeRequirement="9a71e977-a156-426b-8599-c7cf6dc463c1" />
|
||||
</Requirements>
|
||||
<Rules>
|
||||
<TemplateRule Parameters="RepresentationContext[Size]<3 AND ContextType[Value]='Model' AND SubContextIdentifier[Value]='Body' " />
|
||||
</Rules>
|
||||
</Concept>
|
||||
</Concepts>
|
||||
</ConceptRoot>
|
||||
</Roots>
|
||||
</ModelView>
|
||||
</Views>
|
||||
</mvdXML>
|
||||
File diff suppressed because it is too large
Load Diff
+13876
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,213 @@
|
||||
<?xml version="1.0"?>
|
||||
<mvdXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" uuid="b4b7c35a-f8e7-468f-ab57-822fc0750dc8" name="" status="sample" xsi:schemaLocation="http://www.buildingsmart-tech.org/mvd/XML/1.1 http://www.buildingsmart-tech.org/mvd/XML/1.1/mvdXML_V1.1_add1.xsd" xmlns="http://buildingsmart-tech.org/mvd/XML/1.1">
|
||||
<Templates>
|
||||
<ConceptTemplate uuid="d862db8a-fdc4-4d1d-9934-cddee2ae2a88" name="IsExternal" status="sample" applicableSchema="IFC4" applicableEntity="IfcWall">
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="IsDefinedBy">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelDefinesByProperties">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="RelatingPropertyDefinition">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcPropertySet">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel">
|
||||
<Constraints>
|
||||
<Constraint Expression="[Value] = 'Pset_WallCommon'" />
|
||||
</Constraints>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="HasProperties">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcPropertySingleValue">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier">
|
||||
<Constraints>
|
||||
<Constraint Expression="[Value] = 'IsExternal'" />
|
||||
</Constraints>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="NominalValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcBoolean">
|
||||
<Constraints>
|
||||
<Constraint Expression="[Value] = 'True'" />
|
||||
</Constraints>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="57879083-3675-4fe0-b0f1-9d17a6a4dcb6" name="Name" status="sample" applicableSchema="IFC4" applicableEntity="IfcRoot">
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="f99fe764-9732-4029-955e-08c51dd854e3" name="MaterialLayer" status="sample" applicableSchema="IFC4" applicableEntity="IfcWall">
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="HasAssociations">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelAssociatesMaterial">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="RelatingMaterial">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMaterialLayerSetUsage">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="ForLayerSet">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMaterialLayerSet">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="MaterialLayers">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMaterialLayer">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="LayerThickness">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcNonNegativeLengthMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="96ae8928-8f91-4768-bd40-89a89d6c6fc8" name="HasOpenings" status="sample" applicableSchema="IFC4" applicableEntity="IfcWall">
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="HasOpenings">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelVoidsElement">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="GlobalId">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcGloballyUniqueId" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="b6b5f23a-efc8-4b0a-96d5-f8adbddc8796" name="TemplateDefinition2" status="sample" applicableSchema="IFC4" applicableEntity="IfcWall">
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="IsDefinedBy">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelDefinesByProperties">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="RelatingPropertyDefinition">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcPropertySet">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="HasProperties">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcPropertySingleValue">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="NominalValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcAreaMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier">
|
||||
<Constraints>
|
||||
<Constraint Expression="[Value] = 'Area'" />
|
||||
</Constraints>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel">
|
||||
<Constraints>
|
||||
<Constraint Expression="[Value] = 'PSet_Revit_Dimensions'" />
|
||||
</Constraints>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</Templates>
|
||||
<Views>
|
||||
<ModelView uuid="cb00b001-d3d4-4e6a-8c1a-f97526c8d227" name="Wall_Extraction" status="sample" applicableSchema="IFC4">
|
||||
<ExchangeRequirements />
|
||||
<Roots>
|
||||
<ConceptRoot uuid="9c5337ac-83db-4ef3-92fc-086d03dfc521" name="IfcWall" status="proposal" applicableRootEntity="IfcWall">
|
||||
<Applicability uuid="00000000-0000-0000-0000-000000000000" status="sample">
|
||||
<Template ref="96ae8928-8f91-4768-bd40-89a89d6c6fc8" />
|
||||
<TemplateRules operator="and" />
|
||||
</Applicability>
|
||||
<Concepts>
|
||||
<Concept uuid="eaf87838-a06e-4b64-bbd7-bed4d455e825" name="APexternal" status="sample" override="false">
|
||||
<Template ref="d862db8a-fdc4-4d1d-9934-cddee2ae2a88" />
|
||||
</Concept>
|
||||
<Concept uuid="e2f1ffad-4509-489c-a294-81909060e2e9" name="voids" status="sample" override="false">
|
||||
<Template ref="96ae8928-8f91-4768-bd40-89a89d6c6fc8" />
|
||||
</Concept>
|
||||
<Concept uuid="9325e5cb-45d1-4c35-8925-d70409fe6685" name="mat" status="sample" override="false">
|
||||
<Template ref="f99fe764-9732-4029-955e-08c51dd854e3" />
|
||||
</Concept>
|
||||
<Concept uuid="ecb11482-1b53-4853-9674-d3069b45a7ca" name="name" status="sample" override="false">
|
||||
<Template ref="57879083-3675-4fe0-b0f1-9d17a6a4dcb6" />
|
||||
</Concept>
|
||||
<Concept uuid="c93399aa-c032-4f0e-883b-2d41783fa94d" name="area" status="sample" override="false">
|
||||
<Template ref="b6b5f23a-efc8-4b0a-96d5-f8adbddc8796" />
|
||||
</Concept>
|
||||
</Concepts>
|
||||
</ConceptRoot>
|
||||
</Roots>
|
||||
</ModelView>
|
||||
</Views>
|
||||
</mvdXML>
|
||||
@@ -0,0 +1,513 @@
|
||||
<?xml version="1.0"?>
|
||||
<mvdXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" uuid="9cad09cc-c9b9-4425-85cb-0a371405013b" name="" status="sample" xsi:schemaLocation="http://www.buildingsmart-tech.org/mvd/XML/1.1 http://www.buildingsmart-tech.org/mvd/XML/1.1/mvdXML_V1.1_add1.xsd" xmlns="http://buildingsmart-tech.org/mvd/XML/1.1">
|
||||
<Templates>
|
||||
<ConceptTemplate uuid="33e0be15-e301-4858-9f4b-18b2eb5488ba" name="Object Definition" status="sample" applicableSchema="IFC4" applicableEntity="IfcObjectDefinition">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>The concept templates of <em>Object Definition</em> provides the means to define an object occurrence by its object type and attached property and quantity sets.</p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="36984334-3ac8-4e59-85a6-f68d65e379c7" name="Property Sets" status="sample" applicableSchema="IFC4" applicableEntity="IfcRoot">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>The concept template <em>Property Sets</em> describes how sets of properties (usually defined by a name, value, unit triple) are associated to objects or object types.</p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="f74255a6-0c0e-4f31-84ad-24981db62461" name="Property Sets for Objects" version="1" status="sample" applicableSchema="IFC4" applicableEntity="IfcObject">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>The concept template <em>Property Sets for Objects</em> describes how an object occurrence can be related to a single or multiple property sets. A property set
|
||||
contains a single or multiple properties. The data types of
|
||||
an individual property are single value, enumerated value,
|
||||
bounded value, table value, reference value, list value,
|
||||
and combination of property occurrences.
|
||||
</p>
|
||||
|
||||
|
||||
<p>Property sets can also be related to an object type, see concept <em>Property Sets for Types</em>. They then define the common properties for all occurrences of the same type. If the same property (by name) is provided by the same property set (by name), then the properties directly assigned to the object occurrence override the properties assigned to the object type.</p>
|
||||
]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<Rules>
|
||||
<AttributeRule RuleID="PredefinedType" AttributeName="PredefinedType" />
|
||||
<AttributeRule AttributeName="IsDefinedBy">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelDefinesByProperties">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="RelatingPropertyDefinition">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcPropertySet">
|
||||
<AttributeRules>
|
||||
<AttributeRule RuleID="PsetName" AttributeName="Name" />
|
||||
<AttributeRule RuleID="Properties" AttributeName="HasProperties">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcPropertySingleValue">
|
||||
<References>
|
||||
<Template ref="6655f6d0-29a8-47b8-8f3d-c9fce9c9a620" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcPropertyBoundedValue">
|
||||
<References>
|
||||
<Template ref="3d67a2d2-761d-44d9-a09e-b7fbb1fa5632" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcPropertyEnumeratedValue">
|
||||
<References>
|
||||
<Template ref="c148a099-c351-43a8-9266-5f3de0b45a95" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcPropertyListValue">
|
||||
<References>
|
||||
<Template ref="8e10b688-9179-4e3a-8db2-6abcaafe952d" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcPropertyTableValue">
|
||||
<References>
|
||||
<Template ref="35c947b0-6abc-4b13-8ec7-696ef2041721" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="6652398e-6579-4460-8cb4-26295acfacc7" name="Quantity Sets" version="1" status="sample" applicableSchema="IFC4" applicableEntity="IfcObject">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[
|
||||
<p>
|
||||
Any specialization of object can be related to multiple quantity set occurrences. A quantity set
|
||||
contains multiple quantity occurrences. The data type of
|
||||
quantity occurrence values are count, length, area, volume, weight, time, or a combination of quantities. Each quantity is defined by its name, value, and optionally a description and a formula.</p>
|
||||
|
||||
|
||||
<p>The quantity set is expressed by instances of <em>IfcElementQuantity</em>, where the <em>Name</em> attribute determines the common designator of the quantity set. This specification contains a number of predefined quantity sets, a template definition is provided for each of them. The name of the template has to be used as the value of the <em>Name</em> attribute. The <em>MethodOfMeasurement</em> attribute specifies the method, by which the values of the individual quantities are calculated. For the quantity set templates included in this specification, the value of <em>MethodOfMeasurement</em> shall be "BaseQuantities".</p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<Rules>
|
||||
<AttributeRule AttributeName="IsDefinedBy">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcRelDefinesByProperties">
|
||||
<AttributeRules>
|
||||
<AttributeRule AttributeName="RelatingPropertyDefinition">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcElementQuantity">
|
||||
<AttributeRules>
|
||||
<AttributeRule RuleID="QsetName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="MethodOfMeasurement">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="Quantities" AttributeName="Quantities">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcQuantityLength">
|
||||
<References>
|
||||
<Template ref="dd8678e1-e300-4f70-9d63-e539db4bd11c" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcQuantityArea">
|
||||
<References>
|
||||
<Template ref="65ac4747-6eff-437e-94e2-643fd4e3bf86" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcQuantityVolume">
|
||||
<References>
|
||||
<Template ref="6491a3b0-b7e9-412a-8226-bcd91c2b0b0e" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcQuantityWeight">
|
||||
<References>
|
||||
<Template ref="e1016e56-3c89-4f42-9679-07e1db3c0afb" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcQuantityCount">
|
||||
<References>
|
||||
<Template ref="8aaeff32-572c-4f6a-ac64-e2151663cbf1" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
<EntityRule EntityName="IfcQuantityTime">
|
||||
<References>
|
||||
<Template ref="43c4c050-04de-4b0f-9e43-708bd98201a8" />
|
||||
</References>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="a322fdd7-cd28-4ea7-8797-f6cf124ab3d6" name="Partial Templates" status="sample" applicableSchema="IFC4">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>Partial concept templates are described herein to indicate usage of common data types, which are then incorporated into other templates.</p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="88b4aaa9-0925-447c-b009-fe357b7c754e" name="Values" status="sample" applicableSchema="IFC4" applicableEntity="IfcSimpleProperty">
|
||||
<Definitions>
|
||||
<Definition>
|
||||
<Body><![CDATA[<p>Properties may contain user-defined data, where data types are open-ended.</p>]]></Body>
|
||||
</Definition>
|
||||
</Definitions>
|
||||
<Rules>
|
||||
<AttributeRule RuleID="PropertyName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="6655f6d0-29a8-47b8-8f3d-c9fce9c9a620" name="Single Value" status="sample" owner="System" applicableSchema="IFC4" applicableEntity="IfcPropertySingleValue">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="PropertyName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="Value" AttributeName="NominalValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="3d67a2d2-761d-44d9-a09e-b7fbb1fa5632" name="Bounded Value" status="sample" owner="System" applicableSchema="IFC4" applicableEntity="IfcPropertyBoundedValue">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="PropertyName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="UpperValue" AttributeName="UpperBoundValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="LowerValue" AttributeName="LowerBoundValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="SetValue" AttributeName="SetPointValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="c148a099-c351-43a8-9266-5f3de0b45a95" name="Enumerated Value" status="sample" owner="System" applicableSchema="IFC4" applicableEntity="IfcPropertyEnumeratedValue">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="PropertyName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="Value" AttributeName="EnumerationValues">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="EnumerationReference">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcPropertyEnumeration">
|
||||
<AttributeRules>
|
||||
<AttributeRule RuleID="Reference" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</AttributeRules>
|
||||
</EntityRule>
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="8e10b688-9179-4e3a-8db2-6abcaafe952d" name="List Value" status="sample" applicableSchema="IFC4" applicableEntity="IfcPropertyListValue">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="PropertyName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="Value" AttributeName="ListValues">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="35c947b0-6abc-4b13-8ec7-696ef2041721" name="Table Value" status="sample" applicableSchema="IFC4" applicableEntity="IfcPropertyTableValue">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="PropertyName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcIdentifier" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="Value" AttributeName="DefiningValues">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="Reference" AttributeName="DefinedValues">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcValue" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Expression">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="CurveInterpolation">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcCurveInterpolationEnum" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="6c03e465-c5dd-42ce-9412-bebacabd2f3b" name="Quantities" status="sample" applicableSchema="IFC4" applicableEntity="IfcPhysicalSimpleQuantity">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="QuantityName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="dd8678e1-e300-4f70-9d63-e539db4bd11c" name="Length Quantity" status="sample" applicableSchema="IFC4" applicableEntity="IfcQuantityLength">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="QuantityName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="LengthValue" AttributeName="LengthValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLengthMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Formula">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="65ac4747-6eff-437e-94e2-643fd4e3bf86" name="Area Quantity" status="sample" applicableSchema="IFC4" applicableEntity="IfcQuantityArea">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="QuantityName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="AreaValue" AttributeName="AreaValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcAreaMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Formula">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="6491a3b0-b7e9-412a-8226-bcd91c2b0b0e" name="Volume Quantity" status="sample" applicableSchema="IFC4" applicableEntity="IfcQuantityVolume">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="QuantityName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="VolumeValue" AttributeName="VolumeValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcVolumeMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Formula">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="e1016e56-3c89-4f42-9679-07e1db3c0afb" name="Weight Quantity" status="sample" applicableSchema="IFC4" applicableEntity="IfcQuantityWeight">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="QuantityName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="WeightValue" AttributeName="WeightValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcMassMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Formula">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="8aaeff32-572c-4f6a-ac64-e2151663cbf1" name="Count Quantity" status="sample" applicableSchema="IFC4" applicableEntity="IfcQuantityCount">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="QuantityName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="CountValue" AttributeName="CountValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcCountMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Formula">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="43c4c050-04de-4b0f-9e43-708bd98201a8" name="Time Quantity" status="sample" applicableSchema="IFC4" applicableEntity="IfcQuantityTime">
|
||||
<Rules>
|
||||
<AttributeRule RuleID="QuantityName" AttributeName="Name">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Description">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcText" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule RuleID="TimeValue" AttributeName="TimeValue">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcTimeMeasure" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
<AttributeRule AttributeName="Formula">
|
||||
<EntityRules>
|
||||
<EntityRule EntityName="IfcLabel" />
|
||||
</EntityRules>
|
||||
</AttributeRule>
|
||||
</Rules>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
<ConceptTemplate uuid="00000000-0000-0000-0000-000000000000" name="_xset" code="eead5b95-7b55-4d1c-8b71-dac234adfe38" status="sample" applicableSchema="IFC4">
|
||||
<SubTemplates>
|
||||
<ConceptTemplate uuid="be6755a6-b9b6-4884-b820-ea6a73a7402f" status="sample" applicableSchema="IFC4" applicableEntity="IfcObject" />
|
||||
</SubTemplates>
|
||||
</ConceptTemplate>
|
||||
</Templates>
|
||||
<Views>
|
||||
<ModelView uuid="eead5b95-7b55-4d1c-8b71-dac234adfe38" name="xset" status="sample" applicableSchema="IFC4">
|
||||
<ExchangeRequirements />
|
||||
<Roots>
|
||||
<ConceptRoot uuid="8ad3fd6c-547b-47d7-8a8b-e68d92da2566" name="IfcObject" status="sample" applicableRootEntity="IfcObject">
|
||||
<Applicability uuid="00000000-0000-0000-0000-000000000000" status="sample">
|
||||
<Template ref="be6755a6-b9b6-4884-b820-ea6a73a7402f" />
|
||||
<TemplateRules operator="and" />
|
||||
</Applicability>
|
||||
<Concepts>
|
||||
<Concept uuid="50ea6466-6555-424f-9179-ee5f7c0dbf62" name="qset" status="sample" override="false">
|
||||
<Template ref="6652398e-6579-4460-8cb4-26295acfacc7" />
|
||||
</Concept>
|
||||
<Concept uuid="9e3151ca-7c3c-4c1b-b155-e13d30d86b2d" name="pset" status="sample" override="false">
|
||||
<Template ref="f74255a6-0c0e-4f31-84ad-24981db62461" />
|
||||
</Concept>
|
||||
</Concepts>
|
||||
</ConceptRoot>
|
||||
</Roots>
|
||||
</ModelView>
|
||||
</Views>
|
||||
</mvdXML>
|
||||
@@ -0,0 +1,29 @@
|
||||
import pyparsing as pp
|
||||
|
||||
class node(object):
|
||||
def __init__(self, args):
|
||||
if len(args) == 3 and args[1] == '=':
|
||||
self.a, self.b, self.c = args[0], None, args[2]
|
||||
elif (args[1], args[3], args[4]) == ('[', ']', '='):
|
||||
self.a, self.b, self.c = args[0], args[2], args[5]
|
||||
else:
|
||||
self.a, self.b, self.c = None, args[1], args[4]
|
||||
|
||||
def __repr__(self): return "{%s[%s]=%s}" % (self.a, self.b, self.c)
|
||||
|
||||
word = pp.Word(pp.alphanums+"_"+" "+"/"+"#")
|
||||
quoted = pp.Combine("'" + word + "'")
|
||||
bool_value = pp.CaselessLiteral("TRUE") | pp.CaselessLiteral("FALSE")
|
||||
ref_val = word + "[" + word + "]"
|
||||
rhs = quoted | bool_value | ref_val | word
|
||||
stmt = (pp.Optional(word) + pp.Optional("[" + word + "]") + "=" + rhs).setParseAction(node)
|
||||
bool_op = pp.CaselessLiteral("AND") | pp.CaselessLiteral("OR")
|
||||
grammar = stmt + pp.Optional(pp.OneOrMore(bool_op + stmt))
|
||||
|
||||
def parse(exprs):
|
||||
def _():
|
||||
for expr in exprs.split(";"):
|
||||
expr = "".join(c for c in expr if c not in "\r\n")
|
||||
if not expr: continue
|
||||
yield grammar.parseString(expr)
|
||||
return list(_())
|
||||
@@ -0,0 +1,609 @@
|
||||
import io
|
||||
import os
|
||||
import csv
|
||||
import platform
|
||||
import tabulate
|
||||
import operator
|
||||
import itertools
|
||||
import subprocess
|
||||
import ifcopenshell
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
import mvdxml_expression
|
||||
|
||||
def camel(s):
|
||||
"""
|
||||
Camel case conversion function
|
||||
:param s: str
|
||||
:return: camel case formatted string
|
||||
"""
|
||||
|
||||
s = s.title().replace(" ", "")
|
||||
if s.endswith("s"): s = s[:-1]
|
||||
return s[0].lower() + s[1:]
|
||||
|
||||
|
||||
STANDARD_PREFIXES = {
|
||||
'rdf': '<http://www.w3.org/1999/02/22-rdf-syntax-ns#>',
|
||||
'owl': '<http://www.w3.org/2002/07/owl#>',
|
||||
'xsd': '<http://www.w3.org/2001/XMLSchema#>',
|
||||
'list': '<https://w3id.org/list#>',
|
||||
'ifcowl': '',
|
||||
'express': '<https://w3id.org/express#>',
|
||||
}
|
||||
|
||||
def derive_prefix(ttlfn):
|
||||
with open(ttlfn, "r") as f:
|
||||
for ln in f:
|
||||
ln.strip()
|
||||
if ln.startswith("@prefix ifcowl"):
|
||||
uri = ln.split(':', 1)[1].strip()[:-1].strip()
|
||||
print("Detected ifcowl prefix", uri)
|
||||
STANDARD_PREFIXES['ifcowl'] = uri
|
||||
break
|
||||
|
||||
def withschema(fn):
|
||||
"""
|
||||
Decorator that takes a function and adds an IFC latebound schema definition
|
||||
in the first parameter. The schema identifier is looked up based on the
|
||||
global ifcOwl prefix.
|
||||
|
||||
:param fn: input function
|
||||
:return: decorated function
|
||||
"""
|
||||
|
||||
def _(*args, **kwargs):
|
||||
schema_name = STANDARD_PREFIXES['ifcowl'].split('/')[-1][:-2]
|
||||
if "_" in schema_name:
|
||||
schema_name = schema_name.split('_')[0]
|
||||
S = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
return fn(S, *args, **kwargs)
|
||||
return _
|
||||
|
||||
noop = lambda *args: None
|
||||
|
||||
class rule_binding(object):
|
||||
"""
|
||||
Object for mapping rules to generated SPARQL variables
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
class builder(object):
|
||||
"""
|
||||
A helper class for dealing with SPARQL query statements
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.prefixes = {"express": "", "ifcowl": ""}
|
||||
self.statements = []
|
||||
|
||||
def append(self, *stmt):
|
||||
if len(stmt) == 3:
|
||||
for i, pos in enumerate(stmt[1:]):
|
||||
for po in pos.split("/"):
|
||||
if ":" in pos:
|
||||
a, b = po.split(':')
|
||||
self.prefixes[a] = ''
|
||||
self.statements.append(stmt)
|
||||
|
||||
def bind(self, di):
|
||||
for k in set(self.prefixes.keys()) & set(di.keys()):
|
||||
self.prefixes[k] = di[k]
|
||||
|
||||
def x(self):
|
||||
return len(self.statements)
|
||||
|
||||
def __repr__(self):
|
||||
def f(s):
|
||||
S = " ".join(s)
|
||||
if len(s) == 3: S += ' .'
|
||||
return S
|
||||
|
||||
def g(s):
|
||||
return "PREFIX %s: %s" % s
|
||||
|
||||
return "\n".join(itertools.chain(
|
||||
(g(s) for s in self.prefixes.items()),
|
||||
(f(s) for s in self.statements)
|
||||
))
|
||||
|
||||
class ifcOwl(object):
|
||||
"""
|
||||
Helper class with static function for dealing with ifcOwl attribute names
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
@withschema
|
||||
def supertypes(S, entity):
|
||||
"""
|
||||
Yields ifcOwl subtypes for the supplied entity name
|
||||
|
||||
:param S: schema definition (from decorator)
|
||||
:param entity: entity name string
|
||||
:return:
|
||||
"""
|
||||
|
||||
a, b = entity.split('#')
|
||||
try:
|
||||
en = S.declaration_by_name(b)
|
||||
if en.__class__.__name__ == "entity":
|
||||
while en.supertype():
|
||||
yield "%s#%s" % (a, en.supertype().name())
|
||||
en = en.supertype()
|
||||
except: pass
|
||||
|
||||
@staticmethod
|
||||
def get_names(e, c):
|
||||
"""
|
||||
Returns inverse or forward attribute names for latebound entity definition
|
||||
|
||||
:param e: latebound entity definition
|
||||
:param c: either 'all_attributes' or 'all_inverse_attributes'
|
||||
:return: set of attribute names
|
||||
"""
|
||||
|
||||
return set(map(lambda a: a.name(), getattr(e, c)()))
|
||||
|
||||
@staticmethod
|
||||
@withschema
|
||||
def is_boxed(S, entity, attribute, predCount=0):
|
||||
"""
|
||||
Returns whether the entity attribute should be boxed in ifcOwl. Which means
|
||||
that there is an additional indirection.
|
||||
|
||||
inst:IfcRelDefinesByType_21937
|
||||
ifcowl:globalId_IfcRoot inst:IfcGloballyUniqueId_117684 ;
|
||||
|
||||
inst:IfcGloballyUniqueId_117684
|
||||
rdf:type ifcowl:IfcGloballyUniqueId ;
|
||||
express:hasString "2P9FPkykn0r8rCpmBxZH0w" .
|
||||
|
||||
:param S: schema definition (from decorator)
|
||||
:param entity: entity name string
|
||||
:param attribute: attribute name string
|
||||
:param predCount: numeric identifier to postfix predicate identifier in case of SELECT types
|
||||
:return: either a predicate from the express namespace or a variable postfixed with predCount
|
||||
"""
|
||||
|
||||
en = S.declaration_by_name(entity)
|
||||
attr = [a for a in en.all_attributes() if a.name() == attribute][0]
|
||||
ty = attr.type_of_attribute()
|
||||
is_boxed = False
|
||||
while isinstance(ty, ifcopenshell.ifcopenshell_wrapper.named_type):
|
||||
ty = ty.declared_type()
|
||||
|
||||
if isinstance(ty, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
|
||||
# Just assume there is going to be some boxed type in here.
|
||||
# It could be all instance references, but fact is we don't know at this moment.
|
||||
# It's likely that mvdXML will only bind to literals?
|
||||
|
||||
return "?pred%d" % predCount
|
||||
|
||||
else:
|
||||
|
||||
while isinstance(ty, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
is_boxed = True
|
||||
ty = ty.declared_type()
|
||||
if is_boxed and isinstance(ty, ifcopenshell.ifcopenshell_wrapper.simple_type):
|
||||
ty = ty.declared_type()
|
||||
return "express:has%s%s" % (ty[0].upper(), ty[1:])
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
@withschema
|
||||
def name(S, entity, attribute):
|
||||
"""
|
||||
Names the entity attribute according to ifcOwl
|
||||
|
||||
:param S:
|
||||
:param entity:
|
||||
:param attribute:
|
||||
:return:
|
||||
"""
|
||||
en = S.declaration_by_name(entity)
|
||||
|
||||
while True:
|
||||
st = en.supertype()
|
||||
|
||||
attribute_names = ifcOwl.get_names(en, "all_attributes") | \
|
||||
ifcOwl.get_names(en, "all_inverse_attributes")
|
||||
|
||||
if st:
|
||||
attribute_names -= ifcOwl.get_names(st, "all_attributes") | \
|
||||
ifcOwl.get_names(st, "all_inverse_attributes")
|
||||
|
||||
if attribute in attribute_names:
|
||||
return "ifcowl:" + attribute[0].lower() + attribute[1:] + "_" + en.name()
|
||||
|
||||
en = st
|
||||
|
||||
if en is None:
|
||||
raise AttributeError("%s not found on %s" % (attribute, entity))
|
||||
|
||||
@staticmethod
|
||||
@withschema
|
||||
def is_select(S, decl_name):
|
||||
"""
|
||||
Returns True when the declaration is a select type
|
||||
|
||||
:param S:
|
||||
:param decl_name:
|
||||
:return:
|
||||
"""
|
||||
decl = S.declaration_by_name(decl_name)
|
||||
return isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type)
|
||||
|
||||
@staticmethod
|
||||
@withschema
|
||||
def is_inverse(S, entity, attribute):
|
||||
"""
|
||||
When entity attribute is an INVERSE attribute, returns the opposite
|
||||
forward entity and attribute name. Otherwise returns (False, False)
|
||||
|
||||
:param S:
|
||||
:param entity:
|
||||
:param attribute:
|
||||
:return:
|
||||
"""
|
||||
|
||||
en = S.declaration_by_name(entity)
|
||||
attrs = [a for a in en.all_inverse_attributes() if a.name() == attribute]
|
||||
if not attrs: return False, False
|
||||
|
||||
a = attrs[0]
|
||||
assert a.type_of_aggregation_string() == "set"
|
||||
entity = a.entity_reference().name()
|
||||
attr = a.attribute_reference().name()
|
||||
return "ifcowl:" + entity, ifcOwl.name(entity, attr)
|
||||
|
||||
class convertor(object):
|
||||
|
||||
@staticmethod
|
||||
def convert(item, *args, **kwargs):
|
||||
return getattr(convertor, item.__class__.__name__)(item, *args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def concept_or_applicability(concept):
|
||||
"""
|
||||
Convert the Template (SELECT ... WHERE {}) structure and TemplateRule (FILTER)
|
||||
|
||||
:param qtype: 0 or 1, 0 for a general query matching the applicableRootEntity
|
||||
:return:
|
||||
"""
|
||||
|
||||
bld = builder()
|
||||
t = concept.template()
|
||||
bld.append("# %s" % camel(concept.root.name))
|
||||
convertor.template(t, bld, concept.root.entity)
|
||||
bld.bind(STANDARD_PREFIXES)
|
||||
|
||||
return bld
|
||||
|
||||
@staticmethod
|
||||
def root(rootEntity):
|
||||
args = ["URI", "GlobalId"]
|
||||
|
||||
b = builder()
|
||||
b.args = args
|
||||
b.append("SELECT " + " ".join("?" + a for a in args) + " WHERE {")
|
||||
b.append("?URI", "rdf:type", "ifcowl:%s" % rootEntity)
|
||||
b.append("?URI", "ifcowl:globalId_IfcRoot/express:hasString", "?GlobalId")
|
||||
b.append("}")
|
||||
b.bind(STANDARD_PREFIXES)
|
||||
|
||||
return b
|
||||
|
||||
@staticmethod
|
||||
def template(template, bld = None, rootEntity = None):
|
||||
if bld is None:
|
||||
bld = builder()
|
||||
|
||||
if rootEntity is None:
|
||||
rootEntity = template.entity
|
||||
|
||||
args = ["URI", "GlobalId"]
|
||||
|
||||
def enumerate(rule, **kwargs):
|
||||
if rule.bind:
|
||||
args.append(rule.bind)
|
||||
|
||||
template.traverse(enumerate)
|
||||
|
||||
bld.args = args
|
||||
|
||||
bld.append("SELECT " + " ".join("?" + a for a in args) + " WHERE {")
|
||||
|
||||
args = set(args)
|
||||
|
||||
bld.append("?URI", "rdf:type", "ifcowl:%s" % rootEntity)
|
||||
bld.append("?URI", "ifcowl:globalId_IfcRoot/express:hasString", "?GlobalId")
|
||||
|
||||
nm = "?URI"
|
||||
ROOT = type('_', (), {'attribute': rootEntity})()
|
||||
# rule_stack = [ROOT]
|
||||
# name_stack = [nm]
|
||||
# callback_stack = [noop]
|
||||
# G = type('_', (object,), dict(indent = 0, nm = nm, next_nm=None, first=True))
|
||||
|
||||
rule_mapping = defaultdict(rule_binding)
|
||||
rule_mapping[ROOT].name = nm
|
||||
|
||||
def build(rule, parents):
|
||||
# print "AAA", rule.tag, parent.tag if parent else parent
|
||||
# print map(id, rule_stack)
|
||||
# print name_stack
|
||||
INDENT = " " * (len(parents) * 2)
|
||||
return_value = None
|
||||
|
||||
if rule.optional:
|
||||
bld.append(INDENT + "OPTIONAL {")
|
||||
return_value = lambda: bld.append(INDENT + "}")
|
||||
|
||||
if rule.tag == "EntityRule":
|
||||
# G.nm = G.next_nm
|
||||
|
||||
if not ifcOwl.is_select(rule.attribute):
|
||||
# SELECT types should never be qualified as they cannot be inferred
|
||||
bld.append(INDENT + rule_mapping[parents[-1]].name, "rdf:type", "ifcowl:" + rule.attribute)
|
||||
|
||||
# propagate binding name
|
||||
rule_mapping[rule].name = rule_mapping[parents[-1]].name
|
||||
else:
|
||||
|
||||
# if rule_stack[-1] is parent:
|
||||
# # print "sl", id(parent), id(rule)
|
||||
# # same level
|
||||
# pass
|
||||
# elif parent in rule_stack:
|
||||
# # print "up", id(parent), id(rule)
|
||||
# while rule_stack[-1] is not parent:
|
||||
# # rule_stack.pop()
|
||||
# name_stack.pop()
|
||||
# callback_stack.pop()()
|
||||
# else:
|
||||
# # print "dn", id(parent), id(rule)
|
||||
# pass
|
||||
|
||||
indirect = False
|
||||
|
||||
if rule.bind:
|
||||
if len(rule.nodes) == 1:
|
||||
indirect = ifcOwl.is_boxed(parents[-1].attribute, rule.attribute, predCount=bld.x())
|
||||
|
||||
if rule.bind and not indirect:
|
||||
next_nm = "?" + rule.bind
|
||||
else:
|
||||
next_nm = "?var%d" % bld.x()
|
||||
|
||||
rule_mapping[rule].name = next_nm
|
||||
|
||||
inventy, invattr = ifcOwl.is_inverse(parents[-1].attribute, rule.attribute)
|
||||
if invattr:
|
||||
# This seems not to be necessary, because the entity name is also stated in mvdXML
|
||||
# q.append(
|
||||
# next_nm,
|
||||
# "rdf:type",
|
||||
# inventy
|
||||
# )
|
||||
bld.append(
|
||||
INDENT + next_nm,
|
||||
invattr,
|
||||
rule_mapping[parents[-1]].name
|
||||
)
|
||||
else:
|
||||
bld.append(
|
||||
INDENT + rule_mapping[parents[-1]].name,
|
||||
ifcOwl.name(parents[-1].attribute, rule.attribute),
|
||||
next_nm
|
||||
)
|
||||
|
||||
if rule.bind and indirect:
|
||||
# For boxed literals, only strings atm
|
||||
bld.append(INDENT + next_nm, indirect, "?" + rule.bind)
|
||||
|
||||
# rule_stack.append(rule)
|
||||
# name_stack.append(next_nm)
|
||||
# if rule.optional:
|
||||
# callback_stack.append(lambda: q.append(INDENT+"}"))
|
||||
# else:
|
||||
# callback_stack.append(noop)
|
||||
|
||||
# print(q.statements[-1])
|
||||
|
||||
return return_value
|
||||
|
||||
template.traverse(build, root=ROOT, with_parents=True)
|
||||
|
||||
# while callback_stack:
|
||||
# callback_stack.pop()()
|
||||
|
||||
if template.params:
|
||||
bld.append(convertor.build_filter(template))
|
||||
|
||||
bld.append("}")
|
||||
|
||||
return bld
|
||||
|
||||
@staticmethod
|
||||
def build_filter(self):
|
||||
def v(p):
|
||||
if isinstance(p, mvdxml_expression.node):
|
||||
if p.b == "Value":
|
||||
if p.c.lower() in {'true', 'false'}:
|
||||
yield "(%s?%s)" % ("!" if p.c.lower() == "false" else "", p.a)
|
||||
else:
|
||||
yield "(?%s = %s)" % (p.a, p.c)
|
||||
elif p.b == "Exists":
|
||||
yield "(!isBLANK(?%s))" % p.a
|
||||
else:
|
||||
raise Exception("Unsupported " + p.b)
|
||||
elif isinstance(p, str):
|
||||
yield {
|
||||
"and": "&&",
|
||||
"or": "||",
|
||||
"not": "&& !"
|
||||
}[p.lower()]
|
||||
else:
|
||||
yield "("
|
||||
for q in p:
|
||||
yield from v(q)
|
||||
yield ")"
|
||||
|
||||
return "FILTER(%s)" % " ".join(v(self.params))
|
||||
|
||||
def infer_subtypes(ttlfn):
|
||||
# Disabled currently
|
||||
return ttlfn
|
||||
|
||||
if not os.path.exists(ttlfn + ".subclass.nt"):
|
||||
|
||||
print("Inferring supertype relationships")
|
||||
|
||||
import hashlib
|
||||
import rdflib
|
||||
|
||||
a = rdflib.namespace.RDF.type
|
||||
|
||||
# Hardly possible on Windows
|
||||
# graph = rdflib.Graph("Sleepycat")
|
||||
# graph.open("store", create=True)
|
||||
# graph.parse(ttlfn)
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from rdflib_sqlalchemy.store import SQLAlchemy
|
||||
|
||||
if os.path.exists("db.sqlite"):
|
||||
os.unlink("db.sqlite")
|
||||
|
||||
uri = rdflib.Literal("sqlite:///%(here)s/db.sqlite" % {"here": os.getcwd()})
|
||||
ident = rdflib.URIRef(hashlib.sha1(ttlfn.encode()).hexdigest())
|
||||
engine = create_engine(uri)
|
||||
store = SQLAlchemy(
|
||||
identifier=ident,
|
||||
engine=engine,
|
||||
)
|
||||
graph = rdflib.Graph(
|
||||
store,
|
||||
identifier=ident,
|
||||
)
|
||||
graph.open(uri, create=True)
|
||||
graph.parse(ttlfn, format="ttl")
|
||||
|
||||
# print out all the triples in the graph
|
||||
def _():
|
||||
for subject, predicate, object in graph:
|
||||
if predicate == a:
|
||||
for sup in ifcOwl.supertypes(object):
|
||||
yield subject, a, rdflib.URIRef(sup)
|
||||
|
||||
for stmt in list(_()):
|
||||
graph.add(stmt)
|
||||
|
||||
graph.serialize(destination=ttlfn + ".subclass.nt", format="nt")
|
||||
|
||||
ttlfn += ".subclass.nt"
|
||||
|
||||
if platform.system() == "Windows":
|
||||
JENA_SPARQL = os.path.join(os.environ.get("JENA_HOME"), "bat", "sparql.bat")
|
||||
else:
|
||||
JENA_SPARQL = "sparql"
|
||||
|
||||
class executor(object):
|
||||
@staticmethod
|
||||
def run(CR, fn, ttlfn):
|
||||
"""
|
||||
Generates SPARQL queries for the parsed MVD and executes on the building model
|
||||
|
||||
:param CR: A parsed concept root
|
||||
:param fn: A filename used as the prefix to store generate SPARQL queries to disk
|
||||
:param ttlfn: A filename for the LD representation of an IFC model
|
||||
:return:
|
||||
"""
|
||||
|
||||
def dict_to_list(headers):
|
||||
return lambda di: [di[h] for h in headers]
|
||||
|
||||
def execute(query, *args):
|
||||
sparqlfn = ".".join(itertools.chain([fn], map(str, args))) + ".sparql"
|
||||
with open(sparqlfn, "w") as f:
|
||||
print(query, file=f)
|
||||
|
||||
proc = subprocess.Popen(
|
||||
[JENA_SPARQL, "--data=" + ttlfn, "--query=" + sparqlfn, "--results=CSV"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = proc.communicate()
|
||||
|
||||
csvf = io.StringIO(stdout.decode('utf-8'))
|
||||
|
||||
return list(csv.DictReader(csvf))
|
||||
|
||||
root_query = convertor.root(CR.entity)
|
||||
roots = execute(root_query, 0)
|
||||
|
||||
print("\nFile contains %d elements of type %s" % (len(roots), CR.entity))
|
||||
|
||||
passing_all = {}
|
||||
|
||||
# for summary below
|
||||
num_columns = 0
|
||||
|
||||
try:
|
||||
# Full MVD with multiple concepts
|
||||
is_template = False
|
||||
concept_enumerator = list(itertools.chain([CR.applicability()], CR.concepts()))
|
||||
except:
|
||||
is_template = True
|
||||
concept_enumerator = [CR]
|
||||
|
||||
for ci, C in enumerate(concept_enumerator):
|
||||
|
||||
num_columns += 1
|
||||
|
||||
if is_template or ci > 1:
|
||||
print("\n%s" % C.name)
|
||||
else:
|
||||
print("\nApplicability")
|
||||
|
||||
query = convertor.convert(C)
|
||||
|
||||
print("\nSPARQL query")
|
||||
print("============")
|
||||
print(query)
|
||||
|
||||
passing = execute(query, ci, 1)
|
||||
passing_guids = set(r['GlobalId'] for r in passing)
|
||||
|
||||
print("\nElements passing")
|
||||
print(tabulate.tabulate(list(map(dict_to_list(query.args), passing)), query.args, tablefmt="grid"))
|
||||
|
||||
print("\nElements failing concept")
|
||||
hd = ["URI", "GlobalId"]
|
||||
print(tabulate.tabulate(
|
||||
list(map(dict_to_list(hd), [r for r in roots if r["GlobalId"] not in passing_guids])), hd,
|
||||
tablefmt="grid"))
|
||||
|
||||
passing_all[ci] = passing_guids
|
||||
|
||||
print("\nSummary")
|
||||
|
||||
for ci, C in enumerate(concept_enumerator):
|
||||
print("(%d) %s" % (ci+(0 if is_template else 0), C.name))
|
||||
|
||||
def get_stats(guid):
|
||||
v = lambda i: guid in passing_all[i]
|
||||
st = [guid] + ["x" if v(i) else "" for i in range(num_columns)]
|
||||
if not is_template:
|
||||
st += ["x" if not v(0) or all(v(i) for i in range(1, num_columns)) else " "]
|
||||
return st
|
||||
|
||||
hd = ["GlobalId"] + list(map(str, range(num_columns)))
|
||||
if not is_template:
|
||||
hd += ["Valid"]
|
||||
|
||||
print(tabulate.tabulate(list(map(get_stats, map(operator.itemgetter("GlobalId"), roots))), hd, tablefmt="grid"))
|
||||
Reference in New Issue
Block a user