0024596: Slow import of IGES data
authorama <ama@opencascade.com>
Thu, 13 Mar 2014 11:07:45 +0000 (15:07 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 13 Mar 2014 11:08:55 +0000 (15:08 +0400)
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
src/ShapeFix/ShapeFix_IntersectionTool.cxx
tests/bugs/heal/bug24596_1 [new file with mode: 0755]
tests/bugs/heal/bug24596_2 [new file with mode: 0755]

index e751e30..c971583 100644 (file)
 #include <IntRes2d_IntersectionSegment.hxx>
 #include <BRepAdaptor_HSurface.hxx>
 
+#include <TopTools_OrientedShapeMapHasher.hxx>
+#include <NCollection_DataMap.hxx>
+
+typedef NCollection_DataMap<TopoDS_Shape, Bnd_Box2d, TopTools_OrientedShapeMapHasher> 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 );
index 6997d4f..7b0edb1 100644 (file)
@@ -42,6 +42,7 @@
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS_Wire.hxx>
 #include <TopTools_SequenceOfShape.hxx>
+#include <NCollection_Sequence.hxx>
 
 //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<ShapeFix_DataMapOfShapeBox2d> aSeqWirEdgeBoxes;
+  NCollection_Sequence<Bnd_Box2d> 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 (executable)
index 0000000..623c5eb
--- /dev/null
@@ -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 (executable)
index 0000000..35e0152
--- /dev/null
@@ -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"
+}