Getting two shapes When there are more then One top level shape

Hi,

I am creating a OpenSceneGraph plugin to load IGES files using OpenCascade. I am using OpenCascade to read and triangulate IGES files. My problem is that if a model contains more than one top level images I am getting some shapes twice.

Following is a screenshot of CAD exchanger for this model
[URL=http://imageshack.com/i/f7jhnlp][IMG]http://imageshack.com/a/img547/7215...

and here is how i am getting image looks like in Osg Viewer
[URL=http://imageshack.com/i/j652dbp][IMG]http://imageshack.com/a/img690/600/...

Here is how i am reading this IGES file using XDE

Handle(TDocStd_Document) doc;
XCAFApp_Application::GetApplication()->NewDocument("MDTV-XCAF", doc);

IGESCAFControl_Reader reader;
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.SetLayerMode(true);

//IGESControl_Reader Reader;
reader.ReadFile( (Standard_CString)filePath.c_str() );
// transfer data from reader to doc
if(!reader.Transfer(doc))
{
cout return NULL;
}

// To get a node considered as an Assembly from an XDE structure, you can use the Label of the node.
Handle (XCAFDoc_ShapeTool) assembly;
assembly = XCAFDoc_DocumentTool::ShapeTool(doc->Main());

// To query, edit, or initialize a Document to handle Colors of XCAF
Handle(XCAFDoc_ColorTool) colors;
colors = XCAFDoc_DocumentTool::ColorTool(doc->Main());

this is where i read colors from document

/// Try to Get shape color from top level shape
Quantity_Color color;
if (!colors->GetColor(frshapes.Value(i), color))
{
/// If no color found in top level shape then iterate children
/// Sometimes colors are not attached to top level shapes
/// So we will iterate children of this shape to find a color
if (frshapes.Value(i).HasChild())
{
TDF_ChildIterator it;
for(it.Initialize(frshapes.Value(i)); it.More(); it.Next())
{
if(colors->GetColor(it.Value(), XCAFDoc_ColorGen, color) ||
colors->GetColor(it.Value(), XCAFDoc_ColorSurf, color) ||
colors->GetColor(it.Value(), XCAFDoc_ColorCurv, color) )
{
/// if we find a color save it for this shape and break
shapeColor = osg::Vec3(color.Red(), color.Green(), color.Blue());
break;
}
}
}
}

triangulation and shape healing is as follows

BRepTools::Clean(aShape);

ShapeFix_Shape fixer(aShape);
fixer.Perform();
BRepBuilderAPI_Sewing sew;
sew.Add(fixer.Shape());
sew.Perform();
aShape = sew.SewedShape();

/// call to incremental mesh on this shape
BRepMesh::Mesh(aShape, 1);

Finally iterating over faces and getting vertices and indices

for (TopExp_Explorer ex(aShape, TopAbs_FACE); ex.More(); ex.Next())
{
TopoDS_Face face = TopoDS::Face(ex.Current());
TopLoc_Location loc;
/// triangulate current face
Handle (Poly_Triangulation) triangulation = BRep_Tool::Triangulation(face, loc);

if (!triangulation.IsNull())
{
int noOfNodes = triangulation->NbNodes();
// Store vertices. Build vertex array here
for(unsigned int j = 1; j NbNodes(); j++)
{
// populate vertex list
// Ref: http://www.opencascade.org/org/forum/thread_16694/?forum=3
gp_Pnt pt = (triangulation->Nodes())(j).Transformed(loc.Transformation());
vertexList->push_back(osg::Vec3(pt.X(), pt.Y(), pt.Z()));

colorList->push_back(shapeColor);
}

/// now we need to get face indices for triangles
// get list of triangle first
const Poly_Array1OfTriangle& triangles = triangulation->Triangles();

//No of triangles in this triangulation
noOfTriangles = triangulation->NbTriangles();

Standard_Integer v1, v2, v3;
for (unsigned int j = 1; j {
/// If face direction is reversed then we add verticews in reverse order
/// order of vertices is important for normal calculation later
if (face.Orientation() == TopAbs_REVERSED)
{
triangles(j).Get(v1, v3, v2);
}
else
{
triangles(j).Get(v1, v2, v3);
}
triangleStrip->push_back(index + v1 - 1);
triangleStrip->push_back(index + v2 - 1);
triangleStrip->push_back(index + v3 - 1);
}
index = index + noOfNodes;
}
}
}
Previous posts by users on these forums have helped great so far. I just started with OpenCascade.
Please Help

Abhishek Bansal's picture

Sorry for wrong urls before

CAD Exchanger
http://imageshack.com/i/f7jhnlp
My Plugin in OSG Viewer
http://imageshack.com/i/j652dbp

Fotis Sioutis's picture

You must find a way to provide Normals to your visualization engine (openscenegraph) (this is the reason of the wrongly shaded shape). You can use StdPrs_ToolShadedShape in order to get the Normals of a triangulation.

Fotis

Abhishek Bansal's picture

hi,
I am calculating Normals in OpenSceneGraph Using OsgUtil::Smoother.

Pawel's picture

Hi Abhishek,

I haven't analyzed your code too deeply but my guess is you have to process FreeShapes and the XCAFDoc_Location attributes in order to get the correct location.

Hope this helps,
Pawel

Abhishek Bansal's picture

Hi,

If I process only free shapes then I am not getting any color information.

Thank You
-Abhishek

Pawel's picture

Hello,

in this line

if(colors->GetColor(it.Value(), XCAFDoc_ColorGen, color) ||
colors->GetColor(it.Value(), XCAFDoc_ColorSurf, color) ||
colors->GetColor(it.Value(), XCAFDoc_ColorCurv, color) )

differentiate between color types.

Pawel

Abhishek Bansal's picture

Hi Pawel,

None of these condition evaluates to true when I use assembly->GetFreeShapes(frshapes) instead of GetShapes. Which means there is no color information at all.

Thank You
-Abhishek

Pawel's picture

Hi Abhishek,

there might be no color on the free shape that's why it is necessary to process the whole free shape assembly structure in order to get the colors / locations of the components.

Cheers
Pawel

Abhishek Bansal's picture

Hi Pawel,

Thank You for your replies.
I just started with Open Cascade Technology. I am not getting what you want to point exactly. Can you please elaborate a little. What do you mean by processing whole free shape assembly structure ?

Thank You
Abhishek

Pawel's picture

Hello Abhishek,

I mean something like this (pseudo-code):

GetAllFreeShapes
for each FreeShape
{
GetColors(XCAFDoc_ColorCurv, XCAFDoc_ColorSurf, XCAFDoc_ColorGen);
Get XCAFDoc_Location
ProcessCildren (use TDF_ChildIterator) - recursive call
ProcessReferredShapeIfAny (use XCAFDoc_ShapeTool::GetReferredShape) - recursive call

if SimpleShape do visualize
}

Pawel

Abhishek Bansal's picture

Hi Again,

Do you mean to say that free shapes will always be equal to no of top level shapes ?
So I meant to say when I am using getFreeShapes I am not getting any color information in children also.
I am using same code only change is to replace getShapes() by getFreeShapes().

What is simple shape here ? Is it same as free shape ?

Thank You
-Abhishek

Pawel's picture

Dear Abhishek,

a free shape is the root node of the assembly structure. Each component of this structure can have properties (like color for example) assigned so it is necessary to traverse the complete structure of the element and not only its root node.

I suggest you took a look at the "Extended Data Exchange (XDE) User's Guide".

Pawel

Abhishek Bansal's picture

Hi Pawel,

Thank You very much for your consistent replies.

I went through XDE user guide as you suggested. And I changed implementation for recursing whole assembly structure. Now I am only visualizing a shape if it has no children. But even after doing this i am at same place where i started. i.e. i am getting same results as before.(getting shapes twice.)

As you suggested I tried recursing freeshapes but the problem is they never contain any children. shapeTree.HasChild() will always return false. This way i can get full geometry correct but again no color information.

When I recurse allShapes (returned by getShapes) I get color information but again i get multiple shapes like previously posted screenshots.

Here is how my current implementation is
void
ReaderWriterIGES::IGESReader::_traverse(const TDF_Label &shapeTree, Handle(XCAFDoc_ColorTool) colors)
{
if(shapeTree.HasChild())
{
std::cout << std::endl << "No of Children: " << shapeTree.NbChildren();
TDF_ChildIterator it;
for(it.Initialize(shapeTree); it.More(); it.Next())
{
_traverse(it.Value(), colors);
}
}
else
{
if(ANY COLOR IS FOUND)
{
// assign that color
}
else
{
std::cout<< std::endl << "No colors attached with SubShape";
}

TopoDS_Shape shape = _assembly->GetShape(shapeTree);
osg::ref_ptr geom = _createGeometryFromShape(shape, geomColor);
// now visualize geometry
}

Here is how i am getting freeShapes/allShapes

// To get a node considered as an Assembly from an XDE structure, you can use the Label of the node.
_assembly = XCAFDoc_DocumentTool::ShapeTool(doc->Main());

// To query, edit, or initialize a Document to handle Colors of XCAF
Handle(XCAFDoc_ColorTool) colors;
colors = XCAFDoc_DocumentTool::ColorTool(doc->Main());

// get sequence of free shape lables
TDF_LabelSequence freeShapes;
_assembly->GetFreeShapes(freeShapes);

// all shape sequence
// get sequence of all shape lables for color finding
TDF_LabelSequence allShapes;
_assembly->GetShapes(allShapes);

here is how i call _traverse on all nodes/root nodes

for (int i = 1; i <= allShapes.Length(); i++)
{
_traverse(allShapes.Value(i), colors);
}

Thank You
-Abhishek

Pawel's picture

Dear Abishek,

I think you're missing two things in your routine:
1. Traverse 'FreeShapes' instead of 'AllShapes'
2. Process referred labels (as mentioned above)

Then the result should be like on the attached picture.

Pawel

Abhishek Bansal's picture

Hi Pawel,

Thanks for your reply again !
My bad that till now I was thinking that by referred shape you mean children only. Now my recursion look like this

void
ReaderWriterIGES::IGESReader::_traverse(const TDF_Label &shapeTree, Handle(XCAFDoc_ColorTool) colors)
{
TDF_Label referredShape;
if(_assembly->GetReferredShape(shapeTree, referredShape))
{
TDF_ChildIterator it;
for(it.Initialize(referredShape); it.More(); it.Next())
{
_traverse(it.Value(), colors);
}
}
else
{
// Extract color and visualize
}

Now I am getting each shape once and with proper color. Now the problem is location of those shapes.
I think it has something to do with transformations. We need to transform vertices positions using some matrix. You mentioned that location has to be taken with XCAFDoc_Location but how do we get transformation matrix ?

I am attaching resultant image.

Thank You
-Abhishek

Pawel's picture

Handle(XCAFDoc_Location) attribute;
label.FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
trsf *= location.Transformation();
}

Please, note you need to consider the transformation from the above nodes to get it right (that's the reason for the multiplication in my code).

HTH
Pawel

Abhishek Bansal's picture

Hi Again Powel,

Sorry for being such a bother, But i did what you suggested and i am getting an exploded view of inner shape.

here is how i am doing now. I am multiplying transformation matrix at each node. here initially transformation contains transformation matrix of top level freeshape

void
ReaderWriterIGES::IGESReader::_traverse(const TDF_Label &shapeTree, gp_Trsf& transformation)
{
TDF_Label referredShape;
if(_assembly->GetReferredShape(shapeTree, referredShape))
{
TDF_ChildIterator it;
for(it.Initialize(referredShape); it.More(); it.Next())
{
Handle(XCAFDoc_Location) attribute;
shapeTree.FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation *= location.Transformation();
}

_traverse(it.Value(), transformation);
}
}
else
{
// GET COLOR

TopoDS_Shape shape = _assembly->GetShape(shapeTree);

Handle(XCAFDoc_Location) attribute;
shapeTree.FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation *= location.Transformation();
}

osg::ref_ptr geom = _createGeometryFromShape(shape, geomColor, transformation);

// DO VISUALIZATION

}
}

now in _createGeometryFromShape after doing triangulation of each face with
triangulation = BRep_Tool::Triangulation(face, loc1);

I am calculating a vertex position like this

for(unsigned int j = 1; j <= triangulation->NbNodes(); j++)
{
gp_Pnt pt = (triangulation->Nodes())(j).Transformed(transformation * loc1.Transformation()) ;// transformation);
vertexList->push_back(osg::Vec3(pt.X(), pt.Y(), pt.Z()));
}

Attached is the image of resultant output.

Thank You
-Abhishek

Abhishek Bansal's picture

Hi Pawel,

Thank You very much for all your help.

I had a bug in previously posted bug. In _travese() function in inner loop i was multiplying transformation with shapeTree transformation instead of multiplying it with referredShape transformation.

Now I am getting proper geometry. Without your help it would not have been possible !!

Thank You Very Much
-Abhishek

Abhishek Bansal's picture

Ok Actually, when used with getFreeShape it doesn't have any children.

Thank You
-Abhishek