mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
New cmake for doc
This commit is contained in:
+16
-1
@@ -23,6 +23,10 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # not necessary, but encouraged
|
||||
|
||||
project (IfcOpenShell)
|
||||
|
||||
|
||||
#set(Boost_DEBUG 1)
|
||||
|
||||
|
||||
foreach(max_year RANGE 2014 2030)
|
||||
set(max_sdk "$ENV{ADSK_3DSMAX_SDK_${max_year}}")
|
||||
if (NOT "${max_sdk}" STREQUAL "")
|
||||
@@ -104,6 +108,17 @@ MACRO(UNIFY_ENVVARS_AND_CACHE VAR)
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_ROOT)
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_LIBRARYDIR)
|
||||
|
||||
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_ROOT)
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_LIBRARYDIR)
|
||||
|
||||
message(STATUS "BOOST_ROOT ${BOOST_ROOT}")
|
||||
message(STATUS "BOOST_LIBRARYDIR ${BOOST_LIBRARYDIR}")
|
||||
|
||||
|
||||
UNIFY_ENVVARS_AND_CACHE(OCC_INCLUDE_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(OCC_LIBRARY_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(OPENCOLLADA_INCLUDE_DIR)
|
||||
@@ -208,7 +223,7 @@ function(add_debug_variants NAME LIBRARIES POSTFIX)
|
||||
endfunction()
|
||||
|
||||
if(BUILD_IFCGEOM)
|
||||
|
||||
MESSAGE(STATUS "OCC_INCLUDE_DIR ${OCC_INCLUDE_DIR}")
|
||||
# Find Open CASCADE
|
||||
IF("${OCC_INCLUDE_DIR}" STREQUAL "")
|
||||
SET(OCC_INCLUDE_DIR "/usr/include/oce/" CACHE FILEPATH "Open CASCADE header files")
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if hasattr(os, 'uname'):
|
||||
platform_system = os.uname()[0].lower()
|
||||
else:
|
||||
platform_system = 'windows'
|
||||
|
||||
if sys.maxsize == (1 << 31) - 1:
|
||||
platform_architecture = '32bit'
|
||||
else:
|
||||
platform_architecture = '64bit'
|
||||
|
||||
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)))
|
||||
|
||||
try:
|
||||
from . import ifcopenshell_wrapper
|
||||
except Exception as e:
|
||||
if int(python_version_tuple[0]) == 2:
|
||||
# Only for py2, as py3 has exception chaining
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
print('-' * 64)
|
||||
raise ImportError("IfcOpenShell not built for '%s'" % python_distribution)
|
||||
|
||||
from . import guid
|
||||
from .file import file
|
||||
from .entity_instance import entity_instance
|
||||
|
||||
|
||||
def open(fn):
|
||||
f = ifcopenshell_wrapper.open(os.path.abspath(fn))
|
||||
if f.good():
|
||||
return file(f)
|
||||
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()]
|
||||
for idx, arg in attrs:
|
||||
e[idx] = arg
|
||||
return e
|
||||
|
||||
|
||||
from .main import *
|
||||
Binary file not shown.
@@ -0,0 +1,254 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import functools
|
||||
import numbers
|
||||
import itertools
|
||||
|
||||
from . import ifcopenshell_wrapper
|
||||
|
||||
try:
|
||||
import logging
|
||||
except ImportError as e:
|
||||
logging = type('logger', (object,), {'exception': staticmethod(lambda s: print(s))})
|
||||
|
||||
|
||||
class entity_instance(object):
|
||||
"""This is the base Python class for all IFC objects.
|
||||
|
||||
An instantiated entity_instance will have methods of Python and the IFC class itself.
|
||||
|
||||
Example::
|
||||
|
||||
ifc_file = ifcopenshell.open(file_path)
|
||||
products = ifc_file.by_type("IfcProduct")
|
||||
print(products[0].__class__)
|
||||
>>> <class 'ifcopenshell.entity_instance.entity_instance'>
|
||||
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)
|
||||
|
||||
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)))
|
||||
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))
|
||||
|
||||
@staticmethod
|
||||
def walk(f, g, value):
|
||||
if isinstance(value, (tuple, list)):
|
||||
return tuple(map(functools.partial(entity_instance.walk, f, g), value))
|
||||
elif f(value):
|
||||
return g(value)
|
||||
else:
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def wrap_value(v):
|
||||
def wrap(e): return entity_instance(e)
|
||||
|
||||
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 is_instance(e): return isinstance(e, entity_instance)
|
||||
|
||||
return entity_instance.walk(is_instance, unwrap, v)
|
||||
|
||||
def attribute_type(self, attr):
|
||||
"""Return the data type of a positional attribute of the element
|
||||
|
||||
:param attr: The index of the attribute
|
||||
:type attr: int
|
||||
:rtype: string
|
||||
"""
|
||||
attr_idx = attr if isinstance(attr, numbers.Integral) else self.wrapped_data.get_argument_index(attr)
|
||||
return self.wrapped_data.get_argument_type(attr_idx)
|
||||
|
||||
def attribute_name(self, attr_idx):
|
||||
"""Return the name of a positional attribute of the element
|
||||
|
||||
:param attr_idx: The index of the attribute
|
||||
:type attr_idx: int
|
||||
:rtype: string
|
||||
"""
|
||||
return self.wrapped_data.get_argument_name(attr_idx)
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
self[self.wrapped_data.get_argument_index(key)] = value
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key < 0 or key >= len(self):
|
||||
raise IndexError("Attribute index {} out of range for instance of type {}".format(key, self.is_a()))
|
||||
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')
|
||||
|
||||
if value is None:
|
||||
if attr_type != "Derived":
|
||||
self.wrapped_data.setArgumentAsNull(idx)
|
||||
else:
|
||||
valid = attr_type != "Derived"
|
||||
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))
|
||||
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))
|
||||
|
||||
return value
|
||||
|
||||
def __len__(self):
|
||||
return len(self.wrapped_data)
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.wrapped_data)
|
||||
|
||||
def is_a(self, *args):
|
||||
"""Return the IFC class name of an instance, or checks if an instance belongs to a class.
|
||||
|
||||
The check will also return true if a parent class name is provided.
|
||||
|
||||
:param args: If specified, is a case insensitive IFC class name to check
|
||||
:type args: string
|
||||
:returns: Either the name of the class, or a boolean if it passes the check
|
||||
:rtype: string|bool
|
||||
|
||||
Example::
|
||||
|
||||
f = ifcopenshell.file()
|
||||
f.create_entity('IfcPerson')
|
||||
f.is_a()
|
||||
>>> 'IfcPerson'
|
||||
f.is_a('IfcPerson')
|
||||
>>> True
|
||||
"""
|
||||
return self.wrapped_data.is_a(*args)
|
||||
|
||||
def id(self):
|
||||
"""Return the STEP numerical identifier
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
return self.wrapped_data.id()
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(self, type(other)):
|
||||
return False
|
||||
return self.wrapped_data == other.wrapped_data
|
||||
|
||||
def __hash__(self):
|
||||
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())
|
||||
)))
|
||||
|
||||
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.
|
||||
|
||||
:param include_identifier: Whether or not to include the STEP numerical identifier
|
||||
:type include_identifier: bool
|
||||
:param recursive: Whether or not to convert referenced IFC elements into dictionaries too. All attributes also apply recursively
|
||||
:type recursive: bool
|
||||
:param return_type: The return data type to be casted into
|
||||
:type return_type: dict|list|other
|
||||
:param ignore: A list of attribute names to ignore
|
||||
:type ignore: set|list
|
||||
:returns: A dictionary of properties and their corresponding values
|
||||
:rtype: dict
|
||||
|
||||
Example::
|
||||
|
||||
ifc_file = ifcopenshell.open(file_path)
|
||||
products = ifc_file.by_type("IfcProduct")
|
||||
obj_info = products[0].get_info()
|
||||
print(obj_info.keys())
|
||||
>>> dict_keys(['Description', 'Name', 'BuildingAddress', 'LongName', 'GlobalId', 'ObjectPlacement', 'OwnerHistory', 'ObjectType',
|
||||
>>> ...'ElevationOfTerrain', 'CompositionType', 'id', 'Representation', 'type', 'ElevationOfRefHeight'])
|
||||
"""
|
||||
def _():
|
||||
try:
|
||||
if include_identifier:
|
||||
yield "id", self.id()
|
||||
yield "type", self.is_a()
|
||||
except BaseException:
|
||||
logging.exception("unhandled exception while getting id / type info on {}".format(self))
|
||||
for i in range(len(self)):
|
||||
try:
|
||||
if self.wrapped_data.get_attribute_names()[i] in ignore:
|
||||
continue
|
||||
attr_value = self[i]
|
||||
if recursive:
|
||||
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
|
||||
)
|
||||
|
||||
attr_value = entity_instance.walk(is_instance, get_info_, attr_value)
|
||||
yield self.attribute_name(i), attr_value
|
||||
except BaseException:
|
||||
logging.exception("unhandled exception occurred setting attribute name for {}".format(self))
|
||||
|
||||
return return_type(_())
|
||||
|
||||
__dict__ = property(get_info)
|
||||
@@ -0,0 +1,184 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import numbers
|
||||
import functools
|
||||
|
||||
from . import ifcopenshell_wrapper
|
||||
from .entity_instance import entity_instance
|
||||
|
||||
try:
|
||||
# Python 2
|
||||
basestring
|
||||
except NameError:
|
||||
# Python 3 or newer
|
||||
basestring = (str, bytes)
|
||||
|
||||
|
||||
class file(object):
|
||||
"""Base class for containing IFC files.
|
||||
|
||||
Class has instance methods for filtering by element Id, Type, etc.
|
||||
Instantiated objects can be subscripted by Id or Guid
|
||||
|
||||
Example::
|
||||
|
||||
ifc_file = ifcopenshell.open(file_path)
|
||||
products = ifc_file.by_type("IfcProduct")
|
||||
print(products[0].id(), products[0].GlobalId)
|
||||
>>> 122 2XQ$n5SLP5MBLyL442paFx
|
||||
# Subscripting
|
||||
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
|
||||
else:
|
||||
args = filter(None, [schema])
|
||||
args = map(ifcopenshell_wrapper.schema_by_name, args)
|
||||
self.wrapped_data = ifcopenshell_wrapper.file(*args)
|
||||
|
||||
def create_entity(self, type, *args, **kwargs):
|
||||
"""Create a new IFC entity in the file.
|
||||
|
||||
:param type: Case insensitive name of the IFC class
|
||||
:type type: string
|
||||
:param args: The positional arguments of the IFC class
|
||||
:param kwargs: The keyword arguments of the IFC class
|
||||
:returns: An entity instance
|
||||
:rtype: ifcopenshell.entity_instance.entity_instance
|
||||
|
||||
Example::
|
||||
|
||||
f = ifcopenshell.file()
|
||||
f.create_entity('IfcPerson')
|
||||
>>> #1=IfcPerson($,$,$,$,$,$,$,$)
|
||||
f.create_entity('IfcPerson', 'Foobar')
|
||||
>>> #2=IfcPerson('Foobar',$,$,$,$,$,$,$)
|
||||
f.create_entity('IfcPerson', Identification='Foobar')
|
||||
>>> #3=IfcPerson('Foobar',$,$,$,$,$,$,$)
|
||||
"""
|
||||
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()]
|
||||
for idx, arg in attrs:
|
||||
e[idx] = arg
|
||||
return e
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr[0:6] == 'create':
|
||||
return functools.partial(self.create_entity, attr[6:])
|
||||
else:
|
||||
return getattr(self.wrapped_data, attr)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, numbers.Integral):
|
||||
return entity_instance(self.wrapped_data.by_id(key))
|
||||
elif isinstance(key, basestring):
|
||||
return entity_instance(self.wrapped_data.by_guid(str(key)))
|
||||
|
||||
def by_id(self, id):
|
||||
"""Return an IFC entity instance filtered by IFC ID.
|
||||
|
||||
:param id: STEP numerical identifier
|
||||
:type id: int
|
||||
:returns: An ifcopenshell.entity_instance.entity_instance
|
||||
:rtype: ifcopenshell.entity_instance.entity_instance
|
||||
"""
|
||||
return self[id]
|
||||
|
||||
def by_guid(self, guid):
|
||||
"""Return an IFC entity instance filtered by IFC GUID.
|
||||
|
||||
:param guid: GlobalId value in 22-character encoded form
|
||||
:type guid: string
|
||||
:returns: An ifcopenshell.entity_instance.entity_instance
|
||||
:rtype: ifcopenshell.entity_instance.entity_instance
|
||||
"""
|
||||
return self[guid]
|
||||
|
||||
def add(self, inst):
|
||||
"""Adds an entity including any dependent entities to an IFC file.
|
||||
|
||||
If the entity already exists, it is not re-added."""
|
||||
inst.wrapped_data.this.disown()
|
||||
return entity_instance(self.wrapped_data.add(inst.wrapped_data))
|
||||
|
||||
def by_type(self, type):
|
||||
"""Return IFC objects filtered by IFC Type and wrapped with the entity_instance class.
|
||||
|
||||
If an IFC type class has subclasses, all entities of those subclasses are also returned.
|
||||
|
||||
:param type: The case insensitive type of IFC class to return.
|
||||
:type type: string
|
||||
:returns: A list of ifcopenshell.entity_instance.entity_instance objects
|
||||
:rtype: list
|
||||
"""
|
||||
return [entity_instance(e) for e in self.wrapped_data.by_type(type)]
|
||||
|
||||
def traverse(self, inst, max_levels=None):
|
||||
"""Get a list of all referenced instances for a particular instance including itself
|
||||
|
||||
:param inst: The entity instance to get all sub instances
|
||||
:type inst: ifcopenshell.entity_instance.entity_instance
|
||||
:param max_levels: How far deep to recursively fetch sub instances. None or -1 means infinite.
|
||||
:type max_levels: None|int
|
||||
:returns: A list of ifcopenshell.entity_instance.entity_instance objects
|
||||
:rtype: list
|
||||
"""
|
||||
if max_levels is None:
|
||||
max_levels = -1
|
||||
return [entity_instance(e) for e in self.wrapped_data.traverse(inst.wrapped_data, max_levels)]
|
||||
|
||||
def get_inverse(self, inst):
|
||||
"""Return a list of entities that reference this entity
|
||||
|
||||
:param inst: The entity instance to get inverse relationships
|
||||
:type inst: ifcopenshell.entity_instance.entity_instance
|
||||
:returns: A list of ifcopenshell.entity_instance.entity_instance objects
|
||||
:rtype: list
|
||||
"""
|
||||
return [entity_instance(e) for e in self.wrapped_data.get_inverse(inst.wrapped_data)]
|
||||
|
||||
def remove(self, inst):
|
||||
"""Deletes an IFC object in the file.
|
||||
|
||||
Attribute values in other entity instances that reference the deleted
|
||||
object will be set to null. In the case of a list or set of references,
|
||||
the reference to the deleted will be removed from the aggregate.
|
||||
|
||||
:param inst: The entity instance to delete
|
||||
:type inst: ifcopenshell.entity_instance.entity_instance
|
||||
:rtype: None
|
||||
"""
|
||||
return self.wrapped_data.remove(inst.wrapped_data)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self[id] for id in self.wrapped_data.entity_names())
|
||||
|
||||
@staticmethod
|
||||
def from_string(s):
|
||||
return file(ifcopenshell_wrapper.read(s))
|
||||
@@ -0,0 +1,45 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
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
|
||||
|
||||
return False
|
||||
|
||||
|
||||
has_occ = _has_occ()
|
||||
|
||||
if has_occ:
|
||||
from . import occ_utils as utils
|
||||
|
||||
from .main import *
|
||||
@@ -0,0 +1,647 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import operator
|
||||
import functools
|
||||
import multiprocessing
|
||||
|
||||
import OCC.AIS
|
||||
|
||||
from collections import defaultdict, Iterable, OrderedDict
|
||||
|
||||
try:
|
||||
QString = unicode
|
||||
except NameError:
|
||||
# Python 3
|
||||
QString = str
|
||||
|
||||
os.environ['QT_API'] = 'pyqt5'
|
||||
try:
|
||||
from pyqode.qt import QtCore
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from .code_editor_pane import code_edit
|
||||
|
||||
try:
|
||||
from OCC.Display.pyqt5Display import qtViewer3d
|
||||
except BaseException:
|
||||
import OCC.Display
|
||||
|
||||
try:
|
||||
import OCC.Display.backend
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
try:
|
||||
OCC.Display.backend.get_backend("qt-pyqt5")
|
||||
except BaseException:
|
||||
OCC.Display.backend.load_backend("qt-pyqt5")
|
||||
|
||||
from OCC.Display.qtDisplay import qtViewer3d
|
||||
|
||||
from .main import settings, iterator
|
||||
from .occ_utils import display_shape
|
||||
|
||||
from .. import open as open_ifc_file
|
||||
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')
|
||||
|
||||
class geometry_creation_thread(QtCore.QThread):
|
||||
def __init__(self, signals, settings, f):
|
||||
QtCore.QThread.__init__(self)
|
||||
self.signals = signals
|
||||
self.settings = settings
|
||||
self.f = f
|
||||
|
||||
def run(self):
|
||||
t0 = time.time()
|
||||
|
||||
# detect concurrency from hardware, we need to have
|
||||
# at least two threads because otherwise the interface
|
||||
# is different
|
||||
# is different
|
||||
it = iterator(self.settings, self.f, max(2, multiprocessing.cpu_count()))
|
||||
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
|
||||
|
||||
def Cfg():
|
||||
return configparser.ConfigParser(interpolation=None)
|
||||
|
||||
conf_file = os.path.expanduser(os.path.join("~", ".ifcopenshell", "app", "snippets.conf"))
|
||||
if conf_file.startswith("~"):
|
||||
conf_file = None
|
||||
return
|
||||
|
||||
self.config_encode = lambda s: s.replace("\\", "\\\\").replace("\n", "\n|")
|
||||
self.config_decode = lambda s: s.replace("\n|", "\n").replace("\\\\", "\\")
|
||||
|
||||
if not os.path.exists(os.path.dirname(conf_file)):
|
||||
os.makedirs(os.path.dirname(conf_file))
|
||||
|
||||
if not os.path.exists(conf_file):
|
||||
config = Cfg()
|
||||
config.add_section("snippets")
|
||||
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 #
|
||||
###########################################################################
|
||||
|
||||
for wall in model.by_type("IfcWall"):
|
||||
print ("wall with global id: "+str(wall.GlobalId))
|
||||
""".lstrip()))
|
||||
|
||||
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 #
|
||||
###########################################################################
|
||||
|
||||
# check if something is selected
|
||||
if selection:
|
||||
#get the IfcProduct that is stored in the global variable 'selection'
|
||||
obj = selection
|
||||
for relDefinesByProperties in obj.IsDefinedBy:
|
||||
print("[{0}]".format(relDefinesByProperties.RelatingPropertyDefinition.Name))
|
||||
for prop in relDefinesByProperties.RelatingPropertyDefinition.HasProperties:
|
||||
print ("{:<20} :{}".format(prop.Name,prop.NominalValue.wrappedValue))
|
||||
print ("\\n")
|
||||
""".lstrip()))
|
||||
with open(conf_file, 'w') as configfile:
|
||||
config.write(configfile)
|
||||
|
||||
self.config = Cfg()
|
||||
self.config.read(conf_file)
|
||||
|
||||
def options(self, s):
|
||||
return OrderedDict([(k, self.config_decode(self.config.get(s, k))) for k in self.config.options(s)])
|
||||
|
||||
|
||||
class application(QtWidgets.QApplication):
|
||||
"""A pythonOCC, PyQt based IfcOpenShell application
|
||||
with two tree views and a graphical 3d view"""
|
||||
|
||||
class abstract_treeview(QtWidgets.QTreeWidget):
|
||||
|
||||
"""Base class for the two treeview controls"""
|
||||
|
||||
instanceSelected = QtCore.pyqtSignal([object])
|
||||
instanceVisibilityChanged = QtCore.pyqtSignal([object, int])
|
||||
instanceDisplayModeChanged = QtCore.pyqtSignal([object, int])
|
||||
|
||||
def __init__(self):
|
||||
QtWidgets.QTreeView.__init__(self)
|
||||
self.setColumnCount(len(self.ATTRIBUTES))
|
||||
self.setHeaderLabels(self.ATTRIBUTES)
|
||||
self.children = defaultdict(list)
|
||||
|
||||
def get_children(self, inst):
|
||||
c = [inst]
|
||||
i = 0
|
||||
while i < len(c):
|
||||
c.extend(self.children[c[i]])
|
||||
i += 1
|
||||
return c
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
menu = QtWidgets.QMenu(self)
|
||||
visibility = [menu.addAction("Show"), menu.addAction("Hide")]
|
||||
displaymode = [menu.addAction("Solid"), menu.addAction("Wireframe")]
|
||||
action = menu.exec_(self.mapToGlobal(event.pos()))
|
||||
index = self.selectionModel().currentIndex()
|
||||
inst = index.data(QtCore.Qt.UserRole)
|
||||
if hasattr(inst, 'toPyObject'):
|
||||
inst = inst
|
||||
if action in visibility:
|
||||
self.instanceVisibilityChanged.emit(inst, visibility.index(action))
|
||||
elif action in displaymode:
|
||||
self.instanceDisplayModeChanged.emit(inst, displaymode.index(action))
|
||||
|
||||
def clicked_(self, index):
|
||||
inst = index.data(QtCore.Qt.UserRole)
|
||||
if hasattr(inst, 'toPyObject'):
|
||||
inst = inst
|
||||
if inst:
|
||||
self.instanceSelected.emit(inst)
|
||||
|
||||
def select(self, product):
|
||||
itm = self.product_to_item.get(product)
|
||||
if itm is None:
|
||||
return
|
||||
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']
|
||||
|
||||
def parent(self, instance):
|
||||
if instance.is_a("IfcOpeningElement"):
|
||||
return instance.VoidsElements[0].RelatingBuildingElement
|
||||
if instance.is_a("IfcElement"):
|
||||
fills = instance.FillsVoids
|
||||
if len(fills):
|
||||
return fills[0].RelatingOpeningElement
|
||||
containments = instance.ContainedInStructure
|
||||
if len(containments):
|
||||
return containments[0].RelatingStructure
|
||||
if instance.is_a("IfcObjectDefinition"):
|
||||
decompositions = instance.Decomposes
|
||||
if len(decompositions):
|
||||
return decompositions[0].RelatingObject
|
||||
|
||||
def load_file(self, f, **kwargs):
|
||||
products = list(f.by_type("IfcProduct")) + list(f.by_type("IfcProject"))
|
||||
parents = list(map(self.parent, products))
|
||||
items = {}
|
||||
skipped = 0
|
||||
ATTRS = self.ATTRIBUTES
|
||||
while len(items) + skipped < len(products):
|
||||
for product, parent in zip(products, parents):
|
||||
if parent is None and not product.is_a("IfcProject"):
|
||||
skipped += 1
|
||||
continue
|
||||
if (parent is None or parent in items) and product not in items:
|
||||
sl = []
|
||||
for attr in ATTRS:
|
||||
if attr == 'Entity':
|
||||
sl.append(product.is_a())
|
||||
else:
|
||||
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)
|
||||
self.product_to_item = dict(zip(items.keys(), map(self.indexFromItem, items.values())))
|
||||
self.clicked.connect(self.clicked_)
|
||||
self.expandAll()
|
||||
|
||||
class type_treeview(abstract_treeview):
|
||||
|
||||
"""Treeview with typical IFC decomposition relationships"""
|
||||
|
||||
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:
|
||||
add(s)
|
||||
s2, t2 = map(QString, (s, t))
|
||||
if t2 not in items:
|
||||
itm = items[t2] = QtWidgets.QTreeWidgetItem(items.get(s2, self), [t2])
|
||||
itm.setData(0, QtCore.Qt.UserRole, t2)
|
||||
self.children[s2].append(t2)
|
||||
|
||||
if ifcopenshell_version < "0.6":
|
||||
add(t)
|
||||
|
||||
for p in products:
|
||||
t = QString(p.is_a())
|
||||
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)
|
||||
|
||||
self.product_to_item = dict(zip(items.keys(), map(self.indexFromItem, items.values())))
|
||||
self.clicked.connect(self.clicked)
|
||||
self.expandAll()
|
||||
|
||||
class property_table(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self):
|
||||
QtWidgets.QWidget.__init__(self)
|
||||
self.layout = QtWidgets.QVBoxLayout(self)
|
||||
self.setLayout(self.layout)
|
||||
self.scroll = QtWidgets.QScrollArea(self)
|
||||
self.layout.addWidget(self.scroll)
|
||||
self.scroll.setWidgetResizable(True)
|
||||
self.scrollContent = QtWidgets.QWidget(self.scroll)
|
||||
self.scrollLayout = QtWidgets.QVBoxLayout(self.scrollContent)
|
||||
self.scrollContent.setLayout(self.scrollLayout)
|
||||
self.scroll.setWidget(self.scrollContent)
|
||||
self.prop_dict = {}
|
||||
|
||||
# triggered by selection event in either component of parent
|
||||
def select(self, product):
|
||||
|
||||
# Clear the old contents if any
|
||||
while self.scrollLayout.count():
|
||||
child = self.scrollLayout.takeAt(0)
|
||||
if child is not None:
|
||||
if child.widget() is not None:
|
||||
child.widget().deleteLater()
|
||||
|
||||
self.scroll = QtWidgets.QScrollArea()
|
||||
self.scroll.setWidgetResizable(True)
|
||||
|
||||
prop_sets = self.prop_dict.get(str(product))
|
||||
|
||||
if prop_sets is not None:
|
||||
for k, v in prop_sets:
|
||||
group_box = QtWidgets.QGroupBox()
|
||||
|
||||
group_box.setTitle(k)
|
||||
group_layout = QtWidgets.QVBoxLayout()
|
||||
group_box.setLayout(group_layout)
|
||||
|
||||
for name, value in v.items():
|
||||
prop_name = str(name)
|
||||
|
||||
value_str = value
|
||||
if hasattr(value_str, "wrappedValue"):
|
||||
value_str = value_str.wrappedValue
|
||||
|
||||
if isinstance(value_str, unicode):
|
||||
value_str = value_str.encode('utf-8')
|
||||
else:
|
||||
value_str = str(value_str)
|
||||
|
||||
if hasattr(value, "is_a"):
|
||||
type_str = " <i>(%s)</i>" % value.is_a()
|
||||
else:
|
||||
type_str = ""
|
||||
label = QtWidgets.QLabel("<b>%s</b>: %s%s" % (prop_name, value_str, type_str))
|
||||
group_layout.addWidget(label)
|
||||
|
||||
group_layout.addStretch()
|
||||
self.scrollLayout.addWidget(group_box)
|
||||
|
||||
self.scrollLayout.addStretch()
|
||||
else:
|
||||
label = QtWidgets.QLabel("No IfcPropertySets asscociated with selected entity instance")
|
||||
self.scrollLayout.addWidget(label)
|
||||
|
||||
def load_file(self, f, **kwargs):
|
||||
for p in f.by_type("IfcProduct"):
|
||||
propsets = []
|
||||
|
||||
def process_pset(prop_def):
|
||||
if prop_def is not None:
|
||||
prop_set_name = prop_def.Name
|
||||
props = {}
|
||||
if prop_def.is_a("IfcElementQuantity"):
|
||||
for q in prop_def.Quantities:
|
||||
if q.is_a("IfcPhysicalSimpleQuantity"):
|
||||
props[q.Name] = q[3]
|
||||
elif prop_def.is_a("IfcPropertySet"):
|
||||
for prop in prop_def.HasProperties:
|
||||
if prop.is_a("IfcPropertySingleValue"):
|
||||
props[prop.Name] = prop.NominalValue
|
||||
else:
|
||||
# Entity introduced in IFC4
|
||||
# prop_def.is_a("IfcPreDefinedPropertySet"):
|
||||
for prop in range(4, len(prop_def)):
|
||||
props[prop_def.attribute_name(prop)] = prop_def[prop]
|
||||
return prop_set_name, props
|
||||
|
||||
try:
|
||||
for is_def_by in p.IsDefinedBy:
|
||||
if is_def_by.is_a("IfcRelDefinesByProperties"):
|
||||
propsets.append(process_pset(is_def_by.RelatingPropertyDefinition))
|
||||
elif is_def_by.is_a("IfcRelDefinesByType"):
|
||||
type_psets = is_def_by.RelatingType.HasPropertySets
|
||||
if type_psets is None:
|
||||
continue
|
||||
for propset in type_psets:
|
||||
propsets.append(process_pset(propset))
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print("failed to load properties: {}".format(e))
|
||||
traceback.print_exc()
|
||||
|
||||
if len(propsets):
|
||||
self.prop_dict[str(p)] = propsets
|
||||
|
||||
print("property set dictionary has {} entries".format(len(self.prop_dict)))
|
||||
|
||||
class viewer(qtViewer3d):
|
||||
|
||||
instanceSelected = QtCore.pyqtSignal([object])
|
||||
|
||||
@staticmethod
|
||||
def ais_to_key(ais_handle):
|
||||
def yield_shapes():
|
||||
ais = ais_handle.GetObject()
|
||||
if hasattr(ais, 'Shape'):
|
||||
yield ais.Shape()
|
||||
return
|
||||
shp = OCC.AIS.Handle_AIS_Shape.DownCast(ais_handle)
|
||||
if not shp.IsNull():
|
||||
yield shp.Shape()
|
||||
return
|
||||
mult = ais_handle
|
||||
if mult.IsNull():
|
||||
shp = OCC.AIS.Handle_AIS_Shape.DownCast(ais_handle)
|
||||
if not shp.IsNull():
|
||||
yield shp
|
||||
else:
|
||||
li = mult.GetObject().ConnectedTo()
|
||||
for i in range(li.Length()):
|
||||
shp = OCC.AIS.Handle_AIS_Shape.DownCast(li.Value(i + 1))
|
||||
if not shp.IsNull():
|
||||
yield shp
|
||||
|
||||
return tuple(shp.HashCode(1 << 24) for shp in yield_shapes())
|
||||
|
||||
def __init__(self, widget):
|
||||
qtViewer3d.__init__(self, widget)
|
||||
self.ais_to_product = {}
|
||||
self.product_to_ais = {}
|
||||
self.counter = 0
|
||||
self.window = widget
|
||||
self.thread = None
|
||||
|
||||
def initialize(self):
|
||||
self.InitDriver()
|
||||
self._display.Select = self.HandleSelection
|
||||
|
||||
def finished(self, file_shapes):
|
||||
it, f, shapes = file_shapes
|
||||
v = self._display
|
||||
|
||||
t = {0: time.time()}
|
||||
|
||||
def update(dt=None):
|
||||
t1 = time.time()
|
||||
if dt is None or t1 - t[0] > dt:
|
||||
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'}:
|
||||
v.Context.Erase(ais, True)
|
||||
|
||||
update(1.)
|
||||
|
||||
update()
|
||||
|
||||
self.thread = None
|
||||
|
||||
def load_file(self, f, setting=None):
|
||||
|
||||
if self.thread is not None:
|
||||
return
|
||||
|
||||
if setting is None:
|
||||
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.signals.completed.connect(self.finished)
|
||||
self.thread.start()
|
||||
|
||||
def select(self, product):
|
||||
ais = self.product_to_ais.get(product)
|
||||
if ais is None:
|
||||
return
|
||||
v = self._display.Context
|
||||
v.ClearSelected(False)
|
||||
v.SetSelected(ais, True)
|
||||
|
||||
def toggle(self, product_or_products, fn):
|
||||
if not isinstance(product_or_products, Iterable):
|
||||
product_or_products = [product_or_products]
|
||||
aiss = list(filter(None, map(self.product_to_ais.get, product_or_products)))
|
||||
last = len(aiss) - 1
|
||||
for i, ais in enumerate(aiss):
|
||||
fn(ais, i == last)
|
||||
|
||||
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):
|
||||
v = self._display.Context
|
||||
v.Select()
|
||||
v.InitSelected()
|
||||
if v.MoreSelected():
|
||||
ais = v.SelectedInteractive()
|
||||
inst = self.ais_to_product[ais.GetObject().SelectionPriority()]
|
||||
self.instanceSelected.emit(inst)
|
||||
|
||||
class window(QtWidgets.QMainWindow):
|
||||
|
||||
TITLE = "IfcOpenShell IFC viewer"
|
||||
|
||||
window_closed = QtCore.pyqtSignal([])
|
||||
|
||||
def __init__(self):
|
||||
QtWidgets.QMainWindow.__init__(self)
|
||||
self.setWindowTitle(self.TITLE)
|
||||
self.menu = self.menuBar()
|
||||
self.menus = {}
|
||||
|
||||
def closeEvent(self, *args):
|
||||
self.window_closed.emit()
|
||||
|
||||
def add_menu_item(self, menu, label, callback, icon=None, shortcut=None):
|
||||
m = self.menus.get(menu)
|
||||
if m is None:
|
||||
m = self.menu.addMenu(menu)
|
||||
self.menus[menu] = m
|
||||
|
||||
if icon:
|
||||
a = QtWidgets.QAction(QtGui.QIcon(icon), label, self)
|
||||
else:
|
||||
a = QtWidgets.QAction(label, self)
|
||||
|
||||
if shortcut:
|
||||
a.setShortcut(shortcut)
|
||||
|
||||
a.triggered.connect(callback)
|
||||
m.addAction(a)
|
||||
|
||||
def makeSelectionHandler(self, component):
|
||||
def handler(inst):
|
||||
for c in self.components:
|
||||
if c != component:
|
||||
c.select(inst)
|
||||
|
||||
return handler
|
||||
|
||||
def __init__(self, settings=None):
|
||||
QtWidgets.QApplication.__init__(self, sys.argv)
|
||||
self.window = application.window()
|
||||
self.tree = application.decomposition_treeview()
|
||||
self.tree2 = application.type_treeview()
|
||||
self.propview = self.property_table()
|
||||
self.canvas = application.viewer(self.window)
|
||||
self.tabs = QtWidgets.QTabWidget()
|
||||
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.propview, "Properties")
|
||||
splitter2 = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||
splitter2.addWidget(self.canvas)
|
||||
self.editor = code_edit(self.canvas, configuration().options('snippets'))
|
||||
splitter2.addWidget(self.editor)
|
||||
splitter.addWidget(splitter2)
|
||||
splitter.setSizes([200, 600])
|
||||
splitter2.setSizes([400, 200])
|
||||
self.window.setCentralWidget(splitter)
|
||||
self.canvas.initialize()
|
||||
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.tree.instanceSelected.connect(self.makeSelectionHandler(self.tree))
|
||||
self.tree2.instanceSelected.connect(self.makeSelectionHandler(self.tree2))
|
||||
self.canvas.instanceSelected.connect(self.makeSelectionHandler(self.canvas))
|
||||
for t in [self.tree, self.tree2]:
|
||||
t.instanceVisibilityChanged.connect(functools.partial(self.change_visibility, t))
|
||||
t.instanceDisplayModeChanged.connect(functools.partial(self.change_displaymode, t))
|
||||
|
||||
self.settings = settings
|
||||
|
||||
def change_visibility(self, tree, inst, flag):
|
||||
insts = tree.get_children(inst)
|
||||
self.canvas.toggle_visibility(insts, flag)
|
||||
|
||||
def change_displaymode(self, tree, inst, flag):
|
||||
insts = tree.get_children(inst)
|
||||
self.canvas.toggle_wireframe(insts, flag)
|
||||
|
||||
def start(self):
|
||||
self.window.show()
|
||||
sys.exit(self.exec_())
|
||||
|
||||
def browse(self):
|
||||
filename = QtWidgets.QFileDialog.getOpenFileName(self.window, 'Open file', ".",
|
||||
"Industry Foundation Classes (*.ifc)")[0]
|
||||
self.load(filename)
|
||||
|
||||
def clear(self):
|
||||
self.canvas._display.Context.RemoveAll()
|
||||
self.tree.clear()
|
||||
self.files.clear()
|
||||
|
||||
def load(self, fn):
|
||||
if fn in self.files:
|
||||
return
|
||||
f = open_ifc_file(str(fn))
|
||||
self.files[fn] = f
|
||||
for c in self.components:
|
||||
c.load_file(f, setting=self.settings)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
application().start()
|
||||
@@ -0,0 +1,103 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
Rough draft of a client application for the C++ IfcGeomServer binary
|
||||
"""
|
||||
|
||||
import os
|
||||
import numpy
|
||||
import subprocess
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
class message_headers(object):
|
||||
HELLO = 0xff00
|
||||
IFC_MODEL = HELLO + 1
|
||||
GET = IFC_MODEL + 1
|
||||
ENTITY = GET + 1
|
||||
MORE = ENTITY + 1
|
||||
NEXT = MORE + 1
|
||||
BYE = NEXT + 1
|
||||
GET_LOG = BYE + 1
|
||||
LOG = GET_LOG + 1
|
||||
DEFLECTION = LOG + 1
|
||||
SETTING = DEFLECTION + 1
|
||||
|
||||
message = namedtuple("message", ("header", "contents"))
|
||||
|
||||
def process(geomserver_exe, ifc_filename):
|
||||
|
||||
proc = subprocess.Popen([geomserver_exe], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||
|
||||
def cast(data, dtype, n=None):
|
||||
arr = numpy.frombuffer(data, dtype=dtype)
|
||||
if n is None: return arr[0]
|
||||
else: return arr
|
||||
|
||||
def read(dtype, n=None):
|
||||
data = proc.stdout.read(dtype().nbytes * (n or 1))
|
||||
return cast(data, dtype, n)
|
||||
|
||||
def read_message(header_assertion=None):
|
||||
header, size = read(numpy.int32, 2)
|
||||
assert header_assertion is None or header_assertion == header
|
||||
contents = b""
|
||||
if size > 0:
|
||||
contents = proc.stdout.read(size)
|
||||
return message(header, contents)
|
||||
|
||||
def write(header, contents=None):
|
||||
if contents is None: contents = []
|
||||
proc.stdin.write(numpy.int32(header).tobytes())
|
||||
integers_as_int32 = list(map(lambda s: numpy.int32(s) if isinstance(s, int) else s, contents))
|
||||
to_bytes = list(map(lambda s: s.tobytes() if hasattr(s, 'tobytes') else s, integers_as_int32))
|
||||
total_length = numpy.int32(sum(map(len, to_bytes)))
|
||||
proc.stdin.write(total_length.tobytes())
|
||||
for b in to_bytes:
|
||||
proc.stdin.write(b)
|
||||
proc.stdin.flush()
|
||||
|
||||
read_message(message_headers.HELLO)
|
||||
|
||||
# @todo: no need to read the entire file in memory
|
||||
s = open(ifc_filename, "rb").read()
|
||||
|
||||
write(message_headers.SETTING, [numpy.int32((1 << 4)), numpy.int32(1)])
|
||||
write(message_headers.IFC_MODEL, [numpy.int32(len(s)), s, b"\x00" * ((4 - (len(s) % 4)) % 4)])
|
||||
|
||||
while True:
|
||||
has_more = cast(read_message(message_headers.MORE).contents, numpy.int32) == 1
|
||||
if not has_more: break
|
||||
write(message_headers.GET)
|
||||
print(read_message(message_headers.ENTITY).contents)
|
||||
write(message_headers.NEXT)
|
||||
|
||||
write(message_headers.BYE)
|
||||
read_message(message_headers.BYE)
|
||||
proc.wait()
|
||||
assert proc.returncode == 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import platform
|
||||
exe_extension = ".exe" if platform.system() == 'Windows' else ""
|
||||
exe = os.environ.get("IFCGEOMSERVER") or ("IfcGeomServer" + exe_extension)
|
||||
for fn in sys.argv[1:]:
|
||||
process(exe, fn)
|
||||
@@ -0,0 +1,149 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from code import InteractiveConsole
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
try:
|
||||
from PyQt5 import QtWidgets
|
||||
except BaseException:
|
||||
QtWidgets = QtGui
|
||||
|
||||
try:
|
||||
from pyqode.core.panels import CheckerPanel
|
||||
from pyqode.core import api
|
||||
from pyqode.core import modes
|
||||
from pyqode.core import panels
|
||||
from pyqode.core.api import CodeEdit, ColorScheme
|
||||
from pyqode.python.modes import PyAutoIndentMode, PythonSH
|
||||
from pyqode.python.backend import server
|
||||
from pyqode.python import modes as pymodes, panels as pypanels, widgets
|
||||
from pyqode.python.widgets import PyInteractiveConsole
|
||||
|
||||
has_pyqode = True
|
||||
except BaseException:
|
||||
has_pyqode = False
|
||||
CodeEdit = QtWidgets.QPlainTextEdit
|
||||
|
||||
|
||||
class StdoutRedirector(object):
|
||||
"""A class for redirecting stdout to this Text widget."""
|
||||
|
||||
def __init__(self, widget):
|
||||
self.widget = widget
|
||||
self.isError = False
|
||||
|
||||
def write(self, myStr):
|
||||
self.widget.moveCursor(QtGui.QTextCursor.End)
|
||||
if self.isError:
|
||||
self.widget.setTextColor(QtCore.Qt.red)
|
||||
else:
|
||||
self.widget.setTextColor(QtCore.Qt.white)
|
||||
self.widget.insertPlainText(myStr)
|
||||
self.widget.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
|
||||
class code_edit(QtWidgets.QWidget):
|
||||
class Console(InteractiveConsole):
|
||||
def __init__(*args):
|
||||
InteractiveConsole.__init__(*args)
|
||||
|
||||
def enter(self, source):
|
||||
self.runcode(source)
|
||||
|
||||
def runCode(self):
|
||||
sys.stdout = StdoutRedirector(self.output)
|
||||
sys.stderr = StdoutRedirector(self.output)
|
||||
sys.stderr.isError = True
|
||||
|
||||
if not self.model:
|
||||
print("please load a model first", file=sys.stderr)
|
||||
else:
|
||||
self.c.enter(str(self.editor.toPlainText()))
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
|
||||
def select(self, product):
|
||||
self.c = self.Console({'model': self.model, 'viewer': self.viewer, 'selection': product})
|
||||
|
||||
def __init__(self, viewer, snippets=None):
|
||||
self.model = None
|
||||
self.viewer = viewer
|
||||
QtWidgets.QWidget.__init__(self)
|
||||
self.layout = QtWidgets.QVBoxLayout(self)
|
||||
self.setLayout(self.layout)
|
||||
self.c = None
|
||||
self.tools = QtWidgets.QHBoxLayout(self)
|
||||
self.layout.addLayout(self.tools)
|
||||
self.runbutton = QtWidgets.QPushButton("Run")
|
||||
width = self.runbutton.fontMetrics().boundingRect("Run").width() + 20
|
||||
self.runbutton.setMaximumWidth(width)
|
||||
self.tools.addWidget(self.runbutton)
|
||||
self.runbutton.clicked.connect(self.runCode)
|
||||
|
||||
editor = CodeEdit()
|
||||
if has_pyqode:
|
||||
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.EncodingPanel(), api.Panel.Position.TOP)
|
||||
editor.add_separator()
|
||||
editor.panels.append(pypanels.QuickDocPanel(), api.Panel.Position.BOTTOM)
|
||||
sh = editor.modes.append(PythonSH(editor.document()))
|
||||
editor.modes.append(modes.CaretLineHighlighterMode())
|
||||
editor.modes.append(modes.CodeCompletionMode())
|
||||
editor.modes.append(modes.ExtendedSelectionMode())
|
||||
editor.modes.append(modes.FileWatcherMode())
|
||||
editor.modes.append(modes.OccurrencesHighlighterMode())
|
||||
editor.modes.append(modes.RightMarginMode())
|
||||
editor.modes.append(modes.SmartBackSpaceMode())
|
||||
editor.modes.append(modes.SymbolMatcherMode())
|
||||
editor.modes.append(modes.ZoomMode())
|
||||
editor.modes.append(pymodes.CommentsMode())
|
||||
editor.modes.append(pymodes.CalltipsMode())
|
||||
auto = pymodes.PyAutoCompleteMode()
|
||||
auto.logger.setLevel(logging.CRITICAL)
|
||||
editor.modes.append(auto)
|
||||
editor.modes.append(pymodes.PyAutoIndentMode())
|
||||
editor.modes.append(pymodes.PyIndenterMode())
|
||||
editor.show()
|
||||
else:
|
||||
editor.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier;')
|
||||
|
||||
self.editor = editor
|
||||
self.snippets = snippets
|
||||
if self.snippets:
|
||||
self.list = QtWidgets.QComboBox(self)
|
||||
self.replace_snippet(0)
|
||||
for snip_name in self.snippets.keys():
|
||||
self.list.addItem(snip_name)
|
||||
self.tools.addWidget(self.list)
|
||||
self.list.currentIndexChanged[int].connect(self.replace_snippet)
|
||||
|
||||
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.layout.addWidget(self.output)
|
||||
|
||||
def replace_snippet(self, number=None):
|
||||
snip = list(self.snippets.values())[number]
|
||||
if has_pyqode:
|
||||
self.editor.setPlainText(snip, "", "")
|
||||
else:
|
||||
self.editor.setPlainText(snip)
|
||||
|
||||
def load_file(self, f, **kwargs):
|
||||
output = []
|
||||
sys.stdout = StdoutRedirector(self.output)
|
||||
self.model = f
|
||||
self.c = self.Console({'model': self.model, 'selection': None, 'viewer': self.viewer})
|
||||
sys.stdout = sys.__stdout__
|
||||
@@ -0,0 +1,193 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from .. import ifcopenshell_wrapper
|
||||
from ..file import file
|
||||
from ..entity_instance import entity_instance
|
||||
|
||||
from . import has_occ
|
||||
|
||||
|
||||
def wrap_shape_creation(settings, shape):
|
||||
return shape
|
||||
|
||||
|
||||
if has_occ:
|
||||
from . import occ_utils as utils
|
||||
|
||||
try:
|
||||
from OCC.Core import TopoDS
|
||||
except ImportError:
|
||||
from OCC import TopoDS
|
||||
|
||||
def wrap_shape_creation(settings, shape):
|
||||
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):
|
||||
if has_occ:
|
||||
USE_PYTHON_OPENCASCADE = -1
|
||||
|
||||
def set(self, *args):
|
||||
setting, value = args
|
||||
if setting == settings.USE_PYTHON_OPENCASCADE:
|
||||
self.set(settings.USE_BREP_DATA, value)
|
||||
self.set(settings.USE_WORLD_COORDS, value)
|
||||
self.set(settings.DISABLE_TRIANGULATION, value)
|
||||
self.use_python_opencascade = value
|
||||
else:
|
||||
ifcopenshell_wrapper.settings.set(self, *args)
|
||||
|
||||
|
||||
# Assert templated precision to match Python's internal float type
|
||||
assert ifcopenshell_wrapper.iterator_double_precision.mantissa_size() == sys.float_info.mant_dig
|
||||
_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):
|
||||
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)
|
||||
_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
|
||||
|
||||
class tree(ifcopenshell_wrapper.tree):
|
||||
|
||||
def __init__(self, file=None, settings=None):
|
||||
args = [self]
|
||||
if file is not None:
|
||||
args.append(file.wrapped_data)
|
||||
if settings is not None:
|
||||
args.append(settings)
|
||||
ifcopenshell_wrapper.tree.__init__(*args)
|
||||
|
||||
def add_file(self, file, settings):
|
||||
ifcopenshell_wrapper.tree.add_file(self, file.wrapped_data, settings)
|
||||
|
||||
def select(self, value, **kwargs):
|
||||
def unwrap(value):
|
||||
if isinstance(value, entity_instance):
|
||||
return value.wrapped_data
|
||||
elif all(map(lambda v: hasattr(value, v), "XYZ")):
|
||||
return value.X(), value.Y(), value.Z()
|
||||
return value
|
||||
|
||||
args = [self, unwrap(value)]
|
||||
if isinstance(value, entity_instance):
|
||||
args.append(kwargs.get("completely_within", False))
|
||||
elif has_occ:
|
||||
if isinstance(value, TopoDS.TopoDS_Shape):
|
||||
args[1] = utils.serialize_shape(value)
|
||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select(*args)]
|
||||
|
||||
def select_box(self, value, **kwargs):
|
||||
def unwrap(value):
|
||||
if isinstance(value, entity_instance):
|
||||
return value.wrapped_data
|
||||
elif hasattr(value, "Get"):
|
||||
return value.Get()[:3], value.Get()[3:]
|
||||
return value
|
||||
|
||||
args = [self, unwrap(value)]
|
||||
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))
|
||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select_box(*args)]
|
||||
|
||||
|
||||
def create_shape(settings, inst, repr=None):
|
||||
"""
|
||||
Return a geometric representation from STEP-based IFCREPRESENTATIONSHAPE
|
||||
or
|
||||
Return an OpenCASCADE BRep if settings.USE_PYTHON_OPENCASCADE == True
|
||||
|
||||
example:
|
||||
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.USE_PYTHON_OPENCASCADE, True)
|
||||
|
||||
ifc_file = ifcopenshell.open(file_path)
|
||||
products = ifc_file.by_type("IfcProduct")
|
||||
|
||||
for i, product in enumerate(products):
|
||||
if product.Representation is not None:
|
||||
try:
|
||||
shape = geom.create_shape(settings, inst=product).geometry
|
||||
shape_gpXYZ = shape.Location().Transformation().TranslationPart() # These are methods of the TopoDS_Shape class from pythonOCC
|
||||
print(shape_gpXYZ.X(), shape_gpXYZ.Y(), shape_gpXYZ.Z()) # These are methods of the gpXYZ class from pythonOCC
|
||||
"""
|
||||
return wrap_shape_creation(
|
||||
settings,
|
||||
ifcopenshell_wrapper.create_shape(
|
||||
settings,
|
||||
inst.wrapped_data,
|
||||
repr.wrapped_data if repr is not None else None
|
||||
))
|
||||
|
||||
|
||||
def iterate(settings, filename):
|
||||
it = iterator(settings, filename)
|
||||
if it.initialize():
|
||||
while True:
|
||||
yield it.get()
|
||||
if not it.next():
|
||||
break
|
||||
|
||||
|
||||
def make_shape_function(fn):
|
||||
def entity_instance_or_none(e):
|
||||
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 _
|
||||
|
||||
|
||||
serialise = make_shape_function(ifcopenshell_wrapper.serialise)
|
||||
tesselate = make_shape_function(ifcopenshell_wrapper.tesselate)
|
||||
@@ -0,0 +1,233 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import random
|
||||
import operator
|
||||
import warnings
|
||||
|
||||
from collections import namedtuple, Iterable
|
||||
|
||||
try:
|
||||
from OCC.Core import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
|
||||
except ImportError:
|
||||
from OCC import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
def initialize_display():
|
||||
import OCC.Display.SimpleGui
|
||||
|
||||
global handle, main_loop, add_menu, add_function_to_menu
|
||||
handle, main_loop, add_menu, add_function_to_menu = OCC.Display.SimpleGui.init_display()
|
||||
|
||||
def setup():
|
||||
viewer_handle = handle.GetViewer()
|
||||
viewer = viewer_handle.GetObject() if hasattr(viewer_handle, "GetObject") else viewer_handle
|
||||
|
||||
def lights():
|
||||
viewer.InitActiveLights()
|
||||
for _ in range(2):
|
||||
try:
|
||||
active_light = viewer.ActiveLight()
|
||||
except BaseException:
|
||||
break
|
||||
yield active_light
|
||||
viewer.NextActiveLights()
|
||||
|
||||
lights = list(lights())
|
||||
for l in lights:
|
||||
viewer.DelLight(l)
|
||||
|
||||
for dir in [V3d.V3d_TypeOfOrientation_Yup_AxoRight, V3d.V3d_TypeOfOrientation_Zup_AxoRight]:
|
||||
light = V3d.V3d_DirectionalLight(viewer_handle)
|
||||
light.SetDirection(dir)
|
||||
viewer.SetLightOn(light)
|
||||
|
||||
setup()
|
||||
return handle
|
||||
|
||||
|
||||
def yield_subshapes(shape):
|
||||
it = TopoDS.TopoDS_Iterator(shape)
|
||||
while it.More():
|
||||
yield it.Value()
|
||||
it.Next()
|
||||
|
||||
|
||||
def display_shape(shape, clr=None, viewer_handle=None):
|
||||
if viewer_handle is None:
|
||||
viewer_handle = handle
|
||||
|
||||
if isinstance(shape, shape_tuple):
|
||||
shape, representation = shape.geometry, shape
|
||||
else:
|
||||
representation = None
|
||||
|
||||
material = Graphic3d.Graphic3d_MaterialAspect(Graphic3d.Graphic3d_NOM_PLASTER)
|
||||
|
||||
if representation and not clr:
|
||||
if len(set(representation.styles)) == 1:
|
||||
clr = representation.styles[0]
|
||||
if min(clr) < 0. or max(clr) > 1.:
|
||||
clr = DEFAULT_STYLES.get(representation.data.type, DEFAULT_STYLES["DEFAULT"])
|
||||
|
||||
if clr:
|
||||
ais = AIS.AIS_Shape(shape)
|
||||
ais.SetMaterial(material)
|
||||
|
||||
if isinstance(clr, str):
|
||||
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):
|
||||
clr = tuple(clr)
|
||||
if len(clr) < 3 or len(clr) > 4:
|
||||
raise Exception("Need 3 or 4 color components. Got '%r'." % len(clr))
|
||||
qclr = Quantity.Quantity_Color(clr[0], clr[1], clr[2], Quantity.Quantity_TOC_RGB)
|
||||
elif isinstance(clr, Quantity.Quantity_Color):
|
||||
qclr = clr
|
||||
else:
|
||||
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])
|
||||
|
||||
elif representation and hasattr(AIS, "AIS_MultipleConnectedShape"):
|
||||
default_style_applied = None
|
||||
|
||||
ais = AIS.AIS_MultipleConnectedShape(shape)
|
||||
|
||||
subshapes = list(yield_subshapes(shape))
|
||||
lens = len(representation.styles), len(subshapes)
|
||||
if lens[0] != lens[1]:
|
||||
warnings.warn("Unable to assign styles to subshapes. Encountered %d styles for %d shapes." % lens)
|
||||
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"])
|
||||
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])
|
||||
ais.Connect(subshape.GetHandle())
|
||||
|
||||
# For some reason it is necessary to set transparency here again
|
||||
# in order for transparency to be rendered on the subshape.
|
||||
applied_styles = representation.styles
|
||||
if default_style_applied:
|
||||
if len(default_style_applied) == 3:
|
||||
default_style_applied += (1.,)
|
||||
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.)
|
||||
|
||||
else:
|
||||
ais = AIS.AIS_Shape(shape)
|
||||
ais.SetMaterial(material)
|
||||
|
||||
def r():
|
||||
return random.random() * 0.3 + 0.7
|
||||
|
||||
clr = Quantity.Quantity_Color(r(), r(), r(), Quantity.Quantity_TOC_RGB)
|
||||
ais.SetColor(clr)
|
||||
|
||||
ais_handle = ais
|
||||
viewer_handle.Context.Display(ais_handle, False)
|
||||
|
||||
return ais_handle
|
||||
|
||||
|
||||
def set_shape_transparency(ais, t):
|
||||
handle.Context.SetTransparency(ais, t)
|
||||
|
||||
|
||||
def get_bounding_box_center(bbox):
|
||||
bbmin = [0.] * 3
|
||||
bbmax = [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)))
|
||||
|
||||
|
||||
def serialize_shape(shape):
|
||||
shapes = BRepTools.BRepTools_ShapeSet()
|
||||
shapes.Add(shape)
|
||||
return shapes.WriteToString()
|
||||
|
||||
|
||||
def create_shape_from_serialization(brep_object):
|
||||
brep_data, occ_shape, styles = None, None, ()
|
||||
|
||||
is_product_shape = True
|
||||
try:
|
||||
brep_data = brep_object.geometry.brep_data
|
||||
styles = brep_object.geometry.surface_styles
|
||||
except BaseException:
|
||||
try:
|
||||
brep_data = brep_object.brep_data
|
||||
styles = brep_object.surface_styles
|
||||
is_product_shape = False
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
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)
|
||||
|
||||
try:
|
||||
ss = BRepTools.BRepTools_ShapeSet()
|
||||
ss.ReadFromString(brep_data)
|
||||
occ_shape = ss.Shape(ss.NbShapes())
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
if is_product_shape:
|
||||
return shape_tuple(brep_object, occ_shape, styles)
|
||||
else:
|
||||
return occ_shape
|
||||
@@ -0,0 +1,57 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import uuid
|
||||
import string
|
||||
|
||||
from functools import reduce
|
||||
|
||||
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)]
|
||||
|
||||
def b64(v, l=4):
|
||||
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)])
|
||||
|
||||
|
||||
def expand(g):
|
||||
def b64(v):
|
||||
return reduce(lambda a, b: a * 64 + b, map(lambda c: chars.index(c), v))
|
||||
|
||||
bs = [b64(g[0:2])]
|
||||
for i in range(5):
|
||||
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])
|
||||
|
||||
|
||||
def split(g):
|
||||
return '{%s-%s-%s-%s-%s}' % (g[:8], g[8:12], g[12:16], g[16:20], g[20:])
|
||||
|
||||
|
||||
def new():
|
||||
return compress(uuid.uuid4().hex)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from . import ifcopenshell_wrapper
|
||||
|
||||
version = ifcopenshell_wrapper.version()
|
||||
get_log = ifcopenshell_wrapper.get_log
|
||||
@@ -0,0 +1,86 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from .file import file
|
||||
from .guid import compress
|
||||
from . import main
|
||||
|
||||
# A quick way to setup an 'empty' IFC file, taken from:
|
||||
# http://academy.ifcopenshell.org/creating-a-simple-wall-with-property-set-and-quantity-information/
|
||||
TEMPLATE = """ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
|
||||
FILE_NAME('%(filename)s','%(timestring)s',('%(creator)s'),('%(organization)s'),'%(application)s','%(application)s','');
|
||||
FILE_SCHEMA(('%(schema_identifier)s'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPERSON($,$,'%(creator)s',$,$,$,$,$);
|
||||
#2=IFCORGANIZATION($,'%(organization)s',$,$,$);
|
||||
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
|
||||
#4=IFCAPPLICATION(#2,'%(application_version)s','%(application)s','');
|
||||
#5=IFCOWNERHISTORY(#3,#4,$,.ADDED.,$,#3,#4,%(timestamp)s);
|
||||
#6=IFCDIRECTION((1.,0.,0.));
|
||||
#7=IFCDIRECTION((0.,0.,1.));
|
||||
#8=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
|
||||
#10=IFCDIRECTION((0.,1.,0.));
|
||||
#11=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#10);
|
||||
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
|
||||
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
|
||||
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
|
||||
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
|
||||
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
|
||||
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
|
||||
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
|
||||
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
|
||||
#20=IFCPROJECT('%(project_globalid)s',#5,'%(project_name)s',$,$,$,$,(#11),#19);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
"""
|
||||
|
||||
DEFAULTS = {
|
||||
"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()))
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
|
||||
d.update(dict(_()))
|
||||
|
||||
return file.from_string(TEMPLATE % d)
|
||||
@@ -0,0 +1,35 @@
|
||||
def get_psets(element):
|
||||
psets = {}
|
||||
try:
|
||||
if element.is_a('IfcTypeObject'):
|
||||
if element.HasPropertySets:
|
||||
for definition in element.HasPropertySets:
|
||||
psets[definition.Name] = get_properties(definition)
|
||||
else:
|
||||
for relationship in element.IsDefinedBy:
|
||||
if relationship.is_a('IfcRelDefinesByProperties'):
|
||||
definition = relationship.RelatingPropertyDefinition
|
||||
psets[definition.Name] = get_properties(definition)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print('failed to load properties: {}'.format(e))
|
||||
traceback.print_exc()
|
||||
return psets
|
||||
|
||||
def get_properties(definition):
|
||||
if definition is not None:
|
||||
props = {}
|
||||
if definition.is_a('IfcElementQuantity'):
|
||||
for q in definition.Quantities:
|
||||
if q.is_a('IfcPhysicalSimpleQuantity'):
|
||||
props[q.Name] = q[3]
|
||||
elif definition.is_a('IfcPropertySet'):
|
||||
for prop in definition.HasProperties:
|
||||
if prop.is_a('IfcPropertySingleValue'):
|
||||
props[prop.Name] = prop.NominalValue
|
||||
else:
|
||||
# Entity introduced in IFC4
|
||||
# definition.is_a('IfcPreDefinedPropertySet'):
|
||||
for prop in range(4, len(definition)):
|
||||
props[definition.attribute_name(prop)] = definition[prop]
|
||||
return props
|
||||
@@ -0,0 +1,26 @@
|
||||
import math
|
||||
|
||||
def dms2dd(degrees, minutes, seconds, milliseconds=0):
|
||||
dd = float(degrees) + float(minutes)/60.0 + float(seconds)/(3600.0) + float(milliseconds/3600000.0)
|
||||
return dd
|
||||
|
||||
def dd2dms(dd):
|
||||
dd = float(dd)
|
||||
sign = 1 if dd >= 0 else -1
|
||||
dd = abs(dd)
|
||||
minutes, seconds = divmod(dd*3600, 60)
|
||||
degrees, minutes = divmod(minutes, 60)
|
||||
if dd < 0:
|
||||
degrees = -degrees
|
||||
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.
|
||||
rotation = math.atan2(x_axis_ordinate, x_axis_abscissa)
|
||||
a = scale * math.cos(rotation)
|
||||
b = scale * math.sin(rotation)
|
||||
eastings = (a * x) - (b * y) + eastings
|
||||
northings = (b * x) + (a * y) + northings
|
||||
height = z + orthogonal_height
|
||||
return (eastings, northings, height)
|
||||
@@ -0,0 +1,156 @@
|
||||
import lark
|
||||
|
||||
class Selector():
|
||||
def parse(self, ifc_file, query):
|
||||
self.file = ifc_file
|
||||
l = lark.Lark('''start: query (lfunction query)*
|
||||
query: selector | group
|
||||
group: "(" query (lfunction query)* ")"
|
||||
selector: (inverse_relationship)? guid_selector | (inverse_relationship)? class_selector
|
||||
guid_selector: "#" /[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$]{22}/
|
||||
class_selector: "." WORD filter ?
|
||||
filter: "[" filter_key (comparison filter_value)? "]"
|
||||
filter_key: WORD | pset_or_qto
|
||||
filter_value: ESCAPED_STRING
|
||||
pset_or_qto: /[A-Za-z0-9_]+/ "." /[A-Za-z0-9_]+/
|
||||
lfunction: and | or
|
||||
inverse_relationship: types | contains_elements
|
||||
types: "*"
|
||||
contains_elements: "@"
|
||||
and: "&"
|
||||
or: "|"
|
||||
comparison: contains | morethanequalto | lessthanequalto | equal | morethan | lessthan
|
||||
contains: "*="
|
||||
morethanequalto: ">="
|
||||
lessthanequalto: "<"
|
||||
equal: "="
|
||||
morethan: ">"
|
||||
lessthan: "<"
|
||||
|
||||
// Embed common.lark for packaging
|
||||
DIGIT: "0".."9"
|
||||
HEXDIGIT: "a".."f"|"A".."F"|DIGIT
|
||||
INT: DIGIT+
|
||||
SIGNED_INT: ["+"|"-"] INT
|
||||
DECIMAL: INT "." INT? | "." INT
|
||||
_EXP: ("e"|"E") SIGNED_INT
|
||||
FLOAT: INT _EXP | DECIMAL _EXP?
|
||||
SIGNED_FLOAT: ["+"|"-"] FLOAT
|
||||
NUMBER: FLOAT | INT
|
||||
SIGNED_NUMBER: ["+"|"-"] NUMBER
|
||||
_STRING_INNER: /.*?/
|
||||
_STRING_ESC_INNER: _STRING_INNER /(?<!\\\\)(\\\\\\\\)*?/
|
||||
ESCAPED_STRING : "\\"" _STRING_ESC_INNER "\\""
|
||||
LCASE_LETTER: "a".."z"
|
||||
UCASE_LETTER: "A".."Z"
|
||||
LETTER: UCASE_LETTER | LCASE_LETTER
|
||||
WORD: LETTER+
|
||||
CNAME: ("_"|LETTER) ("_"|LETTER|DIGIT)*
|
||||
WS_INLINE: (" "|/\\t/)+
|
||||
WS: /[ \\t\\f\\r\\n]/+
|
||||
CR : /\\r/
|
||||
LF : /\\n/
|
||||
NEWLINE: (CR? LF)+
|
||||
|
||||
%ignore WS // Disregard spaces in text
|
||||
''')
|
||||
|
||||
start = l.parse(query)
|
||||
return self.get_group(start)
|
||||
|
||||
def get_group(self, group):
|
||||
lfunction = None
|
||||
for child in group.children:
|
||||
if child.data == 'query':
|
||||
new_results = self.get_query(child)
|
||||
if not lfunction:
|
||||
results = new_results
|
||||
elif lfunction == 'or':
|
||||
results.extend(new_results)
|
||||
elif lfunction == 'and':
|
||||
results = list(set(results).intersection(new_results))
|
||||
results = list(set(results))
|
||||
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':
|
||||
return self.get_selector(child)
|
||||
elif child.data == 'group':
|
||||
return self.get_group(child)
|
||||
|
||||
def get_selector(self, selector):
|
||||
if len(selector.children) == 1:
|
||||
inverse_relationship = None
|
||||
class_or_guid_selector = selector.children[0]
|
||||
else:
|
||||
inverse_relationship = selector.children[0]
|
||||
class_or_guid_selector = selector.children[1]
|
||||
|
||||
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':
|
||||
results = self.get_guid_selector(class_or_guid_selector)
|
||||
|
||||
if not inverse_relationship:
|
||||
return results
|
||||
return self.parse_inverse_relationship(results, inverse_relationship.children[0].data)
|
||||
|
||||
def parse_inverse_relationship(self, elements, inverse_relationship):
|
||||
results = []
|
||||
for element in elements:
|
||||
if inverse_relationship == 'types':
|
||||
if hasattr(element, 'Types') and element.Types:
|
||||
results.extend(element.Types[0].RelatedObjects)
|
||||
elif hasattr(element, 'ObjectTypeOf') and element.ObjectTypeOf:
|
||||
results.extend(element.ObjectTypeOf[0].RelatedObjects)
|
||||
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):
|
||||
elements = self.file.by_type(class_selector.children[0])
|
||||
if len(class_selector.children) > 1 \
|
||||
and class_selector.children[1].data == 'filter':
|
||||
return self.filter_elements(elements, class_selector.children[1])
|
||||
return elements
|
||||
|
||||
def filter_elements(self, elements, filter_rule):
|
||||
results = []
|
||||
key = filter_rule.children[0].children[0]
|
||||
if not isinstance(key, str):
|
||||
key = key.children[0] + '.' + key.children[1]
|
||||
comparison = value = None
|
||||
if len(filter_rule.children) > 1:
|
||||
comparison = filter_rule.children[1].children[0].data
|
||||
value = filter_rule.children[2].children[0][1:-1]
|
||||
for element in elements:
|
||||
element_value = IfcAttributeExtractor.get_element_key(element, key)
|
||||
if not element_value:
|
||||
continue
|
||||
if not comparison \
|
||||
or self.filter_element(element, element_value, comparison, value):
|
||||
results.append(element)
|
||||
return results
|
||||
|
||||
def filter_element(self, element, element_value, comparison, value):
|
||||
if comparison == 'equal':
|
||||
return str(element_value) == value
|
||||
elif comparison == 'contains':
|
||||
return value in str(element_value)
|
||||
elif comparison == 'morethan':
|
||||
return element_value > float(value)
|
||||
elif comparison == 'lessthan':
|
||||
return element_value < float(value)
|
||||
elif comparison == 'morethanequalto':
|
||||
return element_value >= float(value)
|
||||
elif comparison == 'lessthanequalto':
|
||||
return element_value <= float(value)
|
||||
return False
|
||||
|
||||
def get_guid_selector(self, guid_selector):
|
||||
return [self.file.by_id(guid_selector.children[0])]
|
||||
@@ -0,0 +1,64 @@
|
||||
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}
|
||||
|
||||
unit_names = ['AMPERE', 'BECQUEREL', 'CANDELA', 'COULOMB',
|
||||
'CUBIC_METRE', 'DEGREE CELSIUS', 'FARAD', 'GRAM', 'GRAY', 'HENRY',
|
||||
'HERTZ', 'JOULE', 'KELVIN', 'LUMEN', 'LUX', 'MOLE', 'NEWTON', 'OHM',
|
||||
'PASCAL', 'RADIAN', 'SECOND', 'SIEMENS', 'SIEVERT', 'SQUARE METRE',
|
||||
'METRE', 'STERADIAN', 'TESLA', 'VOLT', 'WATT', 'WEBER']
|
||||
|
||||
si_conversions = {
|
||||
'inch': 0.0254,
|
||||
'foot': 0.3048,
|
||||
'yard': 0.914,
|
||||
'mile': 1609,
|
||||
'square inch': 0.0006452,
|
||||
'square foot': 0.09290,
|
||||
'square yard': 0.83612736,
|
||||
'acre': 4046.86,
|
||||
'square mile': 2588881,
|
||||
'cubic inch': 0.00001639,
|
||||
'cubic foot': 0.02832,
|
||||
'cubic yard': 0.7636,
|
||||
'litre': 0.001,
|
||||
'fluid ounce UK': 0.0000284130625,
|
||||
'fluid ounce US': 0.00002957353,
|
||||
'pint UK': 0.000568,
|
||||
'pint US': 0.000473,
|
||||
'gallon UK': 0.004546,
|
||||
'gallon US': 0.003785,
|
||||
'degree': 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
|
||||
prefix = get_prefix(text)
|
||||
if prefix:
|
||||
return prefixes[prefix]
|
||||
return 1
|
||||
|
||||
def get_unit_name(text):
|
||||
for name in unit_names:
|
||||
if name in text.upper().replace('METER', 'METRE'):
|
||||
return name
|
||||
@@ -0,0 +1,109 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import ifcopenshell
|
||||
|
||||
named_type = ifcopenshell.ifcopenshell_wrapper.named_type
|
||||
aggregation_type = ifcopenshell.ifcopenshell_wrapper.aggregation_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
|
||||
|
||||
class ValidationError(Exception): pass
|
||||
|
||||
simple_type_python_mapping = {
|
||||
# @todo should include unicode for Python2
|
||||
"string": str,
|
||||
"integer": int,
|
||||
"real": float,
|
||||
"number": float,
|
||||
"boolean": bool,
|
||||
"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)
|
||||
if invalid:
|
||||
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
|
||||
# flatten the type declaration to something that
|
||||
# maps to the python types
|
||||
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()]
|
||||
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):
|
||||
invalid = not any(try_valid(x, val) for x in attr_type.select_list())
|
||||
elif isinstance(attr_type, enumeration_type):
|
||||
invalid = val not in attr_type.enumeration_items()
|
||||
elif isinstance(attr_type, aggregation_type):
|
||||
b1, b2 = attr_type.bound1(), attr_type.bound2()
|
||||
ty = attr_type.type_of_element()
|
||||
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:
|
||||
entity = schema.declaration_by_name(inst.is_a())
|
||||
|
||||
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))
|
||||
|
||||
if val is not None:
|
||||
attr_type = attr.type_of_attribute()
|
||||
try:
|
||||
assert_valid(attr, val)
|
||||
except ValidationError as e:
|
||||
logger.error('In {}\n{}'.format(inst, e))
|
||||
|
||||
for attr in entity.all_inverse_attributes():
|
||||
val = getattr(inst, attr.name())
|
||||
try:
|
||||
assert_valid_inverse(attr, val)
|
||||
except ValidationError as e:
|
||||
logger.error('In {}\n{}'.format(inst, e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import logging
|
||||
|
||||
for fn in sys.argv[1:]:
|
||||
logger = logging.getLogger('validate')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
print("Validating", fn)
|
||||
validate(ifcopenshell.open(fn), logger)
|
||||
@@ -50,6 +50,8 @@
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <time.h>
|
||||
@@ -1295,7 +1297,14 @@ namespace latebound_access {
|
||||
}
|
||||
|
||||
void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool stderr_progress) {
|
||||
Logger::Status("HLEEEEEEEE");
|
||||
std::ofstream outfile("test78.txt");
|
||||
|
||||
outfile << "my text here!" << std::endl;
|
||||
|
||||
outfile.close();
|
||||
{
|
||||
|
||||
auto delete_reversed = [&f](const IfcEntityList::ptr& insts) {
|
||||
if (!insts) {
|
||||
return;
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
Submodule test/input updated: 312056462f...a75c92451c
+177
@@ -0,0 +1,177 @@
|
||||
|
||||
This script fetches and builds all IfcOpenShell dependencies
|
||||
|
||||
Generator not passed but VisualStudioVersion=15.0 environment variable detected:
|
||||
using `Visual Studio 15 2017 Win64` as the generator.
|
||||
build-type-cfg.cmd: Warning: BUILD_CFG not specified - using the default RelWithDebInfo
|
||||
|
||||
Script configuration:
|
||||
* CMake Generator = `Visual Studio 15 2017 Win64`
|
||||
- Passed to CMake -G option.
|
||||
* Target Architecture = x64
|
||||
- Whether were doing 32-bit (x86) or 64-bit (x64) build.
|
||||
* Dependency Directory = C:\Users\jlutt\Documents\IfcOpenShell\deps
|
||||
- The directory where IfcOpenShell dependencies are fetched and built.
|
||||
* Installation Directory = C:\Users\jlutt\Documents\IfcOpenShell\deps-vs2017-x64-installed
|
||||
- The directory where IfcOpenShell dependencies are installed.
|
||||
* Build Config Type = RelWithDebInfo
|
||||
- The used build configuration type for the dependencies.
|
||||
Defaults to RelWithDebInfo if not specified.
|
||||
* Build Type = Build
|
||||
- The used build type for the dependencies (Build, Rebuild, Clean).
|
||||
Defaults to Build if not specified. Rebuild/Clean also uninstalls Python (if it was installed by this script).
|
||||
* IFCOS_USE_OCCT = TRUE
|
||||
- Use the official Open CASCADE instead of the community edition.
|
||||
* IFCOS_INSTALL_PYTHON = TRUE
|
||||
- Download and install Python.
|
||||
Set to something other than TRUE if you wish to use an already installed version of Python.
|
||||
* IFCOS_USE_PYTHON2 = FALSE
|
||||
- Use Python 2 instead of 3.
|
||||
Set to TRUE if you wish to use Python 2 instead of 3. Has no effect if IFCOS_INSTALL_PYTHON is not TRUE.
|
||||
* IFCOS_NUM_BUILD_PROCS = 8
|
||||
- How many MSBuild.exe processes may be run in parallel.
|
||||
Defaults to NUMBER_OF_PROCESSORS. Used also by other IfcOpenShell build scripts.
|
||||
|
||||
Requirements for a successful execution:
|
||||
1. Install PowerShell (preinstalled in Windows >= 7) version 5 or higher and make sure 'powershell' is accessible from PATH.
|
||||
- https://support.microsoft.com/en-us/kb/968929
|
||||
2. Install Git and make sure 'git' is accessible from PATH.
|
||||
- https://git-for-windows.github.io/
|
||||
3. Install CMake and make sure 'cmake' is accessible from PATH.
|
||||
- http://www.cmake.org/
|
||||
4. Visual Studio 2008 or newer (2013 or newer recommended) with C++ toolset.
|
||||
- https://www.visualstudio.com/
|
||||
5. Run this batch script with Visual Studio environment variables set.
|
||||
- https://msdn.microsoft.com/en-us/library/ms229859(v=vs.110).aspx
|
||||
|
||||
NB: This script needs to be ran from the directory directly containing it.
|
||||
|
||||
Warning: You will need roughly 8 GB of disk space to proceed (VS 2015 x64 RelWithDebInfo).
|
||||
|
||||
If you are not ready with the above: type 'n' in the prompt below. Build proceeds on all other inputs
|
||||
>
|
||||
Build started at 7:40:11.47.
|
||||
|
||||
Boost 1.67.0 already downloaded. Skipping.
|
||||
Boost 1.67.0 already extracted into C:\Users\jlutt\Documents\IfcOpenShell\deps\boost_1_67_0. Skipping.
|
||||
Building Boost 1.67.0 --with-system --with-regex --with-thread --with-program_options --with-date_time --with-iostreams --with-filesystem Please be patient this will take a while.
|
||||
Performing configuration checks
|
||||
|
||||
- default address-model : none
|
||||
- default architecture : none
|
||||
- symlinks supported : no
|
||||
- junctions supported : yes
|
||||
- hardlinks supported : yes
|
||||
- zlib : no
|
||||
- bzip2 : no
|
||||
- lzma : no
|
||||
- has_icu builds : no
|
||||
|
||||
Component configuration:
|
||||
|
||||
- atomic : not building
|
||||
- chrono : not building
|
||||
- container : not building
|
||||
- context : not building
|
||||
- contract : not building
|
||||
- coroutine : not building
|
||||
- date_time : building
|
||||
- exception : not building
|
||||
- fiber : not building
|
||||
- filesystem : building
|
||||
- graph : not building
|
||||
- graph_parallel : not building
|
||||
- iostreams : building
|
||||
- locale : not building
|
||||
- log : not building
|
||||
- math : not building
|
||||
- mpi : not building
|
||||
- program_options : building
|
||||
- python : not building
|
||||
- random : not building
|
||||
- regex : building
|
||||
- serialization : not building
|
||||
- signals : not building
|
||||
- stacktrace : not building
|
||||
- system : building
|
||||
- test : not building
|
||||
- thread : building
|
||||
- timer : not building
|
||||
- type_erasure : not building
|
||||
- wave : not building
|
||||
|
||||
...patience...
|
||||
...patience...
|
||||
...found 1696 targets...
|
||||
...updating 16 targets...
|
||||
...skipped <pbin.v2\libs\date_time\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>gregorian\greg_month.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\date_time\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>gregorian\greg_weekday.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\date_time\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>gregorian\date_generators.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\date_time\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_date_time-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\date_time\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>gregorian\greg_month.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_date_time-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\date_time\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_date_time-vc141-mt-s-1_67.lib...
|
||||
...skipped <pbin.v2\libs\system\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>error_code.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\system\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_system-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\system\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>error_code.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_system-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\system\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_system-vc141-mt-s-1_67.lib...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>codecvt_error_category.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>operations.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>path.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>path_traits.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>portability.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>unique_path.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>utf8_codecvt_facet.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>windows_file_codecvt.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_filesystem-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>codecvt_error_category.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_filesystem-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\filesystem\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_filesystem-vc141-mt-s-1_67.lib...
|
||||
...skipped <pbin.v2\libs\iostreams\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>file_descriptor.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\iostreams\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>mapped_file.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\iostreams\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_iostreams-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\iostreams\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>file_descriptor.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_iostreams-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\iostreams\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_iostreams-vc141-mt-s-1_67.lib...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>cmdline.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>config_file.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>options_description.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>parsers.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>variables_map.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>value_semantic.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>positional_options.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>utf8_codecvt_facet.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>convert.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>winmain.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>split.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_program_options-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>cmdline.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_program_options-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\program_options\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_program_options-vc141-mt-s-1_67.lib...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>c_regex_traits.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>cpp_regex_traits.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>cregex.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>fileiter.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>icu.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>instances.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>posix_api.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>regex.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>regex_debug.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>regex_raw_buffer.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>regex_traits_defaults.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>static_mutex.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>w32_regex_traits.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>wc_regex_traits.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>wide_posix_api.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>winstances.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>usinstances.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_regex-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>c_regex_traits.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_regex-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_regex-vc141-mt-s-1_67.lib...
|
||||
...skipped <pbin.v2\libs\chrono\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>chrono.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\chrono\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>thread_clock.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\chrono\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>process_cpu_clocks.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\chrono\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_chrono-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\chrono\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>chrono.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_chrono-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\chrono\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi>libboost_chrono-vc141-mt-s-1_67.lib...
|
||||
...skipped <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>win32\thread.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>win32\tss_dll.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>win32\tss_pe.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>win32\thread_primitives.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>future.obj for lack of <pbin.v2\standalone\msvc\msvc-14.1\address-model-64>msvc-setup.nup...
|
||||
...skipped <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>libboost_thread-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>win32\thread.obj...
|
||||
...skipped <pstage\vs2017-x64\lib>libboost_thread-vc141-mt-s-1_67.lib for lack of <pbin.v2\libs\thread\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threadapi-win32\threading-multi>libboost_thread-vc141-mt-s-1_67.lib...
|
||||
...skipped 66 targets...
|
||||
|
||||
An error occurred
|
||||
|
||||
Build ended at 7:40:17.03. Time elapsed 0:00:05.56.
|
||||
@@ -62,6 +62,10 @@ pushd ..\%BUILD_DIR%
|
||||
set BOOST_VERSION=1.67.0
|
||||
set BOOST_VER=%BOOST_VERSION:.=_%
|
||||
|
||||
|
||||
echo "TEEEEEEEEEEEST"
|
||||
echo %OCC_INCLUDE_DIR%
|
||||
|
||||
set BOOST_ROOT=%DEPS_DIR%\boost_%BOOST_VER%
|
||||
set BOOST_LIBRARYDIR=%BOOST_ROOT%\stage\vs%VS_VER%-%VS_PLATFORM%\lib
|
||||
if not defined OCC_INCLUDE_DIR set OCC_INCLUDE_DIR=%INSTALL_DIR%\oce\include\oce
|
||||
|
||||
Reference in New Issue
Block a user