1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0029683: Add functionality to make the TopoDS_Shape periodic in 3D space

Implementation of the new class *BOPAlgo_MakePeriodic* for making the shape periodic in 3D space.
Periodicity of the shape means that the shape can be repeated in any periodic direction any number of times without creation of the new geometry or splits.
The idea of this algorithm is to make the shape look similarly on the opposite sides or on the period bounds of periodic directions.
It does not mean that the opposite sides of the shape will be mirrored. It just means the the opposite sides of the shape should be split by each other and obtain the same geometry on opposite sides.
Such approach will allow repeating the shape, i.e. translating the copy of a shape on the period, without creation of new geometry because there will be no coinciding parts of different dimension.

Draw commands for the new algorithm:
* makeperiodic - makes the shape periodic in required directions;
* repeatshape - repeats the periodic shape in requested periodic direction;
* periodictwins - returns the periodic twins for the shape;
* clearrepetitions - clears all previous repetitions of the periodic shape.

Documentation & test cases for the algorithm.
This commit is contained in:
emv
2018-03-19 07:50:06 +03:00
committed by apn
parent e9c073b866
commit 53a73fc1d1
31 changed files with 2093 additions and 50 deletions

View File

@@ -100,3 +100,15 @@ Unable to orient the shape correctly
.BOPAlgo_AlertUnknownShape
Shape is unknown for operation
.BOPAlgo_AlertNoPeriodicityRequired
No periodicity has been requested for the shape
.BOPAlgo_AlertUnableToTrim
Unable to trim the shape for making it periodic (BOP Common fails)
.BOPAlgo_AlertUnableToMakeIdentical
Unable to make the shape to look identical on opposite sides (Splitter fails)
.BOPAlgo_AlertUnableToRepeat
Unable to repeat the shape (Gluer fails)

View File

@@ -30,7 +30,7 @@ DEFINE_SIMPLE_ALERT(BOPAlgo_AlertBuilderFailed)
//! The intersection of the arguments has failed
DEFINE_SIMPLE_ALERT(BOPAlgo_AlertIntersectionFailed)
//! The type of Boolean Operation is not set
//! More than one argument is provided
DEFINE_SIMPLE_ALERT(BOPAlgo_AlertMultipleArguments)
//! The Pave Filler (the intersection tool) has not been created
@@ -114,4 +114,16 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToOrientTheShape)
//! Shape is unknown for operation
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnknownShape)
//! No periodicity has been requested for the shape
DEFINE_SIMPLE_ALERT(BOPAlgo_AlertNoPeriodicityRequired)
//! Unable to trim the shape for making it periodic (BOP Common fails)
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToTrim)
//! Unable to make the shape to look identical on opposite sides (Splitter fails)
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToMakeIdentical)
//! Unable to repeat the shape (Gluer fails)
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToRepeat)
#endif // _BOPAlgo_Alerts_HeaderFile

View File

@@ -102,4 +102,16 @@ static const char BOPAlgo_BOPAlgo_msg[] =
"Unable to orient the shape correctly\n"
"\n"
".BOPAlgo_AlertUnknownShape\n"
"Shape is unknown for operation\n";
"Shape is unknown for operation\n"
"\n"
".BOPAlgo_AlertNoPeriodicityRequired\n"
"No periodicity has been requested for the shape\n"
"\n"
".BOPAlgo_AlertUnableToTrim\n"
"Unable to trim the shape for making it periodic (BOP Common fails)\n"
"\n"
".BOPAlgo_AlertUnableToMakeIdentical\n"
"Unable to make the shape to look identical on opposite sides (Splitter fails)\n"
"\n"
".BOPAlgo_AlertUnableToRepeat\n"
"Unable to repeat the shape (Gluer fails)\n";

View File

@@ -112,32 +112,35 @@ void BOPAlgo_Builder::FillImagesVertices()
//function : BuildResult
//purpose :
//=======================================================================
void BOPAlgo_Builder::BuildResult(const TopAbs_ShapeEnum theType)
void BOPAlgo_Builder::BuildResult(const TopAbs_ShapeEnum theType)
{
TopAbs_ShapeEnum aType;
BRep_Builder aBB;
TopTools_MapOfShape aM;
TopTools_ListIteratorOfListOfShape aIt, aItIm;
//
aIt.Initialize(myArguments);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aS=aIt.Value();
aType=aS.ShapeType();
if (aType==theType) {
if (myImages.IsBound(aS)){
const TopTools_ListOfShape& aLSIm=myImages.Find(aS);
aItIm.Initialize(aLSIm);
for (; aItIm.More(); aItIm.Next()) {
const TopoDS_Shape& aSIm=aItIm.Value();
if (aM.Add(aSIm)) {
aBB.Add(myShape, aSIm);
}
}
}
else {
if (aM.Add(aS)) {
aBB.Add(myShape, aS);
}
// Fence map
TopTools_MapOfShape aMFence;
// Iterate on all arguments of given type
// and add their images into result
TopTools_ListIteratorOfListOfShape aItA(myArguments);
for (; aItA.More(); aItA.Next())
{
const TopoDS_Shape& aS = aItA.Value();
if (aS.ShapeType() != theType)
continue;
// Get images
const TopTools_ListOfShape* pLSIm = myImages.Seek(aS);
if (!pLSIm)
{
// No images -> add the argument shape itself into result
if (aMFence.Add(aS))
BRep_Builder().Add(myShape, aS);
}
else
{
// Add images of the argument shape into result
TopTools_ListIteratorOfListOfShape aItIm(*pLSIm);
for (; aItIm.More(); aItIm.Next())
{
const TopoDS_Shape& aSIm = aItIm.Value();
if (aMFence.Add(aSIm))
BRep_Builder().Add(myShape, aSIm);
}
}
}

View File

@@ -0,0 +1,617 @@
// Created on: 2018-03-16
// Created by: Eugeny MALTCHIKOV
// Copyright (c) 2018 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 <BOPAlgo_MakePeriodic.hxx>
#include <BOPAlgo_Alerts.hxx>
#include <Bnd_Box.hxx>
#include <BOPAlgo_Builder.hxx>
#include <BOPAlgo_PaveFiller.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Splitter.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <gp_Pln.hxx>
#include <Precision.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
// Periodic/Trim/Repeat directions
static const gp_Dir MY_DIRECTIONS[3] = { gp::DX(),
gp::DY(),
gp::DZ() };
//=======================================================================
//function : Perform
//purpose : Performs the operation
//=======================================================================
void BOPAlgo_MakePeriodic::Perform()
{
// Check the validity of input data
CheckData();
if (HasErrors())
return;
// Trim the shape to fit to the required period in
// required periodic directions
Trim();
if (HasErrors())
return;
// Make the shape identical on the opposite sides in
// required periodic directions
MakeIdentical();
if (HasErrors())
return;
}
//=======================================================================
//function : CheckData
//purpose : Checks the validity of input data
//=======================================================================
void BOPAlgo_MakePeriodic::CheckData()
{
if ( (!IsXPeriodic() || XPeriod() < Precision::Confusion())
&& (!IsYPeriodic() || YPeriod() < Precision::Confusion())
&& (!IsZPeriodic() || ZPeriod() < Precision::Confusion()))
{
// Add error informing the user that no periodicity is required
// or no valid period is set.
AddError(new BOPAlgo_AlertNoPeriodicityRequired());
return;
}
}
//=======================================================================
//function : AddToShape
//purpose : Adds the shape <theWhat> to the shape <theWhere>
//=======================================================================
static void AddToShape(const TopoDS_Shape& theWhat,
TopoDS_Shape& theWhere)
{
if (theWhere.IsNull())
BRep_Builder().MakeCompound(TopoDS::Compound(theWhere));
BRep_Builder().Add(theWhere, theWhat);
}
//=======================================================================
//function : AddToShape
//purpose : Adds the shape in the list <theLWhat> to the shape <theWhere>
//=======================================================================
static void AddToShape(const TopTools_ListOfShape& theLWhat,
TopoDS_Shape& theWhere)
{
TopTools_ListIteratorOfListOfShape it(theLWhat);
for (; it.More(); it.Next())
AddToShape(it.Value(), theWhere);
}
//=======================================================================
//function : Trim
//purpose : Make the trim of the shape to fit to the periodic bounds.
//=======================================================================
void BOPAlgo_MakePeriodic::Trim()
{
// Check if trim is required at all
if (IsInputXTrimmed() &&
IsInputYTrimmed() &&
IsInputZTrimmed())
return;
// Compute bounding box for the shape to use it as a starting
// volume for trimming. If required, the volume will be modified
// to the requested trimming size in requested directions.
Bnd_Box aBox;
BRepBndLib::Add(myInputShape, aBox);
// Enlarge box to avoid overlapping with the shape
aBox.Enlarge(0.1 * sqrt(aBox.SquareExtent()));
// Get Corner points of the bounding box
gp_Pnt aPMin = aBox.CornerMin();
gp_Pnt aPMax = aBox.CornerMax();
// Update corner points according to the requested trim parameters
for (Standard_Integer i = 0; i < 3; ++i)
{
if (IsInputTrimmed(i))
continue;
aPMin.SetCoord(i + 1, PeriodFirst(i));
aPMax.SetCoord(i + 1, PeriodFirst(i) + Period(i));
}
// Build Trimming solid using corner points
BRepPrimAPI_MakeBox aMBox(aPMin, aPMax);
const TopoDS_Shape& aTrimBox = aMBox.Solid();
// Perform trimming of the shape by solid
BRepAlgoAPI_Common aCommon;
// Set Object
TopTools_ListOfShape anObj;
anObj.Append(myInputShape);
aCommon.SetArguments(anObj);
// Set Tool
TopTools_ListOfShape aTool;
aTool.Append(aTrimBox);
aCommon.SetTools(aTool);
// Set the parallel processing mode
aCommon.SetRunParallel(myRunParallel);
// Build
aCommon.Build();
if (aCommon.HasErrors())
{
// Unable to trim the shape
// Merge errors from Common operation
myReport->Merge(aCommon.GetReport());
// Add new error saving the shapes for analysis
TopoDS_Compound aWS;
AddToShape(myInputShape, aWS);
AddToShape(aTrimBox, aWS);
AddError(new BOPAlgo_AlertUnableToTrim(aWS));
return;
}
// Get the trimmed shape
myShape = aCommon.Shape();
// Fill the History for the object only
mySplitHistory = new BRepTools_History();
mySplitHistory->Merge(anObj, aCommon);
}
//=======================================================================
//function : MakeIdentical
//purpose : Make the shape look the same on the opposite sides in the
// required periodic directions.
//=======================================================================
void BOPAlgo_MakePeriodic::MakeIdentical()
{
if (myShape.IsNull())
myShape = myInputShape;
if (mySplitHistory.IsNull())
mySplitHistory = new BRepTools_History;
// Split the negative side of the shape with the geometry
// located on the positive side
SplitNegative();
if (HasErrors())
return;
// Split the positive side of the shape with the geometry
// located on the negative side.
// Make sure that the opposite sides have identical geometries.
// Make associations between identical opposite shapes.
SplitPositive();
myHistory = new BRepTools_History();
myHistory->Merge(mySplitHistory);
}
//=======================================================================
//function : SplitNegative
//purpose : Split the negative side of the shape with the geometry
// located on the positive side.
//=======================================================================
void BOPAlgo_MakePeriodic::SplitNegative()
{
// Copy geometry from positive side of the shape to the negative first.
// So, translate the shape in negative periodic directions only.
//
// To avoid conflicts when copying geometries from positive periodic sides
// perform split of each periodic side in a separate operation.
for (Standard_Integer i = 0; i < 3; ++i)
{
if (!IsPeriodic(i))
continue;
// Translate the shape to the negative side
gp_Trsf aNegTrsf;
aNegTrsf.SetTranslationPart(Period(i) * MY_DIRECTIONS[i].Reversed());
BRepBuilderAPI_Transform aNegT(myShape, aNegTrsf, Standard_False);
// Split the negative side of the shape.
TopTools_ListOfShape aTools;
aTools.Append(aNegT.Shape());
SplitShape(aTools, mySplitHistory);
}
}
//=======================================================================
//function : AddTwin
//purpose : Associates the shape <theS> with the shape <theTwin> in the map.
//=======================================================================
static void AddTwin(const TopoDS_Shape& theS,
const TopoDS_Shape& theTwin,
TopTools_DataMapOfShapeListOfShape& theMap)
{
TopTools_ListOfShape *aTwins = theMap.ChangeSeek(theS);
if (!aTwins)
{
theMap.Bound(theS, TopTools_ListOfShape())->Append(theTwin);
return;
}
// Check if the twin shape is not yet present in the list
TopTools_ListIteratorOfListOfShape itLT(*aTwins);
for (; itLT.More(); itLT.Next())
{
if (theTwin.IsSame(itLT.Value()))
break;
}
if (!itLT.More())
aTwins->Append(theTwin);
}
//=======================================================================
//function : SplitPositive
//purpose : Split the positive side of the shape with the geometry of the
// negative side. Associate the identical opposite sub-shapes.
//=======================================================================
void BOPAlgo_MakePeriodic::SplitPositive()
{
// Prepare map of the sub-shapes of the input shape to make
// associations of the opposite shapes
TopTools_IndexedMapOfShape aSubShapesMap;
TopExp::MapShapes(myShape, aSubShapesMap);
const Standard_Integer aNbS = aSubShapesMap.Extent();
// Translate the shape to the positive periodic directions to make the
// shapes look identical on the opposite sides.
TopTools_ListOfShape aTools;
// Remember the history of shapes translation
TopTools_IndexedDataMapOfShapeListOfShape aTranslationHistMap;
// Make translations for all periodic directions
for (Standard_Integer i = 0; i < 3; ++i)
{
if (!IsPeriodic(i))
continue;
// Translate the shape to the positive side
gp_Trsf aPosTrsf;
aPosTrsf.SetTranslationPart(Period(i) * MY_DIRECTIONS[i]);
BRepBuilderAPI_Transform aTranslator(myShape, aPosTrsf, Standard_False);
aTools.Append(aTranslator.Shape());
// Fill the translation history map
for (Standard_Integer j = 1; j <= aNbS; ++j)
{
const TopoDS_Shape& aS = aSubShapesMap(j);
if (BRepTools_History::IsSupportedType(aS))
{
const TopTools_ListOfShape& aSM = aTranslator.Modified(aS);
TopTools_ListOfShape* pTS = aTranslationHistMap.ChangeSeek(aS);
if (!pTS)
pTS = &aTranslationHistMap(aTranslationHistMap.Add(aS, TopTools_ListOfShape()));
pTS->Append(aSM.First());
}
}
}
// Keep the split shape history and history of tools modifications
// during the split for making association of the opposite identical shapes
Handle(BRepTools_History) aSplitShapeHist = new BRepTools_History,
aSplitToolsHist = new BRepTools_History;
// Split the positive side of the shape
SplitShape(aTools, aSplitShapeHist, aSplitToolsHist);
if (HasErrors())
return;
mySplitHistory->Merge(aSplitShapeHist);
// Make associations between identical opposite sub-shapes
const Standard_Integer aNbSH = aTranslationHistMap.Extent();
for (Standard_Integer i = 1; i <= aNbSH; ++i)
{
const TopoDS_Shape* pS = &aTranslationHistMap.FindKey(i);
const TopTools_ListOfShape& aSIm = aSplitShapeHist->Modified(*pS);
if (aSIm.Extent() == 1)
pS = &aSIm.First();
else if (aSIm.Extent() > 1)
continue;
const TopTools_ListOfShape& aLTranslated = aTranslationHistMap(i);
TopTools_ListIteratorOfListOfShape itLT(aLTranslated);
for (; itLT.More(); itLT.Next())
{
const TopoDS_Shape& aT = itLT.Value();
// Get shapes modifications during the split
const TopTools_ListOfShape& aTSplits = aSplitToolsHist->Modified(aT);
// Associate the shapes to each other
TopTools_ListIteratorOfListOfShape itSp(aTSplits);
for (; itSp.More(); itSp.Next())
{
const TopoDS_Shape& aSp = itSp.Value();
AddTwin(*pS, aSp, myTwins);
AddTwin(aSp, *pS, myTwins);
}
}
}
}
//=======================================================================
//function : SplitShape
//purpose : Splits the shape by the given tools
//=======================================================================
void BOPAlgo_MakePeriodic::SplitShape(const TopTools_ListOfShape& theTools,
Handle(BRepTools_History) theSplitShapeHistory,
Handle(BRepTools_History) theSplitToolsHistory)
{
// Make sure that the geometry from the tools will be copied to the split
// shape. For that, the tool shapes should be given to the Boolean Operations
// algorithm before the shape itself. This will make all coinciding parts
// use the geometry of the first argument.
// Intersection tool for passing ordered arguments
BOPAlgo_PaveFiller anIntersector;
anIntersector.SetArguments(theTools);
// Add the shape
anIntersector.AddArgument(myShape);
// Use gluing to speed-up intersections
anIntersector.SetGlue(BOPAlgo_GlueShift);
// Use safe input mode, to avoid reusing geometry of the shape
anIntersector.SetNonDestructive(Standard_True);
// Set parallel processing mode
anIntersector.SetRunParallel(myRunParallel);
// Perform Intersection of the arguments
anIntersector.Perform();
// Check for the errors
if (anIntersector.HasErrors())
{
// Unable to split the shape on opposite sides
// Copy the intersection errors
myReport->Merge(anIntersector.GetReport());
// Add new error saving the shapes for analysis
TopoDS_Compound aWS;
AddToShape(theTools, aWS);
AddToShape(myShape, aWS);
AddError(new BOPAlgo_AlertUnableToMakeIdentical(aWS));
return;
}
// Perform the splitting of the shape with the precomputed intersection results
BRepAlgoAPI_Splitter aSplitter(anIntersector);
// Set Object
TopTools_ListOfShape anObj;
anObj.Append(myShape);
aSplitter.SetArguments(anObj);
// Set Tools
aSplitter.SetTools(theTools);
// Use Gluing
aSplitter.SetGlue(BOPAlgo_GlueShift);
// Set parallel processing mode
aSplitter.SetRunParallel(myRunParallel);
// Perform splitting
aSplitter.Build();
// Check for the errors
if (aSplitter.HasErrors())
{
// Unable to split the shape on opposite sides
// Copy the splitter errors
myReport->Merge(aSplitter.GetReport());
// Add new error saving the shape for analysis
TopoDS_Compound aWS;
AddToShape(theTools, aWS);
AddToShape(myShape, aWS);
AddError(new BOPAlgo_AlertUnableToMakeIdentical(aWS));
return;
}
// Get the split shape
myShape = aSplitter.Shape();
// Remember the split history
if (!theSplitShapeHistory.IsNull())
theSplitShapeHistory->Merge(anObj, aSplitter);
if (!theSplitToolsHistory.IsNull())
theSplitToolsHistory->Merge(theTools, aSplitter);
}
//=======================================================================
//function : RepeatShape
//purpose : Repeats the shape in the required periodic direction
//=======================================================================
const TopoDS_Shape& BOPAlgo_MakePeriodic::RepeatShape(const Standard_Integer theDir,
const Standard_Integer theTimes)
{
if (myRepeatedShape.IsNull())
myRepeatedShape = myShape;
if (!IsPeriodic(theDir))
return myRepeatedShape;
if (theTimes == 0)
return myRepeatedShape;
// Get the shape's period in the required direction
const Standard_Integer id = BOPAlgo_MakePeriodic::ToDirectionID(theDir);
if (myRepeatPeriod[id] < Precision::Confusion())
myRepeatPeriod[id] = Period(id);
const Standard_Real aPeriod = myRepeatPeriod[id];
// Coefficient to define in which direction the repetition will be performed:
// theTimes is positive - in positive direction;
// theTimes is negative - in negative direction.
const Standard_Integer iDir = theTimes > 0 ? 1 : -1;
// Create the translation history - all translated shapes will be
// created as Generated from the shape.
BRepTools_History aTranslationHistory;
TopTools_IndexedMapOfShape aSubShapesMap;
TopExp::MapShapes(myRepeatedShape, aSubShapesMap);
const Standard_Integer aNbS = aSubShapesMap.Extent();
// Add shapes for gluing
TopTools_ListOfShape aShapes;
// Add the shape itself
aShapes.Append(myRepeatedShape);
for (Standard_Integer i = 1; i <= aNbS; ++i)
{
const TopoDS_Shape& aS = aSubShapesMap(i);
if (BRepTools_History::IsSupportedType(aS))
aTranslationHistory.AddGenerated(aS, aS);
}
// Create translated copies of the shape
for (Standard_Integer i = 1; i <= Abs(theTimes); ++i)
{
gp_Trsf aTrsf;
aTrsf.SetTranslationPart(iDir * i * aPeriod * MY_DIRECTIONS[id]);
BRepBuilderAPI_Transform aTranslator(myRepeatedShape, aTrsf, Standard_False);
aShapes.Append(aTranslator.Shape());
// Fill the translation history
for (Standard_Integer j = 1; j <= aNbS; ++j)
{
const TopoDS_Shape& aS = aSubShapesMap(j);
if (BRepTools_History::IsSupportedType(aS))
{
const TopTools_ListOfShape& aLT = aTranslator.Modified(aS);
aTranslationHistory.AddGenerated(aS, aLT.First());
}
}
}
// Update the history with the translation History
myHistory->Merge(aTranslationHistory);
// Glue the translated shapes all together
BOPAlgo_Builder aGluer;
aGluer.SetArguments(aShapes);
// Avoid intersections of the sub-shapes
aGluer.SetGlue(BOPAlgo_GlueFull);
// Set parallel processing mode
aGluer.SetRunParallel(myRunParallel);
// Perform gluing
aGluer.Perform();
if (aGluer.HasErrors())
{
// Repetition in this direction is not possible
// Add warning saving the shapes for analysis
TopoDS_Compound aWS;
AddToShape(aShapes, aWS);
AddWarning(new BOPAlgo_AlertUnableToRepeat(aWS));
return myRepeatedShape;
}
// Get glued shape
myRepeatedShape = aGluer.Shape();
// Update repetition period for the next repetitions
myRepeatPeriod[id] += Abs(theTimes) * myRepeatPeriod[id];
// Update history with the Gluing history
BRepTools_History aGluingHistory(aShapes, aGluer);
myHistory->Merge(aGluingHistory);
// Update the map of twins after repetition
UpdateTwins(aTranslationHistory, aGluingHistory);
return myRepeatedShape;
}
//=======================================================================
//function : UpdateTwins
//purpose : Updates the map of twins after repetition
//=======================================================================
void BOPAlgo_MakePeriodic::UpdateTwins(const BRepTools_History& theTranslationHistory,
const BRepTools_History& theGluingHistory)
{
if (myTwins.IsEmpty())
return;
if (myRepeatedTwins.IsEmpty())
myRepeatedTwins = myTwins;
// New twins
TopTools_DataMapOfShapeListOfShape aNewTwinsMap;
// Fence map to avoid repeated fill for the twins
TopTools_MapOfShape aMTwinsDone;
// Update the map of twins with the new repeated shapes
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itDMap(myRepeatedTwins);
for (; itDMap.More(); itDMap.Next())
{
const TopoDS_Shape& aS = itDMap.Key();
aMTwinsDone.Add(aS);
const TopTools_ListOfShape& aLTwins = itDMap.Value();
// Check if the twins have not been already processed
TopTools_ListIteratorOfListOfShape itLT(aLTwins);
for (; itLT.More(); itLT.Next())
{
if (aMTwinsDone.Contains(itLT.Value()))
break;
}
if (itLT.More())
// Group of twins has already been processed
continue;
// All shapes generated from the shape itself and generated
// from its twins will be the new twins for the shape
TopTools_IndexedMapOfShape aNewGroup;
itLT.Initialize(aLTwins);
for (Standard_Boolean bShape = Standard_True; itLT.More();)
{
const TopoDS_Shape& aTwin = bShape ? aS : itLT.Value();
const TopTools_ListOfShape& aLG = theTranslationHistory.Generated(aTwin);
TopTools_ListIteratorOfListOfShape itLG(aLG);
for (; itLG.More(); itLG.Next())
{
const TopoDS_Shape& aG = itLG.Value();
const TopTools_ListOfShape& aLM = theGluingHistory.Modified(aG);
if (aLM.IsEmpty())
aNewGroup.Add(aG);
else
{
TopTools_ListIteratorOfListOfShape itLM(aLM);
for (; itLM.More(); itLM.Next())
aNewGroup.Add(itLM.Value());
}
}
if (bShape)
bShape = Standard_False;
else
itLT.Next();
}
// Associate the twins to each other
const Standard_Integer aNbTwins = aNewGroup.Extent();
for (Standard_Integer i = 1; i <= aNbTwins; ++i)
{
TopTools_ListOfShape* pTwins = aNewTwinsMap.Bound(aNewGroup(i), TopTools_ListOfShape());
for (Standard_Integer j = 1; j <= aNbTwins; ++j)
if (i != j) pTwins->Append(aNewGroup(j));
}
}
myRepeatedTwins = aNewTwinsMap;
}

View File

@@ -0,0 +1,603 @@
// Created on: 2018-03-16
// Created by: Eugeny MALTCHIKOV
// Copyright (c) 2018 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 _BOPAlgo_MakePeriodic_HeaderFile
#define _BOPAlgo_MakePeriodic_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <BOPAlgo_Options.hxx>
#include <BRepTools_History.hxx>
#include <Standard_Boolean.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_DataMapOfShapeShape.hxx>
//! BOPAlgo_MakePeriodic is the tool for making an arbitrary shape periodic
//! in 3D space in specified directions.
//!
//! Periodicity of the shape means that the shape can be repeated in any
//! periodic direction any number of times without creation of the new
//! geometry or splits.
//!
//! The idea is to make the shape look identical on the opposite sides of the
//! periodic directions, so when translating the copy of a shape on the period
//! there will be no coinciding parts of different dimensions.
//!
//! If necessary the algorithm will trim the shape to fit it into the
//! requested period by splitting it by the planes limiting the shape's
//! requested period.
//!
//! For making the shape periodic in certain direction the algorithm performs
//! the following steps:
//! * Creates the copy of the shape and moves it on the period into negative
//! side of the requested direction;
//! * Splits the negative side of the shape by the moved copy, ensuring copying
//! of the geometry from positive side to negative;
//! * Creates the copy of the shape (with already split negative side) and moves
//! it on the period into the positive side of the requested direction;
//! * Splits the positive side of the shape by the moved copy, ensuring copying
//! of the geometry from negative side to positive.
//!
//! The algorithm also associates the identical (or twin) shapes located
//! on the opposite sides of the result shape.
//! Using the *GetTwins()* method it is possible to get the twin shapes from
//! the opposite sides.
//!
//! Algorithm also provides the methods to repeat the periodic shape in
//! periodic directions. The subsequent repetitions are performed on the
//! repeated shape, thus repeating the shape two times in X direction will
//! create result in three shapes (original plus two copies).
//! Single subsequent repetition will result already in 6 shapes.
//! The repetitions can be cleared and started over.
//!
//! The algorithm supports History of shapes modifications, thus
//! it is possible to track how the shape has been changed to make it periodic
//! and what new shapes have been created during repetitions.
//!
//! The algorithm supports the parallel processing mode, which allows faster
//! completion of the operations.
//!
//! The algorithm supports the Error/Warning system and returns the following alerts:
//! - *BOPAlgo_AlertNoPeriodicityRequired* - Error alert is given if no periodicity
//! has been requested in any direction;
//! - *BOPAlgo_AlertUnableToTrim* - Error alert is given if the trimming of the shape
//! for fitting it into requested period has failed;
//! - *BOPAlgo_AlertUnableToMakeIdentical* - Error alert is given if splitting of the
//! shape by its moved copies has failed;
//! - *BOPAlgo_AlertUnableToRepeat* - Warning alert is given if the gluing of the repeated
//! shapes has failed.
//!
//! Example of usage of the algorithm:
//! ~~~~
//! TopoDS_Shape aShape = ...; // The shape to make periodic
//! Standard_Boolean bMakeXPeriodic = ...; // Flag for making or not the shape periodic in X direction
//! Standard_Real aXPeriod = ...; // X period for the shape
//! Standard_Boolean isXTrimmed = ...; // Flag defining whether it is necessary to trimming
//! // the shape to fit to X period
//! Standard_Real aXFirst = ...; // Start of the X period
//! // (really necessary only if the trimming is requested)
//! Standard_Boolean bRunParallel = ...; // Parallel processing mode or single
//!
//! BOPAlgo_MakePeriodic aPeriodicityMaker; // Periodicity maker
//! aPeriodicityMaker.SetShape(aShape); // Set the shape
//! aPeriodicityMaker.MakeXPeriodic(bMakePeriodic, aXPeriod); // Making the shape periodic in X direction
//! aPeriodicityMaker.SetTrimmed(isXTrimmed, aXFirst); // Trim the shape to fit X period
//! aPeriodicityMaker.SetRunParallel(bRunParallel); // Set the parallel processing mode
//! aPeriodicityMaker.Perform(); // Performing the operation
//!
//! if (aPeriodicityMaker.HasErrors()) // Check for the errors
//! {
//! // errors treatment
//! Standard_SStream aSStream;
//! aPeriodicityMaker.DumpErrors(aSStream);
//! return;
//! }
//! if (aPeriodicityMaker.HasWarnings()) // Check for the warnings
//! {
//! // warnings treatment
//! Standard_SStream aSStream;
//! aPeriodicityMaker.DumpWarnings(aSStream);
//! }
//! const TopoDS_Shape& aPeriodicShape = aPeriodicityMaker.Shape(); // Result periodic shape
//!
//!
//! aPeriodicityMaker.XRepeat(2); // Making repetitions
//! const TopoDS_Shape& aRepeat = aPeriodicityMaker.RepeatedShape(); // Getting the repeated shape
//! aPeriodicityMaker.ClearRepetitions(); // Clearing the repetitions
//! ~~~~
//!
class BOPAlgo_MakePeriodic : public BOPAlgo_Options
{
public:
DEFINE_STANDARD_ALLOC
public: //! @name Constructor
//! Empty constructor
BOPAlgo_MakePeriodic() : BOPAlgo_Options()
{
myRepeatPeriod[0] = myRepeatPeriod[1] = myRepeatPeriod[2] = 0.0;
}
public: //! @name Setting the shape to make it periodic
//! Sets the shape to make it periodic.
//! @param theShape [in] The shape to make periodic.
void SetShape(const TopoDS_Shape& theShape)
{
myInputShape = theShape;
}
public: //! @name Definition of the structure to keep all periodicity parameters
//! Structure to keep all periodicity parameters:
struct PeriodicityParams
{
PeriodicityParams()
{
Clear();
}
//! Returns all previously set parameters to default values
void Clear()
{
myPeriodic[0] = myPeriodic[1] = myPeriodic[2] = Standard_False;
myPeriod[0] = myPeriod[1] = myPeriod[2] = 0.0;
myIsTrimmed[0] = myIsTrimmed[1] = myIsTrimmed[2] = Standard_True;
myPeriodFirst[0] = myPeriodFirst[1] = myPeriodFirst[2] = 0.0;
}
Standard_Boolean myPeriodic[3]; //!< Array of flags defining whether the shape should be
//! periodic in XYZ directions
Standard_Real myPeriod[3]; //!< Array of XYZ period values. Defining the period for any
//! direction the corresponding flag for that direction in
//! myPeriodic should be set to true
Standard_Boolean myIsTrimmed[3]; //!< Array of flags defining whether the input shape has to be
//! trimmed to fit the required period in the required direction
Standard_Real myPeriodFirst[3]; //!< Array of start parameters of the XYZ periods: required for trimming
};
public: //! @name Setters/Getters for periodicity parameters structure
//! Sets the periodicity parameters.
//! @param theParams [in] Periodicity parameters
void SetPeriodicityParameters(const PeriodicityParams& theParams)
{
myPeriodicityParams = theParams;
}
const PeriodicityParams& PeriodicityParameters() const
{
return myPeriodicityParams;
}
public: //! @name Methods for setting/getting periodicity info using ID as a direction
//! Sets the flag to make the shape periodic in specified direction:
//! - 0 - X direction;
//! - 1 - Y direction;
//! - 2 - Z direction.
//!
//! @param theDirectionID [in] The direction's ID;
//! @param theIsPeriodic [in] Flag defining periodicity in given direction;
//! @param thePeriod [in] Required period in given direction.
void MakePeriodic(const Standard_Integer theDirectionID,
const Standard_Boolean theIsPeriodic,
const Standard_Real thePeriod = 0.0)
{
Standard_Integer id = ToDirectionID(theDirectionID);
myPeriodicityParams.myPeriodic[id] = theIsPeriodic;
myPeriodicityParams.myPeriod[id] = theIsPeriodic ? thePeriod : 0.0;
}
//! Returns the info about Periodicity of the shape in specified direction.
//! @param theDirectionID [in] The direction's ID.
Standard_Boolean IsPeriodic(const Standard_Integer theDirectionID) const
{
return myPeriodicityParams.myPeriodic[ToDirectionID(theDirectionID)];
}
//! Returns the Period of the shape in specified direction.
//! @param theDirectionID [in] The direction's ID.
Standard_Real Period(const Standard_Integer theDirectionID) const
{
Standard_Integer id = ToDirectionID(theDirectionID);
return myPeriodicityParams.myPeriodic[id] ? myPeriodicityParams.myPeriod[id] : 0.0;
}
public: //! @name Named methods for setting/getting info about shape's periodicity
//! Sets the flag to make the shape periodic in X direction.
//! @param theIsPeriodic [in] Flag defining periodicity in X direction;
//! @param thePeriod [in] Required period in X direction.
void MakeXPeriodic(const Standard_Boolean theIsPeriodic,
const Standard_Real thePeriod = 0.0)
{
MakePeriodic(0, theIsPeriodic, thePeriod);
}
//! Returns the info about periodicity of the shape in X direction.
Standard_Boolean IsXPeriodic() const { return IsPeriodic(0); }
//! Returns the XPeriod of the shape
Standard_Real XPeriod() const { return Period(0); }
//! Sets the flag to make the shape periodic in Y direction.
//! @param theIsPeriodic [in] Flag defining periodicity in Y direction;
//! @param thePeriod [in] Required period in Y direction.
void MakeYPeriodic(const Standard_Boolean theIsPeriodic,
const Standard_Real thePeriod = 0.0)
{
MakePeriodic(1, theIsPeriodic, thePeriod);
}
//! Returns the info about periodicity of the shape in Y direction.
Standard_Boolean IsYPeriodic() const { return IsPeriodic(1); }
//! Returns the YPeriod of the shape.
Standard_Real YPeriod() const { return Period(1); }
//! Sets the flag to make the shape periodic in Z direction.
//! @param theIsPeriodic [in] Flag defining periodicity in Z direction;
//! @param thePeriod [in] Required period in Z direction.
void MakeZPeriodic(const Standard_Boolean theIsPeriodic,
const Standard_Real thePeriod = 0.0)
{
MakePeriodic(2, theIsPeriodic, thePeriod);
}
//! Returns the info about periodicity of the shape in Z direction.
Standard_Boolean IsZPeriodic() const { return IsPeriodic(2); }
//! Returns the ZPeriod of the shape.
Standard_Real ZPeriod() const { return Period(2); }
public: //! @name Methods for setting/getting trimming info taking Direction ID as a parameter
//! Defines whether the input shape is already trimmed in specified direction
//! to fit the period in this direction.
//! Direction is defined by an ID:
//! - 0 - X direction;
//! - 1 - Y direction;
//! - 2 - Z direction.
//!
//! If the shape is not trimmed it is required to set the first parameter
//! of the period in that direction.
//! The algorithm will make the shape fit into the period.
//!
//! Before calling this method, the shape has to be set to be periodic in this direction.
//!
//! @param theDirectionID [in] The direction's ID;
//! @param theIsTrimmed [in] The flag defining trimming of the shape in given direction;
//! @param theFirst [in] The first periodic parameter in the given direction.
void SetTrimmed(const Standard_Integer theDirectionID,
const Standard_Boolean theIsTrimmed,
const Standard_Real theFirst = 0.0)
{
Standard_Integer id = ToDirectionID(theDirectionID);
if (IsPeriodic(id))
{
myPeriodicityParams.myIsTrimmed[id] = theIsTrimmed;
myPeriodicityParams.myPeriodFirst[id] = !theIsTrimmed ? theFirst : 0.0;
}
}
//! Returns whether the input shape was trimmed in the specified direction.
//! @param theDirectionID [in] The direction's ID.
Standard_Boolean IsInputTrimmed(const Standard_Integer theDirectionID) const
{
return myPeriodicityParams.myIsTrimmed[ToDirectionID(theDirectionID)];
}
//! Returns the first periodic parameter in the specified direction.
//! @param theDirectionID [in] The direction's ID.
Standard_Real PeriodFirst(const Standard_Integer theDirectionID) const
{
Standard_Integer id = ToDirectionID(theDirectionID);
return !myPeriodicityParams.myIsTrimmed[id] ? myPeriodicityParams.myPeriodFirst[id] : 0.0;
}
public: //! @name Named methods for setting/getting trimming info
//! Defines whether the input shape is already trimmed in X direction
//! to fit the X period. If the shape is not trimmed it is required
//! to set the first parameter for the X period.
//! The algorithm will make the shape fit into the period.
//!
//! Before calling this method, the shape has to be set to be periodic in this direction.
//!
//! @param theIsTrimmed [in] Flag defining whether the shape is already trimmed
//! in X direction to fit the X period;
//! @param theFirst [in] The first X periodic parameter.
void SetXTrimmed(const Standard_Boolean theIsTrimmed,
const Standard_Boolean theFirst = 0.0)
{
SetTrimmed(0, theIsTrimmed, theFirst);
}
//! Returns whether the input shape was already trimmed for X period.
Standard_Boolean IsInputXTrimmed() const
{
return IsInputTrimmed(0);
}
//! Returns the first parameter for the X period.
Standard_Real XPeriodFirst() const
{
return PeriodFirst(0);
}
//! Defines whether the input shape is already trimmed in Y direction
//! to fit the Y period. If the shape is not trimmed it is required
//! to set the first parameter for the Y period.
//! The algorithm will make the shape fit into the period.
//!
//! Before calling this method, the shape has to be set to be periodic in this direction.
//!
//! @param theIsTrimmed [in] Flag defining whether the shape is already trimmed
//! in Y direction to fit the Y period;
//! @param theFirst [in] The first Y periodic parameter.
void SetYTrimmed(const Standard_Boolean theIsTrimmed,
const Standard_Boolean theFirst = 0.0)
{
SetTrimmed(1, theIsTrimmed, theFirst);
}
//! Returns whether the input shape was already trimmed for Y period.
Standard_Boolean IsInputYTrimmed() const
{
return IsInputTrimmed(1);
}
//! Returns the first parameter for the Y period.
Standard_Real YPeriodFirst() const
{
return PeriodFirst(1);
}
//! Defines whether the input shape is already trimmed in Z direction
//! to fit the Z period. If the shape is not trimmed it is required
//! to set the first parameter for the Z period.
//! The algorithm will make the shape fit into the period.
//!
//! Before calling this method, the shape has to be set to be periodic in this direction.
//!
//! @param theIsTrimmed [in] Flag defining whether the shape is already trimmed
//! in Z direction to fit the Z period;
//! @param theFirst [in] The first Z periodic parameter.
void SetZTrimmed(const Standard_Boolean theIsTrimmed,
const Standard_Boolean theFirst = 0.0)
{
SetTrimmed(2, theIsTrimmed, theFirst);
}
//! Returns whether the input shape was already trimmed for Z period.
Standard_Boolean IsInputZTrimmed() const
{
return IsInputTrimmed(2);
}
//! Returns the first parameter for the Z period.
Standard_Real ZPeriodFirst() const
{
return PeriodFirst(2);
}
public: //! @name Performing the operation
//! Makes the shape periodic in necessary directions
Standard_EXPORT void Perform();
public: //! @name Using the algorithm to repeat the shape
//! Performs repetition of the shape in specified direction
//! required number of times.
//! Negative value of times means that the repetition should
//! be perform in negative direction.
//! Makes the repeated shape a base for following repetitions.
//!
//! @param theDirectionID [in] The direction's ID;
//! @param theTimes [in] Requested number of repetitions.
Standard_EXPORT const TopoDS_Shape& RepeatShape(const Standard_Integer theDirectionID,
const Standard_Integer theTimes);
//! Repeats the shape in X direction specified number of times.
//! Negative value of times means that the repetition should be
//! perform in negative X direction.
//! Makes the repeated shape a base for following repetitions.
//!
//! @param theTimes [in] Requested number of repetitions.
const TopoDS_Shape& XRepeat(const Standard_Integer theTimes)
{
return RepeatShape(0, theTimes);
}
//! Repeats the shape in Y direction specified number of times.
//! Negative value of times means that the repetition should be
//! perform in negative Y direction.
//! Makes the repeated shape a base for following repetitions.
//!
//! @param theTimes [in] Requested number of repetitions.
const TopoDS_Shape& YRepeat(const Standard_Integer theTimes)
{
return RepeatShape(1, theTimes);
}
//! Repeats the shape in Z direction specified number of times.
//! Negative value of times means that the repetition should be
//! perform in negative Z direction.
//! Makes the repeated shape a base for following repetitions.
//!
//! @param theTimes [in] Requested number of repetitions.
const TopoDS_Shape& ZRepeat(const Standard_Integer theTimes)
{
return RepeatShape(2, theTimes);
}
public: //! @name Starting the repetitions over
//! Returns the repeated shape
const TopoDS_Shape& RepeatedShape() const { return myRepeatedShape; }
//! Clears all performed repetitions.
//! The next repetition will be performed on the base shape.
void ClearRepetitions()
{
myRepeatPeriod[0] = myRepeatPeriod[1] = myRepeatPeriod[2] = 0.0;
myRepeatedShape.Nullify();
myRepeatedTwins.Clear();
if (!myHistory.IsNull())
{
myHistory->Clear();
if (!mySplitHistory.IsNull())
myHistory->Merge(mySplitHistory);
}
}
public: //! @name Obtaining the result shape
//! Returns the resulting periodic shape
const TopoDS_Shape& Shape() const { return myShape; }
public: //! @name Getting the identical shapes
//! Returns the identical shapes for the given shape located
//! on the opposite periodic side.
//! Returns empty list in case the shape has no twin.
//!
//! @param theS [in] Shape to get the twins for.
const TopTools_ListOfShape& GetTwins(const TopoDS_Shape& theS) const
{
static TopTools_ListOfShape empty;
const TopTools_ListOfShape* aTwins =
myRepeatedTwins.IsEmpty() ? myTwins.Seek(theS) : myRepeatedTwins.Seek(theS);
return (aTwins ? *aTwins : empty);
}
public: //! @name Getting the History of the algorithm
//! Returns the History of the algorithm
const Handle(BRepTools_History)& History() const
{
return myHistory;
}
public: //! @name Clearing the algorithm from previous runs
//! Clears the algorithm from previous runs
void Clear()
{
BOPAlgo_Options::Clear();
myPeriodicityParams.Clear();
myShape.Nullify();
if (!mySplitHistory.IsNull())
mySplitHistory->Clear();
if (!myHistory.IsNull())
myHistory->Clear();
ClearRepetitions();
}
public: //! @name Conversion of the integer to ID of periodic direction
//! Converts the integer to ID of periodic direction
static Standard_Integer ToDirectionID(const Standard_Integer theDirectionID)
{
return Abs(theDirectionID % 3);
}
protected: //! @name Protected methods performing the operation
//! Checks the validity of input data
Standard_EXPORT void CheckData();
//! Trims the shape to fit to the periodic bounds
Standard_EXPORT void Trim();
//! Makes the shape identical on opposite sides
Standard_EXPORT void MakeIdentical();
//! Splits the negative side of the shape with the geometry
//! located on the positive side copying the geometry from
//! positive side to the negative.
Standard_EXPORT void SplitNegative();
//! Splits the positive side of the shape with the geometry
//! located on the negative side of the shape.
//! Ensures that the geometries on the opposite sides will
//! be identical.
//! Associates the identical opposite sub-shapes.
Standard_EXPORT void SplitPositive();
//! Splits the shape by the given tools, copying the geometry of coinciding
//! parts from the given tools to the split shape.
//! @param theTools [in] The tools to split the shape and take the geometry
//! for coinciding parts.
//! @param theSplitShapeHistory [out] The history of shape split
//! @param theSplitToolsHistory [out] The history of tools modifications during the split
Standard_EXPORT void SplitShape(const TopTools_ListOfShape& theTools,
Handle(BRepTools_History) theSplitShapeHistory = NULL,
Handle(BRepTools_History) theSplitToolsHistory = NULL);
//! Updates the map of twins after periodic shape repetition.
//! @param theTranslationHistory [in] The history of translation of the periodic shape.
//! @param theGluingHistory [in] The history of gluing of the repeated shapes.
Standard_EXPORT void UpdateTwins(const BRepTools_History& theTranslationHistory,
const BRepTools_History& theGluingHistory);
protected: //! @name Fields
// Inputs
TopoDS_Shape myInputShape; //!< Input shape to make periodic
PeriodicityParams myPeriodicityParams; //!< Periodicity parameters
// Results
TopoDS_Shape myShape; //!< Resulting periodic shape (base for repetitions)
TopoDS_Shape myRepeatedShape; //!< Resulting shape after making repetitions of the base
Standard_Real myRepeatPeriod[3]; //!< XYZ repeat period
TopTools_DataMapOfShapeListOfShape myRepeatedTwins; //!< Map of associations of the identical sub-shapes
//! after repetition of the periodic shape
// Twins
TopTools_DataMapOfShapeListOfShape myTwins; //!< Map of associations of the identical sub-shapes
//! located on the opposite sides of the shape
// History
Handle(BRepTools_History) mySplitHistory; //!< Split history - history of shapes modification
//! after the split for making the shape periodic
Handle(BRepTools_History) myHistory; //!< Final history of shapes modifications
//! (to include the history of shape repetition)
};
#endif // _BOPAlgo_MakePeriodic_HeaderFile

View File

@@ -173,22 +173,6 @@ void BOPAlgo_PaveFiller::SetSectionAttribute
mySectionAttribute = theSecAttr;
}
//=======================================================================
//function : SetArguments
//purpose :
//=======================================================================
void BOPAlgo_PaveFiller::SetArguments(const TopTools_ListOfShape& theLS)
{
myArguments=theLS;
}
//=======================================================================
//function : Arguments
//purpose :
//=======================================================================
const TopTools_ListOfShape& BOPAlgo_PaveFiller::Arguments()const
{
return myArguments;
}
//=======================================================================
// function: Init
// purpose:
//=======================================================================

View File

@@ -125,9 +125,23 @@ public:
Standard_EXPORT const BOPDS_PIterator& Iterator();
Standard_EXPORT void SetArguments (const TopTools_ListOfShape& theLS);
Standard_EXPORT const TopTools_ListOfShape& Arguments() const;
//! Sets the arguments for operation
void SetArguments (const TopTools_ListOfShape& theLS)
{
myArguments = theLS;
}
//! Adds the argument for operation
void AddArgument(const TopoDS_Shape& theShape)
{
myArguments.Append(theShape);
}
//! Returns the list of arguments
const TopTools_ListOfShape& Arguments() const
{
return myArguments;
}
Standard_EXPORT const Handle(IntTools_Context)& Context();

View File

@@ -17,6 +17,8 @@
#include <BOPAlgo_PaveFiller.hxx>
#include <BOPAlgo_Alerts.hxx>
#include <TopoDS_Iterator.hxx>
//=======================================================================
//function :
//purpose :
@@ -98,3 +100,31 @@ void BOPAlgo_Splitter::Perform()
myEntryPoint = 1;
PerformInternal(*pPF);
}
//=======================================================================
//function : BuildResult
//purpose :
//=======================================================================
void BOPAlgo_Splitter::BuildResult(const TopAbs_ShapeEnum theType)
{
BOPAlgo_Builder::BuildResult(theType);
if (theType == TopAbs_COMPOUND)
{
// The method is called for the last time for this operation.
// If there is only one argument shape and it has been modified into
// a single shape, or has not been modified at all, the result shape
// has to be overwritten to avoid the unnecessary enclosure into compound.
if (myArguments.Extent() == 1)
{
TopoDS_Iterator it(myShape);
if (it.More())
{
const TopoDS_Shape& aSFirst = it.Value();
it.Next();
if (!it.More())
myShape = aSFirst;
}
}
}
}

View File

@@ -66,6 +66,12 @@ protected:
//! Checks the input data
Standard_EXPORT virtual void CheckData() Standard_OVERRIDE;
//! Adds images of the argument shapes into result.
//! When called the for the last time (for compound) it rebuilds the result
//! shape to avoid multiple enclosure into compounds.
Standard_EXPORT virtual void BuildResult(const TopAbs_ShapeEnum theType) Standard_OVERRIDE;
};
#endif // _BOPAlgo_Splitter_HeaderFile

View File

@@ -27,6 +27,8 @@ BOPAlgo_CheckResult.cxx
BOPAlgo_CheckResult.hxx
BOPAlgo_CheckStatus.hxx
BOPAlgo_ListOfCheckResult.hxx
BOPAlgo_MakePeriodic.cxx
BOPAlgo_MakePeriodic.hxx
BOPAlgo_MakerVolume.cxx
BOPAlgo_MakerVolume.hxx
BOPAlgo_MakerVolume.lxx