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.
446 lines
12 KiB
C++
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
|