
Thu, 11/21/2013 - 17:03
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
Thu, 11/21/2013 - 17:05
Sorry for wrong urls before
CAD Exchanger
http://imageshack.com/i/f7jhnlp
My Plugin in OSG Viewer
http://imageshack.com/i/j652dbp
Thu, 11/21/2013 - 17:20
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
Thu, 11/21/2013 - 17:26
hi,
I am calculating Normals in OpenSceneGraph Using OsgUtil::Smoother.
Thu, 11/21/2013 - 17:19
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
Thu, 11/21/2013 - 17:37
Hi,
If I process only free shapes then I am not getting any color information.
Thank You
-Abhishek
Thu, 11/21/2013 - 18:28
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
Thu, 11/21/2013 - 18:37
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
Thu, 11/21/2013 - 18:59
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
Thu, 11/21/2013 - 19:04
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
Thu, 11/21/2013 - 19:49
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
Mon, 11/25/2013 - 12:55
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
Mon, 11/25/2013 - 20:39
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
Thu, 11/28/2013 - 00:21
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
Thu, 11/28/2013 - 01:59
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
Thu, 11/28/2013 - 16:35
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
Thu, 11/28/2013 - 17:00
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
Fri, 11/29/2013 - 01:23
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
Fri, 11/29/2013 - 02:05
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
Mon, 11/25/2013 - 13:34
Ok Actually, when used with getFreeShape it doesn't have any children.
Thank You
-Abhishek