From 41aa3c3d5d77e6e95f02548c893f5dea22e1f65e Mon Sep 17 00:00:00 2001 From: emv Date: Mon, 14 Nov 2016 10:19:15 +0300 Subject: [PATCH] 0028046: Incomplete result of offset operation in mode complete intersection 1. Special usage of the common edges not belonging to any invalidity while rebuilding the invalid faces (method IntersectFaces() in BRepOffset_MakeOffset_1.cxx). Such edges could only be extended to the valid faces boundaries, thus could only split the face and not create any new part. 2. Test cases for the issue. --- src/BRepOffset/BRepOffset_MakeOffset_1.cxx | 457 ++++++++++++++++----- tests/offset/shape_type_i_c/Q1 | 5 +- tests/offset/shape_type_i_c/XC5 | 5 +- tests/offset/shape_type_i_c/XL1 | 10 + tests/offset/shape_type_i_c/XL2 | 19 + tests/offset/shape_type_i_c/XL3 | 10 + tests/offset/shape_type_i_c/XL4 | 19 + tests/offset/shape_type_i_c/XL5 | 10 + tests/offset/shape_type_i_c/XL6 | 10 + tests/offset/shape_type_i_c/XL7 | 10 + tests/offset/shape_type_i_c/XL8 | 21 + tests/offset/shape_type_i_c/XL9 | 10 + tests/offset/shape_type_i_c/XM1 | 10 + tests/offset/shape_type_i_c/XM2 | 10 + tests/offset/shape_type_i_c/XM3 | 14 + tests/offset/shape_type_i_c/ZD9 | 5 +- 16 files changed, 518 insertions(+), 107 deletions(-) create mode 100644 tests/offset/shape_type_i_c/XL1 create mode 100644 tests/offset/shape_type_i_c/XL2 create mode 100644 tests/offset/shape_type_i_c/XL3 create mode 100644 tests/offset/shape_type_i_c/XL4 create mode 100644 tests/offset/shape_type_i_c/XL5 create mode 100644 tests/offset/shape_type_i_c/XL6 create mode 100644 tests/offset/shape_type_i_c/XL7 create mode 100644 tests/offset/shape_type_i_c/XL8 create mode 100644 tests/offset/shape_type_i_c/XL9 create mode 100644 tests/offset/shape_type_i_c/XM1 create mode 100644 tests/offset/shape_type_i_c/XM2 create mode 100644 tests/offset/shape_type_i_c/XM3 diff --git a/src/BRepOffset/BRepOffset_MakeOffset_1.cxx b/src/BRepOffset/BRepOffset_MakeOffset_1.cxx index 0bb423ee20..ffb3749291 100644 --- a/src/BRepOffset/BRepOffset_MakeOffset_1.cxx +++ b/src/BRepOffset/BRepOffset_MakeOffset_1.cxx @@ -333,8 +333,10 @@ static const TopTools_DataMapOfShapeShape& theETrimEInf, const TopTools_DataMapOfShapeListOfShape& theMEInfETrim, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, + const TopTools_MapOfShape& theAllInvs, const Standard_Boolean theForceUse, TopTools_IndexedMapOfShape& theMECV, + TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theDMEETrim, TopTools_ListOfShape& theLFEi, TopTools_ListOfShape& theLFEj, @@ -381,6 +383,7 @@ static const TopTools_IndexedMapOfShape& theMVE, const TopTools_MapOfShape& theVertsToAvoid, const TopTools_MapOfShape& theNewVertsToAvoid, + const TopTools_MapOfShape& theMECheckExt, TopTools_MapOfShape& theMVBounds, TopTools_DataMapOfShapeListOfShape& theEImages); @@ -390,14 +393,14 @@ static BOPAlgo_Builder& theGF, TopTools_MapOfShape& theMEInv); -static - void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, - const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, +static + void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theFLE, const TopTools_MapOfShape& theMVBounds, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theInvertedEdges, + TopTools_MapOfShape& theMECheckExt, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, @@ -413,12 +416,14 @@ static void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE, const TopTools_DataMapOfShapeListOfShape& theEETrim, const TopTools_MapOfShape& theMVBounds, + TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theMEB, TopTools_MapOfShape& theMVOld, TopTools_ListOfShape& theLENew, BOPCol_ListOfShape& theLA, - TopTools_DataMapOfShapeListOfShape& theDMEOr); + TopTools_DataMapOfShapeListOfShape& theDMEOr, + TopTools_DataMapOfShapeListOfShape& theMELF); static void IntersectEdges(const BOPCol_ListOfShape& theLA, @@ -426,9 +431,11 @@ static const TopTools_ListOfShape& theLENew, const TopTools_MapOfShape& theMVBounds, const TopTools_MapOfShape& theVertsToAvoid, + TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theModifiedEdges, TopTools_DataMapOfShapeListOfShape& theDMEOr, + TopTools_DataMapOfShapeListOfShape& theMELF, TopTools_MapOfShape& theMENew, TopoDS_Shape& theSplits); @@ -450,14 +457,15 @@ static static void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, const TopoDS_Shape& theBounds, - const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theMVOld, const TopTools_MapOfShape& theMENew, const TopTools_DataMapOfShapeListOfShape& theDMEOr, + const TopTools_DataMapOfShapeListOfShape& theMELF, const TopTools_DataMapOfShapeListOfShape& theEImages, + const TopTools_MapOfShape& theMECheckExt, TopTools_MapOfShape& theVertsToAvoid, TopTools_MapOfShape& theMEInv); @@ -3312,7 +3320,7 @@ void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebui // when dealing with artificially invalid faces for intersection to be // complete we need to use not only invalid edges, but also the // edges connected to invalid ones - TopTools_MapOfShape aMEAlone, aMFence; + TopTools_MapOfShape aMEAlone, aMFence, aMVEInv; TopTools_IndexedDataMapOfShapeListOfShape aDMVEVal; // TopTools_DataMapIteratorOfDataMapOfShapeShape aItM(theArtInvFaces); @@ -3325,7 +3333,13 @@ void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebui for (TopExp_Explorer aExp(aFInv, TopAbs_EDGE); aExp.More(); aExp.Next()) { const TopoDS_Shape& aE = aExp.Current(); - if (!theInvEdges.Contains(aE) && aMFence.Add(aE)) { + if (theInvEdges.Contains(aE)) { + for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) { + aMVEInv.Add(aItV.Value()); + } + continue; + } + if (aMFence.Add(aE)) { TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aDMVEVal); } } @@ -3335,48 +3349,76 @@ void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebui // collect edges with free vertices Standard_Integer aNbV = aDMVEVal.Extent(); for (i = 1; i <= aNbV; ++i) { + const TopoDS_Shape& aV = aDMVEVal.FindKey(i); + if (!aMVEInv.Contains(aV)) { + continue; + } + // const TopTools_ListOfShape& aLEV = aDMVEVal(i); - if (aLEV.Extent() == 1) { - const TopoDS_Shape& aE = aLEV.First(); - aMEAlone.Add(aE); - // - // if this alone edge adds nothing to the intersection list - // it means that the origin of this edge has been split and we need to - // add the neigboring images of the same origins - if (aDMSF.Find(aE).Extent() > 1) { - continue; + if (aLEV.Extent() > 1) { + continue; + } + // + const TopoDS_Shape& aE = aLEV.First(); + aMEAlone.Add(aE); + // + // if this alone edge adds nothing to the intersection list + // it means that the origin of this edge has been split and we need to + // add the neigboring images of the same origins + if (aDMSF.Find(aE).Extent() > 1) { + continue; + } + // + // check also its vertices + TopoDS_Iterator aItE(aE); + for (; aItE.More(); aItE.Next()) { + const TopoDS_Shape& aV = aItE.Value(); + if (aDMSF.Find(aV).Extent() > 2) { + break; } + } + // + if (aItE.More()) { + continue; + } + // + // the edge is useless - look for other images + const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE); + if (!pLEOr) { + continue; + } + // + TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr); + for (; aItLEOr.More(); aItLEOr.Next()) { + const TopoDS_Shape& aEOr = aItLEOr.Value(); // - // check also its vertices - TopoDS_Iterator aItE(aE); - for (; aItE.More(); aItE.Next()) { - const TopoDS_Shape& aV = aItE.Value(); - if (aDMSF.Find(aV).Extent() > 2) { - break; + const TopTools_ListOfShape& aLEIm = theOEImages.Find(aEOr); + TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); + for (; aItLEIm.More(); aItLEIm.Next()) { + const TopoDS_Shape& aEIm = aItLEIm.Value(); + // + if (aMFence.Contains(aEIm)) { + aMEAlone.Add(aEIm); } } - // - if (aItE.More()) { - continue; - } - // - // the edge is useless - look for other images - const TopTools_ListOfShape *pLEOr = theOEOrigins.Seek(aE); - if (!pLEOr) { - continue; - } - // - TopTools_ListIteratorOfListOfShape aItLEOr(*pLEOr); - for (; aItLEOr.More(); aItLEOr.Next()) { - const TopoDS_Shape& aEOr = aItLEOr.Value(); - // - const TopTools_ListOfShape& aLEIm = theOEImages.Find(aEOr); - TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); - for (; aItLEIm.More(); aItLEIm.Next()) { - const TopoDS_Shape& aEIm = aItLEIm.Value(); - // - if (aMFence.Contains(aEIm)) { - aMEAlone.Add(aEIm); + } + } + // + // Get all invalidities from all faces to be used for avoiding + // repeated usage of the common edges + TopTools_MapOfShape aMAllInvs; + aNbInv = theInvFaces.Extent(); + for (k = 1; k <= aNbInv; ++k) { + TopTools_ListIteratorOfListOfShape aIt(theInvFaces(k)); + for (; aIt.More(); aIt.Next()) { + TopExp_Explorer aExp(aIt.Value(), TopAbs_EDGE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Shape& aE = aExp.Current(); + if (theInvEdges.Contains(aE) || aMEAlone.Contains(aE)) { + aMAllInvs.Add(aE); + TopoDS_Iterator aItV(aE); + for (; aItV.More(); aItV.Next()) { + aMAllInvs.Add(aItV.Value()); } } } @@ -3385,6 +3427,8 @@ void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebui // // Bounding vertices of not trimmed edges TopTools_MapOfShape aMVBounds; + // + TopTools_MapOfShape aMECheckExt; // Save connections between not trimmed edge and its trimmed parts TopTools_DataMapOfShapeListOfShape aDMEETrim; // Splits of the new edges @@ -3505,7 +3549,7 @@ void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebui // no need to intersect if we have common edges between faces Standard_Boolean bForceUse = aMFIntExt.Contains(aFi) || aMFIntExt.Contains(aFj); ProcessCommonEdges(aLEC, theInvEdges, theValidEdges, aME, theETrimEInf, aMEInfETrim, - theOEOrigins, bForceUse, aMECV, aDMEETrim, aLFEi, aLFEj, aMEToInt); + theOEOrigins, aMAllInvs, bForceUse, aMECV, aMECheckExt, aDMEETrim, aLFEi, aLFEj, aMEToInt); continue; } // @@ -3545,15 +3589,15 @@ void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebui } // // intersect and trim edges for this chain - IntersectAndTrimEdges(theFToRebuild, aMFInt, aMEToInt, aDMEETrim, - aME, aMECV, aMVInv, aMVRInv, aMVBounds, aEImages); + IntersectAndTrimEdges(theFToRebuild, aMFInt, aMEToInt, aDMEETrim, aME, aMECV, + aMVInv, aMVRInv, aMECheckExt, aMVBounds, aEImages); } } } // // filter the obtained edges - UpdateValidEdges(theFToRebuild, theFImages, aFLE, aMVBounds, theSolids, theInvEdges, - theInvertedEdges, theEdgesToAvoid, theEdgesOrigins, theOEImages, theOEOrigins, + UpdateValidEdges(theFImages, aFLE, aMVBounds, theSolids, theInvEdges, theInvertedEdges, + aMECheckExt, theEdgesToAvoid, theEdgesOrigins, theOEImages, theOEOrigins, theVertsToAvoid, theETrimEInf, aEImages, aDMEETrim, theModifiedEdges, theAsDes); } @@ -3869,8 +3913,10 @@ void ProcessCommonEdges(const TopTools_ListOfShape& theLEC, const TopTools_DataMapOfShapeShape& theETrimEInf, const TopTools_DataMapOfShapeListOfShape& theMEInfETrim, const TopTools_DataMapOfShapeListOfShape& theOEOrigins, + const TopTools_MapOfShape& theAllInvs, const Standard_Boolean theForceUse, TopTools_IndexedMapOfShape& theMECV, + TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theDMEETrim, TopTools_ListOfShape& theLFEi, TopTools_ListOfShape& theLFEj, @@ -3903,9 +3949,32 @@ void ProcessCommonEdges(const TopTools_ListOfShape& theLEC, } } // - Standard_Boolean bUseOnlyInf = (aLEC.IsEmpty() && theForceUse); + Standard_Boolean bUseOnlyInf = aLEC.IsEmpty(); if (bUseOnlyInf) { - aLEC = theLEC; + if (theForceUse) { + aLEC = theLEC; + } + else { + aItLE.Initialize(theLEC); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aEC = aItLE.Value(); + if (theAllInvs.Contains(aEC) || theInvEdges.Contains(aEC)) { + return; + } + // + TopoDS_Iterator aItV(aEC); + for (; aItV.More(); aItV.Next()) { + if (theAllInvs.Contains(aItV.Value())) { + return; + } + } + // + // use only one element + if (aLEC.IsEmpty()) { + aLEC.Append(aEC); + } + } + } } // aItLE.Initialize(aLEC); @@ -3935,6 +4004,9 @@ void ProcessCommonEdges(const TopTools_ListOfShape& theLEC, } AppendToList(*pLTAdded, aEC); } + else if (!theForceUse) { + theMECheckExt.Add(aEInt); + } // AppendToList(theLFEi, aEInt); AppendToList(theLFEj, aEInt); @@ -4129,6 +4201,7 @@ void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theF const TopTools_IndexedMapOfShape& theMVE, const TopTools_MapOfShape& theVertsToAvoid, const TopTools_MapOfShape& theNewVertsToAvoid, + const TopTools_MapOfShape& theMECheckExt, TopTools_MapOfShape& theMVBounds, TopTools_DataMapOfShapeListOfShape& theEImages) { @@ -4198,10 +4271,15 @@ void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theF TopTools_ListOfShape aLENew; // get edges to intersect TopTools_ListOfShape aLEInt; + // Common intersection edges. Should be intersected separetely + TopTools_ListOfShape aLCE; + // aNb = theMEInt.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aE = theMEInt(i); - if (!aMFence.Add(aE)) { + if (theMECheckExt.Contains(aE)) { + // avoid trimming of the intersection edges by additional common edges + aLCE.Append(aE); continue; } // @@ -4245,6 +4323,11 @@ void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theF TopTools_MapOfShape aMEInv; GetInvalidEdges(theNewVertsToAvoid, theMVBounds, aGF, aMEInv); // + BRep_Builder aBB; + // get valid splits to intersect with the commons + TopoDS_Compound aCEIm; + aBB.MakeCompound(aCEIm); + // // remove the splits containing vertices from invalid edges aIt.Initialize(aLEInt); for (; aIt.More(); aIt.Next()) { @@ -4263,18 +4346,80 @@ void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theF aLEIm.Remove(aIt1); } else { + aBB.Add(aCEIm, aEIm); aIt1.Next(); } } // if (aLEIm.Extent()) { - if (theEImages.IsBound(aE)) { - theEImages.ChangeFind(aE).Append(aLEIm); + TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE); + if (!pLEIm) { + pLEIm = theEImages.Bound(aE, TopTools_ListOfShape()); } - else { - theEImages.Bind(aE, aLEIm); + pLEIm->Append(aLEIm); + } + } + // + if (!aLCE.Extent()) { + return; + } + // + // trim common edges by other intersection edges + BOPAlgo_Builder aGFCE; + aGFCE.SetArguments(aLCE); + aGFCE.AddArgument(aCEIm); + aGFCE.Perform(); + // + if (aGFCE.ErrorStatus()) { + return; + } + // + const BOPDS_PDS& pDS = aGFCE.PDS(); + TopTools_ListIteratorOfListOfShape aItLCE(aLCE); + for (; aItLCE.More(); aItLCE.Next()) { + const TopoDS_Shape& aE = aItLCE.Value(); + TopTools_ListOfShape aLEIm = aGFCE.Modified(aE); + if (aLEIm.IsEmpty()) { + continue; + } + // + // check if it's not coincide with some intersection edge + BOPDS_ListIteratorOfListOfPaveBlock aItLPB(pDS->PaveBlocks(pDS->Index(aE))); + for (; aItLPB.More(); aItLPB.Next()) { + if (pDS->IsCommonBlock(aItLPB.Value())) { + // find with what it is a common + const BOPDS_ListOfPaveBlock& aLPBC = pDS->CommonBlock(aItLPB.Value())->PaveBlocks(); + BOPDS_ListIteratorOfListOfPaveBlock aItLPBC(aLPBC); + for (; aItLPBC.More(); aItLPBC.Next()) { + const TopoDS_Shape& aEC = pDS->Shape(aItLPBC.Value()->OriginalEdge()); + if (!theMECheckExt.Contains(aEC)) { + break; + } + } + if (aItLPBC.More()) { + break; + } } } + if (aItLPB.More()) { + // avoid creation of unnecessary splits from commons which + // coincide with intersection edges + continue; + } + // + // save the images + TopTools_ListOfShape* pLEIm = theEImages.ChangeSeek(aE); + if (!pLEIm) { + pLEIm = theEImages.Bound(aE, TopTools_ListOfShape()); + } + pLEIm->Append(aLEIm); + // + // save bounding vertices + for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) { + const TopoDS_Shape& aV = aItV.Value(); + const TopTools_ListOfShape& aLVIm = aGFCE.Modified(aV); + theMVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First()); + } } } @@ -4344,13 +4489,13 @@ void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid, //function : UpdateValidEdges //purpose : Making the new splits and updating the maps //======================================================================= -void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, - const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, +void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopTools_IndexedDataMapOfShapeListOfShape& theFLE, const TopTools_MapOfShape& theMVBounds, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theInvertedEdges, + TopTools_MapOfShape& theMECheckExt, TopTools_IndexedMapOfShape& theEdgesToAvoid, TopTools_DataMapOfShapeListOfShape& theEdgesOrigins, TopTools_DataMapOfShapeListOfShape& theOEImages, @@ -4403,7 +4548,8 @@ void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToReb // // trim the new intersection edges BOPCol_ListOfShape aLA; - TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theEImages, aMEB, aMVOld, aLENew, aLA, aDMEOr); + TrimNewIntersectionEdges(aLE, theEETrim, theMVBounds, theMECheckExt, theEImages, + aMEB, aMVOld, aLENew, aLA, aDMEOr, aMELF); // if (aLA.IsEmpty()) { // update intersection edges @@ -4415,8 +4561,8 @@ void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToReb TopoDS_Shape aSplits1; if (aLA.Extent() > 1) { // intersect the new splits among themselves to avoid self-intersections - IntersectEdges(aLA, aLE, aLENew, theMVBounds, theVertsToAvoid, theEImages, - theModifiedEdges, aDMEOr, aMENew, aSplits1); + IntersectEdges(aLA, aLE, aLENew, theMVBounds, theVertsToAvoid, theMECheckExt, + theEImages, theModifiedEdges, aDMEOr, aMELF, aMENew, aSplits1); } else { aSplits1 = aLA.First(); @@ -4428,8 +4574,9 @@ void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToReb // // intersect splits and bounds and remove those splits which have pure E/E intersection TopTools_MapOfShape aMEInv; - GetInvalidEdgesByBounds(aSplits1, aFilterBounds, theFToRebuild, theFImages, theSolids, - theInvEdges, aMVOld, aMENew, aDMEOr, theEImages, theVertsToAvoid, aMEInv); + GetInvalidEdgesByBounds(aSplits1, aFilterBounds, theFImages, theSolids, + theInvEdges, aMVOld, aMENew, aDMEOr, aMELF, theEImages, + theMECheckExt, theVertsToAvoid, aMEInv); // // get valid edges only TopoDS_Shape aSplits; @@ -4567,19 +4714,22 @@ void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToReb void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE, const TopTools_DataMapOfShapeListOfShape& theEETrim, const TopTools_MapOfShape& theMVBounds, + TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theMEB, TopTools_MapOfShape& theMVOld, TopTools_ListOfShape& theLENew, BOPCol_ListOfShape& theLA, - TopTools_DataMapOfShapeListOfShape& theDMEOr) + TopTools_DataMapOfShapeListOfShape& theDMEOr, + TopTools_DataMapOfShapeListOfShape& theMELF) { TopTools_ListIteratorOfListOfShape aIt, aIt1; aIt.Initialize(theLE); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); // - if (theEETrim.IsBound(aE)) { + Standard_Boolean bOld = theEETrim.IsBound(aE); + if (bOld) { const TopTools_ListOfShape& aLET = theEETrim.Find(aE); aIt1.Initialize(aLET); for (; aIt1.More(); aIt1.Next()) { @@ -4636,12 +4786,7 @@ void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE, const TopoDS_Shape& aV = aMV(iV); if (theMVBounds.Contains(aV) || aV.IsSame(aV1) || aV.IsSame(aV2)) { const TopTools_ListOfShape& aLVIm = aGFE.Modified(aV); - if (aLVIm.Extent()) { - aMEVBounds.Add(aLVIm.First()); - } - else { - aMEVBounds.Add(aV); - } + aMEVBounds.Add(aLVIm.IsEmpty() ? aV : aLVIm.First()); } } // @@ -4675,18 +4820,36 @@ void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE, } } // + Standard_Boolean bCheckExt = theMECheckExt.Contains(aE); if (aLEIm.IsEmpty()) { theEImages.UnBind(aE); } else { - if (!theEETrim.IsBound(aE)) { - TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); - for (; aItLEIm.More(); aItLEIm.Next()) { - const TopoDS_Shape& aEIm = aItLEIm.Value(); + const TopTools_ListOfShape& aLFE = theMELF.Find(aE); + TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); + for (; aItLEIm.More(); aItLEIm.Next()) { + const TopoDS_Shape& aEIm = aItLEIm.Value(); + TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm); + if (!pLFEIm) { + pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape()); + } + TopTools_ListIteratorOfListOfShape aItLF(aLFE); + for (; aItLF.More(); aItLF.Next()) { + AppendToList(*pLFEIm, aItLF.Value()); + } + // + if (bCheckExt) { + theMECheckExt.Add(aEIm); + } + else if (!bOld) { theLENew.Append(aEIm); } } } + // + if (bCheckExt) { + theMECheckExt.Remove(aE); + } } } @@ -4699,9 +4862,11 @@ void IntersectEdges(const BOPCol_ListOfShape& theLA, const TopTools_ListOfShape& theLENew, const TopTools_MapOfShape& theMVBounds, const TopTools_MapOfShape& theVertsToAvoid, + TopTools_MapOfShape& theMECheckExt, TopTools_DataMapOfShapeListOfShape& theEImages, TopTools_MapOfShape& theModifiedEdges, TopTools_DataMapOfShapeListOfShape& theDMEOr, + TopTools_DataMapOfShapeListOfShape& theMELF, TopTools_MapOfShape& theMENew, TopoDS_Shape& theSplits) { @@ -4745,6 +4910,38 @@ void IntersectEdges(const BOPCol_ListOfShape& theLA, } } // + // update edges after intersection for extended checking + aIt.Initialize(theLA); + for (; aIt.More(); aIt.Next()) { + const TopoDS_Shape& aE = aIt.Value(); + const TopTools_ListOfShape& aLEIm = aGFA.Modified(aE); + if (aLEIm.IsEmpty()) { + continue; + } + // + if (theMECheckExt.Contains(aE)) { + aIt1.Initialize(aLEIm); + for (; aIt1.More(); aIt1.Next()) { + theMECheckExt.Add(aIt1.Value()); + } + theMECheckExt.Remove(aE); + } + // + const TopTools_ListOfShape& aLFE = theMELF.Find(aE); + aIt1.Initialize(aLEIm); + for (; aIt1.More(); aIt1.Next()) { + const TopoDS_Shape& aEIm = aIt1.Value(); + TopTools_ListOfShape* pLFEIm = theMELF.ChangeSeek(aEIm); + if (!pLFEIm) { + pLFEIm = theMELF.Bound(aEIm, TopTools_ListOfShape()); + } + TopTools_ListIteratorOfListOfShape aItLF(aLFE); + for (; aItLF.More(); aItLF.Next()) { + AppendToList(*pLFEIm, aItLF.Value()); + } + } + } + // TopTools_MapOfShape aMEInv; GetInvalidEdges(theVertsToAvoid, theMVBounds, aGFA, aMEInv); if (aMEInv.Extent()) { @@ -4877,14 +5074,15 @@ void GetBoundsToUpdate(const TopTools_ListOfShape& theLF, //======================================================================= void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, const TopoDS_Shape& theBounds, - const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, const TopTools_IndexedDataMapOfShapeListOfShape& theFImages, const TopoDS_Shape& theSolids, const TopTools_IndexedMapOfShape& theInvEdges, const TopTools_MapOfShape& theMVOld, const TopTools_MapOfShape& theMENew, const TopTools_DataMapOfShapeListOfShape& theDMEOr, + const TopTools_DataMapOfShapeListOfShape& theMELF, const TopTools_DataMapOfShapeListOfShape& theEImages, + const TopTools_MapOfShape& theMECheckExt, TopTools_MapOfShape& theVertsToAvoid, TopTools_MapOfShape& theMEInv) { @@ -4906,18 +5104,22 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, Standard_Integer i, aNb = aEEs.Extent(); for (i = 0; i < aNb; ++i) { const BOPDS_InterfEE& aEE = aEEs(i); - if (!aEE.HasIndexNew()) { - continue; - } // const TopoDS_Shape& aE1 = pDS->Shape(aEE.Index1()); const TopoDS_Shape& aE2 = pDS->Shape(aEE.Index2()); // + if (!aEE.HasIndexNew()) { + if (theMECheckExt.Contains(aE1) && (aEE.CommonPart().Type() == TopAbs_EDGE)) { + theMEInv.Add(aE1); + } + continue; + } + // if (theInvEdges.Contains(aE2)) { theMEInv.Add(aE1); } // - // add vertices of all images of this edges for checking + // add vertices of all images of the edge from splits for checking const TopTools_ListOfShape& aLEOr = theDMEOr.Find(aE1); TopTools_ListIteratorOfListOfShape aItLEOr(aLEOr); for (; aItLEOr.More(); aItLEOr.Next()) { @@ -4945,7 +5147,9 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, TopExp::MapShapesAndAncestors(theSplits, TopAbs_VERTEX, TopAbs_EDGE, aDMVE); // // to avoid unnecessary filling of parts due to extra trim of the edges - // process Edge/Edge interferences of type EDGE, i.e. common blocks. + // process Edge/Edge interferences of type EDGE, i.e. common blocks and check + // not the bounding vertices of the edges, but check the edge itself + // to be lying on some face // // all common blocks are contained in the result of SECTION operation // between sets of edges @@ -4974,22 +5178,20 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, const TopoDS_Shape& aEIm = aItLEIm.Value(); if (!aMSSec.Contains(aEIm)) { // the edge included in section only partially. - // the part not included in section may be excesssive + // the part not included in section may be excessive // // check vertices of this edge - if one of them is new // the edge might be removed TopoDS_Vertex aV1, aV2; TopExp::Vertices(TopoDS::Edge(aEIm), aV1, aV2); if (!theMVOld.Contains(aV1) || !theMVOld.Contains(aV2)) { - // add this edge for checking + // add this edge for checking by making new vertex in the middle of the edge TopoDS_Vertex aV; Standard_Real f, l; const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aEIm), f, l); BRep_Builder().MakeVertex(aV, aC->Value((f+l)*0.5), Precision::Confusion()); - // - TopTools_ListOfShape aLEx; - aLEx.Append(aE); - aDMVE.Add(aV, aLEx); + // and adding this vertex for checking + aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE); aMVInv.Add(aV); break; } @@ -4997,7 +5199,24 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, } } // - // add for check also the vertices connected only to new edges + // Add for check also the edges created from common between splits + // of offset faces edges not connected to any invalidity. + // These edges may also accidentally fill some part. + TopTools_MapIteratorOfMapOfShape aItM(theMECheckExt); + for (; aItM.More(); aItM.Next()) { + const TopoDS_Shape& aE = aItM.Value(); + // + // make new vertex in the middle of the edge + TopoDS_Vertex aV; + Standard_Real f, l; + const Handle(Geom_Curve)& aC = BRep_Tool::Curve(TopoDS::Edge(aE), f, l); + BRep_Builder().MakeVertex(aV, aC->Value((f + l)*0.5), Precision::Confusion()); + // add this vertex for checking + aDMVE.ChangeFromIndex(aDMVE.Add(aV, TopTools_ListOfShape())).Append(aE); + aMVInv.Add(aV); + } + // + // add for check also the vertices connected only to new or old edges aNb = aDMVE.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Shape& aV = aDMVE.FindKey(i); @@ -5010,6 +5229,10 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, TopTools_ListIteratorOfListOfShape aIt(aLEx); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE = aIt.Value(); + if (theMECheckExt.Contains(aE)) { + continue; + } + // if (theMENew.Contains(aE)) { bNew = Standard_True; } @@ -5028,17 +5251,38 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, } } // + // perform the checking Handle(IntTools_Context) aCtx = new IntTools_Context; // filter vertices - Standard_Integer iv, aNbIV = aMVInv.Extent(), aNbF = theFToRebuild.Extent(); + Standard_Integer iv, aNbIV = aMVInv.Extent(); for (iv = 1; iv <= aNbIV; ++iv) { const TopoDS_Vertex& aV = TopoDS::Vertex(aMVInv(iv)); - const gp_Pnt& aP = BRep_Tool::Pnt(aV); - Standard_Real aTolV = BRep_Tool::Tolerance(aV); + if (theMVOld.Contains(aV)) { + continue; + } + // + const TopTools_ListOfShape* pLEInv = aDMVE.Seek(aV); + if (!pLEInv) { + continue; + } + // find faces by the edges to check the vertex + TopTools_IndexedMapOfShape aMF; + TopTools_ListIteratorOfListOfShape aItLE(*pLEInv); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aE = aItLE.Value(); + const TopTools_ListOfShape& aLF = theMELF.Find(aE); + TopTools_ListIteratorOfListOfShape aItLF(aLF); + for (; aItLF.More(); aItLF.Next()) { + aMF.Add(aItLF.Value()); + } + } + // + // check the vertex to belong to some split of the faces Standard_Boolean bInvalid = Standard_True; // + Standard_Integer aNbF = aMF.Extent(); for (i = 1; i <= aNbF && bInvalid; ++i) { - const TopoDS_Shape& aF = theFToRebuild.FindKey(i); + const TopoDS_Face& aF = TopoDS::Face(aMF(i)); const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF); // TopTools_ListIteratorOfListOfShape aItLF(aLFIm); @@ -5049,9 +5293,19 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, const TopoDS_Shape& aVF = aExp.Current(); bInvalid = !aVF.IsSame(aV); } - // - if (bInvalid) { - bInvalid = !aCtx->IsValidPointForFace(aP, aFIm, aTolV); + } + // + if (bInvalid) { + Standard_Real U, V, aTol; + Standard_Integer iStatus = aCtx->ComputeVF(aV, aF, U, V, aTol); + if (!iStatus) { + // classify the point relatively faces + gp_Pnt2d aP2d(U, V); + aItLF.Initialize(aLFIm); + for (; aItLF.More() && bInvalid; aItLF.Next()) { + const TopoDS_Face& aFIm = TopoDS::Face(aItLF.Value()); + bInvalid = !aCtx->IsPointInOnFace(aFIm, aP2d); + } } } } @@ -5059,6 +5313,9 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, if (bInvalid && aMVCheckAdd.Contains(aV)) { // the vertex is invalid for all faces // check the same vertex for the solids + const gp_Pnt& aP = BRep_Tool::Pnt(aV); + Standard_Real aTolV = BRep_Tool::Tolerance(aV); + // TopExp_Explorer aExpS(theSolids, TopAbs_SOLID); for (; aExpS.More() && bInvalid; aExpS.Next()) { const TopoDS_Solid& aSol = TopoDS::Solid(aExpS.Current()); @@ -5070,13 +5327,9 @@ void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits, // if (bInvalid) { theVertsToAvoid.Add(aV); - if (aDMVE.Contains(aV)) { - const TopTools_ListOfShape& aLEInv = aDMVE.FindFromKey(aV); - TopTools_ListIteratorOfListOfShape aItLEInv(aLEInv); - for (; aItLEInv.More(); aItLEInv.Next()) { - const TopoDS_Shape& aEInv = aItLEInv.Value(); - theMEInv.Add(aEInv); - } + aItLE.Initialize(*pLEInv); + for (; aItLE.More(); aItLE.Next()) { + theMEInv.Add(aItLE.Value()); } } } diff --git a/tests/offset/shape_type_i_c/Q1 b/tests/offset/shape_type_i_c/Q1 index be4d566c09..84b0035be5 100644 --- a/tests/offset/shape_type_i_c/Q1 +++ b/tests/offset/shape_type_i_c/Q1 @@ -4,4 +4,7 @@ OFFSETSHAPE 1 {} $calcul $type checkprops result -v 2.40965e+007 -s 1.24031e+006 -checknbshapes result -shell 1 +unifysamedom result_unif result +checknbshapes result_unif -face 423 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XC5 b/tests/offset/shape_type_i_c/XC5 index 3eabe75235..1532e696ea 100644 --- a/tests/offset/shape_type_i_c/XC5 +++ b/tests/offset/shape_type_i_c/XC5 @@ -1,5 +1,6 @@ -puts "TODO CR27414 ALL: Error : The area of result shape is" -puts "TODO CR27414 ALL: Error : The volume of result shape is" +puts "TODO OCC27414 ALL: Error: The command cannot be built" +puts "TODO OCC27414 ALL: gives an empty result" +puts "TODO OCC27414 ALL: TEST INCOMPLETE" restore [locate_data_file bug26917_input.dom7742_simple.brep] s diff --git a/tests/offset/shape_type_i_c/XL1 b/tests/offset/shape_type_i_c/XL1 new file mode 100644 index 0000000000..ba53c6139f --- /dev/null +++ b/tests/offset/shape_type_i_c/XL1 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-106_merged_input.brep] s + +OFFSETSHAPE 10 {} $calcul $type + +checkprops result -v 4.46191e+007 -s 2.11027e+006 + +unifysamedom result_unif result +checknbshapes result_unif -face 95 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL2 b/tests/offset/shape_type_i_c/XL2 new file mode 100644 index 0000000000..dab1434b67 --- /dev/null +++ b/tests/offset/shape_type_i_c/XL2 @@ -0,0 +1,19 @@ +restore [locate_data_file bug28046_rm-106_merged_input.brep] s + +offsetparameter 1e-7 c i +offsetload s 10 +foreach f [explode s f] { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs(abs($z) - 1) < 1.e-7} { + offsetonface $f 0 + } +} +offsetperform result + +checkprops result -v 3.76417e+007 -s 2.03956e+006 + +unifysamedom result_unif result +checknbshapes result_unif -face 95 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL3 b/tests/offset/shape_type_i_c/XL3 new file mode 100644 index 0000000000..dc30780994 --- /dev/null +++ b/tests/offset/shape_type_i_c/XL3 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-106_merged_input_trim4.brep] s + +OFFSETSHAPE 10 {} $calcul $type + +checkprops result -v 1.59174e+006 -s 107814 + +unifysamedom result_unif result +checknbshapes result_unif -face 14 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL4 b/tests/offset/shape_type_i_c/XL4 new file mode 100644 index 0000000000..3b82b41ec9 --- /dev/null +++ b/tests/offset/shape_type_i_c/XL4 @@ -0,0 +1,19 @@ +restore [locate_data_file bug28046_rm-106_merged_input_trim4.brep] s + +offsetparameter 1e-7 c i +offsetload s 10 +foreach f [explode s f] { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs(abs($z) - 1) < 1.e-7} { + offsetonface $f 0 + } +} +offsetperform result + +checkprops result -v 1.28281e+006 -s 95811.8 + +unifysamedom result_unif result +checknbshapes result_unif -face 14 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL5 b/tests/offset/shape_type_i_c/XL5 new file mode 100644 index 0000000000..183a73a3d9 --- /dev/null +++ b/tests/offset/shape_type_i_c/XL5 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-106_merged_input.brep] s + +OFFSETSHAPE 17 {} $calcul $type + +checkprops result -v 6.02286e+007 -s 2.35028e+006 + +unifysamedom result_unif result +checknbshapes result_unif -face 92 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL6 b/tests/offset/shape_type_i_c/XL6 new file mode 100644 index 0000000000..611359e32b --- /dev/null +++ b/tests/offset/shape_type_i_c/XL6 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-106_merged_input_trim4.brep] s + +OFFSETSHAPE 17 {} $calcul $type + +checkprops result -v 2.44997e+006 -s 138177 + +unifysamedom result_unif result +checknbshapes result_unif -face 11 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL7 b/tests/offset/shape_type_i_c/XL7 new file mode 100644 index 0000000000..8d81a306f0 --- /dev/null +++ b/tests/offset/shape_type_i_c/XL7 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-107_merged_input.brep] s + +OFFSETSHAPE 5 {} $calcul $type + +checkprops result -v 3.77167e+007 -s 2.38257e+006 + +unifysamedom result_unif result +checknbshapes result_unif -face 600 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL8 b/tests/offset/shape_type_i_c/XL8 new file mode 100644 index 0000000000..c230b73b5a --- /dev/null +++ b/tests/offset/shape_type_i_c/XL8 @@ -0,0 +1,21 @@ +restore [locate_data_file bug28046_rm-107_merged_input_with_faces.brep] c + +#get the shape +explode c +copy c_1 s + +offsetparameter 1e-7 c i +offsetload s 5 + +foreach f [explode c_2 f] { + offsetonface $f 2 +} + +offsetperform result + +checkprops result -v 3.49518e+007 -s 2.3549e+006 + +unifysamedom result_unif result +checknbshapes result_unif -face 600 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XL9 b/tests/offset/shape_type_i_c/XL9 new file mode 100644 index 0000000000..0914bb1455 --- /dev/null +++ b/tests/offset/shape_type_i_c/XL9 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-107_merged_input.brep] s + +OFFSETSHAPE 6 {} $calcul $type + +checkprops result -v 4.01015e+007 -s 1.94455e+006 + +unifysamedom result_unif result +checknbshapes result_unif -face 244 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XM1 b/tests/offset/shape_type_i_c/XM1 new file mode 100644 index 0000000000..747eeadea4 --- /dev/null +++ b/tests/offset/shape_type_i_c/XM1 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-107_merged_input.brep] s + +OFFSETSHAPE 8 {} $calcul $type + +checkprops result -v 4.40128e+007 -s 1.81672e+006 + +unifysamedom result_unif result +checknbshapes result_unif -face 64 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XM2 b/tests/offset/shape_type_i_c/XM2 new file mode 100644 index 0000000000..d7a9132e95 --- /dev/null +++ b/tests/offset/shape_type_i_c/XM2 @@ -0,0 +1,10 @@ +restore [locate_data_file bug28046_rm-107_merged_input_trim1.brep] s + +OFFSETSHAPE 6 {} $calcul $type + +checkprops result -v 996384 -s 79069.4 + +unifysamedom result_unif result +checknbshapes result_unif -face 18 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/XM3 b/tests/offset/shape_type_i_c/XM3 new file mode 100644 index 0000000000..a8e558405f --- /dev/null +++ b/tests/offset/shape_type_i_c/XM3 @@ -0,0 +1,14 @@ +restore [locate_data_file bug28046_rm-106_simple.brep] s + +offsetparameter 1e-7 c i +offsetload s 1 +explode s f +offsetonface s_6 6 +offsetperform result + +checkprops result -v 1302.49 -s 857.327 + +unifysamedom result_unif result +checknbshapes result_unif -face 10 -shell 1 + +checkview -display result_unif -2d -path ${imagedir}/${test_image}.png diff --git a/tests/offset/shape_type_i_c/ZD9 b/tests/offset/shape_type_i_c/ZD9 index 7a00c42db1..c03747378c 100755 --- a/tests/offset/shape_type_i_c/ZD9 +++ b/tests/offset/shape_type_i_c/ZD9 @@ -1,9 +1,10 @@ -puts "TODO CR27414 ALL: Error : The command is not valid. The volume is 0." +puts "TODO CR27414 ALL: Error : The area of result shape is" +puts "TODO CR27414 ALL: Error : The volume of result shape is" restore [locate_data_file bug26917_M2_trim9.brep] s OFFSETSHAPE 15 {} $calcul $type -checkprops result -v 0 +checkprops result -s 0 -v 0 checknbshapes result -shell 1