1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00

0028708: Create a mechanism to serve shape history by a way common for algorithms accepting and producing shapes

A shape history mechanism was created. It supports history for shapes with types
'vertex', 'edge', 'face' and 'solid'. It allows define relations 'generated',
'modified' and 'removed' between the accepted and the produced shapes. It
provides functionality for the other widely used history mechanism 'Generated',
'Modified', 'IsDeleted'. It provides algorithm to merge two histories of
sequentially applied algorithms. Recommendations were formalized to choose
between relations 'generated' and 'modified'.
This commit is contained in:
abk 2017-04-24 16:04:45 +03:00 committed by bugmaster
parent 9fd2d2c382
commit 2c02f319a4
3 changed files with 628 additions and 0 deletions

View File

@ -0,0 +1,422 @@
// Created on: 2017-04-21
// Created by: Alexander Bobkov
// Copyright (c) 2017 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 <BRepTools_History.hxx>
#include <TopExp.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
// Implement the OCCT RTTI for the type.
IMPLEMENT_STANDARD_RTTIEXT(BRepTools_History, Standard_Transient)
namespace
{
//==============================================================================
//function : add
//purpose : Adds the elements of the list to the map.
//==============================================================================
void add(TopTools_MapOfShape& theMap, const TopTools_ListOfShape& theList)
{
for (TopTools_ListOfShape::Iterator aSIt(theList); aSIt.More(); aSIt.Next())
{
theMap.Add(aSIt.Value());
}
}
//==============================================================================
//function : add
//purpose : Adds the elements of the collection to the list.
//==============================================================================
template<typename TCollection>
void add(TopTools_ListOfShape& theList, const TCollection& theCollection)
{
for (typename TCollection::Iterator aSIt(theCollection);
aSIt.More(); aSIt.Next())
{
theList.Append(aSIt.Value());
}
}
}
//==============================================================================
//function : AddGenerated
//purpose :
//==============================================================================
void BRepTools_History::AddGenerated(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
{
if (!prepareGenerated(theInitial, theGenerated))
{
return;
}
TopTools_ListOfShape* aGenerations =
myShapeToGenerated.ChangeSeek(theInitial);
if (aGenerations == NULL)
{
aGenerations = myShapeToGenerated.Bound(theInitial, TopTools_ListOfShape());
}
Standard_ASSERT_VOID(!aGenerations->Contains(theGenerated),
"Error: a duplicated generation of a shape.");
aGenerations->Append(theGenerated);
}
//==============================================================================
//function : AddModified
//purpose :
//==============================================================================
void BRepTools_History::AddModified(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
{
if (!prepareModified(theInitial, theModified))
{
return;
}
TopTools_ListOfShape* aModifications =
myShapeToModified.ChangeSeek(theInitial);
if (aModifications == NULL)
{
aModifications =
myShapeToModified.Bound(theInitial, TopTools_ListOfShape());
}
Standard_ASSERT_VOID(!aModifications->Contains(theModified),
"Error: a duplicated modification of a shape.");
aModifications->Append(theModified);
}
//==============================================================================
//function : Remove
//purpose :
//==============================================================================
void BRepTools_History::Remove(const TopoDS_Shape& theRemoved)
{
// Apply the limitations.
Standard_ASSERT_RETURN(IsSupportedType(theRemoved), myMsgUnsupportedType,);
if (myShapeToGenerated.UnBind(theRemoved))
{
Standard_ASSERT_INVOKE_(, myMsgGeneratedAndRemoved);
}
if (myShapeToModified.UnBind(theRemoved))
{
Standard_ASSERT_INVOKE_(, myMsgModifiedAndRemoved);
}
//
myRemoved.Add(theRemoved);
}
//==============================================================================
//function : ReplaceGenerated
//purpose :
//==============================================================================
void BRepTools_History::ReplaceGenerated(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
{
if (!prepareGenerated(theInitial, theGenerated))
{
return;
}
TopTools_ListOfShape* aGenerations =
myShapeToGenerated.Bound(theInitial, TopTools_ListOfShape());
aGenerations->Append(theGenerated);
}
//==============================================================================
//function : ReplaceModified
//purpose :
//==============================================================================
void BRepTools_History::ReplaceModified(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
{
if (!prepareModified(theInitial, theModified))
{
return;
}
TopTools_ListOfShape* aModifications =
myShapeToModified.Bound(theInitial, TopTools_ListOfShape());
aModifications->Append(theModified);
}
//==============================================================================
//function : Generated
//purpose :
//==============================================================================
const TopTools_ListOfShape& BRepTools_History::Generated(
const TopoDS_Shape& theInitial) const
{
// Apply the limitations.
Standard_ASSERT_RETURN(theInitial.IsNull() || IsSupportedType(theInitial),
myMsgUnsupportedType, emptyList());
//
const TopTools_ListOfShape* aGenerations =
myShapeToGenerated.Seek(theInitial);
return (aGenerations != NULL) ? *aGenerations : emptyList();
}
//==============================================================================
//function : Modified
//purpose :
//==============================================================================
const TopTools_ListOfShape& BRepTools_History::Modified(
const TopoDS_Shape& theInitial) const
{
// Apply the limitations.
Standard_ASSERT_RETURN(IsSupportedType(theInitial),
myMsgUnsupportedType, emptyList());
//
const TopTools_ListOfShape* aModifications =
myShapeToModified.Seek(theInitial);
return (aModifications != NULL) ? *aModifications : emptyList();
}
//==============================================================================
//function : IsRemoved
//purpose :
//==============================================================================
Standard_Boolean BRepTools_History::IsRemoved(
const TopoDS_Shape& theInitial) const
{
// Apply the limitations.
Standard_ASSERT_RETURN(IsSupportedType(theInitial),
myMsgUnsupportedType, Standard_False);
//
return myRemoved.Contains(theInitial);
}
//==============================================================================
//function : Merge
//purpose :
//==============================================================================
void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
{
// Propagate R23 directly and M23 and G23 fully to M12 and G12.
// Remember the propagated shapes.
TopTools_DataMapOfShapeListOfShape* aS1ToGAndM[] =
{&myShapeToGenerated, &myShapeToModified};
TopTools_MapOfShape aRPropagated;
{
// Propagate R23, M23 and G23 to M12 and G12 directly.
// Remember the propagated shapes.
TopTools_MapOfShape aMAndGPropagated;
for (Standard_Integer aI = 0; aI < 2; ++aI)
{
for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt1(*aS1ToGAndM[aI]);
aMIt1.More(); aMIt1.Next())
{
TopTools_ListOfShape& aL12 = aMIt1.ChangeValue();
TopTools_MapOfShape aAdditions[2]; // The G and M additions.
for (TopTools_ListOfShape::Iterator aSIt2(aL12); aSIt2.More();)
{
const TopoDS_Shape& aS2 = aSIt2.Value();
if (theHistory23->IsRemoved(aS2))
{
aL12.Remove(aSIt2);
aRPropagated.Add(aS2);
}
else
{
if (theHistory23->myShapeToGenerated.IsBound(aS2))
{
add(aAdditions[0], theHistory23->myShapeToGenerated(aS2));
aMAndGPropagated.Add(aS2);
}
if (theHistory23->myShapeToModified.IsBound(aS2))
{
add(aAdditions[aI], theHistory23->myShapeToModified(aS2));
aMAndGPropagated.Add(aS2);
aL12.Remove(aSIt2);
}
else
{
aSIt2.Next();
}
}
}
add(aL12, aAdditions[aI]);
if (aI != 0 && !aAdditions[0].IsEmpty())
{
const TopoDS_Shape& aS1 = aMIt1.Key();
TopTools_ListOfShape* aGAndM = aS1ToGAndM[0]->ChangeSeek(aS1);
if (aGAndM == NULL)
{
aGAndM = aS1ToGAndM[0]->Bound(aS1, TopTools_ListOfShape());
}
add(*aGAndM, aAdditions[0]);
}
}
}
// Propagate M23 and G23 to M12 and G12 sequentially.
const TopTools_DataMapOfShapeListOfShape* aS2ToGAndM[] =
{&theHistory23->myShapeToGenerated, &theHistory23->myShapeToModified};
for (Standard_Integer aI = 0; aI < 2; ++aI)
{
for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt2(*aS2ToGAndM[aI]);
aMIt2.More(); aMIt2.Next())
{
const TopoDS_Shape& aS2 = aMIt2.Key();
if (!aMAndGPropagated.Contains(aS2))
{
if (!aS1ToGAndM[aI]->IsBound(aS2))
{
aS1ToGAndM[aI]->Bind(aS2, TopTools_ListOfShape());
}
TopTools_ListOfShape aM2 = aMIt2.Value();
((*aS1ToGAndM[aI])(aS2)).Append(aM2);
}
}
}
}
// Unbound the empty M12 and G12.
for (Standard_Integer aI = 0; aI < 2; ++aI)
{
for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt1(*aS1ToGAndM[aI]);
aMIt1.More();)
{
const TopoDS_Shape& aS1 = aMIt1.Key();
const TopTools_ListOfShape& aL12 = aMIt1.Value();
aMIt1.Next();
if (aL12.IsEmpty())
{
aS1ToGAndM[aI]->UnBind(aS1);
}
}
}
// Propagate R23 to R12 sequentially.
for (TopTools_MapOfShape::Iterator aRIt23(theHistory23->myRemoved);
aRIt23.More(); aRIt23.Next())
{
const TopoDS_Shape& aS2 = aRIt23.Value();
if (!aRPropagated.Contains(aS2) &&
!myShapeToModified.IsBound(aS2) &&
!myShapeToGenerated.IsBound(aS2))
{
myRemoved.Add(aS2);
}
}
}
//==============================================================================
//function : prepareGenerated
//purpose :
//==============================================================================
Standard_Boolean BRepTools_History::prepareGenerated(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
{
Standard_ASSERT_RETURN(theInitial.IsNull() ||
IsSupportedType(theInitial), myMsgUnsupportedType, Standard_False);
if (myRemoved.Remove(theInitial))
{
Standard_ASSERT_INVOKE_(, myMsgGeneratedAndRemoved);
}
if (myShapeToModified.IsBound(theInitial) &&
myShapeToModified(theInitial).Remove(theGenerated))
{
Standard_ASSERT_INVOKE_(, myMsgGeneratedAndModified);
}
return Standard_True;
}
//==============================================================================
//function : prepareModified
//purpose :
//==============================================================================
Standard_Boolean BRepTools_History::prepareModified(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
{
Standard_ASSERT_RETURN(IsSupportedType(theInitial),
myMsgUnsupportedType, Standard_False);
if (myRemoved.Remove(theInitial))
{
Standard_ASSERT_INVOKE_(, myMsgModifiedAndRemoved);
}
if (myShapeToGenerated.IsBound(theInitial) &&
myShapeToGenerated(theInitial).Remove(theModified))
{
Standard_ASSERT_INVOKE_(, myMsgGeneratedAndModified);
}
return Standard_True;
}
//==============================================================================
//data : myEmptyList
//purpose :
//==============================================================================
const TopTools_ListOfShape BRepTools_History::myEmptyList;
//==============================================================================
//function : emptyList
//purpose :
//==============================================================================
const TopTools_ListOfShape& BRepTools_History::emptyList()
{
return myEmptyList;
}
//==============================================================================
//data : myMsgUnsupportedType
//purpose :
//==============================================================================
const char* BRepTools_History::myMsgUnsupportedType =
"Error: unsupported shape type.";
//==============================================================================
//data : myMsgGeneratedAndRemoved
//purpose :
//==============================================================================
const char* BRepTools_History::myMsgGeneratedAndRemoved =
"Error: a shape is generated and removed simultaneously.";
//==============================================================================
//data : myMsgModifiedAndRemoved
//purpose :
//==============================================================================
const char* BRepTools_History::myMsgModifiedAndRemoved =
"Error: a shape is modified and removed simultaneously.";
//==============================================================================
//data : myMsgGeneratedAndModified
//purpose :
//==============================================================================
const char* BRepTools_History::myMsgGeneratedAndModified =
"Error: a shape is generated and modified "
"from the same shape simultaneously.";

View File

@ -0,0 +1,204 @@
// Created on: 2017-04-21
// Created by: Alexander Bobkov
// Copyright (c) 2017 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 _BRepTools_History_HeaderFile
#define _BRepTools_History_HeaderFile
#include <NCollection_Handle.hxx>
#include <TopTools_DataMapOfShapeListOfShape.hxx>
#include <TopTools_MapOfShape.hxx>
class BRepTools_History;
DEFINE_STANDARD_HANDLE(BRepTools_History, Standard_Transient)
//! The history keeps the following relations between the input shapes
//! (S1, ..., Sm) and output shapes (T1, ..., Tn):
//! 1) an output shape Tj is generated from an input shape Si: Tj <= G(Si);
//! 2) a output shape Tj is modified from an input shape Si: Tj <= M(Si);
//! 3) an input shape (Si) is removed: R(Si) == 1.
//!
//! The relations are kept only for shapes of types vertex, edge, face, and
//! solid.
//!
//! The last relation means that:
//! 1) shape Si is not an output shape and
//! 2) no any shape is generated or modified (produced) from shape Si:
//! R(Si) == 1 ==> Si != Tj, G(Si) == 0, M(Si) == 0.
//!
//! No any shape could be generated and modified from the same shape
//! simultaneously: sets G(Si) and M(Si) are not intersected
//! (G(Si) ^ M(Si) == 0).
//!
//! Each output shape should be:
//! 1) an input shape or
//! 2) generated or modified from an input shape (even generated from the
//! implicit null shape if necessary):
//! Tj == Si V (exists Si that Tj <= G(Si) U M(Si)).
//!
//! Recommendations to choose between relations 'generated' and 'modified':
//! 1) a shape is generated from input shapes if it dimension is greater or
//! smaller than the dimensions of the input shapes;
//! 2) a shape is generated from input shapes if these shapes are also output
//! shapes;
//! 3) a shape is generated from input shapes of the same dimension if it is
//! produced by joining shapes generated from these shapes;
//! 4) a shape is modified from an input shape if it replaces the input shape by
//! changes of the location, the tolerance, the bounds of the parametrical
//! space (the faces for a solid), the parametrization and/or by applying of
//! an approximation;
//! 5) a shape is modified from input shapes of the same dimension if it is
//! produced by joining shapes modified from these shapes.
//!
//! Two sequential histories:
//! - one history (H12) of shapes S1, ..., Sm to shapes T1, ..., Tn and
//! - another history (H23) of shapes T1, ..., Tn to shapes Q1, ..., Ql
//! could be merged to the single history (H13) of shapes S1, ..., Sm to shapes
//! Q1, ..., Ql.
//!
//! During the merge:
//! 1) if shape Tj is generated from shape Si then each shape generated or
//! modified from shape Tj is considered as a shape generated from shape Si
//! among shapes Q1, ..., Ql:
//! Tj <= G12(Si), Qk <= G23(Tj) U M23(Tj) ==> Qk <= G13(Si).
//! 2) if shape Tj is modified from shape Si, shape Qk is generated from shape
//! Tj then shape Qk is considered as a shape generated from shape Si among
//! shapes Q1, ..., Ql:
//! Tj <= M12(Si), Qk <= G23(Tj) ==> Qk <= G13(Si);
//! 3) if shape Tj is modified from shape Si, shape Qk is modified from shape
//! Tj then shape Qk is considered as a shape modified from shape Si among
//! shapes Q1, ..., Ql:
//! Tj <= M12(Si), Qk <= M23(Tj) ==> Qk <= M13(Si);
class BRepTools_History: public Standard_Transient
{
public:
//! The types of the historical relations.
enum TRelationType
{
TRelationType_Removed,
TRelationType_Generated,
TRelationType_Modified
};
public:
//! Returns 'true' if the type of the shape is supported by the history.
static Standard_Boolean IsSupportedType(const TopoDS_Shape& theShape)
{
const TopAbs_ShapeEnum aType = theShape.ShapeType();
return aType == TopAbs_VERTEX || aType == TopAbs_EDGE ||
aType == TopAbs_FACE || aType == TopAbs_SOLID;
}
public: //! Methods to set the history.
//! Set the second shape as generated one from the first shape.
Standard_EXPORT void AddGenerated(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated);
//! Set the second shape as modified one from the first shape.
Standard_EXPORT void AddModified(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified);
//! Set the shape as removed one.
Standard_EXPORT void Remove(const TopoDS_Shape& theRemoved);
//! Set the second shape as the only generated one from the first one.
Standard_EXPORT void ReplaceGenerated(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated);
//! Set the second shape as the only modified one from the first one.
Standard_EXPORT void ReplaceModified(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified);
//! Clears the history.
void Clear()
{
myShapeToModified.Clear();
myShapeToGenerated.Clear();
myRemoved.Clear();
}
public: //! Methods to read the history.
//! Returns all shapes generated from the shape.
Standard_EXPORT
const TopTools_ListOfShape& Generated(const TopoDS_Shape& theInitial) const;
//! Returns all shapes modified from the shape.
Standard_EXPORT
const TopTools_ListOfShape& Modified(const TopoDS_Shape& theInitial) const;
//! Returns 'true' if the shape is removed.
Standard_EXPORT
Standard_Boolean IsRemoved(const TopoDS_Shape& theInitial) const;
public: //! A method to merge a next history to this history.
//! Merges the next history to this history.
Standard_EXPORT void Merge(const Handle(BRepTools_History)& theHistory23);
public:
//! Define the OCCT RTTI for the type.
DEFINE_STANDARD_RTTIEXT(BRepTools_History, Standard_Transient)
private:
//! Prepares the shapes generated from the first shape to set the second one
//! as generated one from the first one by the addition or the replacement.
//! Returns 'true' on success.
Standard_Boolean prepareGenerated(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated);
//! Prepares the shapes modified from the first shape to set the second one
//! as modified one from the first one by the addition or the replacement.
//! Returns 'true' on success.
Standard_Boolean prepareModified(
const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified);
private: //! Data to keep the history.
//! Maps each input shape to all shapes modified from it.
//! If an input shape is not bound to the map then
//! there is no shapes modified from the shape.
//! No any shape should be mapped to an empty list.
TopTools_DataMapOfShapeListOfShape myShapeToModified;
//! Maps each input shape to all shapes generated from it.
//! If an input shape is not bound to the map then
//! there is no shapes generated from the shape.
//! No any shape should be mapped to an empty list.
TopTools_DataMapOfShapeListOfShape myShapeToGenerated;
TopTools_MapOfShape myRemoved; //!< The removed shapes.
private: //! Auxiliary members to read the history.
//! An auxiliary empty list.
static const TopTools_ListOfShape myEmptyList;
//! A method to export the auxiliary list.
Standard_EXPORT static const TopTools_ListOfShape& emptyList();
private:
//! Auxiliary messages.
static const char* myMsgUnsupportedType;
static const char* myMsgGeneratedAndRemoved;
static const char* myMsgModifiedAndRemoved;
static const char* myMsgGeneratedAndModified;
};
#endif // _BRepTools_History_HeaderFile

View File

@ -4,6 +4,8 @@ BRepTools_DataMapIteratorOfMapOfVertexPnt2d.hxx
BRepTools_Debug.cxx
BRepTools_GTrsfModification.cxx
BRepTools_GTrsfModification.hxx
BRepTools_History.hxx
BRepTools_History.cxx
BRepTools_MapOfVertexPnt2d.hxx
BRepTools_Modification.cxx
BRepTools_Modification.hxx