Wed, 06/10/2009 - 17:45
Hi,
I'm just starting to dive into the wonders of OCAF ( I like what I see! ) & the salome GEOM module ( thanks Sioutis! ) in pythonOCC.
I've made an example where 2 parametric boxes are booleaned ( intersection ).
All is good, except that I would like the TPrsStd_AISPresentation to update themselves.
I've got a class Parameters that loop through the solvers when an parameter is changed.
This works just perfect, except that I have to register the following callback to get a visual update of the geometry.
My question is: what can I do such that the TPrsStd_AISPresentation objects ( prs1-3 ) and the TPrsStd_AISViewer ( viewer ) update when the solvers are triggered.
The objective is to just register a presentation of an object ( register_presentation ) and be done.
Many thanks in advance, the GEOM module really is pretty incredible!
Cheers,
-jelle
def update():
prs1.Update()
prs2.Update()
prs3.Update()
viewer.Update()
display.FitAll()
parameters.add_callback(update)
from __future__ import with_statement
from OCC.GEOMImpl import *
from OCC.SGEOM import *
from OCC.BRep import *
from OCC.gp import *
from OCC.TDF import *
from OCC.Utils.Topology import Topo
from OCC.Display.wxSamplesGui import start_display, display, add_function_to_menu, add_menu
from OCC.TPrsStd import *
from OCC.TNaming import *
import time
#===============================================================================
# SETUP
#===============================================================================
RESULT_LABEL = 2
# Create engine
docId = 100
myEngine = GEOMImpl_Gen()
engine = myEngine.GetEngine()
doc_h = myEngine.GetDocument(docId)
doc = doc_h.GetObject()
# get access to operations
prim_operations = myEngine.GetI3DPrimOperations(docId)
basic_operations = myEngine.GetIBasicOperations(docId)
bool_operations = myEngine.GetIBooleanOperations(docId)
display.EnableAntiAliasing()
#===============================================================================
# UTILITIES
#===============================================================================
class operation(object):
'''
raises an assertion error when IsDone() returns false, with the error specified in error_statement
'''
def __init__(self, operation):
self.operation = operation
def __enter__(self):
print 'start operation'
self.operation.StartOperation()
def __exit__(self, type, value, traceback):
print 'finish operation'
self.operation.FinishOperation()
if not self.operation.IsDone():
error_code = self.operation.GetErrorCode()
raise AssertionError('did not complete operation.\nused operation class: %s \nerror code: %s' % (self.operation.__class__, error_code) )
def to_string(_str):
from OCC.TCollection import TCollection_AsciiString as String
return String(_str)
def to_param(x):
return GEOM_Parameter(x)
class Parameters(object):
def __init__(self, engine, docId):
object.__setattr__(self, 'engine', engine)
object.__setattr__(self, 'docId', docId)
object.__setattr__(self, 'solvers', [])
object.__setattr__(self, 'callbacks', [])
def add_solver(self, solver):
assert isinstance( solver, GEOM_Solver), '%s is not a GEOM_Solver instance' % ( solver.__class__ )
self.solvers.append(solver)
def add_callback(self, call):
if callable(call):
self.callbacks.append(call)
else:
raise TypeError('%s is not a callable object' % ( call.__class__ ) )
def __setattr__(self, name, value):
# if an attribute is a numerical value ( integer or float )
# than its considered to be a parameter
# hence, the interpreter constant is updated
# and all solvers that have been added are updated
if isinstance(value, int) or isinstance(value, float):
print 'got numerical value', value
else:
raise TypeError('an paramter ( that is an attribute of the class Parameters ) is either a float or integer')
object.__setattr__(self, name, value)
docId = object.__getattribute__(self, 'docId')
self.engine.SetInterpreterConstant( docId,
to_string(name),
value)
for solv in self.solvers:
seq = TDF_LabelSequence()
print 'calling solver:', solv.__class__
solv.Update(docId, seq)
for call in self.callbacks:
print 'calling callback:', call
call()
def __getattribute__(self, name):
attr = object.__getattribute__(self, name)
if isinstance(attr, int) or isinstance(attr, float):
print 'parameter: %s value: %s' % (name, attr)
return to_param(to_string(name))
else:
return attr
def print_vertices(shape):
for i,v in enumerate(Topo(shape).vertices()):
print 'Vertex: %s Coord: %s' % ( i, BRep_Tool().Pnt(v).Coord())
def register_presentation(geomObject):
result_label = geomObject.GetLastFunction().GetObject().GetEntry().FindChild(RESULT_LABEL)
prs_main = TPrsStd_AISPresentation().Set(result_label, TNaming_NamedShape().GetID()).GetObject()
prs_main.Display(True)
return prs_main
#===============================================================================
# EXAMPLE
#===============================================================================
def example_parametric_box(blah):
parameters = Parameters(engine, docId)
parameters.add_solver(prim_operations.GetSolver())
parameters.add_solver(basic_operations.GetSolver())
parameters.add_solver(bool_operations.GetSolver())
# box 1
parameters.depth = 12
parameters.height = 70
parameters.width = 12
parameters.depth_a = 0
parameters.height_a = 0
parameters.width_a = 0
# box 2
parameters.lower = -100
parameters.upper = 100
parameters.fixed_height_lower = 0
parameters.fixed_height_higher = 10
with operation(basic_operations):
pnt1 = basic_operations.MakePointXYZ(parameters.width,
parameters.depth,
parameters.height)
pnt1.GetObject().SetName("point 1")
pnt2 = basic_operations.MakePointXYZ(parameters.width_a,
parameters.depth_a,
parameters.height_a)
pnt2.GetObject().SetName("point 2")
pnt3 = basic_operations.MakePointXYZ(parameters.lower,
parameters.lower,
parameters.fixed_height_lower)
pnt3.GetObject().SetName("point 3")
pnt4 = basic_operations.MakePointXYZ(parameters.upper,
parameters.upper,
parameters.fixed_height_higher)
pnt4.GetObject().SetName("point 4")
with operation(prim_operations):
Box = prim_operations.MakeBoxTwoPnt(pnt1, pnt2).GetObject()
BoxBool = prim_operations.MakeBoxTwoPnt(pnt3, pnt4).GetObject()
root = doc.Main().Root()
viewer = TPrsStd_AISViewer().New(root, display.Context_handle).GetObject()
with operation(bool_operations):
fff = bool_operations.MakeBoolean(Box.GetHandle(), BoxBool.GetHandle(), 1).GetObject()
dt = TPrsStd_DriverTable()
dt.Get()
dt.InitStandardDrivers()
prs1 = register_presentation(Box)
prs2 = register_presentation(BoxBool)
prs3 = register_presentation(fff)
prs1.SetTransparency(0.8)
prs2.SetTransparency(0.8)
prs1.SetColor(12)
prs2.SetColor(200)
prs3.SetColor(100)
def update():
prs1.Update()
prs2.Update()
prs3.Update()
viewer.Update()
display.FitAll()
parameters.add_callback(update)
for i in range(-66, -11):
parameters.depth_a = i
for i in range(-80, 0):
parameters.height_a = i
for i in range(-44, 0):
parameters.width_a = i
add_menu('GEOM')
add_function_to_menu('GEOM', example_parametric_box)
start_display()
Wed, 06/10/2009 - 18:10
Hello Jelle
There is no "automatic" way to update a TPrsStd_AISPresentation on change of the underlying geometry.You will propably need to access somehow the updated object's TPrsStd_AISPresentation and call its Update() method.In case you need to update all the objects (GEOM_Object) in the DataFramework then you can itterate the tree using TDF_ChildIterator and search for all AISPresentation classes and call their update method.
In order to automate the presentation updating you can always wrap the GEOM_Solver methods and update manually your objects.
Greets
Fotis Sioutis