You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AppFlow/FITK_Component/FITKGeoOCCIOHDF5/FITKOCCShapeIO.cpp

446 lines
12 KiB
C++

#include "FITKOCCShapeIO.h"
// Qt
#include <QFile>
#include <QDir>
#include <QApplication>
// OCC
#include <TopoDS_Shape.hxx>
#include <XCAFApp_Application.hxx>
#include <TDocStd_Document.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <TDF_Label.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_AttributeIterator.hxx>
#include <TDataStd_Name.hxx>
#include <BinXCAFDrivers_DocumentRetrievalDriver.hxx>
#include <BinXCAFDrivers_DocumentStorageDriver.hxx>
#include <TopExp.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
// Geometry
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoCommand.h"
#include "FITK_Component/FITKGeoCompOCC/FITKAbstractOCCModel.h"
#include "FITK_Component/FITKGeoCompOCC/FITKOCCVirtualTopoCreator.h"
namespace IO
{
// Base.
//@{
FITKOCCShapeIO::FITKOCCShapeIO()
{
// Nothing to do here.
}
FITKOCCShapeIO::~FITKOCCShapeIO()
{
// Clear data.
m_topoShape = nullptr;
m_fileName.clear();
m_errorText.clear();
}
void FITKOCCShapeIO::setFileName(QString fileName)
{
// Save the file name.
m_fileName = fileName;
}
QString FITKOCCShapeIO::getFileName()
{
return m_fileName;
}
void FITKOCCShapeIO::setShape(TopoDS_Shape* shape)
{
// Save the shape data pointer.
m_topoShape = shape;
}
TopoDS_Shape* FITKOCCShapeIO::getShape()
{
return m_topoShape;
}
QString FITKOCCShapeIO::errorInfo()
{
// Get the error text.
return m_errorText;
}
bool FITKOCCShapeIO::checkInputData()
{
if (m_fileName.isEmpty())
{
m_errorText = tr("The file name cannot be empty !");
return false;
}
if (!m_topoShape)
{
m_errorText = tr("The shape data cannot be empty !");
return false;
}
return true;
}
bool FITKOCCShapeIO::getShapeLabel(TDF_Label& root, TDF_Label &label)
{
// Get shape root label
TDF_ChildIterator iter(root);
// Get all sub labels.
for (; iter.More(); iter.Next())
{
const TDF_Label childLabel = iter.Value();
// Get all attributes.
TDF_AttributeIterator iterAttri(childLabel);
for (; iterAttri.More(); iterAttri.Next())
{
Handle(TDF_Attribute) childAttri = iterAttri.Value();
if (childAttri->DynamicType() == STANDARD_TYPE(TDataStd_Name))
{
Handle(TDataStd_Name) val = Handle(TDataStd_Name)::DownCast(childAttri);
QString aName = QString::fromUtf16(val->Get().ToExtString());
if (aName == "Shapes")
{
label = childLabel;
return true;
}
}
}
}
return false;
}
//@}
// Reader.
//@{
bool FITKOCCShapeReader::read()
{
m_errorText.clear();
// Check input.
bool flag = checkInputData();
if (!flag)
{
return false;
}
// Create OCC XCAF bin reader.
BinXCAFDrivers_DocumentRetrievalDriver binReader;
// Create XCAD document.
Handle(TDocStd_Document) doc;
XCAFApp_Application::GetApplication()->NewDocument("MDTV-XCAF", doc);
// Read bin file.
binReader.Read(m_fileName.toUtf8().data(), doc, XCAFApp_Application::GetApplication());
// Get the document shape tool.
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
// Get shape from document.
TDF_Label rootLabel = doc->Main();
// Get the shape label.
TDF_Label shapeLabel;
flag = getShapeLabel(rootLabel, shapeLabel);
if (!flag)
{
m_errorText = tr("Invalid document data, no shape lable in this document !");
return false;
}
// Check the shape labels count.
int nChild = shapeLabel.NbChildren();
if (nChild != 1)
{
m_errorText = tr("Invalid document data, wrong shape labels number !");
return false;
}
// Get first child label's shape.
TDF_ChildIterator iter(shapeLabel);
for (; iter.More(); iter.Next())
{
const TDF_Label childLabel = iter.Value();
TopoDS_Shape childShape = shapeTool->GetShape(childLabel);
if (childShape.IsNull())
{
m_errorText = tr("Invalid shape data in bin file !");
return false;
}
// Save the shape data.
*m_topoShape = childShape;
break;
}
return true;
}
bool FITKOCCShapeReader::update()
{
return read();
}
//@}
// Writer.
//@{
bool FITKOCCShapeWriter::write()
{
m_errorText.clear();
// Check input.
bool flag = checkInputData();
if (!flag)
{
return false;
}
// Check the shape.
if (m_topoShape->IsNull())
{
m_errorText = tr("The shape cannot be null !");
return false;
}
// Create OCC XCAF bin writer.
BinXCAFDrivers_DocumentStorageDriver binWriter;
// Create XCAD document.
Handle(TDocStd_Document) doc;
XCAFApp_Application::GetApplication()->NewDocument("MDTV-XCAF", doc);
// Get the document shape tool.
TDF_Label rootLabel = doc->Main();
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(rootLabel);
// Get the shape label.
TDF_Label shapeLabel;
flag = getShapeLabel(rootLabel, shapeLabel);
if (!flag)
{
m_errorText = tr("Invalid document data, no shape lable in this document !");
return false;
}
// Create a shape label.
TDF_Label newShapeLabel = shapeLabel.NewChild();
// Add shape to document.
shapeTool->SetShape(newShapeLabel, *m_topoShape);
// Write bin file.
binWriter.Write(doc, m_fileName.toUtf8().data());
return true;
}
bool FITKOCCShapeWriter::update()
{
return write();
}
//@}
// Tools.
//@{
bool FITKOCCIOTool::ShapeToData(TopoDS_Shape* shape, uint & len, char* & data, QString fileName)
{
// Check the input.
if (!shape)
{
return false;
}
// Prepare the temp file folder.
if (fileName.isEmpty())
{
QString folderPath = qApp->applicationDirPath() + "/temp";
QDir dir(folderPath);
if (!dir.exists())
{
dir.mkpath(folderPath);
}
fileName = qApp->applicationDirPath() + "/temp/bin.temp";
}
// Use OCC shape bin writer.
FITKOCCShapeWriter writer;
writer.setFileName(fileName);
writer.setShape(shape);
writer.update();
// Read the raw data file.
//@{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly))
{
return false;
}
// Read binary data.
len = file.size();
data = new char[len];
file.read(data, len);
file.close();
//@}
// Remove temp file.
QFile::remove(fileName);
return true;
}
bool FITKOCCIOTool::DataToShape(TopoDS_Shape* shape, uint len, char* data, QString fileName)
{
// Check the input.
if (!shape || !data || len == 0)
{
return false;
}
// Prepare the temp file folder.
if (fileName.isEmpty())
{
QString folderPath = qApp->applicationDirPath() + "/temp";
QDir dir(folderPath);
if (!dir.exists())
{
dir.mkpath(folderPath);
}
fileName = qApp->applicationDirPath() + "/temp/bin.temp";
}
// Write the raw data to file.
//@{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly))
{
return false;
}
// Write binary data.
file.write(data, len);
file.close();
//@}
// Use OCC shape bin reader.
FITKOCCShapeReader reader;
reader.setFileName(fileName);
reader.setShape(shape);
bool flag = reader.update();
// Remove temp file.
QFile::remove(fileName);
return flag;
}
bool FITKOCCIOTool::SetDataToCommand(Interface::FITKAbsGeoCommand* cmd, uint len, char* data, QString fileName)
{
// Check the input data first.
if (!cmd)
{
return false;
}
// Get the agent's shape data.
//@{
OCC::FITKAbstractOCCModel* occModel = dynamic_cast<OCC::FITKAbstractOCCModel*>(cmd->getShapeAgent());
if (!occModel)
{
return false;
}
TopoDS_Shape* shape = occModel->getShape();
//@}
// Get virtual topo managers.
Interface::FITKVirtualTopoManager* vMgrs = occModel->getVirtualTopoManager();
// Get all types of virtual topo.
const QList<Interface::FITKGeoEnum::VTopoShapeType> & types = vMgrs->getTopoTypes();
if (!shape || !vMgrs || types.isEmpty())
{
return false;
}
// Convert the data to the TopoDS_Shape.
bool flag = FITKOCCIOTool::DataToShape(shape, len, data, fileName);
if (!flag)
{
return false;
}
// Initialize index maps.
//@{
TopTools_IndexedMapOfShape iVert, iEdge, iWire, iFace, iShell, iSolid, iComPound;
TopExp::MapShapes(*shape, TopAbs_VERTEX, iVert);
TopExp::MapShapes(*shape, TopAbs_EDGE, iEdge);
TopExp::MapShapes(*shape, TopAbs_WIRE, iWire);
TopExp::MapShapes(*shape, TopAbs_FACE, iFace);
TopExp::MapShapes(*shape, TopAbs_SHELL, iShell);
TopExp::MapShapes(*shape, TopAbs_SOLID, iSolid);
TopExp::MapShapes(*shape, TopAbs_COMPOUND, iComPound);
// The enum map for virtual topo shape type and OCC shape index map.
QHash<Interface::FITKGeoEnum::VTopoShapeType, TopTools_IndexedMapOfShape> enumMap =
{
{Interface::FITKGeoEnum::VSPoint, iVert},
{Interface::FITKGeoEnum::VSEdge, iEdge},
{Interface::FITKGeoEnum::VSWire, iWire},
{Interface::FITKGeoEnum::VSFace, iFace},
{Interface::FITKGeoEnum::VSShell, iShell},
{Interface::FITKGeoEnum::VSSolid, iSolid},
{Interface::FITKGeoEnum::VSAssembly, iComPound}
};
//@}
// Set the shape to virtual topos.
for (const Interface::FITKGeoEnum::VTopoShapeType & type : types)
{
Interface::FITKShapeVirtualTopoManager* shapeTopoMgr = vMgrs->getShapeVirtualTopoManager(type);
if (!shapeTopoMgr)
{
return false;
}
// Get the index map.
TopTools_IndexedMapOfShape & map = enumMap[type];
int nTopo = shapeTopoMgr->getDataCount();
for (int i = 0; i < nTopo; i++)
{
Interface::FITKAbsVirtualTopo* vTopo = shapeTopoMgr->getDataByIndex(i);
if (!vTopo)
{
return false;
}
// Get the shape by index.
qDebug()<< 2 << type << nTopo << map.Size() << vTopo << "" << vTopo->getIndexLabel();
const TopoDS_Shape & subShape = map.FindKey(vTopo->getIndexLabel() + 1);
vTopo->setShape(new OCC::FITKOCCTopoShape(subShape));
}
}
return true;
}
//@}
} // namespace IO