mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
black ifcopenshell-python
This commit is contained in:
@@ -21,15 +21,18 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
def _has_occ():
|
||||
try:
|
||||
import OCC.Core.BRepTools
|
||||
|
||||
return True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import OCC.BRepTools
|
||||
|
||||
return True
|
||||
except ImportError:
|
||||
pass
|
||||
@@ -41,5 +44,5 @@ has_occ = _has_occ()
|
||||
|
||||
if has_occ:
|
||||
from . import occ_utils as utils
|
||||
|
||||
|
||||
from .main import *
|
||||
|
||||
@@ -12,9 +12,10 @@ import multiprocessing
|
||||
import OCC.AIS
|
||||
|
||||
from collections import defaultdict, OrderedDict
|
||||
|
||||
try: # python 3.3+
|
||||
from collections.abc import Iterable
|
||||
except ModuleNotFoundError: # python 2
|
||||
except ModuleNotFoundError: # python 2
|
||||
from collections import Iterable
|
||||
|
||||
try:
|
||||
@@ -23,7 +24,7 @@ except NameError:
|
||||
# Python 3
|
||||
QString = str
|
||||
|
||||
os.environ['QT_API'] = 'pyqt5'
|
||||
os.environ["QT_API"] = "pyqt5"
|
||||
try:
|
||||
from pyqode.qt import QtCore
|
||||
except BaseException:
|
||||
@@ -59,11 +60,13 @@ from .. import version as ifcopenshell_version
|
||||
if ifcopenshell_version < "0.6":
|
||||
# not yet ported
|
||||
from .. import get_supertype
|
||||
|
||||
|
||||
|
||||
class geometry_creation_signals(QtCore.QObject):
|
||||
completed = QtCore.pyqtSignal('PyQt_PyObject')
|
||||
progress = QtCore.pyqtSignal('PyQt_PyObject')
|
||||
|
||||
completed = QtCore.pyqtSignal("PyQt_PyObject")
|
||||
progress = QtCore.pyqtSignal("PyQt_PyObject")
|
||||
|
||||
|
||||
class geometry_creation_thread(QtCore.QThread):
|
||||
def __init__(self, signals, settings, f):
|
||||
QtCore.QThread.__init__(self)
|
||||
@@ -82,25 +85,27 @@ class geometry_creation_thread(QtCore.QThread):
|
||||
if not it.initialize():
|
||||
self.signals.completed.emit([])
|
||||
return
|
||||
|
||||
|
||||
def _():
|
||||
|
||||
old_progress = -1
|
||||
while True:
|
||||
shape = it.get()
|
||||
|
||||
|
||||
if shape:
|
||||
yield shape
|
||||
|
||||
|
||||
if not it.next():
|
||||
break
|
||||
|
||||
self.signals.completed.emit((it, self.f, list(_())))
|
||||
|
||||
|
||||
class configuration(object):
|
||||
def __init__(self):
|
||||
try:
|
||||
import ConfigParser
|
||||
|
||||
Cfg = ConfigParser.RawConfigParser
|
||||
except BaseException:
|
||||
import configparser
|
||||
@@ -122,7 +127,11 @@ class configuration(object):
|
||||
if not os.path.exists(conf_file):
|
||||
config = Cfg()
|
||||
config.add_section("snippets")
|
||||
config.set("snippets", "print all wall ids", self.config_encode("""
|
||||
config.set(
|
||||
"snippets",
|
||||
"print all wall ids",
|
||||
self.config_encode(
|
||||
"""
|
||||
###########################################################################
|
||||
# A simple script that iterates over all walls in the current model #
|
||||
# and prints their Globally unique IDs (GUIDS) to the console window #
|
||||
@@ -130,9 +139,15 @@ class configuration(object):
|
||||
|
||||
for wall in model.by_type("IfcWall"):
|
||||
print ("wall with global id: "+str(wall.GlobalId))
|
||||
""".lstrip()))
|
||||
""".lstrip()
|
||||
),
|
||||
)
|
||||
|
||||
config.set("snippets", "print properties of current selection", self.config_encode("""
|
||||
config.set(
|
||||
"snippets",
|
||||
"print properties of current selection",
|
||||
self.config_encode(
|
||||
"""
|
||||
###########################################################################
|
||||
# A simple script that iterates over all IfcPropertySets of the currently #
|
||||
# selected object and prints them to the console #
|
||||
@@ -147,8 +162,10 @@ if selection:
|
||||
for prop in relDefinesByProperties.RelatingPropertyDefinition.HasProperties:
|
||||
print ("{:<20} :{}".format(prop.Name,prop.NominalValue.wrappedValue))
|
||||
print ("\\n")
|
||||
""".lstrip()))
|
||||
with open(conf_file, 'w') as configfile:
|
||||
""".lstrip()
|
||||
),
|
||||
)
|
||||
with open(conf_file, "w") as configfile:
|
||||
config.write(configfile)
|
||||
|
||||
self.config = Cfg()
|
||||
@@ -191,7 +208,7 @@ class application(QtWidgets.QApplication):
|
||||
action = menu.exec_(self.mapToGlobal(event.pos()))
|
||||
index = self.selectionModel().currentIndex()
|
||||
inst = index.data(QtCore.Qt.UserRole)
|
||||
if hasattr(inst, 'toPyObject'):
|
||||
if hasattr(inst, "toPyObject"):
|
||||
inst = inst
|
||||
if action in visibility:
|
||||
self.instanceVisibilityChanged.emit(inst, visibility.index(action))
|
||||
@@ -200,7 +217,7 @@ class application(QtWidgets.QApplication):
|
||||
|
||||
def clicked_(self, index):
|
||||
inst = index.data(QtCore.Qt.UserRole)
|
||||
if hasattr(inst, 'toPyObject'):
|
||||
if hasattr(inst, "toPyObject"):
|
||||
inst = inst
|
||||
if inst:
|
||||
self.instanceSelected.emit(inst)
|
||||
@@ -209,14 +226,15 @@ class application(QtWidgets.QApplication):
|
||||
itm = self.product_to_item.get(product)
|
||||
if itm is None:
|
||||
return
|
||||
self.selectionModel().setCurrentIndex(itm,
|
||||
QtCore.QItemSelectionModel.SelectCurrent | QtCore.QItemSelectionModel.Rows)
|
||||
self.selectionModel().setCurrentIndex(
|
||||
itm, QtCore.QItemSelectionModel.SelectCurrent | QtCore.QItemSelectionModel.Rows
|
||||
)
|
||||
|
||||
class decomposition_treeview(abstract_treeview):
|
||||
|
||||
"""Treeview with typical IFC decomposition relationships"""
|
||||
|
||||
ATTRIBUTES = ['Entity', 'GlobalId', 'Name']
|
||||
ATTRIBUTES = ["Entity", "GlobalId", "Name"]
|
||||
|
||||
def parent(self, instance):
|
||||
if instance.is_a("IfcOpeningElement"):
|
||||
@@ -247,10 +265,10 @@ class application(QtWidgets.QApplication):
|
||||
if (parent is None or parent in items) and product not in items:
|
||||
sl = []
|
||||
for attr in ATTRS:
|
||||
if attr == 'Entity':
|
||||
if attr == "Entity":
|
||||
sl.append(product.is_a())
|
||||
else:
|
||||
sl.append(getattr(product, attr) or '')
|
||||
sl.append(getattr(product, attr) or "")
|
||||
itm = items[product] = QtWidgets.QTreeWidgetItem(items.get(parent, self), sl)
|
||||
itm.setData(0, QtCore.Qt.UserRole, product)
|
||||
self.children[parent].append(product)
|
||||
@@ -262,13 +280,14 @@ class application(QtWidgets.QApplication):
|
||||
|
||||
"""Treeview with typical IFC decomposition relationships"""
|
||||
|
||||
ATTRIBUTES = ['Name']
|
||||
ATTRIBUTES = ["Name"]
|
||||
|
||||
def load_file(self, f, **kwargs):
|
||||
products = list(f.by_type("IfcProduct"))
|
||||
types = set(map(lambda i: i.is_a(), products))
|
||||
items = {}
|
||||
for t in types:
|
||||
|
||||
def add(t):
|
||||
s = get_supertype(t)
|
||||
if s:
|
||||
@@ -284,7 +303,7 @@ class application(QtWidgets.QApplication):
|
||||
|
||||
for p in products:
|
||||
t = QString(p.is_a())
|
||||
itm = items[p] = QtWidgets.QTreeWidgetItem(items.get(t, self), [p.Name or '<no name>'])
|
||||
itm = items[p] = QtWidgets.QTreeWidgetItem(items.get(t, self), [p.Name or "<no name>"])
|
||||
itm.setData(0, QtCore.Qt.UserRole, t)
|
||||
self.children[t].append(p)
|
||||
|
||||
@@ -293,7 +312,6 @@ class application(QtWidgets.QApplication):
|
||||
self.expandAll()
|
||||
|
||||
class property_table(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self):
|
||||
QtWidgets.QWidget.__init__(self)
|
||||
self.layout = QtWidgets.QVBoxLayout(self)
|
||||
@@ -338,7 +356,7 @@ class application(QtWidgets.QApplication):
|
||||
value_str = value_str.wrappedValue
|
||||
|
||||
if isinstance(value_str, unicode):
|
||||
value_str = value_str.encode('utf-8')
|
||||
value_str = value_str.encode("utf-8")
|
||||
else:
|
||||
value_str = str(value_str)
|
||||
|
||||
@@ -392,6 +410,7 @@ class application(QtWidgets.QApplication):
|
||||
propsets.append(process_pset(propset))
|
||||
except Exception as e:
|
||||
import traceback
|
||||
|
||||
print("failed to load properties: {}".format(e))
|
||||
traceback.print_exc()
|
||||
|
||||
@@ -408,7 +427,7 @@ class application(QtWidgets.QApplication):
|
||||
def ais_to_key(ais_handle):
|
||||
def yield_shapes():
|
||||
ais = ais_handle.GetObject()
|
||||
if hasattr(ais, 'Shape'):
|
||||
if hasattr(ais, "Shape"):
|
||||
yield ais.Shape()
|
||||
return
|
||||
shp = OCC.AIS.Handle_AIS_Shape.DownCast(ais_handle)
|
||||
@@ -444,7 +463,7 @@ class application(QtWidgets.QApplication):
|
||||
def finished(self, file_shapes):
|
||||
it, f, shapes = file_shapes
|
||||
v = self._display
|
||||
|
||||
|
||||
t = {0: time.time()}
|
||||
|
||||
def update(dt=None):
|
||||
@@ -453,29 +472,29 @@ class application(QtWidgets.QApplication):
|
||||
v.FitAll()
|
||||
v.Repaint()
|
||||
t[0] = t1
|
||||
|
||||
|
||||
for shape in shapes:
|
||||
ais = display_shape(shape, viewer_handle=v)
|
||||
product = f[shape.data.id]
|
||||
|
||||
|
||||
ais.GetObject().SetSelectionPriority(self.counter)
|
||||
self.ais_to_product[self.counter] = product
|
||||
self.product_to_ais[product] = ais
|
||||
self.counter += 1
|
||||
|
||||
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
||||
if product.is_a() in {'IfcSpace', 'IfcOpeningElement'}:
|
||||
|
||||
if product.is_a() in {"IfcSpace", "IfcOpeningElement"}:
|
||||
v.Context.Erase(ais, True)
|
||||
|
||||
update(1.)
|
||||
|
||||
|
||||
update(1.0)
|
||||
|
||||
update()
|
||||
|
||||
|
||||
self.thread = None
|
||||
|
||||
|
||||
def load_file(self, f, setting=None):
|
||||
|
||||
|
||||
if self.thread is not None:
|
||||
return
|
||||
|
||||
@@ -483,10 +502,10 @@ class application(QtWidgets.QApplication):
|
||||
setting = settings()
|
||||
setting.set(setting.INCLUDE_CURVES, True)
|
||||
setting.set(setting.USE_PYTHON_OPENCASCADE, True)
|
||||
|
||||
|
||||
self.signals = geometry_creation_signals()
|
||||
thread = self.thread = geometry_creation_thread(self.signals, setting, f)
|
||||
self.window.window_closed.connect(lambda *args: thread.terminate())
|
||||
self.window.window_closed.connect(lambda *args: thread.terminate())
|
||||
self.signals.completed.connect(self.finished)
|
||||
self.thread.start()
|
||||
|
||||
@@ -509,23 +528,31 @@ class application(QtWidgets.QApplication):
|
||||
def toggle_visibility(self, product_or_products, flag):
|
||||
v = self._display.Context
|
||||
if flag:
|
||||
|
||||
def visibility(ais, last):
|
||||
v.Erase(ais, last)
|
||||
|
||||
else:
|
||||
|
||||
def visibility(ais, last):
|
||||
v.Display(ais, last)
|
||||
|
||||
self.toggle(product_or_products, visibility)
|
||||
|
||||
def toggle_wireframe(self, product_or_products, flag):
|
||||
v = self._display.Context
|
||||
if flag:
|
||||
|
||||
def wireframe(ais, last):
|
||||
if v.IsDisplayed(ais):
|
||||
v.SetDisplayMode(ais, 0, last)
|
||||
|
||||
else:
|
||||
|
||||
def wireframe(ais, last):
|
||||
if v.IsDisplayed(ais):
|
||||
v.SetDisplayMode(ais, 1, last)
|
||||
|
||||
self.toggle(product_or_products, wireframe)
|
||||
|
||||
def HandleSelection(self, X, Y):
|
||||
@@ -588,12 +615,12 @@ class application(QtWidgets.QApplication):
|
||||
self.window.resize(800, 600)
|
||||
splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
splitter.addWidget(self.tabs)
|
||||
self.tabs.addTab(self.tree, 'Decomposition')
|
||||
self.tabs.addTab(self.tree2, 'Types')
|
||||
self.tabs.addTab(self.tree, "Decomposition")
|
||||
self.tabs.addTab(self.tree2, "Types")
|
||||
self.tabs.addTab(self.propview, "Properties")
|
||||
splitter2 = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||
splitter2.addWidget(self.canvas)
|
||||
self.editor = code_edit(self.canvas, configuration().options('snippets'))
|
||||
self.editor = code_edit(self.canvas, configuration().options("snippets"))
|
||||
splitter2.addWidget(self.editor)
|
||||
splitter.addWidget(splitter2)
|
||||
splitter.setSizes([200, 600])
|
||||
@@ -603,9 +630,9 @@ class application(QtWidgets.QApplication):
|
||||
self.components = [self.tree, self.tree2, self.canvas, self.propview, self.editor]
|
||||
self.files = {}
|
||||
|
||||
self.window.add_menu_item('File', '&Open', self.browse, shortcut='CTRL+O')
|
||||
self.window.add_menu_item('File', '&Close', self.clear, shortcut='CTRL+W')
|
||||
self.window.add_menu_item('File', '&Exit', self.window.close, shortcut='ALT+F4')
|
||||
self.window.add_menu_item("File", "&Open", self.browse, shortcut="CTRL+O")
|
||||
self.window.add_menu_item("File", "&Close", self.clear, shortcut="CTRL+W")
|
||||
self.window.add_menu_item("File", "&Exit", self.window.close, shortcut="ALT+F4")
|
||||
|
||||
self.tree.instanceSelected.connect(self.makeSelectionHandler(self.tree))
|
||||
self.tree2.instanceSelected.connect(self.makeSelectionHandler(self.tree2))
|
||||
@@ -629,8 +656,9 @@ class application(QtWidgets.QApplication):
|
||||
sys.exit(self.exec_())
|
||||
|
||||
def browse(self):
|
||||
filename = QtWidgets.QFileDialog.getOpenFileName(self.window, 'Open file', ".",
|
||||
"Industry Foundation Classes (*.ifc)")[0]
|
||||
filename = QtWidgets.QFileDialog.getOpenFileName(
|
||||
self.window, "Open file", ".", "Industry Foundation Classes (*.ifc)"
|
||||
)[0]
|
||||
self.load(filename)
|
||||
|
||||
def clear(self):
|
||||
|
||||
@@ -70,7 +70,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
sys.stderr = sys.__stderr__
|
||||
|
||||
def select(self, product):
|
||||
self.c = self.Console({'model': self.model, 'viewer': self.viewer, 'selection': product})
|
||||
self.c = self.Console({"model": self.model, "viewer": self.viewer, "selection": product})
|
||||
|
||||
def __init__(self, viewer, snippets=None):
|
||||
self.model = None
|
||||
@@ -92,8 +92,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
editor.backend.start(server.__file__)
|
||||
editor.panels.append(panels.FoldingPanel())
|
||||
editor.panels.append(panels.LineNumberPanel())
|
||||
editor.panels.append(panels.SearchAndReplacePanel(),
|
||||
panels.SearchAndReplacePanel.Position.BOTTOM)
|
||||
editor.panels.append(panels.SearchAndReplacePanel(), panels.SearchAndReplacePanel.Position.BOTTOM)
|
||||
editor.panels.append(panels.EncodingPanel(), api.Panel.Position.TOP)
|
||||
editor.add_separator()
|
||||
editor.panels.append(pypanels.QuickDocPanel(), api.Panel.Position.BOTTOM)
|
||||
@@ -116,7 +115,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
editor.modes.append(pymodes.PyIndenterMode())
|
||||
editor.show()
|
||||
else:
|
||||
editor.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier;')
|
||||
editor.setStyleSheet("font-size: 10pt; font-family: Consolas, Courier;")
|
||||
|
||||
self.editor = editor
|
||||
self.snippets = snippets
|
||||
@@ -131,7 +130,7 @@ class code_edit(QtWidgets.QWidget):
|
||||
self.layout.addWidget(self.editor)
|
||||
self.output = QtWidgets.QTextEdit()
|
||||
self.output.setReadOnly(True)
|
||||
self.output.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier; background-color: #444;')
|
||||
self.output.setStyleSheet("font-size: 10pt; font-family: Consolas, Courier; background-color: #444;")
|
||||
self.layout.addWidget(self.output)
|
||||
|
||||
def replace_snippet(self, number=None):
|
||||
@@ -145,5 +144,5 @@ class code_edit(QtWidgets.QWidget):
|
||||
output = []
|
||||
sys.stdout = StdoutRedirector(self.output)
|
||||
self.model = f
|
||||
self.c = self.Console({'model': self.model, 'selection': None, 'viewer': self.viewer})
|
||||
self.c = self.Console({"model": self.model, "selection": None, "viewer": self.viewer})
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
@@ -45,11 +45,12 @@ if has_occ:
|
||||
from OCC import TopoDS
|
||||
|
||||
def wrap_shape_creation(settings, shape):
|
||||
if getattr(settings, 'use_python_opencascade', False):
|
||||
if getattr(settings, "use_python_opencascade", False):
|
||||
return utils.create_shape_from_serialization(shape)
|
||||
else:
|
||||
return shape
|
||||
|
||||
|
||||
# Subclass the settings module to provide an additional
|
||||
# setting to enable pythonOCC when available
|
||||
class settings(ifcopenshell_wrapper.settings):
|
||||
@@ -73,60 +74,57 @@ _iterator = ifcopenshell_wrapper.iterator_double_precision
|
||||
|
||||
# Make sure people are able to use python's platform agnostic paths
|
||||
class iterator(_iterator):
|
||||
def __init__(self, settings, file_or_filename, num_threads = 1, include = None, exclude = None):
|
||||
def __init__(self, settings, file_or_filename, num_threads=1, include=None, exclude=None):
|
||||
self.settings = settings
|
||||
if isinstance(file_or_filename, file):
|
||||
file_or_filename = file_or_filename.wrapped_data
|
||||
else:
|
||||
file_or_filename = os.path.abspath(file_or_filename)
|
||||
|
||||
|
||||
if include is not None and exclude is not None:
|
||||
raise ValueError("include and exclude cannot be specified simultaneously")
|
||||
|
||||
|
||||
if include is not None or exclude is not None:
|
||||
# Couldn't get the typemaps properly applied using %extend so we
|
||||
# replicate the SWIG-generated __init__ call on the output of a
|
||||
# free function.
|
||||
# @todo verify this works with SWIG 4
|
||||
|
||||
|
||||
include_or_exclude = include if exclude is None else exclude
|
||||
include_or_exclude_type = set(x.__class__.__name__ for x in include_or_exclude)
|
||||
print(include_or_exclude_type)
|
||||
|
||||
|
||||
if include_or_exclude_type == {"entity_instance"}:
|
||||
if not all(inst.is_a("IfcProduct") for inst in include_or_exclude):
|
||||
raise ValueError("include and exclude need to be an aggregate of IfcProduct")
|
||||
|
||||
initializer = ifcopenshell_wrapper.\
|
||||
construct_iterator_double_precision_with_include_exclude_globalid
|
||||
|
||||
decode_unicode = lambda x: x.encode('ascii') if x.__class__.__name__ == "unicode" else x
|
||||
include_or_exclude = list(map(decode_unicode, map(operator.attrgetter('GlobalId'), include_or_exclude)))
|
||||
|
||||
initializer = ifcopenshell_wrapper.construct_iterator_double_precision_with_include_exclude_globalid
|
||||
|
||||
decode_unicode = lambda x: x.encode("ascii") if x.__class__.__name__ == "unicode" else x
|
||||
include_or_exclude = list(map(decode_unicode, map(operator.attrgetter("GlobalId"), include_or_exclude)))
|
||||
else:
|
||||
initializer = ifcopenshell_wrapper.\
|
||||
construct_iterator_double_precision_with_include_exclude
|
||||
|
||||
initializer = ifcopenshell_wrapper.construct_iterator_double_precision_with_include_exclude
|
||||
|
||||
self.this = initializer(
|
||||
self.settings,
|
||||
file_or_filename,
|
||||
include_or_exclude,
|
||||
include is not None,
|
||||
num_threads)
|
||||
self.settings, file_or_filename, include_or_exclude, include is not None, num_threads
|
||||
)
|
||||
else:
|
||||
_iterator.__init__(self, settings, file_or_filename, num_threads)
|
||||
|
||||
if has_occ:
|
||||
|
||||
def get(self):
|
||||
return wrap_shape_creation(self.settings, _iterator.get(self))
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
if self.initialize():
|
||||
while True:
|
||||
yield self.get()
|
||||
if not self.next(): break
|
||||
if not self.next():
|
||||
break
|
||||
|
||||
|
||||
class tree(ifcopenshell_wrapper.tree):
|
||||
|
||||
def __init__(self, file=None, settings=None):
|
||||
args = [self]
|
||||
if file is not None:
|
||||
@@ -166,7 +164,7 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
if "extend" in kwargs or "completely_within" in kwargs:
|
||||
args.append(kwargs.get("completely_within", False))
|
||||
if "extend" in kwargs:
|
||||
args.append(kwargs.get("extend", -1.e-5))
|
||||
args.append(kwargs.get("extend", -1.0e-5))
|
||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select_box(*args)]
|
||||
|
||||
|
||||
@@ -193,14 +191,11 @@ def create_shape(settings, inst, repr=None):
|
||||
"""
|
||||
return wrap_shape_creation(
|
||||
settings,
|
||||
ifcopenshell_wrapper.create_shape(
|
||||
settings,
|
||||
inst.wrapped_data,
|
||||
repr.wrapped_data if repr is not None else None
|
||||
))
|
||||
ifcopenshell_wrapper.create_shape(settings, inst.wrapped_data, repr.wrapped_data if repr is not None else None),
|
||||
)
|
||||
|
||||
|
||||
def iterate(settings, file_or_filename, num_threads = 1, include = None, exclude = None):
|
||||
def iterate(settings, file_or_filename, num_threads=1, include=None, exclude=None):
|
||||
it = iterator(settings, file_or_filename, num_threads, include, exclude)
|
||||
if it.initialize():
|
||||
while True:
|
||||
@@ -214,13 +209,17 @@ def make_shape_function(fn):
|
||||
return None if e is None else entity_instance(e)
|
||||
|
||||
if has_occ:
|
||||
|
||||
def _(schema, string_or_shape, *args):
|
||||
if isinstance(string_or_shape, TopoDS.TopoDS_Shape):
|
||||
string_or_shape = utils.serialize_shape(string_or_shape)
|
||||
return entity_instance_or_none(fn(schema, string_or_shape, *args))
|
||||
|
||||
else:
|
||||
|
||||
def _(schema, string, *args):
|
||||
return entity_instance_or_none(fn(schema, string, *args))
|
||||
|
||||
return _
|
||||
|
||||
|
||||
|
||||
@@ -26,35 +26,38 @@ import operator
|
||||
import warnings
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
try: # python 3.3+
|
||||
from collections.abc import Iterable
|
||||
except ModuleNotFoundError: # python 2
|
||||
except ModuleNotFoundError: # python 2
|
||||
from collections import Iterable
|
||||
|
||||
try:
|
||||
from OCC.Core import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
|
||||
|
||||
USE_OCCT_HANDLE = False
|
||||
except ImportError:
|
||||
from OCC import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
|
||||
|
||||
USE_OCCT_HANDLE = True
|
||||
|
||||
shape_tuple = namedtuple('shape_tuple', ('data', 'geometry', 'styles'))
|
||||
shape_tuple = namedtuple("shape_tuple", ("data", "geometry", "styles"))
|
||||
|
||||
handle, main_loop, add_menu, add_function_to_menu = None, None, None, None
|
||||
|
||||
DEFAULT_STYLES = {
|
||||
"DEFAULT": (.7, .7, .7),
|
||||
"IfcWall": (.8, .8, .8),
|
||||
"IfcSite": (.75, .8, .65),
|
||||
"IfcSlab": (.4, .4, .4),
|
||||
"IfcWallStandardCase": (.9, .9, .9),
|
||||
"IfcWall": (.9, .9, .9),
|
||||
"IfcWindow": (.75, .8, .75, .3),
|
||||
"IfcDoor": (.55, .3, .15),
|
||||
"IfcBeam": (.75, .7, .7),
|
||||
"IfcRailing": (.65, .6, .6),
|
||||
"IfcMember": (.65, .6, .6),
|
||||
"IfcPlate": (.8, .8, .8)
|
||||
"DEFAULT": (0.7, 0.7, 0.7),
|
||||
"IfcWall": (0.8, 0.8, 0.8),
|
||||
"IfcSite": (0.75, 0.8, 0.65),
|
||||
"IfcSlab": (0.4, 0.4, 0.4),
|
||||
"IfcWallStandardCase": (0.9, 0.9, 0.9),
|
||||
"IfcWall": (0.9, 0.9, 0.9),
|
||||
"IfcWindow": (0.75, 0.8, 0.75, 0.3),
|
||||
"IfcDoor": (0.55, 0.3, 0.15),
|
||||
"IfcBeam": (0.75, 0.7, 0.7),
|
||||
"IfcRailing": (0.65, 0.6, 0.6),
|
||||
"IfcMember": (0.65, 0.6, 0.6),
|
||||
"IfcPlate": (0.8, 0.8, 0.8),
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +85,7 @@ def initialize_display():
|
||||
for l in lights:
|
||||
viewer.DelLight(l)
|
||||
|
||||
if hasattr(V3d, 'V3d_TypeOfOrientation_Yup_AxoRight'):
|
||||
if hasattr(V3d, "V3d_TypeOfOrientation_Yup_AxoRight"):
|
||||
dirs = [[V3d.V3d_TypeOfOrientation_Yup_AxoRight], [V3d.V3d_TypeOfOrientation_Zup_AxoRight]]
|
||||
else:
|
||||
dirs = [(3, 2, 1), (-1, -2, -3)]
|
||||
@@ -117,7 +120,7 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
if representation and not clr:
|
||||
if len(set(representation.styles)) == 1:
|
||||
clr = representation.styles[0]
|
||||
if min(clr) < 0. or max(clr) > 1.:
|
||||
if min(clr) < 0.0 or max(clr) > 1.0:
|
||||
clr = DEFAULT_STYLES.get(representation.data.type, DEFAULT_STYLES["DEFAULT"])
|
||||
|
||||
if clr:
|
||||
@@ -125,8 +128,9 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
ais.SetMaterial(material)
|
||||
|
||||
if isinstance(clr, str):
|
||||
qclr = getattr(Quantity, "Quantity_NOC_%s" % clr.upper(),
|
||||
getattr(Quantity, "Quantity_NOC_%s1" % clr.upper(), None))
|
||||
qclr = getattr(
|
||||
Quantity, "Quantity_NOC_%s" % clr.upper(), getattr(Quantity, "Quantity_NOC_%s1" % clr.upper(), None)
|
||||
)
|
||||
if qclr is None:
|
||||
raise Exception("No color named '%s'" % clr.upper())
|
||||
elif isinstance(clr, Iterable):
|
||||
@@ -140,8 +144,8 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
raise Exception("Object of type %r cannot be used as a color." % type(clr))
|
||||
|
||||
ais.SetColor(qclr)
|
||||
if isinstance(clr, tuple) and len(clr) == 4 and clr[3] < 1.:
|
||||
ais.SetTransparency(1. - clr[3])
|
||||
if isinstance(clr, tuple) and len(clr) == 4 and clr[3] < 1.0:
|
||||
ais.SetTransparency(1.0 - clr[3])
|
||||
|
||||
elif representation and hasattr(AIS, "AIS_MultipleConnectedShape"):
|
||||
default_style_applied = None
|
||||
@@ -155,13 +159,14 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
else:
|
||||
for shp, stl in zip(subshapes, representation.styles):
|
||||
subshape = AIS.AIS_Shape(shp)
|
||||
if min(stl) < 0. or max(stl) > 1.:
|
||||
default_style_applied = stl = DEFAULT_STYLES.get(representation.data.type,
|
||||
DEFAULT_STYLES["DEFAULT"])
|
||||
if min(stl) < 0.0 or max(stl) > 1.0:
|
||||
default_style_applied = stl = DEFAULT_STYLES.get(
|
||||
representation.data.type, DEFAULT_STYLES["DEFAULT"]
|
||||
)
|
||||
subshape.SetColor(Quantity.Quantity_Color(stl[0], stl[1], stl[2], Quantity.Quantity_TOC_RGB))
|
||||
subshape.SetMaterial(material)
|
||||
if len(stl) == 4 and stl[3] < 1.:
|
||||
subshape.SetTransparency(1. - stl[3])
|
||||
if len(stl) == 4 and stl[3] < 1.0:
|
||||
subshape.SetTransparency(1.0 - stl[3])
|
||||
ais.Connect(subshape.GetHandle())
|
||||
|
||||
# For some reason it is necessary to set transparency here again
|
||||
@@ -169,14 +174,14 @@ def display_shape(shape, clr=None, viewer_handle=None):
|
||||
applied_styles = representation.styles
|
||||
if default_style_applied:
|
||||
if len(default_style_applied) == 3:
|
||||
default_style_applied += (1.,)
|
||||
default_style_applied += (1.0,)
|
||||
applied_styles += (default_style_applied,)
|
||||
|
||||
if len(applied_styles):
|
||||
# The only way for this not to be true if is the entire shape is NULL
|
||||
min_transp = min(map(operator.itemgetter(3), applied_styles))
|
||||
if min_transp < 1.:
|
||||
ais.SetTransparency(1.)
|
||||
if min_transp < 1.0:
|
||||
ais.SetTransparency(1.0)
|
||||
|
||||
else:
|
||||
ais = AIS.AIS_Shape(shape)
|
||||
@@ -199,10 +204,10 @@ def set_shape_transparency(ais, t):
|
||||
|
||||
|
||||
def get_bounding_box_center(bbox):
|
||||
bbmin = [0.] * 3
|
||||
bbmax = [0.] * 3
|
||||
bbmin = [0.0] * 3
|
||||
bbmax = [0.0] * 3
|
||||
bbmin[0], bbmin[1], bbmin[2], bbmax[0], bbmax[1], bbmax[2] = bbox.Get()
|
||||
return gp.gp_Pnt(*map(lambda xy: (xy[0] + xy[1]) / 2., zip(bbmin, bbmax)))
|
||||
return gp.gp_Pnt(*map(lambda xy: (xy[0] + xy[1]) / 2.0, zip(bbmin, bbmax)))
|
||||
|
||||
|
||||
def serialize_shape(shape):
|
||||
@@ -226,7 +231,7 @@ def create_shape_from_serialization(brep_object):
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
styles = tuple(styles[i:i + 4] for i in range(0, len(styles), 4))
|
||||
styles = tuple(styles[i : i + 4] for i in range(0, len(styles), 4))
|
||||
|
||||
if not brep_data:
|
||||
return shape_tuple(brep_object, None, styles)
|
||||
|
||||
Reference in New Issue
Block a user