mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +00:00
Enable per-item styles in the pythonOCC viewer
This commit is contained in:
@@ -38,6 +38,23 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
|
|||||||
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
|
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
|
||||||
const TopoDS_Shape& s = it->Shape();
|
const TopoDS_Shape& s = it->Shape();
|
||||||
gp_GTrsf trsf = it->Placement();
|
gp_GTrsf trsf = it->Placement();
|
||||||
|
|
||||||
|
if (it->hasStyle() && it->Style().Diffuse()) {
|
||||||
|
const IfcGeom::SurfaceStyle::ColorComponent& clr = *it->Style().Diffuse();
|
||||||
|
_surface_styles.push_back(clr.R());
|
||||||
|
_surface_styles.push_back(clr.G());
|
||||||
|
_surface_styles.push_back(clr.B());
|
||||||
|
} else {
|
||||||
|
_surface_styles.push_back(-1.);
|
||||||
|
_surface_styles.push_back(-1.);
|
||||||
|
_surface_styles.push_back(-1.);
|
||||||
|
}
|
||||||
|
if (it->hasStyle() && it->Style().Transparency()) {
|
||||||
|
_surface_styles.push_back(1. - *it->Style().Transparency());
|
||||||
|
} else {
|
||||||
|
_surface_styles.push_back(1.);
|
||||||
|
}
|
||||||
|
|
||||||
if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
|
if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
|
||||||
gp_Trsf scale;
|
gp_Trsf scale;
|
||||||
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
|
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
|
||||||
|
|||||||
@@ -76,9 +76,11 @@ namespace IfcGeom {
|
|||||||
private:
|
private:
|
||||||
int _id;
|
int _id;
|
||||||
std::string _brep_data;
|
std::string _brep_data;
|
||||||
|
std::vector<double> _surface_styles;
|
||||||
public:
|
public:
|
||||||
int id() const { return _id; }
|
int id() const { return _id; }
|
||||||
const std::string& brep_data() const { return _brep_data; }
|
const std::string& brep_data() const { return _brep_data; }
|
||||||
|
const std::vector<double>& surface_styles() const { return _surface_styles; }
|
||||||
Serialization(const BRep& brep);
|
Serialization(const BRep& brep);
|
||||||
virtual ~Serialization() {}
|
virtual ~Serialization() {}
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -18,18 +18,35 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import random
|
import random
|
||||||
from collections import namedtuple
|
import operator
|
||||||
|
from collections import namedtuple, Iterable
|
||||||
|
|
||||||
import OCC.gp
|
import OCC.gp
|
||||||
import OCC.V3d
|
import OCC.V3d
|
||||||
|
import OCC.AIS
|
||||||
import OCC.Quantity
|
import OCC.Quantity
|
||||||
import OCC.BRepTools
|
import OCC.BRepTools
|
||||||
import OCC.Display.SimpleGui
|
import OCC.Display.SimpleGui
|
||||||
|
|
||||||
tuple = namedtuple('shape', ('data', 'geometry'))
|
shape_tuple = namedtuple('shape_tuple', ('data', 'geometry', 'styles'))
|
||||||
|
|
||||||
handle, main_loop, add_menu, add_function_to_menu = None, None, None, None
|
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():
|
def initialize_display():
|
||||||
global handle, main_loop, add_menu, add_function_to_menu
|
global handle, main_loop, add_menu, add_function_to_menu
|
||||||
handle, main_loop, add_menu, add_function_to_menu = OCC.Display.SimpleGui.init_display()
|
handle, main_loop, add_menu, add_function_to_menu = OCC.Display.SimpleGui.init_display()
|
||||||
@@ -37,25 +54,113 @@ def initialize_display():
|
|||||||
def setup():
|
def setup():
|
||||||
viewer_handle = handle.GetViewer()
|
viewer_handle = handle.GetViewer()
|
||||||
viewer = viewer_handle.GetObject()
|
viewer = viewer_handle.GetObject()
|
||||||
while True:
|
|
||||||
|
def lights():
|
||||||
viewer.InitActiveLights()
|
viewer.InitActiveLights()
|
||||||
try: active_light = viewer.ActiveLight()
|
while True:
|
||||||
except: break
|
try: active_light = viewer.ActiveLight()
|
||||||
viewer.DelLight(active_light)
|
except: break
|
||||||
viewer.NextActiveLights()
|
yield active_light
|
||||||
for dir in [(1,2,-3), (-2,-1,1)]:
|
viewer.NextActiveLights()
|
||||||
|
|
||||||
|
lights = list(lights())
|
||||||
|
for l in lights:
|
||||||
|
viewer.DelLight(l)
|
||||||
|
|
||||||
|
for dir in [(3,2,1), (-1,-2,-3)]:
|
||||||
light = OCC.V3d.V3d_DirectionalLight(viewer_handle)
|
light = OCC.V3d.V3d_DirectionalLight(viewer_handle)
|
||||||
light.SetDirection(*dir)
|
light.SetDirection(*dir)
|
||||||
viewer.SetLightOn(light.GetHandle())
|
viewer.SetLightOn(light.GetHandle())
|
||||||
|
|
||||||
setup()
|
setup()
|
||||||
return handle
|
return handle
|
||||||
|
|
||||||
|
def yield_subshapes(shape):
|
||||||
|
it = OCC.TopoDS.TopoDS_Iterator(shape)
|
||||||
|
while it.More():
|
||||||
|
yield it.Value()
|
||||||
|
it.Next()
|
||||||
|
|
||||||
def display_shape(shape, clr=None):
|
def display_shape(shape, clr=None):
|
||||||
if not clr:
|
if isinstance(shape, shape_tuple):
|
||||||
|
shape, representation = shape.geometry, shape
|
||||||
|
else: representation is None
|
||||||
|
|
||||||
|
material = OCC.Graphic3d.Graphic3d_MaterialAspect(OCC.Graphic3d.Graphic3d_NOM_PLASTER)
|
||||||
|
material.SetDiffuse(1)
|
||||||
|
|
||||||
|
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 = OCC.AIS.AIS_Shape(shape)
|
||||||
|
ais.SetMaterial(material)
|
||||||
|
|
||||||
|
if isinstance(clr, str):
|
||||||
|
qclr = getattr(OCC.Quantity, "Quantity_NOC_%s" % clr.upper(), getattr(OCC.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 and len(clr) > 4:
|
||||||
|
raise Exception("Need 3 or 4 colour components. Got '%r'." % clr)
|
||||||
|
qclr = OCC.Quantity.Quantity_Color(clr[0], clr[1], clr[2], OCC.Quantity.Quantity_TOC_RGB)
|
||||||
|
elif isinstance(clr, OCC.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:
|
||||||
|
default_style_applied = None
|
||||||
|
|
||||||
|
ais = OCC.AIS.AIS_MultipleConnectedShape(shape)
|
||||||
|
|
||||||
|
subshapes = list(yield_subshapes(shape))
|
||||||
|
lens = len(representation.styles), len(subshapes)
|
||||||
|
if lens[0] != lens[1]:
|
||||||
|
import warnings
|
||||||
|
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 = OCC.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(OCC.Quantity.Quantity_Color(stl[0], stl[1], stl[2], OCC.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,)
|
||||||
|
|
||||||
|
min_transp = min(map(operator.itemgetter(3), applied_styles))
|
||||||
|
if min_transp < 1.:
|
||||||
|
ais.SetTransparency(1.)
|
||||||
|
|
||||||
|
else:
|
||||||
|
ais = OCC.AIS.AIS_Shape(shape)
|
||||||
|
ais.SetMaterial(material)
|
||||||
|
|
||||||
r = lambda: random.random() * 0.3 + 0.7
|
r = lambda: random.random() * 0.3 + 0.7
|
||||||
clr = OCC.Quantity.Quantity_Color(r(), r(), r(), OCC.Quantity.Quantity_TOC_RGB)
|
clr = OCC.Quantity.Quantity_Color(r(), r(), r(), OCC.Quantity.Quantity_TOC_RGB)
|
||||||
return handle.DisplayShape(shape, color=clr, update=True)
|
ais.SetColor(clr)
|
||||||
|
|
||||||
|
ais_handle = ais.GetHandle()
|
||||||
|
handle.Context.Display(ais_handle, False)
|
||||||
|
|
||||||
|
return ais_handle
|
||||||
|
|
||||||
|
|
||||||
def set_shape_transparency(ais, t):
|
def set_shape_transparency(ais, t):
|
||||||
@@ -69,17 +174,22 @@ def get_bounding_box_center(bbox):
|
|||||||
|
|
||||||
|
|
||||||
def create_shape_from_serialization(brep_object):
|
def create_shape_from_serialization(brep_object):
|
||||||
brep_data, occ_shape = None, None
|
brep_data, occ_shape, styles = None, None, ()
|
||||||
|
|
||||||
is_product_shape = True
|
is_product_shape = True
|
||||||
try:
|
try:
|
||||||
brep_data = brep_object.geometry.brep_data
|
brep_data = brep_object.geometry.brep_data
|
||||||
|
styles = brep_object.geometry.surface_styles
|
||||||
except:
|
except:
|
||||||
try:
|
try:
|
||||||
brep_data = brep_object.brep_data
|
brep_data = brep_object.brep_data
|
||||||
|
styles = brep_object.surface_styles
|
||||||
is_product_shape = False
|
is_product_shape = False
|
||||||
except: pass
|
except: pass
|
||||||
if not brep_data: return tuple(brep_object, None)
|
|
||||||
|
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:
|
try:
|
||||||
ss = OCC.BRepTools.BRepTools_ShapeSet()
|
ss = OCC.BRepTools.BRepTools_ShapeSet()
|
||||||
@@ -88,7 +198,7 @@ def create_shape_from_serialization(brep_object):
|
|||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
if is_product_shape:
|
if is_product_shape:
|
||||||
return tuple(brep_object, occ_shape)
|
return shape_tuple(brep_object, occ_shape, styles)
|
||||||
else:
|
else:
|
||||||
return occ_shape
|
return occ_shape
|
||||||
|
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
|||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
id = property(id)
|
id = property(id)
|
||||||
brep_data = property(brep_data)
|
brep_data = property(brep_data)
|
||||||
|
surface_styles = property(surface_styles)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user