Files
IfcOpenShell/src/ifcopenshell-python/ifcopenshell/geom/main.py
T

211 lines
8.2 KiB
Python
Raw Normal View History

2016-04-17 15:27:05 +02:00
###############################################################################
# #
# 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
2016-04-17 15:27:05 +02:00
import os
import sys
from .. import ifcopenshell_wrapper
from ..file import file
2016-06-22 15:03:18 +02:00
from ..entity_instance import entity_instance
2016-04-17 15:27:05 +02:00
2019-12-09 11:52:30 +01:00
from . import has_occ
2017-11-06 09:10:28 +01:00
2017-11-06 11:06:40 +01:00
def wrap_shape_creation(settings, shape):
return shape
2017-11-06 09:10:28 +01:00
2016-04-17 15:27:05 +02:00
if has_occ:
from . import occ_utils as utils
2017-11-06 09:10:28 +01:00
2019-12-08 16:57:36 +01:00
try:
from OCC.Core import TopoDS
except ImportError:
2019-12-08 16:57:36 +01:00
from OCC import TopoDS
2019-07-19 15:55:22 +02:00
def wrap_shape_creation(settings, shape):
if getattr(settings, 'use_python_opencascade', False):
return utils.create_shape_from_serialization(shape)
else:
return shape
2017-11-06 11:06:40 +01:00
2016-04-17 15:27:05 +02:00
# 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
2017-11-06 09:10:28 +01:00
2016-04-17 15:27:05 +02:00
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)
2017-11-06 09:10:28 +01:00
2018-07-08 10:32:26 +02:00
# Assert templated precision to match Python's internal float type
assert ifcopenshell_wrapper.iterator_double_precision.mantissa_size() == sys.float_info.mant_dig
2018-07-08 11:06:45 +02:00
_iterator = ifcopenshell_wrapper.iterator_double_precision
2016-04-17 15:27:05 +02:00
# Make sure people are able to use python's platform agnostic paths
class iterator(_iterator):
def __init__(self, settings, file_or_filename, num_threads = 1, include = None, exclude = None):
2016-04-17 15:27:05 +02:00
self.settings = settings
if isinstance(file_or_filename, file):
file_or_filename = file_or_filename.wrapped_data
else:
file_or_filename = os.path.abspath(file_or_filename)
if include is not None and exclude is not None:
raise ValueError("include and exclude cannot be specified simultaneously")
if include is not None or exclude is not None:
# Couldn't get the typemaps properly applied using %extend so we
# replicate the SWIG-generated __init__ call on the output of a
# free function.
# @todo verify this works with SWIG 4
self.this = ifcopenshell_wrapper.\
construct_iterator_double_precision_with_include_exclude(
self.settings,
file_or_filename,
include if exclude is None else exclude,
include is not None,
num_threads)
else:
_iterator.__init__(self, settings, file_or_filename, num_threads)
2017-11-06 11:06:40 +01:00
2016-04-17 15:27:05 +02:00
if has_occ:
def get(self):
return wrap_shape_creation(self.settings, _iterator.get(self))
2018-01-01 11:22:12 +01:00
def __iter__(self):
if self.initialize():
while True:
yield self.get()
if not self.next(): break
2016-04-17 15:27:05 +02:00
class tree(ifcopenshell_wrapper.tree):
2017-11-06 09:10:28 +01:00
def __init__(self, file=None, settings=None):
args = [self]
2017-11-06 09:10:28 +01:00
if file is not None:
args.append(file.wrapped_data)
if settings is not None:
args.append(settings)
ifcopenshell_wrapper.tree.__init__(*args)
2017-11-06 09:10:28 +01:00
def add_file(self, file, settings):
ifcopenshell_wrapper.tree.add_file(self, file.wrapped_data, settings)
2017-11-06 09:10:28 +01:00
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
2017-11-06 11:06:40 +01:00
args = [self, unwrap(value)]
if isinstance(value, entity_instance):
args.append(kwargs.get("completely_within", False))
elif has_occ:
2019-12-08 16:57:36 +01:00
if isinstance(value, TopoDS.TopoDS_Shape):
args[1] = utils.serialize_shape(value)
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select(*args)]
2017-11-06 09:10:28 +01:00
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
2017-11-06 11:06:40 +01:00
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))
2017-12-04 12:21:42 -08:00
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select_box(*args)]
2017-11-06 09:10:28 +01:00
def create_shape(settings, inst, repr=None):
2017-12-04 09:16:30 -08:00
"""
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
"""
2016-04-17 15:27:05 +02:00
return wrap_shape_creation(
settings,
ifcopenshell_wrapper.create_shape(
2017-11-06 09:10:28 +01:00
settings,
2016-04-17 15:27:05 +02:00
inst.wrapped_data,
repr.wrapped_data if repr is not None else None
2017-11-06 09:10:28 +01:00
))
2016-04-17 15:27:05 +02:00
def iterate(settings, file_or_filename, num_threads = 1, include = None, exclude = None):
it = iterator(settings, file_or_filename, num_threads, include, exclude)
2016-04-17 15:27:05 +02:00
if it.initialize():
while True:
yield it.get()
2017-11-06 09:10:28 +01:00
if not it.next():
break
2016-06-22 15:03:18 +02:00
def make_shape_function(fn):
2017-11-06 11:06:40 +01:00
def entity_instance_or_none(e):
return None if e is None else entity_instance(e)
2016-06-22 15:03:18 +02:00
if has_occ:
def _(schema, string_or_shape, *args):
2019-12-08 16:57:36 +01:00
if isinstance(string_or_shape, TopoDS.TopoDS_Shape):
2016-06-22 15:03:18 +02:00
string_or_shape = utils.serialize_shape(string_or_shape)
return entity_instance_or_none(fn(schema, string_or_shape, *args))
2016-06-22 15:03:18 +02:00
else:
def _(schema, string, *args):
return entity_instance_or_none(fn(schema, string, *args))
2016-06-22 15:03:18 +02:00
return _
2017-11-06 09:10:28 +01:00
2016-06-22 15:03:18 +02:00
serialise = make_shape_function(ifcopenshell_wrapper.serialise)
tesselate = make_shape_function(ifcopenshell_wrapper.tesselate)