From 9bd57e39d205ad7a3acd0d37e3676dfa9a449314 Mon Sep 17 00:00:00 2001 From: mpv Date: Sat, 9 Jan 2021 18:01:53 +0300 Subject: [PATCH] 0031918: Application Framework - New binary format for fast reading part of OCAF document Initial implementation of new format for quick reading and writing parts of the documents. It consists in writing shapes and all their contents right in the TNaming_NamedShape attribute placement and skipping the shape section. For the current moment it is implemented as a new version 12 of the binary format. It will be decided later to have it like this and make this version of the format as default, or setting a special flag for such version reading/writing. Modifications: BinLDrivers and BinDrivers packages - modifications related to the quick part tree format flag usage, skipping shape section writing and adding labels sizes into the document to be able to pass labels during the reading quickly. BinObjMgt_Persistent amd BinObjMgt_Position - to add possibility to write directly into the stream some data just after the attribute. Before this record a data-size is recorded. BinMXCAFDoc package modifications to write BinMXCAFDoc_LocationDriver location in the same way as shapes write location data right after the attribute (empty) data in this new format. BinTools package: creation of ShapeReader and ShapeWriter classes with same root class ShapeSetBase with ShapeSet class. These classes allows to write/read shapes directly to the stream. If some object is already in the stream, write a reference - relative position of the duplicated object. PCDM_ReaderFilter - modified to be able to browse labels tree quickly, without usage of referencing by entry-strings. # Conflicts: # src/BinMNaming/BinMNaming_NamedShapeDriver.cxx # src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.cxx # src/BinTools/BinTools_ShapeSet.cxx # src/BinTools/BinTools_ShapeSet.hxx # src/BinTools/FILES --- .../BinDrivers_DocumentRetrievalDriver.cxx | 23 +- .../BinDrivers_DocumentRetrievalDriver.hxx | 4 +- .../BinDrivers_DocumentStorageDriver.cxx | 40 ++ .../BinDrivers_DocumentStorageDriver.hxx | 7 + .../BinLDrivers_DocumentRetrievalDriver.cxx | 97 ++- .../BinLDrivers_DocumentRetrievalDriver.hxx | 8 +- .../BinLDrivers_DocumentSection.cxx | 1 + .../BinLDrivers_DocumentStorageDriver.cxx | 109 +++- .../BinLDrivers_DocumentStorageDriver.hxx | 21 +- .../BinMNaming_NamedShapeDriver.cxx | 152 +++-- .../BinMNaming_NamedShapeDriver.hxx | 25 +- .../BinMNaming_NamedShapeDriver.lxx | 14 +- src/BinMXCAFDoc/BinMXCAFDoc.cxx | 4 +- .../BinMXCAFDoc_LocationDriver.cxx | 51 +- .../BinMXCAFDoc_LocationDriver.hxx | 12 +- .../BinMXCAFDoc_LocationDriver.lxx | 26 - src/BinMXCAFDoc/FILES | 1 - src/BinObjMgt/BinObjMgt_Persistent.cxx | 45 +- src/BinObjMgt/BinObjMgt_Persistent.hxx | 48 +- src/BinObjMgt/BinObjMgt_Persistent.lxx | 1 + src/BinObjMgt/BinObjMgt_Position.cxx | 47 ++ src/BinObjMgt/BinObjMgt_Position.hxx | 44 ++ src/BinObjMgt/FILES | 2 + src/BinTools/BinTools.cxx | 37 +- src/BinTools/BinTools.hxx | 8 + src/BinTools/BinTools_IStream.cxx | 257 ++++++++ src/BinTools/BinTools_IStream.hxx | 90 +++ src/BinTools/BinTools_LocationSet.cxx | 2 +- src/BinTools/BinTools_LocationSet.hxx | 5 +- src/BinTools/BinTools_ObjectType.hxx | 46 ++ src/BinTools/BinTools_Position.cxx | 86 +++ src/BinTools/BinTools_Position.hxx | 45 ++ src/BinTools/BinTools_ShapeReader.cxx | 591 ++++++++++++++++++ src/BinTools/BinTools_ShapeReader.hxx | 79 +++ src/BinTools/BinTools_ShapeSet.cxx | 284 ++------- src/BinTools/BinTools_ShapeSet.hxx | 53 +- src/BinTools/BinTools_ShapeSetBase.cxx | 63 ++ src/BinTools/BinTools_ShapeSetBase.hxx | 110 ++++ src/BinTools/BinTools_ShapeWriter.cxx | 513 +++++++++++++++ src/BinTools/BinTools_ShapeWriter.hxx | 80 +++ src/BinTools/FILES | 11 + src/PCDM/PCDM_ReaderFilter.cxx | 113 +++- src/PCDM/PCDM_ReaderFilter.hxx | 44 +- src/TDocStd/TDocStd_FormatVersion.hxx | 5 +- tests/bugs/caf/bug31918_1 | 89 +++ tests/bugs/caf/bug31918_2 | 123 ++++ 46 files changed, 3030 insertions(+), 486 deletions(-) delete mode 100644 src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.lxx create mode 100644 src/BinObjMgt/BinObjMgt_Position.cxx create mode 100644 src/BinObjMgt/BinObjMgt_Position.hxx create mode 100644 src/BinTools/BinTools_IStream.cxx create mode 100644 src/BinTools/BinTools_IStream.hxx create mode 100644 src/BinTools/BinTools_ObjectType.hxx create mode 100644 src/BinTools/BinTools_Position.cxx create mode 100644 src/BinTools/BinTools_Position.hxx create mode 100644 src/BinTools/BinTools_ShapeReader.cxx create mode 100644 src/BinTools/BinTools_ShapeReader.hxx create mode 100644 src/BinTools/BinTools_ShapeSetBase.cxx create mode 100644 src/BinTools/BinTools_ShapeSetBase.hxx create mode 100644 src/BinTools/BinTools_ShapeWriter.cxx create mode 100644 src/BinTools/BinTools_ShapeWriter.hxx create mode 100644 tests/bugs/caf/bug31918_1 create mode 100644 tests/bugs/caf/bug31918_2 diff --git a/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.cxx b/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.cxx index e7dde6a91b..2776f95d13 100644 --- a/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.cxx +++ b/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -59,7 +60,6 @@ void BinDrivers_DocumentRetrievalDriver::ReadShapeSection (BinLDrivers_DocumentSection& /*theSection*/, Standard_IStream& theIS, const Standard_Boolean /*isMess*/, - const Standard_Boolean thePostponeShapes, const Message_ProgressRange& theRange) { @@ -71,7 +71,7 @@ void BinDrivers_DocumentRetrievalDriver::ReadShapeSection OCC_CATCH_SIGNALS Handle(BinMNaming_NamedShapeDriver) aNamedShapeDriver = Handle(BinMNaming_NamedShapeDriver)::DownCast (aDriver); - aNamedShapeDriver->ReadShapeSection (theIS, thePostponeShapes, theRange); + aNamedShapeDriver->ReadShapeSection (theIS, theRange); } catch(Standard_Failure const& anException) { const TCollection_ExtendedString aMethStr @@ -108,4 +108,23 @@ void BinDrivers_DocumentRetrievalDriver::Clear() BinLDrivers_DocumentRetrievalDriver::Clear(); } +//======================================================================= +//function : EnableQuickPartReading +//purpose : +//======================================================================= +void BinDrivers_DocumentRetrievalDriver::EnableQuickPartReading( + const Handle(Message_Messenger)& theMessageDriver, Standard_Boolean theValue) +{ + if (myDrivers.IsNull()) + myDrivers = AttributeDrivers(theMessageDriver); + if (myDrivers.IsNull()) + return; + Handle(BinMDF_ADriver) aDriver; + myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver); + Handle(BinMNaming_NamedShapeDriver) aShapesDriver = Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver); + if (aShapesDriver.IsNull()) + throw Standard_NotImplemented("Internal Error - TNaming_NamedShape is not found!"); + + aShapesDriver->EnableQuickPart(theValue); +} diff --git a/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.hxx b/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.hxx index 836edd6f3d..b7c51d8f7b 100644 --- a/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.hxx +++ b/src/BinDrivers/BinDrivers_DocumentRetrievalDriver.hxx @@ -49,7 +49,6 @@ public: (BinLDrivers_DocumentSection& theSection, Standard_IStream& theIS, const Standard_Boolean isMess = Standard_False, - const Standard_Boolean thePostponeShapes = Standard_False, const Message_ProgressRange& theRange = Message_ProgressRange()) Standard_OVERRIDE; Standard_EXPORT virtual void CheckShapeSection @@ -58,6 +57,9 @@ public: //! Clears the NamedShape driver Standard_EXPORT virtual void Clear() Standard_OVERRIDE; + //! Enables reading in the quick part access mode. + Standard_EXPORT virtual void EnableQuickPartReading(const Handle(Message_Messenger)& theMessageDriver, Standard_Boolean theValue); + DEFINE_STANDARD_RTTIEXT(BinDrivers_DocumentRetrievalDriver,BinLDrivers_DocumentRetrievalDriver) diff --git a/src/BinDrivers/BinDrivers_DocumentStorageDriver.cxx b/src/BinDrivers/BinDrivers_DocumentStorageDriver.cxx index fda11dfff1..b04b5bb12e 100644 --- a/src/BinDrivers/BinDrivers_DocumentStorageDriver.cxx +++ b/src/BinDrivers/BinDrivers_DocumentStorageDriver.cxx @@ -93,6 +93,46 @@ void BinDrivers_DocumentStorageDriver::SetWithTriangles (const Handle(Message_Me aShapesDriver->SetWithTriangles (theWithTriangulation); } +void BinDrivers_DocumentStorageDriver::EnableQuickPartWriting(const Handle(Message_Messenger)& theMessageDriver, + const Standard_Boolean theValue) +{ + if (myDrivers.IsNull()) + { + myDrivers = AttributeDrivers(theMessageDriver); + } + if (myDrivers.IsNull()) + { + return; + } + + Handle(BinMDF_ADriver) aDriver; + myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver); + Handle(BinMNaming_NamedShapeDriver) aShapesDriver = Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver); + if (aShapesDriver.IsNull()) + { + throw Standard_NotImplemented("Internal Error - TNaming_NamedShape is not found!"); + } + + aShapesDriver->EnableQuickPart(theValue); +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void BinDrivers_DocumentStorageDriver::Clear() +{ + // Clear NamedShape driver + Handle(BinMDF_ADriver) aDriver; + if (myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver)) + { + Handle(BinMNaming_NamedShapeDriver) aNamedShapeDriver = + Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver); + aNamedShapeDriver->Clear(); + } + BinLDrivers_DocumentStorageDriver::Clear(); +} + //======================================================================= //function : WriteShapeSection //purpose : Implements WriteShapeSection diff --git a/src/BinDrivers/BinDrivers_DocumentStorageDriver.hxx b/src/BinDrivers/BinDrivers_DocumentStorageDriver.hxx index 4423371308..486714fc85 100644 --- a/src/BinDrivers/BinDrivers_DocumentStorageDriver.hxx +++ b/src/BinDrivers/BinDrivers_DocumentStorageDriver.hxx @@ -56,6 +56,13 @@ public: Standard_EXPORT void SetWithTriangles (const Handle(Message_Messenger)& theMessageDriver, const Standard_Boolean theWithTriangulation); + //! Enables writing in the quick part access mode. + Standard_EXPORT void EnableQuickPartWriting(const Handle(Message_Messenger)& theMessageDriver, + const Standard_Boolean theValue) Standard_OVERRIDE; + + //! Clears the NamedShape driver + Standard_EXPORT virtual void Clear() Standard_OVERRIDE; + DEFINE_STANDARD_RTTIEXT(BinDrivers_DocumentStorageDriver,BinLDrivers_DocumentStorageDriver) }; diff --git a/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.cxx b/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.cxx index 39c6955283..34b1af63dc 100644 --- a/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.cxx +++ b/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.cxx @@ -50,6 +50,7 @@ IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentRetrievalDriver,PCDM_RetrievalDriver) #define SHAPESECTION_POS "SHAPE_SECTION_POS:" +#define ENDSECTION_POS ":" #define SIZEOFSHAPELABEL 18 #define DATATYPE_MIGRATION @@ -179,7 +180,6 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& Standard_Boolean begin = Standard_False; Standard_Integer i; for (i=1; i <= aUserInfo.Length(); i++) { - //const TCollection_AsciiString& aStr = aUserInfo(i); TCollection_AsciiString aStr = aUserInfo(i); if (aStr == START_TYPES) begin = Standard_True; @@ -227,8 +227,8 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& Handle(TDF_Data) aData = (!theFilter.IsNull() && theFilter->IsAppendMode()) ? aDoc->GetData() : new TDF_Data(); std::streampos aDocumentPos = -1; - Message_ProgressScope aPS(theRange, "Reading data", 3); - Standard_Boolean aPostponeShapes = !theFilter.IsNull() && (theFilter->IsPartTree() || !theFilter->IsPassedAttr("TNaming_NamedShape")); + Message_ProgressScope aPS (theRange, "Reading data", 3); + Standard_Boolean aQuickPart = IsQuickPart (aFileVer); // 2b. Read the TOC of Sections if (aFileVer >= 3) { @@ -236,7 +236,8 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& do { BinLDrivers_DocumentSection::ReadTOC (aSection, theIStream, aFileVer); mySections.Append(aSection); - } while(!aSection.Name().IsEqual((Standard_CString)SHAPESECTION_POS) && !theIStream.eof()); + } while (!aSection.Name().IsEqual ((Standard_CString) + (aQuickPart ? ENDSECTION_POS : SHAPESECTION_POS)) && !theIStream.eof()); if (theIStream.eof()) { // There is no shape section in the file. @@ -254,14 +255,14 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& theIStream.seekg ((std::streampos) aCurSection.Offset()); if (aCurSection.Name().IsEqual ((Standard_CString)SHAPESECTION_POS)) { - ReadShapeSection (aCurSection, theIStream, false, aPostponeShapes, aPS.Next()); + ReadShapeSection (aCurSection, theIStream, false, aPS.Next()); if (!aPS.More()) { myReaderStatus = PCDM_RS_UserBreak; return; } } - else + else if (!aCurSection.Name().IsEqual ((Standard_CString)ENDSECTION_POS)) ReadSection (aCurSection, theDoc, theIStream); } } @@ -300,7 +301,7 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& CheckShapeSection(aShapeSectionPos, theIStream); // Read Shapes BinLDrivers_DocumentSection aCurSection; - ReadShapeSection (aCurSection, theIStream, Standard_False, aPostponeShapes, aPS.Next()); + ReadShapeSection (aCurSection, theIStream, Standard_False, aPS.Next()); if (!aPS.More()) { myReaderStatus = PCDM_RS_UserBreak; @@ -317,8 +318,14 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& Standard_Integer aTag; theIStream.read ((char*)&aTag, sizeof(Standard_Integer)); + if (aQuickPart) + myPAtt.SetIStream (theIStream); // for reading shapes data from the stream directly + EnableQuickPartReading (myMsgDriver, aQuickPart); + // read sub-tree of the root label - Standard_Integer nbRead = ReadSubTree (theIStream, aData->Root(), theFilter, aPS.Next()); + if (!theFilter.IsNull()) + theFilter->StartIteration(); + Standard_Integer nbRead = ReadSubTree (theIStream, aData->Root(), theFilter, aQuickPart, aPS.Next()); if (!aPS.More()) { myReaderStatus = PCDM_RS_UserBreak; @@ -366,6 +373,7 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree (Standard_IStream& theIS, const TDF_Label& theLabel, const Handle(PCDM_ReaderFilter)& theFilter, + const Standard_Boolean& theQuickPart, const Message_ProgressRange& theRange) { Standard_Integer nbRead = 0; @@ -374,12 +382,26 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree Message_ProgressScope aPS(theRange, "Reading sub tree", 2, true); - TCollection_AsciiString anEntry; bool aSkipAttrs = Standard_False; if (!theFilter.IsNull() && theFilter->IsPartTree()) + aSkipAttrs = !theFilter->IsPassed(); + + if (theQuickPart) { - TDF_Tool::Entry(theLabel, anEntry); - aSkipAttrs = !theFilter->IsPassed(anEntry); + uint64_t aLabelSize = 0; + theIS.read((char*)&aLabelSize, sizeof(uint64_t)); +#if DO_INVERSE + aLabelSize = InverseUint64(aLabelSize); +#endif + // no one sub-label is needed, so, skip everything + if (aSkipAttrs && !theFilter->IsSubPassed()) + { + aLabelSize -= sizeof (uint64_t); + theIS.seekg (aLabelSize, std::ios_base::cur); + if (!theFilter.IsNull()) + theFilter->Up(); + return 0; + } } // Read attributes: @@ -395,16 +417,21 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree return -1; } if (aSkipAttrs) + { + if (myPAtt.IsDirect()) // skip direct written stream + { + uint64_t aStreamSize = 0; + theIS.read ((char*)&aStreamSize, sizeof (uint64_t)); + aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size + theIS.seekg (aStreamSize, std::ios_base::cur); + } continue; + } // get a driver according to TypeId Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(myPAtt.TypeId()); if (!aDriver.IsNull()) { - if (!theFilter.IsNull() && !theFilter->IsPassed(aDriver->SourceType())) { - continue; - } // create transient attribute - nbRead++; Standard_Integer anID = myPAtt.Id(); Handle(TDF_Attribute) tAtt; Standard_Boolean isBound = myRelocTable.IsBound(anID); @@ -413,6 +440,18 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree else tAtt = aDriver->NewEmpty(); + if (!theFilter.IsNull() && !theFilter->IsPassed (tAtt->DynamicType())) { + if (myPAtt.IsDirect()) // skip direct written stream + { + uint64_t aStreamSize = 0; + theIS.read ((char*)&aStreamSize, sizeof (uint64_t)); + aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size + theIS.seekg (aStreamSize, std::ios_base::cur); + } + continue; + } + nbRead++; + if (tAtt->Label().IsNull()) { if (!theFilter.IsNull() && theFilter->Mode() != PCDM_ReaderFilter::AppendMode_Forbid && theLabel.IsAttribute(tAtt->ID())) @@ -482,7 +521,9 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree // read sub-tree - Standard_Integer nbSubRead = ReadSubTree(theIS, aLab, theFilter, aPS.Next()); + if (!theFilter.IsNull()) + theFilter->Down (aTag); + Standard_Integer nbSubRead = ReadSubTree (theIS, aLab, theFilter, theQuickPart, aPS.Next()); // check for error if (nbSubRead == -1) return -1; @@ -501,6 +542,8 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree myReaderStatus = PCDM_RS_UnrecognizedFileFormat; return -1; } + if (!theFilter.IsNull()) + theFilter->Up(); return nbRead; } @@ -538,7 +581,6 @@ void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection (BinLDrivers_DocumentSection& theSection, Standard_IStream& /*theIS*/, const Standard_Boolean isMess, - const Standard_Boolean /*thePostponeShapes*/, const Message_ProgressRange &/*theRange*/) { @@ -552,13 +594,12 @@ void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection //function : CheckShapeSection //purpose : //======================================================================= -void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection( - const Storage_Position& ShapeSectionPos, - Standard_IStream& IS) +void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection + (const Storage_Position& ShapeSectionPos, Standard_IStream& IS) { if (!IS.eof()) { - const std::streamoff endPos = IS.rdbuf()->pubseekoff(0L, std::ios_base::end, std::ios_base::in); + const std::streamoff endPos = IS.rdbuf()->pubseekoff (0L, std::ios_base::end, std::ios_base::in); #ifdef OCCT_DEBUG std::cout << "endPos = " << endPos < theCurVersion) { // file was written with another version @@ -594,3 +634,12 @@ Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion( } return Standard_True; } + +//======================================================================= +//function : IsQuickPart +//purpose : +//======================================================================= +Standard_Boolean BinLDrivers_DocumentRetrievalDriver::IsQuickPart (const Standard_Integer theFileVer) +{ + return theFileVer >= TDocStd_FormatVersion_VERSION_11; +} diff --git a/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.hxx b/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.hxx index 5c77e85149..100175365d 100644 --- a/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.hxx +++ b/src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.hxx @@ -84,6 +84,7 @@ protected: (Standard_IStream& theIS, const TDF_Label& theData, const Handle(PCDM_ReaderFilter)& theFilter, + const Standard_Boolean& theQuickPart, const Message_ProgressRange& theRanges = Message_ProgressRange()); @@ -98,7 +99,6 @@ protected: (BinLDrivers_DocumentSection& theSection, Standard_IStream& theIS, const Standard_Boolean isMess = Standard_False, - const Standard_Boolean thePostponeShapes = Standard_False, const Message_ProgressRange& theRange = Message_ProgressRange()); //! checks the shapes section can be correctly retreived. @@ -114,6 +114,12 @@ protected: //! current or lesser than 2, then return false, else true Standard_EXPORT virtual Standard_Boolean CheckDocumentVersion (const Standard_Integer theFileVersion, const Standard_Integer theCurVersion); + //! Return true if document retrieved document allows to read parts quickly. + static Standard_Boolean IsQuickPart (const Standard_Integer theFileVer); + + //! Enables reading in the quick part access mode. + Standard_EXPORT virtual void EnableQuickPartReading (const Handle(Message_Messenger)& /*theMessageDriver*/, Standard_Boolean /*theValue*/) {} + Handle(BinMDF_ADriverTable) myDrivers; BinObjMgt_RRelocationTable myRelocTable; Handle(Message_Messenger) myMsgDriver; diff --git a/src/BinLDrivers/BinLDrivers_DocumentSection.cxx b/src/BinLDrivers/BinLDrivers_DocumentSection.cxx index b51ba2fa7d..17ab3bedf8 100644 --- a/src/BinLDrivers/BinLDrivers_DocumentSection.cxx +++ b/src/BinLDrivers/BinLDrivers_DocumentSection.cxx @@ -228,6 +228,7 @@ void BinLDrivers_DocumentSection::ReadTOC #endif if (aNameBufferSize > 0) { theStream.read ((char *)&aBuf[0], (Standard_Size)aNameBufferSize); + aBuf[aNameBufferSize] = '\0'; theSection.myName = (Standard_CString)&aBuf[0]; uint64_t aValue[3]; diff --git a/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.cxx b/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.cxx index a682929815..53f3e99f29 100644 --- a/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.cxx +++ b/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -47,13 +48,14 @@ IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentStorageDriver,PCDM_StorageDriver) #define SHAPESECTION_POS (Standard_CString)"SHAPE_SECTION_POS:" +#define ENDSECTION_POS (Standard_CString)":" //======================================================================= //function : BinLDrivers_DocumentStorageDriver //purpose : Constructor //======================================================================= -BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver () +BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver () : myIsQuickPart(Standard_True) { } @@ -97,9 +99,9 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)& theD { myMsgDriver = theDoc->Application()->MessageDriver(); myMapUnsupported.Clear(); + mySizesToWrite.Clear(); - Handle(TDocStd_Document) aDoc = - Handle(TDocStd_Document)::DownCast(theDoc); + Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast (theDoc); if (aDoc.IsNull()) { SetIsError(Standard_True); SetStoreStatus(PCDM_SS_Doc_IsNull); @@ -129,20 +131,33 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)& theD for (; anIterS.More(); anIterS.Next()) anIterS.ChangeValue().WriteTOC (theOStream, aDocVer); - // Shapes Section is the last one, it indicates the end of the table. - BinLDrivers_DocumentSection aShapesSection (SHAPESECTION_POS, - Standard_False); - aShapesSection.WriteTOC (theOStream, aDocVer); + EnableQuickPartWriting (myMsgDriver, IsQuickPart (aDocVer)); + BinLDrivers_DocumentSection* aShapesSection = 0; + Standard_Boolean aQuickPart = IsQuickPart (aDocVer); + if (!aQuickPart) + { + // Shapes Section is the last one, it indicates the end of the table. + aShapesSection = new BinLDrivers_DocumentSection (SHAPESECTION_POS, Standard_False); + aShapesSection->WriteTOC (theOStream, aDocVer); + } + else + { + // End Section is the last one, it indicates the end of the table. + BinLDrivers_DocumentSection anEndSection (ENDSECTION_POS, Standard_False); + anEndSection.WriteTOC (theOStream, aDocVer); + } // 3. Write document contents // (Storage data to the stream) myRelocTable.Clear(); myPAtt.Init(); + if (aQuickPart) + myPAtt.SetOStream (theOStream); // for writing shapes data into the stream directly Message_ProgressScope aPS(theRange, "Writing document", 3); // Write Doc structure - WriteSubTree (aData->Root(), theOStream, aPS.Next()); // Doc is written + WriteSubTree (aData->Root(), theOStream, aQuickPart, aPS.Next()); // Doc is written if (!aPS.More()) { SetIsError(Standard_True); @@ -151,12 +166,19 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)& theD } // 4. Write Shapes section - WriteShapeSection (aShapesSection, theOStream, aDocVer, aPS.Next()); + if (!aQuickPart) + { + WriteShapeSection (*aShapesSection, theOStream, aDocVer, aPS.Next()); + delete aShapesSection; + } + else + Clear(); + if (!aPS.More()) { - SetIsError(Standard_True); - SetStoreStatus(PCDM_SS_UserBreak); - return; + SetIsError (Standard_True); + SetStoreStatus (PCDM_SS_UserBreak); + return; } // Write application-defined sections @@ -167,6 +189,10 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)& theD aSection.Write (theOStream, aSectionOffset, aDocVer); } +// 5. Write sizes along the file where it is needed for quick part mode + if (aQuickPart) + WriteSizes (theOStream); + // End of processing: close structures and check the status myPAtt.Destroy(); // free buffer myEmptyLabels.Clear(); @@ -211,7 +237,7 @@ void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg { #ifdef OCCT_DEBUG TCollection_ExtendedString aMsg - ("BinDrivers_DocumentStorageDriver: warning: attribute driver for type "); + ("BinLDrivers_DocumentStorageDriver: warning: attribute driver for type "); #endif if (!myMapUnsupported.Contains(theType)) { myMapUnsupported.Add(theType); @@ -229,6 +255,7 @@ void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg void BinLDrivers_DocumentStorageDriver::WriteSubTree (const TDF_Label& theLabel, Standard_OStream& theOS, + const Standard_Boolean& theQuickPart, const Message_ProgressRange& theRange) { // Skip empty labels @@ -244,6 +271,13 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree #endif theOS.write ((char*)&aTag, sizeof(Standard_Integer)); + Handle(BinObjMgt_Position) aPosition; + if (theQuickPart) + { + aPosition = mySizesToWrite.Append (new BinObjMgt_Position (theOS)); + aPosition->WriteSize (theOS); + } + // Write attributes TDF_AttributeIterator itAtt (theLabel); for ( ; itAtt.More() && theOS && aPS.More(); itAtt.Next()) { @@ -251,7 +285,7 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree const Handle(Standard_Type)& aType = tAtt->DynamicType(); // Get type ID and driver Handle(BinMDF_ADriver) aDriver; - const Standard_Integer aTypeId = myDrivers->GetDriver (aType,aDriver); + const Standard_Integer aTypeId = myDrivers->GetDriver (aType, aDriver); if (aTypeId > 0) { // Add source to relocation table const Standard_Integer anId = myRelocTable.Add (tAtt); @@ -260,6 +294,12 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree myPAtt.SetTypeId (aTypeId); myPAtt.SetId (anId); aDriver->Paste (tAtt, myPAtt, myRelocTable); + if (!myPAtt.StreamStart().IsNull()) + { + Handle(BinObjMgt_Position) anAttrPosition = myPAtt.StreamStart(); + anAttrPosition->StoreSize (theOS); + mySizesToWrite.Append (anAttrPosition); + } // Write data to the stream -->!!! theOS << myPAtt; @@ -297,16 +337,16 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree SetStoreStatus(PCDM_SS_UserBreak); return; } - WriteSubTree (aChildLab, theOS, aPS.Next()); + WriteSubTree (aChildLab, theOS, theQuickPart, aPS.Next()); } - // Write the end label marker BinLDrivers_Marker anEndLabel = BinLDrivers_ENDLABEL; #if DO_INVERSE - anEndLabel = (BinLDrivers_Marker) InverseInt (anEndLabel); + anEndLabel = (BinLDrivers_Marker)InverseInt (anEndLabel); #endif - theOS.write ((char*)&anEndLabel, sizeof(anEndLabel)); - + theOS.write ((char*)&anEndLabel, sizeof (anEndLabel)); + if (theQuickPart) + aPosition->StoreSize (theOS); } //======================================================================= @@ -553,3 +593,34 @@ void BinLDrivers_DocumentStorageDriver::WriteShapeSection const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp(); theSection.Write (theOS, aShapesSectionOffset, theDocVer); } + +//======================================================================= +//function : IsQuickPart +//purpose : Return true if document should be stored in quick mode for partial reading +//======================================================================= +Standard_Boolean BinLDrivers_DocumentStorageDriver::IsQuickPart (const Standard_Integer theVersion) const +{ + return theVersion >= TDocStd_FormatVersion_VERSION_11; +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void BinLDrivers_DocumentStorageDriver::Clear() +{ + // empty; should be redefined in subclasses +} + + +//======================================================================= +//function : WriteSizes +//purpose : +//======================================================================= +void BinLDrivers_DocumentStorageDriver::WriteSizes (Standard_OStream& theOS) +{ + NCollection_List::Iterator anIter (mySizesToWrite); + for (; anIter.More() && theOS; anIter.Next()) + anIter.Value()->WriteSize (theOS); + mySizesToWrite.Clear(); +} diff --git a/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.hxx b/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.hxx index 2de015c415..fc7eb7c24e 100644 --- a/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.hxx +++ b/src/BinLDrivers/BinLDrivers_DocumentStorageDriver.hxx @@ -36,6 +36,7 @@ class CDM_Document; class TDF_Label; class TCollection_AsciiString; class BinLDrivers_DocumentSection; +class BinObjMgt_Position; class BinLDrivers_DocumentStorageDriver; @@ -66,7 +67,8 @@ public: //! Create a section that should be written after the OCAF data Standard_EXPORT void AddSection (const TCollection_AsciiString& theName, const Standard_Boolean isPostRead = Standard_True); - + //! Return true if document should be stored in quick mode for partial reading + Standard_EXPORT Standard_Boolean IsQuickPart (const Standard_Integer theVersion) const; DEFINE_STANDARD_RTTIEXT(BinLDrivers_DocumentStorageDriver,PCDM_StorageDriver) @@ -76,7 +78,8 @@ protected: //! Write the tree under to the stream Standard_EXPORT void WriteSubTree (const TDF_Label& theData, - Standard_OStream& theOS, + Standard_OStream& theOS, + const Standard_Boolean& theQuickPart, const Message_ProgressRange& theRange = Message_ProgressRange()); //! define the procedure of writing a section to file. @@ -90,6 +93,13 @@ protected: const Standard_Integer theDocVer, const Message_ProgressRange& theRange = Message_ProgressRange()); + //! Enables writing in the quick part access mode. + Standard_EXPORT virtual void EnableQuickPartWriting ( + const Handle(Message_Messenger)& /*theMessageDriver*/, const Standard_Boolean /*theValue*/) {} + + //! clears the writing-cash data in drivers if any. + Standard_EXPORT virtual void Clear(); + Handle(BinMDF_ADriverTable) myDrivers; BinObjMgt_SRelocationTable myRelocTable; Handle(Message_Messenger) myMsgDriver; @@ -107,13 +117,18 @@ private: Standard_EXPORT void UnsupportedAttrMsg (const Handle(Standard_Type)& theType); + //! Writes sizes along the file where it is needed for quick part mode + Standard_EXPORT void WriteSizes (Standard_OStream& theOS); + BinObjMgt_Persistent myPAtt; TDF_LabelList myEmptyLabels; TColStd_MapOfTransient myMapUnsupported; TColStd_IndexedMapOfTransient myTypesMap; BinLDrivers_VectorOfDocumentSection mySections; TCollection_ExtendedString myFileName; - + Standard_Boolean myIsQuickPart; + //! Sizes of labels and some attributes that will be stored in the second pass + NCollection_List mySizesToWrite; }; #endif // _BinLDrivers_DocumentStorageDriver_HeaderFile diff --git a/src/BinMNaming/BinMNaming_NamedShapeDriver.cxx b/src/BinMNaming/BinMNaming_NamedShapeDriver.cxx index bb79761d35..e2a8909153 100644 --- a/src/BinMNaming/BinMNaming_NamedShapeDriver.cxx +++ b/src/BinMNaming/BinMNaming_NamedShapeDriver.cxx @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,7 +38,7 @@ IMPLEMENT_STANDARD_RTTIEXT(BinMNaming_NamedShapeDriver,BinMDF_ADriver) #define SHAPESET "SHAPE_SECTION" #define FORMAT_NUMBER 3 //======================================================================= -static Standard_Character EvolutionToChar(const TNaming_Evolution theEvol) +static Standard_Character EvolutionToChar (const TNaming_Evolution theEvol) { switch(theEvol) { case TNaming_PRIMITIVE : return 'P'; @@ -51,7 +53,7 @@ static Standard_Character EvolutionToChar(const TNaming_Evolution theEvol) } //======================================================================= -static TNaming_Evolution EvolutionToEnum(const Standard_Character theEvol) +static TNaming_Evolution EvolutionToEnum (const Standard_Character theEvol) { switch(theEvol) { case 'P': return TNaming_PRIMITIVE; @@ -65,7 +67,7 @@ static TNaming_Evolution EvolutionToEnum(const Standard_Character theEvol) } } //======================================================================= -static Standard_Character OrientationToChar(const TopAbs_Orientation theOrient) +static Standard_Character OrientationToChar (const TopAbs_Orientation theOrient) { switch(theOrient) { case TopAbs_FORWARD : return 'F'; @@ -77,7 +79,7 @@ static Standard_Character OrientationToChar(const TopAbs_Orientation theOrient) } } //======================================================================= -static TopAbs_Orientation CharToOrientation(const Standard_Character theCharOrient) +static TopAbs_Orientation CharToOrientation (const Standard_Character theCharOrient) { switch(theCharOrient) { case 'F': return TopAbs_FORWARD; @@ -92,45 +94,45 @@ static TopAbs_Orientation CharToOrientation(const Standard_Character theCharOri //======================================================================= static void TranslateTo (const TopoDS_Shape& theShape, BinObjMgt_Persistent& theResult, - BinTools_ShapeSet& theShapeSet) + BinTools_ShapeSet* theShapeSet) { // Check for empty shape if (theShape.IsNull()) { - theResult.PutInteger(-1); - theResult.PutInteger(-1); - theResult.PutInteger(-1); + theResult.PutInteger (-1); + theResult.PutInteger (-1); + theResult.PutInteger (-1); return; } // Add to shape set both TShape and Location contained in - const Standard_Integer aTShapeID = theShapeSet.Add (theShape); + const Standard_Integer aTShapeID = theShapeSet->Add (theShape); const Standard_Integer aLocID = - theShapeSet.Locations().Index (theShape.Location()); + theShapeSet->Locations().Index (theShape.Location()); // Fill theResult with shape parameters: TShape ID, Location, Orientation theResult << aTShapeID; theResult << aLocID; - theResult << OrientationToChar(theShape.Orientation()); + theResult << OrientationToChar (theShape.Orientation()); } //======================================================================= static int TranslateFrom (const BinObjMgt_Persistent& theSource, TopoDS_Shape& theResult, - BinTools_ShapeSet& theShapeSet) + BinTools_ShapeSet* theShapeSet) { Standard_Integer aShapeID, aLocID; Standard_Character aCharOrient; Standard_Boolean Ok = theSource >> aShapeID; //TShapeID; if(!Ok) return 1; // Read TShape and Orientation - if (aShapeID <= 0 || aShapeID > theShapeSet.NbShapes()) + if (aShapeID <= 0 || aShapeID > theShapeSet->NbShapes()) return 1; Ok = theSource >> aLocID; if(!Ok) return 1; Ok = theSource >> aCharOrient; if(!Ok) return 1; - TopAbs_Orientation anOrient = CharToOrientation(aCharOrient); + TopAbs_Orientation anOrient = CharToOrientation (aCharOrient); - theResult.TShape (theShapeSet.Shape(aShapeID).TShape());//TShape - theResult.Location (theShapeSet.Locations().Location (aLocID)); //Location + theResult.TShape (theShapeSet->Shape (aShapeID).TShape());//TShape + theResult.Location (theShapeSet->Locations().Location (aLocID)); //Location theResult.Orientation (anOrient);//Orientation return 0; } @@ -142,7 +144,11 @@ static int TranslateFrom (const BinObjMgt_Persistent& theSource, BinMNaming_NamedShapeDriver::BinMNaming_NamedShapeDriver (const Handle(Message_Messenger)& theMsgDriver) - : BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_NamedShape)->Name()), myShapeSet(Standard_False),myFormatNb(FORMAT_NUMBER) + : BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_NamedShape)->Name()), + myShapeSet (NULL), + myFormatNb (BinTools_FormatVersion_VERSION_1), + myIsQuickPart (Standard_False), + myWithTriangles (Standard_False) { } @@ -166,11 +172,11 @@ Standard_Boolean BinMNaming_NamedShapeDriver::Paste const Handle(TDF_Attribute)& theTarget, BinObjMgt_RRelocationTable& ) const { - Handle(TNaming_NamedShape) aTAtt= Handle(TNaming_NamedShape)::DownCast(theTarget); + Handle(TNaming_NamedShape) aTAtt= Handle(TNaming_NamedShape)::DownCast (theTarget); Standard_Integer aNbShapes; theSource >> aNbShapes; TDF_Label aLabel = theTarget->Label (); - TNaming_Builder aBuilder (aLabel); + TNaming_Builder aBuilder (aLabel); Standard_Integer aVer; Standard_Boolean ok = theSource >> aVer; if(!ok) return Standard_False; @@ -178,10 +184,13 @@ Standard_Boolean BinMNaming_NamedShapeDriver::Paste Standard_Character aCharEvol; ok = theSource >> aCharEvol; if(!ok) return Standard_False; - TNaming_Evolution anEvol = EvolutionToEnum(aCharEvol); //Evolution - aTAtt->SetVersion(anEvol); + TNaming_Evolution anEvol = EvolutionToEnum (aCharEvol); //Evolution + aTAtt->SetVersion (anEvol); - BinTools_ShapeSet& aShapeSet = (BinTools_ShapeSet&) myShapeSet; + BinTools_ShapeSetBase* aShapeSet = const_cast(this)->ShapeSet (Standard_True); + Standard_IStream* aDirectStream = NULL; + if (myIsQuickPart) // enables direct reading of shapes from the stream + aDirectStream = const_cast(&theSource)->GetIStream(); NCollection_List anOldShapes, aNewShapes; for (Standard_Integer i = 1; i <= aNbShapes; i++) @@ -189,10 +198,16 @@ Standard_Boolean BinMNaming_NamedShapeDriver::Paste TopoDS_Shape anOldShape, aNewShape; if (anEvol != TNaming_PRIMITIVE) - if (TranslateFrom (theSource, anOldShape, aShapeSet)) return Standard_False; + if (myIsQuickPart) + aShapeSet->Read (*aDirectStream, anOldShape); + else + if (TranslateFrom (theSource, anOldShape, static_cast(aShapeSet))) return Standard_False; if (anEvol != TNaming_DELETE) - if (TranslateFrom (theSource, aNewShape, aShapeSet)) return Standard_False; + if (myIsQuickPart) + aShapeSet->Read (*aDirectStream, aNewShape); + else + if (TranslateFrom (theSource, aNewShape, static_cast(aShapeSet))) return Standard_False; // Here we add shapes in reverse order because TNaming_Builder also adds them in reverse order. anOldShapes.Prepend (anOldShape); @@ -246,24 +261,38 @@ void BinMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource, for (TNaming_Iterator SItr (aSAtt); SItr.More (); SItr.Next ()) NbShapes++; //-------------------------------------------------------------- - BinTools_ShapeSet& aShapeSet = (BinTools_ShapeSet&) myShapeSet; + BinTools_ShapeSetBase* aShapeSet = const_cast(this)->ShapeSet (Standard_False); TNaming_Evolution anEvol = aSAtt->Evolution(); theTarget << NbShapes; theTarget << aSAtt->Version(); - theTarget << EvolutionToChar(anEvol); - + theTarget << EvolutionToChar (anEvol); + + + Standard_OStream* aDirectStream = NULL; + if (myIsQuickPart) // enables direct writing of shapes to the stream + aDirectStream = theTarget.GetOStream(); Standard_Integer i = 1; - for (TNaming_Iterator SIterator(aSAtt) ;SIterator.More(); SIterator.Next()) { - const TopoDS_Shape& OldShape = SIterator.OldShape(); - const TopoDS_Shape& NewShape = SIterator.NewShape(); + for (TNaming_Iterator SIterator(aSAtt); SIterator.More(); SIterator.Next()) { + const TopoDS_Shape& anOldShape = SIterator.OldShape(); + const TopoDS_Shape& aNewShape = SIterator.NewShape(); - if ( anEvol != TNaming_PRIMITIVE ) - TranslateTo (OldShape, theTarget, aShapeSet); + if (anEvol != TNaming_PRIMITIVE) + { + if (myIsQuickPart) + aShapeSet->Write (anOldShape, *aDirectStream); + else + TranslateTo (anOldShape, theTarget, static_cast(aShapeSet)); + } - if (anEvol != TNaming_DELETE) - TranslateTo (NewShape, theTarget, aShapeSet); + if (anEvol != TNaming_DELETE) + { + if (myIsQuickPart) + aShapeSet->Write (aNewShape, *aDirectStream); + else + TranslateTo (aNewShape, theTarget, static_cast(aShapeSet)); + } i++; } @@ -279,10 +308,11 @@ void BinMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource, void BinMNaming_NamedShapeDriver::WriteShapeSection (Standard_OStream& theOS, const Message_ProgressRange& theRange) { - theOS << SHAPESET; - myShapeSet.SetFormatNb(myFormatNb); - myShapeSet.Write (theOS, theRange); - myShapeSet.Clear(); + myIsQuickPart = Standard_False; + theOS << SHAPESET; + ShapeSet (Standard_False)->SetFormatNb (myFormatNb); + ShapeSet (Standard_False)->Write (theOS, theRange); + ShapeSet (Standard_False)->Clear(); } //======================================================================= @@ -292,7 +322,12 @@ void BinMNaming_NamedShapeDriver::WriteShapeSection (Standard_OStream& theOS, void BinMNaming_NamedShapeDriver::Clear() { - myShapeSet.Clear(); + if (myShapeSet) + { + myShapeSet->Clear(); + delete myShapeSet; + myShapeSet = NULL; + } } //======================================================================= @@ -301,19 +336,48 @@ void BinMNaming_NamedShapeDriver::Clear() //======================================================================= void BinMNaming_NamedShapeDriver::ReadShapeSection (Standard_IStream& theIS, - const Standard_Boolean thePostponeShapes, const Message_ProgressRange& theRange) { + myIsQuickPart = Standard_False; // check section title string; note that some versions of OCCT (up to 6.3.1) // might avoid writing shape section if it is empty std::streamoff aPos = theIS.tellg(); TCollection_AsciiString aSectionTitle; theIS >> aSectionTitle; if(aSectionTitle.Length() > 0 && aSectionTitle == SHAPESET) { - myShapeSet.Clear(); - myShapeSet.Read (theIS, thePostponeShapes, theRange); - SetFormatNb(myShapeSet.FormatNb()); + BinTools_ShapeSetBase* aShapeSet = ShapeSet (Standard_True); + aShapeSet->Clear(); + aShapeSet->Read (theIS, theRange); + SetFormatNb (aShapeSet->FormatNb()); } else - theIS.seekg(aPos); // no shape section is present, try to return to initial point + theIS.seekg (aPos); // no shape section is present, try to return to initial point +} + +//======================================================================= +//function : ShapeSet +//purpose : +//======================================================================= + +BinTools_ShapeSetBase* BinMNaming_NamedShapeDriver::ShapeSet (const Standard_Boolean theReading) +{ + if (!myShapeSet) + if (myIsQuickPart) + if (theReading) + myShapeSet = new BinTools_ShapeReader(); + else + myShapeSet = new BinTools_ShapeWriter (myWithTriangles); + else + myShapeSet = new BinTools_ShapeSet (myWithTriangles); + return myShapeSet; +} + +//======================================================================= +//function : GetShapesLocations +//purpose : +//======================================================================= +BinTools_LocationSet& BinMNaming_NamedShapeDriver::GetShapesLocations() const +{ + BinTools_ShapeSetBase* aShapeSet = const_cast(this)->ShapeSet (Standard_False); + return static_cast(aShapeSet)->ChangeLocations(); } diff --git a/src/BinMNaming/BinMNaming_NamedShapeDriver.hxx b/src/BinMNaming/BinMNaming_NamedShapeDriver.hxx index 54bd4bc7f2..b2d93e4802 100644 --- a/src/BinMNaming/BinMNaming_NamedShapeDriver.hxx +++ b/src/BinMNaming/BinMNaming_NamedShapeDriver.hxx @@ -53,7 +53,6 @@ public: //! Input the shapes from Bin Document file Standard_EXPORT void ReadShapeSection (Standard_IStream& theIS, - const Standard_Boolean thePostponeShapes = Standard_False, const Message_ProgressRange& therange = Message_ProgressRange()); //! Output the shapes into Bin Document file @@ -64,7 +63,7 @@ public: Standard_EXPORT void Clear(); //! Return true if shape should be stored with triangles. - Standard_Boolean IsWithTriangles() const { return myShapeSet.IsWithTriangles(); } + Standard_Boolean IsWithTriangles() const { return myWithTriangles; } //! set whether to store triangulation void SetWithTriangles (const Standard_Boolean isWithTriangles); @@ -73,29 +72,33 @@ public: //! First : does not write CurveOnSurface UV Points into the file //! on reading calls Check() method. //! Second: stores CurveOnSurface UV Points. - void SetFormatNb (const Standard_Integer theFormat); + void SetFormatNb (const Standard_Integer theFormat); //! get the format of topology - Standard_Integer GetFormatNb() const; + Standard_Integer GetFormatNb() const; //! get the format of topology - BinTools_LocationSet& GetShapesLocations(); - + Standard_EXPORT BinTools_LocationSet& GetShapesLocations() const; + //! Sets the flag for quick part of the document access: shapes are stored in the attribute. + Standard_EXPORT void EnableQuickPart(const Standard_Boolean theValue) { myIsQuickPart = theValue; } + //! Returns true if quick part of the document access is enabled: shapes are stored in the attribute. + Standard_EXPORT Standard_Boolean IsQuickPart() { return myIsQuickPart; } + //! Returns shape-set of the needed type + Standard_EXPORT BinTools_ShapeSetBase* ShapeSet (const Standard_Boolean theReading); DEFINE_STANDARD_RTTIEXT(BinMNaming_NamedShapeDriver,BinMDF_ADriver) -protected: - - - private: - BinTools_ShapeSet myShapeSet; + BinTools_ShapeSetBase *myShapeSet; Standard_Integer myFormatNb; + Standard_Boolean myWithTriangles; + //! Enables storing of whole shape data just in the attribute, not in a separated shapes section + Standard_Boolean myIsQuickPart; }; diff --git a/src/BinMNaming/BinMNaming_NamedShapeDriver.lxx b/src/BinMNaming/BinMNaming_NamedShapeDriver.lxx index da9a59daeb..744bdf78c9 100644 --- a/src/BinMNaming/BinMNaming_NamedShapeDriver.lxx +++ b/src/BinMNaming/BinMNaming_NamedShapeDriver.lxx @@ -40,15 +40,7 @@ inline void BinMNaming_NamedShapeDriver::SetFormatNb(const Standard_Integer theF inline void BinMNaming_NamedShapeDriver::SetWithTriangles(const Standard_Boolean isWithTriangles) { - myShapeSet.SetWithTriangles(isWithTriangles); + myWithTriangles = isWithTriangles; + if (myShapeSet) + myShapeSet->SetWithTriangles (isWithTriangles); } - -//======================================================================= -//function : GetShapesLocations -//purpose : -//======================================================================= -inline BinTools_LocationSet& BinMNaming_NamedShapeDriver::GetShapesLocations() -{ - return myShapeSet.ChangeLocations(); -} - diff --git a/src/BinMXCAFDoc/BinMXCAFDoc.cxx b/src/BinMXCAFDoc/BinMXCAFDoc.cxx index b458ebe82d..3a2bac5218 100644 --- a/src/BinMXCAFDoc/BinMXCAFDoc.cxx +++ b/src/BinMXCAFDoc/BinMXCAFDoc.cxx @@ -51,9 +51,9 @@ void BinMXCAFDoc::AddDrivers(const Handle(BinMDF_ADriverTable)& theDriverTable, Handle(BinMNaming_NamedShapeDriver)::DownCast (aNSDriver); Handle(BinMXCAFDoc_LocationDriver) aLocationDriver = new BinMXCAFDoc_LocationDriver (theMsgDrv); - if( !aNamedShapeDriver.IsNull() ) + if (!aNamedShapeDriver.IsNull()) { - aLocationDriver->SetSharedLocations( &(aNamedShapeDriver->GetShapesLocations()) ); + aLocationDriver->SetNSDriver (aNamedShapeDriver); } theDriverTable->AddDriver( aLocationDriver); diff --git a/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.cxx b/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.cxx index 43fa820dfe..65736d1519 100644 --- a/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.cxx +++ b/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.cxx @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,7 +39,7 @@ IMPLEMENT_STANDARD_RTTIEXT(BinMXCAFDoc_LocationDriver,BinMDF_ADriver) //======================================================================= BinMXCAFDoc_LocationDriver::BinMXCAFDoc_LocationDriver(const Handle(Message_Messenger)& theMsgDriver) : BinMDF_ADriver(theMsgDriver, STANDARD_TYPE(XCAFDoc_Location)->Name()) - , myLocations(0) { +{ } //======================================================================= @@ -84,6 +86,14 @@ Standard_Boolean BinMXCAFDoc_LocationDriver::Translate(const BinObjMgt_Persisten TopLoc_Location& theLoc, BinObjMgt_RRelocationTable& theMap) const { + if (!myNSDriver.IsNull() && myNSDriver->IsQuickPart()) + { + BinTools_IStream aDirectStream (*(const_cast(&theSource)->GetIStream())); + BinTools_ShapeReader* aReader = static_cast(myNSDriver->ShapeSet (Standard_True)); + theLoc = *(aReader->ReadLocation (aDirectStream)); + return Standard_True; + } + Standard_Integer anId = 0; theSource >> anId; @@ -91,19 +101,25 @@ Standard_Boolean BinMXCAFDoc_LocationDriver::Translate(const BinObjMgt_Persisten { return Standard_True; } + + if (!myNSDriver.IsNull() && myNSDriver->IsQuickPart()) + { // read directly from the stream + + + } Standard_Integer aFileVer = theMap.GetHeaderData()->StorageVersion().IntegerValue(); - if( aFileVer > 5 && myLocations == 0 ) + if( aFileVer >= TDocStd_FormatVersion_VERSION_6 && myNSDriver.IsNull() ) { return Standard_False; } - Standard_Integer aPower; + Standard_Integer aPower (0); Handle(TopLoc_Datum3D) aDatum; - if( aFileVer > 5 ) + if (aFileVer >= TDocStd_FormatVersion_VERSION_6) { - const TopLoc_Location& aLoc = myLocations->Location(anId); + const TopLoc_Location& aLoc = myNSDriver->GetShapesLocations().Location (anId); aPower = aLoc.FirstPower(); aDatum = aLoc.FirstDatum(); } else { @@ -168,35 +184,42 @@ void BinMXCAFDoc_LocationDriver::Translate(const TopLoc_Location& theLoc, BinObjMgt_Persistent& theTarget, BinObjMgt_SRelocationTable& theMap) const { - if(theLoc.IsIdentity()) + // The location is not identity + if (!myNSDriver.IsNull() && myNSDriver->IsQuickPart()) + { // write directly to the stream + Standard_OStream* aDirectStream = theTarget.GetOStream(); + BinTools_ShapeWriter* aWriter = static_cast(myNSDriver->ShapeSet (Standard_False)); + aWriter->WriteLocation (*aDirectStream, theLoc); + return; + } + if(theLoc.IsIdentity()) { theTarget.PutInteger(0); return; } - // The location is not identity - if( myLocations == 0 ) + if (myNSDriver.IsNull()) { #ifdef OCCT_DEBUG - std::cout<<"Pointer to LocationSet is NULL\n"; + std::cout << "NamedShape Driver is NULL\n"; #endif return; } - - Standard_Integer anId = myLocations->Add(theLoc); + + Standard_Integer anId = myNSDriver->GetShapesLocations().Add (theLoc); theTarget << anId; - + // In earlier version of this driver a datums from location stored in // the relocation table, but now it's not necessary // (try to uncomment it if some problems appear) /* Handle(TopLoc_Datum3D) aDatum = theLoc.FirstDatum(); - + if(!theMap.Contains(aDatum)) { theMap.Add(aDatum); } */ - + Translate(theLoc.NextLocation(), theTarget, theMap); } diff --git a/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.hxx b/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.hxx index 76fe223d8b..c46d5b8838 100644 --- a/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.hxx +++ b/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.hxx @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -53,7 +53,7 @@ public: //! Translate transient location to storable Standard_EXPORT void Translate (const TopLoc_Location& theLoc, BinObjMgt_Persistent& theTarget, BinObjMgt_SRelocationTable& theMap) const; - void SetSharedLocations (const BinTools_LocationSetPtr& theLocations); + void SetNSDriver (const Handle(BinMNaming_NamedShapeDriver)& theNSDriver) { myNSDriver = theNSDriver; } @@ -68,16 +68,10 @@ protected: private: - BinTools_LocationSetPtr myLocations; - + Handle(BinMNaming_NamedShapeDriver) myNSDriver; }; -#include - - - - #endif // _BinMXCAFDoc_LocationDriver_HeaderFile diff --git a/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.lxx b/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.lxx deleted file mode 100644 index f4ab83ae08..0000000000 --- a/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.lxx +++ /dev/null @@ -1,26 +0,0 @@ -// Created on: 2011-02-08 -// Created by: Oleg AGASHIN -// Copyright (c) 2011-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -//======================================================================= -//function : SetSharedLocations -//purpose : -//======================================================================= -inline void BinMXCAFDoc_LocationDriver::SetSharedLocations(const BinTools_LocationSetPtr& theLocations) -{ - if( myLocations != theLocations ) - { - myLocations = theLocations; - } -} diff --git a/src/BinMXCAFDoc/FILES b/src/BinMXCAFDoc/FILES index 68f84fabf9..93026d7d16 100644 --- a/src/BinMXCAFDoc/FILES +++ b/src/BinMXCAFDoc/FILES @@ -14,7 +14,6 @@ BinMXCAFDoc_GraphNodeDriver.cxx BinMXCAFDoc_GraphNodeDriver.hxx BinMXCAFDoc_LocationDriver.cxx BinMXCAFDoc_LocationDriver.hxx -BinMXCAFDoc_LocationDriver.lxx BinMXCAFDoc_MaterialDriver.cxx BinMXCAFDoc_MaterialDriver.hxx BinMXCAFDoc_NoteDriver.cxx diff --git a/src/BinObjMgt/BinObjMgt_Persistent.cxx b/src/BinObjMgt/BinObjMgt_Persistent.cxx index cf3983753f..d8900ed810 100644 --- a/src/BinObjMgt/BinObjMgt_Persistent.cxx +++ b/src/BinObjMgt/BinObjMgt_Persistent.cxx @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -52,7 +53,10 @@ BinObjMgt_Persistent::BinObjMgt_Persistent () : myIndex (1), myOffset(BP_HEADSIZE), mySize (BP_HEADSIZE), - myIsError (Standard_False) + myIsError (Standard_False), + myIStream (NULL), + myOStream (NULL), + myDirectWritingIsEnabled (Standard_False) { Init(); } @@ -76,6 +80,7 @@ void BinObjMgt_Persistent::Init () myOffset = BP_HEADSIZE; mySize = BP_HEADSIZE; myIsError = Standard_False; + myDirectWritingIsEnabled = Standard_False; } //======================================================================= @@ -85,12 +90,19 @@ void BinObjMgt_Persistent::Init () // const BinObjMgt_Persistent&) is also available //======================================================================= -Standard_OStream& BinObjMgt_Persistent::Write (Standard_OStream& theOS) +Standard_OStream& BinObjMgt_Persistent::Write (Standard_OStream& theOS, const Standard_Boolean theDirectStream) { + if (myDirectWritingIsEnabled) + { // if direct writing was enabled, everything is already written, just pass this stage + myDirectWritingIsEnabled = Standard_False; + return theOS; + } Standard_Integer nbWritten = 0; Standard_Integer *aData = (Standard_Integer*) myData(1); // update data length aData[2] = mySize - BP_HEADSIZE; + if (theDirectStream) + aData[1] = -aData[1]; #if DO_INVERSE aData[0] = InverseInt (aData[0]); aData[1] = InverseInt (aData[1]); @@ -141,7 +153,9 @@ Standard_IStream& BinObjMgt_Persistent::Read (Standard_IStream& theIS) aData[1] = InverseInt (aData[1]); aData[2] = InverseInt (aData[2]); #endif - if (theIS && aData[1] > 0 && aData[2] > 0) { + if (myDirectWritingIsEnabled = (aData[1] < 0)) + aData[1] = -aData[1]; + if (theIS && aData[2] > 0) { mySize += aData[2]; // read remaining data Standard_Integer nbRead = BP_HEADSIZE; @@ -1164,3 +1178,28 @@ void BinObjMgt_Persistent::inverseShortRealData } } } + +//======================================================================= +//function : GetOStream +//purpose : Gets the stream for and enables direct writing +//======================================================================= + +Standard_OStream* BinObjMgt_Persistent::GetOStream() +{ + Write (*myOStream, Standard_True); // finishes already stored data save + myStreamStart = new BinObjMgt_Position (*myOStream); + myStreamStart->WriteSize (*myOStream); + myDirectWritingIsEnabled = Standard_True; + return myOStream; +} + +//======================================================================= +//function : GetOStream +//purpose : Gets the stream for and enables direct writing +//======================================================================= +Standard_IStream* BinObjMgt_Persistent::GetIStream() +{ + // skip the stream size first + myIStream->seekg (sizeof (uint64_t), std::ios_base::cur); + return myIStream; +} diff --git a/src/BinObjMgt/BinObjMgt_Persistent.hxx b/src/BinObjMgt/BinObjMgt_Persistent.hxx index a43a51de7b..2919efc00a 100644 --- a/src/BinObjMgt/BinObjMgt_Persistent.hxx +++ b/src/BinObjMgt/BinObjMgt_Persistent.hxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -261,13 +262,13 @@ const BinObjMgt_Persistent& operator >> (Standard_GUID& theValue) const //! Indicates an error after Get methods or SetPosition Standard_Boolean IsError() const; Standard_Boolean operator !() const -{ - return IsError(); -} + { + return IsError(); + } //! Indicates a good state after Get methods or SetPosition Standard_Boolean IsOK() const; -operator Standard_Boolean () const { return IsOK(); } + operator Standard_Boolean () const { return IsOK(); } //! Initializes me to reuse again Standard_EXPORT void Init(); @@ -289,8 +290,9 @@ operator Standard_Boolean () const { return IsOK(); } //! Stores to the stream. //! inline Standard_OStream& operator<< (Standard_OStream&, - //! BinObjMgt_Persistent&) is also available - Standard_EXPORT Standard_OStream& Write (Standard_OStream& theOS); + //! BinObjMgt_Persistent&) is also available. + //! If theDirectStream is true, after this data the direct stream data is stored. + Standard_EXPORT Standard_OStream& Write (Standard_OStream& theOS, const Standard_Boolean theDirectStream = Standard_False); //! Retrieves from the stream. //! inline Standard_IStream& operator>> (Standard_IStream&, @@ -300,19 +302,23 @@ operator Standard_Boolean () const { return IsOK(); } //! Frees the allocated memory; //! This object can be reused after call to Init Standard_EXPORT void Destroy(); -~BinObjMgt_Persistent() -{ - Destroy(); -} - - - - -protected: - - - + ~BinObjMgt_Persistent() + { + Destroy(); + } + //! Sets the stream for direct writing + Standard_EXPORT void SetOStream (Standard_OStream& theStream) { myOStream = &theStream; } + //! Sets the stream for direct reading + Standard_EXPORT void SetIStream (Standard_IStream& theStream) { myIStream = &theStream; } + //! Gets the stream for and enables direct writing + Standard_EXPORT Standard_OStream* GetOStream(); + //! Gets the stream for and enables direct reading + Standard_EXPORT Standard_IStream* GetIStream(); + //! Returns true if after this record a direct writing to the stream is performed. + Standard_EXPORT Standard_Boolean IsDirect() { return myDirectWritingIsEnabled; } + //! Returns the start position of the direct writing in the stream + Standard_EXPORT Handle(BinObjMgt_Position) StreamStart() { return myStreamStart; } private: @@ -358,8 +364,10 @@ private: Standard_Integer myOffset; Standard_Integer mySize; Standard_Boolean myIsError; - - + Standard_OStream* myOStream; ///< stream to write in case direct writing is enabled + Standard_IStream* myIStream; ///< stream to write in case direct reading is enabled + Standard_Boolean myDirectWritingIsEnabled; + Handle(BinObjMgt_Position) myStreamStart; ///< position where the direct writing to the script is started }; diff --git a/src/BinObjMgt/BinObjMgt_Persistent.lxx b/src/BinObjMgt/BinObjMgt_Persistent.lxx index c7c22afc07..9ea3282cf6 100644 --- a/src/BinObjMgt/BinObjMgt_Persistent.lxx +++ b/src/BinObjMgt/BinObjMgt_Persistent.lxx @@ -34,6 +34,7 @@ inline void BinObjMgt_Persistent::SetId (const Standard_Integer theId) inline void BinObjMgt_Persistent::SetTypeId (const Standard_Integer theTypeId) { ((Standard_Integer*) myData(1)) [0] = theTypeId; + myStreamStart.Nullify(); } //======================================================================= diff --git a/src/BinObjMgt/BinObjMgt_Position.cxx b/src/BinObjMgt/BinObjMgt_Position.cxx new file mode 100644 index 0000000000..a5a7b8ed04 --- /dev/null +++ b/src/BinObjMgt/BinObjMgt_Position.cxx @@ -0,0 +1,47 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_RTTIEXT (BinObjMgt_Position, Standard_Transient) + +//======================================================================= +//function : BinObjMgt_Position +//purpose : +//======================================================================= +BinObjMgt_Position::BinObjMgt_Position (Standard_OStream& theStream) : + myPosition (theStream.tellp()), mySize(0) +{} + +//======================================================================= +//function : StoreSize +//purpose : +//======================================================================= +void BinObjMgt_Position::StoreSize (Standard_OStream& theStream) +{ + mySize = uint64_t (theStream.tellp() - myPosition); +} + +//======================================================================= +//function : WriteSize +//purpose : +//======================================================================= +void BinObjMgt_Position::WriteSize (Standard_OStream& theStream) +{ + if (theStream.tellp() != myPosition) + theStream.seekp (myPosition); +#if DO_INVERSE + mySize = FSD_BinaryFile::InverseUint64 (mySize); +#endif + theStream.write ((char*)&mySize, sizeof (uint64_t)); +} diff --git a/src/BinObjMgt/BinObjMgt_Position.hxx b/src/BinObjMgt/BinObjMgt_Position.hxx new file mode 100644 index 0000000000..d6029ad3be --- /dev/null +++ b/src/BinObjMgt/BinObjMgt_Position.hxx @@ -0,0 +1,44 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BinObjMgt_Position_HeaderFile +#define _BinObjMgt_Position_HeaderFile + +#include + +class BinObjMgt_Position; +DEFINE_STANDARD_HANDLE (BinObjMgt_Position, Standard_Transient) + +//! Stores and manipulates position in the stream. +class BinObjMgt_Position : public Standard_Transient +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Creates position using the current stream position. + Standard_EXPORT BinObjMgt_Position (Standard_OStream& theStream); + + //! Stores the difference between the current position and the stored one. + Standard_EXPORT void StoreSize (Standard_OStream& theStream); + //! Writes stored size at the stored position. Changes the current stream position. + Standard_EXPORT void WriteSize (Standard_OStream& theStream); + + DEFINE_STANDARD_RTTIEXT (BinObjMgt_Position, Standard_Transient) + +private: + std::streampos myPosition; + uint64_t mySize; +}; + +#endif // _BinObjMgt_Position_HeaderFile diff --git a/src/BinObjMgt/FILES b/src/BinObjMgt/FILES index 7954116694..4683730dcb 100755 --- a/src/BinObjMgt/FILES +++ b/src/BinObjMgt/FILES @@ -5,6 +5,8 @@ BinObjMgt_Persistent.hxx BinObjMgt_Persistent.lxx BinObjMgt_PExtChar.hxx BinObjMgt_PInteger.hxx +BinObjMgt_Position.cxx +BinObjMgt_Position.hxx BinObjMgt_PReal.hxx BinObjMgt_PShortReal.hxx BinObjMgt_RRelocationTable.cxx diff --git a/src/BinTools/BinTools.cxx b/src/BinTools/BinTools.cxx index 32f6a77688..7c5b3b0f40 100644 --- a/src/BinTools/BinTools.cxx +++ b/src/BinTools/BinTools.cxx @@ -42,7 +42,7 @@ Standard_OStream& BinTools::PutInteger(Standard_OStream& OS, const Standard_Inte #if DO_INVERSE anIntValue = InverseInt (aValue); #endif - OS.write((char*)&anIntValue, sizeof(Standard_Integer)); + OS.write ((char*)&anIntValue, sizeof (Standard_Integer)); return OS; } @@ -56,9 +56,9 @@ Standard_OStream& BinTools::PutReal (Standard_OStream& theOS, { #if DO_INVERSE const Standard_Real aRValue = InverseReal (theValue); - theOS.write((char*)&aRValue, sizeof(Standard_Real)); + theOS.write ((char*)&aRValue, sizeof (Standard_Real)); #else - theOS.write((char*)&theValue, sizeof(Standard_Real)); + theOS.write ((char*)&theValue, sizeof (Standard_Real)); #endif return theOS; } @@ -94,6 +94,35 @@ Standard_OStream& BinTools::PutExtChar(Standard_OStream& OS, const Standard_ExtC return OS; } +//======================================================================= +//function : PutBools +//purpose : +//======================================================================= + +Standard_OStream& BinTools::PutBools (Standard_OStream& OS, + const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3) +{ + Standard_Byte aValue = (theValue1 ? 1 : 0) | (theValue2 ? 2 : 0) | (theValue3 ? 4 : 0); + OS.write((char*)&aValue, sizeof(Standard_Byte)); + return OS; +} + +//======================================================================= +//function : PutBools +//purpose : +//======================================================================= + +Standard_OStream& BinTools::PutBools (Standard_OStream& OS, + const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3, + const Standard_Boolean theValue4, const Standard_Boolean theValue5, const Standard_Boolean theValue6, + const Standard_Boolean theValue7) +{ + Standard_Byte aValue = (theValue1 ? 1 : 0) | (theValue2 ? 2 : 0) | (theValue3 ? 4 : 0) | (theValue4 ? 8 : 0) | + (theValue5 ? 16 : 0) | (theValue6 ? 32 : 0) | (theValue7 ? 64 : 0); + OS.write ((char*)&aValue, sizeof(Standard_Byte)); + return OS; +} + //======================================================================= //function : GetReal //purpose : @@ -193,7 +222,7 @@ void BinTools::Read (TopoDS_Shape& theShape, Standard_IStream& theStream, const Message_ProgressRange& theRange) { BinTools_ShapeSet aShapeSet(Standard_True); - aShapeSet.Read (theStream, Standard_False, theRange); + aShapeSet.Read (theStream, theRange); aShapeSet.ReadSubs (theShape, theStream, aShapeSet.NbShapes()); } diff --git a/src/BinTools/BinTools.hxx b/src/BinTools/BinTools.hxx index 07ad4655bb..882502f6f7 100644 --- a/src/BinTools/BinTools.hxx +++ b/src/BinTools/BinTools.hxx @@ -52,6 +52,14 @@ public: Standard_EXPORT static Standard_OStream& PutBool (Standard_OStream& OS, const Standard_Boolean theValue); Standard_EXPORT static Standard_OStream& PutExtChar (Standard_OStream& OS, const Standard_ExtCharacter theValue); + + Standard_EXPORT static Standard_OStream& PutBools (Standard_OStream& OS, + const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3); + + Standard_EXPORT static Standard_OStream& PutBools (Standard_OStream& OS, + const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3, + const Standard_Boolean theValue4, const Standard_Boolean theValue5, const Standard_Boolean theValue6, + const Standard_Boolean theValue7); Standard_EXPORT static Standard_IStream& GetReal (Standard_IStream& IS, Standard_Real& theValue); diff --git a/src/BinTools/BinTools_IStream.cxx b/src/BinTools/BinTools_IStream.cxx new file mode 100644 index 0000000000..fe684037ba --- /dev/null +++ b/src/BinTools/BinTools_IStream.cxx @@ -0,0 +1,257 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +//======================================================================= +//function : BinTools_IStream +//purpose : +//======================================================================= +BinTools_IStream::BinTools_IStream (Standard_IStream& theStream) + : myStream (&theStream), myPosition (theStream.tellg()), myLastType (BinTools_ObjectType_Unknown) +{} + +//======================================================================= +//function : ReadType +//purpose : +//======================================================================= +BinTools_ObjectType BinTools_IStream::ReadType() +{ + myLastType = BinTools_ObjectType (myStream->get()); + myPosition++; + return myLastType; +} + +//======================================================================= +//function : IsReference +//purpose : +//======================================================================= +Standard_Boolean BinTools_IStream::IsReference() +{ + return myLastType == BinTools_ObjectType_Reference8 || myLastType == BinTools_ObjectType_Reference16 || + myLastType == BinTools_ObjectType_Reference32 || myLastType == BinTools_ObjectType_Reference64; +} + +//======================================================================= +//function : ReadReference +//purpose : +//======================================================================= +uint64_t BinTools_IStream::ReadReference() +{ + uint64_t aDelta = 0; + uint64_t aCurrentPos = uint64_t (myStream->tellg()); + switch (myLastType) + { + case BinTools_ObjectType_Reference8: + aDelta = uint64_t (myStream->get()); + myPosition++; + break; + case BinTools_ObjectType_Reference16: + { + uint16_t aDelta16 = 0; + myStream->read ((char*)&aDelta16, sizeof (uint16_t)); + myPosition += 2; +#if DO_INVERSE + aDelta16 = (0 | ((aDelta16 & 0x00FF) << 8) + | ((aDelta16 & 0xFF00) >> 8)); +#endif + aDelta = uint64_t (aDelta16); + break; + } + case BinTools_ObjectType_Reference32: + { + uint32_t aDelta32 = 0; + myStream->read ((char*)&aDelta32, sizeof (uint32_t)); + myPosition += 4; +#if DO_INVERSE + aDelta32 = (0 | ((aDelta32 & 0x000000ff) << 24) + | ((aDelta32 & 0x0000ff00) << 8) + | ((aDelta32 & 0x00ff0000) >> 8) + | ((aDelta32 >> 24) & 0x000000ff)); +#endif + aDelta = uint64_t (aDelta32); + break; + } + case BinTools_ObjectType_Reference64: + myStream->read ((char*)&aDelta, sizeof (uint64_t)); + myPosition += 8; +#if DO_INVERSE + aDelta = InverseUint64 (aDelta); +#endif + break; + default: + break; + } + if (aDelta == 0) + { + Standard_SStream aMsg; + aMsg << "BinTools_Position::ReadReference: invalid reference " << (char)myLastType << std::endl; + throw Standard_Failure (aMsg.str().c_str()); + } + return aCurrentPos - aDelta - 1; // add a type-byte +} + +//======================================================================= +//function : GoTo +//purpose : +//======================================================================= +void BinTools_IStream::GoTo (const uint64_t& thePosition) +{ + myStream->seekg (std::streampos (thePosition)); + myPosition = thePosition; +} + +//======================================================================= +//function : ShapeType +//purpose : +//======================================================================= +TopAbs_ShapeEnum BinTools_IStream::ShapeType() +{ + return TopAbs_ShapeEnum ((Standard_Byte (myLastType) - Standard_Byte (BinTools_ObjectType_EndShape) - 1) >> 2); +} + +//======================================================================= +//function : ShapeOrientation +//purpose : +//======================================================================= +TopAbs_Orientation BinTools_IStream::ShapeOrientation() +{ + return TopAbs_Orientation ((Standard_Byte (myLastType) - Standard_Byte (BinTools_ObjectType_EndShape) - 1) & 3); +} + +//======================================================================= +//function : operator bool +//purpose : +//======================================================================= +BinTools_IStream::operator bool() const +{ + return myStream->operator bool(); +} + +//======================================================================= +//function : operator << +//purpose : +//======================================================================= +BinTools_IStream& BinTools_IStream::operator >> (Standard_Real& theValue) +{ + if (!myStream->read ((char*)&theValue, sizeof (Standard_Real))) + throw Storage_StreamTypeMismatchError(); + myPosition += sizeof (Standard_Real); +#if DO_INVERSE + theValue = InverseReal (theValue); +#endif + return *this; +} + +//======================================================================= +//function : operator << +//purpose : +//======================================================================= +BinTools_IStream& BinTools_IStream::operator >> (Standard_Integer& theValue) +{ + if (!myStream->read ((char*)&theValue, sizeof (Standard_Integer))) + throw Storage_StreamTypeMismatchError(); + myPosition += sizeof (Standard_Integer); +#if DO_INVERSE + theValue = InverseInt (theValue); +#endif + return *this; +} + +//======================================================================= +//function : operator << +//purpose : +//======================================================================= +BinTools_IStream& BinTools_IStream::operator >> (gp_Pnt& theValue) +{ + Standard_Real aValue; + for (int aCoord = 1; aCoord <= 3; aCoord++) + { + if (!myStream->read ((char*)&aValue, sizeof (Standard_Real))) + throw Storage_StreamTypeMismatchError(); +#if DO_INVERSE + aValue = InverseReal (aValue); +#endif + theValue.SetCoord (aCoord, aValue); + } + myPosition += 3 * sizeof (Standard_Real); + return *this; +} + +//======================================================================= +//function : operator << +//purpose : +//======================================================================= +BinTools_IStream& BinTools_IStream::operator >> (Standard_Byte& theValue) +{ + myStream->read ((char*)&theValue, sizeof (Standard_Byte)); + myPosition += sizeof (Standard_Byte); + return *this; +} + +//======================================================================= +//function : operator << +//purpose : +//======================================================================= +BinTools_IStream& BinTools_IStream::operator >> (Standard_ShortReal& theValue) +{ + myStream->read ((char*)&theValue, sizeof (Standard_ShortReal)); + myPosition += sizeof (Standard_ShortReal); + return *this; +} + +//======================================================================= +//function : operator << +//purpose : +//======================================================================= +BinTools_IStream& BinTools_IStream::operator >> (gp_Trsf& theValue) +{ + Standard_Real aV1[3], aV2[3], aV3[3], aV[3]; + *this >> aV1[0] >> aV1[1] >> aV1[2] >> aV[0]; + *this >> aV2[0] >> aV2[1] >> aV2[2] >> aV[1]; + *this >> aV3[0] >> aV3[1] >> aV3[2] >> aV[2]; + theValue.SetValues (aV1[0], aV1[1], aV1[2], aV[0], + aV2[0], aV2[1], aV2[2], aV[1], + aV3[0], aV3[1], aV3[2], aV[2]); + return *this; +} + +//======================================================================= +//function : ReadBools +//purpose : +//======================================================================= +void BinTools_IStream::ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3) +{ + Standard_Byte aByte = ReadByte(); + theBool1 = (aByte & 1) == 1; + theBool2 = (aByte & 2) == 2; + theBool3 = (aByte & 4) == 4; +} + +//======================================================================= +//function : ReadBools +//purpose : +//======================================================================= +void BinTools_IStream::ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3, + Standard_Boolean& theBool4, Standard_Boolean& theBool5, Standard_Boolean& theBool6, Standard_Boolean& theBool7) +{ + Standard_Byte aByte = ReadByte(); + theBool1 = (aByte & 1) == 1; + theBool2 = (aByte & 2) == 2; + theBool3 = (aByte & 4) == 4; + theBool4 = (aByte & 8) == 8; + theBool5 = (aByte & 16) == 16; + theBool6 = (aByte & 32) == 32; + theBool7 = (aByte & 64) == 64; +} diff --git a/src/BinTools/BinTools_IStream.hxx b/src/BinTools/BinTools_IStream.hxx new file mode 100644 index 0000000000..319005b3f6 --- /dev/null +++ b/src/BinTools/BinTools_IStream.hxx @@ -0,0 +1,90 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BinTools_IStream_HeaderFile +#define _BinTools_IStream_HeaderFile + +#include +#include +#include +#include +#include + +//! Substitution of IStream for shape reader for fast management of position in the file (get and go) +//! and operation on all reading types. +class BinTools_IStream +{ +public: + + //! Creates IStream using the current stream IStream. + Standard_EXPORT BinTools_IStream (Standard_IStream& theStream); + + //! Reads and returns the type. + Standard_EXPORT BinTools_ObjectType ReadType(); + //! Returns the last read type. + Standard_EXPORT const BinTools_ObjectType& LastType() { return myLastType; } + //! Returns the shape type by the last retrieved type. + Standard_EXPORT TopAbs_ShapeEnum ShapeType(); + //! Returns the shape orientation by the last retrieved type. + Standard_EXPORT TopAbs_Orientation ShapeOrientation(); + + //! Returns the current position in the stream. + Standard_EXPORT uint64_t Position() { return myPosition; } + //! Moves the current stream position to the given one. + Standard_EXPORT void GoTo (const uint64_t& thePosition); + + //! Returns true if the last restored type is one of a reference + Standard_EXPORT Standard_Boolean IsReference(); + //! Reads a reference IStream using the last restored type. + Standard_EXPORT uint64_t ReadReference(); + //! Returns the original IStream. + Standard_EXPORT Standard_IStream& Stream() { return *myStream; } + //! Makes up to date the myPosition because myStream was used outside and position is changed. + Standard_EXPORT void UpdatePosition() { myPosition = uint64_t (myStream->tellg()); } + + //! Returns false if stream reading is failed. + Standard_EXPORT operator bool() const; + //! Reads real value from the stream. + Standard_EXPORT Standard_Real ReadReal() { Standard_Real aValue; *this >> aValue; return aValue; } + Standard_EXPORT BinTools_IStream& operator >> (Standard_Real& theValue); + //! Reads integer value from the stream. + Standard_EXPORT Standard_Integer ReadInteger() { Standard_Integer aValue; *this >> aValue; return aValue; } + Standard_EXPORT BinTools_IStream& operator >> (Standard_Integer& theValue); + //! Reads point coordinates value from the stream. + Standard_EXPORT gp_Pnt ReadPnt() { gp_Pnt aValue; *this >> aValue; return aValue; } + Standard_EXPORT BinTools_IStream& operator >> (gp_Pnt& theValue); + //! Reads byte value from the stream. + Standard_EXPORT Standard_Byte ReadByte() { Standard_Byte aValue; *this >> aValue; return aValue; } + Standard_EXPORT BinTools_IStream& operator >> (Standard_Byte& theValue); + //! Reads boolean value from the stream (stored as one byte). + Standard_EXPORT Standard_Boolean ReadBool() { return ReadByte() != 0; } + Standard_EXPORT BinTools_IStream& operator >> (Standard_Boolean& theValue) { theValue = ReadByte() != 0; return *this; } + //! Reads short real value from the stream. + Standard_EXPORT Standard_ShortReal ReadShortReal() { Standard_ShortReal aValue; *this >> aValue; return aValue; } + Standard_EXPORT BinTools_IStream& operator >> (Standard_ShortReal& theValue); + //! Reads transformation value from the stream. + Standard_EXPORT BinTools_IStream& operator >> (gp_Trsf& theValue); + //! Reads 3 boolean values from one byte + Standard_EXPORT void ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3); + //! Reads 7 boolean values from one byte + Standard_EXPORT void ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3, + Standard_Boolean& theBool4, Standard_Boolean& theBool5, Standard_Boolean& theBool6, Standard_Boolean& theBool7); + + +private: + Standard_IStream* myStream; ///< pointer to the stream + uint64_t myPosition; ///< equivalent to tellg returned value for fast access + BinTools_ObjectType myLastType; ///< last type that was read +}; + +#endif // _BinTools_IStream_HeaderFile diff --git a/src/BinTools/BinTools_LocationSet.cxx b/src/BinTools/BinTools_LocationSet.cxx index c269197602..3f16450a14 100644 --- a/src/BinTools/BinTools_LocationSet.cxx +++ b/src/BinTools/BinTools_LocationSet.cxx @@ -57,7 +57,7 @@ static Standard_IStream& operator >>(Standard_IStream& IS, gp_Trsf& T) //function : operator << (gp_Trsf& T) //purpose : //======================================================================= -static Standard_OStream& operator <<(Standard_OStream& OS,const gp_Trsf& T) +Standard_OStream& operator <<(Standard_OStream& OS,const gp_Trsf& T) { gp_XYZ V = T.TranslationPart(); gp_Mat M = T.VectorialPart(); diff --git a/src/BinTools/BinTools_LocationSet.hxx b/src/BinTools/BinTools_LocationSet.hxx index d28d4aebbb..b00d598f05 100644 --- a/src/BinTools/BinTools_LocationSet.hxx +++ b/src/BinTools/BinTools_LocationSet.hxx @@ -27,6 +27,8 @@ class Standard_OutOfRange; class TopLoc_Location; +//! Operator for writing transformation into the stream +Standard_OStream& operator << (Standard_OStream& OS, const gp_Trsf& T); //! The class LocationSet stores a set of location in //! a relocatable state. @@ -68,9 +70,6 @@ public: //! is first cleared. Standard_EXPORT void Read (Standard_IStream& IS); - - - protected: diff --git a/src/BinTools/BinTools_ObjectType.hxx b/src/BinTools/BinTools_ObjectType.hxx new file mode 100644 index 0000000000..5db8177682 --- /dev/null +++ b/src/BinTools/BinTools_ObjectType.hxx @@ -0,0 +1,46 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BinTools_ObjectType_HeaderFile +#define _BinTools_ObjectType_HeaderFile + +//! Enumeration defining objects identifiers in the shape read/write format. +enum BinTools_ObjectType +{ + BinTools_ObjectType_Unknown = 0, + BinTools_ObjectType_Reference8, //!< 8-bits reference + BinTools_ObjectType_Reference16, //!< 16-bits reference + BinTools_ObjectType_Reference32, //!< 32-bits reference + BinTools_ObjectType_Reference64, //!< 64-bits reference + BinTools_ObjectType_Location, + BinTools_ObjectType_SimpleLocation, + BinTools_ObjectType_EmptyLocation, + BinTools_ObjectType_LocationEnd, + BinTools_ObjectType_Curve, + BinTools_ObjectType_EmptyCurve, + BinTools_ObjectType_Curve2d, + BinTools_ObjectType_EmptyCurve2d, + BinTools_ObjectType_Surface, + BinTools_ObjectType_EmptySurface, + BinTools_ObjectType_Polygon3d, + BinTools_ObjectType_EmptyPolygon3d, + BinTools_ObjectType_PolygonOnTriangulation, + BinTools_ObjectType_EmptyPolygonOnTriangulation, + BinTools_ObjectType_Triangulation, + BinTools_ObjectType_EmptyTriangulation, + BinTools_ObjectType_EmptyShape = 198, //!< identifier of the null shape + BinTools_ObjectType_EndShape = 199, //!< identifier of the shape record end + // here is the space for TopAbs_ShapeEnum+Orientation types +}; + +#endif // _BinTools_ObjectType_HeaderFile diff --git a/src/BinTools/BinTools_Position.cxx b/src/BinTools/BinTools_Position.cxx new file mode 100644 index 0000000000..ef9e8034f1 --- /dev/null +++ b/src/BinTools/BinTools_Position.cxx @@ -0,0 +1,86 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +//======================================================================= +//function : BinTools_Position +//purpose : +//======================================================================= +BinTools_Position::BinTools_Position (Standard_OStream& theStream) : + myOStream (&theStream), myPosition (theStream.tellp()) +{} + +//======================================================================= +//function : WriteReference +//purpose : +//======================================================================= +void BinTools_Position::WriteReference() const +{ + uint64_t aDelta = uint64_t (myOStream->tellp()) - myPosition; + if (aDelta <= 0xFF) + { + *myOStream << (Standard_Byte)BinTools_ObjectType_Reference8; + *myOStream << (Standard_Byte)aDelta; + } + else if (aDelta <= 0xFFFF) + { + *myOStream << (Standard_Byte)BinTools_ObjectType_Reference16; + uint16_t aDelta16 = uint16_t (aDelta); +#if DO_INVERSE + aDelta16 = (0 | ((aDelta16 & 0x00FF) << 8) + | ((aDelta16 & 0xFF00) >> 8)); +#endif + myOStream->write ((char*)&aDelta16, sizeof (uint16_t)); + } + else if (aDelta <= 0xFFFFFFFF) + { + *myOStream << (Standard_Byte)BinTools_ObjectType_Reference32; + uint32_t aDelta32 = uint32_t (aDelta); +#if DO_INVERSE + aDelta32 = (0 | ((aDelta32 & 0x000000ff) << 24) + | ((aDelta32 & 0x0000ff00) << 8) + | ((aDelta32 & 0x00ff0000) >> 8) + | ((aDelta32 >> 24) & 0x000000ff) ); +#endif + myOStream->write ((char*)&aDelta32, sizeof (uint32_t)); + } + else + { + *myOStream << (Standard_Byte)BinTools_ObjectType_Reference64; +#if DO_INVERSE + aDelta = InverseUint64 (aDelta); +#endif + myOStream->write ((char*)&aDelta, sizeof (uint64_t)); + } +} + +//======================================================================= +//function : WriteShape +//purpose : +//======================================================================= +void BinTools_Position::WriteShape (const TopAbs_ShapeEnum& theType, const TopAbs_Orientation& theOrientation) const +{ + Standard_Byte aType = Standard_Byte (BinTools_ObjectType_EndShape) + 1 + // taking into account that orientation <= 3 + (Standard_Byte (theType) << 2) + Standard_Byte (theOrientation); // and type <= 8 + *myOStream << (Standard_Byte)aType; +} + +//======================================================================= +//function : WriteObject +//purpose : +//======================================================================= +void BinTools_Position::WriteObject(const BinTools_ObjectType& theType) const +{ + *myOStream << (Standard_Byte)theType; +} diff --git a/src/BinTools/BinTools_Position.hxx b/src/BinTools/BinTools_Position.hxx new file mode 100644 index 0000000000..bb0678ea0e --- /dev/null +++ b/src/BinTools/BinTools_Position.hxx @@ -0,0 +1,45 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BinTools_Position_HeaderFile +#define _BinTools_Position_HeaderFile + +#include +#include + +#include +#include + +//! Stores and manipulates position in the stream. +class BinTools_Position +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Creates position using the current stream position. + Standard_EXPORT BinTools_Position (Standard_OStream& theStream); + + //! Writes a reference to my position into the stream + Standard_EXPORT void WriteReference() const; + //! Writes an identifier of shape type and orientation into the stream. + Standard_EXPORT void WriteShape (const TopAbs_ShapeEnum& theType, const TopAbs_Orientation& theOrientation) const; + //! Writes an identifier of an object into the stream. + Standard_EXPORT void WriteObject (const BinTools_ObjectType& theType) const; + +private: + Standard_OStream* myOStream; + std::streampos myPosition; +}; + +#endif // _BinTools_Position_HeaderFile diff --git a/src/BinTools/BinTools_ShapeReader.cxx b/src/BinTools/BinTools_ShapeReader.cxx new file mode 100644 index 0000000000..0119a3d489 --- /dev/null +++ b/src/BinTools/BinTools_ShapeReader.cxx @@ -0,0 +1,591 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +//function : BinTools_ShapeReader +//purpose : +//======================================================================= +BinTools_ShapeReader::BinTools_ShapeReader() +{} + +//======================================================================= +//function : ~BinTools_ShapeReader +//purpose : +//======================================================================= +BinTools_ShapeReader::~BinTools_ShapeReader() +{} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void BinTools_ShapeReader::Clear() +{ + BinTools_ShapeSetBase::Clear(); + myShapePos.Clear(); + myLocationPos.Clear(); + myCurvePos.Clear(); + myCurve2dPos.Clear(); + mySurfacePos.Clear(); + myPolygon3dPos.Clear(); + myPolygonPos.Clear(); + myTriangulationPos.Clear(); +} + +//======================================================================= +//function : Read +//purpose : +//======================================================================= +void BinTools_ShapeReader::Read (Standard_IStream& theStream, TopoDS_Shape& theShape) +{ + BinTools_IStream aStream(theStream); + theShape = ReadShape(aStream); +} + +//======================================================================= +//function : ReadShape +//purpose : +//======================================================================= +TopoDS_Shape BinTools_ShapeReader::ReadShape (BinTools_IStream& theStream) +{ + TopoDS_Shape aResult; + uint64_t aPosition = theStream.Position(); + const BinTools_ObjectType& aType = theStream.ReadType(); + if (aType == BinTools_ObjectType_EmptyShape || aType == BinTools_ObjectType_EndShape) + return aResult; + + if (theStream.IsReference()) + { + uint64_t aRef = theStream.ReadReference(); + const TopoDS_Shape* aFound = myShapePos.Seek(aRef); + if (aFound) // the shape is already retrieved, just add location + { + aResult = *aFound; + } + else + { + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + aResult = ReadShape (theStream); + theStream.GoTo (aCurrent); // returns to the current position + } + aResult.Location (*ReadLocation (theStream)); + aResult.Orientation (TopAbs_Orientation (theStream.ReadByte())); + return aResult; + } + // read the shape + TopAbs_ShapeEnum aShapeType = theStream.ShapeType(); + TopAbs_Orientation aShapeOrientation = theStream.ShapeOrientation(); + const TopLoc_Location* aShapeLocation = ReadLocation (theStream); + Standard_Real aTol; + static BRep_Builder aBuilder; + try { + OCC_CATCH_SIGNALS + switch (aShapeType) { + case TopAbs_VERTEX: + { + TopoDS_Vertex& aV = TopoDS::Vertex (aResult); + // Read the point geometry + theStream >> aTol; + gp_Pnt aPnt = theStream.ReadPnt(); + aBuilder.MakeVertex (aV, aPnt, aTol); + Handle(BRep_TVertex) aTV = Handle(BRep_TVertex)::DownCast (aV.TShape()); + BRep_ListOfPointRepresentation& aLpr = aTV->ChangePoints(); + static TopLoc_Location anEmptyLoc; + while (theStream) { + Standard_Byte aPrsType = theStream.ReadByte(); + if (aPrsType == 0) // end of the cycle + break; + Standard_Real aParam = theStream.ReadReal(); + Handle(BRep_PointRepresentation) aPR; + switch (aPrsType) { + case 1: + { + Handle(Geom_Curve) aCurve = ReadCurve (theStream); + if (!aCurve.IsNull()) + aPR = new BRep_PointOnCurve (aParam, aCurve, anEmptyLoc); + break; + } + case 2: + { + Handle(Geom2d_Curve) aCurve2d = ReadCurve2d (theStream); + Handle(Geom_Surface) aSurface = ReadSurface (theStream); + if (!aCurve2d.IsNull() && aSurface.IsNull()) + aPR = new BRep_PointOnCurveOnSurface (aParam, aCurve2d, aSurface, anEmptyLoc); + break; + } + case 3: + { + Standard_Real aParam2 = theStream.ReadReal(); + Handle(Geom_Surface) aSurface = ReadSurface (theStream); + if (!aSurface.IsNull()) + aPR = new BRep_PointOnSurface (aParam, aParam2, aSurface, anEmptyLoc); + break; + } + default: + { + Standard_SStream aMsg; + aMsg << "BinTools_ShapeReader::Read: UnExpected BRep_PointRepresentation = " << aPrsType << std::endl; + throw Standard_Failure (aMsg.str().c_str()); + } + } + const TopLoc_Location* aPRLoc = ReadLocation (theStream); + if (!aPR.IsNull()) + { + aPR->Location (*aPRLoc); + aLpr.Append (aPR); + } + } + break; + } + case TopAbs_EDGE: + { + TopoDS_Edge& aE = TopoDS::Edge (aResult); + aBuilder.MakeEdge(aE); + // Read the curve geometry + theStream >> aTol; + Standard_Boolean aSameParameter, aSameRange, aDegenerated; + theStream.ReadBools (aSameParameter, aSameRange, aDegenerated); + aBuilder.SameParameter (aE, aSameParameter); + aBuilder.SameRange (aE, aSameRange); + aBuilder.Degenerated (aE, aDegenerated); + Standard_Real aFirst, aLast; + while (theStream) { + Standard_Byte aPrsType = theStream.ReadByte(); //{0|1|2|3|4|5|6|7} + if (aPrsType == 0) + break; + switch (aPrsType) + { + case 1: // -1- Curve 3D + { + Handle(Geom_Curve) aCurve = ReadCurve (theStream); + const TopLoc_Location* aLoc = ReadLocation (theStream); + theStream >> aFirst; + theStream >> aLast; + if (!aCurve.IsNull()) + { + aBuilder.UpdateEdge (aE, aCurve, *aLoc, aTol); + aBuilder.Range (aE, aFirst, aLast, Standard_True); + } + break; + } + case 2: // -2- Curve on surf + case 3: // -3- Curve on closed surf + { + Standard_Boolean aClosed = (aPrsType == 3); + Handle(Geom2d_Curve) aCurve2d_2, aCurve2d_1 = ReadCurve2d (theStream); + GeomAbs_Shape aReg = GeomAbs_C0; + if (aClosed) { + aCurve2d_2 = ReadCurve2d (theStream); + aReg = (GeomAbs_Shape)theStream.ReadByte(); + } + Handle(Geom_Surface) aSurface = ReadSurface (theStream); + const TopLoc_Location* aLoc = ReadLocation (theStream); + // range + theStream >> aFirst; + theStream >> aLast; + if (!aCurve2d_1.IsNull() && (!aClosed || !aCurve2d_2.IsNull()) && !aSurface.IsNull()) + { + if (aClosed) + { + aBuilder.UpdateEdge (aE, aCurve2d_1, aCurve2d_2, aSurface, *aLoc, aTol); + aBuilder.Continuity (aE, aSurface, aSurface, *aLoc, *aLoc, aReg); + } + else + aBuilder.UpdateEdge (aE, aCurve2d_1, aSurface, *aLoc, aTol); + aBuilder.Range (aE, aSurface, *aLoc, aFirst, aLast); + } + break; + } + case 4: // -4- Regularity + { + GeomAbs_Shape aReg = (GeomAbs_Shape)theStream.ReadByte(); + Handle(Geom_Surface) aSurface1 = ReadSurface (theStream); + const TopLoc_Location* aLoc1 = ReadLocation (theStream); + Handle(Geom_Surface) aSurface2 = ReadSurface (theStream); + const TopLoc_Location* aLoc2 = ReadLocation (theStream); + if (!aSurface1.IsNull() && !aSurface2.IsNull()) + aBuilder.Continuity (aE, aSurface1, aSurface2, *aLoc1, *aLoc2, aReg); + break; + } + case 5: // -5- Polygon3D + { + Handle(Poly_Polygon3D) aPolygon = ReadPolygon3d (theStream); + const TopLoc_Location* aLoc = ReadLocation (theStream); + aBuilder.UpdateEdge (aE, aPolygon, *aLoc); + break; + } + case 6: // -6- Polygon on triangulation + case 7: // -7- Polygon on closed triangulation + { + Standard_Boolean aClosed = (aPrsType == 7); + Handle(Poly_PolygonOnTriangulation) aPoly2, aPoly1 = ReadPolygon (theStream); + if (aClosed) + aPoly2 = ReadPolygon (theStream); + Handle(Poly_Triangulation) aTriangulation = ReadTriangulation (theStream); + const TopLoc_Location* aLoc = ReadLocation (theStream); + if (aClosed) + aBuilder.UpdateEdge (aE, aPoly1, aPoly2, aTriangulation, *aLoc); + else + aBuilder.UpdateEdge (aE, aPoly1, aTriangulation, *aLoc); + // range + break; + } + default: + { + Standard_SStream aMsg; + aMsg << "Unexpected Curve Representation =" << aPrsType << std::endl; + throw Standard_Failure (aMsg.str().c_str()); + } + + } + } + break; + } + case TopAbs_WIRE: + aBuilder.MakeWire (TopoDS::Wire (aResult)); + break; + case TopAbs_FACE: + { + TopoDS_Face& aF = TopoDS::Face (aResult); + aBuilder.MakeFace (aF); + Standard_Boolean aNatRes = theStream.ReadBool(); + theStream >> aTol; + Handle(Geom_Surface) aSurface = ReadSurface (theStream); + const TopLoc_Location* aLoc = ReadLocation (theStream); + aBuilder.UpdateFace (aF, aSurface, *aLoc, aTol); + aBuilder.NaturalRestriction (aF, aNatRes); + if (theStream.ReadByte() == 2) // triangulation + aBuilder.UpdateFace (aF, ReadTriangulation (theStream)); + break; + } + case TopAbs_SHELL: + aBuilder.MakeShell (TopoDS::Shell (aResult)); + break; + case TopAbs_SOLID: + aBuilder.MakeSolid (TopoDS::Solid (aResult)); + break; + case TopAbs_COMPSOLID: + aBuilder.MakeCompSolid (TopoDS::CompSolid (aResult)); + break; + case TopAbs_COMPOUND: + aBuilder.MakeCompound (TopoDS::Compound (aResult)); + break; + default: + { + Standard_SStream aMsg; + aMsg << "Unexpected topology type = " << aShapeType << std::endl; + throw Standard_Failure (aMsg.str().c_str()); + break; + } + } + } + catch (Standard_Failure const& anException) + { + Standard_SStream aMsg; + aMsg << "EXCEPTION in BinTools_ShapeReader::Read" << std::endl; + aMsg << anException << std::endl; + throw Standard_Failure (aMsg.str().c_str()); + } + // read flags and subs + Standard_Boolean aFree, aMod, aChecked, anOrient, aClosed, anInf, aConv; + theStream.ReadBools (aFree, aMod, aChecked, anOrient, aClosed, anInf, aConv); + // sub-shapes + for(TopoDS_Shape aSub = ReadShape (theStream); !aSub.IsNull(); aSub = ReadShape (theStream)) + aBuilder.Add (aResult, aSub); + aResult.Free (aFree); + aResult.Modified (aMod); + aResult.Checked (aChecked); + aResult.Orientable (anOrient); + aResult.Closed (aClosed); + aResult.Infinite (anInf); + aResult.Convex (aConv); + myShapePos.Bind (aPosition, aResult); + aResult.Orientation (aShapeOrientation); + aResult.Location (*aShapeLocation); + return aResult; +} + +//======================================================================= +//function : ReadLocation +//purpose : +//======================================================================= +const TopLoc_Location* BinTools_ShapeReader::ReadLocation (BinTools_IStream& theStream) +{ + static const TopLoc_Location* anEmptyLoc = new TopLoc_Location; + + uint64_t aPosition = theStream.Position(); + const BinTools_ObjectType& aType = theStream.ReadType(); + if (aType == BinTools_ObjectType_EmptyLocation || aType == BinTools_ObjectType_LocationEnd) + return anEmptyLoc; + if (theStream.IsReference()) + { + uint64_t aRef = theStream.ReadReference(); + const TopLoc_Location* aFound = myLocationPos.Seek (aRef); + if (aFound) // the location is already retrieved + return aFound; + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + const TopLoc_Location* aResult = ReadLocation (theStream); + theStream.GoTo (aCurrent); // returns to the current position + return aResult; + } + // read the location directly from the stream + TopLoc_Location aLoc; + if (aType == BinTools_ObjectType_SimpleLocation) + { + gp_Trsf aTrsf; + theStream >> aTrsf; + aLoc = aTrsf; + } + else if (aType == BinTools_ObjectType_Location) + { + for(const TopLoc_Location* aNextLoc = ReadLocation (theStream); !aNextLoc->IsIdentity(); + aNextLoc = ReadLocation (theStream)) + aLoc = aNextLoc->Powered (theStream.ReadInteger()) * aLoc; + } + myLocationPos.Bind (aPosition, aLoc); + return myLocationPos.Seek (aPosition); +} + +//======================================================================= +//function : ReadCurve +//purpose : +//======================================================================= +Handle(Geom_Curve) BinTools_ShapeReader::ReadCurve (BinTools_IStream& theStream) +{ + Handle(Geom_Curve) aResult; + uint64_t aPosition = theStream.Position(); + theStream.ReadType(); + if (theStream.IsReference()) + { // get by reference + uint64_t aRef = theStream.ReadReference(); + const Handle(Geom_Curve)* aFound = myCurvePos.Seek (aRef); + if (aFound) // the location is already retrieved + return *aFound; + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + aResult = ReadCurve (theStream); + theStream.GoTo (aCurrent); // returns to the current position + } + else if (theStream.LastType() == BinTools_ObjectType_Curve) + { // read from the stream + BinTools_CurveSet::ReadCurve (theStream.Stream(), aResult); + theStream.UpdatePosition(); + myCurvePos.Bind (aPosition, aResult); + } + return aResult; +} + +//======================================================================= +//function : ReadCurve2d +//purpose : +//======================================================================= +Handle(Geom2d_Curve) BinTools_ShapeReader::ReadCurve2d (BinTools_IStream& theStream) +{ + Handle(Geom2d_Curve) aResult; + uint64_t aPosition = theStream.Position(); + theStream.ReadType(); + if (theStream.IsReference()) + { // get by reference + uint64_t aRef = theStream.ReadReference(); + const Handle(Geom2d_Curve)* aFound = myCurve2dPos.Seek (aRef); + if (aFound) // the location is already retrieved + return *aFound; + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + aResult = ReadCurve2d (theStream); + theStream.GoTo (aCurrent); // returns to the current position + } + else if (theStream.LastType() == BinTools_ObjectType_Curve2d) + { // read from the stream + BinTools_Curve2dSet::ReadCurve2d (theStream.Stream(), aResult); + theStream.UpdatePosition(); + myCurve2dPos.Bind (aPosition, aResult); + } + return aResult; +} + +//======================================================================= +//function : ReadSurface +//purpose : +//======================================================================= +Handle(Geom_Surface) BinTools_ShapeReader::ReadSurface (BinTools_IStream& theStream) +{ + Handle(Geom_Surface) aResult; + uint64_t aPosition = theStream.Position(); + theStream.ReadType(); + if (theStream.IsReference()) + { // get by reference + uint64_t aRef = theStream.ReadReference(); + const Handle(Geom_Surface)* aFound = mySurfacePos.Seek (aRef); + if (aFound) // the location is already retrieved + return *aFound; + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + aResult = ReadSurface (theStream); + theStream.GoTo (aCurrent); // returns to the current position + } + else if (theStream.LastType() == BinTools_ObjectType_Surface) + { // read from the stream + BinTools_SurfaceSet::ReadSurface (theStream.Stream(), aResult); + theStream.UpdatePosition(); + mySurfacePos.Bind (aPosition, aResult); + } + return aResult; +} + +//======================================================================= +//function : ReadPolygon3d +//purpose : +//======================================================================= +Handle(Poly_Polygon3D) BinTools_ShapeReader::ReadPolygon3d (BinTools_IStream& theStream) +{ + Handle(Poly_Polygon3D) aResult; + uint64_t aPosition = theStream.Position(); + theStream.ReadType(); + if (theStream.IsReference()) + { // get by reference + uint64_t aRef = theStream.ReadReference(); + const Handle(Poly_Polygon3D)* aFound = myPolygon3dPos.Seek (aRef); + if (aFound) // the location is already retrieved + return *aFound; + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + aResult = ReadPolygon3d (theStream); + theStream.GoTo (aCurrent); // returns to the current position + } + else if (theStream.LastType() == BinTools_ObjectType_Polygon3d) + { // read from the stream + Standard_Integer aNbNodes = theStream.ReadInteger(); + Standard_Boolean aHasParameters = theStream.ReadBool(); + aResult = new Poly_Polygon3D (aNbNodes, aHasParameters); + aResult->Deflection (theStream.ReadReal()); + TColgp_Array1OfPnt& aNodes = aResult->ChangeNodes(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + theStream >> aNodes.ChangeValue (aNodeIter); + if (aHasParameters) + { + TColStd_Array1OfReal& aParam = aResult->ChangeParameters(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + theStream >> aParam.ChangeValue (aNodeIter); + } + myPolygon3dPos.Bind (aPosition, aResult); + } + return aResult; +} + +//======================================================================= +//function : ReadPolygon +//purpose : +//======================================================================= +Handle(Poly_PolygonOnTriangulation) BinTools_ShapeReader::ReadPolygon (BinTools_IStream& theStream) +{ + Handle(Poly_PolygonOnTriangulation) aResult; + uint64_t aPosition = theStream.Position(); + theStream.ReadType(); + if (theStream.IsReference()) + { // get by reference + uint64_t aRef = theStream.ReadReference(); + const Handle(Poly_PolygonOnTriangulation)* aFound = myPolygonPos.Seek (aRef); + if (aFound) // the location is already retrieved + return *aFound; + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + aResult = ReadPolygon (theStream); + theStream.GoTo (aCurrent); // returns to the current position + } + else if (theStream.LastType() == BinTools_ObjectType_PolygonOnTriangulation) + { // read from the stream + Standard_Integer aNbNodes = theStream.ReadInteger(); + aResult = new Poly_PolygonOnTriangulation (aNbNodes, Standard_False); + TColStd_Array1OfInteger& aNodes = aResult->ChangeNodes(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + theStream >> aNodes.ChangeValue (aNodeIter); + aResult->Deflection (theStream.ReadReal()); + if (theStream.ReadBool()) + { + Handle(TColStd_HArray1OfReal) aParams = new TColStd_HArray1OfReal (1, aNbNodes); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + theStream >> aParams->ChangeValue (aNodeIter); + aResult->SetParameters (aParams); + } + myPolygonPos.Bind (aPosition, aResult); + } + return aResult; +} + +//======================================================================= +//function : ReadTriangulation +//purpose : +//======================================================================= +Handle(Poly_Triangulation) BinTools_ShapeReader::ReadTriangulation (BinTools_IStream& theStream) +{ + Handle(Poly_Triangulation) aResult; + uint64_t aPosition = theStream.Position(); + const BinTools_ObjectType& aType = theStream.ReadType(); + if (theStream.IsReference()) + { // get by reference + uint64_t aRef = theStream.ReadReference(); + const Handle(Poly_Triangulation)* aFound = myTriangulationPos.Seek (aRef); + if (aFound) // the location is already retrieved + return *aFound; + uint64_t aCurrent = theStream.Position(); + theStream.GoTo (aRef); // go to the referenced position + aResult = ReadTriangulation (theStream); + theStream.GoTo (aCurrent); // returns to the current position + } + else if (aType == BinTools_ObjectType_Triangulation) + { // read from the stream + Standard_Integer aNbNodes = theStream.ReadInteger(); + Standard_Integer aNbTriangles = theStream.ReadInteger(); + Standard_Boolean aHasUV = theStream.ReadBool(); + aResult = new Poly_Triangulation (aNbNodes, aNbTriangles, aHasUV); + aResult->Deflection (theStream.ReadReal()); + TColgp_Array1OfPnt& aNodes = aResult->ChangeNodes(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + theStream >> aNodes.ChangeValue (aNodeIter); + if (aHasUV) + { + TColgp_Array1OfPnt2d& aUVNodes = aResult->ChangeUVNodes(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + { + gp_XY& anUV = aUVNodes.ChangeValue (aNodeIter).ChangeCoord(); + theStream >> anUV.ChangeCoord (1); + theStream >> anUV.ChangeCoord (2); + } + } + // read the triangles + Poly_Array1OfTriangle& aTriangles = aResult->ChangeTriangles(); + for (Standard_Integer aTriIter = 1; aTriIter <= aNbTriangles; ++aTriIter) + { + Poly_Triangle& aTri = aTriangles.ChangeValue (aTriIter); + theStream >> aTri.ChangeValue (1); + theStream >> aTri.ChangeValue (2); + theStream >> aTri.ChangeValue (3); + } + myTriangulationPos.Bind (aPosition, aResult); + } + return aResult; +} diff --git a/src/BinTools/BinTools_ShapeReader.hxx b/src/BinTools/BinTools_ShapeReader.hxx new file mode 100644 index 0000000000..aab88614d9 --- /dev/null +++ b/src/BinTools/BinTools_ShapeReader.hxx @@ -0,0 +1,79 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BinTools_ShapeReader_HeaderFile +#define _BinTools_ShapeReader_HeaderFile + +#include +#include +#include + +class TopLoc_Location; +class Geom_Curve; +class Geom2d_Curve; +class Geom_Surface; +class Poly_Polygon3D; +class Poly_PolygonOnTriangulation; +class Poly_Triangulation; + + +//! Reads topology from IStream in binary format without grouping of objects by types +//! and using relative positions in a file as references. +class BinTools_ShapeReader : public BinTools_ShapeSetBase +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Initializes a shape reader. + Standard_EXPORT BinTools_ShapeReader(); + + Standard_EXPORT virtual ~BinTools_ShapeReader(); + + //! Clears the content of the set. + Standard_EXPORT virtual void Clear() override; + + //! Reads the shape from stream using previously restored shapes and objects by references. + Standard_EXPORT void Read (Standard_IStream& theStream, TopoDS_Shape& theShape) override; + + //! Reads location from the stream. + Standard_EXPORT const TopLoc_Location* ReadLocation (BinTools_IStream& theStream); + +private: + //! Reads the shape from stream using previously restored shapes and objects by references. + TopoDS_Shape ReadShape (BinTools_IStream& theStream); + //! Reads curve from the stream. + Handle(Geom_Curve) ReadCurve (BinTools_IStream& theStream); + //! Reads curve2d from the stream. + Handle(Geom2d_Curve) ReadCurve2d (BinTools_IStream& theStream); + //! Reads surface from the stream. + Handle(Geom_Surface) ReadSurface (BinTools_IStream& theStream); + //! Reads ploygon3d from the stream. + Handle(Poly_Polygon3D) ReadPolygon3d (BinTools_IStream& theStream); + //! Reads polygon on triangulation from the stream. + Handle(Poly_PolygonOnTriangulation) ReadPolygon (BinTools_IStream& theStream); + //! Reads triangulation from the stream. + Handle(Poly_Triangulation) ReadTriangulation (BinTools_IStream& theStream); + + /// position of the shape previously restored + NCollection_DataMap myShapePos; + NCollection_DataMap myLocationPos; + NCollection_DataMap myCurvePos; + NCollection_DataMap myCurve2dPos; + NCollection_DataMap mySurfacePos; + NCollection_DataMap myPolygon3dPos; + NCollection_DataMap myPolygonPos; + NCollection_DataMap myTriangulationPos; +}; + +#endif // _BinTools_ShapeReader_HeaderFile diff --git a/src/BinTools/BinTools_ShapeSet.cxx b/src/BinTools/BinTools_ShapeSet.cxx index bcb4aeb54c..0d396cca45 100644 --- a/src/BinTools/BinTools_ShapeSet.cxx +++ b/src/BinTools/BinTools_ShapeSet.cxx @@ -54,29 +54,13 @@ #include #include -//#define MDTV_DEB 1 -const char* Version_1 = "Open CASCADE Topology V1 (c)"; -const char* Version_2 = "Open CASCADE Topology V2 (c)"; -const char* Version_3 = "Open CASCADE Topology V3 (c)"; -//======================================================================= -//function : operator << (gp_Pnt) -//purpose : -//======================================================================= -static Standard_OStream& operator <<(Standard_OStream& OS, const gp_Pnt P) -{ - BinTools::PutReal(OS, P.X()); - BinTools::PutReal(OS, P.Y()); - BinTools::PutReal(OS, P.Z()); - return OS; -} //======================================================================= //function : BinTools_ShapeSet //purpose : //======================================================================= - -BinTools_ShapeSet::BinTools_ShapeSet(const Standard_Boolean isWithTriangles) - :myFormatNb(3), myWithTriangles(isWithTriangles) +BinTools_ShapeSet::BinTools_ShapeSet (const Standard_Boolean theWithTriangles) + : BinTools_ShapeSetBase (theWithTriangles) {} //======================================================================= @@ -87,24 +71,6 @@ BinTools_ShapeSet::BinTools_ShapeSet(const Standard_Boolean isWithTriangles) BinTools_ShapeSet::~BinTools_ShapeSet() {} -//======================================================================= -//function : SetFormatNb -//purpose : -//======================================================================= -void BinTools_ShapeSet::SetFormatNb(const Standard_Integer theFormatNb) -{ - myFormatNb = theFormatNb; -} - -//======================================================================= -//function : FormatNb -//purpose : -//======================================================================= -Standard_Integer BinTools_ShapeSet::FormatNb() const -{ - return myFormatNb; -} - //======================================================================= //function : Clear //purpose : @@ -132,19 +98,15 @@ Standard_Integer BinTools_ShapeSet::Add (const TopoDS_Shape& theShape) if (theShape.IsNull()) return 0; myLocations.Add(theShape.Location()); TopoDS_Shape aS2 = theShape; - aS2.Location(TopLoc_Location()); - - const int* anIndex = myShapes.Seek2(aS2); - if (!anIndex) - { - AddShape (aS2); + aS2.Location (TopLoc_Location()); + Standard_Integer anIndex = myShapes.FindIndex (aS2); + if (anIndex == 0) { + AddShape (aS2); for (TopoDS_Iterator its (aS2, Standard_False, Standard_False); its.More(); its.Next()) Add (its.Value()); - int aNewIndex = myShapes.Size() + 1; - myShapes.Bind(aNewIndex, aS2); - return aNewIndex; + anIndex = myShapes.Add (aS2); } - return *anIndex; + return anIndex; } @@ -153,22 +115,9 @@ Standard_Integer BinTools_ShapeSet::Add (const TopoDS_Shape& theShape) //purpose : //======================================================================= -const TopoDS_Shape& BinTools_ShapeSet::Shape(const Standard_Integer theIndx) +const TopoDS_Shape& BinTools_ShapeSet::Shape (const Standard_Integer theIndx) { - const TopoDS_Shape* aShape = myShapes.Seek1 (theIndx); - if (!aShape && myStream) - { - std::streampos aCurrentPos = myStream->tellg(); - myStream->seekg(myShapesPositions.Value(theIndx)); - TopoDS_Shape aNewShape; - TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)myStream->get(); - ReadShape (T, *myStream, aNewShape); - ReadFlagsAndSubs (aNewShape, T, *myStream, myShapesPositions.Length()); - myShapes.Bind(theIndx, aNewShape); - myStream->seekg(aCurrentPos); - return myShapes.Find1(theIndx); - } - return *aShape; + return myShapes (theIndx); } //======================================================================= @@ -176,9 +125,9 @@ const TopoDS_Shape& BinTools_ShapeSet::Shape(const Standard_Integer theIndx) //purpose : //======================================================================= -Standard_Integer BinTools_ShapeSet::Index(const TopoDS_Shape& theShape) const +Standard_Integer BinTools_ShapeSet::Index (const TopoDS_Shape& theShape) const { - return myShapes.Find2(theShape); + return myShapes.FindIndex (theShape); } //======================================================================= @@ -264,7 +213,7 @@ void BinTools_ShapeSet::AddShape (const TopoDS_Shape& S) mySurfaces.Add(CR->Surface2()); ChangeLocations().Add(CR->Location2()); } - else if (myWithTriangles) { + else if (IsWithTriangles()) { if (CR->IsPolygon3D()) { if (!CR->Polygon3D().IsNull()) { myPolygons3D.Add(CR->Polygon3D()); @@ -296,8 +245,7 @@ void BinTools_ShapeSet::AddShape (const TopoDS_Shape& S) Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape()); if (!TF->Surface().IsNull()) mySurfaces.Add(TF->Surface()); - if (myWithTriangles - || TF->Surface().IsNull()) + if (IsWithTriangles() || TF->Surface().IsNull()) { Handle(Poly_Triangulation) Tr = TF->Triangulation(); if (!Tr.IsNull()) myTriangulations.Add(Tr); @@ -340,13 +288,16 @@ void BinTools_ShapeSet::WriteGeometry (Standard_OStream& OS, //======================================================================= void BinTools_ShapeSet::Write (Standard_OStream& OS, - const Message_ProgressRange& theRange) const + const Message_ProgressRange& theRange) { // write the copyright - if (myFormatNb == 3) + if (FormatNb() == BinTools_FormatVersion_VERSION_3) + { OS << "\n" << Version_3 << "\n"; - else if (myFormatNb == 2) + } + else if (FormatNb() == BinTools_FormatVersion_VERSION_2) + { OS << "\n" << Version_2 << "\n"; else OS << "\n" << Version_1 << "\n"; @@ -378,7 +329,7 @@ void BinTools_ShapeSet::Write (Standard_OStream& OS, // subshapes are written first for (i = 1; i <= nbShapes && aPSinner.More(); i++, aPSinner.Next()) { - const TopoDS_Shape& S = myShapes.Find1(i); + const TopoDS_Shape& S = myShapes (i); // Type OS << (Standard_Byte)S.ShapeType(); @@ -411,10 +362,8 @@ void BinTools_ShapeSet::Write (Standard_OStream& OS, //purpose : //======================================================================= void BinTools_ShapeSet::Read (Standard_IStream& IS, - const Standard_Boolean thePostponeShapes, const Message_ProgressRange& theRange) { - myPostponed = thePostponeShapes; Clear(); // Check the version @@ -467,26 +416,14 @@ void BinTools_ShapeSet::Read (Standard_IStream& IS, IS >> nbShapes; IS.get();//remove lf Message_ProgressScope aPSinner(aPSouter.Next(), "Reading Shapes", nbShapes); - for (int i = 1; i <= nbShapes && aPSinner.More(); i++, aPSinner.Next()) { - - if (myPostponed) - { - std::streampos aCurrentPos = IS.tellg(); - myShapesPositions.Append (aCurrentPos); - TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)IS.get(); - PassShape (T, IS); - PassFlagsAndSubs (IS); - } - else { - TopoDS_Shape S; - TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)IS.get(); - ReadShape (T, IS, S); - ReadFlagsAndSubs (S, T, IS, nbShapes); - myShapes.Bind(i, S); - } + for (int i = 1; i <= nbShapes && aPSinner.More(); i++, aPSinner.Next()) + { + TopoDS_Shape S; + TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)IS.get(); + ReadShape (T, IS, S); + ReadFlagsAndSubs (S, T, IS, nbShapes); + myShapes.Add (S); } - if (myPostponed) - myStream = &IS; } //======================================================================= @@ -495,7 +432,7 @@ void BinTools_ShapeSet::Read (Standard_IStream& IS, //======================================================================= void BinTools_ShapeSet::Write (const TopoDS_Shape& S, - Standard_OStream& OS)const + Standard_OStream& OS) { if (S.IsNull()) @@ -503,13 +440,13 @@ void BinTools_ShapeSet::Write (const TopoDS_Shape& S, else { // {TopAbs_FORWARD, TopAbs_REVERSED, TopAbs_INTERNAL, TopAbs_EXTERNAL} OS << (Standard_Byte) S.Orientation(); - BinTools::PutInteger(OS, myShapes.Extent() - myShapes.Find2(S.Located(TopLoc_Location())) + 1); - BinTools::PutInteger(OS, Locations().Index(S.Location())); + BinTools::PutInteger (OS, myShapes.Extent() - myShapes.FindIndex (S.Located (TopLoc_Location())) + 1); + BinTools::PutInteger (OS, Locations().Index (S.Location())); } } //======================================================================= -//function : Read +//function : ReadFlagsAndSubs //purpose : //======================================================================= @@ -536,8 +473,8 @@ void BinTools_ShapeSet::ReadFlagsAndSubs(TopoDS_Shape& S, const TopAbs_ShapeEnum S.Free(aFree); S.Modified(aMod); - if (myFormatNb != BinTools_FormatVersion_VERSION_2 - && myFormatNb != BinTools_FormatVersion_VERSION_3) + if (FormatNb() != BinTools_FormatVersion_VERSION_2 && + FormatNb() != BinTools_FormatVersion_VERSION_3) { aChecked = false; // force check at reading } @@ -548,13 +485,17 @@ void BinTools_ShapeSet::ReadFlagsAndSubs(TopoDS_Shape& S, const TopAbs_ShapeEnum S.Convex (aConv); // check - if (myFormatNb == BinTools_FormatVersion_VERSION_1) + if (FormatNb() == BinTools_FormatVersion_VERSION_1) if (T == TopAbs_FACE) { const TopoDS_Face& F = TopoDS::Face(S); BRepTools::Update(F); } } +//======================================================================= +//function : ReadSubs +//purpose : +//======================================================================= void BinTools_ShapeSet::ReadSubs(TopoDS_Shape& S, Standard_IStream& IS, const Standard_Integer nbshapes) { @@ -576,16 +517,6 @@ void BinTools_ShapeSet::ReadSubs(TopoDS_Shape& S, Standard_IStream& IS, } } - -void BinTools_ShapeSet::PassFlagsAndSubs(Standard_IStream& IS) -{ - IS.ignore(7 * sizeof(Standard_Byte)); // 7 shape flags - Standard_Character aChar = '\0'; - for (IS >> aChar; aChar != '*'; IS >> aChar) - if (aChar != '*') - IS.ignore(2 * sizeof(Standard_Integer)); // sub-shape and its location indices -} - //======================================================================= //function : ReadGeometry //purpose : @@ -731,7 +662,8 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S, BinTools::PutReal(OS, last); // Write UV Points for higher performance - if (FormatNb() >= 2) + if (FormatNb() == BinTools_FormatVersion_VERSION_2 + || FormatNb() == BinTools_FormatVersion_VERSION_3) { gp_Pnt2d Pf,Pl; if (CR->IsCurveOnClosedSurface()) { @@ -761,7 +693,7 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S, } - else if (myWithTriangles) { + else if (IsWithTriangles()) { if (CR->IsPolygon3D()) { Handle(BRep_Polygon3D) GC = Handle(BRep_Polygon3D)::DownCast(itrc.Value()); if (!GC->Polygon3D().IsNull()) { @@ -811,8 +743,7 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S, : 0); BinTools::PutInteger (OS, Locations().Index (TF->Location())); - if (myWithTriangles - || TF->Surface().IsNull()) + if (IsWithTriangles() || TF->Surface().IsNull()) { if (!(TF->Triangulation()).IsNull()) { OS << (Standard_Byte) 2; @@ -833,7 +764,7 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S, } //======================================================================= -//function : ReadGeometry +//function : ReadShape //purpose : //======================================================================= @@ -874,7 +805,7 @@ void BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T, BRep_ListOfPointRepresentation& lpr = TV->ChangePoints(); TopLoc_Location L; do { - if (myFormatNb == BinTools_FormatVersion_VERSION_3) { + if (FormatNb() == BinTools_FormatVersion_VERSION_3) { val = (Standard_Integer)IS.get();//case {0|1|2|3} if (val > 0 && val <= 3) BinTools::GetReal(IS, p1); @@ -1037,7 +968,8 @@ void BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T, BinTools::GetReal(IS, last); // read UV Points // for XML Persistence higher performance - if (FormatNb() >= 2) + if (FormatNb() == BinTools_FormatVersion_VERSION_2 + || FormatNb() == BinTools_FormatVersion_VERSION_3) { BinTools::GetReal(IS, PfX); BinTools::GetReal(IS, PfY); @@ -1053,8 +985,8 @@ void BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T, break; if (closed) { - if (myFormatNb == BinTools_FormatVersion_VERSION_2 - || myFormatNb == BinTools_FormatVersion_VERSION_3) + if (FormatNb() == BinTools_FormatVersion_VERSION_2 + || FormatNb() == BinTools_FormatVersion_VERSION_3) { myBuilder.UpdateEdge(E, myCurves2d.Curve2d(pc), myCurves2d.Curve2d(pc2), @@ -1079,8 +1011,8 @@ void BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T, } else { - if (myFormatNb == BinTools_FormatVersion_VERSION_2 - || myFormatNb == BinTools_FormatVersion_VERSION_3) + if (FormatNb() == BinTools_FormatVersion_VERSION_2 + || FormatNb() == BinTools_FormatVersion_VERSION_3) { myBuilder.UpdateEdge(E, myCurves2d.Curve2d(pc), mySurfaces.Surface(s), @@ -1246,117 +1178,6 @@ void BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T, } } -//======================================================================= -//function : PassShape -//purpose : -//======================================================================= - -void BinTools_ShapeSet::PassShape (const TopAbs_ShapeEnum T, Standard_IStream& IS) -{ - Standard_Integer val; - - switch (T) { - case TopAbs_VERTEX: - IS.ignore(4 * sizeof(Standard_Real)); // tolerance + 3 coordinates - do { - if (myFormatNb > 2) { - val = (Standard_Integer)IS.get(); - if (val > 0 && val <= 3) - IS.ignore(sizeof(Standard_Real)); // parameter - } - else { - std::streampos aPos = IS.tellg(); - IS.ignore(sizeof(Standard_Real)); - val = (Standard_Integer)IS.get(); - if (val != 1 && val != 2 && val != 3) { - IS.seekg(aPos); - val = (Standard_Integer)IS.get(); - if (val > 0 && val <= 3) - IS.ignore(sizeof(Standard_Real)); // parameter - } - } - switch (val) { - case 0: - break; - case 1: - IS.ignore(sizeof(Standard_Integer)); // index of curve - break; - case 2: - IS.ignore(sizeof(Standard_Integer) * 2); // curve 2d and surface indices - break; - case 3: - IS.ignore(sizeof(Standard_Real) + sizeof(Standard_Integer)); // parameter + surface index - break; - default: - { - Standard_SStream aMsg; - aMsg << "BinTools_SurfaceSet::ReadGeometry: UnExpected BRep_PointRepresentation = " << val << std::endl; - throw Standard_Failure(aMsg.str().c_str()); - } - } - - if (val > 0) - IS.ignore(sizeof(Standard_Integer));//Locations index - } while (val > 0); - break; - case TopAbs_EDGE: - IS.ignore(sizeof(Standard_Real) + 3); // tolerance + 3 flags - do { - val = (Standard_Integer)IS.get(); - switch (val) { - case 0: - break; - case 1: - IS.ignore(2 * sizeof(Standard_Integer) + 2 * sizeof(Standard_Real)); // curve and location indices + 2 parameters - break; - case 2: // -2- Curve on surf - case 3: // -3- Curve on closed surf - IS.ignore((val == 3 ? 4 : 3) * sizeof(Standard_Integer) + (val == 3 ? 1 : 0) + (FormatNb() >= 2 ? 6 : 2) * sizeof(Standard_Real)); - break; - case 4: // -4- Regularity - IS.ignore(1 + 4 * sizeof(Standard_Integer)); // reg byte + surace + location + surface + location indices - break; - case 5: // -5- Polygon3D - IS.ignore(2 * sizeof(Standard_Integer)); // polygon + location indices - break; - case 6: // -6- Polygon on triangulation - case 7: // -7- Polygon on closed triangulation - IS.ignore((val == 7 ? 4 : 3) * sizeof(Standard_Integer)); // polygon + triangulation + location indices - break; - default: - { - Standard_SStream aMsg; - aMsg << "Unexpected Curve Representation =" << val << std::endl; - throw Standard_Failure(aMsg.str().c_str()); - } - } - } while (val > 0); - break; - case TopAbs_WIRE: - break; - case TopAbs_FACE: - IS.ignore(1 + sizeof(Standard_Real) + 2 * sizeof(Standard_Integer)); // flag + tolerance + surface and location indices - if ((Standard_Byte)IS.get() == 2) - IS.ignore(sizeof(Standard_Integer)); // triangulation index - break; - case TopAbs_SHELL: - break; - case TopAbs_SOLID: - break; - case TopAbs_COMPSOLID: - break; - case TopAbs_COMPOUND: - break; - default: - { - Standard_SStream aMsg; - aMsg << "Unexpected topology type = " << T << std::endl; - throw Standard_Failure(aMsg.str().c_str()); - break; - } - } -} - //======================================================================= //function : AddShapes //purpose : @@ -1368,7 +1189,6 @@ void BinTools_ShapeSet::AddShapes(TopoDS_Shape& S1, myBuilder.Add(S1,S2); } - //======================================================================= //function : WritePolygonOnTriangulation //purpose : @@ -1739,5 +1559,5 @@ void BinTools_ShapeSet::ReadTriangulation (Standard_IStream& IS, Standard_Integer BinTools_ShapeSet::NbShapes() const { - return myPostponed ? myShapesPositions.Length() : myShapes.Extent(); + return myShapes.Extent(); } diff --git a/src/BinTools/BinTools_ShapeSet.hxx b/src/BinTools/BinTools_ShapeSet.hxx index c3e486249f..279f1b1e4d 100644 --- a/src/BinTools/BinTools_ShapeSet.hxx +++ b/src/BinTools/BinTools_ShapeSet.hxx @@ -16,33 +16,21 @@ #ifndef _BinTools_ShapeSet_HeaderFile #define _BinTools_ShapeSet_HeaderFile -#include -#include -#include +#include -#include -#include -#include +#include #include -#include #include #include #include #include #include -#include #include #include -#include -#include -#include - -class TopoDS_Shape; -class BinTools_LocationSet; //! Writes topology in OStream in binary format -class BinTools_ShapeSet +class BinTools_ShapeSet : public BinTools_ShapeSetBase { public: @@ -55,22 +43,6 @@ public: Standard_EXPORT virtual ~BinTools_ShapeSet(); - //! Return true if shape should be stored with triangles. - Standard_Boolean IsWithTriangles() const { return myWithTriangles; } - - //! Define if shape will be stored with triangles. - //! Ignored (always written) if face defines only triangulation (no surface). - void SetWithTriangles (const Standard_Boolean isWithTriangles) { myWithTriangles = isWithTriangles; } - - Standard_EXPORT void SetFormatNb (const Standard_Integer theFormatNb); - - //! two formats available for the moment: - //! First: does not write CurveOnSurface UV Points into the file - //! on reading calls Check() method. - //! Second: stores CurveOnSurface UV Points. - //! On reading format is recognized from Version string. - Standard_EXPORT Standard_Integer FormatNb() const; - //! Clears the content of the set. Standard_EXPORT virtual void Clear(); @@ -105,7 +77,7 @@ public: //! Write the flags, the subshapes. Standard_EXPORT virtual void Write (Standard_OStream& OS, - const Message_ProgressRange& theRange = Message_ProgressRange()) const; + const Message_ProgressRange& theRange = Message_ProgressRange()); //! Reads the content of me from the binary stream . me //! is first cleared. @@ -121,13 +93,12 @@ public: //! Reads the flag, the subshapes. Standard_EXPORT virtual void Read (Standard_IStream& IS, - const Standard_Boolean thePostponeShapes = Standard_False, const Message_ProgressRange& theRange = Message_ProgressRange()); //! Writes on the shape . Writes the //! orientation, the index of the TShape and the index //! of the Location. - Standard_EXPORT virtual void Write (const TopoDS_Shape& S, Standard_OStream& OS) const; + Standard_EXPORT virtual void Write (const TopoDS_Shape& S, Standard_OStream& OS); //! Writes the geometry of me on the stream in a //! binary format that can be read back by Read. @@ -150,8 +121,8 @@ public: Standard_EXPORT virtual void ReadSubs (TopoDS_Shape& S, Standard_IStream& IS, const Standard_Integer NbShapes); - //! Passes in a shape flags and sub-shapes indices. - Standard_EXPORT virtual void PassFlagsAndSubs(Standard_IStream& IS); + //! An empty virtual method for redefinition in shape-reader. + Standard_EXPORT virtual void Read (Standard_IStream& /*theStream*/, TopoDS_Shape& /*theShape*/) {}; //! Writes the shape on the stream in a //! binary format that can be read back by Read. @@ -160,9 +131,6 @@ public: //! Reads a shape of type from the stream and returns it in . Standard_EXPORT virtual void ReadShape (const TopAbs_ShapeEnum T, Standard_IStream& IS, TopoDS_Shape& S); - //! Passes in the input stream of a shape of type . - Standard_EXPORT virtual void PassShape (const TopAbs_ShapeEnum T, Standard_IStream& IS); - //! Stores the shape . Standard_EXPORT virtual void AddShape (const TopoDS_Shape& S); @@ -210,12 +178,8 @@ public: private: - NCollection_DoubleMap myShapes; ///< index and its shape (started from 1) - NCollection_Sequence myShapesPositions; ///< positions in the file of the shape start for postponed reading - Standard_Boolean myPostponed; ///< postponed reading stores buffer positions, but does not create shapes - Standard_IStream* myStream; ///< stream used for postponed reading of shapes + TopTools_IndexedMapOfShape myShapes; ///< index and its shape (started from 1) BinTools_LocationSet myLocations; - Standard_Integer myFormatNb; BRep_Builder myBuilder; BinTools_SurfaceSet mySurfaces; BinTools_CurveSet myCurves; @@ -224,7 +188,6 @@ private: NCollection_IndexedMap myPolygons3D; NCollection_IndexedMap myTriangulations; NCollection_IndexedMap myNodes; - Standard_Boolean myWithTriangles; }; #endif // _BinTools_ShapeSet_HeaderFile diff --git a/src/BinTools/BinTools_ShapeSetBase.cxx b/src/BinTools/BinTools_ShapeSetBase.cxx new file mode 100644 index 0000000000..bfe0f73693 --- /dev/null +++ b/src/BinTools/BinTools_ShapeSetBase.cxx @@ -0,0 +1,63 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include + +Standard_CString BinTools_ShapeSetBase::Version_1 = "Open CASCADE Topology V1 (c)"; +Standard_CString BinTools_ShapeSetBase::Version_2 = "Open CASCADE Topology V2 (c)"; +Standard_CString BinTools_ShapeSetBase::Version_3 = "Open CASCADE Topology V3 (c)"; + +//======================================================================= +//function : operator << (gp_Pnt) +//purpose : +//======================================================================= +Standard_OStream& operator << (Standard_OStream& OS, const gp_Pnt P) +{ + BinTools::PutReal (OS, P.X()); + BinTools::PutReal (OS, P.Y()); + BinTools::PutReal (OS, P.Z()); + return OS; +} + +//======================================================================= +//function : BinTools_ShapeSetBase +//purpose : +//======================================================================= + +BinTools_ShapeSetBase::BinTools_ShapeSetBase (const Standard_Boolean theWithTriangles) + : myFormatNb (BinTools_FormatVersion_CURRENT), myWithTriangles (theWithTriangles) +{} + +//======================================================================= +//function : ~BinTools_ShapeSetBase +//purpose : +//======================================================================= + +BinTools_ShapeSetBase::~BinTools_ShapeSetBase() +{} + +//======================================================================= +//function : SetFormatNb +//purpose : +//======================================================================= +void BinTools_ShapeSetBase::SetFormatNb (const Standard_Integer theFormatNb) +{ + Standard_ASSERT_RETURN(theFormatNb == BinTools_FormatVersion_VERSION_1 || + theFormatNb == BinTools_FormatVersion_VERSION_2 || + theFormatNb == BinTools_FormatVersion_VERSION_3, + "Error: unsupported BinTools version.", ); + + myFormatNb = theFormatNb; +} diff --git a/src/BinTools/BinTools_ShapeSetBase.hxx b/src/BinTools/BinTools_ShapeSetBase.hxx new file mode 100644 index 0000000000..2a09175a20 --- /dev/null +++ b/src/BinTools/BinTools_ShapeSetBase.hxx @@ -0,0 +1,110 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BinTools_ShapeSetBase_HeaderFile +#define _BinTools_ShapeSetBase_HeaderFile + +#include +#include +#include + +#include +#include +#include +#include + +class TopoDS_Shape; +class gp_Pnt; + +//! Writes to the stream a gp_Pnt data +Standard_OStream& operator << (Standard_OStream& OS, const gp_Pnt P); + +//! A base class for all readers/writers of TopoDS_Shape into/from stream. +class BinTools_ShapeSetBase +{ +public: + + DEFINE_STANDARD_ALLOC + + + //! A default constructor.. + //! Parameter is added for XML Persistence + Standard_EXPORT BinTools_ShapeSetBase (const Standard_Boolean theWithTriangles = Standard_False); + + Standard_EXPORT virtual ~BinTools_ShapeSetBase(); + + //! Return true if shape should be stored with triangles. + Standard_Boolean IsWithTriangles() const { return myWithTriangles; } + + //! Define if shape will be stored with triangles. + //! Ignored (always written) if face defines only triangulation (no surface). + void SetWithTriangles (const Standard_Boolean theWithTriangles) { myWithTriangles = theWithTriangles; } + + //! Sets the BinTools_FormatVersion. + Standard_EXPORT void SetFormatNb (const Standard_Integer theFormatNb); + + //! Returns the BinTools_FormatVersion. + Standard_EXPORT Standard_Integer FormatNb() const { return myFormatNb; } + + //! Clears the content of the set. + Standard_EXPORT virtual void Clear() {} + + //! Writes the content of me on the stream in binary + //! format that can be read back by Read. + //! + //! Writes the locations. + //! + //! Writes the geometry calling WriteGeometry. + //! + //! Dumps the shapes from last to first. + //! For each shape : + //! Write the type. + //! calls WriteGeometry(S). + //! Write the flags, the subshapes. + Standard_EXPORT virtual void Write + (Standard_OStream& /*OS*/, const Message_ProgressRange& /*theRange*/ = Message_ProgressRange()) {} + + //! Reads the content of me from the binary stream . me + //! is first cleared. + //! + //! Reads the locations. + //! + //! Reads the geometry calling ReadGeometry. + //! + //! Reads the shapes. + //! For each shape + //! Reads the type. + //! calls ReadGeometry(T,S). + //! Reads the flag, the subshapes. + Standard_EXPORT virtual void Read + (Standard_IStream& /*IS*/, const Message_ProgressRange& /*theRange*/ = Message_ProgressRange()) {} + + //! Writes on the shape . Writes the + //! orientation, the index of the TShape and the index + //! of the Location. + Standard_EXPORT virtual void Write (const TopoDS_Shape& /*theShape*/, Standard_OStream& /*theStream*/) {} + + //! An empty virtual method for redefinition in shape-reader. + Standard_EXPORT virtual void Read (Standard_IStream& /*theStream*/, TopoDS_Shape& /*theShape*/) {} + + static Standard_CString Version_1; + static Standard_CString Version_2; + static Standard_CString Version_3; + +private: + + Standard_Integer myFormatNb; + Standard_Boolean myWithTriangles; +}; + +#endif // _BinTools_ShapeSet_HeaderFile diff --git a/src/BinTools/BinTools_ShapeWriter.cxx b/src/BinTools/BinTools_ShapeWriter.cxx new file mode 100644 index 0000000000..36222d9800 --- /dev/null +++ b/src/BinTools/BinTools_ShapeWriter.cxx @@ -0,0 +1,513 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +//function : BinTools_ShapeWriter +//purpose : +//======================================================================= +BinTools_ShapeWriter::BinTools_ShapeWriter (const Standard_Boolean theWithTriangles) + : BinTools_ShapeSetBase (theWithTriangles) +{} + +//======================================================================= +//function : ~BinTools_ShapeWriter +//purpose : +//======================================================================= +BinTools_ShapeWriter::~BinTools_ShapeWriter() +{} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void BinTools_ShapeWriter::Clear() +{ + BinTools_ShapeSetBase::Clear(); + myShapePos.Clear(); + myLocationPos.Clear(); + myCurvePos.Clear(); + myCurve2dPos.Clear(); + mySurfacePos.Clear(); + myPolygon3dPos.Clear(); + myPolygonPos.Clear(); + myTriangulationPos.Clear(); +} + +//======================================================================= +//function : Write +//purpose : +//======================================================================= +void BinTools_ShapeWriter::Write (const TopoDS_Shape& theShape, Standard_OStream& theStream) +{ + WriteShape (theStream, theShape); +} + +//======================================================================= +//function : WriteShape +//purpose : +//======================================================================= +void BinTools_ShapeWriter::WriteShape (Standard_OStream& theStream, const TopoDS_Shape& theShape) +{ + if (theShape.IsNull()) + { + BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyShape); + return; + } + TopoDS_Shape aShape = theShape.Located (TopLoc_Location()); + const BinTools_Position* anExisting = myShapePos.Seek (aShape); + if (anExisting) // shape is already there, so, write reference to it + { + anExisting->WriteReference(); + WriteLocation (theStream, theShape.Location()); + theStream << Standard_Byte (theShape.Orientation ()); + return; + } + BinTools_Position aNewPos (theStream); + myShapePos.Bind (aShape, aNewPos); + aNewPos.WriteShape (aShape.ShapeType(), aShape.Orientation()); + WriteLocation (theStream, theShape.Location()); + + try { + OCC_CATCH_SIGNALS + switch (aShape.ShapeType()) + { + case TopAbs_VERTEX: + { + TopoDS_Vertex aV = TopoDS::Vertex (aShape); + BinTools::PutReal (theStream, BRep_Tool::Tolerance (aV)); + gp_Pnt aP = BRep_Tool::Pnt (aV); + theStream << aP; + Handle(BRep_TVertex) aTV = Handle(BRep_TVertex)::DownCast (aShape.TShape()); + for(BRep_ListIteratorOfListOfPointRepresentation anIter (aTV->Points()); anIter.More(); anIter.Next()) + { + const Handle(BRep_PointRepresentation)& aPR = anIter.Value(); + if (aPR->IsPointOnCurve()) + { + theStream << (Standard_Byte)1; // 1 + BinTools::PutReal (theStream, aPR->Parameter()); + WriteCurve (theStream, aPR->Curve()); + } + else if (aPR->IsPointOnCurveOnSurface()) + { + theStream << (Standard_Byte)2;// 2 + BinTools::PutReal (theStream, aPR->Parameter()); + WriteCurve (theStream, aPR->PCurve()); + WriteSurface (theStream, aPR->Surface()); + } + else if (aPR->IsPointOnSurface()) + { + theStream << (Standard_Byte)3;// 3 + BinTools::PutReal (theStream, aPR->Parameter2()); + BinTools::PutReal (theStream, aPR->Parameter()); + WriteSurface (theStream, aPR->Surface()); + } + WriteLocation (theStream, aPR->Location()); + } + theStream.put ((Standard_Byte)0); + } + break; + case TopAbs_EDGE: + { + Handle(BRep_TEdge) aTE = Handle(BRep_TEdge)::DownCast (aShape.TShape()); + BinTools::PutReal (theStream, aTE->Tolerance()); + BinTools::PutBools (theStream, aTE->SameParameter(), aTE->SameRange(), aTE->Degenerated()); + Standard_Real aFirst, aLast; + for(BRep_ListIteratorOfListOfCurveRepresentation anIter = aTE->Curves(); anIter.More(); anIter.Next()) + { + const Handle(BRep_CurveRepresentation)& aCR = anIter.Value(); + if (aCR->IsCurve3D()) + { + if (!aCR->Curve3D().IsNull()) + { + Handle(BRep_GCurve) aGC = Handle(BRep_GCurve)::DownCast (aCR); + aGC->Range (aFirst, aLast); + theStream << (Standard_Byte)1;//CURVE_3D; + WriteCurve (theStream, aCR->Curve3D()); + WriteLocation (theStream, aCR->Location()); + BinTools::PutReal (theStream, aFirst); + BinTools::PutReal (theStream, aLast); + } + } + else if (aCR->IsCurveOnSurface()) { + Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast (aCR); + GC->Range (aFirst, aLast); + if (!aCR->IsCurveOnClosedSurface()) + // -2- Curve on surf + theStream << (Standard_Byte)2; + else + // -3- Curve on closed surf + theStream << (Standard_Byte)3; + WriteCurve (theStream, aCR->PCurve()); + + if (aCR->IsCurveOnClosedSurface()) {//+ int|char + WriteCurve (theStream, aCR->PCurve2()); + theStream << (Standard_Byte)aCR->Continuity(); + } + WriteSurface (theStream, aCR->Surface()); + WriteLocation (theStream, aCR->Location()); + BinTools::PutReal (theStream, aFirst); + BinTools::PutReal (theStream, aLast); + } + else if (aCR->IsRegularity()) + { + // -4- Regularity + theStream << (Standard_Byte)4; + theStream << (Standard_Byte)aCR->Continuity(); + WriteSurface (theStream, aCR->Surface()); + WriteLocation (theStream, aCR->Location()); + WriteSurface (theStream, aCR->Surface2()); + WriteLocation (theStream, aCR->Location2()); + } + else if (IsWithTriangles()) + { + if (aCR->IsPolygon3D()) + { + Handle(BRep_Polygon3D) aGC = Handle(BRep_Polygon3D)::DownCast (aCR); + if (!aGC->Polygon3D().IsNull()) + { + // -5- Polygon3D + theStream << (Standard_Byte)5; + WritePolygon (theStream, aCR->Polygon3D()); + WriteLocation (theStream, aCR->Location()); + } + } + else if (aCR->IsPolygonOnTriangulation()) + { + Handle(BRep_PolygonOnTriangulation) aPT = Handle(BRep_PolygonOnTriangulation)::DownCast (aCR); + if (!aCR->IsPolygonOnClosedTriangulation()) + // -6- Polygon on triangulation + theStream << (Standard_Byte)6; + else + // -7- Polygon on closed triangulation + theStream << (Standard_Byte)7; + WritePolygon (theStream, aPT->PolygonOnTriangulation()); + + if (aCR->IsPolygonOnClosedTriangulation()) + WritePolygon (theStream, aPT->PolygonOnTriangulation2()); + // edge triangulation does not need normals + WriteTriangulation (theStream, aPT->Triangulation()); + WriteLocation (theStream, aCR->Location()); + } + } + } + theStream << (Standard_Byte)0; + } + break; + case TopAbs_FACE: + { + + Handle(BRep_TFace) aTF = Handle(BRep_TFace)::DownCast (aShape.TShape()); + const TopoDS_Face& aF = TopoDS::Face (aShape); + + // Write the surface geometry + Standard_Boolean aNatRes = BRep_Tool::NaturalRestriction (aF); + BinTools::PutBool (theStream, aNatRes); + BinTools::PutReal (theStream, aTF->Tolerance()); + WriteSurface (theStream, aTF->Surface()); + WriteLocation (theStream, aTF->Location()); + + if (IsWithTriangles() || aTF->Surface().IsNull()) + { + if (!(aTF->Triangulation()).IsNull()) + { + theStream << (Standard_Byte)2; + WriteTriangulation (theStream, aTF->Triangulation()); + } + else + theStream << (Standard_Byte)1; + } + else + theStream << (Standard_Byte)0;//without triangulation + } + break; + } + } + catch (Standard_Failure const& anException) + { + Standard_SStream aMsg; + aMsg << "EXCEPTION in BinTools_ShapeWriter::WriteShape" << std::endl; + aMsg << anException << std::endl; + throw Standard_Failure(aMsg.str().c_str()); + } + BinTools::PutBools (theStream, aShape.Free(), aShape.Modified(), aShape.Checked(), + aShape.Orientable(), aShape.Closed(), aShape.Infinite(), aShape.Convex()); + // process sub-shapes + for (TopoDS_Iterator aSub (aShape, Standard_False, Standard_False); aSub.More(); aSub.Next()) + WriteShape (theStream, aSub.Value()); + aNewPos.WriteObject (BinTools_ObjectType_EndShape); +} + +//======================================================================= +//function : WriteLocation +//purpose : +//======================================================================= +void BinTools_ShapeWriter::WriteLocation (Standard_OStream& theStream, const TopLoc_Location& theLocation) +{ + if (theLocation.IsIdentity()) + { + BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyLocation); + return; + } + const BinTools_Position* aLoc = myLocationPos.Seek (theLocation); + if (aLoc) + { + aLoc->WriteReference(); + return; + } + BinTools_Position aNewLoc (theStream); + try + { + OCC_CATCH_SIGNALS + TopLoc_Location aL2 = theLocation.NextLocation(); + Standard_Boolean isSimple = aL2.IsIdentity(); + Standard_Integer aPower = theLocation.FirstPower(); + TopLoc_Location aL1 = theLocation.FirstDatum(); + Standard_Boolean elementary = (isSimple && aPower == 1); + if (elementary) + { + aNewLoc.WriteObject (BinTools_ObjectType_SimpleLocation); + theStream << theLocation.Transformation(); + } + else + { + aNewLoc.WriteObject (BinTools_ObjectType_Location); + WriteLocation (theStream, aL1); + BinTools::PutInteger (theStream, aPower); + while (!aL2.IsIdentity()) { + aL1 = aL2.FirstDatum(); + aPower = aL2.FirstPower(); + aL2 = aL2.NextLocation(); + WriteLocation (theStream, aL1); + BinTools::PutInteger (theStream, aPower); + } + aNewLoc.WriteObject (BinTools_ObjectType_LocationEnd); + } + myLocationPos.Bind (theLocation, aNewLoc); + } + catch (Standard_Failure const& anException) { + Standard_SStream aMsg; + aMsg << "EXCEPTION in BinTools_ShapeWriter::WriteLocation" << std::endl; + aMsg << anException << std::endl; + throw Standard_Failure (aMsg.str().c_str()); + } +} + +//======================================================================= +//function : WriteCurve +//purpose : +//======================================================================= +void BinTools_ShapeWriter::WriteCurve (Standard_OStream& theStream, const Handle(Geom_Curve)& theCurve) +{ + if (theCurve.IsNull()) + { + BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyCurve); + return; + } + const BinTools_Position* aCurve = myCurvePos.Seek (theCurve); + if (aCurve) + { + aCurve->WriteReference(); + return; + } + BinTools_Position aNewCurve (theStream); + aNewCurve.WriteObject (BinTools_ObjectType_Curve); + BinTools_CurveSet::WriteCurve (theCurve, theStream); + myCurvePos.Bind (theCurve, aNewCurve); +} + +//======================================================================= +//function : WriteCurve +//purpose : +//======================================================================= +void BinTools_ShapeWriter::WriteCurve (Standard_OStream& theStream, const Handle(Geom2d_Curve)& theCurve) +{ + if (theCurve.IsNull()) + { + BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyCurve2d); + return; + } + const BinTools_Position* aCurve = myCurve2dPos.Seek (theCurve); + if (aCurve) + { + aCurve->WriteReference(); + return; + } + BinTools_Position aNewCurve (theStream); + aNewCurve.WriteObject (BinTools_ObjectType_Curve2d); + BinTools_Curve2dSet::WriteCurve2d (theCurve, theStream); + myCurve2dPos.Bind (theCurve, aNewCurve); +} + +//======================================================================= +//function : WriteSurface +//purpose : +//======================================================================= +void BinTools_ShapeWriter::WriteSurface (Standard_OStream& theStream, const Handle(Geom_Surface)& theSurface) +{ + if (theSurface.IsNull()) + { + BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptySurface); + return; + } + const BinTools_Position* aSurface = mySurfacePos.Seek (theSurface); + if (aSurface) + { + aSurface->WriteReference(); + return; + } + BinTools_Position aNewSurface (theStream); + aNewSurface.WriteObject (BinTools_ObjectType_Surface); + BinTools_SurfaceSet::WriteSurface (theSurface, theStream); + mySurfacePos.Bind (theSurface, aNewSurface); +} + +//======================================================================= +//function : WritePolygon +//purpose : +//======================================================================= +void BinTools_ShapeWriter::WritePolygon (Standard_OStream& theStream, const Handle(Poly_Polygon3D)& thePolygon) +{ + if (thePolygon.IsNull()) + { + BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyPolygon3d); + return; + } + const BinTools_Position* aPolygon = myPolygon3dPos.Seek (thePolygon); + if (aPolygon) + { + aPolygon->WriteReference(); + return; + } + BinTools_Position aNewPolygon (theStream); + aNewPolygon.WriteObject (BinTools_ObjectType_Polygon3d); + + const Standard_Integer aNbNodes = thePolygon->NbNodes(); + BinTools::PutInteger (theStream, aNbNodes); + BinTools::PutBool (theStream, thePolygon->HasParameters()); + BinTools::PutReal (theStream, thePolygon->Deflection()); + const TColgp_Array1OfPnt& aNodes = thePolygon->Nodes(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + theStream << aNodes.Value (aNodeIter); + if (thePolygon->HasParameters()) + { + const TColStd_Array1OfReal& aParam = thePolygon->Parameters(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + BinTools::PutReal (theStream, aParam.Value (aNodeIter)); + } + + myPolygon3dPos.Bind (thePolygon, aNewPolygon); +} + +//======================================================================= +//function : WritePolygon +//purpose : +//======================================================================= +void BinTools_ShapeWriter::WritePolygon (Standard_OStream& theStream, + const Handle(Poly_PolygonOnTriangulation)& thePolygon) +{ + if (thePolygon.IsNull()) + { + BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyPolygonOnTriangulation); + return; + } + const BinTools_Position* aPolygon = myPolygonPos.Seek (thePolygon); + if (aPolygon) + { + aPolygon->WriteReference(); + return; + } + BinTools_Position aNewPolygon (theStream); + aNewPolygon.WriteObject (BinTools_ObjectType_PolygonOnTriangulation); + + const TColStd_Array1OfInteger& aNodes = thePolygon->Nodes(); + BinTools::PutInteger (theStream, aNodes.Length()); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNodes.Length(); ++aNodeIter) + BinTools::PutInteger (theStream, aNodes.Value(aNodeIter)); + BinTools::PutReal (theStream, thePolygon->Deflection()); + if (const Handle(TColStd_HArray1OfReal)& aParam = thePolygon->Parameters()) + { + BinTools::PutBool (theStream, Standard_True); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aParam->Length(); ++aNodeIter) + BinTools::PutReal (theStream, aParam->Value(aNodeIter)); + } + else + BinTools::PutBool (theStream, Standard_False); + + myPolygonPos.Bind (thePolygon, aNewPolygon); +} + +void BinTools_ShapeWriter::WriteTriangulation (Standard_OStream& theStream, + const Handle(Poly_Triangulation)& theTriangulation) +{ + if (theTriangulation.IsNull()) + { + BinTools_Position(theStream).WriteObject (BinTools_ObjectType_EmptyTriangulation); + return; + } + const BinTools_Position* aTriangulation = myTriangulationPos.Seek (theTriangulation); + if (aTriangulation) + { + aTriangulation->WriteReference(); + return; + } + BinTools_Position aNewTriangulation (theStream); + aNewTriangulation.WriteObject (BinTools_ObjectType_Triangulation); + + const Standard_Integer aNbNodes = theTriangulation->NbNodes(); + const Standard_Integer aNbTriangles = theTriangulation->NbTriangles(); + BinTools::PutInteger (theStream, aNbNodes); + BinTools::PutInteger (theStream, aNbTriangles); + BinTools::PutBool (theStream, theTriangulation->HasUVNodes() ? 1 : 0); + BinTools::PutReal (theStream, theTriangulation->Deflection()); + // write the 3d nodes + const TColgp_Array1OfPnt& aNodes = theTriangulation->Nodes(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + theStream << aNodes.Value (aNodeIter); + if (theTriangulation->HasUVNodes()) + { + const TColgp_Array1OfPnt2d& aUVNodes = theTriangulation->UVNodes(); + for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter) + { + const gp_Pnt2d aUV = aUVNodes.Value (aNodeIter); + BinTools::PutReal (theStream, aUV.X()); + BinTools::PutReal (theStream, aUV.Y()); + } + } + const Poly_Array1OfTriangle& aTriangles = theTriangulation->Triangles(); + for (Standard_Integer aTriIter = 1; aTriIter <= aNbTriangles; ++aTriIter) + { + const Poly_Triangle& aTri = aTriangles.Value (aTriIter); + BinTools::PutInteger (theStream, aTri.Value (1)); + BinTools::PutInteger (theStream, aTri.Value (2)); + BinTools::PutInteger (theStream, aTri.Value (3)); + } + myTriangulationPos.Bind (theTriangulation, aNewTriangulation); +} diff --git a/src/BinTools/BinTools_ShapeWriter.hxx b/src/BinTools/BinTools_ShapeWriter.hxx new file mode 100644 index 0000000000..11b5776524 --- /dev/null +++ b/src/BinTools/BinTools_ShapeWriter.hxx @@ -0,0 +1,80 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BinTools_ShapeWriter_HeaderFile +#define _BinTools_ShapeWriter_HeaderFile + +#include +#include +#include +#include + +class TopLoc_Location; +class Geom_Curve; +class Geom2d_Curve; +class Geom_Surface; +class Poly_Polygon3D; +class Poly_PolygonOnTriangulation; +class Poly_Triangulation; + +//! Writes topology in OStream in binary format without grouping of objects by types +//! and using relative positions in a file as references. +class BinTools_ShapeWriter : public BinTools_ShapeSetBase +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Builds an empty ShapeSet. + //! Parameter is added for XML Persistence + Standard_EXPORT BinTools_ShapeWriter (const Standard_Boolean theWithTriangles = Standard_False); + + Standard_EXPORT virtual ~BinTools_ShapeWriter(); + + //! Clears the content of the set. + Standard_EXPORT virtual void Clear() override; + + //! Writes the shape to stream using previously stored shapes and objects to refer them. + Standard_EXPORT virtual void Write (const TopoDS_Shape& theShape, Standard_OStream& theStream) override; + + //! Writes location to the stream (all the needed sub-information or reference if it is already used). + Standard_EXPORT virtual void WriteLocation (Standard_OStream& theStream, const TopLoc_Location& theLocation); + +private: + //! Writes shape to the stream (all the needed sub-information or reference if it is already used). + virtual void WriteShape (Standard_OStream& theStream, const TopoDS_Shape& theShape); + //! Writes curve to the stream (all the needed sub-information or reference if it is already used). + void WriteCurve (Standard_OStream& theStream, const Handle(Geom_Curve)& theCurve); + //! Writes curve2d to the stream (all the needed sub-information or reference if it is already used). + void WriteCurve (Standard_OStream& theStream, const Handle(Geom2d_Curve)& theCurve); + //! Writes surface to the stream. + void WriteSurface (Standard_OStream& theStream, const Handle(Geom_Surface)& theSurface); + //! Writes ploygon3d to the stream. + void WritePolygon (Standard_OStream& theStream, const Handle(Poly_Polygon3D)& thePolygon); + //! Writes polygon on triangulation to the stream. + void WritePolygon (Standard_OStream& theStream, const Handle(Poly_PolygonOnTriangulation)& thePolygon); + //! Writes triangulation to the stream. + void WriteTriangulation (Standard_OStream& theStream, const Handle(Poly_Triangulation)& theTriangulation); + + /// position of the shape previously stored + NCollection_DataMap myShapePos; + NCollection_DataMap myLocationPos; + NCollection_DataMap myCurvePos; + NCollection_DataMap myCurve2dPos; + NCollection_DataMap mySurfacePos; + NCollection_DataMap myPolygon3dPos; + NCollection_DataMap myPolygonPos; + NCollection_DataMap myTriangulationPos; +}; + +#endif // _BinTools_ShapeWriter_HeaderFile diff --git a/src/BinTools/FILES b/src/BinTools/FILES index fd4a059d36..2b7455af35 100644 --- a/src/BinTools/FILES +++ b/src/BinTools/FILES @@ -4,10 +4,21 @@ BinTools_Curve2dSet.cxx BinTools_Curve2dSet.hxx BinTools_CurveSet.cxx BinTools_CurveSet.hxx +BinTools_IStream.cxx +BinTools_IStream.hxx BinTools_LocationSet.cxx BinTools_LocationSet.hxx BinTools_LocationSetPtr.hxx BinTools_ShapeSet.cxx BinTools_ShapeSet.hxx +BinTools_ShapeSetBase.cxx +BinTools_ShapeSetBase.hxx BinTools_SurfaceSet.cxx BinTools_SurfaceSet.hxx +BinTools_ObjectType.hxx +BinTools_Position.hxx +BinTools_Position.cxx +BinTools_ShapeReader.hxx +BinTools_ShapeReader.cxx +BinTools_ShapeWriter.hxx +BinTools_ShapeWriter.cxx diff --git a/src/PCDM/PCDM_ReaderFilter.cxx b/src/PCDM/PCDM_ReaderFilter.cxx index 9a74bb4d89..20d0230fc2 100644 --- a/src/PCDM/PCDM_ReaderFilter.cxx +++ b/src/PCDM/PCDM_ReaderFilter.cxx @@ -36,6 +36,11 @@ void PCDM_ReaderFilter::Clear() mySubTrees.Clear(); } +PCDM_ReaderFilter::~PCDM_ReaderFilter() +{ + ClearTree(); +} + Standard_Boolean PCDM_ReaderFilter::IsPassed (const Handle(Standard_Type)& theAttributeID) const { return IsPassedAttr(theAttributeID->Name()); @@ -51,12 +56,12 @@ Standard_Boolean PCDM_ReaderFilter::IsPassed (const TCollection_AsciiString& the { if (mySubTrees.IsEmpty()) return true; - NCollection_List::Iterator anEntry (mySubTrees); - for (; anEntry.More(); anEntry.Next()) { + for (NCollection_List::Iterator anEntry (mySubTrees); anEntry.More(); anEntry.Next()) + { if (theEntry.StartsWith (anEntry.Value())) { - if (theEntry.Length() > anEntry.Value().Length() && // case when theEntry="0:10" should not match "0:1" - theEntry.Value (anEntry.Value().Length() + 1) != ':') + if (theEntry.Length() > anEntry.Value().Length() && + theEntry.Value (anEntry.Value().Length() + 1) != ':') // case when theEntry="0:10" should not match "0:1" continue; return true; } @@ -64,7 +69,107 @@ Standard_Boolean PCDM_ReaderFilter::IsPassed (const TCollection_AsciiString& the return false; } +Standard_Boolean PCDM_ReaderFilter::IsSubPassed (const TCollection_AsciiString& theEntry) const +{ + if (mySubTrees.IsEmpty() || theEntry.Length() == 2) // root is always passed if any sub is defined + return true; + for (NCollection_List::Iterator anEntry (mySubTrees); anEntry.More(); anEntry.Next()) + { + if (theEntry.Length() < anEntry.Value().Length() && + anEntry.Value().Value (theEntry.Length() + 1) == ':' && // case when theEntry="0:1" should not match "0:10" + anEntry.Value().StartsWith (theEntry)) + return true; + } + return false; +} + Standard_Boolean PCDM_ReaderFilter::IsPartTree() { return !(mySubTrees.IsEmpty() || (mySubTrees.Size() == 1 && mySubTrees.First().Length() < 3)); } + +void PCDM_ReaderFilter::StartIteration() +{ + myCurrent = &myTree; + myCurrentDepth = 0; + ClearTree(); + myTree.Bind(-1, NULL); + if (mySubTrees.IsEmpty()) + return; + // create an iteration-tree by the mySubTrees entries + for (NCollection_List::Iterator aTreeIter (mySubTrees); aTreeIter.More(); aTreeIter.Next()) + { + TagTree* aMap = &myTree; + TCollection_AsciiString aTagStr, anEntry = aTreeIter.Value(); + for (Standard_Integer aTagIndex = 2; Standard_True; ++aTagIndex) // skip the root tag + { + aTagStr = anEntry.Token(":", aTagIndex); + if (aTagStr.IsEmpty()) + break; + Standard_Integer aTag = aTagStr.IntegerValue(); + if (aMap->IsBound (aTag)) + { + aMap = (TagTree*)aMap->Find (aTag); + } + else + { + TagTree* aNewMap = new TagTree; + aNewMap->Bind (-1, aMap); // to be able to iterate up, keep father map in the child + aMap->Bind(aTag, aNewMap); + aMap = aNewMap; + } + } + aMap->Bind (-2, NULL); // identifier that this node is in subtrees definition + } +} + +void PCDM_ReaderFilter::Up() +{ + if (myCurrentDepth == 0) + myCurrent = (TagTree*)myCurrent->Find(-1); + else + myCurrentDepth--; +} + +void PCDM_ReaderFilter::Down (const int& theTag) +{ + if (myCurrentDepth== 0) + { + if (myCurrent->IsBound (theTag)) + myCurrent= (TagTree*)myCurrent->Find (theTag); + else + ++myCurrentDepth; + } + else + ++myCurrentDepth; +} + +Standard_Boolean PCDM_ReaderFilter::IsPassed() const +{ + return myCurrent->IsBound(-2); +} + +Standard_Boolean PCDM_ReaderFilter::IsSubPassed() const +{ + return myCurrentDepth == 0; +} + +void PCDM_ReaderFilter::ClearSubTree (const Standard_Address theMap) +{ + if (theMap) + { + TagTree* aMap = (TagTree*)theMap; + for (TagTree::Iterator aTagIter (*aMap); aTagIter.More(); aTagIter.Next()) + if (aTagIter.Key() != -1) + ClearSubTree (aTagIter.Value()); + delete aMap; + } +} + +void PCDM_ReaderFilter::ClearTree() +{ + for (TagTree::Iterator aTagIter (myTree); aTagIter.More(); aTagIter.Next()) + if (aTagIter.Key() != -1) + ClearSubTree (aTagIter.Value()); + myTree.Clear(); +} diff --git a/src/PCDM/PCDM_ReaderFilter.hxx b/src/PCDM/PCDM_ReaderFilter.hxx index b78a5c3933..73b680b3b9 100644 --- a/src/PCDM/PCDM_ReaderFilter.hxx +++ b/src/PCDM/PCDM_ReaderFilter.hxx @@ -56,8 +56,11 @@ public: //! Creates a filter to append the content of file to open to existing document. Standard_EXPORT PCDM_ReaderFilter (const AppendMode theAppend); + //! Destructor for the filter content + Standard_EXPORT ~PCDM_ReaderFilter(); + //! Adds skipped attribute by type. - Standard_EXPORT void AddSkipped(const Handle(Standard_Type)& theSkipped) { mySkip.Add(theSkipped->Name()); } + Standard_EXPORT void AddSkipped (const Handle(Standard_Type)& theSkipped) { mySkip.Add(theSkipped->Name()); } //! Adds skipped attribute by type name. Standard_EXPORT void AddSkipped (const TCollection_AsciiString& theSkipped) { mySkip.Add (theSkipped); } @@ -78,6 +81,8 @@ public: Standard_EXPORT virtual Standard_Boolean IsPassedAttr (const TCollection_AsciiString& theAttributeType) const; //! Returns true if content of the label must be read. Standard_EXPORT virtual Standard_Boolean IsPassed (const TCollection_AsciiString& theEntry) const; + //! Returns true if some sub-label of the given label is passed. + Standard_EXPORT virtual Standard_Boolean IsSubPassed (const TCollection_AsciiString& theEntry) const; //! Returns true if only part of the document tree will be retrieved. Standard_EXPORT virtual Standard_Boolean IsPartTree(); @@ -86,17 +91,46 @@ public: //! Returns true if appending to the document is performed. Standard_EXPORT Standard_Boolean IsAppendMode() { return myAppend != PCDM_ReaderFilter::AppendMode_Forbid; } + //! Starts the tree iterator. It is used for fast searching of passed labels if the whole tree of labels + //! is parsed. So, on each iteration step the methods Up and Down must be called after the iteration start. + Standard_EXPORT virtual void StartIteration(); + //! Iteration to the child label. + Standard_EXPORT virtual void Up(); + //! Iteration to the child with defined tag. + Standard_EXPORT virtual void Down (const int& theTag); + //! Returns true if content of the currently iterated label must be read. + Standard_EXPORT virtual Standard_Boolean IsPassed() const; + //! Returns true if some sub-label of the currently iterated label is passed. + Standard_EXPORT virtual Standard_Boolean IsSubPassed() const; + DEFINE_STANDARD_RTTIEXT (PCDM_ReaderFilter, Standard_Transient) +private: + //! Clears the iteration tree + Standard_EXPORT void ClearTree(); + //! Clears the iteration sub-tree + Standard_EXPORT static void ClearSubTree (const Standard_Address theMap); + protected: - // Append mode for reading files into existing document + //! Append mode for reading files into existing document AppendMode myAppend; - // Class names of attributes that must be skipped during the read + //! Class names of attributes that must be skipped during the read NCollection_Map mySkip; - // Class names of only attributes to read (if it is not empty, mySkip is unused) + //! Class names of only attributes to read (if it is not empty, mySkip is unused) NCollection_Map myRead; - // Paths to the labels that must be read. If it is empty, read all. + //! Paths to the labels that must be read. If it is empty, read all. NCollection_List mySubTrees; + + //! Map from tag of a label to sub-tree of this tag. Used for fast browsing the tree + //! and compare with entities that must be read. + typedef NCollection_DataMap TagTree; + //! Whole tree that correspond to retrieved document. + TagTree myTree; + //! Pointer to the current node of the iterator. + TagTree* myCurrent; + //! If a node does not described in the read-entries, the iterator goes inside of this subtree just by + //! keeping the depth of iteration. + Standard_Integer myCurrentDepth; }; #endif // _PCDM_ReaderFilter_HeaderFile diff --git a/src/TDocStd/TDocStd_FormatVersion.hxx b/src/TDocStd/TDocStd_FormatVersion.hxx index 3634ee6020..0f27913322 100644 --- a/src/TDocStd/TDocStd_FormatVersion.hxx +++ b/src/TDocStd/TDocStd_FormatVersion.hxx @@ -63,7 +63,10 @@ enum TDocStd_FormatVersion TDocStd_FormatVersion_VERSION_10, //!< OCCT 7.2.0 //!< * BIN: ReadTOC changed to handle 64-bit file length [#0028736] - TDocStd_FormatVersion_CURRENT = TDocStd_FormatVersion_VERSION_10 //!< The latest version + TDocStd_FormatVersion_VERSION_11, //!< OCCT 7.6.0 + //!< * BIN: New binary format for fast reading part of OCAF document [#0031918] + + TDocStd_FormatVersion_CURRENT = TDocStd_FormatVersion_VERSION_11 //!< The latest version }; #endif // _TDocStdFormatVersion_HeaderFile diff --git a/tests/bugs/caf/bug31918_1 b/tests/bugs/caf/bug31918_1 new file mode 100644 index 0000000000..35e358f766 --- /dev/null +++ b/tests/bugs/caf/bug31918_1 @@ -0,0 +1,89 @@ +puts "===========" +puts "0031918: Application Framework - New binary format for fast reading part of OCAF document" +puts "===========" + +set docname ${imagedir}/doc_${casename}.cbfl + +NewDocument D0 BinLOcaf +UndoLimit D0 10 + +NewCommand D0 + +# set an array 1000 values from 100 to 1099 +set values "100 " +for {set i 101} {$i < 1100} {incr i} {set values "$values $i"} + +# set 100 arrays to sub-labels of 0:1 0:2 0:3 and 0:4 +for {set lab 1} {$lab <= 4} {incr lab} { + for {set sublab 1} {$sublab <= 100} {incr sublab} { + set command "SetIntArray D0 0:$lab:$sublab 0 1 1000 $values" + eval $command + SetReal D0 0:$lab:$sublab 0.1 + } +} + +CommitCommand D0 + +SaveAs D0 ${docname} +Close D0 + +set whole_time [lindex [time { + Open ${docname} D1 + Close D1 +} 20] 0] +puts "Whole document open time $whole_time mcs" + +set quater_time [lindex [time { + Open ${docname} D2 -read0:2 + Close D2 +} 20] 0] +puts "Quater of document open time $quater_time mcs" + +# Check that open of quater of the document is at least twice faster than open of whole. +if { [expr $quater_time * 2] > $whole_time } { + puts "Error : loading of quater of the document content too slow relatively to the whole document load" +} + +set four_quaters_time [lindex [time { + Open ${docname} D3 -read0:1 -read0:2 -read0:3 -read0:4 + Close D3 +} 20] 0] +puts "Four quaters of document open time $four_quaters_time mcs" + +# Check that open of four quaters of the document is not too much slower than opening of the whole document. +if { [expr $four_quaters_time * 0.9] > $whole_time } { + puts "Error : loading of four quaters of the document content too slow relatively to the whole document load" +} + +set no_arrays_time [lindex [time { + Open ${docname} D4 -skipTDataStd_IntegerArray -read0:2 +}] 0] +puts "Quater of document without arrays open time $no_arrays_time mcs" + +set attrs [Attributes D4 0:2:13] +if {"${attrs}" != "TDataStd_Real "} { + puts "Error : loading of document skipping arrays contains invalid attributes list '${attrs}'" +} + +if {![catch {Attributes D4 0:1:1:13}] || ![catch {Attributes D4 0:1:3:14}] || ![catch {Attributes D4 0:1:4:1}]} { + puts "Error : loading of document skipping arrays and sub-trees contains invalid attributes list" +} + +set append_arrays_time [lindex [time { + Open ${docname} D4 -append -readTDataStd_IntegerArray -read0:2 -read0:3 +}] 0] +puts "Half of document arrays open time $append_arrays_time mcs" + +set attrs [Attributes D4 0:2:13] +if {"${attrs}" != "TDataStd_Real TDataStd_IntegerArray "} { + puts "Error : loading of document reading arrays separately contains invalid attributes list '${attrs}'" +} +set attrs [Attributes D4 0:3:1] +if {"${attrs}" != "TDataStd_IntegerArray "} { + puts "Error : loading of document reading arrays separately contains invalid attributes list on subtree 3 '${attrs}'" +} +if {![catch {Attributes D4 0:1:1:13}] || ![catch {Attributes D4 0:1:4:1}]} { + puts "Error : loading of document reading arrays separately contains invalid attributes list on 1 and 4 subtrees" +} + +Close D4 diff --git a/tests/bugs/caf/bug31918_2 b/tests/bugs/caf/bug31918_2 new file mode 100644 index 0000000000..9b4eb1bac2 --- /dev/null +++ b/tests/bugs/caf/bug31918_2 @@ -0,0 +1,123 @@ +puts "===========" +puts "0031918: Application Framework - New binary format for fast reading part of OCAF document" +puts "===========" + +pload XDE + +NewDocument D0 BinOcaf + +# creates part-shape by the given sizes +proc store_part {nx ny dx dy dz entry} { + global D0 + box b1 0 0 0 [expr $nx + .5] [expr $ny + .5] 1 + box b2 0.5 0.5 0 [expr $nx - .5] [expr $nx - .5] 0.4 + cut base b1 b2 + + set command "compound" + for {set x 0} {$x < $nx} {incr x} { + for {set y 0} {$y < $ny} {incr y} { + pcylinder c${x}_$y 0.25 1.01 + ttranslate c${x}_$y [expr $x+.75] [expr $y+.75] 0.39 + set command "$command c${x}_$y" + } + } + eval "$command cc" + bop base cc + bopfuse part + ttranslate part $dx $dy $dz + Label D0 $entry + SetShape D0 $entry part +} + +store_part 16 16 0 0 0 0:1:1 + +for {set n 1} {$n < 5} {incr n} { + store_part 4 4 $n $n $n 0:2:$n + store_part 4 4 [expr 16-4-$n] $n $n 0:2:[expr $n+4] + store_part 4 4 $n [expr 16-4-$n] $n 0:2:[expr $n+8] + store_part 4 4 [expr 16-4-$n] [expr 16-4-$n] $n 0:2:[expr $n+12] +} +store_part 6 6 5 5 5 0:3:1 +store_part 4 4 6 6 6 0:3:2 +GetShape D0 0:3:2 top2 + +set docname ${imagedir}/doc_${casename}.cbf +set save_time [lindex [time { + SaveAs D0 ${docname} +}] 0] +puts "Save time $save_time mcs" + +Close D0 + +set whole_time [lindex [time { + Open ${docname} D1 + Close D1 +} 20] 0] +puts "Whole document open time $whole_time mcs" + +set half_time1 [lindex [time { + Open ${docname} D2 -read0:1 -read0:3 + Close D2 +} 20] 0] +puts "First half of document open time $half_time1 mcs" + +set half_time2 [lindex [time { + Open ${docname} D3 -read0:2 + Close D3 +} 20] 0] +puts "Second half of document open time $half_time2 mcs" + +# Check that open of two halfs of the document separately is not too much slower than open of the whole +if { [expr ($half_time1 + $half_time2) * 0.9] > $whole_time } { + puts "Error : loading of half of the document content is too slow relatively to the whole document load" +} + +Open ${docname} D4 -read0:3:2 +GetShape D4 0:3:2 opened_top2 +checkshape opened_top2 + +# check shapes are the same before open and after +if {[string first [whatis top2] [whatis opened_top2]] != 7} { + puts "Error : saved and opened shapes are different" +} +Open ${docname} D4 -append -read0:1 -read0:2 +GetShape D4 0:1:1 s +checkshape s +for {set n 1} {$n < 16} {incr n} { + GetShape D4 0:2:$n s + checkshape s +} +Close D4 + +set no_shapes_time [lindex [time { + Open ${docname} D5 -skipTNaming_NamedShape + Close D5 +} 20] 0] +puts "Document without shapes open time $no_shapes_time mcs" + +# Check that open of the document without shapes is much faster than open of the whole +if { [expr $no_shapes_time * 20] > $whole_time } { + puts "Error : loading of the document without shapes is too slow relatively to the whole document load" +} + +# check shapes storage with triangulations +set length_wo_tirangulation [string length [dump s]] +vinit +vdisplay top2 -displaymode 1 +NewDocument D6 BinOcaf +UndoLimit D6 10 +SetShape D6 0:1 top2 +StoreTriangulation 1 +SaveAs D6 ${docname} +Close D6 + +Open ${docname} D7 +GetShape D7 0:1 top3 +Close D7 + +checkshape top3 + +set length_with_tirangulation [string length [dump top3]] +if { [expr $length_with_tirangulation / 7] < $length_wo_tirangulation } { + puts "Error : looks like shape stored with triangulation loaded without trianulation" +} -- 2.39.5