AIS_InteractiveContext::SetColor(...) doesn't assign color

Hello folks,

as an introduction a small snippet:

Handle(AIS_InteractiveObject) io = theIC->Current();

if(theIC->HasColor(io))
cout Color(io)

theIC->SetColor(io, color, Standard_True );

if(theIC->HasColor(io))
{
cout cout Color(io) }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

The output looks like this:
New Color = 516
Assigned Color = 147

Old Color = 147
New Color = 352
Assigned Color = 147

Old Color = 147
New Color = 107
Assigned Color = 147
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

As one can see, the assigned color stays unchanged. Now here's the question: Why? I have no idea what's going wrong. I was also trying to set the color via the InteractiveObject's TPrsStd_AISPresentation, since I am using XCAF. Without any success.

I'm grateful for any idea/hint.

Thanks,

Dennis

arkoala's picture

I got that problem several weeks ago.
My problem was related with wires and coloring them. The problem in my case was that all the selected objects are painted in gray, and not in their original (assigned) color.

When I realized that detail, I can manage colors unselecting what I want (or selecting others).

Maybe your problem is other, with solids...

This is working for me: (Assign color before display the shape)

m_ais = occWnd->CreateShape(m_wCut);
occWnd->SetColor(m_ais, Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
occWnd->ShowShape(m_ais);

Roman Lygin's picture

Hi Dennis,

If you use XCAF then you should use its framework to set up colors. If you look at XCAFPrs_AISObject (which is a subclass of AIS_Shape) then you'll see that it uses data stored in the OCAF tree to display.
You might want to (re-)read XDE to remind usage. Here is a possible code:

TopoDS_Shape aFreeShape = ...; //free shape in your XCAF document
Handle(XCAFDoc_ColorTool) aColorTool = ...;
TDF_Label aColorLabel = aColorTool->AddColor (...);//returns a label where your color is placed
aColorTool->SetColor (aFreeShape, aColorLabel, aColorType);

Once you have updated the doc structure, you must update visual representation and AIS context. This depends how you update presentations (e.g. using TDataStd_AISPresentation and XCAFPrs_Driver).

Hope this helps.
Roman

---
opencascade.blogspot.com - blog on Open CASCADE

Dennis G.'s picture

Thank you Roman,

I really appreciate your commitment to the OCC community. I followed the instructions in your blog to set up my XCAF visualization section. Change of colors basically works now. When I tried to alter the color via the TPrs functions in the first place I only updated the TPrsStd_AISPresentation and forgot to TPrsStd_AISViewer::Update(). Thanks again.

The only problem that's left is that I can't highlight/select any visualized objects in the view after introducing the objects to the Context via TPrsStd_AISPresentation::Display(). Although I set the SelectionMode of the AISPresentation to '0' (= selection of the shape itself).
When I introduce AIS_InteractiveObjects to the Context manually the objects are selectable.

How can I make the displayed objects selectable without opening a local context?

Best regards,

Dennis

Roman Lygin's picture

Hi Dennis,

Strange, this should be quite straightforward. The following code works just fine:

//Shapes
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (myOcafDoc->Main());
TDF_LabelSequence aLabSeq;
aShapeTool->GetFreeShapes (aLabSeq); //only free shapes are displayed
//set presentations and show
for (i = 1; i <= aLabSeq.Length(); i++) {
Handle(TPrsStd_AISPresentation) aPrs;
if (!aLabSeq.Value(i).FindAttribute(TPrsStd_AISPresentation::GetID(), aPrs) ) {
aPrs = TPrsStd_AISPresentation::Set (aLabSeq.Value(i), XCAFPrs_AISDriver::GetID());
aPrs->SetMaterial(Graphic3d_NOM_PLASTIC);
}
aPrs->SetMode (myDispMode);
aPrs->Display (Standard_False);

myAISContext->OpenLocalContext();
myAISContext->ActivateStandardMode (TopAbs_FACE);
}
myAISContext->UpdateCurrentViewer();

Commenting two last lines in braces out will keep highlighting and selection in neutral point (i.e. entire shapes). Otherwise, face selection mode is activated.

Hope this helps.
Roman

---
opencascade.blogspot.com - blog on Open CASCADE

Dennis G.'s picture

Hello Roman,

thank you again. Unfortunately your last post didn't help. I checked everything again and again and again, but it won't work.
There aren't too many possible sources for the problem, though. The TDocStd_Document is valid. I created it after your blog, and everything works fine with that. The initialization of the V3d_Viewer, the AIS_InteractiveContext and the V3d_View are known to work in the simple non-OCAF way, as it is implemented in OCAF's qt-sample. So, I think this part also is correct.
I import data using the STEPCAFControl_Reader to the TDocStd_Document and call my UpdateView() function, which basically is what you posted in your last post above.

Here is step by step what I'm doing.
=====================================

// 1st: Create V3d_Viewer as in Qt-Sample from OCC
myViewer = new V3d_Viewer(defaultdevice,theName,theDomain,theViewSize,theViewProj,Standard_True,Standard_True);
// create collector the same way

// 2nd: Create AIS_InteractiveContext as in Qt-Sample, but with explicit collector
myContext = new AIS_InteractiveContext(myViewer, myCollector);

// 3rd: Create V3d_View as in Qt-Sample
myView = myContext->CurrentViewer()->CreateView();
Handle(Xw_Window) theXWindow = new Xw_Window(Handle(Graphic3d_GraphicDevice)::DownCast(theContext->CurrentViewer()->Device()), (int)
hi,(int)lo,Xw_WQ_SAMEQUALITY,Quantity_NOC_BLACK);
myView->SetWindow(theXWindow);

// using the above with standard AIS works fine

// 4th: Initialize TDocument and load STEP-File using STEPCAFControl_Reader
//TDocStd_Document loaded and verified, Document created as XmlXCAF as described in your OCC-Blog

//5th: update the view
void MyProgram::UpdateView()
{
Handle(AIS_InteractiveContext) theContext = myDoc->GetContext();
Handle(TDocStd_Document) theTDoc = myDoc->GetTDoc();

//mark: Init Visualization Drivers; without this part view doesn't show anything
Handle(XCAFPrs_Driver) aPrsDriver = new XCAFPrs_Driver();
TPrsStd_DriverTable::Get();
TPrsStd_DriverTable::Get()->InitStandardDrivers();
TPrsStd_DriverTable::Get()->AddDriver(XCAFPrs_Driver::GetID(), aPrsDriver);

Handle(TPrsStd_AISViewer) aTViewer;
TDF_Label rootLabel = theTDoc->GetData()->Root();

if (!TPrsStd_AISViewer::Find (rootLabel, theContext)) // test if viewer is added to TDoc
{
Handle(V3d_Viewer) aViewer = myViewer->GetViewer();
aTViewer = TPrsStd_AISViewer::New(rootLabel, aViewer);
}

//Update Visualization
Handle(XCAFDoc_ShapeTool) sTool = XCAFDoc_DocumentTool::ShapeTool(theTDoc->Main());
TDF_LabelSequence freeShapes;
sTool->GetFreeShapes(freeShapes);

for(Standard_Integer i=1; i<=freeShapes.Length(); i++)
{
TDF_Label curL = freeShapes.Value(i);
Handle(TPrsStd_AISPresentation) aPrs;
if (!curL.FindAttribute(TPrsStd_AISPresentation::GetID(), aPrs) )
{
aPrs = TPrsStd_AISPresentation::Set (curL, XCAFPrs_Driver::GetID());
aPrs->SetMaterial(Graphic3d_NOM_PLASTIC);
}
aPrs->SetMode (1);
aPrs->Display (Standard_False);
}
theContext->UpdateCurrentViewer();

//
AIS_ListOfInteractive ioList;
theContext->DisplayedObjects(ioList);
cout << "number of displayed objects : " << ioList.Extent() << endl;
}

Now, the problem is, that the above code does not create any AIS_InteractiveObjects in the V3d_Viewer. AIS_InteractiveContext::DisplayedObjects(AIS_ListOfInteractive& ...); returns an empty list of interactive objects.
Also, without the marked section (beginning with //mark) the view stays empty.
I could add the Interactive Objects manually to the Context, but that is followed by other problems and is not what I intent to do.

As I understand the marked section shouldn't be neccessary in the first place, since I never saw it anywhere except in one post in this forum. But if I leave it out nothing is displayed. Well, not that it is any good to see objects I can't interact with.

If you don't find any fundamental mistakes, I will give up on this for now and load the interactive objects manually to the context.

Best regards,

Dennis

Roman Lygin's picture

Hi Dennis,

First off, your code in UpdateView() is a bit too mixed - you try to make initialization and regular update in one place. So, for easier debugging make sure you do the following:

1. somewhere in your global initialization (e.g. in singleton application class) make sure you create an instance of XCAFApp_Application:
/*! Initializes the XDE application XCAFApp_Application.
*/
bool ExchangerGui_Application::Init()
{
bool aRes = QODesk_Application::Init();
if (aRes) {
myOcafApp = XCAFApp_Application::GetApplication();
}
return aRes;
}

2. When creating your custom document object make sure you properly initialize OCAF (XDE) document:

bool ExchangerGui_Document::OnNewDocument()
{
...
anApp->OcafApplication()->NewDocument ("XmlXCAF", myOcafDoc);
}

/*! Performs common initialization after creating a document from scratch
or from restoring it from a file.
Creates a structure of OCAF document required to support connection with AIS:
\li attaches TPrsStd_AISViewer attribute to the root label;
*/
void ExchangerGui_Document::InitDocument()
{
//attach TPrsStd_AISViewer using already created AIS_InteractiveContext
TPrsStd_AISViewer::New (myOcafDoc->Main(), myAISContext);
}

After this you won't need all the stuff in UpdateView() about XCAFPrs_Driver and TPrsStd_AISViewer().

3. Adding presentations for new objects (your simplified UpdateView() should be fine). Here is my code

/*! Updates (if \a theReplace is FALSE) or rebuilds (if TRUE) presentations
of free shapes stored in the document.
If \a theUpdate is TRUE then the view is updated.
*/
void ExchangerGui_Document::DisplayPrs (bool theUpdate) const
{
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (myOcafDoc->Main());
TDF_LabelSequence aShapeLabSeq, aMeshLabSeq;
aShapeTool->GetFreeShapes (aShapeLabSeq); //only free shapes are displayed
DisplayShapes (aShapeLabSeq);

if (theUpdate)
myAISContext->UpdateCurrentViewer();
}

void ExchangerGui_Document::DisplayShapes (const TDF_LabelSequence& theSeq) const
{
int n = theSeq.Length();
for (int i = 1; i <= n; i++) {
const TDF_Label& aLab = theSeq.Value(i);
Handle(TPrsStd_AISPresentation) aPrs;
if (!aLab.FindAttribute (TPrsStd_AISPresentation::GetID(), aPrs)) {
aPrs = TPrsStd_AISPresentation::Set (aLab,
XCAFPrs_ADriver::GetID());
aPrs->SetMaterial(Graphic3d_NOM_PLASTIC); //@TODO@: should be some initialization
}
aPrs->SetMode (myDispMode);
aPrs->Display (Standard_False);
}
}

In my app, I don't directly access AIS_Context::DisplayedObjects() - always use a data model instead (XCAFDoc_ShapeTool::GetFreeShapes()).

In my case your test with AIS_Context::DisplayedObjects() returns non zero.
So check if the problem still persists after you make proper initialization of the application and aisviewer.

Good luck.
Roman

---
opencascade.blogspot.com - blog on Open CASCADE