diff --git a/src/ifcopenshell-python/ifcopenshell/geom/__init__.py b/src/ifcopenshell-python/ifcopenshell/geom/__init__.py index 2a0577f172..b4e933743a 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/__init__.py @@ -22,7 +22,33 @@ import sys from .. import ifcopenshell_wrapper -settings = ifcopenshell_wrapper.settings +def has_occ(): + try: import OCC.BRepTools + except: return False + return True + + +has_occ = has_occ() +wrap_shape_creation = lambda settings, shape: shape +if has_occ: + import occ_utils as utils + wrap_shape_creation = lambda settings, shape: utils.create_shape_from_serialization(shape) if getattr(settings, 'use_python_opencascade', False) else 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.DISABLE_TRIANGULATION, value) + self.use_python_opencascade = value + else: + ifcopenshell_wrapper.settings.set(self, *args) + # Hide templating precision to the user by choosing based on Python's # internal float type. This is probably always going to be a double. @@ -34,11 +60,15 @@ for ty in (ifcopenshell_wrapper.iterator_single_precision, ifcopenshell_wrapper. # Make sure people are able to use python's platform agnostic paths class iterator(_iterator): def __init__(self, settings, filename): + self.settings = settings _iterator.__init__(self, settings, os.path.abspath(filename)) + if has_occ: + def get(self): + return wrap_shape_creation(self.settings, _iterator.get(self)) def create_shape(settings, inst): - return ifcopenshell_wrapper.create_shape(settings, inst.wrapped_data) + return wrap_shape_creation(settings, ifcopenshell_wrapper.create_shape(settings, inst.wrapped_data)) def iterate(settings, filename): @@ -47,3 +77,5 @@ def iterate(settings, filename): while True: yield it.get() if not it.next(): break + + diff --git a/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py new file mode 100644 index 0000000000..be5c93e8b3 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py @@ -0,0 +1,66 @@ +import random +from collections import namedtuple + +import OCC.gp +import OCC.V3d +import OCC.Quantity +import OCC.BRepTools +import OCC.Display.SimpleGui + +tuple = namedtuple('shape', ('data', 'geometry')) + +handle, main_loop, add_menu, add_function_to_menu = None, None, None, None + +def initialize_display(): + 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() + while True: + viewer.InitActiveLights() + try: active_light = viewer.ActiveLight() + except: break + viewer.DelLight(active_light) + viewer.NextActiveLights() + for dir in [(1,2,-3), (-2,-1,1)]: + light = OCC.V3d.V3d_DirectionalLight(viewer_handle) + light.SetDirection(*dir) + viewer.SetLightOn(light.GetHandle()) + setup() + return handle + + +def display_shape(shape, clr=None): + if not clr: + r = lambda: random.random() * 0.3 + 0.7 + clr = OCC.Quantity.Quantity_Color(r(), r(), r(), OCC.Quantity.Quantity_TOC_RGB) + return handle.DisplayShape(shape, color=clr, update=True) + + +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 OCC.gp.gp_Pnt(*map(lambda xy: (xy[0]+xy[1])/2., zip(bbmin, bbmax))) + + +def create_shape_from_serialization(brep_object): + brep_data, occ_shape = None, None + + try: brep_data = brep_object.geometry.brep_data + except: pass + if not brep_data: return tuple(brep_object, None) + + try: + ss = OCC.BRepTools.BRepTools_ShapeSet() + ss.ReadFromString(brep_data) + occ_shape = ss.Shape(ss.NbShapes()) + except: pass + + return tuple(brep_object, occ_shape) +