From 7c8090aa6cd7cddc5b22c74d9f17c70b4bd320cc Mon Sep 17 00:00:00 2001 From: ama Date: Thu, 13 Mar 2014 15:07:45 +0400 Subject: [PATCH] 0024596: Slow import of IGES data Part 1: Speed up of import functionality. Correction in ShapeFix_IntersectionTool::FixIntersectingWires() - preliminary construction of ShapeAnalysis_Surface tool for the whole face; computation of 2d bounding boxes for edges and wires before intersection checking. Part 2: Speed up of check shape. Correction in BRepCheck_Face::IntersectWires() in the same way: preliminary computation of 2d boxes for edges and wires in order to reduce the number of calls of intersection tool for pair of wires. Test cases for issue CR24596 --- src/BRepCheck/BRepCheck_Face.cxx | 82 +++++++++++++++++++--- src/ShapeFix/ShapeFix_IntersectionTool.cxx | 44 +++++++++--- tests/bugs/heal/bug24596_1 | 65 +++++++++++++++++ tests/bugs/heal/bug24596_2 | 65 +++++++++++++++++ 4 files changed, 238 insertions(+), 18 deletions(-) create mode 100755 tests/bugs/heal/bug24596_1 create mode 100755 tests/bugs/heal/bug24596_2 diff --git a/src/BRepCheck/BRepCheck_Face.cxx b/src/BRepCheck/BRepCheck_Face.cxx index e751e30e1e..c971583a1c 100644 --- a/src/BRepCheck/BRepCheck_Face.cxx +++ b/src/BRepCheck/BRepCheck_Face.cxx @@ -63,10 +63,15 @@ #include #include +#include +#include + +typedef NCollection_DataMap DataMapOfShapeBox2d; static Standard_Boolean Intersect(const TopoDS_Wire&, const TopoDS_Wire&, - const TopoDS_Face&); + const TopoDS_Face&, + const DataMapOfShapeBox2d&); static Standard_Boolean IsInside(const TopoDS_Wire& wir, @@ -201,7 +206,36 @@ BRepCheck_Status BRepCheck_Face::IntersectWires(const Standard_Boolean Update) } exp1.Next(); } - + + Geom2dAdaptor_Curve aC; + Standard_Real aFirst, aLast; + DataMapOfShapeBox2d aMapShapeBox2d; + for (exp1.Init (myShape, TopAbs_WIRE); exp1.More(); exp1.Next()) + { + const TopoDS_Wire& aWire = TopoDS::Wire (exp1.Current()); + // create 2d boxes for all edges from wire + Bnd_Box2d aBoxW; + for (exp2.Init (aWire, TopAbs_EDGE); exp2.More(); exp2.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge (exp2.Current()); + aC.Load (BRep_Tool::CurveOnSurface (anEdge, TopoDS::Face (myShape), aFirst, aLast)); + // To avoid exeption in Segment if C1 is BSpline + if (aC.FirstParameter() > aFirst) + { + aFirst = aC.FirstParameter(); + } + if (aC.LastParameter() < aLast) + { + aLast = aC.LastParameter(); + } + Bnd_Box2d aBoxE; + BndLib_Add2dCurve::Add (aC, aFirst, aLast, 0., aBoxE); + aMapShapeBox2d.Bind (anEdge, aBoxE); + aBoxW.Add (aBoxE); + } + aMapShapeBox2d.Bind (aWire, aBoxW); + } + Standard_Integer Nbwire, Index,Indexbis; Nbwire = myMapImb.Extent(); @@ -215,10 +249,24 @@ BRepCheck_Status BRepCheck_Face::IntersectWires(const Standard_Boolean Update) } } TopoDS_Wire wir1 = TopoDS::Wire(exp1.Current()); + // to reduce the number of calls Intersect(wir1,wir2) + Bnd_Box2d aBox1, aBox2; + if (aMapShapeBox2d.IsBound (wir1)) + { + aBox1 = aMapShapeBox2d (wir1); + } exp1.Next(); for (; exp1.More(); exp1.Next()) { const TopoDS_Wire& wir2 = TopoDS::Wire(exp1.Current()); - if (Intersect(wir1,wir2,TopoDS::Face(myShape))) { + if (aMapShapeBox2d.IsBound (wir2)) + { + aBox2 = aMapShapeBox2d (wir2); + } + if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2)) + { + continue; + } + if (Intersect(wir1,wir2,TopoDS::Face(myShape), aMapShapeBox2d)) { myIntres = BRepCheck_IntersectingWires; if (Update) { BRepCheck::Add(myMap(myShape),myIntres); @@ -503,7 +551,8 @@ Standard_Boolean BRepCheck_Face::GeometricControls() const static Standard_Boolean Intersect(const TopoDS_Wire& wir1, const TopoDS_Wire& wir2, - const TopoDS_Face& F) + const TopoDS_Face& F, + const DataMapOfShapeBox2d& theMapEdgeBox) { Standard_Real Inter2dTol = 1.e-10; TopExp_Explorer exp1,exp2; @@ -551,11 +600,15 @@ static Standard_Boolean Intersect(const TopoDS_Wire& wir1, if(C1.FirstParameter() > first1) first1 = C1.FirstParameter(); if(C1.LastParameter() < last1 ) last1 = C1.LastParameter(); - BRep_Tool::UVPoints(edg1,F,pfirst1,plast1); - myDomain1.SetValues( pfirst1, first1, Inter2dTol, plast1, last1, Inter2dTol ); Box1.SetVoid(); - BndLib_Add2dCurve::Add( C1, first1, last1, 0., Box1 ); - + if (theMapEdgeBox.IsBound (edg1)) + { + Box1 = theMapEdgeBox (edg1); + } + if (Box1.IsVoid()) + { + BndLib_Add2dCurve::Add( C1, first1, last1, 0., Box1 ); + } for (exp2.Init(wir2,TopAbs_EDGE); exp2.More(); exp2.Next()) { const TopoDS_Edge& edg2 = TopoDS::Edge(exp2.Current()); @@ -567,10 +620,19 @@ static Standard_Boolean Intersect(const TopoDS_Wire& wir1, if(C2.FirstParameter() > first2) first2 = C2.FirstParameter(); if(C2.LastParameter() < last2 ) last2 = C2.LastParameter(); - Box2.SetVoid(); - BndLib_Add2dCurve::Add( C2, first2, last2, 0., Box2 ); + Box2.SetVoid(); + if (theMapEdgeBox.IsBound (edg2)) + { + Box2 = theMapEdgeBox (edg2); + } + if (Box2.IsVoid()) + { + BndLib_Add2dCurve::Add( C2, first2, last2, 0., Box2 ); + } if (! Box1.IsOut( Box2 )) { + BRep_Tool::UVPoints(edg1,F,pfirst1,plast1); + myDomain1.SetValues( pfirst1, first1, Inter2dTol, plast1, last1, Inter2dTol ); BRep_Tool::UVPoints(edg2,F,pfirst2,plast2); myDomain2.SetValues( pfirst2, first2, Inter2dTol, plast2, last2, Inter2dTol ); Inter.Perform( C1, myDomain1, C2, myDomain2, Inter2dTol, Inter2dTol ); diff --git a/src/ShapeFix/ShapeFix_IntersectionTool.cxx b/src/ShapeFix/ShapeFix_IntersectionTool.cxx index 6997d4fec1..7b0edb179d 100644 --- a/src/ShapeFix/ShapeFix_IntersectionTool.cxx +++ b/src/ShapeFix/ShapeFix_IntersectionTool.cxx @@ -42,6 +42,7 @@ #include #include #include +#include //gka 06.09.04 BUG 6555 shape is modified always independently either intersection was fixed or not //======================================================================= @@ -684,11 +685,12 @@ Standard_Boolean ShapeFix_IntersectionTool::UnionVertexes(const Handle(ShapeExte //function : CreateBoxes2d //purpose : auxilary //======================================================================= -static Standard_Boolean CreateBoxes2d(const Handle(ShapeExtend_WireData)& sewd, +static Bnd_Box2d CreateBoxes2d(const Handle(ShapeExtend_WireData)& sewd, const TopoDS_Face& face, ShapeFix_DataMapOfShapeBox2d& boxes) { // create box2d for edges from wire + Bnd_Box2d aTotalBox; TopLoc_Location L; const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L); Handle(Geom2d_Curve) c2d; @@ -710,9 +712,10 @@ static Standard_Boolean CreateBoxes2d(const Handle(ShapeExtend_WireData)& sewd, gac.Load(c2d,cf,cl); BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box); boxes.Bind(E,box); + aTotalBox.Add (box); } } - return Standard_True; + return aTotalBox; } @@ -832,7 +835,7 @@ Standard_Boolean ShapeFix_IntersectionTool::FixSelfIntersectWire // step 2 : intersection of non-adjacent edges ShapeFix_DataMapOfShapeBox2d boxes; - CreateBoxes2d(sewd,face,boxes); + Bnd_Box2d aTotalBox = CreateBoxes2d(sewd,face,boxes); Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face)); NbSplit=0; @@ -1469,19 +1472,36 @@ Standard_Boolean ShapeFix_IntersectionTool::FixIntersectingWires } Standard_Boolean isDone = Standard_False; //gka 06.09.04 ShapeAnalysis_Edge sae; + Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface (BRep_Tool::Surface (face)); + + // precompute edge boxes for all wires + NCollection_Sequence aSeqWirEdgeBoxes; + NCollection_Sequence aSeqWirBoxes; + for (Standard_Integer n = 1; n <= SeqWir.Length(); n++) + { + const TopoDS_Wire& aWire = TopoDS::Wire (SeqWir.Value (n)); + Handle(ShapeExtend_WireData) aSewd = new ShapeExtend_WireData (aWire); + ShapeFix_DataMapOfShapeBox2d aBoxes; + Bnd_Box2d aTotalBox = CreateBoxes2d (aSewd, face, aBoxes); + aSeqWirEdgeBoxes.Append (aBoxes); + aSeqWirBoxes.Append (aTotalBox); + } for(Standard_Integer n1=1; n1<=SeqWir.Length()-1; n1++) { TopoDS_Wire wire1 = TopoDS::Wire(SeqWir.Value(n1)); Handle(ShapeExtend_WireData) sewd1 = new ShapeExtend_WireData(wire1); + ShapeFix_DataMapOfShapeBox2d& boxes1 = aSeqWirEdgeBoxes.ChangeValue (n1); + Bnd_Box2d aBox1 = aSeqWirBoxes (n1); for(Standard_Integer n2=n1+1; n2<=SeqWir.Length(); n2++) { TopoDS_Wire wire2 = TopoDS::Wire(SeqWir.Value(n2)); Handle(ShapeExtend_WireData) sewd2 = new ShapeExtend_WireData(wire2); + ShapeFix_DataMapOfShapeBox2d& boxes2 = aSeqWirEdgeBoxes.ChangeValue (n2); + Bnd_Box2d aBox2 = aSeqWirBoxes (n2); + if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2)) + { + continue; + } // detect possible intersections: - ShapeFix_DataMapOfShapeBox2d boxes1,boxes2; - CreateBoxes2d(sewd1,face,boxes1); - CreateBoxes2d(sewd2,face,boxes2); - Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face)); - Standard_Integer NbModif=0; Standard_Integer nbReplaced =0;//gka 06.09.04 Standard_Boolean hasModifWire = Standard_False; //gka 06.09.04 @@ -1909,9 +1929,17 @@ Standard_Boolean ShapeFix_IntersectionTool::FixIntersectingWires SeqWir.SetValue(n1,sewd1->Wire()); myContext->Replace( wire1, sewd1->Wire() ); wire1 = sewd1->Wire(); + //recompute boxes for wire1 + boxes1.Clear(); + Bnd_Box2d aNewBox1 = CreateBoxes2d (sewd1, face, boxes1); + aSeqWirBoxes.SetValue (n1, aNewBox1); SeqWir.SetValue(n2,sewd2->Wire()); myContext->Replace( wire2, sewd2->Wire() ); wire2 = sewd2->Wire(); + //recompute boxes for wire2 + boxes2.Clear(); + Bnd_Box2d aNewBox2 = CreateBoxes2d (sewd2, face, boxes2); + aSeqWirBoxes.SetValue (n2, aNewBox2); } } diff --git a/tests/bugs/heal/bug24596_1 b/tests/bugs/heal/bug24596_1 new file mode 100755 index 0000000000..623c5eb038 --- /dev/null +++ b/tests/bugs/heal/bug24596_1 @@ -0,0 +1,65 @@ +puts "============" +puts "OCC24596" +puts "============" +puts "" +############################### +## Slow import of IGES data +############################### + +pload QAcommands + +cpulimit 2000 + +if { [regexp {Debug mode} [dversion]] } { + if { [regexp {Windows} [dversion]] } { + set max_time 900 + set max_time2 500 + } else { + set max_time 1200 + set max_time2 800 + } +} else { + if { [regexp {Windows} [dversion]] } { + set max_time 900 + set max_time2 500 + } else { + set max_time 1200 + set max_time2 800 + } +} + +# 1 - igesread +dchrono h reset +dchrono h start + +igesread [locate_data_file 100B_Nosecone_with_Triangular_FSS.igs] a 43479 + +dchrono h stop +set q [dchrono h show] + +regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z +puts "$z" + +if { $z > ${max_time} } { + puts "Elapsed time of igesread is more than ${max_time} seconds - Faulty" +} else { + puts "Elapsed time of igesread is less than ${max_time} seconds - OK" +} + +# 2 - checkshape +dchrono h2 reset +dchrono h2 start + +checkshape a_1 + +dchrono h2 stop +set q2 [dchrono h2 show] + +regexp {CPU user time: ([-0-9.+eE]+) seconds} $q2 full z2 +puts "$z2" + +if { $z2 > ${max_time2} } { + puts "Elapsed time of checkshape is more than ${max_time2} seconds - Faulty" +} else { + puts "Elapsed time of checkshape is less than ${max_time2} seconds - OK" +} diff --git a/tests/bugs/heal/bug24596_2 b/tests/bugs/heal/bug24596_2 new file mode 100755 index 0000000000..35e0152827 --- /dev/null +++ b/tests/bugs/heal/bug24596_2 @@ -0,0 +1,65 @@ +puts "============" +puts "OCC24596" +puts "============" +puts "" +############################### +## Slow import of IGES data +############################### + +pload QAcommands + +cpulimit 2000 + +if { [regexp {Debug mode} [dversion]] } { + if { [regexp {Windows} [dversion]] } { + set max_time 900 + set max_time2 500 + } else { + set max_time 1200 + set max_time2 800 + } +} else { + if { [regexp {Windows} [dversion]] } { + set max_time 900 + set max_time2 500 + } else { + set max_time 1200 + set max_time2 800 + } +} + +# 1 - igesread +dchrono h reset +dchrono h start + +igesread [locate_data_file 100B_Nosecone_with_Triangular_FSS.igs] b 86884 + +dchrono h stop +set q [dchrono h show] + +regexp {CPU user time: ([-0-9.+eE]+) seconds} $q full z +puts "$z" + +if { $z > ${max_time} } { + puts "Elapsed time is more than ${max_time} seconds - Faulty" +} else { + puts "Elapsed time is less than ${max_time} seconds - OK" +} + +# 2 - checkshape +dchrono h2 reset +dchrono h2 start + +checkshape b_1 + +dchrono h2 stop +set q2 [dchrono h2 show] + +regexp {CPU user time: ([-0-9.+eE]+) seconds} $q2 full z2 +puts "$z2" + +if { $z2 > ${max_time2} } { + puts "Elapsed time of checkshape is more than ${max_time2} seconds - Faulty" +} else { + puts "Elapsed time of checkshape is less than ${max_time2} seconds - OK" +}