mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
black ifcopenshell-python
This commit is contained in:
@@ -24,24 +24,20 @@ from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
|
||||
if hasattr(os, 'uname'):
|
||||
if hasattr(os, "uname"):
|
||||
platform_system = os.uname()[0].lower()
|
||||
else:
|
||||
platform_system = 'windows'
|
||||
platform_system = "windows"
|
||||
|
||||
if sys.maxsize == (1 << 31) - 1:
|
||||
platform_architecture = '32bit'
|
||||
platform_architecture = "32bit"
|
||||
else:
|
||||
platform_architecture = '64bit'
|
||||
platform_architecture = "64bit"
|
||||
|
||||
python_version_tuple = tuple(sys.version.split(' ')[0].split('.'))
|
||||
python_version_tuple = tuple(sys.version.split(" ")[0].split("."))
|
||||
|
||||
python_distribution = os.path.join(platform_system,
|
||||
platform_architecture,
|
||||
'python%s.%s' % python_version_tuple[:2])
|
||||
sys.path.append(os.path.abspath(os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'lib', python_distribution)))
|
||||
python_distribution = os.path.join(platform_system, platform_architecture, "python%s.%s" % python_version_tuple[:2])
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "lib", python_distribution)))
|
||||
|
||||
try:
|
||||
from . import ifcopenshell_wrapper
|
||||
@@ -51,7 +47,7 @@ except Exception as e:
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
print('-' * 64)
|
||||
print("-" * 64)
|
||||
raise ImportError("IfcOpenShell not built for '%s'" % python_distribution)
|
||||
|
||||
from . import guid
|
||||
@@ -66,17 +62,21 @@ def open(fn):
|
||||
else:
|
||||
raise IOError("Unable to open file for reading")
|
||||
|
||||
|
||||
def create_entity(type, *args, **kwargs):
|
||||
e = entity_instance(type)
|
||||
attrs = list(enumerate(args)) + \
|
||||
[(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
||||
attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
||||
for idx, arg in attrs:
|
||||
e[idx] = arg
|
||||
return e
|
||||
|
||||
|
||||
|
||||
gcroot = []
|
||||
|
||||
|
||||
def register_schema(schema):
|
||||
gcroot.append(schema)
|
||||
ifcopenshell_wrapper.register_schema(schema.schema)
|
||||
|
||||
|
||||
from .main import *
|
||||
|
||||
@@ -30,7 +30,7 @@ from . import ifcopenshell_wrapper
|
||||
try:
|
||||
import logging
|
||||
except ImportError as e:
|
||||
logging = type('logger', (object,), {'exception': staticmethod(lambda s: print(s))})
|
||||
logging = type("logger", (object,), {"exception": staticmethod(lambda s: print(s))})
|
||||
|
||||
|
||||
class entity_instance(object):
|
||||
@@ -47,22 +47,25 @@ class entity_instance(object):
|
||||
print(products[0].Representation)
|
||||
>>> #423=IfcProductDefinitionShape($,$,(#409,#421))
|
||||
"""
|
||||
|
||||
def __init__(self, e):
|
||||
if isinstance(e, tuple):
|
||||
e = ifcopenshell_wrapper.new_IfcBaseClass(*e)
|
||||
super(entity_instance, self).__setattr__('wrapped_data', e)
|
||||
super(entity_instance, self).__setattr__("wrapped_data", e)
|
||||
|
||||
def __getattr__(self, name):
|
||||
INVALID, FORWARD, INVERSE = range(3)
|
||||
attr_cat = self.wrapped_data.get_attribute_category(name)
|
||||
if attr_cat == FORWARD:
|
||||
return entity_instance.wrap_value(
|
||||
self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
|
||||
self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name))
|
||||
)
|
||||
elif attr_cat == INVERSE:
|
||||
return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
|
||||
else:
|
||||
raise AttributeError(
|
||||
"entity instance of type '%s' has no attribute '%s'" % (self.wrapped_data.is_a(), name))
|
||||
"entity instance of type '%s' has no attribute '%s'" % (self.wrapped_data.is_a(), name)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def walk(f, g, value):
|
||||
@@ -75,17 +78,21 @@ class entity_instance(object):
|
||||
|
||||
@staticmethod
|
||||
def wrap_value(v):
|
||||
def wrap(e): return entity_instance(e)
|
||||
def wrap(e):
|
||||
return entity_instance(e)
|
||||
|
||||
def is_instance(e): return isinstance(e, ifcopenshell_wrapper.entity_instance)
|
||||
def is_instance(e):
|
||||
return isinstance(e, ifcopenshell_wrapper.entity_instance)
|
||||
|
||||
return entity_instance.walk(is_instance, wrap, v)
|
||||
|
||||
@staticmethod
|
||||
def unwrap_value(v):
|
||||
def unwrap(e): return e.wrapped_data
|
||||
def unwrap(e):
|
||||
return e.wrapped_data
|
||||
|
||||
def is_instance(e): return isinstance(e, entity_instance)
|
||||
def is_instance(e):
|
||||
return isinstance(e, entity_instance)
|
||||
|
||||
return entity_instance.walk(is_instance, unwrap, v)
|
||||
|
||||
@@ -117,32 +124,36 @@ class entity_instance(object):
|
||||
return entity_instance.wrap_value(self.wrapped_data.get_argument(key))
|
||||
|
||||
def __setitem__(self, idx, value):
|
||||
attr_type = real_attr_type = self.attribute_type(idx).title().replace(' ', '')
|
||||
real_attr_type = real_attr_type.replace('Derived', 'None')
|
||||
attr_type = attr_type.replace('Binary', 'String')
|
||||
attr_type = attr_type.replace('Enumeration', 'String')
|
||||
|
||||
attr_type = real_attr_type = self.attribute_type(idx).title().replace(" ", "")
|
||||
real_attr_type = real_attr_type.replace("Derived", "None")
|
||||
attr_type = attr_type.replace("Binary", "String")
|
||||
attr_type = attr_type.replace("Enumeration", "String")
|
||||
|
||||
if value is None:
|
||||
if attr_type != "Derived":
|
||||
self.wrapped_data.setArgumentAsNull(idx)
|
||||
else:
|
||||
valid = attr_type != "Derived"
|
||||
if valid:
|
||||
if valid:
|
||||
try:
|
||||
if isinstance(value, unicode):
|
||||
value = value.encode("utf-8")
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
if attr_type != "Derived":
|
||||
getattr(self.wrapped_data, "setArgumentAs%s" % attr_type)(idx, entity_instance.unwrap_value(value))
|
||||
getattr(self.wrapped_data, "setArgumentAs%s" % attr_type)(
|
||||
idx, entity_instance.unwrap_value(value)
|
||||
)
|
||||
except BaseException as e:
|
||||
valid = False
|
||||
|
||||
if not valid:
|
||||
raise ValueError("Expected %s for attribute %s.%s, got %r" % (
|
||||
real_attr_type, self.is_a(), self.attribute_name(idx), value))
|
||||
raise ValueError(
|
||||
"Expected %s for attribute %s.%s, got %r"
|
||||
% (real_attr_type, self.is_a(), self.attribute_name(idx), value)
|
||||
)
|
||||
|
||||
return value
|
||||
|
||||
@@ -189,11 +200,15 @@ class entity_instance(object):
|
||||
return hash((self.id(), self.wrapped_data.file_pointer()))
|
||||
|
||||
def __dir__(self):
|
||||
return sorted(set(itertools.chain(
|
||||
dir(type(self)),
|
||||
map(str, self.wrapped_data.get_attribute_names()),
|
||||
map(str, self.wrapped_data.get_inverse_attribute_names())
|
||||
)))
|
||||
return sorted(
|
||||
set(
|
||||
itertools.chain(
|
||||
dir(type(self)),
|
||||
map(str, self.wrapped_data.get_attribute_names()),
|
||||
map(str, self.wrapped_data.get_inverse_attribute_names()),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def get_info(self, include_identifier=True, recursive=False, return_type=dict, ignore=()):
|
||||
"""Return a dictionary of the entity_instance's properties (Python and IFC) and their values.
|
||||
@@ -218,6 +233,7 @@ class entity_instance(object):
|
||||
>>> dict_keys(['Description', 'Name', 'BuildingAddress', 'LongName', 'GlobalId', 'ObjectPlacement', 'OwnerHistory', 'ObjectType',
|
||||
>>> ...'ElevationOfTerrain', 'CompositionType', 'id', 'Representation', 'type', 'ElevationOfRefHeight'])
|
||||
"""
|
||||
|
||||
def _():
|
||||
try:
|
||||
if include_identifier:
|
||||
@@ -231,18 +247,21 @@ class entity_instance(object):
|
||||
continue
|
||||
attr_value = self[i]
|
||||
if recursive:
|
||||
def is_instance(e): return isinstance(e, entity_instance)
|
||||
|
||||
def is_instance(e):
|
||||
return isinstance(e, entity_instance)
|
||||
|
||||
def get_info_(inst):
|
||||
# for ty in ignore:
|
||||
# if inst.is_a(ty):
|
||||
# return None
|
||||
return entity_instance.get_info(inst,
|
||||
include_identifier=include_identifier,
|
||||
recursive=recursive,
|
||||
return_type=return_type,
|
||||
ignore=ignore
|
||||
)
|
||||
return entity_instance.get_info(
|
||||
inst,
|
||||
include_identifier=include_identifier,
|
||||
recursive=recursive,
|
||||
return_type=return_type,
|
||||
ignore=ignore,
|
||||
)
|
||||
|
||||
attr_value = entity_instance.walk(is_instance, get_info_, attr_value)
|
||||
yield self.attribute_name(i), attr_value
|
||||
|
||||
@@ -10,11 +10,12 @@ exp_parser_fn = os.path.join(d, "express_parser.py")
|
||||
if not os.path.exists(exp_parser_fn):
|
||||
with open(exp_parser_fn, "w") as f:
|
||||
subprocess.call([sys.executable, "bootstrap.py"], cwd=d, stdout=f)
|
||||
|
||||
|
||||
import express_parser
|
||||
import schema_class
|
||||
import ifcopenshell.ifcopenshell_wrapper
|
||||
|
||||
|
||||
def parse(fn):
|
||||
mapping = express_parser.parse(fn)
|
||||
return schema_class.SchemaClass(mapping, schema_class.LateBoundSchemaInstantiator).code
|
||||
|
||||
@@ -25,47 +25,63 @@ import itertools
|
||||
|
||||
from pyparsing import *
|
||||
|
||||
try: from functools import reduce
|
||||
except: pass
|
||||
try:
|
||||
from functools import reduce
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
class Expression:
|
||||
def __init__(self, contents):
|
||||
self.contents = contents[0]
|
||||
|
||||
def __repr__(self):
|
||||
if self.op is None: return repr(self.contents)
|
||||
c = [isinstance(c,str) and c or str(c) for c in self.contents]
|
||||
if "%s" in self.op: return self.op % (" ".join(c))
|
||||
else: return "(%s)" % (" %s "%self.op).join(c)
|
||||
if self.op is None:
|
||||
return repr(self.contents)
|
||||
c = [isinstance(c, str) and c or str(c) for c in self.contents]
|
||||
if "%s" in self.op:
|
||||
return self.op % (" ".join(c))
|
||||
else:
|
||||
return "(%s)" % (" %s " % self.op).join(c)
|
||||
|
||||
def __iter__(self):
|
||||
return self.contents.__iter__()
|
||||
|
||||
|
||||
class Union(Expression):
|
||||
op = "|"
|
||||
|
||||
|
||||
class Concat(Expression):
|
||||
op = "+"
|
||||
|
||||
|
||||
class Optional(Expression):
|
||||
op = "Optional(%s)"
|
||||
|
||||
|
||||
class Repeated(Expression):
|
||||
op = "ZeroOrMore(%s)"
|
||||
|
||||
|
||||
class Term(Expression):
|
||||
op = None
|
||||
|
||||
|
||||
class Keyword:
|
||||
def __init__(self, contents):
|
||||
self.contents = contents[0]
|
||||
|
||||
def __repr__(self):
|
||||
return self.contents
|
||||
|
||||
|
||||
class Terminal:
|
||||
def __init__(self, contents):
|
||||
self.contents = contents[0]
|
||||
s = self.contents
|
||||
self.is_keyword = len(s) >= 4 and s[0::len(s)-1] == '""' and \
|
||||
all(c in alphanums+"_" for c in s[1:-1])
|
||||
self.is_keyword = len(s) >= 4 and s[0 :: len(s) - 1] == '""' and all(c in alphanums + "_" for c in s[1:-1])
|
||||
|
||||
def __repr__(self):
|
||||
ty = "CaselessKeyword" if self.is_keyword else "CaselessLiteral"
|
||||
return "%s(%s)" % (ty, self.contents)
|
||||
@@ -78,31 +94,33 @@ RBRACK = Suppress("]")
|
||||
LBRACE = Suppress("{")
|
||||
RBRACE = Suppress("}")
|
||||
EQUALS = Suppress("=")
|
||||
VBAR = Suppress("|")
|
||||
VBAR = Suppress("|")
|
||||
PERIOD = Suppress(".")
|
||||
HASH = Suppress("#")
|
||||
HASH = Suppress("#")
|
||||
|
||||
identifier = Word(alphanums+"_")
|
||||
keyword = Word(alphanums+"_").setParseAction(Keyword)
|
||||
identifier = Word(alphanums + "_")
|
||||
keyword = Word(alphanums + "_").setParseAction(Keyword)
|
||||
expression = Forward()
|
||||
optional = Group(LBRACK + expression + RBRACK).setParseAction(Optional)
|
||||
repeated = Group(LBRACE + expression + RBRACE).setParseAction(Repeated)
|
||||
terminal = quotedString.setParseAction(Terminal)
|
||||
term = (keyword | terminal | optional | repeated | (LPAREN + expression + RPAREN)).setParseAction(Term)
|
||||
concat = Group(term + OneOrMore(term)).setParseAction(Concat)
|
||||
factor = concat | term
|
||||
union = Group(factor + OneOrMore(VBAR + factor)).setParseAction(Union)
|
||||
rule = identifier + EQUALS + expression + PERIOD
|
||||
optional = Group(LBRACK + expression + RBRACK).setParseAction(Optional)
|
||||
repeated = Group(LBRACE + expression + RBRACE).setParseAction(Repeated)
|
||||
terminal = quotedString.setParseAction(Terminal)
|
||||
term = (keyword | terminal | optional | repeated | (LPAREN + expression + RPAREN)).setParseAction(Term)
|
||||
concat = Group(term + OneOrMore(term)).setParseAction(Concat)
|
||||
factor = concat | term
|
||||
union = Group(factor + OneOrMore(VBAR + factor)).setParseAction(Union)
|
||||
rule = identifier + EQUALS + expression + PERIOD
|
||||
|
||||
expression << (union | factor)
|
||||
|
||||
grammar = OneOrMore(Group(rule))
|
||||
grammar.ignore(HASH + restOfLine)
|
||||
|
||||
express = grammar.parseFile(os.path.join(os.path.dirname(__file__), 'express.bnf'))
|
||||
express = grammar.parseFile(os.path.join(os.path.dirname(__file__), "express.bnf"))
|
||||
|
||||
def find_bytype(expr, ty, li = None):
|
||||
if li is None: li = []
|
||||
|
||||
def find_bytype(expr, ty, li=None):
|
||||
if li is None:
|
||||
li = []
|
||||
if isinstance(expr, Term):
|
||||
expr = expr.contents
|
||||
if isinstance(expr, ty):
|
||||
@@ -113,34 +131,35 @@ def find_bytype(expr, ty, li = None):
|
||||
find_bytype(term, ty, li)
|
||||
return set(li)
|
||||
|
||||
|
||||
actions = {
|
||||
'type_decl' : "TypeDeclaration",
|
||||
'entity_decl' : "EntityDeclaration",
|
||||
'enumeration_type' : "EnumerationType",
|
||||
'aggregation_types' : "AggregationType",
|
||||
'general_aggregation_types' : "AggregationType",
|
||||
'select_type' : "SelectType",
|
||||
'binary_type' : "BinaryType",
|
||||
'subtype_declaration' : "SubTypeExpression",
|
||||
'supertype_constraint' : "SuperTypeExpression",
|
||||
'derive_clause' : "AttributeList",
|
||||
'inverse_clause' : "AttributeList",
|
||||
'inverse_attr' : "InverseAttribute",
|
||||
'bound_spec' : "BoundSpecification",
|
||||
'explicit_attr' : "ExplicitAttribute",
|
||||
'width_spec' : "WidthSpec",
|
||||
'string_type' : "StringType",
|
||||
'named_types' : "NamedType",
|
||||
'simple_types' : "SimpleType",
|
||||
"type_decl": "TypeDeclaration",
|
||||
"entity_decl": "EntityDeclaration",
|
||||
"enumeration_type": "EnumerationType",
|
||||
"aggregation_types": "AggregationType",
|
||||
"general_aggregation_types": "AggregationType",
|
||||
"select_type": "SelectType",
|
||||
"binary_type": "BinaryType",
|
||||
"subtype_declaration": "SubTypeExpression",
|
||||
"supertype_constraint": "SuperTypeExpression",
|
||||
"derive_clause": "AttributeList",
|
||||
"inverse_clause": "AttributeList",
|
||||
"inverse_attr": "InverseAttribute",
|
||||
"bound_spec": "BoundSpecification",
|
||||
"explicit_attr": "ExplicitAttribute",
|
||||
"width_spec": "WidthSpec",
|
||||
"string_type": "StringType",
|
||||
"named_types": "NamedType",
|
||||
"simple_types": "SimpleType",
|
||||
}
|
||||
|
||||
to_emit = set(id for id, expr in express)
|
||||
emitted = set()
|
||||
to_combine = set(["simple_id"])
|
||||
statements = []
|
||||
|
||||
terminals = reduce(lambda x,y: x | y, (find_bytype(e, Terminal) for id, e in express))
|
||||
keywords = list(filter(operator.attrgetter('is_keyword'), terminals))
|
||||
|
||||
terminals = reduce(lambda x, y: x | y, (find_bytype(e, Terminal) for id, e in express))
|
||||
keywords = list(filter(operator.attrgetter("is_keyword"), terminals))
|
||||
negated_keywords = map(lambda s: "~%s" % s, keywords)
|
||||
no_action = {"letter", "digit", "digits", "real_literal", "integer_literal"}
|
||||
|
||||
@@ -157,14 +176,15 @@ while True:
|
||||
stmt = " + ".join(itertools.chain(negated_keywords, ("originalTextFor(Combine%s)" % stmt,)))
|
||||
if id not in no_action and not isinstance(expr.contents, Keyword) and not id in to_combine:
|
||||
node_type = "ListNode" if "ZeroOrMore" in stmt else "Node"
|
||||
action = actions.get(id, "lambda s, loc, t: %s(s, loc, t, rule=\"%s\")" % (node_type, id))
|
||||
action = actions.get(id, 'lambda s, loc, t: %s(s, loc, t, rule="%s")' % (node_type, id))
|
||||
stmt = "%s.setParseAction(%s)" % (stmt, action)
|
||||
statements.append("%s = %s(\"%s\")" % (id, stmt, id))
|
||||
statements.append('%s = %s("%s")' % (id, stmt, id))
|
||||
to_emit -= emitted_in_loop
|
||||
if not emitted_in_loop: break
|
||||
if not emitted_in_loop:
|
||||
break
|
||||
|
||||
for id in to_emit:
|
||||
statements.append("%s = Forward()(\"%s\")" % (id, id))
|
||||
statements.append('%s = Forward()("%s")' % (id, id))
|
||||
|
||||
for id in to_emit:
|
||||
expr = [e for k, e in express if k == id][0]
|
||||
@@ -173,11 +193,14 @@ for id in to_emit:
|
||||
stmt = "Suppress%s" % stmt
|
||||
if id not in no_action and not isinstance(expr.contents, Keyword):
|
||||
node_type = "ListNode" if "ZeroOrMore" in stmt else "Node"
|
||||
action = ".setParseAction(%s)" % (actions[id] if id in actions else "lambda s, loc, t: %s(s, loc, t, rule=\"%s\")" % (node_type, id))
|
||||
action = ".setParseAction(%s)" % (
|
||||
actions[id] if id in actions else 'lambda s, loc, t: %s(s, loc, t, rule="%s")' % (node_type, id)
|
||||
)
|
||||
stmt = "(%s)%s" % (stmt, action)
|
||||
statements.append("%s << %s" % (id, stmt))
|
||||
|
||||
print ("""
|
||||
print(
|
||||
"""
|
||||
# This file is generated by IfcOpenShell ifcexpressparser bootstrap.py
|
||||
|
||||
import os
|
||||
@@ -215,4 +238,6 @@ if __name__ == "__main__":
|
||||
mdl = importlib.import_module(output)
|
||||
mdl.Generator(m).emit()
|
||||
sys.stdout.write(m.schema.name)
|
||||
"""%('\n '.join(statements)))
|
||||
"""
|
||||
% ("\n ".join(statements))
|
||||
)
|
||||
|
||||
@@ -17,19 +17,23 @@
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
|
||||
class Base(object):
|
||||
"""
|
||||
A base class for all code generation classes. Currently only working around
|
||||
some python 2/3 incompatibilities in terms of unicode file handling.
|
||||
"""
|
||||
|
||||
def emit(self):
|
||||
import platform
|
||||
|
||||
if tuple(map(int, platform.python_version_tuple())) < (2, 8):
|
||||
from io import open as unicode_open
|
||||
|
||||
unicode_type = unicode
|
||||
else:
|
||||
unicode_open = open
|
||||
unicode_type = lambda x, *args, **kwargs: x
|
||||
f = unicode_open(self.file_name, 'w', encoding='utf-8')
|
||||
f.write(unicode_type(repr(self), encoding='utf-8', errors='ignore'))
|
||||
f = unicode_open(self.file_name, "w", encoding="utf-8")
|
||||
f.write(unicode_type(repr(self), encoding="utf-8", errors="ignore"))
|
||||
f.close()
|
||||
|
||||
@@ -24,45 +24,47 @@ import codegen
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class Definitions(codegen.Base):
|
||||
def __init__(self, mapping):
|
||||
|
||||
|
||||
schema_name = mapping.schema.name
|
||||
self.schema_name = schema_name_title = schema_name.capitalize()
|
||||
|
||||
statements = ['']
|
||||
|
||||
|
||||
statements = [""]
|
||||
|
||||
def write_entity(schema_name, name, type):
|
||||
|
||||
|
||||
attribute_names = list(map(lambda t: (t.name, t.optional), type.attributes))
|
||||
for attr, is_optional in attribute_names:
|
||||
statements.append("#define SCHEMA_%(name)s_HAS_%(attr)s" % locals())
|
||||
if is_optional:
|
||||
statements.append("#define SCHEMA_%(name)s_%(attr)s_IS_OPTIONAL" % locals())
|
||||
inverse_attribute_names = list(map(operator.attrgetter('name'), type.inverse))
|
||||
inverse_attribute_names = list(map(operator.attrgetter("name"), type.inverse))
|
||||
for attr in inverse_attribute_names:
|
||||
statements.append("#define SCHEMA_%(name)s_HAS_%(attr)s" % locals())
|
||||
|
||||
|
||||
def write(name):
|
||||
statements.append("#define SCHEMA_HAS_%(name)s" % locals())
|
||||
fn = None
|
||||
if mapping.schema.is_entity(name):
|
||||
fn = write_entity
|
||||
|
||||
|
||||
if fn is not None:
|
||||
decl = mapping.schema[name]
|
||||
if isinstance(decl, nodes.TypeDeclaration):
|
||||
decl = decl.type.type
|
||||
fn(schema_name, name, decl) is not False
|
||||
|
||||
|
||||
for name in mapping.schema:
|
||||
write(name)
|
||||
|
||||
|
||||
self.str = "\n".join(statements) + "\n"
|
||||
|
||||
self.file_name = '%s-definitions.h' % self.schema_name
|
||||
|
||||
self.file_name = "%s-definitions.h" % self.schema_name
|
||||
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
|
||||
|
||||
Generator = Definitions
|
||||
|
||||
@@ -31,10 +31,12 @@ import re
|
||||
import os
|
||||
import csv
|
||||
|
||||
from schema import OrderedCaseInsensitiveDict
|
||||
from schema import OrderedCaseInsensitiveDict
|
||||
|
||||
try: from html.entities import entitydefs
|
||||
except: from htmlentitydefs import entitydefs
|
||||
try:
|
||||
from html.entities import entitydefs
|
||||
except:
|
||||
from htmlentitydefs import entitydefs
|
||||
|
||||
make_absolute = lambda fn: os.path.join(os.path.dirname(os.path.realpath(__file__)), fn)
|
||||
|
||||
@@ -42,36 +44,45 @@ name_to_oid = OrderedCaseInsensitiveDict()
|
||||
oid_to_desc = {}
|
||||
oid_to_name = {}
|
||||
oid_to_pid = {}
|
||||
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+']],['','\n\n',' ']))
|
||||
regices = list(
|
||||
zip(
|
||||
[re.compile(s, re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>', r"(\n[\t ]*){2,}", r"^[\t ]+"]],
|
||||
["", "\n\n", " "],
|
||||
)
|
||||
)
|
||||
|
||||
definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv']
|
||||
definition_files = ["DocEntity.csv", "DocEnumeration.csv", "DocDefined.csv", "DocSelect.csv"]
|
||||
definition_files = map(make_absolute, definition_files)
|
||||
for fn in definition_files:
|
||||
with open(fn, encoding="utf8", errors='ignore') as f:
|
||||
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
|
||||
with open(fn, encoding="utf8", errors="ignore") as f:
|
||||
for oid, name, desc in csv.reader(f, delimiter=";", quotechar='"'):
|
||||
name_to_oid[name] = oid
|
||||
oid_to_name[oid] = name
|
||||
oid_to_desc[oid] = desc
|
||||
|
||||
with open(make_absolute('DocEntityAttributes.csv')) as f:
|
||||
for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'):
|
||||
with open(make_absolute("DocEntityAttributes.csv")) as f:
|
||||
for pid, x, oid in csv.reader(f, delimiter=";", quotechar='"'):
|
||||
oid_to_pid[oid] = pid
|
||||
|
||||
with open(make_absolute('DocAttribute.csv')) as f:
|
||||
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
|
||||
with open(make_absolute("DocAttribute.csv")) as f:
|
||||
for oid, name, desc in csv.reader(f, delimiter=";", quotechar='"'):
|
||||
pid = oid_to_pid[oid]
|
||||
pname = oid_to_name[pid]
|
||||
name_to_oid[".".join((pname, name))] = oid
|
||||
oid_to_desc[oid] = desc
|
||||
|
||||
|
||||
def description(item):
|
||||
global name_to_oid, oid_to_desc, oid_to_name, oid_to_pid
|
||||
oid = name_to_oid.get(item,0)
|
||||
oid = name_to_oid.get(item, 0)
|
||||
desc = oid_to_desc.get(oid, None)
|
||||
if desc:
|
||||
for a,b in entitydefs.items(): desc = desc.replace("&%s;"%a,b)
|
||||
desc = desc.replace("\r","")
|
||||
for r,s in regices: desc = r.sub(s,desc)
|
||||
for a, b in entitydefs.items():
|
||||
desc = desc.replace("&%s;" % a, b)
|
||||
desc = desc.replace("\r", "")
|
||||
for r, s in regices:
|
||||
desc = r.sub(s, desc)
|
||||
desc = desc.strip()
|
||||
return desc.split("\n")
|
||||
else: return []
|
||||
else:
|
||||
return []
|
||||
|
||||
@@ -23,31 +23,35 @@ import codegen
|
||||
import templates
|
||||
import documentation
|
||||
|
||||
|
||||
class Header(codegen.Base):
|
||||
def __init__(self, mapping):
|
||||
declarations = []
|
||||
|
||||
write = lambda str, **kwargs: declarations.append(str%dict({
|
||||
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
|
||||
|
||||
write = lambda str, **kwargs: declarations.append(
|
||||
str
|
||||
% dict({"documentation": templates.multi_line_comment(documentation.description(kwargs["name"]))}, **kwargs)
|
||||
)
|
||||
|
||||
forward_names = list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys())
|
||||
forward_definitions = "".join(["class %s; "%n for n in forward_names])
|
||||
|
||||
forward_definitions = "".join(["class %s; " % n for n in forward_names])
|
||||
|
||||
for name, type in mapping.schema.selects.items():
|
||||
write(templates.select, name=name)
|
||||
|
||||
for name, type in mapping.schema.enumerations.items():
|
||||
short_name = name[:-4] if name.endswith("Enum") else name
|
||||
write(templates.enumeration, name=name, values=", ".join(["%s_%s"%(short_name, v) for v in type.values]))
|
||||
|
||||
write(templates.enumeration, name=name, values=", ".join(["%s_%s" % (short_name, v) for v in type.values]))
|
||||
|
||||
emitted_simpletypes = set()
|
||||
while len(emitted_simpletypes) < len(mapping.schema.simpletypes):
|
||||
for name, type in mapping.schema.simpletypes.items():
|
||||
if name.lower() in emitted_simpletypes: continue
|
||||
if name.lower() in emitted_simpletypes:
|
||||
continue
|
||||
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
|
||||
attr_type = mapping.make_argument_type(type)
|
||||
superclass = mapping.simple_type_parent(name)
|
||||
if superclass is None:
|
||||
if superclass is None:
|
||||
superclass = "IfcUtil::IfcBaseType"
|
||||
elif superclass.lower() not in emitted_simpletypes:
|
||||
continue
|
||||
@@ -59,91 +63,154 @@ class Header(codegen.Base):
|
||||
|
||||
class_definitions = []
|
||||
|
||||
write = lambda str, **kwargs: class_definitions.append(str%dict({
|
||||
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
|
||||
write = lambda str, **kwargs: class_definitions.append(
|
||||
str
|
||||
% dict({"documentation": templates.multi_line_comment(documentation.description(kwargs["name"]))}, **kwargs)
|
||||
)
|
||||
|
||||
emitted_entities = set()
|
||||
while len(emitted_entities) < len(mapping.schema.entities):
|
||||
for name, type in mapping.schema.entities.items():
|
||||
if name.lower() in emitted_entities: continue
|
||||
if name.lower() in emitted_entities:
|
||||
continue
|
||||
if len(type.supertypes) == 0 or set(map(str.lower, type.supertypes)) <= emitted_entities:
|
||||
attr_lines = []
|
||||
|
||||
def write_method(attr):
|
||||
if attr.optional:
|
||||
attr_lines.append(templates.optional_attribute_description % (attr.name, name))
|
||||
attr_lines.append("bool has%s() const;"%(attr.name))
|
||||
attr_lines.extend(["/// %s"%d for d in documentation.description(".".join((name, attr.name)))])
|
||||
attr_lines.append("bool has%s() const;" % (attr.name))
|
||||
attr_lines.extend(
|
||||
["/// %s" % d for d in documentation.description(".".join((name, attr.name)))]
|
||||
)
|
||||
type_str = mapping.get_parameter_type(attr, allow_optional=False, allow_entities=False)
|
||||
if mapping.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN":
|
||||
attr_lines.append("%s %s() const;"%(type_str, attr.name))
|
||||
attr_lines.append("void set%s(%s v);"%(attr.name, type_str))
|
||||
attr_lines.append("%s %s() const;" % (type_str, attr.name))
|
||||
attr_lines.append("void set%s(%s v);" % (attr.name, type_str))
|
||||
|
||||
[write_method(attr) for attr in type.attributes]
|
||||
|
||||
inv_lines = []
|
||||
|
||||
def write_inverse(attr):
|
||||
inv_lines.append(templates.inverse_attr%{'name':attr.name, 'entity':attr.entity, 'attribute':attr.attribute})
|
||||
inv_lines.append(
|
||||
templates.inverse_attr
|
||||
% {"name": attr.name, "entity": attr.entity, "attribute": attr.attribute}
|
||||
)
|
||||
|
||||
if type.inverse:
|
||||
[write_inverse(attr) for attr in type.inverse]
|
||||
|
||||
attributes = "\n".join(["%s%s"%(' '*4, a) for a in attr_lines])
|
||||
if len(attributes): attributes += '\n'
|
||||
attributes = "\n".join(["%s%s" % (" " * 4, a) for a in attr_lines])
|
||||
if len(attributes):
|
||||
attributes += "\n"
|
||||
|
||||
inverse = "\n".join(["%s%s"%(' '*4, a) for a in inv_lines])
|
||||
if len(inverse): inverse += '\n'
|
||||
inverse = "\n".join(["%s%s" % (" " * 4, a) for a in inv_lines])
|
||||
if len(inverse):
|
||||
inverse += "\n"
|
||||
|
||||
def case_norm(n):
|
||||
n = n.lower()
|
||||
return [k for k in mapping.schema.entities.keys() if k.lower() == n][0]
|
||||
|
||||
supertypes = map(case_norm, type.supertypes) if len(type.supertypes) else ['IfcUtil::IfcBaseEntity']
|
||||
superclass = ": %s "%(", ".join(["public %s"%c for c in supertypes]))
|
||||
|
||||
supertypes = map(case_norm, type.supertypes) if len(type.supertypes) else ["IfcUtil::IfcBaseEntity"]
|
||||
superclass = ": %s " % (", ".join(["public %s" % c for c in supertypes]))
|
||||
|
||||
argument_count = mapping.argument_count(type)
|
||||
|
||||
argument_start = argument_count - len(type.attributes)
|
||||
|
||||
argument_name_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return "%s"; '%(i+argument_start, attr.name) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
|
||||
argument_name_function_body_tail = (" return %s::getArgumentName(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
|
||||
argument_name_function_body_switch_stmt = (
|
||||
" switch (i) {%s}"
|
||||
% (
|
||||
"".join(
|
||||
[
|
||||
'case %d: return "%s"; ' % (i + argument_start, attr.name)
|
||||
for i, attr in enumerate(type.attributes)
|
||||
]
|
||||
)
|
||||
)
|
||||
if len(type.attributes)
|
||||
else ""
|
||||
)
|
||||
argument_name_function_body_tail = (
|
||||
(" return %s::getArgumentName(i); " % type.supertypes[0])
|
||||
if len(type.supertypes) == 1
|
||||
else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
|
||||
)
|
||||
|
||||
argument_name_function_body = (
|
||||
argument_name_function_body_switch_stmt + argument_name_function_body_tail
|
||||
)
|
||||
|
||||
argument_name_function_body = argument_name_function_body_switch_stmt + argument_name_function_body_tail
|
||||
|
||||
derived = mapping.derived_in_supertype(type)
|
||||
attribute_names = list(map(operator.attrgetter('name'), mapping.arguments(type)))
|
||||
attribute_names = list(map(operator.attrgetter("name"), mapping.arguments(type)))
|
||||
derived_in_supertype = set(derived) & set(attribute_names)
|
||||
derived_in_supertype_indices = sorted(attribute_names.index(nm) for nm in derived_in_supertype)
|
||||
attribute_type_cases = ['case %d: return IfcUtil::Argument_DERIVED; ' % idx for idx in derived_in_supertype_indices]
|
||||
attribute_type_cases += ['case %d: return %s; '%(i+argument_start, mapping.make_argument_type(attr)) for i, attr in enumerate(type.attributes)]
|
||||
argument_type_function_body_switch_stmt = " switch (i) {%s}"%("".join(attribute_type_cases)) if len(type.attributes) else ""
|
||||
argument_type_function_body_tail = (" return %s::getArgumentType(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
|
||||
attribute_type_cases = [
|
||||
"case %d: return IfcUtil::Argument_DERIVED; " % idx for idx in derived_in_supertype_indices
|
||||
]
|
||||
attribute_type_cases += [
|
||||
"case %d: return %s; " % (i + argument_start, mapping.make_argument_type(attr))
|
||||
for i, attr in enumerate(type.attributes)
|
||||
]
|
||||
argument_type_function_body_switch_stmt = (
|
||||
" switch (i) {%s}" % ("".join(attribute_type_cases)) if len(type.attributes) else ""
|
||||
)
|
||||
argument_type_function_body_tail = (
|
||||
(" return %s::getArgumentType(i); " % type.supertypes[0])
|
||||
if len(type.supertypes) == 1
|
||||
else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
|
||||
)
|
||||
|
||||
argument_type_function_body = argument_type_function_body_switch_stmt + argument_type_function_body_tail
|
||||
|
||||
argument_entity_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return %s; '%(i+argument_start, mapping.make_argument_entity(attr)) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
|
||||
argument_entity_function_body_tail = (" return %s::getArgumentEntity(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
|
||||
argument_type_function_body = (
|
||||
argument_type_function_body_switch_stmt + argument_type_function_body_tail
|
||||
)
|
||||
|
||||
argument_entity_function_body = argument_entity_function_body_switch_stmt + argument_entity_function_body_tail
|
||||
argument_entity_function_body_switch_stmt = (
|
||||
" switch (i) {%s}"
|
||||
% (
|
||||
"".join(
|
||||
[
|
||||
"case %d: return %s; " % (i + argument_start, mapping.make_argument_entity(attr))
|
||||
for i, attr in enumerate(type.attributes)
|
||||
]
|
||||
)
|
||||
)
|
||||
if len(type.attributes)
|
||||
else ""
|
||||
)
|
||||
argument_entity_function_body_tail = (
|
||||
(" return %s::getArgumentEntity(i); " % type.supertypes[0])
|
||||
if len(type.supertypes) == 1
|
||||
else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); '
|
||||
)
|
||||
|
||||
constructor_arguments = ", ".join("%(full_type)s v%(index)d_%(name)s"%a for a in mapping.get_assignable_arguments(type))
|
||||
argument_entity_function_body = (
|
||||
argument_entity_function_body_switch_stmt + argument_entity_function_body_tail
|
||||
)
|
||||
|
||||
constructor_arguments = ", ".join(
|
||||
"%(full_type)s v%(index)d_%(name)s" % a for a in mapping.get_assignable_arguments(type)
|
||||
)
|
||||
|
||||
write(templates.entity, **locals())
|
||||
emitted_entities.add(name)
|
||||
|
||||
self.str = templates.header % {
|
||||
'schema_name_upper' : mapping.schema.name.upper(),
|
||||
'schema_name' : mapping.schema.name.capitalize(),
|
||||
'declarations' : ''.join(declarations),
|
||||
'forward_definitions' : forward_definitions,
|
||||
'class_definitions' : ''.join(class_definitions)
|
||||
"schema_name_upper": mapping.schema.name.upper(),
|
||||
"schema_name": mapping.schema.name.capitalize(),
|
||||
"declarations": "".join(declarations),
|
||||
"forward_definitions": forward_definitions,
|
||||
"class_definitions": "".join(class_definitions),
|
||||
}
|
||||
|
||||
self.schema_name = mapping.schema.name.capitalize()
|
||||
|
||||
self.file_name = '%s.h'%self.schema_name
|
||||
|
||||
|
||||
|
||||
self.file_name = "%s.h" % self.schema_name
|
||||
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
|
||||
|
||||
Generator = Header
|
||||
|
||||
@@ -22,6 +22,7 @@ import templates
|
||||
|
||||
from schema import OrderedCaseInsensitiveDict
|
||||
|
||||
|
||||
class Implementation(codegen.Base):
|
||||
def __init__(self, mapping):
|
||||
enumeration_functions = []
|
||||
@@ -31,230 +32,324 @@ class Implementation(codegen.Base):
|
||||
schema_name = mapping.schema.name.capitalize()
|
||||
schema_name_upper = mapping.schema.name.upper()
|
||||
|
||||
stringify = lambda s: '"%s"'%s
|
||||
stringify = lambda s: '"%s"' % s
|
||||
cat = lambda vs: "".join(vs)
|
||||
catc = lambda vs: ", ".join(vs)
|
||||
catnl = lambda vs: "\n".join(vs)
|
||||
cator = lambda vs: " || ".join(vs)
|
||||
nl = lambda s: "%s\n"%s if len(s) else s
|
||||
nl = lambda s: "%s\n" % s if len(s) else s
|
||||
|
||||
write = lambda str, **kwargs: enumeration_functions.append(str%kwargs)
|
||||
write = lambda str, **kwargs: enumeration_functions.append(str % kwargs)
|
||||
|
||||
for name, enum in mapping.schema.enumerations.items():
|
||||
short_name = name[:-4] if name.endswith("Enum") else name
|
||||
context = locals()
|
||||
write(
|
||||
templates.enumeration_function,
|
||||
max_id = len(enum.values),
|
||||
name = name,
|
||||
schema_name = schema_name,
|
||||
schema_name_upper = schema_name_upper,
|
||||
values = catc(map(stringify, enum.values)),
|
||||
from_string_statements = catnl(templates.enum_from_string_stmt%dict(context,**locals()) for value in enum.values)
|
||||
max_id=len(enum.values),
|
||||
name=name,
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
values=catc(map(stringify, enum.values)),
|
||||
from_string_statements=catnl(
|
||||
templates.enum_from_string_stmt % dict(context, **locals()) for value in enum.values
|
||||
),
|
||||
)
|
||||
|
||||
write = lambda str, **kwargs: entity_implementations.append(str%kwargs)
|
||||
write = lambda str, **kwargs: entity_implementations.append(str % kwargs)
|
||||
|
||||
for name, type in mapping.schema.entities.items():
|
||||
parent_type_test = "" if not type.supertypes or len(type.supertypes) != 1 \
|
||||
else templates.parent_type_test%(type.supertypes[0])
|
||||
|
||||
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
|
||||
constructor_arguments_str = catc("%(full_type)s v%(index)d_%(name)s"%a for a in constructor_arguments if not a['is_derived'])
|
||||
for name, type in mapping.schema.entities.items():
|
||||
parent_type_test = (
|
||||
""
|
||||
if not type.supertypes or len(type.supertypes) != 1
|
||||
else templates.parent_type_test % (type.supertypes[0])
|
||||
)
|
||||
|
||||
constructor_arguments = mapping.get_assignable_arguments(type, include_derived=True)
|
||||
constructor_arguments_str = catc(
|
||||
"%(full_type)s v%(index)d_%(name)s" % a for a in constructor_arguments if not a["is_derived"]
|
||||
)
|
||||
attributes = []
|
||||
constructor_implementations = []
|
||||
write_attr = lambda str, **kwargs: attributes.append(str%kwargs)
|
||||
write_attr = lambda str, **kwargs: attributes.append(str % kwargs)
|
||||
for arg in constructor_arguments:
|
||||
if not arg['is_inherited'] and not arg['is_derived']:
|
||||
if arg['is_optional']:
|
||||
if not arg["is_inherited"] and not arg["is_derived"]:
|
||||
if arg["is_optional"]:
|
||||
write_attr(
|
||||
templates.const_function,
|
||||
class_name = name,
|
||||
schema_name = schema_name,
|
||||
schema_name_upper = schema_name_upper,
|
||||
name = 'has%s'%arg['name'],
|
||||
arguments = '',
|
||||
return_type = 'bool',
|
||||
body = templates.optional_attr_stmt % {'index':arg['index']-1}
|
||||
class_name=name,
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
name="has%s" % arg["name"],
|
||||
arguments="",
|
||||
return_type="bool",
|
||||
body=templates.optional_attr_stmt % {"index": arg["index"] - 1},
|
||||
)
|
||||
|
||||
|
||||
def find_template(arg):
|
||||
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
|
||||
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
|
||||
express = mapping.flatten_type_string(arg['list_instance_type']) in mapping.express_to_cpp_typemapping
|
||||
if arg['is_enum']: return templates.get_attr_stmt_enum
|
||||
elif arg['is_nested'] and arg['is_templated_list']: return templates.get_attr_stmt_nested_array
|
||||
elif arg['is_templated_list'] and not (select or simple or express): return templates.get_attr_stmt_array
|
||||
elif arg['non_optional_type'].endswith('*'): return templates.get_attr_stmt_entity
|
||||
else: return templates.get_attr_stmt
|
||||
simple = mapping.schema.is_simpletype(arg["list_instance_type"])
|
||||
select = arg["list_instance_type"] == "IfcUtil::IfcBaseClass"
|
||||
express = (
|
||||
mapping.flatten_type_string(arg["list_instance_type"]) in mapping.express_to_cpp_typemapping
|
||||
)
|
||||
if arg["is_enum"]:
|
||||
return templates.get_attr_stmt_enum
|
||||
elif arg["is_nested"] and arg["is_templated_list"]:
|
||||
return templates.get_attr_stmt_nested_array
|
||||
elif arg["is_templated_list"] and not (select or simple or express):
|
||||
return templates.get_attr_stmt_array
|
||||
elif arg["non_optional_type"].endswith("*"):
|
||||
return templates.get_attr_stmt_entity
|
||||
else:
|
||||
return templates.get_attr_stmt
|
||||
|
||||
tmpl = find_template(arg)
|
||||
write_attr(
|
||||
templates.const_function,
|
||||
class_name = name,
|
||||
name = arg['name'],
|
||||
arguments = '',
|
||||
schema_name = schema_name,
|
||||
schema_name_upper = schema_name_upper,
|
||||
return_type = arg['non_optional_type'],
|
||||
body = tmpl % {'index': arg['index']-1,
|
||||
'type' : arg['non_optional_type'].replace('::Value', ''),
|
||||
'list_instance_type' : arg['list_instance_type']}
|
||||
class_name=name,
|
||||
name=arg["name"],
|
||||
arguments="",
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
return_type=arg["non_optional_type"],
|
||||
body=tmpl
|
||||
% {
|
||||
"index": arg["index"] - 1,
|
||||
"type": arg["non_optional_type"].replace("::Value", ""),
|
||||
"list_instance_type": arg["list_instance_type"],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def find_template(arg):
|
||||
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
|
||||
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
|
||||
express = arg['list_instance_type'] in mapping.express_to_cpp_typemapping
|
||||
if arg['is_enum']: return templates.set_attr_stmt_enum
|
||||
elif arg['is_templated_list'] and not (select or simple or express): return templates.set_attr_stmt_array
|
||||
else: return templates.set_attr_stmt
|
||||
simple = mapping.schema.is_simpletype(arg["list_instance_type"])
|
||||
select = arg["list_instance_type"] == "IfcUtil::IfcBaseClass"
|
||||
express = arg["list_instance_type"] in mapping.express_to_cpp_typemapping
|
||||
if arg["is_enum"]:
|
||||
return templates.set_attr_stmt_enum
|
||||
elif arg["is_templated_list"] and not (select or simple or express):
|
||||
return templates.set_attr_stmt_array
|
||||
else:
|
||||
return templates.set_attr_stmt
|
||||
|
||||
tmpl = find_template(arg)
|
||||
write_attr(
|
||||
templates.function,
|
||||
class_name = name,
|
||||
name = 'set%s'%arg['name'],
|
||||
arguments = '%s v'%arg['non_optional_type'],
|
||||
return_type = 'void',
|
||||
schema_name = schema_name,
|
||||
schema_name_upper = schema_name_upper,
|
||||
body = tmpl % {'index': arg['index']-1,
|
||||
'type' : arg['non_optional_type'].replace('::Value', '')}
|
||||
class_name=name,
|
||||
name="set%s" % arg["name"],
|
||||
arguments="%s v" % arg["non_optional_type"],
|
||||
return_type="void",
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
body=tmpl
|
||||
% {"index": arg["index"] - 1, "type": arg["non_optional_type"].replace("::Value", "")},
|
||||
)
|
||||
|
||||
if arg['is_derived']:
|
||||
constructor_implementations.append(templates.constructor_stmt_derived % {'index' : arg['index']-1})
|
||||
if arg["is_derived"]:
|
||||
constructor_implementations.append(templates.constructor_stmt_derived % {"index": arg["index"] - 1})
|
||||
else:
|
||||
is_optional_non_naked_ptr = arg['is_optional'] and not arg['non_optional_type'].endswith('*')
|
||||
arg_name = "v%(index)d_%(name)s"%arg
|
||||
deref_name = ("*%s"%arg_name) if is_optional_non_naked_ptr else arg_name
|
||||
is_optional_non_naked_ptr = arg["is_optional"] and not arg["non_optional_type"].endswith("*")
|
||||
arg_name = "v%(index)d_%(name)s" % arg
|
||||
deref_name = ("*%s" % arg_name) if is_optional_non_naked_ptr else arg_name
|
||||
|
||||
tmpl = templates.constructor_stmt_array if arg['is_templated_list'] \
|
||||
else templates.constructor_stmt_enum if arg['is_enum'] \
|
||||
tmpl = (
|
||||
templates.constructor_stmt_array
|
||||
if arg["is_templated_list"]
|
||||
else templates.constructor_stmt_enum
|
||||
if arg["is_enum"]
|
||||
else templates.constructor_stmt
|
||||
impl = tmpl % {'name' : deref_name,
|
||||
'index' : arg['index']-1,
|
||||
'type' : arg['non_optional_type'].replace('::Value', '')}
|
||||
)
|
||||
impl = tmpl % {
|
||||
"name": deref_name,
|
||||
"index": arg["index"] - 1,
|
||||
"type": arg["non_optional_type"].replace("::Value", ""),
|
||||
}
|
||||
if is_optional_non_naked_ptr:
|
||||
impl = templates.constructor_stmt_optional%{'name' : arg_name,
|
||||
'index' : arg['index']-1,
|
||||
'stmt' : impl}
|
||||
impl = templates.constructor_stmt_optional % {
|
||||
"name": arg_name,
|
||||
"index": arg["index"] - 1,
|
||||
"stmt": impl,
|
||||
}
|
||||
constructor_implementations.append(impl)
|
||||
|
||||
|
||||
def get_attribute_index(entity, attr_name):
|
||||
related_entity = mapping.schema.entities[entity]
|
||||
return [a['name'].lower() for a in mapping.get_assignable_arguments(related_entity, include_derived=True)].index(attr_name.lower())
|
||||
return [
|
||||
a["name"].lower() for a in mapping.get_assignable_arguments(related_entity, include_derived=True)
|
||||
].index(attr_name.lower())
|
||||
|
||||
inverse = [templates.const_function % {
|
||||
'class_name' : name,
|
||||
'schema_name' : schema_name,
|
||||
'schema_name_upper' : schema_name_upper,
|
||||
'name' : i.name,
|
||||
'arguments' : '',
|
||||
'return_type' : '::%s::%s::list::ptr' % (schema_name, i.entity),
|
||||
'body' : templates.get_inverse % {'type': i.entity, 'index':get_attribute_index(i.entity, i.attribute), 'schema_name' : schema_name, 'schema_name_upper': schema_name_upper}
|
||||
} for i in type.inverse]
|
||||
inverse = [
|
||||
templates.const_function
|
||||
% {
|
||||
"class_name": name,
|
||||
"schema_name": schema_name,
|
||||
"schema_name_upper": schema_name_upper,
|
||||
"name": i.name,
|
||||
"arguments": "",
|
||||
"return_type": "::%s::%s::list::ptr" % (schema_name, i.entity),
|
||||
"body": templates.get_inverse
|
||||
% {
|
||||
"type": i.entity,
|
||||
"index": get_attribute_index(i.entity, i.attribute),
|
||||
"schema_name": schema_name,
|
||||
"schema_name_upper": schema_name_upper,
|
||||
},
|
||||
}
|
||||
for i in type.inverse
|
||||
]
|
||||
|
||||
superclass = "%s((IfcEntityInstanceData*)0)" % type.supertypes[0] if len(type.supertypes) == 1 else 'IfcUtil::IfcBaseEntity()'
|
||||
superclass = (
|
||||
"%s((IfcEntityInstanceData*)0)" % type.supertypes[0]
|
||||
if len(type.supertypes) == 1
|
||||
else "IfcUtil::IfcBaseEntity()"
|
||||
)
|
||||
|
||||
write(
|
||||
templates.entity_implementation,
|
||||
name = name,
|
||||
parent_type_test = parent_type_test,
|
||||
constructor_arguments = constructor_arguments_str,
|
||||
constructor_implementation = cat(constructor_implementations),
|
||||
attributes = nl(catnl(attributes)),
|
||||
inverse = nl(catnl(inverse)),
|
||||
superclass = superclass,
|
||||
schema_name = schema_name,
|
||||
schema_name_upper = schema_name_upper
|
||||
name=name,
|
||||
parent_type_test=parent_type_test,
|
||||
constructor_arguments=constructor_arguments_str,
|
||||
constructor_implementation=cat(constructor_implementations),
|
||||
attributes=nl(catnl(attributes)),
|
||||
inverse=nl(catnl(inverse)),
|
||||
superclass=superclass,
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
)
|
||||
|
||||
selectable_simple_types = sorted(set(sum([b.values for a,b in mapping.schema.selects.items()], [])) & set(map(str, mapping.schema.types.keys())))
|
||||
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.simpletypes.items()]
|
||||
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.entities.items()]
|
||||
selectable_simple_types = sorted(
|
||||
set(sum([b.values for a, b in mapping.schema.selects.items()], []))
|
||||
& set(map(str, mapping.schema.types.keys()))
|
||||
)
|
||||
schema_entity_statements += [
|
||||
templates.schema_entity_stmt % locals() for name, type in mapping.schema.simpletypes.items()
|
||||
]
|
||||
schema_entity_statements += [
|
||||
templates.schema_entity_stmt % locals() for name, type in mapping.schema.entities.items()
|
||||
]
|
||||
|
||||
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
|
||||
enumerable_types = sorted(
|
||||
set(
|
||||
[name for name, type in mapping.schema.types.items()]
|
||||
+ [name for name, type in mapping.schema.entities.items()]
|
||||
)
|
||||
)
|
||||
max_len = max(map(len, enumerable_types))
|
||||
type_name_strings = catc(map(stringify, enumerable_types))
|
||||
string_map_statements = [templates.string_map_statement % {
|
||||
'uppercase_name' : name.upper(),
|
||||
'name' : name,
|
||||
'padding' : ' ' * (max_len - len(name))
|
||||
} for name in enumerable_types]
|
||||
|
||||
enumeration_index_by_str = OrderedCaseInsensitiveDict((j,i) for i,j in enumerate(enumerable_types))
|
||||
string_map_statements = [
|
||||
templates.string_map_statement
|
||||
% {"uppercase_name": name.upper(), "name": name, "padding": " " * (max_len - len(name))}
|
||||
for name in enumerable_types
|
||||
]
|
||||
|
||||
enumeration_index_by_str = OrderedCaseInsensitiveDict((j, i) for i, j in enumerate(enumerable_types))
|
||||
|
||||
def get_parent_id(s):
|
||||
e = mapping.schema.entities.get(s)
|
||||
if e and e.supertypes:
|
||||
return enumeration_index_by_str[e.supertypes[0]]
|
||||
else: return -1
|
||||
else:
|
||||
return -1
|
||||
|
||||
parent_type_statements = ",".join(map(str, map(get_parent_id, enumerable_types)))
|
||||
|
||||
max_id = len(enumerable_types)
|
||||
|
||||
simple_type_statements = cator("v == Type::%s"%name for name in selectable_simple_types)
|
||||
|
||||
simple_type_statements = cator("v == Type::%s" % name for name in selectable_simple_types)
|
||||
|
||||
simple_type_impl = []
|
||||
for class_name, type in mapping.schema.simpletypes.items():
|
||||
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
|
||||
attr_type = mapping.make_argument_type(type)
|
||||
superclass = mapping.simple_type_parent(class_name)
|
||||
|
||||
simpletype_impl_is = templates.simpletype_impl_is_with_supertype if superclass \
|
||||
|
||||
simpletype_impl_is = (
|
||||
templates.simpletype_impl_is_with_supertype
|
||||
if superclass
|
||||
else templates.simpletype_impl_is_without_supertype
|
||||
|
||||
constructor = templates.constructor_single_initlist if superclass \
|
||||
else templates.constructor
|
||||
|
||||
simpletype_impl_cast = templates.simpletype_impl_cast_templated if mapping.is_templated_list(type) \
|
||||
)
|
||||
|
||||
constructor = templates.constructor_single_initlist if superclass else templates.constructor
|
||||
|
||||
simpletype_impl_cast = (
|
||||
templates.simpletype_impl_cast_templated
|
||||
if mapping.is_templated_list(type)
|
||||
else templates.simpletype_impl_cast
|
||||
|
||||
simpletype_impl_constructor = templates.simpletype_impl_constructor_templated if mapping.is_templated_list(type) \
|
||||
)
|
||||
|
||||
simpletype_impl_constructor = (
|
||||
templates.simpletype_impl_constructor_templated
|
||||
if mapping.is_templated_list(type)
|
||||
else templates.simpletype_impl_constructor
|
||||
|
||||
)
|
||||
|
||||
def compose(params, schema_name=schema_name, schema_name_upper=schema_name_upper):
|
||||
class_name, attr_type, superclass, superclass_init, name, tmpl, return_type, args, body = params
|
||||
underlying_type = mapping.list_instance_type(type)
|
||||
arguments = ",".join(args)
|
||||
body = body % locals()
|
||||
return tmpl % locals()
|
||||
|
||||
simple_type_impl.append(templates.simpletype_impl_comment % {'name': class_name})
|
||||
simple_type_impl.extend(map(compose, map(lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0")+x, (
|
||||
('Class', templates.function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_class ),
|
||||
('declaration', templates.const_function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_declaration ),
|
||||
('', constructor, '', ('IfcEntityInstanceData* e',), templates.simpletype_impl_explicit_constructor),
|
||||
('', constructor, '', ("%s v" % type_str,), simpletype_impl_constructor ),
|
||||
('', templates.cast_function, type_str, (), simpletype_impl_cast )
|
||||
))))
|
||||
simple_type_impl.append('')
|
||||
|
||||
external_definitions = [("extern entity* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.entities.keys() ] + \
|
||||
[("extern type_declaration* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.simpletypes.keys()]
|
||||
|
||||
simple_type_impl.append(templates.simpletype_impl_comment % {"name": class_name})
|
||||
simple_type_impl.extend(
|
||||
map(
|
||||
compose,
|
||||
map(
|
||||
lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0") + x,
|
||||
(
|
||||
(
|
||||
"Class",
|
||||
templates.function,
|
||||
"const IfcParse::type_declaration&",
|
||||
(),
|
||||
templates.simpletype_impl_class,
|
||||
),
|
||||
(
|
||||
"declaration",
|
||||
templates.const_function,
|
||||
"const IfcParse::type_declaration&",
|
||||
(),
|
||||
templates.simpletype_impl_declaration,
|
||||
),
|
||||
(
|
||||
"",
|
||||
constructor,
|
||||
"",
|
||||
("IfcEntityInstanceData* e",),
|
||||
templates.simpletype_impl_explicit_constructor,
|
||||
),
|
||||
("", constructor, "", ("%s v" % type_str,), simpletype_impl_constructor),
|
||||
("", templates.cast_function, type_str, (), simpletype_impl_cast),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
simple_type_impl.append("")
|
||||
|
||||
external_definitions = [
|
||||
("extern entity* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.entities.keys()
|
||||
] + [
|
||||
("extern type_declaration* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.simpletypes.keys()
|
||||
]
|
||||
|
||||
self.str = templates.implementation % {
|
||||
'schema_name_upper' : schema_name_upper,
|
||||
'schema_name' : schema_name,
|
||||
'max_id' : max_id,
|
||||
'enumeration_functions' : cat(enumeration_functions),
|
||||
'schema_entity_statements' : catnl(schema_entity_statements),
|
||||
'type_name_strings' : type_name_strings,
|
||||
'string_map_statements' : catnl(string_map_statements),
|
||||
'simple_type_statement' : simple_type_statements,
|
||||
'parent_type_statements' : parent_type_statements,
|
||||
'entity_implementations' : catnl(entity_implementations),
|
||||
'simple_type_impl' : catnl(simple_type_impl),
|
||||
'external_definitions' : catnl(external_definitions)
|
||||
"schema_name_upper": schema_name_upper,
|
||||
"schema_name": schema_name,
|
||||
"max_id": max_id,
|
||||
"enumeration_functions": cat(enumeration_functions),
|
||||
"schema_entity_statements": catnl(schema_entity_statements),
|
||||
"type_name_strings": type_name_strings,
|
||||
"string_map_statements": catnl(string_map_statements),
|
||||
"simple_type_statement": simple_type_statements,
|
||||
"parent_type_statements": parent_type_statements,
|
||||
"entity_implementations": catnl(entity_implementations),
|
||||
"simple_type_impl": catnl(simple_type_impl),
|
||||
"external_definitions": catnl(external_definitions),
|
||||
}
|
||||
|
||||
self.schema_name = mapping.schema.name.capitalize()
|
||||
|
||||
self.file_name = '%s.cpp'%self.schema_name
|
||||
|
||||
|
||||
|
||||
self.file_name = "%s.cpp" % self.schema_name
|
||||
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
|
||||
|
||||
@@ -23,57 +23,80 @@ import sys
|
||||
import nodes
|
||||
import templates
|
||||
|
||||
|
||||
class Mapping:
|
||||
|
||||
express_to_cpp_typemapping = {
|
||||
'boolean' : 'bool',
|
||||
'logical' : 'bool',
|
||||
'integer' : 'int',
|
||||
'real' : 'double',
|
||||
'number' : 'double',
|
||||
'string' : 'std::string',
|
||||
'binary' : 'boost::dynamic_bitset<>'
|
||||
"boolean": "bool",
|
||||
"logical": "bool",
|
||||
"integer": "int",
|
||||
"real": "double",
|
||||
"number": "double",
|
||||
"string": "std::string",
|
||||
"binary": "boost::dynamic_bitset<>",
|
||||
}
|
||||
|
||||
supported_argument_types = set([
|
||||
'INT', 'BOOL', 'DOUBLE', 'STRING', 'BINARY', 'ENUMERATION', 'ENTITY_INSTANCE',
|
||||
'AGGREGATE_OF_INT', 'AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_STRING', 'AGGREGATE_OF_BINARY', 'AGGREGATE_OF_ENTITY_INSTANCE',
|
||||
'AGGREGATE_OF_AGGREGATE_OF_INT', 'AGGREGATE_OF_AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE',
|
||||
])
|
||||
|
||||
supported_argument_types = set(
|
||||
[
|
||||
"INT",
|
||||
"BOOL",
|
||||
"DOUBLE",
|
||||
"STRING",
|
||||
"BINARY",
|
||||
"ENUMERATION",
|
||||
"ENTITY_INSTANCE",
|
||||
"AGGREGATE_OF_INT",
|
||||
"AGGREGATE_OF_DOUBLE",
|
||||
"AGGREGATE_OF_STRING",
|
||||
"AGGREGATE_OF_BINARY",
|
||||
"AGGREGATE_OF_ENTITY_INSTANCE",
|
||||
"AGGREGATE_OF_AGGREGATE_OF_INT",
|
||||
"AGGREGATE_OF_AGGREGATE_OF_DOUBLE",
|
||||
"AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE",
|
||||
]
|
||||
)
|
||||
|
||||
def __init__(self, schema):
|
||||
self.schema = schema
|
||||
|
||||
|
||||
def flatten_type_string(self, type):
|
||||
return self.flatten_type_string(self.schema.types[type].type) if self.schema.is_simpletype(type) else type
|
||||
|
||||
|
||||
def flatten_type(self, type):
|
||||
res = self.flatten_type(self.schema.types[type].type) if self.schema.is_simpletype(type) else type
|
||||
return res
|
||||
|
||||
|
||||
def simple_type_parent(self, type):
|
||||
parent = self.schema.types[type].type
|
||||
if isinstance(parent, (nodes.AggregationType, nodes.StringType)) or (isinstance(parent, nodes.SimpleType) and isinstance(parent.type, nodes.StringType)):
|
||||
if isinstance(parent, (nodes.AggregationType, nodes.StringType)) or (
|
||||
isinstance(parent, nodes.SimpleType) and isinstance(parent.type, nodes.StringType)
|
||||
):
|
||||
return None
|
||||
if str(parent) in self.express_to_cpp_typemapping:
|
||||
return None
|
||||
return str(parent)
|
||||
|
||||
def make_type_string(self, type):
|
||||
if isinstance(type, nodes.StringType) or (isinstance(type, nodes.SimpleType) and isinstance(type.type, nodes.StringType)):
|
||||
if isinstance(type, nodes.StringType) or (
|
||||
isinstance(type, nodes.SimpleType) and isinstance(type.type, nodes.StringType)
|
||||
):
|
||||
type = "string"
|
||||
if isinstance(type, (str, nodes.BinaryType, nodes.SimpleType, nodes.NamedType)):
|
||||
return self.express_to_cpp_typemapping.get(str(type), "::%s::%s" % (self.schema.name.capitalize(), type))
|
||||
else:
|
||||
if type.bounds is None:
|
||||
import pdb; pdb.set_trace()
|
||||
import pdb
|
||||
|
||||
pdb.set_trace()
|
||||
is_list = self.schema.is_entity(type.type)
|
||||
is_nested_list = isinstance(type.type, nodes.AggregationType)
|
||||
tmpl = templates.list_list_type if is_nested_list else templates.list_type if is_list else templates.array_type
|
||||
tmpl = (
|
||||
templates.list_list_type if is_nested_list else templates.list_type if is_list else templates.array_type
|
||||
)
|
||||
return tmpl % {
|
||||
'instance_type' : self.make_type_string(self.flatten_type_string(type.type)),
|
||||
'lower' : type.bounds.lower,
|
||||
'upper' : type.bounds.upper,
|
||||
"instance_type": self.make_type_string(self.flatten_type_string(type.type)),
|
||||
"lower": type.bounds.lower,
|
||||
"upper": type.bounds.upper,
|
||||
}
|
||||
|
||||
def is_array(self, type):
|
||||
@@ -83,12 +106,15 @@ class Mapping:
|
||||
return self.is_array(self.schema.types[type].type)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def make_argument_entity(self, attr):
|
||||
type = attr.type if hasattr(attr, 'type') else attr
|
||||
while isinstance(type, nodes.AggregationType): type = type.type
|
||||
if str(type) in self.express_to_cpp_typemapping: return "Type::UNDEFINED"
|
||||
else: return "Type::%s" % type
|
||||
type = attr.type if hasattr(attr, "type") else attr
|
||||
while isinstance(type, nodes.AggregationType):
|
||||
type = type.type
|
||||
if str(type) in self.express_to_cpp_typemapping:
|
||||
return "Type::UNDEFINED"
|
||||
else:
|
||||
return "Type::%s" % type
|
||||
|
||||
def make_argument_type(self, attr):
|
||||
def _make_argument_type(type):
|
||||
@@ -104,18 +130,20 @@ class Mapping:
|
||||
return "ENUMERATION"
|
||||
elif isinstance(type, nodes.AggregationType):
|
||||
ty = _make_argument_type(type.type)
|
||||
if ty == "UNKNOWN": return "UNKNOWN"
|
||||
if ty == "UNKNOWN":
|
||||
return "UNKNOWN"
|
||||
return "AGGREGATE_OF_" + ty
|
||||
elif str(type) in self.express_to_cpp_typemapping:
|
||||
return self.express_to_cpp_typemapping.get(str(type), type).split('::')[-1].upper()
|
||||
return self.express_to_cpp_typemapping.get(str(type), type).split("::")[-1].upper()
|
||||
elif self.schema.is_type(type):
|
||||
return _make_argument_type(self.schema.types[type].type)
|
||||
else:
|
||||
raise ValueError("Unable to map type %r for attribute %r" % (type, attr))
|
||||
ty = _make_argument_type(attr.type if hasattr(attr, 'type') else attr)
|
||||
|
||||
ty = _make_argument_type(attr.type if hasattr(attr, "type") else attr)
|
||||
if ty not in self.supported_argument_types:
|
||||
print("Attribute %r mapped as 'unknown'" % (attr), file=sys.stderr)
|
||||
ty = 'UNKNOWN'
|
||||
ty = "UNKNOWN"
|
||||
return "IfcUtil::Argument_%s" % ty
|
||||
|
||||
def get_type_dep(self, type):
|
||||
@@ -124,18 +152,20 @@ class Mapping:
|
||||
else:
|
||||
return self.get_type_dep(type.type)
|
||||
|
||||
def get_parameter_type(self, attr, allow_optional, allow_entities, allow_pointer = True):
|
||||
def get_parameter_type(self, attr, allow_optional, allow_entities, allow_pointer=True):
|
||||
attr_type = self.flatten_type(attr.type)
|
||||
|
||||
if (isinstance(attr_type, nodes.SimpleType) and isinstance(attr_type.type, nodes.StringType)) or isinstance(attr_type, nodes.StringType):
|
||||
|
||||
if (isinstance(attr_type, nodes.SimpleType) and isinstance(attr_type.type, nodes.StringType)) or isinstance(
|
||||
attr_type, nodes.StringType
|
||||
):
|
||||
type_str = self.express_to_cpp_typemapping["string"]
|
||||
else:
|
||||
type_str = self.express_to_cpp_typemapping.get(str(attr_type), attr_type)
|
||||
|
||||
|
||||
is_ptr = False
|
||||
|
||||
|
||||
if self.schema.is_enumeration(attr_type):
|
||||
type_str = '::%s::%s::Value' % (self.schema.name.capitalize(), attr_type)
|
||||
type_str = "::%s::%s::Value" % (self.schema.name.capitalize(), attr_type)
|
||||
elif isinstance(type_str, nodes.AggregationType):
|
||||
is_nested_list = isinstance(attr_type.type, nodes.AggregationType)
|
||||
ty = self.get_parameter_type(attr_type.type if is_nested_list else attr_type, False, allow_entities, False)
|
||||
@@ -144,18 +174,12 @@ class Mapping:
|
||||
elif self.schema.is_simpletype(ty) or str(ty) in self.express_to_cpp_typemapping.values():
|
||||
tmpl = templates.nested_array_type if is_nested_list else templates.array_type
|
||||
bounds = (attr_type.bounds.lower, attr_type.bounds.upper) if attr_type.bounds else (-1, -1)
|
||||
type_str = tmpl % {
|
||||
'instance_type' : ty,
|
||||
'lower' : bounds[0],
|
||||
'upper' : bounds[1]
|
||||
}
|
||||
type_str = tmpl % {"instance_type": ty, "lower": bounds[0], "upper": bounds[1]}
|
||||
else:
|
||||
tmpl = templates.list_list_type if is_nested_list else templates.list_type
|
||||
type_str = tmpl % {
|
||||
'instance_type': ty
|
||||
}
|
||||
elif (self.schema.is_entity(type_str) or self.schema.is_select(type_str)):
|
||||
type_str = '::%s::%s' % (self.schema.name.capitalize(), attr_type)
|
||||
type_str = tmpl % {"instance_type": ty}
|
||||
elif self.schema.is_entity(type_str) or self.schema.is_select(type_str):
|
||||
type_str = "::%s::%s" % (self.schema.name.capitalize(), attr_type)
|
||||
if allow_pointer:
|
||||
type_str += "*"
|
||||
is_ptr = True
|
||||
@@ -163,7 +187,7 @@ class Mapping:
|
||||
type_str = "IfcUtil::IfcBaseClass*"
|
||||
is_ptr = True
|
||||
if allow_optional and attr.optional and not is_ptr:
|
||||
type_str = "boost::optional< %s >"%type_str
|
||||
type_str = "boost::optional< %s >" % type_str
|
||||
return type_str
|
||||
|
||||
def argument_count(self, t):
|
||||
@@ -181,39 +205,49 @@ class Mapping:
|
||||
|
||||
def list_instance_type(self, attr):
|
||||
attr_type = attr.type if isinstance(attr, nodes.ExplicitAttribute) else attr
|
||||
if isinstance(attr_type, str): return None
|
||||
if isinstance(attr_type, str):
|
||||
return None
|
||||
|
||||
def f(v):
|
||||
v = self.flatten_type(v)
|
||||
if isinstance(v, (nodes.AggregationType, nodes.StringType)) or (isinstance(v, nodes.SimpleType) and isinstance(v.type, nodes.StringType)):
|
||||
if isinstance(v, (nodes.AggregationType, nodes.StringType)) or (
|
||||
isinstance(v, nodes.SimpleType) and isinstance(v.type, nodes.StringType)
|
||||
):
|
||||
return "string"
|
||||
if self.schema.is_select(v):
|
||||
return 'IfcUtil::IfcBaseClass'
|
||||
return "IfcUtil::IfcBaseClass"
|
||||
elif str(v) in self.schema.types or str(v) in self.schema.entities:
|
||||
return "::%s::%s" % (self.schema.name.capitalize(), v)
|
||||
else: return str(v)
|
||||
else:
|
||||
return str(v)
|
||||
|
||||
if self.is_array(attr_type):
|
||||
if not isinstance(attr_type, str) and self.is_array(attr_type.type):
|
||||
if isinstance(attr_type.type, str):
|
||||
return f(attr_type.type)
|
||||
else: return f(attr_type.type.type)
|
||||
else:
|
||||
return f(attr_type.type.type)
|
||||
else:
|
||||
if isinstance(attr_type, str):
|
||||
return f(attr_type)
|
||||
else: return f(attr_type.type)
|
||||
else:
|
||||
return f(attr_type.type)
|
||||
return None
|
||||
|
||||
def is_templated_list(self, attr):
|
||||
attr_type = attr.type if isinstance(attr, nodes.ExplicitAttribute) else attr
|
||||
if isinstance(attr, str): return False
|
||||
if isinstance(attr, str):
|
||||
return False
|
||||
ty = self.list_instance_type(attr)
|
||||
if ty is None: return False
|
||||
if ty is None:
|
||||
return False
|
||||
arr = self.is_array(attr_type)
|
||||
simple = self.schema.is_simpletype(ty)
|
||||
express = self.flatten_type_string(ty) in self.express_to_cpp_typemapping
|
||||
select = ty == 'IfcUtil::IfcBaseClass'
|
||||
select = ty == "IfcUtil::IfcBaseClass"
|
||||
return arr and not simple and not express and not select
|
||||
|
||||
def get_assignable_arguments(self, t, include_derived = False):
|
||||
def get_assignable_arguments(self, t, include_derived=False):
|
||||
count = self.argument_count(t)
|
||||
num_inherited = count - len(t.attributes)
|
||||
derived = set(self.derived_in_supertype(t))
|
||||
@@ -224,22 +258,27 @@ class Mapping:
|
||||
supported = self.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN"
|
||||
return not_derived and supported
|
||||
|
||||
return [{
|
||||
'index' : i+1,
|
||||
'name' : attr.name,
|
||||
'full_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=True),
|
||||
'specialized_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=False),
|
||||
'non_optional_type' : self.get_parameter_type(attr, allow_optional=False, allow_entities=False),
|
||||
'list_instance_type' : self.list_instance_type(attr),
|
||||
'is_optional' : attr.optional,
|
||||
'is_inherited' : i < num_inherited,
|
||||
'is_enum' : attr.type in self.schema.enumerations,
|
||||
'is_array' : self.is_array(attr.type),
|
||||
'is_nested' : self.is_array(attr.type) and not isinstance(attr.type, str) and self.is_array(attr.type.type),
|
||||
'is_derived' : attr.name in derived,
|
||||
'is_templated_list' : self.is_templated_list(attr),
|
||||
'argument_type_enum' : self.make_argument_type(attr),
|
||||
'argument_entity' : self.make_argument_entity(attr),
|
||||
'argument_type' : attr.type
|
||||
} for i, attr in attrs if include(attr)]
|
||||
|
||||
return [
|
||||
{
|
||||
"index": i + 1,
|
||||
"name": attr.name,
|
||||
"full_type": self.get_parameter_type(attr, allow_optional=True, allow_entities=True),
|
||||
"specialized_type": self.get_parameter_type(attr, allow_optional=True, allow_entities=False),
|
||||
"non_optional_type": self.get_parameter_type(attr, allow_optional=False, allow_entities=False),
|
||||
"list_instance_type": self.list_instance_type(attr),
|
||||
"is_optional": attr.optional,
|
||||
"is_inherited": i < num_inherited,
|
||||
"is_enum": attr.type in self.schema.enumerations,
|
||||
"is_array": self.is_array(attr.type),
|
||||
"is_nested": self.is_array(attr.type)
|
||||
and not isinstance(attr.type, str)
|
||||
and self.is_array(attr.type.type),
|
||||
"is_derived": attr.name in derived,
|
||||
"is_templated_list": self.is_templated_list(attr),
|
||||
"argument_type_enum": self.make_argument_type(attr),
|
||||
"argument_entity": self.make_argument_entity(attr),
|
||||
"argument_type": attr.type,
|
||||
}
|
||||
for i, attr in attrs
|
||||
if include(attr)
|
||||
]
|
||||
|
||||
@@ -23,61 +23,77 @@ import io
|
||||
import string
|
||||
import collections
|
||||
|
||||
|
||||
class Node:
|
||||
def __init__(self, s, loc, tokens, rule=None):
|
||||
self.rule = rule or (type(self).__name__)
|
||||
self.tokens = tokens.asDict()
|
||||
self.flat = sum([getattr(t, 'flat', [t]) for t in tokens.asList()], [])
|
||||
self.flat = sum([getattr(t, "flat", [t]) for t in tokens.asList()], [])
|
||||
if rule is None:
|
||||
self.init()
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.rule, ",".join("%s:%s" % i for i in self.tokens.items()))
|
||||
|
||||
def __getattr__(self, k):
|
||||
return self.tokens.get(k)
|
||||
def __getstate__(self): return self.__dict__
|
||||
def __setstate__(self, d): self.__dict__.update(d)
|
||||
def init(self): pass
|
||||
|
||||
def __getstate__(self):
|
||||
return self.__dict__
|
||||
|
||||
def __setstate__(self, d):
|
||||
self.__dict__.update(d)
|
||||
|
||||
def init(self):
|
||||
pass
|
||||
|
||||
def any(self):
|
||||
return next(iter(self.tokens.values()))
|
||||
|
||||
|
||||
class ListNode:
|
||||
def __init__(self, s, loc, tokens, rule=None):
|
||||
self.rule = rule or (type(self).__name__)
|
||||
self.tokens = tokens.asList()
|
||||
self.flat = sum([getattr(t, 'flat', [t]) for t in self.tokens], [])
|
||||
self.flat = sum([getattr(t, "flat", [t]) for t in self.tokens], [])
|
||||
|
||||
def __repr__(self):
|
||||
return "%s[%s]" % (self.rule, ",".join("%s" % i for i in self.tokens))
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.tokens)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.tokens[i]
|
||||
def init(self): pass
|
||||
|
||||
|
||||
def init(self):
|
||||
pass
|
||||
|
||||
|
||||
class SimpleType(Node):
|
||||
|
||||
def get_type(self):
|
||||
t = self.any()
|
||||
if (type(t) == Node):
|
||||
if type(t) == Node:
|
||||
return t.any()
|
||||
else:
|
||||
t = t[0]
|
||||
if (type(t) == Node):
|
||||
if type(t) == Node:
|
||||
return t.any().any()
|
||||
else:
|
||||
return t
|
||||
|
||||
|
||||
type = property(get_type)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.type)
|
||||
|
||||
|
||||
def format_clause(exp):
|
||||
def whitespace(t):
|
||||
if t in {'=', '|', '<*', 'or', 'in', '<>', 'and'}:
|
||||
return ' %s ' % t
|
||||
if t in {"=", "|", "<*", "or", "in", "<>", "and"}:
|
||||
return " %s " % t
|
||||
return t
|
||||
|
||||
return "".join(whitespace(term) for term in exp.flat)
|
||||
|
||||
|
||||
@@ -85,18 +101,18 @@ class TypeDeclaration(Node):
|
||||
name = property(lambda self: self.type_id[0])
|
||||
utype = property(lambda self: self.underlying_type.any().any())
|
||||
type = property(lambda self: self.utype[0] if isinstance(self.utype, list) else self.utype)
|
||||
|
||||
def init(self):
|
||||
|
||||
|
||||
def init(self):
|
||||
|
||||
assert hasattr(self, "TYPE")
|
||||
|
||||
|
||||
self.where = []
|
||||
clause = self.where_clause
|
||||
if clause:
|
||||
clause = clause[0]
|
||||
|
||||
|
||||
self.where = [(r.simple_id, format_clause(r.expression[0])) for r in clause[1::2]]
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
s = "TYPE %s = %s;\n" % (self.name, self.type)
|
||||
if self.where:
|
||||
@@ -112,7 +128,7 @@ class EntityDeclaration(Node):
|
||||
supertype = property(lambda self: self.entity_head[0].subsuper[0].supertype_constraint)
|
||||
subtype = property(lambda self: self.entity_head[0].subsuper[0].subtype_declaration)
|
||||
supertypes = property(lambda self: [self.subtype.super_type] if self.subtype else [])
|
||||
|
||||
|
||||
def get_abstract(self):
|
||||
if self.entity_head[0].subsuper[0].supertype_constraint:
|
||||
return self.entity_head[0].subsuper[0].supertype_constraint.abstract
|
||||
@@ -120,72 +136,71 @@ class EntityDeclaration(Node):
|
||||
return False
|
||||
|
||||
abstract = property(get_abstract)
|
||||
|
||||
|
||||
def init(self):
|
||||
|
||||
def redeclared_attribute(a):
|
||||
try:
|
||||
return (
|
||||
a.attribute_decl.redeclared_attribute.qualified_attribute.group_qualifier.simple_id,
|
||||
a.attribute_decl.redeclared_attribute.qualified_attribute.attribute_qualifier.simple_id
|
||||
a.attribute_decl.redeclared_attribute.qualified_attribute.attribute_qualifier.simple_id,
|
||||
)
|
||||
except:
|
||||
return a.attribute_decl.simple_id
|
||||
|
||||
assert self.flat[0] == 'entity'
|
||||
|
||||
|
||||
assert self.flat[0] == "entity"
|
||||
|
||||
self.attributes = [a for a in self.entity_body[0] if isinstance(a, ExplicitAttribute)]
|
||||
self.inverse = []
|
||||
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == 'inverse']
|
||||
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == "inverse"]
|
||||
if alist:
|
||||
self.inverse = alist[0]
|
||||
|
||||
self.inverse = alist[0]
|
||||
|
||||
self.derive = []
|
||||
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == 'derive']
|
||||
alist = [x for x in self.entity_body[0] if isinstance(x, AttributeList) and x.type == "derive"]
|
||||
if alist:
|
||||
alist = alist[0]
|
||||
self.derive = [(redeclared_attribute(a), format_clause(a.expression[0])) for a in alist]
|
||||
|
||||
|
||||
self.where = []
|
||||
clause = [r for r in self.entity_body[0] if r.rule == "where_clause"]
|
||||
if clause:
|
||||
clause = clause[0]
|
||||
|
||||
|
||||
self.where = [(r.simple_id, format_clause(r.expression[0])) for r in clause[1::2]]
|
||||
|
||||
|
||||
self.unique = []
|
||||
clause = [r for r in self.entity_body[0] if r.rule == "unique_clause"]
|
||||
if clause:
|
||||
clause = clause[0]
|
||||
self.unique = [(r[0], r[2].simple_id) for r in clause[1::2]]
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
strm = io.StringIO()
|
||||
|
||||
|
||||
print("ENTITY %s" % self.name, file=strm)
|
||||
|
||||
|
||||
if self.supertype:
|
||||
print("", self.supertype, file=strm)
|
||||
if self.subtype:
|
||||
print("", self.subtype, file=strm)
|
||||
|
||||
|
||||
strm.seek(strm.tell() - 1)
|
||||
print(";", file=strm)
|
||||
|
||||
|
||||
for a in self.attributes:
|
||||
print(" ", a, ";", file=strm, sep='')
|
||||
|
||||
print(" ", a, ";", file=strm, sep="")
|
||||
|
||||
if self.derive:
|
||||
print(" DERIVE", file=strm)
|
||||
for nm, exp in self.derive:
|
||||
if isinstance(nm, tuple):
|
||||
nm = "SELF\\%s.%s" % nm
|
||||
print(" %s : %s;" % (nm, exp), file=strm)
|
||||
|
||||
|
||||
if self.inverse:
|
||||
print(" INVERSE", file=strm)
|
||||
print(self.inverse, file=strm)
|
||||
|
||||
|
||||
if self.where:
|
||||
print(" WHERE", file=strm)
|
||||
for nm_exp in self.where:
|
||||
@@ -195,19 +210,21 @@ class EntityDeclaration(Node):
|
||||
print(" UNIQUE", file=strm)
|
||||
for nm_exp in self.unique:
|
||||
print(" %s : %s;" % nm_exp, file=strm)
|
||||
|
||||
|
||||
print("END_ENTITY;", file=strm)
|
||||
return strm.getvalue()
|
||||
|
||||
|
||||
class EnumerationType(Node):
|
||||
values = property(lambda self: self.enumeration_type[2][1::2])
|
||||
|
||||
def __repr__(self):
|
||||
return "ENUMERATION OF (" + ",".join(self.values) + ")"
|
||||
|
||||
|
||||
return "ENUMERATION OF (" + ",".join(self.values) + ")"
|
||||
|
||||
|
||||
class NamedType(Node):
|
||||
type = property(lambda self: self.simple_id)
|
||||
|
||||
def __repr__(self):
|
||||
return self.type
|
||||
|
||||
@@ -216,7 +233,7 @@ class AggregationType(Node):
|
||||
aggregate_type = property(lambda self: self.flat[0])
|
||||
bounds = property(lambda self: (list(self.tokens.values())[0][0].bound_spec or [None])[0])
|
||||
unique = property(lambda self: list(self.tokens.values())[0][0].UNIQUE is not None)
|
||||
|
||||
|
||||
def get_type(self):
|
||||
v = list(self.tokens.values())[0][0]
|
||||
if v.instantiable_type:
|
||||
@@ -231,51 +248,61 @@ class AggregationType(Node):
|
||||
elif v.parameter_type.generalized_types.general_aggregation_types:
|
||||
return v.parameter_type.generalized_types.general_aggregation_types
|
||||
else:
|
||||
import pdb; pdb.set_trace()
|
||||
import pdb
|
||||
|
||||
pdb.set_trace()
|
||||
raise ValueError()
|
||||
|
||||
|
||||
type = property(get_type)
|
||||
|
||||
|
||||
def init(self):
|
||||
assert self.bounds is None or isinstance(self.bounds, BoundSpecification)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s%s of %s%s"%(self.aggregate_type, self.bounds, "unique " if self.unique else "", self.type)
|
||||
return "%s%s of %s%s" % (self.aggregate_type, self.bounds, "unique " if self.unique else "", self.type)
|
||||
|
||||
|
||||
class SelectType(Node):
|
||||
values = property(lambda self: self.select_type[1][1::2])
|
||||
|
||||
def __repr__(self):
|
||||
return "SELECT (" + ",".join(map(str, self.values)) + ")"
|
||||
|
||||
|
||||
class SuperTypeExpression(Node):
|
||||
abstract = property(lambda self: self.abstract_supertype_declaration is not None)
|
||||
|
||||
def get_sub_types(self):
|
||||
if self.abstract:
|
||||
constraint = self.abstract_supertype_declaration[0]
|
||||
else:
|
||||
constraint = self.supertype_rule[0]
|
||||
return [s[0][0].simple_id for s in constraint.subtype_constraint[0].supertype_expression[0][0][0].one_of[0][2::2]]
|
||||
return [
|
||||
s[0][0].simple_id for s in constraint.subtype_constraint[0].supertype_expression[0][0][0].one_of[0][2::2]
|
||||
]
|
||||
|
||||
sub_types = property(get_sub_types)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%sSUPERTYPE OF(ONEOF(%s))" % ("ABSTRACT " if self.abstract else "",",".join(self.sub_types))
|
||||
return "%sSUPERTYPE OF(ONEOF(%s))" % ("ABSTRACT " if self.abstract else "", ",".join(self.sub_types))
|
||||
|
||||
|
||||
class SubTypeExpression(Node):
|
||||
super_type = property(lambda self: self.entity_ref[0])
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "SUBTYPE OF(%s)" % self.super_type
|
||||
|
||||
|
||||
class AttributeList(ListNode):
|
||||
type = property(lambda self: self.flat[0] if self.flat[0] in {'inverse', 'derive'} else 'explicit')
|
||||
type = property(lambda self: self.flat[0] if self.flat[0] in {"inverse", "derive"} else "explicit")
|
||||
|
||||
def __repr__(self):
|
||||
return "\n".join([" %s;"%s for s in self.tokens[1:]])
|
||||
return "\n".join([" %s;" % s for s in self.tokens[1:]])
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.tokens[1:])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.tokens[1:])
|
||||
|
||||
@@ -286,6 +313,7 @@ class InverseAttribute(Node):
|
||||
bounds = property(lambda self: self.bound_spec[0] if self.bound_spec else None)
|
||||
entity = property(lambda self: self.entity_ref[0])
|
||||
attribute = property(lambda self: self.attribute_ref[0])
|
||||
|
||||
def __repr__(self):
|
||||
def _():
|
||||
yield self.name
|
||||
@@ -298,8 +326,10 @@ class InverseAttribute(Node):
|
||||
yield self.entity
|
||||
yield "FOR"
|
||||
yield self.attribute
|
||||
|
||||
return " ".join(map(str, _()))
|
||||
|
||||
|
||||
"""
|
||||
class DerivedAttribute(Node):
|
||||
def init(self):
|
||||
@@ -310,6 +340,7 @@ class DerivedAttribute(Node):
|
||||
return str(self.name)
|
||||
"""
|
||||
|
||||
|
||||
class BinaryType(Node):
|
||||
def __repr__(self):
|
||||
return "binary"
|
||||
@@ -320,32 +351,32 @@ class BoundSpecification(Node):
|
||||
upper = property(lambda self: self.flat[3])
|
||||
|
||||
def __repr__(self):
|
||||
return "[%s:%s]"%(self.lower, self.upper)
|
||||
return "[%s:%s]" % (self.lower, self.upper)
|
||||
|
||||
|
||||
class ExplicitAttribute(Node):
|
||||
name = property(lambda self: self.attribute_decl.simple_id)
|
||||
optional = property(lambda self: self.OPTIONAL is not None)
|
||||
|
||||
|
||||
def get_type(self):
|
||||
v = next(iter(self.parameter_type.tokens.values()))
|
||||
if v.general_aggregation_types:
|
||||
return v.general_aggregation_types
|
||||
else:
|
||||
return v
|
||||
|
||||
|
||||
type = property(get_type)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s : %s%s" % (self.name, "optional " if self.optional else "", self.type)
|
||||
|
||||
|
||||
|
||||
class WidthSpec(Node):
|
||||
fixed = property(lambda self: self.FIXED is not None)
|
||||
|
||||
|
||||
def init(self):
|
||||
self.width = int(''.join(self.width[0].flat))
|
||||
|
||||
self.width = int("".join(self.width[0].flat))
|
||||
|
||||
def __repr__(self):
|
||||
return "(%d)%s" % (self.width, " fixed" if self.fixed else "")
|
||||
|
||||
|
||||
@@ -23,13 +23,15 @@ import collections
|
||||
|
||||
if tuple(map(int, platform.python_version_tuple())) < (2, 7):
|
||||
import ordereddict
|
||||
|
||||
collections.OrderedDict = ordereddict.OrderedDict
|
||||
|
||||
# According to ISO 10303-11 7.1.2: Letters: "... The case of
|
||||
|
||||
# According to ISO 10303-11 7.1.2: Letters: "... The case of
|
||||
# letters is significant only within explicit string literals."
|
||||
class OrderedCaseInsensitiveDict_KeyObject(str):
|
||||
def __eq__(self, other):
|
||||
return self.lower() == other.lower()
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.lower())
|
||||
|
||||
@@ -39,53 +41,73 @@ class OrderedCaseInsensitiveDict(collections.OrderedDict):
|
||||
collections.OrderedDict.__init__(self)
|
||||
for key, value in collections.OrderedDict(*args, **kwargs).items():
|
||||
self[OrderedCaseInsensitiveDict_KeyObject(key)] = value
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
return collections.OrderedDict.__setitem__(self, OrderedCaseInsensitiveDict_KeyObject(key), value)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return collections.OrderedDict.__getitem__(self, OrderedCaseInsensitiveDict_KeyObject(key))
|
||||
|
||||
def get(self, key, *args, **kwargs):
|
||||
return collections.OrderedDict.get(self, OrderedCaseInsensitiveDict_KeyObject(key), *args, **kwargs)
|
||||
|
||||
def __contains__(self, key):
|
||||
return collections.OrderedDict.__contains__(self, OrderedCaseInsensitiveDict_KeyObject(key))
|
||||
|
||||
def __delitem__(self, key):
|
||||
return collections.OrderedDict.__delitem__(self, OrderedCaseInsensitiveDict_KeyObject(key))
|
||||
|
||||
|
||||
|
||||
class Schema:
|
||||
def is_enumeration(self, v):
|
||||
return str(v) in self.enumerations
|
||||
|
||||
def is_select(self, v):
|
||||
return str(v) in self.selects
|
||||
|
||||
def is_simpletype(self, v):
|
||||
return str(v) in self.simpletypes
|
||||
|
||||
def is_type(self, v):
|
||||
return str(v) in self.types
|
||||
|
||||
def is_entity(self, v):
|
||||
return str(v) in self.entities
|
||||
|
||||
def __len__(self):
|
||||
return len(self.types) + len(self.entities)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.keys)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.types_entities[key]
|
||||
|
||||
def __init__(self, parsetree):
|
||||
self.name = parsetree.syntax[0][0].simple_id
|
||||
|
||||
sort = lambda d: OrderedCaseInsensitiveDict(sorted(d))
|
||||
|
||||
declarations = [d.any()[0] for d in parsetree.syntax[0][0].schema_body[0] if d.rule == 'declaration' and d.any()[0].rule != 'function_decl']
|
||||
|
||||
self.types = sort([(t.name,t) for t in declarations if isinstance(t, nodes.TypeDeclaration)])
|
||||
self.entities = sort([(t.name,t) for t in declarations if isinstance(t, nodes.EntityDeclaration)])
|
||||
|
||||
sort = lambda d: OrderedCaseInsensitiveDict(sorted(d))
|
||||
|
||||
declarations = [
|
||||
d.any()[0]
|
||||
for d in parsetree.syntax[0][0].schema_body[0]
|
||||
if d.rule == "declaration" and d.any()[0].rule != "function_decl"
|
||||
]
|
||||
|
||||
self.types = sort([(t.name, t) for t in declarations if isinstance(t, nodes.TypeDeclaration)])
|
||||
self.entities = sort([(t.name, t) for t in declarations if isinstance(t, nodes.EntityDeclaration)])
|
||||
|
||||
self.keys = list(self.types.keys()) + list(self.entities.keys())
|
||||
self.types_entities = {k: v for d in (self.types, self.entities) for k, v in d.items()}
|
||||
|
||||
of_type = lambda *types: sort([(a, b.type) for a,b in self.types.items() if any(isinstance(b.type, ty) for ty in types)])
|
||||
of_type = lambda *types: sort(
|
||||
[(a, b.type) for a, b in self.types.items() if any(isinstance(b.type, ty) for ty in types)]
|
||||
)
|
||||
|
||||
self.enumerations = of_type(nodes.EnumerationType)
|
||||
self.selects = of_type(nodes.SelectType)
|
||||
self.simpletypes = of_type(str, nodes.AggregationType, nodes.BinaryType, nodes.StringType, nodes.SimpleType, nodes.NamedType)
|
||||
|
||||
self.simpletypes = of_type(
|
||||
str, nodes.AggregationType, nodes.BinaryType, nodes.StringType, nodes.SimpleType, nodes.NamedType
|
||||
)
|
||||
|
||||
assert len(self.enumerations) + len(self.selects) + len(self.simpletypes) == len(self.types)
|
||||
|
||||
@@ -27,109 +27,127 @@ from collections import defaultdict
|
||||
|
||||
import ifcopenshell.ifcopenshell_wrapper as w
|
||||
|
||||
|
||||
class LateBoundSchemaInstantiator:
|
||||
|
||||
def __init__(self, schema_name):
|
||||
self.schema_name = schema_name
|
||||
self.schema_name_title = schema_name.capitalize()
|
||||
self.schema_name_title = schema_name.capitalize()
|
||||
self.declarations = {}
|
||||
self.names = []
|
||||
# We need to make sure anonymous types are not gc'ed.
|
||||
self.cache = []
|
||||
|
||||
|
||||
def aggregation_type(self, aggr_type, bound1, bound2, decl_type):
|
||||
self.cache.append(w.aggregation_type(getattr(w.aggregation_type, aggr_type + "_type"), bound1, bound2, decl_type))
|
||||
self.cache.append(
|
||||
w.aggregation_type(getattr(w.aggregation_type, aggr_type + "_type"), bound1, bound2, decl_type)
|
||||
)
|
||||
return self.cache[-1]
|
||||
|
||||
|
||||
def simple_type(self, type):
|
||||
self.cache.append(w.simple_type(getattr(w.simple_type, type + "_type")))
|
||||
return self.cache[-1]
|
||||
|
||||
|
||||
def named_type(self, type):
|
||||
self.cache.append(w.named_type(self.declarations[str(type)]))
|
||||
return self.cache[-1]
|
||||
|
||||
|
||||
def declare(self, definition_type, name):
|
||||
self.names.append(str(name))
|
||||
|
||||
|
||||
def begin_schema(self):
|
||||
self.names.sort(key=str.lower)
|
||||
|
||||
|
||||
def typedef(self, name, declared_type):
|
||||
index_in_schema = self.names.index(str(name))
|
||||
self.declarations[str(name)] = w.type_declaration(name, index_in_schema, declared_type)
|
||||
|
||||
|
||||
def enumeration(self, name, enum):
|
||||
schema_name = self.schema_name
|
||||
index_in_schema = self.names.index(str(name))
|
||||
self.declarations[str(name)] = w.enumeration_type(name, index_in_schema, sorted(enum.values))
|
||||
|
||||
|
||||
def entity(self, name, type):
|
||||
index_in_schema = self.names.index(str(name))
|
||||
supertype = None if len(type.supertypes) == 0 else self.declarations[str(type.supertypes[0])]
|
||||
self.declarations[str(name)] = w.entity(name, type.abstract, index_in_schema, supertype)
|
||||
|
||||
|
||||
def select(self, name, type):
|
||||
index_in_schema = self.names.index(str(name))
|
||||
children = [self.declarations[str(v)] for v in type.values]
|
||||
self.declarations[str(name)] = w.select_type(name, index_in_schema, children)
|
||||
|
||||
|
||||
def entity_attributes(self, name, attribute_definitions, is_derived):
|
||||
attributes = []
|
||||
for attr_name, decl_type, optional in attribute_definitions:
|
||||
attributes.append(w.attribute(attr_name, decl_type, optional))
|
||||
self.declarations[str(name)].set_attributes(attributes, is_derived)
|
||||
self.cache.append(attributes)
|
||||
|
||||
|
||||
def inverse_attributes(self, name, inv_attrs):
|
||||
attributes = []
|
||||
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
|
||||
en = self.declarations[str(entity_ref)]
|
||||
attributes.append(w.inverse_attribute(attr_name, getattr(w.inverse_attribute, aggr_type + "_type"), bound1, bound2, en, en.attributes()[attribute_entity_index]))
|
||||
attributes.append(
|
||||
w.inverse_attribute(
|
||||
attr_name,
|
||||
getattr(w.inverse_attribute, aggr_type + "_type"),
|
||||
bound1,
|
||||
bound2,
|
||||
en,
|
||||
en.attributes()[attribute_entity_index],
|
||||
)
|
||||
)
|
||||
self.declarations[str(name)].set_inverse_attributes(attributes)
|
||||
|
||||
|
||||
def entity_subtypes(self, name, tys):
|
||||
self.declarations[str(name)].set_subtypes([self.declarations[str(v)] for v in tys])
|
||||
|
||||
def finalize(self, can_be_instantiated_set, override_schema_name = None):
|
||||
self.schema = w.schema_definition(override_schema_name or self.schema_name, list(self.declarations.values()), None)
|
||||
|
||||
|
||||
def finalize(self, can_be_instantiated_set, override_schema_name=None):
|
||||
self.schema = w.schema_definition(
|
||||
override_schema_name or self.schema_name, list(self.declarations.values()), None
|
||||
)
|
||||
|
||||
|
||||
class EarlyBoundCodeWriter:
|
||||
|
||||
def __init__(self, schema_name):
|
||||
self.schema_name = schema_name
|
||||
self.schema_name_title = schema_name.capitalize()
|
||||
|
||||
self.statements = ['',
|
||||
'#include "../ifcparse/IfcSchema.h"',
|
||||
'#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__,
|
||||
'',
|
||||
'using namespace IfcParse;',
|
||||
'']
|
||||
|
||||
|
||||
self.statements = [
|
||||
"",
|
||||
'#include "../ifcparse/IfcSchema.h"',
|
||||
'#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__,
|
||||
"",
|
||||
"using namespace IfcParse;",
|
||||
"",
|
||||
]
|
||||
|
||||
self.names = []
|
||||
|
||||
|
||||
def aggregation_type(self, aggr_type, bound1, bound2, decl_type):
|
||||
return "new aggregation_type(aggregation_type::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(decl_type)s)" % locals()
|
||||
|
||||
return (
|
||||
"new aggregation_type(aggregation_type::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(decl_type)s)"
|
||||
% locals()
|
||||
)
|
||||
|
||||
def simple_type(self, type):
|
||||
return "new simple_type(simple_type::%s_type)" % type
|
||||
|
||||
|
||||
def named_type(self, type):
|
||||
return "new named_type(%s_%s_type)" % (self.schema_name, type)
|
||||
|
||||
|
||||
def declare(self, definition_type, name):
|
||||
schema_name = self.schema_name
|
||||
self.statements.append('%(definition_type)s* %(schema_name)s_%(name)s_type = 0;' % locals())
|
||||
self.statements.append("%(definition_type)s* %(schema_name)s_%(name)s_type = 0;" % locals())
|
||||
self.names.append(name)
|
||||
|
||||
|
||||
def begin_schema(self):
|
||||
self.names.sort(key=str.lower)
|
||||
|
||||
|
||||
self.statements.append("{factory_placeholder}")
|
||||
|
||||
self.statements.append("""
|
||||
|
||||
self.statements.append(
|
||||
"""
|
||||
#if defined(__clang__)
|
||||
__attribute__((optnone))
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
@@ -138,132 +156,182 @@ __attribute__((optnone))
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma optimize("", off)
|
||||
#endif
|
||||
""")
|
||||
self.statements.append('IfcParse::schema_definition* %s_populate_schema() {' % self.schema_name)
|
||||
|
||||
"""
|
||||
)
|
||||
self.statements.append("IfcParse::schema_definition* %s_populate_schema() {" % self.schema_name)
|
||||
|
||||
def typedef(self, name, declared_type):
|
||||
schema_name = self.schema_name
|
||||
index_in_schema = self.names.index(name)
|
||||
self.statements.append(' %(schema_name)s_%(name)s_type = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);' % locals())
|
||||
|
||||
self.statements.append(
|
||||
' %(schema_name)s_%(name)s_type = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);'
|
||||
% locals()
|
||||
)
|
||||
|
||||
def enumeration(self, name, enum):
|
||||
schema_name = self.schema_name
|
||||
index_in_schema = self.names.index(name)
|
||||
self.statements.append(' {')
|
||||
self.statements.append(' std::vector<std::string> items; items.reserve(%d);' % len(enum.values))
|
||||
self.statements.append(" {")
|
||||
self.statements.append(" std::vector<std::string> items; items.reserve(%d);" % len(enum.values))
|
||||
self.statements.extend(map(lambda v: ' items.push_back("%s");' % v, sorted(enum.values)))
|
||||
self.statements.append(' %(schema_name)s_%(name)s_type = new enumeration_type("%(name)s", %(index_in_schema)d, items);' % locals())
|
||||
self.statements.append(' }')
|
||||
|
||||
self.statements.append(
|
||||
' %(schema_name)s_%(name)s_type = new enumeration_type("%(name)s", %(index_in_schema)d, items);'
|
||||
% locals()
|
||||
)
|
||||
self.statements.append(" }")
|
||||
|
||||
def entity(self, name, type):
|
||||
schema_name = self.schema_name
|
||||
index_in_schema = self.names.index(name)
|
||||
supertype = '0' if len(type.supertypes) == 0 else '%s_%s_type' % (self.schema_name, type.supertypes[0])
|
||||
supertype = "0" if len(type.supertypes) == 0 else "%s_%s_type" % (self.schema_name, type.supertypes[0])
|
||||
is_abstract = "true" if type.abstract else "false"
|
||||
self.statements.append(' %(schema_name)s_%(name)s_type = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, %(supertype)s);' % locals())
|
||||
|
||||
self.statements.append(
|
||||
' %(schema_name)s_%(name)s_type = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, %(supertype)s);'
|
||||
% locals()
|
||||
)
|
||||
|
||||
def select(self, name, type):
|
||||
schema_name = self.schema_name
|
||||
index_in_schema = self.names.index(name)
|
||||
self.statements.append(' {')
|
||||
self.statements.append(' std::vector<const declaration*> items; items.reserve(%d);' % len(type.values))
|
||||
self.statements.extend(map(lambda v: ' items.push_back(%s_%s_type);' % (self.schema_name, v), sorted(map(str, type.values))))
|
||||
self.statements.append(' %(schema_name)s_%(name)s_type = new select_type("%(name)s", %(index_in_schema)d, items);' % locals())
|
||||
self.statements.append(' }')
|
||||
|
||||
self.statements.append(" {")
|
||||
self.statements.append(" std::vector<const declaration*> items; items.reserve(%d);" % len(type.values))
|
||||
self.statements.extend(
|
||||
map(lambda v: " items.push_back(%s_%s_type);" % (self.schema_name, v), sorted(map(str, type.values)))
|
||||
)
|
||||
self.statements.append(
|
||||
' %(schema_name)s_%(name)s_type = new select_type("%(name)s", %(index_in_schema)d, items);'
|
||||
% locals()
|
||||
)
|
||||
self.statements.append(" }")
|
||||
|
||||
def entity_attributes(self, name, attribute_definitions, is_derived):
|
||||
schema_name = self.schema_name
|
||||
self.statements.append(' {')
|
||||
self.statements.append(' std::vector<const attribute*> attributes; attributes.reserve(%d);' % len(attribute_definitions))
|
||||
self.statements.append(" {")
|
||||
self.statements.append(
|
||||
" std::vector<const attribute*> attributes; attributes.reserve(%d);" % len(attribute_definitions)
|
||||
)
|
||||
for attr_name, decl_type, optional in attribute_definitions:
|
||||
optional_cpp = str(optional).lower()
|
||||
self.statements.append(' attributes.push_back(new attribute("%(attr_name)s", %(decl_type)s, %(optional_cpp)s));' % locals())
|
||||
self.statements.append(' std::vector<bool> derived; derived.reserve(%d);' % len(is_derived))
|
||||
self.statements.append(' ' + " ".join(map(lambda b: 'derived.push_back(%s);' % str(b).lower(), is_derived)))
|
||||
self.statements.append(' %(schema_name)s_%(name)s_type->set_attributes(attributes, derived);' % locals())
|
||||
self.statements.append(' }')
|
||||
|
||||
self.statements.append(
|
||||
' attributes.push_back(new attribute("%(attr_name)s", %(decl_type)s, %(optional_cpp)s));'
|
||||
% locals()
|
||||
)
|
||||
self.statements.append(" std::vector<bool> derived; derived.reserve(%d);" % len(is_derived))
|
||||
self.statements.append(
|
||||
" " + " ".join(map(lambda b: "derived.push_back(%s);" % str(b).lower(), is_derived))
|
||||
)
|
||||
self.statements.append(" %(schema_name)s_%(name)s_type->set_attributes(attributes, derived);" % locals())
|
||||
self.statements.append(" }")
|
||||
|
||||
def inverse_attributes(self, name, inv_attrs):
|
||||
schema_name = self.schema_name
|
||||
self.statements.append(' {')
|
||||
self.statements.append(' std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);' % len(inv_attrs))
|
||||
self.statements.append(" {")
|
||||
self.statements.append(
|
||||
" std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);" % len(inv_attrs)
|
||||
)
|
||||
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
|
||||
self.statements.append(' attributes.push_back(new inverse_attribute("%(attr_name)s", inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(schema_name)s_%(entity_ref)s_type, %(schema_name)s_%(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));' % locals())
|
||||
self.statements.append(' %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);' % locals())
|
||||
self.statements.append(' }')
|
||||
|
||||
self.statements.append(
|
||||
' attributes.push_back(new inverse_attribute("%(attr_name)s", inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(schema_name)s_%(entity_ref)s_type, %(schema_name)s_%(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));'
|
||||
% locals()
|
||||
)
|
||||
self.statements.append(" %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);" % locals())
|
||||
self.statements.append(" }")
|
||||
|
||||
def entity_subtypes(self, name, tys):
|
||||
schema_name = self.schema_name
|
||||
self.statements.append(' {')
|
||||
self.statements.append(' std::vector<const entity*> defs; defs.reserve(%d);' % len(tys))
|
||||
self.statements.append((' ' + "".join(map(lambda t: ("defs.push_back(%%(schema_name)s_%s_type);" % t), tys))) % locals())
|
||||
self.statements.append(' %(schema_name)s_%(name)s_type->set_subtypes(defs);' % locals())
|
||||
self.statements.append(' }')
|
||||
|
||||
self.statements.append(" {")
|
||||
self.statements.append(" std::vector<const entity*> defs; defs.reserve(%d);" % len(tys))
|
||||
self.statements.append(
|
||||
(" " + "".join(map(lambda t: ("defs.push_back(%%(schema_name)s_%s_type);" % t), tys))) % locals()
|
||||
)
|
||||
self.statements.append(" %(schema_name)s_%(name)s_type->set_subtypes(defs);" % locals())
|
||||
self.statements.append(" }")
|
||||
|
||||
def finalize(self, can_be_instantiated_set):
|
||||
schema_name = self.schema_name
|
||||
schema_name_title = self.schema_name.capitalize()
|
||||
|
||||
|
||||
num_declarations = len(self.names)
|
||||
|
||||
self.statements.append('')
|
||||
self.statements.append(' std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);' % locals())
|
||||
|
||||
self.statements.append("")
|
||||
self.statements.append(
|
||||
" std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);" % locals()
|
||||
)
|
||||
for type_name in self.names:
|
||||
self.statements.append(' declarations.push_back(%(schema_name)s_%(type_name)s_type);' % locals())
|
||||
|
||||
self.statements.append(' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());' % locals())
|
||||
|
||||
self.statements.extend(('}',''))
|
||||
|
||||
self.statements.append("""
|
||||
self.statements.append(" declarations.push_back(%(schema_name)s_%(type_name)s_type);" % locals())
|
||||
|
||||
self.statements.append(
|
||||
' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());'
|
||||
% locals()
|
||||
)
|
||||
|
||||
self.statements.extend(("}", ""))
|
||||
|
||||
self.statements.append(
|
||||
"""
|
||||
#if defined(__clang__)
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC pop_options
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
""")
|
||||
|
||||
self.statements.extend(('const schema_definition& %s::get_schema() {' % schema_name_title,
|
||||
'',
|
||||
' static const schema_definition* s = %(schema_name)s_populate_schema();' % locals(),
|
||||
' return *s;',
|
||||
'}','',''))
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
self.statements.extend(
|
||||
(
|
||||
"const schema_definition& %s::get_schema() {" % schema_name_title,
|
||||
"",
|
||||
" static const schema_definition* s = %(schema_name)s_populate_schema();" % locals(),
|
||||
" return *s;",
|
||||
"}",
|
||||
"",
|
||||
"",
|
||||
)
|
||||
)
|
||||
|
||||
def can_be_instantiated(idx_name):
|
||||
name = idx_name[1]
|
||||
return name in can_be_instantiated_set
|
||||
|
||||
|
||||
instance_mapping = """switch(data->type()->index_in_schema()) {
|
||||
%s
|
||||
default: throw IfcParse::IfcException(data->type()->name() + " cannot be instantiated");
|
||||
}
|
||||
""" % "\n ".join(map(lambda tup: ("case %%d: return new ::%s::%%s(data);" % schema_name_title) % tup, filter(can_be_instantiated, enumerate(self.names))))
|
||||
""" % "\n ".join(
|
||||
map(
|
||||
lambda tup: ("case %%d: return new ::%s::%%s(data);" % schema_name_title) % tup,
|
||||
filter(can_be_instantiated, enumerate(self.names)),
|
||||
)
|
||||
)
|
||||
|
||||
self.statements[self.statements.index("{factory_placeholder}")] = """
|
||||
self.statements[self.statements.index("{factory_placeholder}")] = (
|
||||
"""
|
||||
class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
|
||||
virtual IfcUtil::IfcBaseClass* operator()(IfcEntityInstanceData* data) const {
|
||||
%(instance_mapping)s
|
||||
}
|
||||
};
|
||||
""" % locals()
|
||||
"""
|
||||
% locals()
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return "\n".join(self.statements)
|
||||
return "\n".join(self.statements)
|
||||
|
||||
|
||||
class SchemaClass(codegen.Base):
|
||||
def __init__(self, mapping, code=EarlyBoundCodeWriter):
|
||||
|
||||
class UnmetDependenciesException(Exception): pass
|
||||
|
||||
class UnmetDependenciesException(Exception):
|
||||
pass
|
||||
|
||||
schema_name = mapping.schema.name
|
||||
self.schema_name = schema_name_title = schema_name.capitalize()
|
||||
|
||||
declared_types = []
|
||||
|
||||
|
||||
x = code(schema_name)
|
||||
|
||||
|
||||
def get_declared_type(type, emitted_names=None):
|
||||
if isinstance(type, nodes.SimpleType):
|
||||
type = type.type
|
||||
@@ -272,7 +340,7 @@ class SchemaClass(codegen.Base):
|
||||
|
||||
if isinstance(type, nodes.AggregationType):
|
||||
aggr_type = type.aggregate_type
|
||||
make_bound = lambda b: -1 if b == '?' else int(b)
|
||||
make_bound = lambda b: -1 if b == "?" else int(b)
|
||||
bound1, bound2 = map(make_bound, (type.bounds.lower, type.bounds.upper))
|
||||
decl_type = get_declared_type(type.type, emitted_names)
|
||||
return x.aggregation_type(aggr_type, bound1, bound2, decl_type)
|
||||
@@ -295,38 +363,41 @@ class SchemaClass(codegen.Base):
|
||||
attributes_per_subtype = []
|
||||
while True:
|
||||
entity = mapping.schema.entities[entity_name]
|
||||
attr_names = list(map(operator.attrgetter('name'), entity.attributes))
|
||||
attr_names = list(map(operator.attrgetter("name"), entity.attributes))
|
||||
if len(attr_names):
|
||||
attributes_per_subtype.append((entity_name, attr_names))
|
||||
if len(entity.supertypes) != 1: break
|
||||
if len(entity.supertypes) != 1:
|
||||
break
|
||||
entity_name = entity.supertypes[0]
|
||||
index = 0
|
||||
for et, attrs in attributes_per_subtype[::-1]:
|
||||
try: return et, attrs.index(attribute_name)
|
||||
except: pass
|
||||
|
||||
try:
|
||||
return et, attrs.index(attribute_name)
|
||||
except:
|
||||
pass
|
||||
|
||||
else:
|
||||
raise Exception("No declared type for <%r>" % type)
|
||||
|
||||
|
||||
|
||||
collections_by_type = (('entity', mapping.schema.entities ),
|
||||
('type_declaration', mapping.schema.simpletypes ),
|
||||
('select_type', mapping.schema.selects ),
|
||||
('enumeration_type', mapping.schema.enumerations))
|
||||
collections_by_type = (
|
||||
("entity", mapping.schema.entities),
|
||||
("type_declaration", mapping.schema.simpletypes),
|
||||
("select_type", mapping.schema.selects),
|
||||
("enumeration_type", mapping.schema.enumerations),
|
||||
)
|
||||
|
||||
for definition_type, collection in collections_by_type:
|
||||
for name in collection.keys():
|
||||
x.declare(definition_type, name)
|
||||
|
||||
|
||||
declarations_by_index = []
|
||||
|
||||
|
||||
x.begin_schema()
|
||||
|
||||
|
||||
emitted = set()
|
||||
len_to_emit = len(mapping.schema)
|
||||
|
||||
def write_simpletype(schema_name, name, type):
|
||||
|
||||
def write_simpletype(schema_name, name, type):
|
||||
try:
|
||||
declared_type = get_declared_type(type, emitted)
|
||||
except UnmetDependenciesException:
|
||||
@@ -335,20 +406,22 @@ class SchemaClass(codegen.Base):
|
||||
return False
|
||||
|
||||
x.typedef(name, declared_type)
|
||||
|
||||
|
||||
def write_enumeration(schema_name, name, enum):
|
||||
x.enumeration(name, enum)
|
||||
|
||||
|
||||
def write_entity(schema_name, name, type):
|
||||
if len(type.supertypes) == 0 or set(map(lambda s: s.lower(), type.supertypes)) < emitted:
|
||||
x.entity(name, type)
|
||||
else: return False
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
def write_select(schema_name, name, type):
|
||||
if set(map(lambda s: str(s).lower(), type.values)) < emitted:
|
||||
x.select(name, type)
|
||||
else: return False
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
def write(name):
|
||||
if mapping.schema.is_simpletype(name):
|
||||
fn = write_simpletype
|
||||
@@ -358,64 +431,69 @@ class SchemaClass(codegen.Base):
|
||||
fn = write_entity
|
||||
elif mapping.schema.is_select(name):
|
||||
fn = write_select
|
||||
|
||||
|
||||
decl = mapping.schema[name]
|
||||
if isinstance(decl, nodes.TypeDeclaration):
|
||||
decl = decl.type
|
||||
return fn(schema_name, name, decl) is not False
|
||||
|
||||
|
||||
while len(emitted) < len_to_emit:
|
||||
for name in mapping.schema:
|
||||
if name.lower() in emitted: continue
|
||||
if name.lower() in emitted:
|
||||
continue
|
||||
if write(name):
|
||||
emitted.add(name.lower())
|
||||
declarations_by_index.append(name)
|
||||
declared_types.append('%(schema_name)s_%(name)s_type' % locals())
|
||||
declared_types.append("%(schema_name)s_%(name)s_type" % locals())
|
||||
|
||||
num_declarations = len(declared_types)
|
||||
|
||||
|
||||
for name, type in mapping.schema.entities.items():
|
||||
derived = set(mapping.derived_in_supertype(type))
|
||||
attribute_names = list(map(operator.attrgetter('name'), mapping.arguments(type)))
|
||||
attribute_names = list(map(operator.attrgetter("name"), mapping.arguments(type)))
|
||||
is_derived = [b in derived for b in attribute_names]
|
||||
attribute_definitions = []
|
||||
for attr in type.attributes:
|
||||
decl_type = get_declared_type(attr.type)
|
||||
attribute_definitions.append((attr.name, decl_type, attr.optional))
|
||||
x.entity_attributes(name, attribute_definitions, is_derived)
|
||||
|
||||
|
||||
for name, type in mapping.schema.entities.items():
|
||||
if type.inverse:
|
||||
inv_attrs = []
|
||||
for attr in type.inverse:
|
||||
if attr.bounds:
|
||||
make_bound = lambda b: -1 if b == '?' else int(b)
|
||||
make_bound = lambda b: -1 if b == "?" else int(b)
|
||||
bound1, bound2 = map(make_bound, (attr.bounds.lower, attr.bounds.upper))
|
||||
else:
|
||||
bound1, bound2 = -1, -1
|
||||
attr_name, aggr_type, entity_ref = attr.name, attr.type, attr.entity
|
||||
if aggr_type is None: aggr_type = 'unspecified'
|
||||
if aggr_type is None:
|
||||
aggr_type = "unspecified"
|
||||
attribute_entity, attribute_entity_index = find_inverse_name_and_index(entity_ref, attr.attribute)
|
||||
inv_attrs.append((attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index))
|
||||
inv_attrs.append(
|
||||
(attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index)
|
||||
)
|
||||
x.inverse_attributes(name, inv_attrs)
|
||||
|
||||
|
||||
subtypes = defaultdict(list)
|
||||
|
||||
|
||||
for name, type in mapping.schema.entities.items():
|
||||
for ty in type.supertypes:
|
||||
subtypes[ty].append(name)
|
||||
|
||||
|
||||
for name, tys in subtypes.items():
|
||||
x.entity_subtypes(name, tys)
|
||||
|
||||
|
||||
can_be_instantiated_set = set(list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys()))
|
||||
x.finalize(can_be_instantiated_set)
|
||||
|
||||
|
||||
self.str = str(x)
|
||||
self.file_name = '%s-schema.cpp' % self.schema_name
|
||||
self.file_name = "%s-schema.cpp" % self.schema_name
|
||||
self.code = x
|
||||
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
|
||||
|
||||
Generator = SchemaClass
|
||||
|
||||
@@ -65,7 +65,7 @@ enum_header = """
|
||||
|
||||
lb_header = """"""
|
||||
|
||||
implementation= """
|
||||
implementation = """
|
||||
#include "../ifcparse/%(schema_name)s.h"
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
@@ -103,8 +103,8 @@ enumeration_descriptor = """ values.clear(); values.reserve(128);
|
||||
|
||||
enumeration_descriptor_value = ' values.push_back("%(name)s");'
|
||||
|
||||
derived_field_statement = ' {std::set<int> idxs; %(statements)sderived_map[Type::%(type)s] = idxs;}';
|
||||
derived_field_statement_attrs = 'idxs.insert(%d); '
|
||||
derived_field_statement = " {std::set<int> idxs; %(statements)sderived_map[Type::%(type)s] = idxs;}"
|
||||
derived_field_statement_attrs = "idxs.insert(%d); "
|
||||
|
||||
simpletype = """%(documentation)s
|
||||
class IFC_PARSE_API %(name)s : public %(superclass)s {
|
||||
@@ -118,19 +118,24 @@ public:
|
||||
"""
|
||||
|
||||
simpletype_impl_comment = "// Function implementations for %(name)s"
|
||||
simpletype_impl_argument_type = "if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException(\"Argument index out of range\"); }"
|
||||
simpletype_impl_argument_type = 'if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); }'
|
||||
simpletype_impl_argument = "return data_->getArgument(i);"
|
||||
simpletype_impl_is_with_supertype = "return v == %(class_name)s_type || %(superclass)s::is(v);"
|
||||
simpletype_impl_is_without_supertype = "return v == %(class_name)s_type;"
|
||||
simpletype_impl_type = "return *%(schema_name_upper)s_%(class_name)s_type;"
|
||||
simpletype_impl_class = "return *%(schema_name_upper)s_%(class_name)s_type;"
|
||||
simpletype_impl_explicit_constructor = "data_ = e;"
|
||||
simpletype_impl_constructor = "data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v" +"); data_->setArgument(0, attr);}"
|
||||
simpletype_impl_constructor = (
|
||||
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v"
|
||||
+ "); data_->setArgument(0, attr);}"
|
||||
)
|
||||
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(%(schema_name_upper)s_%(class_name)s_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v->generalize()); data_->setArgument(0, attr);}"
|
||||
simpletype_impl_cast = "return *data_->getArgument(0);"
|
||||
simpletype_impl_cast_templated = "IfcEntityList::ptr es = *data_->getArgument(0); return es->as< %(underlying_type)s >();"
|
||||
simpletype_impl_cast_templated = (
|
||||
"IfcEntityList::ptr es = *data_->getArgument(0); return es->as< %(underlying_type)s >();"
|
||||
)
|
||||
simpletype_impl_declaration = "return *%(schema_name_upper)s_%(class_name)s_type;"
|
||||
|
||||
|
||||
select = """%(documentation)s
|
||||
typedef IfcUtil::IfcBaseClass %(name)s;
|
||||
"""
|
||||
@@ -154,7 +159,7 @@ public:
|
||||
};
|
||||
"""
|
||||
|
||||
enumeration_function="""
|
||||
enumeration_function = """
|
||||
const char* %(schema_name)s::%(name)s::ToString(Value v) {
|
||||
if ( v < 0 || v >= %(max_id)d ) throw IfcException("Unable to find find keyword in schema");
|
||||
const char* names[] = { %(values)s };
|
||||
@@ -181,7 +186,9 @@ optional_attribute_description = "/// Whether the optional attribute %s is defin
|
||||
function = "%(return_type)s %(schema_name)s::%(class_name)s::%(name)s(%(arguments)s) { %(body)s }"
|
||||
const_function = "%(return_type)s %(schema_name)s::%(class_name)s::%(name)s(%(arguments)s) const { %(body)s }"
|
||||
constructor = "%(schema_name)s::%(class_name)s::%(class_name)s(%(arguments)s) { %(body)s }"
|
||||
constructor_single_initlist = "%(schema_name)s::%(class_name)s::%(class_name)s(%(arguments)s) : %(superclass)s(%(superclass_init)s) { %(body)s }"
|
||||
constructor_single_initlist = (
|
||||
"%(schema_name)s::%(class_name)s::%(class_name)s(%(arguments)s) : %(superclass)s(%(superclass_init)s) { %(body)s }"
|
||||
)
|
||||
cast_function = "%(schema_name)s::%(class_name)s::operator %(return_type)s() const { %(body)s }"
|
||||
|
||||
array_type = "std::vector< %(instance_type)s > /*[%(lower)s:%(upper)s]*/"
|
||||
@@ -193,9 +200,9 @@ inverse_attr = "IfcTemplatedEntityList< %(entity)s >::ptr %(name)s() const; // I
|
||||
|
||||
enum_from_string_stmt = ' if (s == "%(value)s") return ::%(schema_name)s::%(name)s::%(short_name)s_%(value)s;'
|
||||
|
||||
schema_entity_stmt = ' case Type::%(name)s: return new %(name)s(e); break;'
|
||||
schema_entity_stmt = " case Type::%(name)s: return new %(name)s(e); break;"
|
||||
string_map_statement = ' string_map["%(uppercase_name)s"%(padding)s] = Type::%(name)s;'
|
||||
parent_type_stmt = ' if(v==%(name)s%(padding)s) { return %(parent)s; }'
|
||||
parent_type_stmt = " if(v==%(name)s%(padding)s) { return %(parent)s; }"
|
||||
|
||||
parent_type_test = " || %s::is(v)"
|
||||
|
||||
@@ -204,24 +211,46 @@ optional_attr_stmt = "return !data_->getArgument(%(index)d)->isNull();"
|
||||
get_attr_stmt = "return *data_->getArgument(%(index)d);"
|
||||
get_attr_stmt_enum = "return %(type)s::FromString(*data_->getArgument(%(index)d));"
|
||||
get_attr_stmt_entity = "return (%(type)s)((IfcUtil::IfcBaseClass*)(*data_->getArgument(%(index)d)));"
|
||||
get_attr_stmt_array = "IfcEntityList::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
|
||||
get_attr_stmt_nested_array = "IfcEntityListList::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
|
||||
get_attr_stmt_array = (
|
||||
"IfcEntityList::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
|
||||
)
|
||||
get_attr_stmt_nested_array = (
|
||||
"IfcEntityListList::ptr es = *data_->getArgument(%(index)d); return es->as< %(list_instance_type)s >();"
|
||||
)
|
||||
|
||||
get_inverse = "return data_->getInverse(%(schema_name_upper)s_%(type)s_type, %(index)d)->as<%(type)s>();"
|
||||
|
||||
set_attr_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v" +");data_->setArgument(%(index)d,attr);}"
|
||||
set_attr_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,%(type)s::ToString(v)));data_->setArgument(%(index)d,attr);}"
|
||||
set_attr_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize()" +");data_->setArgument(%(index)d,attr);}"
|
||||
set_attr_stmt = (
|
||||
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v"
|
||||
+ ");data_->setArgument(%(index)d,attr);}"
|
||||
)
|
||||
set_attr_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,%(type)s::ToString(v)));data_->setArgument(%(index)d,attr);}"
|
||||
set_attr_stmt_array = (
|
||||
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize()"
|
||||
+ ");data_->setArgument(%(index)d,attr);}"
|
||||
)
|
||||
|
||||
constructor_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)" +");data_->setArgument(%(index)d,attr);}"
|
||||
constructor_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(%(name)s,%(type)s::ToString(%(name)s)))" +");data_->setArgument(%(index)d,attr);}"
|
||||
constructor_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)->generalize()" +");data_->setArgument(%(index)d,attr);}"
|
||||
constructor_stmt_derived = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::Derived()" +");data_->setArgument(%(index)d,attr);}"
|
||||
constructor_stmt = (
|
||||
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)"
|
||||
+ ");data_->setArgument(%(index)d,attr);}"
|
||||
)
|
||||
constructor_stmt_enum = (
|
||||
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(%(name)s,%(type)s::ToString(%(name)s)))"
|
||||
+ ");data_->setArgument(%(index)d,attr);}"
|
||||
)
|
||||
constructor_stmt_array = (
|
||||
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)->generalize()"
|
||||
+ ");data_->setArgument(%(index)d,attr);}"
|
||||
)
|
||||
constructor_stmt_derived = (
|
||||
"{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::Derived()"
|
||||
+ ");data_->setArgument(%(index)d,attr);}"
|
||||
)
|
||||
|
||||
constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(%(index)d, attr); }"
|
||||
|
||||
inverse_implementation = " inverse_map[Type::%(type)s].insert(std::make_pair(\"%(name)s\", std::make_pair(Type::%(related_type)s, %(index)d)));"
|
||||
inverse_implementation = ' inverse_map[Type::%(type)s].insert(std::make_pair("%(name)s", std::make_pair(Type::%(related_type)s, %(index)d)));'
|
||||
|
||||
|
||||
def multi_line_comment(li):
|
||||
return ("/// %s"%("\n/// ".join(li))) if len(li) else ""
|
||||
|
||||
return ("/// %s" % ("\n/// ".join(li))) if len(li) else ""
|
||||
|
||||
@@ -51,6 +51,7 @@ class file(object):
|
||||
print(products[0] == ifc_file[122] == ifc_file['2XQ$n5SLP5MBLyL442paFx'])
|
||||
>>> True
|
||||
"""
|
||||
|
||||
def __init__(self, f=None, schema=None):
|
||||
if f is not None:
|
||||
self.wrapped_data = f
|
||||
@@ -82,14 +83,13 @@ class file(object):
|
||||
e = entity_instance((self.schema, type))
|
||||
self.wrapped_data.add(e.wrapped_data)
|
||||
e.wrapped_data.this.disown()
|
||||
attrs = list(enumerate(args)) + \
|
||||
[(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
||||
attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
||||
for idx, arg in attrs:
|
||||
e[idx] = arg
|
||||
return e
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr[0:6] == 'create':
|
||||
if attr[0:6] == "create":
|
||||
return functools.partial(self.create_entity, attr[6:])
|
||||
else:
|
||||
return getattr(self.wrapped_data, attr)
|
||||
|
||||
@@ -21,15 +21,18 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
def _has_occ():
|
||||
try:
|
||||
import OCC.Core.BRepTools
|
||||
|
||||
return True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import OCC.BRepTools
|
||||
|
||||
return True
|
||||
except ImportError:
|
||||
pass
|
||||
@@ -41,5 +44,5 @@ has_occ = _has_occ()
|
||||
|
||||
if has_occ:
|
||||
from . import occ_utils as utils
|
||||
|
||||
|
||||
from .main import *
|
||||
|
||||
@@ -12,9 +12,10 @@ import multiprocessing
|
||||
import OCC.AIS
|
||||
|
||||
from collections import defaultdict, OrderedDict
|
||||
|
||||
try: # python 3.3+
|
||||
from collections.abc import Iterable
|
||||
except ModuleNotFoundError: # python 2
|
||||
except ModuleNotFoundError: # python 2
|
||||
from collections import Iterable
|
||||
|
||||
try:
|
||||
@@ -23,7 +24,7 @@ except NameError:
|
||||
# Python 3
|
||||
QString = str
|
||||
|
||||
os.environ['QT_API'] = 'pyqt5'
|
||||
os.environ["QT_API"] = "pyqt5"
|
||||
try:
|
||||
from pyqode.qt import QtCore
|
||||
except BaseException:
|
||||
@@ -59,11 +60,13 @@ from .. import version as ifcopenshell_version
|
||||
if ifcopenshell_version < "0.6":
|
||||
# not yet ported
|
||||
from .. import get_supertype
|
||||
|
||||
|
||||
|
||||
class geometry_creation_signals(QtCore.QObject):
|
||||
completed = QtCore.pyqtSignal('PyQt_PyObject')
|
||||
progress = QtCore.pyqtSignal('PyQt_PyObject')
|
||||
|
||||
completed = QtCore.pyqtSignal("PyQt_PyObject")
|
||||
progress = QtCore.pyqtSignal("PyQt_PyObject")
|
||||
|
||||
|
||||
class geometry_creation_thread(QtCore.QThread):
|
||||
def __init__(self, signals, settings, f):
|
||||
QtCore.QThread.__init__(self)
|
||||
@@ -82,25 +85,27 @@ class geometry_creation_thread(QtCore.QThread):
|
||||
if not it.initialize():
|
||||
self.signals.completed.emit([])
|
||||
return
|
||||
|
||||
|
||||
def _():
|
||||
|
||||
old_progress = -1
|
||||
while True:
|
||||
shape = it.get()
|
||||
|
||||
|
||||
if shape:
|
||||
yield shape
|
||||
|
||||
|
||||
if not it.next():
|
||||
break
|
||||
|
||||
self.signals.completed.emit((it, self.f, list(_())))
|
||||
|
||||
|
||||
class configuration(object):
|
||||
def __init__(self):
|
||||
try:
|
||||
import ConfigParser
|
||||
|
||||
Cfg = ConfigParser.RawConfigParser
|
||||
except BaseException:
|
||||
import configparser
|
||||
@@ -122,7 +127,11 @@ class configuration(object):
|
||||
if not os.path.exists(conf_file):
|
||||
config = Cfg()
|
||||
config.add_section("snippets")
|
||||
config.set("snippets", "print all wall ids", self.config_encode("""
|
||||
config.set(
|
||||
"snippets",
|
||||
"print all wall ids",
|
||||
self.config_encode(
|
||||
"""
|
||||
###########################################################################
|
||||
# A simple script that iterates over all walls in the current model #
|
||||
# and prints their Globally unique IDs (GUIDS) to the console window #
|
||||
@@ -130,9 +139,15 @@ class configuration(object):
|
||||
|
||||
for wall in model.by_type("IfcWall"):
|
||||
print ("wall with global id: "+str(wall.GlobalId))
|
||||
""".lstrip()))
|
||||
""".lstrip()
|
||||
),
|
||||
)
|
||||
|
||||
config.set("snippets", "print properties of current selection", self.config_encode("""
|
||||
config.set(
|
||||
"snippets",
|
||||
"print properties of current selection",
|
||||
self.config_encode(
|
||||
"""
|
||||
###########################################################################
|
||||
# A simple script that iterates over all IfcPropertySets of the currently #
|
||||
# selected object and prints them to the console #
|
||||
@@ -147,8 +162,10 @@ if selection:
|
||||
for prop in relDefinesByProperties.RelatingPropertyDefinition.HasProperties:
|
||||
print ("{:<20} :{}".format(prop.Name,prop.NominalValue.wrappedValue))
|
||||
print ("\\n")
|
||||
""".lstrip()))
|
||||
with open(conf_file, 'w') as configfile:
|
||||
""".lstrip()
|
||||
),
|
||||
)
|
||||
with open(conf_file, "w") as configfile:
|
||||
config.write(configfile)
|
||||
|
||||
self.config = Cfg()
|
||||
@@ -191,7 +208,7 @@ class application(QtWidgets.QApplication):
|
||||
action = menu.exec_(self.mapToGlobal(event.pos()))
|
||||
index = self.selectionModel().currentIndex()
|
||||
inst = index.data(QtCore.Qt.UserRole)
|
||||
if hasattr(inst, 'toPyObject'):
|
||||
if hasattr(inst, "toPyObject"):
|
||||
inst = inst
|
||||
if action in visibility:
|
||||
self.instanceVisibilityChanged.emit(inst, visibility.index(action))
|
||||
@@ -200,7 +217,7 @@ class application(QtWidgets.QApplication):
|
||||
|
||||
def clicked_(self, index):
|
||||
inst = index.data(QtCore.Qt.UserRole)
|
||||
if hasattr(inst, 'toPyObject'):
|
||||
if hasattr(inst, "toPyObject"):
|
||||
inst = inst
|
||||
if inst:
|
||||
self.instanceSelected.emit(inst)
|
||||
@@ -209,14 +226,15 @@ class application(QtWidgets.QApplication):
|
||||
itm = self.product_to_item.get(product)
|
||||
if itm is None:
|
||||
return
|
||||
self.selectionModel().setCurrentIndex(itm,
|
||||
QtCore.QItemSelectionModel.SelectCurrent | QtCore.QItemSelectionModel.Rows)
|
||||
self.selectionModel().setCurrentIndex(
|
||||
itm, QtCore.QItemSelectionModel.SelectCurrent | QtCore.QItemSelectionModel.Rows
|
||||
)
|
||||
|
||||
class decomposition_treeview(abstract_treeview):
|
||||
|
||||
"""Treeview with typical IFC decomposition relationships"""
|
||||
|
||||
ATTRIBUTES = ['Entity', 'GlobalId', 'Name']
|
||||
ATTRIBUTES = ["Entity", "GlobalId", "Name"]
|
||||
|
||||
def parent(self, instance):
|
||||
if instance.is_a("IfcOpeningElement"):
|
||||
@@ -247,10 +265,10 @@ class application(QtWidgets.QApplication):
|
||||
if (parent is None or parent in items) and product not in items:
|
||||
sl = []
|
||||
for attr in ATTRS:
|
||||
if attr == 'Entity':
|
||||
if attr == "Entity":
|
||||
sl.append(product.is_a())
|
||||
else:
|
||||
sl.append(getattr(product, attr) or '')
|
||||
sl.append(getattr(product, attr) or "")
|
||||
itm = items[product] = QtWidgets.QTreeWidgetItem(items.get(parent, self), sl)
|
||||
itm.setData(0, QtCore.Qt.UserRole, product)
|
||||
self.children[parent].append(product)
|
||||
@@ -262,13 +280,14 @@ class application(QtWidgets.QApplication):
|
||||
|
||||
"""Treeview with typical IFC decomposition relationships"""
|
||||
|
||||
ATTRIBUTES = ['Name']
|
||||
ATTRIBUTES = ["Name"]
|
||||
|
||||
def load_file(self, f, **kwargs):
|
||||
products = list(f.by_type("IfcProduct"))
|
||||
types = set(map(lambda i: i.is_a(), products))
|
||||
items = {}
|
||||
for t in types:
|
||||
|
||||
def add(t):
|
||||
s = get_supertype(t)
|
||||
if s:
|
||||
@@ -284,7 +303,7 @@ class application(QtWidgets.QApplication):
|
||||
|
||||
for p in products:
|
||||
t = QString(p.is_a())
|
||||
itm = items[p] = QtWidgets.QTreeWidgetItem(items.get(t, self), [p.Name or '<no name>'])
|
||||
itm = items[p] = QtWidgets.QTreeWidgetItem(items.get(t, self), [p.Name or "<no name>"])
|
||||
itm.setData(0, QtCore.Qt.UserRole, t)
|
||||
self.children[t].append(p)
|
||||
|
||||
@@ -293,7 +312,6 @@ class application(QtWidgets.QApplication):
|
||||
self.expandAll()
|
||||
|
||||
class property_table(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self):
|
||||
QtWidgets.QWidget.__init__(self)
|
||||
self.layout = QtWidgets.QVBoxLayout(self)
|
||||
@@ -338,7 +356,7 @@ class application(QtWidgets.QApplication):
|
||||
value_str = value_str.wrappedValue
|
||||
|
||||
if isinstance(value_str, unicode):
|
||||
value_str = value_str.encode('utf-8')
|
||||
value_str = value_str.encode("utf-8")
|
||||
else:
|
||||
value_str = str(value_str)
|
||||
|
||||
@@ -392,6 +410,7 @@ class application(QtWidgets.QApplication):
|
||||
propsets.append(process_pset(propset))
|
||||
except Exception as e:
|
||||
import traceback
|
||||
|
||||
print("failed to load properties: {}".format(e))
|
||||
traceback.print_exc()
|
||||
|
||||
@@ -408,7 +427,7 @@ class application(QtWidgets.QApplication):
|
||||
def ais_to_key(ais_handle):
|
||||
def yield_shapes():
|
||||
ais = ais_handle.GetObject()
|
||||
if hasattr(ais, 'Shape'):
|
||||
if hasattr(ais, "Shape"):
|
||||
yield ais.Shape()
|
||||
return
|
||||
shp = OCC.AIS.Handle_AIS_Shape.DownCast(ais_handle)
|
||||
@@ -444,7 +463,7 @@ class application(QtWidgets.QApplication):
|
||||
def finished(self, file_shapes):
|
||||
it, f, shapes = file_shapes
|
||||
v = self._display
|
||||
|
||||
|
||||
t = {0: time.time()}
|
||||
|
||||
def update(dt=None):
|
||||
@@ -453,29 +472,29 @@ class application(QtWidgets.QApplication):
|
||||
v.FitAll()
|
||||
v.Repaint()
|
||||
t[0] = t1
|
||||
|
||||
|
||||
for shape in shapes:
|
||||
ais = display_shape(shape, viewer_handle=v)
|
||||
product = f[shape.data.id]
|
||||
|
||||
|
||||
ais.GetObject().SetSelectionPriority(self.counter)
|
||||
self.ais_to_product[self.counter] = product
|
||||
self.product_to_ais[product] = ais
|
||||
self.counter += 1
|
||||
|
||||
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
||||
if product.is_a() in {'IfcSpace', 'IfcOpeningElement'}:
|
||||
|
||||
if product.is_a() in {"IfcSpace", "IfcOpeningElement"}:
|
||||
v.Context.Erase(ais, True)
|
||||
|
||||
update(1.)
|
||||
|
||||
|
||||
update(1.0)
|
||||
|
||||
update()
|
||||
|
||||
|
||||
self.thread = None
|
||||
|
||||
|
||||
def load_file(self, f, setting=None):
|
||||
|
||||
|
||||
if self.thread is not None:
|
||||
return
|
||||
|
||||
@@ -483,10 +502,10 @@ class application(QtWidgets.QApplication):
|
||||
setting = settings()
|
||||
setting.set(setting.INCLUDE_CURVES, True)
|
||||
setting.set(setting.USE_PYTHON_OPENCASCADE, True)
|
||||
|
||||
|
||||
self.signals = geometry_creation_signals()
|
||||
thread = self.thread = geometry_creation_thread(self.signals, setting, f)
|
||||
self.window.window_closed.connect(lambda *args: thread.terminate())
|
||||
self.window.window_closed.connect(lambda *args: thread.terminate())
|
||||
self.signals.completed.connect(self.finished)
|
||||
self.thread.start()
|
||||
|
||||
@@ -509,23 +528,31 @@ class application(QtWidgets.QApplication):
|
||||
def toggle_visibility(self, product_or_products, flag):
|
||||
v = self._display.Context
|
||||
if flag:
|
||||
|
||||
def visibility(ais, last):
|
||||
v.Erase(ais, last)
|
||||
|
||||
else:
|
||||
|
||||
def visibility(ais, last):
|
||||
v.Display(ais, last)
|
||||
|
||||
self.toggle(product_or_products, visibility)
|
||||
|
||||
def toggle_wireframe(self, product_or_products, flag):
|
||||
v = self._display.Context
|
||||
if flag:
|
||||
|
||||
def wireframe(ais, last):
|
||||
if v.IsDisplayed(ais):
|
||||
v.SetDisplayMode(ais, 0, last)
|
||||
|
||||
else:
|
||||
|
||||
def wireframe(ais, last):
|
||||
if v.IsDisplayed(ais):
|
||||
v.SetDisplayMode(ais, 1, last)
|
||||
|
||||
self.toggle(product_or_products, wireframe)
|
||||
|
||||
def HandleSelection(self, X, Y):
|
||||
@@ -588,12 +615,12 @@ class application(QtWidgets.QApplication):
|
||||
self.window.resize(800, 600)
|
||||
splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
splitter.addWidget(self.tabs)
|
||||
self.tabs.addTab(self.tree, 'Decomposition')
|
||||
self.tabs.addTab(self.tree2, 'Types')
|
||||
self.tabs.addTab(self.tree, "Decomposition")
|
||||
self.tabs.addTab(self.tree2, "Types")
|
||||
self.tabs.addTab(self.propview, "Properties")
|
||||
splitter2 = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||
splitter2.addWidget(self.canvas)
|
||||
self.editor = code_edit(self.canvas, configuration().options('snippets'))
|
||||
self.editor = code_edit(self.canvas, configuration().options("snippets"))
|
||||
splitter2.addWidget(self.editor)
|
||||
splitter.addWidget(splitter2)
|
||||
splitter.setSizes([200, 600])
|
||||
@@ -603,9 +630,9 @@ class application(QtWidgets.QApplication):
|
||||
self.components = [self.tree, self.tree2, self.canvas, self.propview, self.editor]
|
||||
self.files = {}
|
||||
|
||||
self.window.add_menu_item('File', '&Open', self.browse, shortcut='CTRL+O')
|
||||
self.window.add_menu_item('File', '&Close', self.clear, shortcut='CTRL+W')
|
||||
self.window.add_menu_item('File', '&Exit', self.window.close, shortcut='ALT+F4')
|
||||
self.window.add_menu_item("File", "&Open", self.browse, shortcut="CTRL+O")
|
||||
self.window.add_menu_item("File", "&Close", self.clear, shortcut="CTRL+W")
|
||||
self.window.add_menu_item("File", "&Exit", self.window.close, shortcut="ALT+F4")
|
||||
|
||||
self.tree.instanceSelected.connect(self.makeSelectionHandler(self.tree))
|
||||
self.tree2.instanceSelected.connect(self.makeSelectionHandler(self.tree2))
|
||||
@@ -629,8 +656,9 @@ class application(QtWidgets.QApplication):
|
||||
sys.exit(self.exec_())
|
||||
|
||||
def browse(self):
|
||||
filename = QtWidgets.QFileDialog.getOpenFileName(self.window, 'Open file', ".",
|
||||
"Industry Foundation Classes (*.ifc)")[0]
|
||||
filename = QtWidgets.QFileDialog.getOpenFileName(
|
||||
self.window, "Open file", ".", "Industry Foundation Classes (*.ifc)"
|
||||
)[0]
|
||||
self.load(filename)
|
||||
|
||||
def clear(self):
|
||||
|
||||
@@ -70,7 +70,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
sys.stderr = sys.__stderr__
|
||||
|
||||
def select(self, product):
|
||||
self.c = self.Console({'model': self.model, 'viewer': self.viewer, 'selection': product})
|
||||
self.c = self.Console({"model": self.model, "viewer": self.viewer, "selection": product})
|
||||
|
||||
def __init__(self, viewer, snippets=None):
|
||||
self.model = None
|
||||
@@ -92,8 +92,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
editor.backend.start(server.__file__)
|
||||
editor.panels.append(panels.FoldingPanel())
|
||||
editor.panels.append(panels.LineNumberPanel())
|
||||
editor.panels.append(panels.SearchAndReplacePanel(),
|
||||
panels.SearchAndReplacePanel.Position.BOTTOM)
|
||||
editor.panels.append(panels.SearchAndReplacePanel(), panels.SearchAndReplacePanel.Position.BOTTOM)
|
||||
editor.panels.append(panels.EncodingPanel(), api.Panel.Position.TOP)
|
||||
editor.add_separator()
|
||||
editor.panels.append(pypanels.QuickDocPanel(), api.Panel.Position.BOTTOM)
|
||||
@@ -116,7 +115,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
editor.modes.append(pymodes.PyIndenterMode())
|
||||
editor.show()
|
||||
else:
|
||||
editor.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier;')
|
||||
editor.setStyleSheet("font-size: 10pt; font-family: Consolas, Courier;")
|
||||
|
||||
self.editor = editor
|
||||
self.snippets = snippets
|
||||
@@ -131,7 +130,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
self.layout.addWidget(self.editor)
|
||||
self.output = QtWidgets.QTextEdit()
|
||||
self.output.setReadOnly(True)
|
||||
self.output.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier; background-color: #444;')
|
||||
self.output.setStyleSheet("font-size: 10pt; font-family: Consolas, Courier; background-color: #444;")
|
||||
self.layout.addWidget(self.output)
|
||||
|
||||
def replace_snippet(self, number=None):
|
||||
@@ -145,5 +144,5 @@ class code_edit(QtWidgets.QWidget):
|
||||
output = []
|
||||
sys.stdout = StdoutRedirector(self.output)
|
||||
self.model = f
|
||||
self.c = self.Console({'model': self.model, 'selection': None, 'viewer': self.viewer})
|
||||
self.c = self.Console({"model": self.model, "selection": None, "viewer": self.viewer})
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
@@ -45,11 +45,12 @@ if has_occ:
|
||||
from OCC import TopoDS
|
||||
|
||||
def wrap_shape_creation(settings, shape):
|
||||
if getattr(settings, 'use_python_opencascade', False):
|
||||
if getattr(settings, "use_python_opencascade", False):
|
||||
return utils.create_shape_from_serialization(shape)
|
||||
else:
|
||||
return shape
|
||||
|
||||
|
||||
# Subclass the settings module to provide an additional
|
||||
# setting to enable pythonOCC when available
|
||||
class settings(ifcopenshell_wrapper.settings):
|
||||
@@ -73,60 +74,57 @@ _iterator = ifcopenshell_wrapper.iterator_double_precision
|
||||
|
||||
# Make sure people are able to use python's platform agnostic paths
|
||||
class iterator(_iterator):
|
||||
def __init__(self, settings, file_or_filename, num_threads = 1, include = None, exclude = None):
|
||||
def __init__(self, settings, file_or_filename, num_threads=1, include=None, exclude=None):
|
||||
self.settings = settings
|
||||
if isinstance(file_or_filename, file):
|
||||
file_or_filename = file_or_filename.wrapped_data
|
||||
else:
|
||||
file_or_filename = os.path.abspath(file_or_filename)
|
||||
|
||||
|
||||
if include is not None and exclude is not None:
|
||||
raise ValueError("include and exclude cannot be specified simultaneously")
|
||||
|
||||
|
||||
if include is not None or exclude is not None:
|
||||
# Couldn't get the typemaps properly applied using %extend so we
|
||||
# replicate the SWIG-generated __init__ call on the output of a
|
||||
# free function.
|
||||
# @todo verify this works with SWIG 4
|
||||
|
||||
|
||||
include_or_exclude = include if exclude is None else exclude
|
||||
include_or_exclude_type = set(x.__class__.__name__ for x in include_or_exclude)
|
||||
print(include_or_exclude_type)
|
||||
|
||||
|
||||
if include_or_exclude_type == {"entity_instance"}:
|
||||
if not all(inst.is_a("IfcProduct") for inst in include_or_exclude):
|
||||
raise ValueError("include and exclude need to be an aggregate of IfcProduct")
|
||||
|
||||
initializer = ifcopenshell_wrapper.\
|
||||
construct_iterator_double_precision_with_include_exclude_globalid
|
||||
|
||||
decode_unicode = lambda x: x.encode('ascii') if x.__class__.__name__ == "unicode" else x
|
||||
include_or_exclude = list(map(decode_unicode, map(operator.attrgetter('GlobalId'), include_or_exclude)))
|
||||
|
||||
initializer = ifcopenshell_wrapper.construct_iterator_double_precision_with_include_exclude_globalid
|
||||
|
||||
decode_unicode = lambda x: x.encode("ascii") if x.__class__.__name__ == "unicode" else x
|
||||
include_or_exclude = list(map(decode_unicode, map(operator.attrgetter("GlobalId"), include_or_exclude)))
|
||||
else:
|
||||
initializer = ifcopenshell_wrapper.\
|
||||
construct_iterator_double_precision_with_include_exclude
|
||||
|
||||
initializer = ifcopenshell_wrapper.construct_iterator_double_precision_with_include_exclude
|
||||
|
||||
self.this = initializer(
|
||||
self.settings,
|
||||
file_or_filename,
|
||||
include_or_exclude,
|
||||
include is not None,
|
||||
num_threads)
|
||||
self.settings, file_or_filename, include_or_exclude, include is not None, num_threads
|
||||
)
|
||||
else:
|
||||
_iterator.__init__(self, settings, file_or_filename, num_threads)
|
||||
|
||||
if has_occ:
|
||||
|
||||
def get(self):
|
||||
return wrap_shape_creation(self.settings, _iterator.get(self))
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
if self.initialize():
|
||||
while True:
|
||||
yield self.get()
|
||||
if not self.next(): break
|
||||
if not self.next():
|
||||
break
|
||||
|
||||
|
||||
class tree(ifcopenshell_wrapper.tree):
|
||||
|
||||
def __init__(self, file=None, settings=None):
|
||||
args = [self]
|
||||
if file is not None:
|
||||
@@ -166,7 +164,7 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
if "extend" in kwargs or "completely_within" in kwargs:
|
||||
args.append(kwargs.get("completely_within", False))
|
||||
if "extend" in kwargs:
|
||||
args.append(kwargs.get("extend", -1.e-5))
|
||||
args.append(kwargs.get("extend", -1.0e-5))
|
||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select_box(*args)]
|
||||
|
||||
|
||||
@@ -193,14 +191,11 @@ def create_shape(settings, inst, repr=None):
|
||||
"""
|
||||
return wrap_shape_creation(
|
||||
settings,
|
||||
ifcopenshell_wrapper.create_shape(
|
||||
settings,
|
||||
inst.wrapped_data,
|
||||
repr.wrapped_data if repr is not None else None
|
||||
))
|
||||
ifcopenshell_wrapper.create_shape(settings, inst.wrapped_data, repr.wrapped_data if repr is not None else None),
|
||||
)
|
||||
|
||||
|
||||
def iterate(settings, file_or_filename, num_threads = 1, include = None, exclude = None):
|
||||
def iterate(settings, file_or_filename, num_threads=1, include=None, exclude=None):
|
||||
it = iterator(settings, file_or_filename, num_threads, include, exclude)
|
||||
if it.initialize():
|
||||
while True:
|
||||
@@ -214,13 +209,17 @@ def make_shape_function(fn):
|
||||
return None if e is None else entity_instance(e)
|
||||
|
||||
if has_occ:
|
||||
|
||||
def _(schema, string_or_shape, *args):
|
||||
if isinstance(string_or_shape, TopoDS.TopoDS_Shape):
|
||||
string_or_shape = utils.serialize_shape(string_or_shape)
|
||||
return entity_instance_or_none(fn(schema, string_or_shape, *args))
|
||||
|
||||
else:
|
||||
|
||||
def _(schema, string, *args):
|
||||
return entity_instance_or_none(fn(schema, string, *args))
|
||||
|
||||
return _
|
||||
|
||||
|
||||
|
||||
@@ -26,35 +26,38 @@ import operator
|
||||
import warnings
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
try: # python 3.3+
|
||||
from collections.abc import Iterable
|
||||
except ModuleNotFoundError: # python 2
|
||||
except ModuleNotFoundError: # python 2
|
||||
from collections import Iterable
|
||||
|
||||
try:
|
||||
from OCC.Core import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
|
||||
|
||||
USE_OCCT_HANDLE = False
|
||||
except ImportError:
|
||||
from OCC import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
|
||||
|
||||
USE_OCCT_HANDLE = True
|
||||
|
||||
shape_tuple = namedtuple('shape_tuple', ('data', 'geometry', 'styles'))
|
||||
shape_tuple = namedtuple("shape_tuple", ("data", "geometry", "styles"))
|
||||
|
||||
handle, main_loop, add_menu, add_function_to_menu = None, None, None, None
|
||||
|
||||
DEFAULT_STYLES = {
|
||||
"DEFAULT": (.7, .7, .7),
|
||||
"IfcWall": (.8, .8, .8),
|
||||
"IfcSite": (.75, .8, .65),
|
||||
"IfcSlab": (.4, .4, .4),
|
||||
"IfcWallStandardCase": (.9, .9, .9),
|
||||
"IfcWall": (.9, .9, .9),
|
||||
"IfcWindow": (.75, .8, .75, .3),
|
||||
"IfcDoor": (.55, .3, .15),
|
||||
"IfcBeam": (.75, .7, .7),
|
||||
"IfcRailing": (.65, .6, .6),
|
||||
"IfcMember": (.65, .6, .6),
|
||||
"IfcPlate": (.8, .8, .8)
|
||||
"DEFAULT": (0.7, 0.7, 0.7),
|
||||
"IfcWall": (0.8, 0.8, 0.8),
|
||||
"IfcSite": (0.75, 0.8, 0.65),
|
||||
"IfcSlab": (0.4, 0.4, 0.4),
|
||||
"IfcWallStandardCase": (0.9, 0.9, 0.9),
|
||||
"IfcWall": (0.9, 0.9, 0.9),
|
||||
"IfcWindow": (0.75, 0.8, 0.75, 0.3),
|
||||
"IfcDoor": (0.55, 0.3, 0.15),
|
||||
"IfcBeam": (0.75, 0.7, 0.7),
|
||||
"IfcRailing": (0.65, 0.6, 0.6),
|
||||
"IfcMember": (0.65, 0.6, 0.6),
|
||||
"IfcPlate": (0.8, 0.8, 0.8),
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +85,7 @@ def initialize_display():
|
||||
for l in lights:
|
||||
viewer.DelLight(l)
|
||||
|
||||
if hasattr(V3d, 'V3d_TypeOfOrientation_Yup_AxoRight'):
|
||||
if hasattr(V3d, "V3d_TypeOfOrientation_Yup_AxoRight"):
|
||||
dirs = [[V3d.V3d_TypeOfOrientation_Yup_AxoRight], [V3d.V3d_TypeOfOrientation_Zup_AxoRight]]
|
||||
else:
|
||||
dirs = [(3, 2, 1), (-1, -2, -3)]
|
||||
@@ -117,7 +120,7 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
if representation and not clr:
|
||||
if len(set(representation.styles)) == 1:
|
||||
clr = representation.styles[0]
|
||||
if min(clr) < 0. or max(clr) > 1.:
|
||||
if min(clr) < 0.0 or max(clr) > 1.0:
|
||||
clr = DEFAULT_STYLES.get(representation.data.type, DEFAULT_STYLES["DEFAULT"])
|
||||
|
||||
if clr:
|
||||
@@ -125,8 +128,9 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
ais.SetMaterial(material)
|
||||
|
||||
if isinstance(clr, str):
|
||||
qclr = getattr(Quantity, "Quantity_NOC_%s" % clr.upper(),
|
||||
getattr(Quantity, "Quantity_NOC_%s1" % clr.upper(), None))
|
||||
qclr = getattr(
|
||||
Quantity, "Quantity_NOC_%s" % clr.upper(), getattr(Quantity, "Quantity_NOC_%s1" % clr.upper(), None)
|
||||
)
|
||||
if qclr is None:
|
||||
raise Exception("No color named '%s'" % clr.upper())
|
||||
elif isinstance(clr, Iterable):
|
||||
@@ -140,8 +144,8 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
raise Exception("Object of type %r cannot be used as a color." % type(clr))
|
||||
|
||||
ais.SetColor(qclr)
|
||||
if isinstance(clr, tuple) and len(clr) == 4 and clr[3] < 1.:
|
||||
ais.SetTransparency(1. - clr[3])
|
||||
if isinstance(clr, tuple) and len(clr) == 4 and clr[3] < 1.0:
|
||||
ais.SetTransparency(1.0 - clr[3])
|
||||
|
||||
elif representation and hasattr(AIS, "AIS_MultipleConnectedShape"):
|
||||
default_style_applied = None
|
||||
@@ -155,13 +159,14 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
else:
|
||||
for shp, stl in zip(subshapes, representation.styles):
|
||||
subshape = AIS.AIS_Shape(shp)
|
||||
if min(stl) < 0. or max(stl) > 1.:
|
||||
default_style_applied = stl = DEFAULT_STYLES.get(representation.data.type,
|
||||
DEFAULT_STYLES["DEFAULT"])
|
||||
if min(stl) < 0.0 or max(stl) > 1.0:
|
||||
default_style_applied = stl = DEFAULT_STYLES.get(
|
||||
representation.data.type, DEFAULT_STYLES["DEFAULT"]
|
||||
)
|
||||
subshape.SetColor(Quantity.Quantity_Color(stl[0], stl[1], stl[2], Quantity.Quantity_TOC_RGB))
|
||||
subshape.SetMaterial(material)
|
||||
if len(stl) == 4 and stl[3] < 1.:
|
||||
subshape.SetTransparency(1. - stl[3])
|
||||
if len(stl) == 4 and stl[3] < 1.0:
|
||||
subshape.SetTransparency(1.0 - stl[3])
|
||||
ais.Connect(subshape.GetHandle())
|
||||
|
||||
# For some reason it is necessary to set transparency here again
|
||||
@@ -169,14 +174,14 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
applied_styles = representation.styles
|
||||
if default_style_applied:
|
||||
if len(default_style_applied) == 3:
|
||||
default_style_applied += (1.,)
|
||||
default_style_applied += (1.0,)
|
||||
applied_styles += (default_style_applied,)
|
||||
|
||||
if len(applied_styles):
|
||||
# The only way for this not to be true if is the entire shape is NULL
|
||||
min_transp = min(map(operator.itemgetter(3), applied_styles))
|
||||
if min_transp < 1.:
|
||||
ais.SetTransparency(1.)
|
||||
if min_transp < 1.0:
|
||||
ais.SetTransparency(1.0)
|
||||
|
||||
else:
|
||||
ais = AIS.AIS_Shape(shape)
|
||||
@@ -199,10 +204,10 @@ def set_shape_transparency(ais, t):
|
||||
|
||||
|
||||
def get_bounding_box_center(bbox):
|
||||
bbmin = [0.] * 3
|
||||
bbmax = [0.] * 3
|
||||
bbmin = [0.0] * 3
|
||||
bbmax = [0.0] * 3
|
||||
bbmin[0], bbmin[1], bbmin[2], bbmax[0], bbmax[1], bbmax[2] = bbox.Get()
|
||||
return gp.gp_Pnt(*map(lambda xy: (xy[0] + xy[1]) / 2., zip(bbmin, bbmax)))
|
||||
return gp.gp_Pnt(*map(lambda xy: (xy[0] + xy[1]) / 2.0, zip(bbmin, bbmax)))
|
||||
|
||||
|
||||
def serialize_shape(shape):
|
||||
@@ -226,7 +231,7 @@ def create_shape_from_serialization(brep_object):
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
styles = tuple(styles[i:i + 4] for i in range(0, len(styles), 4))
|
||||
styles = tuple(styles[i : i + 4] for i in range(0, len(styles), 4))
|
||||
|
||||
if not brep_data:
|
||||
return shape_tuple(brep_object, None, styles)
|
||||
|
||||
@@ -26,16 +26,16 @@ import string
|
||||
|
||||
from functools import reduce
|
||||
|
||||
chars = string.digits + string.ascii_uppercase + string.ascii_lowercase + '_$'
|
||||
chars = string.digits + string.ascii_uppercase + string.ascii_lowercase + "_$"
|
||||
|
||||
|
||||
def compress(g):
|
||||
bs = [int(g[i:i + 2], 16) for i in range(0, len(g), 2)]
|
||||
bs = [int(g[i : i + 2], 16) for i in range(0, len(g), 2)]
|
||||
|
||||
def b64(v, l=4):
|
||||
return ''.join([chars[(v // (64 ** i)) % 64] for i in range(l)][::-1])
|
||||
return "".join([chars[(v // (64 ** i)) % 64] for i in range(l)][::-1])
|
||||
|
||||
return ''.join([b64(bs[0], 2)] + [b64((bs[i] << 16) + (bs[i + 1] << 8) + bs[i + 2]) for i in range(1, 16, 3)])
|
||||
return "".join([b64(bs[0], 2)] + [b64((bs[i] << 16) + (bs[i + 1] << 8) + bs[i + 2]) for i in range(1, 16, 3)])
|
||||
|
||||
|
||||
def expand(g):
|
||||
@@ -44,13 +44,13 @@ def expand(g):
|
||||
|
||||
bs = [b64(g[0:2])]
|
||||
for i in range(5):
|
||||
d = b64(g[2 + 4 * i:6 + 4 * i])
|
||||
d = b64(g[2 + 4 * i : 6 + 4 * i])
|
||||
bs += [(d >> (8 * (2 - j))) % 256 for j in range(3)]
|
||||
return ''.join(['%02x' % b for b in bs])
|
||||
return "".join(["%02x" % b for b in bs])
|
||||
|
||||
|
||||
def split(g):
|
||||
return '{%s-%s-%s-%s-%s}' % (g[:8], g[8:12], g[12:16], g[16:20], g[20:])
|
||||
return "{%s-%s-%s-%s-%s}" % (g[:8], g[8:12], g[12:16], g[16:20], g[20:])
|
||||
|
||||
|
||||
def new():
|
||||
|
||||
@@ -62,24 +62,33 @@ END-ISO-10303-21;
|
||||
"""
|
||||
|
||||
DEFAULTS = {
|
||||
"application": lambda d: 'IfcOpenShell-%s' % main.version,
|
||||
"application": lambda d: "IfcOpenShell-%s" % main.version,
|
||||
"application_version": lambda d: main.version,
|
||||
"project_globalid": lambda d: compress(uuid.uuid4().hex),
|
||||
"schema_identifier": lambda d: main.schema_identifier,
|
||||
"timestamp": lambda d: int(time.time()),
|
||||
"timestring": lambda d: time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(d.get('timestamp') or time.time()))
|
||||
"timestring": lambda d: time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(d.get("timestamp") or time.time())),
|
||||
}
|
||||
|
||||
|
||||
def create(filename=None, timestring=None, organization=None, creator=None,
|
||||
schema_identifier=None, application_version=None, timestamp=None,
|
||||
application=None, project_globalid=None, project_name=None):
|
||||
def create(
|
||||
filename=None,
|
||||
timestring=None,
|
||||
organization=None,
|
||||
creator=None,
|
||||
schema_identifier=None,
|
||||
application_version=None,
|
||||
timestamp=None,
|
||||
application=None,
|
||||
project_globalid=None,
|
||||
project_name=None,
|
||||
):
|
||||
d = dict(locals())
|
||||
|
||||
def _():
|
||||
for var, value in d.items():
|
||||
if value is None:
|
||||
yield var, DEFAULTS.get(var, lambda *args: '')(d)
|
||||
yield var, DEFAULTS.get(var, lambda *args: "")(d)
|
||||
|
||||
d.update(dict(_()))
|
||||
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
def get_psets(element):
|
||||
psets = {}
|
||||
try:
|
||||
if element.is_a('IfcTypeObject'):
|
||||
if element.is_a("IfcTypeObject"):
|
||||
if element.HasPropertySets:
|
||||
for definition in element.HasPropertySets:
|
||||
psets[definition.Name] = get_property_definition(definition)
|
||||
else:
|
||||
for relationship in element.IsDefinedBy:
|
||||
if relationship.is_a('IfcRelDefinesByProperties'):
|
||||
if relationship.is_a("IfcRelDefinesByProperties"):
|
||||
definition = relationship.RelatingPropertyDefinition
|
||||
psets[definition.Name] = get_property_definition(definition)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print('failed to load properties: {}'.format(e))
|
||||
|
||||
print("failed to load properties: {}".format(e))
|
||||
traceback.print_exc()
|
||||
return psets
|
||||
|
||||
@@ -20,9 +21,9 @@ def get_psets(element):
|
||||
def get_property_definition(definition):
|
||||
if definition is not None:
|
||||
props = {}
|
||||
if definition.is_a('IfcElementQuantity'):
|
||||
if definition.is_a("IfcElementQuantity"):
|
||||
props.update(get_quantities(definition.Quantities))
|
||||
elif definition.is_a('IfcPropertySet'):
|
||||
elif definition.is_a("IfcPropertySet"):
|
||||
props.update(get_properties(definition.HasProperties))
|
||||
else:
|
||||
# Entity introduced in IFC4
|
||||
@@ -35,7 +36,7 @@ def get_property_definition(definition):
|
||||
def get_quantities(quantities):
|
||||
results = {}
|
||||
for quantity in quantities:
|
||||
if quantity.is_a('IfcPhysicalSimpleQuantity'):
|
||||
if quantity.is_a("IfcPhysicalSimpleQuantity"):
|
||||
results[quantity.Name] = quantity[3]
|
||||
return results
|
||||
|
||||
@@ -43,22 +44,22 @@ def get_quantities(quantities):
|
||||
def get_properties(properties):
|
||||
results = {}
|
||||
for prop in properties:
|
||||
if prop.is_a('IfcPropertySingleValue'):
|
||||
if prop.is_a("IfcPropertySingleValue"):
|
||||
results[prop.Name] = prop.NominalValue.wrappedValue
|
||||
elif prop.is_a('IfcComplexProperty'):
|
||||
elif prop.is_a("IfcComplexProperty"):
|
||||
data = prop.get_info()
|
||||
data['properties'] = get_properties(prop.HasProperties)
|
||||
del(data['HasProperties'])
|
||||
data["properties"] = get_properties(prop.HasProperties)
|
||||
del data["HasProperties"]
|
||||
results[prop.Name] = data
|
||||
return results
|
||||
|
||||
|
||||
def get_type(element):
|
||||
if hasattr(element, 'IsTypedBy') and element.IsTypedBy:
|
||||
if hasattr(element, "IsTypedBy") and element.IsTypedBy:
|
||||
return element.IsTypedBy[0].RelatingType
|
||||
elif hasattr(element, 'IsDefinedBy') and element.IsDefinedBy: # IFC2X3
|
||||
elif hasattr(element, "IsDefinedBy") and element.IsDefinedBy: # IFC2X3
|
||||
for relationship in element.IsDefinedBy:
|
||||
if relationship.is_a('IfcRelDefinesByType'):
|
||||
if relationship.is_a("IfcRelDefinesByType"):
|
||||
return relationship.RelatingType
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import math
|
||||
|
||||
|
||||
def dms2dd(degrees, minutes, seconds, ms=0):
|
||||
dd = float(degrees) + float(minutes)/60.0 + float(seconds)/(3600.0) + float(ms/3600000000.0)
|
||||
dd = float(degrees) + float(minutes) / 60.0 + float(seconds) / (3600.0) + float(ms / 3600000000.0)
|
||||
return dd
|
||||
|
||||
|
||||
def dd2dms(dd, use_ms=False):
|
||||
dd = float(dd)
|
||||
sign = 1 if dd >= 0 else -1
|
||||
dd = abs(dd)
|
||||
if use_ms:
|
||||
seconds, ms = divmod(dd*60*60*1000000, 1000000)
|
||||
minutes, seconds = divmod(dd*60*60, 60)
|
||||
seconds, ms = divmod(dd * 60 * 60 * 1000000, 1000000)
|
||||
minutes, seconds = divmod(dd * 60 * 60, 60)
|
||||
degrees, minutes = divmod(minutes, 60)
|
||||
if dd < 0:
|
||||
degrees = -degrees
|
||||
@@ -18,9 +20,10 @@ def dd2dms(dd, use_ms=False):
|
||||
return (int(degrees) * sign, int(minutes) * sign, int(seconds) * sign, int(ms) * sign)
|
||||
return (int(degrees) * sign, int(minutes) * sign, int(seconds) * sign)
|
||||
|
||||
|
||||
def xyz2enh(x, y, z, eastings, northings, orthogonal_height, x_axis_abscissa, x_axis_ordinate, scale=None):
|
||||
if scale is None:
|
||||
scale = 1.
|
||||
scale = 1.0
|
||||
rotation = math.atan2(x_axis_ordinate, x_axis_abscissa)
|
||||
a = scale * math.cos(rotation)
|
||||
b = scale * math.sin(rotation)
|
||||
@@ -29,6 +32,7 @@ def xyz2enh(x, y, z, eastings, northings, orthogonal_height, x_axis_abscissa, x_
|
||||
height = z + orthogonal_height
|
||||
return (eastings, northings, height)
|
||||
|
||||
|
||||
# Used for converting the X and Y vectors of the X Axis in IFC geolocation
|
||||
def xy2angle(x, y):
|
||||
return math.degrees(math.atan2(y, x))
|
||||
|
||||
@@ -3,65 +3,67 @@ import ifcopenshell.util.element
|
||||
import lark
|
||||
|
||||
cobie_type_assets = [
|
||||
'IfcDoorStyle',
|
||||
'IfcBuildingElementProxyType',
|
||||
'IfcChimneyType',
|
||||
'IfcCoveringType',
|
||||
'IfcDoorType',
|
||||
'IfcFootingType',
|
||||
'IfcPileType',
|
||||
'IfcRoofType',
|
||||
'IfcShadingDeviceType',
|
||||
'IfcWindowType',
|
||||
'IfcDistributionControlElementType',
|
||||
'IfcDistributionChamberElementType',
|
||||
'IfcEnergyConversionDeviceType',
|
||||
'IfcFlowControllerType',
|
||||
'IfcFlowMovingDeviceType',
|
||||
'IfcFlowStorageDeviceType',
|
||||
'IfcFlowTerminalType',
|
||||
'IfcFlowTreatmentDeviceType',
|
||||
'IfcElementAssemblyType',
|
||||
'IfcBuildingElementPartType',
|
||||
'IfcDiscreteAccessoryType',
|
||||
'IfcMechanicalFastenerType',
|
||||
'IfcReinforcingElementType',
|
||||
'IfcVibrationIsolatorType',
|
||||
'IfcFurnishingElementType',
|
||||
'IfcGeographicElementType',
|
||||
'IfcTransportElementType',
|
||||
'IfcSpatialZoneType',
|
||||
'IfcWindowStyle',
|
||||
"IfcDoorStyle",
|
||||
"IfcBuildingElementProxyType",
|
||||
"IfcChimneyType",
|
||||
"IfcCoveringType",
|
||||
"IfcDoorType",
|
||||
"IfcFootingType",
|
||||
"IfcPileType",
|
||||
"IfcRoofType",
|
||||
"IfcShadingDeviceType",
|
||||
"IfcWindowType",
|
||||
"IfcDistributionControlElementType",
|
||||
"IfcDistributionChamberElementType",
|
||||
"IfcEnergyConversionDeviceType",
|
||||
"IfcFlowControllerType",
|
||||
"IfcFlowMovingDeviceType",
|
||||
"IfcFlowStorageDeviceType",
|
||||
"IfcFlowTerminalType",
|
||||
"IfcFlowTreatmentDeviceType",
|
||||
"IfcElementAssemblyType",
|
||||
"IfcBuildingElementPartType",
|
||||
"IfcDiscreteAccessoryType",
|
||||
"IfcMechanicalFastenerType",
|
||||
"IfcReinforcingElementType",
|
||||
"IfcVibrationIsolatorType",
|
||||
"IfcFurnishingElementType",
|
||||
"IfcGeographicElementType",
|
||||
"IfcTransportElementType",
|
||||
"IfcSpatialZoneType",
|
||||
"IfcWindowStyle",
|
||||
]
|
||||
cobie_component_assets = [
|
||||
'IfcBuildingElementProxy',
|
||||
'IfcChimney',
|
||||
'IfcCovering',
|
||||
'IfcDoor',
|
||||
'IfcShadingDevice',
|
||||
'IfcWindow',
|
||||
'IfcDistributionControlElement',
|
||||
'IfcDistributionChamberElement',
|
||||
'IfcEnergyConversionDevice',
|
||||
'IfcFlowController',
|
||||
'IfcFlowMovingDevice',
|
||||
'IfcFlowStorageDevice',
|
||||
'IfcFlowTerminal',
|
||||
'IfcFlowTreatmentDevice',
|
||||
'IfcDiscreteAccessory',
|
||||
'IfcTendon',
|
||||
'IfcTendonAnchor',
|
||||
'IfcVibrationIsolator',
|
||||
'IfcFurnishingElement',
|
||||
'IfcGeographicElement',
|
||||
'IfcTransportElement',
|
||||
"IfcBuildingElementProxy",
|
||||
"IfcChimney",
|
||||
"IfcCovering",
|
||||
"IfcDoor",
|
||||
"IfcShadingDevice",
|
||||
"IfcWindow",
|
||||
"IfcDistributionControlElement",
|
||||
"IfcDistributionChamberElement",
|
||||
"IfcEnergyConversionDevice",
|
||||
"IfcFlowController",
|
||||
"IfcFlowMovingDevice",
|
||||
"IfcFlowStorageDevice",
|
||||
"IfcFlowTerminal",
|
||||
"IfcFlowTreatmentDevice",
|
||||
"IfcDiscreteAccessory",
|
||||
"IfcTendon",
|
||||
"IfcTendonAnchor",
|
||||
"IfcVibrationIsolator",
|
||||
"IfcFurnishingElement",
|
||||
"IfcGeographicElement",
|
||||
"IfcTransportElement",
|
||||
]
|
||||
|
||||
class Selector():
|
||||
|
||||
class Selector:
|
||||
def parse(self, ifc_file, query):
|
||||
self.file = ifc_file
|
||||
|
||||
l = lark.Lark('''start: query (lfunction query)*
|
||||
l = lark.Lark(
|
||||
"""start: query (lfunction query)*
|
||||
query: selector | group
|
||||
group: "(" query (lfunction query)* ")"
|
||||
selector: (inverse_relationship)? guid_selector | (inverse_relationship)? class_selector
|
||||
@@ -111,7 +113,8 @@ class Selector():
|
||||
NEWLINE: (CR? LF)+
|
||||
|
||||
%ignore WS // Disregard spaces in text
|
||||
''')
|
||||
"""
|
||||
)
|
||||
|
||||
start = l.parse(query)
|
||||
return self.get_group(start)
|
||||
@@ -119,24 +122,24 @@ class Selector():
|
||||
def get_group(self, group):
|
||||
lfunction = None
|
||||
for child in group.children:
|
||||
if child.data == 'query':
|
||||
if child.data == "query":
|
||||
new_results = self.get_query(child)
|
||||
if not lfunction:
|
||||
results = new_results
|
||||
elif lfunction == 'or':
|
||||
elif lfunction == "or":
|
||||
results.extend(new_results)
|
||||
elif lfunction == 'and':
|
||||
elif lfunction == "and":
|
||||
results = list(set(results).intersection(new_results))
|
||||
results = list(set(results))
|
||||
elif child.data == 'lfunction':
|
||||
elif child.data == "lfunction":
|
||||
lfunction = child.children[0].data
|
||||
return results
|
||||
|
||||
def get_query(self, query):
|
||||
for child in query.children:
|
||||
if child.data == 'selector':
|
||||
if child.data == "selector":
|
||||
return self.get_selector(child)
|
||||
elif child.data == 'group':
|
||||
elif child.data == "group":
|
||||
return self.get_group(child)
|
||||
|
||||
def get_selector(self, selector):
|
||||
@@ -147,9 +150,9 @@ class Selector():
|
||||
inverse_relationship = selector.children[0]
|
||||
class_or_guid_selector = selector.children[1]
|
||||
|
||||
if class_or_guid_selector.data == 'class_selector':
|
||||
if class_or_guid_selector.data == "class_selector":
|
||||
results = self.get_class_selector(class_or_guid_selector)
|
||||
elif class_or_guid_selector.data == 'guid_selector':
|
||||
elif class_or_guid_selector.data == "guid_selector":
|
||||
results = self.get_guid_selector(class_or_guid_selector)
|
||||
|
||||
if not inverse_relationship:
|
||||
@@ -159,26 +162,25 @@ class Selector():
|
||||
def parse_inverse_relationship(self, elements, inverse_relationship):
|
||||
results = []
|
||||
for element in elements:
|
||||
if inverse_relationship == 'types':
|
||||
if hasattr(element, 'Types') and element.Types:
|
||||
if inverse_relationship == "types":
|
||||
if hasattr(element, "Types") and element.Types:
|
||||
results.extend(element.Types[0].RelatedObjects)
|
||||
elif hasattr(element, 'ObjectTypeOf') and element.ObjectTypeOf:
|
||||
elif hasattr(element, "ObjectTypeOf") and element.ObjectTypeOf:
|
||||
results.extend(element.ObjectTypeOf[0].RelatedObjects)
|
||||
elif inverse_relationship == 'contains_elements' \
|
||||
and hasattr(element, 'ContainsElements'):
|
||||
elif inverse_relationship == "contains_elements" and hasattr(element, "ContainsElements"):
|
||||
for relationship in element.ContainsElements:
|
||||
results.extend(relationship.RelatedElements)
|
||||
return results
|
||||
|
||||
def get_class_selector(self, class_selector):
|
||||
if class_selector.children[0] == 'COBie':
|
||||
if class_selector.children[0] == "COBie":
|
||||
elements = []
|
||||
for ifc_class in cobie_component_assets:
|
||||
try:
|
||||
elements += self.file.by_type(ifc_class)
|
||||
except:
|
||||
pass
|
||||
elif class_selector.children[0] == 'COBieType':
|
||||
elif class_selector.children[0] == "COBieType":
|
||||
elements = []
|
||||
for ifc_class in cobie_type_assets:
|
||||
try:
|
||||
@@ -187,8 +189,7 @@ class Selector():
|
||||
pass
|
||||
else:
|
||||
elements = self.file.by_type(class_selector.children[0])
|
||||
if len(class_selector.children) > 1 \
|
||||
and class_selector.children[1].data == 'filter':
|
||||
if len(class_selector.children) > 1 and class_selector.children[1].data == "filter":
|
||||
return self.filter_elements(elements, class_selector.children[1])
|
||||
return elements
|
||||
|
||||
@@ -196,7 +197,7 @@ class Selector():
|
||||
results = []
|
||||
key = filter_rule.children[0].children[0]
|
||||
if not isinstance(key, str):
|
||||
key = key.children[0] + '.' + key.children[1]
|
||||
key = key.children[0] + "." + key.children[1]
|
||||
comparison = value = None
|
||||
if len(filter_rule.children) > 1:
|
||||
comparison = filter_rule.children[1].children[0].data
|
||||
@@ -205,42 +206,40 @@ class Selector():
|
||||
element_value = self.get_element_value(element, key)
|
||||
if not element_value:
|
||||
continue
|
||||
if not comparison \
|
||||
or self.filter_element(element, element_value, comparison, value):
|
||||
if not comparison or self.filter_element(element, element_value, comparison, value):
|
||||
results.append(element)
|
||||
return results
|
||||
|
||||
def get_element_value(self, element, key):
|
||||
if '.' in key \
|
||||
and key.split('.')[0] == 'type':
|
||||
if "." in key and key.split(".")[0] == "type":
|
||||
try:
|
||||
element = ifcopenshell.util.element.get_type(element)
|
||||
if not element:
|
||||
return None
|
||||
except:
|
||||
return
|
||||
key = '.'.join(key.split('.')[1:])
|
||||
key = ".".join(key.split(".")[1:])
|
||||
info = element.get_info()
|
||||
if key in info:
|
||||
return info[key]
|
||||
elif '.' in key:
|
||||
pset_name, prop = key.split('.')
|
||||
elif "." in key:
|
||||
pset_name, prop = key.split(".")
|
||||
psets = ifcopenshell.util.element.get_psets(element)
|
||||
if pset_name in psets and prop in psets[pset_name]:
|
||||
return psets[pset_name][prop]
|
||||
|
||||
def filter_element(self, element, element_value, comparison, value):
|
||||
if comparison == 'equal':
|
||||
if comparison == "equal":
|
||||
return str(element_value) == value
|
||||
elif comparison == 'contains':
|
||||
elif comparison == "contains":
|
||||
return value in str(element_value)
|
||||
elif comparison == 'morethan':
|
||||
elif comparison == "morethan":
|
||||
return element_value > float(value)
|
||||
elif comparison == 'lessthan':
|
||||
elif comparison == "lessthan":
|
||||
return element_value < float(value)
|
||||
elif comparison == 'morethanequalto':
|
||||
elif comparison == "morethanequalto":
|
||||
return element_value >= float(value)
|
||||
elif comparison == 'lessthanequalto':
|
||||
elif comparison == "lessthanequalto":
|
||||
return element_value <= float(value)
|
||||
return False
|
||||
|
||||
|
||||
@@ -1,55 +1,99 @@
|
||||
from math import pi
|
||||
|
||||
prefixes = {'EXA': 1e18, 'PETA': 1e15, 'TERA': 1e12, 'GIGA': 1e9, 'MEGA':
|
||||
1e6, 'KILO': 1e3, 'HECTO': 1e2, 'DECA': 1e1, 'DECI': 1e-1, 'CENTI':
|
||||
1e-2, 'MILLI': 1e-3, 'MICRO': 1e-6, 'NANO': 1e-9, 'PICO': 1e-12,
|
||||
'FEMTO': 1e-15, 'ATTO': 1e-18}
|
||||
prefixes = {
|
||||
"EXA": 1e18,
|
||||
"PETA": 1e15,
|
||||
"TERA": 1e12,
|
||||
"GIGA": 1e9,
|
||||
"MEGA": 1e6,
|
||||
"KILO": 1e3,
|
||||
"HECTO": 1e2,
|
||||
"DECA": 1e1,
|
||||
"DECI": 1e-1,
|
||||
"CENTI": 1e-2,
|
||||
"MILLI": 1e-3,
|
||||
"MICRO": 1e-6,
|
||||
"NANO": 1e-9,
|
||||
"PICO": 1e-12,
|
||||
"FEMTO": 1e-15,
|
||||
"ATTO": 1e-18,
|
||||
}
|
||||
|
||||
unit_names = ['AMPERE', 'BECQUEREL', 'CANDELA', 'COULOMB',
|
||||
'CUBIC_METRE', 'DEGREE CELSIUS', 'FARAD', 'GRAM', 'GRAY', 'HENRY',
|
||||
'HERTZ', 'JOULE', 'KELVIN', 'LUMEN', 'LUX', 'MOLE', 'NEWTON', 'OHM',
|
||||
'PASCAL', 'RADIAN', 'SECOND', 'SIEMENS', 'SIEVERT', 'SQUARE METRE',
|
||||
'METRE', 'STERADIAN', 'TESLA', 'VOLT', 'WATT', 'WEBER']
|
||||
unit_names = [
|
||||
"AMPERE",
|
||||
"BECQUEREL",
|
||||
"CANDELA",
|
||||
"COULOMB",
|
||||
"CUBIC_METRE",
|
||||
"DEGREE CELSIUS",
|
||||
"FARAD",
|
||||
"GRAM",
|
||||
"GRAY",
|
||||
"HENRY",
|
||||
"HERTZ",
|
||||
"JOULE",
|
||||
"KELVIN",
|
||||
"LUMEN",
|
||||
"LUX",
|
||||
"MOLE",
|
||||
"NEWTON",
|
||||
"OHM",
|
||||
"PASCAL",
|
||||
"RADIAN",
|
||||
"SECOND",
|
||||
"SIEMENS",
|
||||
"SIEVERT",
|
||||
"SQUARE METRE",
|
||||
"METRE",
|
||||
"STERADIAN",
|
||||
"TESLA",
|
||||
"VOLT",
|
||||
"WATT",
|
||||
"WEBER",
|
||||
]
|
||||
|
||||
si_conversions = {
|
||||
'inch': 0.0254,
|
||||
'foot': 0.3048,
|
||||
'yard': 0.914,
|
||||
'mile': 1609,
|
||||
'square inch': 0.0006452,
|
||||
'square foot': 0.09290304,
|
||||
'square yard': 0.83612736,
|
||||
'acre': 4046.86,
|
||||
'square mile': 2588881,
|
||||
'cubic inch': 0.00001639,
|
||||
'cubic foot': 0.02831684671168849,
|
||||
'cubic yard': 0.7636,
|
||||
'litre': 0.001,
|
||||
'fluid ounce UK': 0.0000284130625,
|
||||
'fluid ounce US': 0.00002957353,
|
||||
'pint UK': 0.000568,
|
||||
'pint US': 0.000473,
|
||||
'gallon UK': 0.004546,
|
||||
'gallon US': 0.003785,
|
||||
'degree': pi/180,
|
||||
'ounce': 0.02835,
|
||||
'pound': 0.454,
|
||||
'ton UK': 1016.0469088,
|
||||
'ton US': 907.18474,
|
||||
'lbf': 4.4482216153,
|
||||
'kip': 4448.2216153,
|
||||
'psi': 6894.7572932,
|
||||
'ksi': 6894757.2932,
|
||||
'minute': 60,
|
||||
'hour': 3600,
|
||||
'day': 86400,
|
||||
'btu': 1055.056}
|
||||
"inch": 0.0254,
|
||||
"foot": 0.3048,
|
||||
"yard": 0.914,
|
||||
"mile": 1609,
|
||||
"square inch": 0.0006452,
|
||||
"square foot": 0.09290304,
|
||||
"square yard": 0.83612736,
|
||||
"acre": 4046.86,
|
||||
"square mile": 2588881,
|
||||
"cubic inch": 0.00001639,
|
||||
"cubic foot": 0.02831684671168849,
|
||||
"cubic yard": 0.7636,
|
||||
"litre": 0.001,
|
||||
"fluid ounce UK": 0.0000284130625,
|
||||
"fluid ounce US": 0.00002957353,
|
||||
"pint UK": 0.000568,
|
||||
"pint US": 0.000473,
|
||||
"gallon UK": 0.004546,
|
||||
"gallon US": 0.003785,
|
||||
"degree": pi / 180,
|
||||
"ounce": 0.02835,
|
||||
"pound": 0.454,
|
||||
"ton UK": 1016.0469088,
|
||||
"ton US": 907.18474,
|
||||
"lbf": 4.4482216153,
|
||||
"kip": 4448.2216153,
|
||||
"psi": 6894.7572932,
|
||||
"ksi": 6894757.2932,
|
||||
"minute": 60,
|
||||
"hour": 3600,
|
||||
"day": 86400,
|
||||
"btu": 1055.056,
|
||||
}
|
||||
|
||||
|
||||
def get_prefix(text):
|
||||
for prefix in prefixes.keys():
|
||||
if prefix in text.upper():
|
||||
return prefix
|
||||
|
||||
|
||||
def get_prefix_multiplier(text):
|
||||
if not text:
|
||||
return 1
|
||||
@@ -58,11 +102,13 @@ def get_prefix_multiplier(text):
|
||||
return prefixes[prefix]
|
||||
return 1
|
||||
|
||||
|
||||
def get_unit_name(text):
|
||||
for name in unit_names:
|
||||
if name in text.upper().replace('METER', 'METRE'):
|
||||
if name in text.upper().replace("METER", "METRE"):
|
||||
return name
|
||||
|
||||
|
||||
def convert(value, from_prefix, from_unit, to_prefix, to_unit):
|
||||
"""Converts between length, area, and volume units
|
||||
|
||||
@@ -81,18 +127,18 @@ def convert(value, from_prefix, from_unit, to_prefix, to_unit):
|
||||
value *= si_conversions[from_unit]
|
||||
elif from_prefix:
|
||||
value *= get_prefix_multiplier(from_prefix)
|
||||
if 'SQUARE' in from_unit:
|
||||
if "SQUARE" in from_unit:
|
||||
value *= get_prefix_multiplier(from_prefix)
|
||||
elif 'CUBIC' in from_unit:
|
||||
elif "CUBIC" in from_unit:
|
||||
value *= get_prefix_multiplier(from_prefix)
|
||||
value *= get_prefix_multiplier(from_prefix)
|
||||
if to_unit in si_conversions:
|
||||
return value * (1 / si_conversions[to_unit])
|
||||
elif to_prefix:
|
||||
value *= (1 / get_prefix_multiplier(to_prefix))
|
||||
if 'SQUARE' in from_unit:
|
||||
value *= (1 / get_prefix_multiplier(to_prefix))
|
||||
elif 'CUBIC' in from_unit:
|
||||
value *= (1 / get_prefix_multiplier(to_prefix))
|
||||
value *= (1 / get_prefix_multiplier(to_prefix))
|
||||
value *= 1 / get_prefix_multiplier(to_prefix)
|
||||
if "SQUARE" in from_unit:
|
||||
value *= 1 / get_prefix_multiplier(to_prefix)
|
||||
elif "CUBIC" in from_unit:
|
||||
value *= 1 / get_prefix_multiplier(to_prefix)
|
||||
value *= 1 / get_prefix_multiplier(to_prefix)
|
||||
return value
|
||||
|
||||
@@ -8,31 +8,34 @@ from collections import namedtuple
|
||||
|
||||
import ifcopenshell
|
||||
|
||||
named_type = ifcopenshell.ifcopenshell_wrapper.named_type
|
||||
named_type = ifcopenshell.ifcopenshell_wrapper.named_type
|
||||
aggregation_type = ifcopenshell.ifcopenshell_wrapper.aggregation_type
|
||||
simple_type = ifcopenshell.ifcopenshell_wrapper.simple_type
|
||||
simple_type = ifcopenshell.ifcopenshell_wrapper.simple_type
|
||||
type_declaration = ifcopenshell.ifcopenshell_wrapper.type_declaration
|
||||
enumeration_type = ifcopenshell.ifcopenshell_wrapper.enumeration_type
|
||||
entity_type = ifcopenshell.ifcopenshell_wrapper.entity
|
||||
select_type = ifcopenshell.ifcopenshell_wrapper.select_type
|
||||
attribute = ifcopenshell.ifcopenshell_wrapper.attribute
|
||||
entity_type = ifcopenshell.ifcopenshell_wrapper.entity
|
||||
select_type = ifcopenshell.ifcopenshell_wrapper.select_type
|
||||
attribute = ifcopenshell.ifcopenshell_wrapper.attribute
|
||||
|
||||
class ValidationError(Exception): pass
|
||||
|
||||
log_entry_type = namedtuple('log_entry_type', ("level", "message", "instance"))
|
||||
class ValidationError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
log_entry_type = namedtuple("log_entry_type", ("level", "message", "instance"))
|
||||
|
||||
|
||||
class json_logger:
|
||||
|
||||
def __init__(self):
|
||||
self.statements = []
|
||||
self.instance = None
|
||||
|
||||
|
||||
def set_instance(self, instance):
|
||||
self.instance = instance
|
||||
|
||||
|
||||
def log(self, level, message, instance):
|
||||
self.statements.append(log_entry_type(level, message, instance)._asdict())
|
||||
|
||||
|
||||
def __getattr__(self, level):
|
||||
return functools.partial(self.log, level, instance=self.instance)
|
||||
|
||||
@@ -44,10 +47,11 @@ simple_type_python_mapping = {
|
||||
"real": float,
|
||||
"number": float,
|
||||
"boolean": bool,
|
||||
"logical": bool, # still not implemented in IfcOpenShell
|
||||
"binary": str # maps to a str of "0" and "1"
|
||||
"logical": bool, # still not implemented in IfcOpenShell
|
||||
"binary": str, # maps to a str of "0" and "1"
|
||||
}
|
||||
|
||||
|
||||
def assert_valid_inverse(attr, val):
|
||||
b1, b2 = attr.bound1(), attr.bound2()
|
||||
invalid = len(val) < b1 or (b2 != -1 and len(val) > b2)
|
||||
@@ -55,24 +59,25 @@ def assert_valid_inverse(attr, val):
|
||||
raise ValidationError("%r not valid for %s" % (val, attr))
|
||||
return True
|
||||
|
||||
|
||||
def assert_valid(attr, val):
|
||||
if isinstance(attr, attribute):
|
||||
attr_type = attr.type_of_attribute()
|
||||
else:
|
||||
attr_type = attr
|
||||
|
||||
|
||||
type_wrappers = (named_type,)
|
||||
if not isinstance(val, ifcopenshell.entity_instance):
|
||||
# If val is not an entity instance we need to
|
||||
# If val is not an entity instance we need to
|
||||
# flatten the type declaration to something that
|
||||
# maps to the python types
|
||||
type_wrappers += (type_declaration,)
|
||||
|
||||
type_wrappers += (type_declaration,)
|
||||
|
||||
while isinstance(attr_type, type_wrappers):
|
||||
attr_type = attr_type.declared_type()
|
||||
|
||||
|
||||
if isinstance(attr_type, simple_type):
|
||||
invalid = type(val) != simple_type_python_mapping[attr_type.declared_type()]
|
||||
invalid = type(val) != simple_type_python_mapping[attr_type.declared_type()]
|
||||
elif isinstance(attr_type, (entity_type, type_declaration)):
|
||||
invalid = not isinstance(val, ifcopenshell.entity_instance) or not val.is_a(attr_type.name())
|
||||
elif isinstance(attr_type, select_type):
|
||||
@@ -85,77 +90,79 @@ def assert_valid(attr, val):
|
||||
invalid = len(val) < b1 or (b2 != -1 and len(val) > b2) or not all(assert_valid(ty, v) for v in val)
|
||||
else:
|
||||
raise NotImplementedError("Not impl %s %s" % (type(attr_type), attr_type))
|
||||
|
||||
|
||||
if invalid:
|
||||
raise ValidationError("%r not valid for %s" % (val, attr))
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def try_valid(attr, val):
|
||||
try:
|
||||
return assert_valid(attr, val)
|
||||
except ValidationError as e:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def validate(f, logger):
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(f.schema)
|
||||
for inst in f:
|
||||
if hasattr(logger, 'set_instance'):
|
||||
if hasattr(logger, "set_instance"):
|
||||
logger.set_instance(inst)
|
||||
|
||||
|
||||
entity = schema.declaration_by_name(inst.is_a())
|
||||
|
||||
|
||||
if entity.is_abstract():
|
||||
e = "Entity %s is abstract" % entity.name()
|
||||
if hasattr(logger, 'set_instance'):
|
||||
if hasattr(logger, "set_instance"):
|
||||
logger.error(e)
|
||||
else:
|
||||
logger.error('In %s\n%s', inst, e)
|
||||
logger.error("In %s\n%s", inst, e)
|
||||
|
||||
for attr, val, is_derived in zip(entity.all_attributes(), inst, entity.derived()):
|
||||
|
||||
|
||||
if val is None and not (is_derived or attr.optional()):
|
||||
logger.error("Attribute %s.%s not optional", entity, attr)
|
||||
logger.error("Attribute %s.%s not optional", entity, attr)
|
||||
|
||||
if val is not None:
|
||||
attr_type = attr.type_of_attribute()
|
||||
try:
|
||||
try:
|
||||
assert_valid(attr, val)
|
||||
except ValidationError as e:
|
||||
if hasattr(logger, 'set_instance'):
|
||||
if hasattr(logger, "set_instance"):
|
||||
logger.error(str(e))
|
||||
else:
|
||||
logger.error('In %s\n%s', inst, e)
|
||||
|
||||
logger.error("In %s\n%s", inst, e)
|
||||
|
||||
for attr in entity.all_inverse_attributes():
|
||||
val = getattr(inst, attr.name())
|
||||
try:
|
||||
assert_valid_inverse(attr, val)
|
||||
except ValidationError as e:
|
||||
if hasattr(logger, 'set_instance'):
|
||||
if hasattr(logger, "set_instance"):
|
||||
logger.error(str(e))
|
||||
else:
|
||||
logger.error('In %s\n%s', inst, e)
|
||||
logger.error("In %s\n%s", inst, e)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import logging
|
||||
|
||||
filenames = [x for x in sys.argv[1:] if not x.startswith('--')]
|
||||
flags = set(x for x in sys.argv[1:] if x.startswith('--'))
|
||||
|
||||
|
||||
filenames = [x for x in sys.argv[1:] if not x.startswith("--")]
|
||||
flags = set(x for x in sys.argv[1:] if x.startswith("--"))
|
||||
|
||||
for fn in filenames:
|
||||
if '--json' in flags:
|
||||
if "--json" in flags:
|
||||
logger = json_logger()
|
||||
else:
|
||||
logger = logging.getLogger('validate')
|
||||
logger = logging.getLogger("validate")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
f = ifcopenshell.open(fn)
|
||||
|
||||
|
||||
print("Validating", fn, file=sys.stderr)
|
||||
validate(f, logger)
|
||||
|
||||
if '--json' in flags:
|
||||
|
||||
if "--json" in flags:
|
||||
print("\n".join(json.dumps(x, default=str) for x in logger.statements))
|
||||
|
||||
Reference in New Issue
Block a user