1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/XmlMNaming/XmlMNaming_NamedShapeDriver.cxx
vro 6cb968fd6f 0032757: Application Framework, scaling transformation - loading of an OCAF XML document fails
A flag not to raise an exception is used on reading of an OCAF document. If such a shape with scaling transformation is stored in the document, it should be read.

Modified files:
XmlMNaming\XmlMNaming_NamedShapeDriver.cxx: not checking of the type of transformation for a read shape
2022-01-10 19:43:48 +03:00

418 lines
15 KiB
C++

// Created on: 2001-07-11
// Created by: Julia DOROVSKIKH
// Copyright (c) 2001-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.
//AGV 150202: Changed prototype LDOM_Node::getOwnerDocument()
#include <BRepTools.hxx>
#include <Message_Messenger.hxx>
#include <Message_ProgressScope.hxx>
#include <LDOM_OSStream.hxx>
#include <LDOM_Text.hxx>
#include <Standard_SStream.hxx>
#include <Standard_Type.hxx>
#include <TDF_Attribute.hxx>
#include <TDF_Label.hxx>
#include <TNaming_Builder.hxx>
#include <TNaming_Iterator.hxx>
#include <TNaming_NamedShape.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_LocationSet.hxx>
#include <XmlLDrivers.hxx>
#include <XmlMNaming_NamedShapeDriver.hxx>
#include <XmlMNaming_Shape1.hxx>
#include <XmlObjMgt.hxx>
#include <XmlObjMgt_Array1.hxx>
#include <XmlObjMgt_Persistent.hxx>
IMPLEMENT_STANDARD_RTTIEXT(XmlMNaming_NamedShapeDriver,XmlMDF_ADriver)
static TNaming_Evolution EvolutionEnum (const XmlObjMgt_DOMString&);
static const XmlObjMgt_DOMString& EvolutionString (const TNaming_Evolution);
static void doTranslate (const TopoDS_Shape&,
XmlMNaming_Shape1&,
BRepTools_ShapeSet&);
static int doTranslate (const XmlMNaming_Shape1&,
TopoDS_Shape&,
BRepTools_ShapeSet&);
IMPLEMENT_DOMSTRING (OldsString, "olds")
IMPLEMENT_DOMSTRING (NewsString, "news")
IMPLEMENT_DOMSTRING (StatusString, "evolution")
IMPLEMENT_DOMSTRING (VersionString, "version")
IMPLEMENT_DOMSTRING (ShapesString, "shapes")
IMPLEMENT_DOMSTRING (EvolPrimitiveString, "primitive")
IMPLEMENT_DOMSTRING (EvolGeneratedString, "generated")
IMPLEMENT_DOMSTRING (EvolModifyString, "modify")
IMPLEMENT_DOMSTRING (EvolDeleteString, "delete")
IMPLEMENT_DOMSTRING (EvolSelectedString, "selected")
IMPLEMENT_DOMSTRING (EvolReplaceString, "replace")
//=======================================================================
//function : XmlMNaming_NamedShapeDriver
//purpose : Constructor
//=======================================================================
XmlMNaming_NamedShapeDriver::XmlMNaming_NamedShapeDriver
(const Handle(Message_Messenger)& theMessageDriver)
: XmlMDF_ADriver (theMessageDriver, NULL),
myShapeSet (Standard_False) // triangles mode
{}
//=======================================================================
//function : NewEmpty()
//purpose :
//=======================================================================
Handle(TDF_Attribute) XmlMNaming_NamedShapeDriver::NewEmpty () const
{
return (new TNaming_NamedShape());
}
//=======================================================================
//function : Paste()
//purpose : retrieval of TNaming_NamedShape
//=======================================================================
Standard_Boolean XmlMNaming_NamedShapeDriver::Paste
(const XmlObjMgt_Persistent& theSource,
const Handle(TDF_Attribute)& theTarget,
XmlObjMgt_RRelocationTable&) const
{
Handle(TNaming_NamedShape) aTarget =
Handle(TNaming_NamedShape)::DownCast(theTarget);
TDF_Label Label = aTarget -> Label();
TNaming_Builder aBld (Label);
// Get Version
Standard_Integer aVersion = 0;
const XmlObjMgt_Element& anElement = theSource;
XmlObjMgt_DOMString aVerString = anElement.getAttribute (::VersionString());
if (aVerString != NULL)
aVerString.GetInteger (aVersion);
// Get Evolution status
XmlObjMgt_DOMString aStatus = anElement.getAttribute (::StatusString());
TNaming_Evolution evol = EvolutionEnum (aStatus);
// apres creation Builder qui a mis la version a 1 :
aTarget -> SetVersion (aVersion);
const XmlObjMgt_Array1 OldPShapes (anElement, ::OldsString());
const XmlObjMgt_Array1 NewPShapes (anElement, ::NewsString());
if (NewPShapes.Length() == 0 && OldPShapes.Length() == 0)
return Standard_True;
TopoDS_Shape anOldShape;
TopoDS_Shape aNewShape;
BRepTools_ShapeSet& aShapeSet = (BRepTools_ShapeSet&) myShapeSet;
Standard_Integer lower = NewPShapes.Lower();
if (OldPShapes.Lower() < lower) lower = OldPShapes.Lower();
Standard_Integer upper = NewPShapes.Upper();
if (OldPShapes.Upper() > upper) upper = OldPShapes.Upper();
for (Standard_Integer i = upper; i >= lower; --i)
{
const XmlMNaming_Shape1 aNewPShape = NewPShapes.Value(i);
const XmlMNaming_Shape1 anOldPShape = OldPShapes.Value(i);
if ( evol != TNaming_PRIMITIVE && anOldPShape.Element() != NULL )
{
if (::doTranslate (anOldPShape, anOldShape, aShapeSet)) {
myMessageDriver->Send ("NamedShapeDriver: Error reading a shape from array", Message_Fail);
return Standard_False;
}
}
if (evol != TNaming_DELETE && aNewPShape.Element() != NULL )
{
if (::doTranslate (aNewPShape, aNewShape, aShapeSet)) {
myMessageDriver->Send ("NamedShapeDriver: Error reading a shape from array", Message_Fail);
return Standard_False;
}
}
switch (evol)
{
case TNaming_PRIMITIVE:
aBld.Generated(aNewShape);
break;
case TNaming_GENERATED:
aBld.Generated(anOldShape,aNewShape);
break;
case TNaming_MODIFY:
aBld.Modify(anOldShape,aNewShape);
break;
case TNaming_DELETE:
aBld.Delete(anOldShape);
break;
case TNaming_SELECTED:
aBld.Select(aNewShape, anOldShape);
break;
case TNaming_REPLACE:
aBld.Modify(anOldShape,aNewShape);
break; // for compatibility
// case TNaming_REPLACE:
// aBld.Replace(anOldShape,aNewShape);
// break;
default:
throw Standard_DomainError("TNaming_Evolution; enum term unknown");
}
anOldShape.Nullify();
aNewShape.Nullify();
}
return Standard_True;
}
//=======================================================================
//function : Paste()
//purpose : storage of TNaming_NamedShape
//=======================================================================
void XmlMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource,
XmlObjMgt_Persistent& theTarget,
XmlObjMgt_SRelocationTable&) const
{
//AGV XmlObjMgt_Document& aDoc =
//AGV (XmlObjMgt_Document&) theTarget.Element().getOwnerDocument();
XmlObjMgt_Document aDoc =
XmlObjMgt_Document (theTarget.Element().getOwnerDocument());
Handle(TNaming_NamedShape) aNamedShape =
Handle(TNaming_NamedShape)::DownCast(theSource);
TNaming_Evolution evol = aNamedShape->Evolution();
// Create arrays
Standard_Integer NbShapes = 0;
TNaming_Iterator SItr (aNamedShape);
while (SItr.More()) {
NbShapes++;
SItr.Next ();
}
BRepTools_ShapeSet& aShapeSet = (BRepTools_ShapeSet&) myShapeSet;
XmlObjMgt_Array1 OldPShapes (1,NbShapes), NewPShapes (1,NbShapes);
OldPShapes.CreateArrayElement (theTarget, ::OldsString());
NewPShapes.CreateArrayElement (theTarget, ::NewsString());
// Fill arrays
Standard_Integer i = 1;
TNaming_Iterator SIterator(aNamedShape);
while (SIterator.More())
{
const TopoDS_Shape& OldShape = SIterator.OldShape();
const TopoDS_Shape& NewShape = SIterator.NewShape();
if ( evol != TNaming_PRIMITIVE )
{
XmlMNaming_Shape1 anOldPShape (aDoc);
::doTranslate (OldShape, anOldPShape, aShapeSet);
OldPShapes.SetValue (i, anOldPShape.Element());
}
if (evol != TNaming_DELETE)
{
XmlMNaming_Shape1 aNewPShape (aDoc);
::doTranslate (NewShape, aNewPShape, aShapeSet);
NewPShapes.SetValue (i, aNewPShape.Element());
}
i++;
SIterator.Next();
}
theTarget.Element().setAttribute (::StatusString(), EvolutionString(evol));
Standard_Integer aVersion = aNamedShape -> Version();
if (aVersion != 0)
theTarget.Element().setAttribute (::VersionString(), aVersion);
}
//=======================================================================
//function : EvolutionEnum
//purpose : static
//=======================================================================
static const XmlObjMgt_DOMString& EvolutionString(const TNaming_Evolution i)
{
switch(i) {
case TNaming_PRIMITIVE : return ::EvolPrimitiveString();
case TNaming_GENERATED : return ::EvolGeneratedString();
case TNaming_MODIFY : return ::EvolModifyString();
case TNaming_DELETE : return ::EvolDeleteString();
case TNaming_SELECTED : return ::EvolSelectedString();
case TNaming_REPLACE : return ::EvolModifyString(); // case TNaming_REPLACE : return ::EvolReplaceString(); for compatibility
default:
throw Standard_DomainError("TNaming_Evolution; enum term unknown");
}
}
//=======================================================================
//function : EvolutionEnum
//purpose : static
//=======================================================================
static TNaming_Evolution EvolutionEnum (const XmlObjMgt_DOMString& theString)
{
TNaming_Evolution aResult = TNaming_PRIMITIVE;
if (theString.equals (::EvolPrimitiveString()) == Standard_False) {
if (theString.equals (::EvolGeneratedString()))
aResult = TNaming_GENERATED;
else if (theString.equals (::EvolModifyString()))
aResult = TNaming_MODIFY;
else if (theString.equals (::EvolDeleteString()))
aResult = TNaming_DELETE;
else if (theString.equals (::EvolSelectedString()))
aResult = TNaming_SELECTED;
else if (theString.equals (::EvolReplaceString()))
aResult = TNaming_MODIFY; // for compatibility //TNaming_REPLACE;
else
throw Standard_DomainError("TNaming_Evolution; string value without enum term equivalence");
}
return aResult;
}
//=======================================================================
//function : doTranslate
//purpose : shape storage to XML
//=======================================================================
static void doTranslate (const TopoDS_Shape& theShape,
XmlMNaming_Shape1& theResult,
BRepTools_ShapeSet& theShapeSet)
{
// Check for empty shape
if (theShape.IsNull()) return;
// Add to shape set both TShape and Location contained in theShape
const Standard_Integer aTShapeId = theShapeSet.Add (theShape);
const Standard_Integer aLocId =
theShapeSet.Locations().Index (theShape.Location());
// Fill theResult with shape parameters: TShape ID, Location, Orientation
theResult.SetShape (aTShapeId, aLocId, theShape.Orientation());
if (theShape.ShapeType() == TopAbs_VERTEX)
{
theResult.SetVertex(theShape);
}
}
//=======================================================================
//function : doTranslate
//purpose : shape retrieval from XML
//=======================================================================
static int doTranslate (const XmlMNaming_Shape1& thePShape,
TopoDS_Shape& theResult,
BRepTools_ShapeSet& theShapeSet)
{
const Standard_Integer aShapeId = thePShape.TShapeId();
// Read TShape and Orientation
if (aShapeId <= 0 || aShapeId > theShapeSet.NbShapes())
return 1;
theResult.TShape (theShapeSet.Shape(aShapeId).TShape());
theResult.Orientation (thePShape.Orientation());
theResult.Location (theShapeSet.Locations().Location (thePShape.LocId()), false);
return 0;
}
//=======================================================================
//function : ReadShapeSection
//purpose :
//=======================================================================
void XmlMNaming_NamedShapeDriver::ReadShapeSection (const XmlObjMgt_Element& theElement,
const Message_ProgressRange& theRange)
{
XmlObjMgt_Element anElement =
XmlObjMgt::FindChildByName (theElement, ::ShapesString());
if (anElement != NULL) {
for (LDOM_Node aNode = anElement.getFirstChild();
aNode != NULL;
aNode = anElement.getNextSibling())
{
if (aNode.getNodeType() == LDOM_Node::TEXT_NODE) {
LDOMString aData = aNode.getNodeValue();
std::stringstream aStream (std::string(aData.GetString()));
myShapeSet.Clear();
myShapeSet.Read (aStream, theRange);
break;
}
}
}
}
//=======================================================================
//function : WriteShapeSection
//purpose :
//=======================================================================
void XmlMNaming_NamedShapeDriver::WriteShapeSection (XmlObjMgt_Element& theElement,
TDocStd_FormatVersion theStorageFormatVersion,
const Message_ProgressRange& theRange)
{
// Create "shapes" element and append it as child
XmlObjMgt_Document aDoc = theElement.getOwnerDocument();
XmlObjMgt_Element anElement = aDoc.createElement (::ShapesString());
theElement.appendChild (anElement);
// Add text to the "shapes" element
if (myShapeSet.NbShapes() > 0)
{
if (theStorageFormatVersion >= TDocStd_FormatVersion_VERSION_11)
{
myShapeSet.SetFormatNb(TopTools_FormatVersion_VERSION_3);
}
else
{
myShapeSet.SetFormatNb(TopTools_FormatVersion_VERSION_1);
}
LDOM_OSStream aStream (16 * 1024);
// ostrstream aStream;
// aStream.rdbuf() -> setbuf (0, 16380);
Message_ProgressScope aPS(theRange, "Writing shape section", 2);
myShapeSet.Write (aStream, aPS.Next());
if (!aPS.More())
return;
aStream << std::ends;
char * aStr = (char *)aStream.str();
LDOM_Text aText = aDoc.createTextNode (aStr);
delete [] aStr;
aText.SetValueClear(); // There are no characters '<' and '&' and like
// aStream.rdbuf() -> freeze(0); // release the buffer
anElement.appendChild (aText);
// Clear the shape set to avoid appending to it on the next write
BRepTools_ShapeSet& aShapeSet = (BRepTools_ShapeSet&) myShapeSet;
aShapeSet.Clear();
if (!aPS.More())
return;
aPS.Next();
}
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void XmlMNaming_NamedShapeDriver::Clear()
{
myShapeSet.Clear();
}