Enable per-item styles in the pythonOCC viewer

This commit is contained in:
Thomas Krijnen
2016-04-11 11:50:43 +02:00
parent 426b1279e3
commit 81ee60079e
4 changed files with 144 additions and 14 deletions
+17
View File
@@ -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());
+2
View File
@@ -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
+1
View File
@@ -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)
%} %}
}; };