Repository: DGtal-team/DGtal (language: python)

Issue:
testStabbingCircleComputer failing
Cf https://github.com/DGtal-team/DGtal/actions/runs/3836135851/jobs/6529980104 
On my computer, there is no problem but GithubBots have issues with this test.

@troussil could you please have a look ?



Discussion / hints:
tested with Ubuntu 22.04.1 LTS : 
- works fine in Debug
- fails in Release mode
I disable the test (see  #1679 ) until we find the bug (it's in my TODO list) 
Here is the result of my investigation : it's a numerical issue. Indeed all tests pass with int64_t or BigInteger as a coordinate type and whatever the mode is (Debug or Release). I'm waiting PR #1681 to change the test because it is better to not default-construct KhalimskySpace. 
👌 #1681 has been merged.

Fix patch:
diff --git a/ChangeLog.md b/ChangeLog.md
index 428dd49133..bff47cd59f 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -29,6 +29,10 @@
   - Fix KhalimskySpaceND to get it work with BigInteger (Tristan Roussillon,
     [#1681](https://github.com/DGtal-team/DGtal/pull/1681)
 
+- *Geometry package*
+  - Fix Issue #1676 in testStabbingCircleComputer (Tristan Roussillon,
+    [#1688](https://github.com/DGtal-team/DGtal/pull/1688)
+
 - *IO*
   - Fix of the `getHSV` method in the `Color` class. (David Coeurjolly,
     [#1674](https://github.com/DGtal-team/DGtal/pull/1674))


Test patch:
diff --git a/tests/geometry/curves/testStabbingCircleComputer.cpp b/tests/geometry/curves/testStabbingCircleComputer.cpp
index c23ec327da..e8184b4def 100644
--- a/tests/geometry/curves/testStabbingCircleComputer.cpp
+++ b/tests/geometry/curves/testStabbingCircleComputer.cpp
@@ -70,18 +70,14 @@ template<typename TP, typename TI>
 struct MyBallPredicate
 {
   typedef TP Point;
-  typedef TI Integer;
-  MyBallPredicate(const TP &c, const TI r) {myCenter=c; myRad=r;};
-  bool operator()(const Point &p) const { return (p-myCenter).dot(p-myCenter) < myRad*myRad; };
-  Point myCenter;
+  typedef TI Integer; 
+  MyBallPredicate(const Integer& aR) : myRad(aR) {};
+  bool operator()(const Point &aP) const { return aP.dot(aP) <= myRad*myRad; };
   Integer myRad;
 };
 
-
-
 template<typename TKSpace, typename Integer>
-GridCurve<TKSpace>
-ballGenerator(Integer aCx, Integer aCy, Integer aR, bool aFlagIsCW)
+void ballGenerator(const TKSpace& aKSpace, GridCurve<TKSpace>& aGC, const Integer& aR, const bool& aFlagIsCW)
 {
 
   // Types
@@ -93,39 +89,33 @@ ballGenerator(Integer aCx, Integer aCy, Integer aR, bool aFlagIsCW)
   typedef typename Space::Point Point;
   typedef typename Space::RealPoint RealPoint;
   typedef HyperRectDomain<Space> Domain;
-
-  Point center(aCx,aCy);
-  MyBallPredicate<Point,Integer> predicate(center,aR);
+  typedef typename Point::Component Component;
+  
+  MyBallPredicate<Point,Integer> predicate(aR);
   try 
-  {
-    KSpace K;
-    bool ok = K.init( center - Point::diagonal(2*aR), center + Point::diagonal(2*aR), true);
-
-    // Extracts shape boundary
-    SurfelAdjacency<KSpace::dimension> SAdj( true );
-    SCell bel = Surfaces<KSpace>::findABel( K, predicate, 10000 );
-    // Getting the consecutive surfels of the 2D boundary
-    std::vector<Point> points, points2;
-    Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, predicate, bel );
-    //counter-clockwise oriented by default
-    GridCurve c; 
-    if (aFlagIsCW)
     {
-      points2.assign( points.rbegin(), points.rend() );
-      c.initFromVector(points2); 
-    } 
-    else 
-    {
-      c.initFromVector(points); 
+      // Extracts shape boundary
+      SurfelAdjacency<KSpace::dimension> SAdj( true );
+      SCell bel = Surfaces<KSpace>::findABel( aKSpace, predicate, 10000 );
+      // Getting the consecutive surfels of the 2D boundary
+      std::vector<Point> points, points2;
+      Surfaces<KSpace>::track2DBoundaryPoints( points,  aKSpace, SAdj, predicate, bel );
+      //counter-clockwise oriented by default
+      if (aFlagIsCW)
+	{
+	  points2.assign( points.rbegin(), points.rend() );
+	  aGC.initFromVector(points2); 
+	} 
+      else 
+	{
+	  aGC.initFromVector(points); 
+	}
     }
-    return c;
-  }
   catch ( InputException& e )
-  {
+    {
       std::cerr << " "
-    << " error in finding a bel." << std::endl;
-      return GridCurve();
-  }
+		<< " error in finding a bel." << std::endl;
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -276,26 +266,25 @@ bool testStabbingCircleComputer(const TCurve& curve)
  */
 bool testRecognition()
 {
-
-  typedef KhalimskySpaceND<2,int> KSpace; 
-  GridCurve<KSpace> c; 
+  typedef KhalimskySpaceND<2,int64_t> KSpace;
+  //Note: int64_t is enough for radii less than 200
+  typedef KSpace::Space Space;  
+  typedef Space::Point Point;
   
   unsigned int nbok = 0;
   unsigned int nb = 0;
 
   trace.beginBlock ( "Recognition" );
   bool flag=true;
-  
-  
-  
-  for (unsigned int i = 0; i < 50 && flag; ++i)
+    
+  for (unsigned int i = 1; i < 200 && flag; ++i)
   {
-    //generate digital circle
-    uint32_t cx = (rand()%100 ) ;
-    uint32_t cy = (rand()%100 ) ;
-    uint32_t radius = (rand()%100 )+100;
-    c = ballGenerator<KSpace>( cx, cy, radius, ((i%2)==1) ); 
-    trace.info() << " #ball #" << i << " c(" << cx << "," << cy << ") r=" << radius << endl; 
+    int radius = i; 
+    KSpace kspace( Point::diagonal(-2*radius), Point::diagonal(2*radius), true ); 
+    GridCurve<KSpace> c(kspace); 
+    ballGenerator<KSpace>( kspace, c, radius, ((i%2)==0) ); 
+    trace.info() << " #ball c(0,0) r=" << radius
+		 << " cw=" << ((i%2)==0) << endl; 
     
     //range
     typedef GridCurve<KSpace>::IncidentPointsRange Range; 
@@ -323,10 +312,11 @@ bool testRecognition()
       flag = ( p1(it->first)&&p2(it->second) ); 
       if (!flag)
       {
-        trace.info() << it->first <<" "<< it->second<<std::endl;
+        trace.info() << s.getSeparatingCircle() << " "
+		     << it->first << " "
+		     << it->second << std::endl;
       }
     }
-    
    
     //conclusion
     nbok += flag ? 1 : 0; 
@@ -434,12 +424,12 @@ int main( int argc, char** argv )
   }
   
   {//basic operations
-    typedef KhalimskySpaceND<2,int> KSpace; 
-
+    typedef KhalimskySpaceND<2,int> KSpace;
+    typedef KSpace::Space::Point Point; 
+    KSpace kspace(Point::diagonal(-10),Point::diagonal(10),true); 
     GridCurve<KSpace> c, rc; 
-    c = ballGenerator<KSpace>(0,0,6,false); 
-    std::vector<PointVector<2,int> > rv; 
-    rc = ballGenerator<KSpace>(0,0,6,true); 
+    ballGenerator(kspace,c,6,false); 
+    ballGenerator(kspace,rc,6,true); 
 
     res = testStabbingCircleComputer(c)
   && drawingTestStabbingCircleComputer(c, "CCW")
@@ -447,8 +437,7 @@ int main( int argc, char** argv )
   }
   
   {//recognition
-    //TODO fix the bug in Release mode : 
-    //res = res && testRecognition();
+    res = res && testRecognition();
   }
   
   {//segmentations