1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0029234: BRepOffsetAPI_NormalProjection produces INTERNAL edges and vertices

Make the algorithm BRepOffsetAPI_NormalProjection use section operation instead of common to get the edge-result of projection to be in face restrictions.

Correct Boolean operation algorithm to produce correctly oriented result in the case of common between face and edge.

The algorithm ShapeUpgrade_UnifySameDomain has been patched to correctly gather same domain faces in a compound.

The TCL script snowflake.tcl has been corrected to get rid of dependence on the order of edges in the result of Boolean operation.
This commit is contained in:
msv 2017-10-20 18:59:01 +03:00
parent 2c26e60bf9
commit 977ad98334
10 changed files with 115 additions and 123 deletions

View File

@ -59,12 +59,10 @@ prism f4 l2 0 -1 0
compound f1 f2 f3 bc
bfuse r bc f4
bcut r r f5
explode r e
wire w r_4 r_1 r_20 r_21 r_22 r_23 r_24 r_25 r_26 r_7 r_30 r_31 r_32 r_33 r_27 r_28 r_29 r_11 r_38 r_34 r_35 r_36 r_37 r_16 r_17
tcopy w w1
tmirror w1 -6 0 0 0 1 0
wire w w w1
mkface w p w
tcopy r r1
tmirror r1 -6 0 0 0 1 0
bfuse w r r1
unifysamedom w w
donly w
# construct complete snowflake

View File

@ -16,6 +16,7 @@
#include <BOPAlgo_BOP.hxx>
#include <BOPAlgo_BuilderSolid.hxx>
#include <BOPAlgo_PaveFiller.hxx>
#include <BOPAlgo_Tools.hxx>
#include <BOPAlgo_Alerts.hxx>
#include <BOPCol_DataMapOfShapeShape.hxx>
#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
@ -777,9 +778,11 @@ void BOPAlgo_BOP::BuildShape()
}
// make containers
BOPCol_ListOfShape aLCRes;
BOPCol_MapOfShape aMInpFence;
aItLS.Initialize(aLSC);
for (; aItLS.More(); aItLS.Next()) {
const TopoDS_Shape& aSC = aItLS.Value();
aMInpFence.Add(aSC);
//
BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
//
@ -861,19 +864,44 @@ void BOPAlgo_BOP::BuildShape()
for (; aItLS.More(); aItLS.Next()) {
aBB.Add(aResult, aItLS.Value());
}
//
// add the rest of the shapes into result
// create map of containers
BOPCol_MapOfShape aMSResult;
BOPTools::MapShapes(aResult, aMSResult);
//
aIt.Initialize(myRC);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aS = aIt.Value();
if (aMSResult.Add(aS)) {
aBB.Add(aResult, aS);
// get input non-container shapes
BOPCol_ListOfShape aLSNonCont;
for (i = 0; i < 2; ++i)
{
const BOPCol_ListOfShape& aLS = !i ? myArguments : myTools;
aItLS.Initialize(aLS);
for (; aItLS.More(); aItLS.Next())
{
const TopoDS_Shape& aS = aItLS.Value();
BOPAlgo_Tools::TreatCompound(aS, aMInpFence, aLSNonCont);
}
}
//
// put non-container shapes in the result
aItLS.Initialize(aLSNonCont);
for (; aItLS.More(); aItLS.Next())
{
const TopoDS_Shape& aS = aItLS.Value();
if (myImages.IsBound(aS))
{
const BOPCol_ListOfShape& aLSIm = myImages.Find(aS);
aItLSIm.Initialize(aLSIm);
for (; aItLSIm.More(); aItLSIm.Next())
{
const TopoDS_Shape& aSIm = aItLSIm.Value();
if (aMSRC.Contains(aSIm) && aMSResult.Add(aSIm))
aBB.Add(aResult, aSIm);
}
}
else if (aMSRC.Contains(aS) && aMSResult.Add(aS))
aBB.Add(aResult, aS);
}
myShape = aResult;
}
//=======================================================================

View File

@ -64,6 +64,7 @@
#include <BOPTools_Set.hxx>
//
#include <BOPAlgo_BuilderSolid.hxx>
#include <BOPAlgo_Tools.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_IncAllocator.hxx>
@ -74,11 +75,6 @@ static
void OwnInternalShapes(const TopoDS_Shape& ,
BOPCol_IndexedMapOfShape& );
static
void TreatCompound(const TopoDS_Shape& theS,
BOPCol_MapOfShape& aMFence,
BOPCol_ListOfShape& theLS);
//=======================================================================
// BOPAlgo_BuilderSolid
//
@ -941,7 +937,7 @@ void BOPAlgo_Builder::FillInternalShapes()
aIt.Initialize(aArguments);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aS=aIt.Value();
TreatCompound(aS, aMFence, aLSC);
BOPAlgo_Tools::TreatCompound(aS, aMFence, aLSC);
}
aIt.Initialize(aLSC);
for (; aIt.More(); aIt.Next()) {
@ -1146,29 +1142,3 @@ void OwnInternalShapes(const TopoDS_Shape& theS,
}
}
}
//=======================================================================
//function : TreatCompound
//purpose :
//=======================================================================
void TreatCompound(const TopoDS_Shape& theS,
BOPCol_MapOfShape& aMFence,
BOPCol_ListOfShape& theLS)
{
TopAbs_ShapeEnum aType;
//
aType = theS.ShapeType();
if (aType != TopAbs_COMPOUND) {
if (aMFence.Add(theS)) {
theLS.Append(theS);
}
return;
}
//
TopoDS_Iterator aIt;
//
aIt.Initialize(theS);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aS = aIt.Value();
TreatCompound(aS, aMFence, theLS);
}
}

View File

@ -16,6 +16,7 @@
#include <BOPAlgo_BuilderSolid.hxx>
#include <BOPAlgo_MakerVolume.hxx>
#include <BOPAlgo_PaveFiller.hxx>
#include <BOPAlgo_Tools.hxx>
#include <BOPAlgo_Alerts.hxx>
#include <BOPCol_DataMapOfShapeListOfShape.hxx>
#include <BOPCol_ListOfShape.hxx>
@ -29,10 +30,6 @@
static
void AddFace(const TopoDS_Shape& theF,
BOPCol_ListOfShape& theLF);
static
void TreatCompound(const TopoDS_Shape& theS,
BOPCol_MapOfShape& aMFence,
BOPCol_ListOfShape& theLS);
//=======================================================================
//function : CheckData
@ -352,7 +349,7 @@ void BOPAlgo_MakerVolume::FillInternalShapes(const BOPCol_ListOfShape& theLSR)
aIt.Initialize(anArguments);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aS = aIt.Value();
TreatCompound(aS, aMFence, aLSC);
BOPAlgo_Tools::TreatCompound(aS, aMFence, aLSC);
}
//
aIt.Initialize(aLSC);
@ -440,26 +437,3 @@ void AddFace(const TopoDS_Shape& theF,
aFF.Orientation(TopAbs_REVERSED);
theLF.Append(aFF);
}
//=======================================================================
//function : TreatCompound
//purpose :
//=======================================================================
void TreatCompound(const TopoDS_Shape& theS,
BOPCol_MapOfShape& aMFence,
BOPCol_ListOfShape& theLS)
{
TopAbs_ShapeEnum aType = theS.ShapeType();
if (aType != TopAbs_COMPOUND) {
if (aMFence.Add(theS)) {
theLS.Append(theS);
}
return;
}
//
TopoDS_Iterator aIt(theS);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aS = aIt.Value();
TreatCompound(aS, aMFence, theLS);
}
}

View File

@ -1089,3 +1089,26 @@ void BOPAlgo_Tools::IntersectVertices(const BOPCol_IndexedDataMapOfShapeReal& th
}
}
}
//=======================================================================
//function : TreatCompound
//purpose :
//=======================================================================
void BOPAlgo_Tools::TreatCompound(const TopoDS_Shape& theS,
BOPCol_MapOfShape& aMFence,
BOPCol_ListOfShape& theLS)
{
TopAbs_ShapeEnum aType = theS.ShapeType();
if (aType != TopAbs_COMPOUND)
{
if (aMFence.Add(theS))
theLS.Append(theS);
return;
}
TopoDS_Iterator aIt(theS);
for (; aIt.More(); aIt.Next())
{
const TopoDS_Shape& aS = aIt.Value();
TreatCompound(aS, aMFence, theLS);
}
}

View File

@ -23,6 +23,8 @@
#include <BOPDS_IndexedDataMapOfPaveBlockListOfInteger.hxx>
#include <BOPCol_IndexedDataMapOfShapeReal.hxx>
#include <BOPCol_ListOfListOfShape.hxx>
#include <BOPCol_MapOfShape.hxx>
#include <BOPCol_ListOfShape.hxx>
#include <BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock.hxx>
#include <BOPDS_PDS.hxx>
#include <Standard_Integer.hxx>
@ -155,6 +157,12 @@ public:
const Standard_Real theFuzzyValue,
BOPCol_ListOfListOfShape& theChains);
//! Collect in the output list recursively all non-compound subshapes of the first level
//! of the given shape theS. If a shape presents in the map theMFence it is skipped.
//! All shapes put in the output are also added into theMFence.
Standard_EXPORT static void TreatCompound(const TopoDS_Shape& theS,
BOPCol_MapOfShape& theMFence,
BOPCol_ListOfShape& theLS);
};
#endif // _BOPAlgo_Tools_HeaderFile

View File

@ -24,7 +24,7 @@
#include <BRepAdaptor_Surface.hxx>
#include <BRepAlgo_NormalProjection.hxx>
#include <BRepAlgo_SequenceOfSequenceOfInteger.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Section.hxx>
#include <BRepLib_MakeEdge.hxx>
#include <BRepLib_MakeVertex.hxx>
#include <BRepLib_MakeWire.hxx>
@ -481,9 +481,9 @@ void BRepAlgo_NormalProjection::SetDefaultParams()
if (!Degenerated) {
// Perform Boolean COMMON operation to get parts of projected edge
// inside the face
BRepAlgoAPI_Common aCommon(Faces->Value(j), prj);
if (aCommon.IsDone()) {
const TopoDS_Shape& aRC = aCommon.Shape();
BRepAlgoAPI_Section aSection(Faces->Value(j), prj);
if (aSection.IsDone()) {
const TopoDS_Shape& aRC = aSection.Shape();
//
TopExp_Explorer aExpE(aRC, TopAbs_EDGE);
for (; aExpE.More(); aExpE.Next()) {

View File

@ -125,41 +125,6 @@ static Standard_Boolean IsLikeSeam(const TopoDS_Edge& anEdge,
return Standard_False;
}
static Standard_Boolean CheckSharedEdgeOri(const TopoDS_Face& theF1,
const TopoDS_Face& theF2,
const TopoDS_Edge& theE)
{
TopAbs_Orientation anEOri = theE.Orientation();
if (anEOri == TopAbs_EXTERNAL || anEOri == TopAbs_INTERNAL)
return Standard_False;
TopExp_Explorer Exp(theF1, TopAbs_EDGE);
for (;Exp.More();Exp.Next())
{
const TopoDS_Shape& aCE = Exp.Current();
if (aCE.IsSame(theE))
{
anEOri = aCE.Orientation();
break;
}
}
for (Exp.Init(theF2, TopAbs_EDGE);Exp.More();Exp.Next())
{
const TopoDS_Shape& aCE = Exp.Current();
if (aCE.IsSame(theE))
{
if (aCE.Orientation() == TopAbs::Reverse(anEOri))
return Standard_True;
else
return Standard_False;
}
}
return Standard_False;
}
//=======================================================================
//function : AddOrdinaryEdges
//purpose : auxilary
@ -1234,7 +1199,7 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
// unify faces in each shell separately
TopExp_Explorer exps;
for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next())
IntUnifyFaces(exps.Current(), aGMapEdgeFaces, Standard_False);
IntUnifyFaces(exps.Current(), aGMapEdgeFaces);
// gather all faces out of shells in one compound and unify them at once
BRep_Builder aBB;
@ -1245,7 +1210,7 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
aBB.Add(aCmp, exps.Current());
if (nbf > 0)
IntUnifyFaces(aCmp, aGMapEdgeFaces, Standard_True);
IntUnifyFaces(aCmp, aGMapEdgeFaces);
myShape = myContext->Apply(myShape);
}
@ -1274,8 +1239,7 @@ static void SetFixWireModes(ShapeFix_Face& theSff)
//=======================================================================
void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape,
TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
Standard_Boolean IsCheckSharedEdgeOri)
TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces)
{
// creating map of edge faces for the shape
TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
@ -1356,9 +1320,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
if (aProcessed.Contains(anCheckedFace))
continue;
if (IsCheckSharedEdgeOri && !CheckSharedEdgeOri(aFace, anCheckedFace, edge) )
continue;
if (bCheckNormals) {
// get normal of checked face using the same parameter on edge
gp_Dir aDN2;

View File

@ -133,8 +133,7 @@ protected:
Standard_EXPORT void UnifyEdges();
void IntUnifyFaces(const TopoDS_Shape& theInpShape,
TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
Standard_Boolean IsCheckSharedEdgeOri);
TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces);
//! Fills the history of the modifications during the operation.
Standard_EXPORT void FillHistory();

View File

@ -0,0 +1,31 @@
puts "========"
puts "OCC29234"
puts "========"
puts ""
#################################################
# BRepOffsetAPI_NormalProjection produces INTERNAL edges and vertices
#################################################
restore [locate_data_file bug29234_cyl_n_wire.brep] a
explode a
renamevar a_1 f
renamevar a_2 w
nproject r w f
foreach e [explode r e] {
if [regexp "INTERNAL" [dtyp $e]] {
puts "Error: projection result contains edges oriented INTERNAL"
break
}
}
don r
fit
checknbshapes r -m "projection result" -edge 4
checkview -display r -2d -path ${imagedir}/${test_image}_1.png
bcommon r1 f r
foreach e [explode r1 e] {
if [regexp "INTERNAL" [dtyp $e]] {
puts "Error: result of common between face and edge contains edges oriented INTERNAL"
break
}
}