Wed, 10/19/2016 - 14:12
Forums:
Hello,
I need to implement the following approach in my application - load IGES file, get tessellation and some other data for every element:
- vertices and faces,
- object name;
- object color.
Could you please give me some hints how to get it.
I load IGES files in this way:
IGESControl_Controller::Init();
IGESControl_Reader aReader;
if (aReader.ReadFile((const Standard_CString)FileName) == IFSelect_RetDone)
{
aReader.SetReadVisible(Standard_True);
aReader.PrintCheckLoad(Standard_True,IFSelect_GeneralInfo);
aReader.ClearShapes();
aReader.TransferRoots();
}
Wed, 10/19/2016 - 14:24
Hello Vladimir,
With the code you posted you can read only the geometry. To have names and colors, you can use XDE (https://dev.opencascade.org/doc/overview/html/occt_user_guides__xde.html). Check out IGESCAFControl_Reader utility which reads IGES files with all metadata to an XDE document.
To produce a tessellation, you can use BRepMesh_IncrementalMesh. Notice that tessellation will be built after IGES loading, so it is not somewhat stored in the file initially. Then, to get sub-shapes like vertices or faces, you may use TopExp package.
Regards,
Qr.
Thu, 10/20/2016 - 11:19
Here is some code snippet you might want to look at:
bool ImporterExporter::getIGESShapeColor(
const Handle(IGESData_IGESEntity)& shapeEntity,
const Handle(Interface_InterfaceModel)& model, Quantity_NameOfColor& color)
{
int colorRank = shapeEntity->RankColor();
if (colorRank >= 0)
{
IGESSelect_SignColor entityRedColorSigner(4);
std::string red = entityRedColorSigner.Value(shapeEntity, model);
if (red.empty())
{
return false;
}
IGESSelect_SignColor entityGreenColorSigner(5);
std::string green = entityGreenColorSigner.Value(shapeEntity, model);
if (green.empty())
{
return false;
}
IGESSelect_SignColor entityBlueColorSigner(6);
std::string blue = entityBlueColorSigner.Value(shapeEntity, model);
if (blue.empty())
{
return false;
}
double redValue = std::stod(red) / 100.0;
double greenValue = std::stod(green) / 100.0;
double blueValue = std::stod(blue) / 100.0;
Quantity_Color shapeColor(redValue, greenValue, blueValue,
Quantity_TOC_RGB);
color = shapeColor.Name();
return true;
}
else
{
const Handle(IGESData_ColorEntity)& colorEntity = shapeEntity->Color();
if (colorEntity.IsNull())
{
return false;
}
else
{
Handle(IGESGraph_Color) colorGraph = Handle(IGESGraph_Color)::DownCast(
colorEntity);
if (colorGraph.IsNull())
{
return false;
}
else
{
double red;
double green;
double blue;
colorGraph->RGBIntensity(red, green, blue);
red = red / 100.00;
green = green / 100.00;
blue = blue / 100.00;
Quantity_Color shapeQuantityColor(red, green, blue, Quantity_TOC_RGB);
color = shapeQuantityColor.Name();
return true;
}
}
}
return false;
}
std::string ImporterExporter::getIGESShapeName(const IGESControl_Reader& reader,
const TopoDS_Shape& shape, Handle(IGESData_IGESEntity)& shapeEntity)
{
const Handle(XSControl_WorkSession)& workSession = reader.WS();
const Handle(XSControl_TransferReader)& transferReader =
workSession->TransferReader();
const Handle(Transfer_TransientProcess)& readerTransientProcess =
transferReader->TransientProcess();
shapeEntity = Handle(IGESData_IGESEntity)::DownCast(
transferReader->EntityFromShapeResult(shape, -1));
if (shapeEntity.IsNull())
{
return getDefaultShapeName(shape);
}
if (shapeEntity->HasName())
{
return shapeEntity->NameValue()->String().ToCString();
}
else
{
return getDefaultShapeName(shape);
}
}
Thu, 10/20/2016 - 17:59
Thank you all for the tips. I found examples of the use of the BRepMesh_IncrementalMesh:
https://www.opencascade.com/content/cannot-loadsave-stl-file
https://www.opencascade.com/content/import-step-export-mesh-wrong-placem...
However, an linking error(error LNK2019) occurs when i use the header file (BRepMesh_IncrementalMesh.hxx)
Project Settings and errors attached to the post.
Sat, 10/22/2016 - 14:16
It seems you're missing TKMesh.lib in your linker's input.
Tue, 10/25/2016 - 19:00
Thank you very much. It helped a lot. Now I understand how to get tessellation:
BRepMesh_IncrementalMesh(shape, 0.001);
for (TopExp_Explorer ex(shape, TopAbs_FACE); ex.More(); ex.Next())
{
TopoDS_Face F = TopoDS::Face(ex.Current());
TopLoc_Location L = TopLoc_Location();
Handle(Poly_Triangulation) facing = BRep_Tool::Triangulation(F, L);
int nbtris = facing->NbTriangles();
gPointsList.clear();
gVertexList.clear();
gIndexesList.clear();
const Poly_Array1OfTriangle & triangles = facing->Triangles();
const TColgp_Array1OfPnt & nodes = facing->Nodes();
for (int i = facing->NbTriangles(); i >= 1; i--)
{
Poly_Triangle triangle = triangles(i);
Standard_Integer node1, node2, node3;
triangle.Get(node1, node2, node3);
AddPoint(gPointsList, nodes(node1));
AddPoint(gPointsList, nodes(node2));
AddPoint(gPointsList, nodes(node3));
}
GenerateGeometryData(gPointsList, &gVertexList, &gIndexesList);
}
Could you please give me a hint how to scan all elements (sub-assemblies and parts) of an assembly and get their name and color?
I created an IGES file of the following structure:
-assembly1
---part1_asm1
---part2_asm1
---assembly2
------part1_asm2
I tried to get data in the following way:
IGESCAFControl_Reader aReader;
aReader.SetColorMode(true);
aReader.SetNameMode(true);
aReader.SetLayerMode(true);
if (aReader.ReadFile("C:\\TEST\\Sborka2.igs") == IFSelect_RetDone)
{
Handle(TDocStd_Document) aDoc = new TDocStd_Document("IgesReader");
aReader.SetReadVisible(Standard_True);
aReader.PrintCheckLoad(Standard_True, IFSelect_GeneralInfo);
if (aReader.Transfer(aDoc))
{
aReader.PrintCheckTransfer(Standard_True, IFSelect_GeneralInfo);
Handle(XCAFDoc_ShapeTool) myAssembly = XCAFDoc_DocumentTool::ShapeTool(aDoc->Main());
Handle(XCAFDoc_ColorTool) myColors = XCAFDoc_DocumentTool::ColorTool(aDoc->Main());
TDF_LabelSequence frshapes;
myAssembly->GetShapes(frshapes);
for (Standard_Integer i = 1; i <= frshapes.Length(); i++)
{
const TDF_Label& label = frshapes.Value(i);
Handle(TDataStd_Name) name;
TCollection_AsciiString ascii_name;
if (label.FindAttribute(TDataStd_Name::GetID(), name))
{
TCollection_ExtendedString extstr = name->Get();
ascii_name = name->Get();
fout1 << "Name: "<<ascii_name.ToCString()<<"\n";
}
XCAFDoc_ColorType ctype = XCAFDoc_ColorGen;
Quantity_Color col;
//This metod not found
if (myColors->GetColor(label, ctype, col))
{
}
}
}
}
However I got name of parts only:
=>[0:1:1:2]
part1_asm1
=>[0:1:1:4]
part2_amsm1
=>[0:1:1:6]
part1_asm2)
How can I get names of two assemblies (assembly1 и assembly2)?
Tue, 10/25/2016 - 21:15
First, I would recommend you to start using Draw for visualization of XDE structure. In Draw you can do the following:
> ReadIges [filename] doc # read IGES with all metadata to OCAF document
> XShow doc # show assembly in 3D viewer
> DFBrowse doc # show OCAF structure
You have to understand the XDE structure in order to learn how to iterate an assembly. Here is a sample code how you can do that. To understand better what is "free shape", "reference", "component", etc., there is no any better way than checking out the OpenCascade's sources.
// This function iterates XDE starting from the root items (empty "rootEntry").
void IterateBranch(const TCollection_AsciiString& rootEntry,
const TCollection_AsciiString& parentItem)
{
Handle(TDocStd_Document) Doc = ...;
Handle(XCAFDoc_ShapeTool) ShapeTool = ...;
//
TDF_LabelSequence Labels;
if ( rootEntry.IsEmpty() )
{
// Get list of roots
ShapeTool->GetFreeShapes(Labels);
}
else
{
// Access label by its ID
TDF_Label RootLabel;
TDF_Tool::Label(Doc->Main().Data(), rootEntry, RootLabel);
// Access all components of an assembly
if ( ShapeTool->IsAssembly(RootLabel) )
ShapeTool->GetComponents(RootLabel, Labels);
}
// Iterate over the root entities
for ( int lit = 1; lit <= Labels.Length(); ++lit )
{
TDF_Label L = Labels.Value(lit);
//
TCollection_AsciiString RefName, EntryId, RefEntryId, Name;
Handle(TDataStd_Name) NodeName;
TDF_Tool::Entry(L, EntryId);
if ( ShapeTool->IsReference(L) ) // It is a reference to a part with location
{
// NAME OF THE REFERENCE
if ( L.FindAttribute(TDataStd_Name::GetID(), NodeName) )
RefName = TCollection_AsciiString( NodeName->Get() );
TDF_Label RefLabel;
if ( ShapeTool->GetReferredShape(L, RefLabel) ) // Get the real underlying part
{
L = RefLabel;
TDF_Tool::Entry(RefLabel, RefEntryId);
}
}
// NAME OF THE PART
if ( L.FindAttribute(TDataStd_Name::GetID(), NodeName) )
{
Name = TCollection_AsciiString( NodeName->Get() );
// Trim spaces
RefName.RightAdjust();
RefName.LeftAdjust();
if ( !RefName.IsEmpty() &&
RefName.Search("=>[0:") != 1 &&
!IsEqual(RefName, Name) )
{
Name += TCollection_AsciiString (" [") + RefName + "]";
}
}
if ( RefEntryId.IsEmpty() )
RefEntryId = EntryId;
// Build path to entry in the assembly tree
if ( !parentItem.IsEmpty() )
{
EntryId.Prepend("/");
EntryId.Prepend(parentItem);
}
// Continue iteration recursively
IterateBranch(RefEntryId, EntryId);
}
}
Fri, 10/28/2016 - 20:07
Thank you very much for your help! I read and analyze samples with using XDE structure. Your code provides me the following information without names of assemblies:
=>[0:1:1:2]
part1_asm1
=>[0:1:1:4]
part2_amsm1
=>[0:1:1:6]
part1_asm2
Condition [ if (ShapeTool->IsAssembly(RootLabel)) ] is never true.
And I never some to the following sections (if this code is commented then part names are available):
if (!RefName.IsEmpty() && RefName.Search("=>[0:") != 1 && !IsEqual(RefName, Name))
Maybe I use wrong parameters in your code? Could you please check it?
Handle(TDocStd_Document) gDoc;
void IterateBranch(const TCollection_AsciiString& rootEntry, const TCollection_AsciiString& parentItem)
{
Handle(TDocStd_Document) Doc = gDoc;
Handle(XCAFDoc_ShapeTool) ShapeTool = XCAFDoc_DocumentTool::ShapeTool(Doc->Main());
//////
}
int _tmain(int argc, _TCHAR* argv[])
{
IGESCAFControl_Reader aReader;
//aReader.SetColorMode(true);
aReader.SetNameMode(true);
//aReader.SetLayerMode(true);
aReader.ReadFile("C:\\TEST\\sborka.igs");
gDoc = new TDocStd_Document("IgesReader");
//aReader.SetReadVisible(Standard_True);
aReader.PrintCheckLoad(Standard_True, IFSelect_GeneralInfo);
aReader.Transfer(gDoc);
TCollection_AsciiString par1, par2;
IterateBranch(par1, par2);
return 0;
}
Sat, 10/29/2016 - 22:26
Vladimir, could you share your IGES file? It will be easier to profile on the reference data.