// function Find-First-k-Candidate-Neighbours-Forward&Backward(D,
 //	    var point p, var point b, var point f,
 //	    var backwardSearch, var forwardSearch, var k-Neighborhood,
 //          k, var i)
 public void Find_First_k_Candidate_Neighbours_Forward_Backward(
     ArrayList<ISpatialObject> D,
     Point p,
     Point[] b,
     Point[] f,
     Integer backwardSearch,
     Integer forwardSearch, /*TriangleNeighborhood tn,*/
     int k,
     int[] i) {
   // while backwardSearch and forwardSearch and (i < k) do
   while (backwardSearch == 1 && forwardSearch == 1 && (i[0] < k)) {
     //    i = i + 1;
     i[0] = i[0] + 1;
     //    if p.dist - b.dist < f.dist - p.dist then
     if (p.dist - b[0].dist < f[0].dist - p.dist) {
       //        dist2 = Distance2(b, p);
       double dist = Distance.Distance(b[0], p);
       //        insert element e = (position of b, dist2)
       //            in k-Neighborhood holding it sorted wrt. e.dist2;
       // insertSorted(k_Neighborhood, dist, b[0]);
       tn.insertSorted(dist, b[0]);
       //        backwardSearch = PrecedingPoint(D, b)
       backwardSearch = PrecedingPoint(D, b);
       //    else
     } else {
       //        dist2 = Distance2(f, p);
       double dist = Distance.Distance(f[0], p);
       //        insert element e = (position of f, dist2) in
       //            k-Neighborhood holding it sorted wrt. e.dist2;
       // insertSorted(tn, dist, f[0]);
       tn.insertSorted(dist, f[0]);
       //        forwardSearch = FollowingPoint(D, f);
       forwardSearch = FollowingPoint(D, f);
       //    endif
     }
     // endwhile
   }
 }
  public void createSortedTableD(Collection<ISpatialObject> input, Point refPoint) {
    D = new ArrayList<ISpatialObject>();
    for (ISpatialObject o : input) {

      Point point = (Point) o;

      double distance = Distance.Distance(refPoint, point);

      point.dist = distance;

      if (D.size() == 0) {
        D.add(point);
      } else {
        for (int i = 0; i < D.size(); i++) {
          Point tip = (Point) D.get(i);

          if (distance < tip.dist) {
            // insert before the current point
            D.add(i, point);
            if (i > 0) {
              Point pr = (Point) D.get(i - 1);
            }
            break;
          } else if (i == D.size() - 1) {
            // insert at the end
            D.add(point);
            break;
          } else {
            // compare to the next point
            ;
          }
        }
      }
    }
    for (int i = 0; i < D.size(); i++) {
      Point p = (Point) D.get(i);
      //                prnl(p + " " + p.dist);
      p.pos = i;
    }

    //            prn("x");

  }
 // function Find-First-k-Candidate-Neighbours-Backward(D,var point p,
 //          var point b, var backwardSearch, var k-Neighborhood, k, var i)
 public void Find_First_k_Candidate_Neighbours_Forward(
     ArrayList<ISpatialObject> D,
     Point p,
     Point[] f,
     Integer forwardSearch, /*TriangleNeighborhood tn,*/
     int[] i) {
   //      while forwardSearch and (i < k) do // TODO i is not initialized
   while (forwardSearch == 1 && i[0] < k) {
     //          i = i + 1;
     i[0] = i[0] + 1;
     //          dist2 = Distance2(b, p);
     double dist = Distance.Distance(f[0], p);
     //          insert element e = (position of b, dist2) in k-Neighborhood
     //              holding it sorted wrt. e.dist2;
     // insertSorted(k_Neighborhood, dist, f[0]);
     tn.insertSorted(dist, f[0]);
     //          backwardSearch = PrecedingPoint(D, b)
     forwardSearch = FollowingPoint(D, f);
     //      endwhile
   }
 }
  // function Verify-k-Candidate-Neighbours-Forward(D, var point p,
  //  var point f, var forwardSearch, var k-Neighborhood, var Eps2)
  public void Verify_k_Candidate_Neighbours_Forward(
      ArrayList<ISpatialObject> D,
      Point p,
      Point[] f,
      Integer forwardSearch,
      /*TriangleNeighborhood tn,*/ double[] Eps) {
    // Eps = (Eps2)1/2;
    //   double Eps = Math.sqrt(Eps2[0]);
    // while forwardSearch and (f.dist – p.dist <= Eps) do
    //
    // prnl("----------------------------------------------------------------------------------------");
    //            prnl("Verify_k_Candidate_Neighbours_Forward");
    //
    // prnl("----------------------------------------------------------------------------------------");
    //            prnl("\tforwardSearch=" + forwardSearch);
    //            prnl("\tb=" + f[0]);
    //            prnl("\tEps=" + Eps[0]);
    //            int xx =0 ;
    while (forwardSearch == 1 && (f[0].dist - p.dist <= Eps[0])) {
      //                prnl("\t------ forward " + xx++ + "---------");
      //                double x = f[0].dist - p.dist;
      //                prnl("\t\tf.dist - p.dist = " + f[0].dist + "-" + p.dist + "=" + x );
      //                prnl("\t\tEps=" + Eps[0]);
      //                prnl("\t\tf.dist - p.dist <= Eps " + (x < Eps[0]?"TRUE":"FALSE"));
      //    dist2 = Distance2(f, p);
      //        prn("Forward: " + Eps[0] + " " + (f[0].dist - p.dist));

      double dist = Distance.Distance(f[0], p);
      //                prnl("\t\tdist2 = Distance2(b,p) = " + dist);
      //    if dist2 < Eps2 then
      // int i = getI(k_Neighborhood, Eps[0]);
      int i = tn.getI(Eps[0]);
      //                prnl("\t\ti=" + i);

      if (dist < Eps[0]) {
        //                    prnl("\t\tdist2 < Eps2 " + "TRUE");
        //        i = |{e  k-Neighborhood| e.dist2 = Eps2}};
        //        if |k-Neighborhood| - i >= k - 1 then
        //                    prnl("\t\tk-Neighborhood|-i > k-1 = " + tn.size() + "-" + i + " >= " +
        // k + "-1 " + ((tn.size()-i>=k-1)?"TRUE":"FALSE"));
        if (tn.size() - i >= k - 1) {
          // remove(k_Neighborhood, Eps[0]);
          tn.remove(Eps[0]);
          // insertSorted(k_Neighborhood, dist, f[0]);
          tn.insertSorted(dist, f[0]);
          // Eps[0] = dist;
          // getEps(k_Neighborhood, Eps);
          tn.getEps(Eps);
          //                        prnl("\t\tEps=" + Eps[0]);
        } else {
          //        Eps2 = dist2;
          //                 getEps(k_Neighborhood, Eps);
          //        Eps = (Eps2)1/2;
          //      Eps = Math.sqrt(Eps[0]);

          //        endif

          //        insert element e = (position of f, dist2) in
          //            k-Neighborhood holding it sorted wrt. e.dist2;
          // insertSorted(k_Neighborhood, dist, f[0]);
          // Eps[0] = dist;
          tn.insertSorted(dist, f[0]);
        }
        //    else if dist2 = Eps2
      } else if (dist == Eps[0]) {
        //        insert element e = (position of f, dist2) in
        //            k-Neighborhood holding it sorted wrt. e.dist2
        // insertSorted(k_Neighborhood, dist, f[0]);
        //                    prnl("\t\tdist2 == Eps2 " + "TRUE");
        tn.insertSorted(dist, f[0]);
        //    endif
      }
      //    forwardSearch = FollowingPoint(D, f)
      forwardSearch = FollowingPoint(D, f);
      //                prnl("\t\tforwardSearch=" + forwardSearch);
      //                prnl("\t\tf = " + f[0]);
      //                double x2 = f[0].dist - p.dist;
      //                prnl("\t\tf.dist - p.dist = " + f[0].dist + "-" + p.dist + "=" + x2 );
      //                prnl("\t\t" + ((forwardSearch == 1 && x2 <= Eps[0])?"next
      // iteration":"stop"));
      // endwhile
    }
  }
  // function Verify-k-Candidate-Neighbours-Backward(D, var point p,
  //	  var point b, var backwardSearch, var k-Neighborhood, k, var Eps2k)
  public void Verify_k_Candidate_Neighbours_Backward(
      ArrayList<ISpatialObject> D,
      Point p,
      Point[] b,
      Integer backwardSearch, /*TriangleNeighborhood tn,*/
      int k,
      double[] Eps) {
    //	// Eps = (Eps2)1/2;
    //        //    double Eps = Math.sqrt(Eps[0]);
    //	// while backwardSearch and (p.dist – b.dist <= Eps) do
    //
    // prnl("----------------------------------------------------------------------------------------");
    //            prnl("Verify_k_Candidate_Neighbours_Backward");
    //
    // prnl("----------------------------------------------------------------------------------------");
    //            prnl("\tbackwardSearch=" + backwardSearch);
    //            prnl("\tb=" + b[0]);
    //            prnl("\tEps=" + Eps[0]);
    // prn("p.dist-b.dist <= Eps " + (x < Eps[0]?"TRUE":"FALSE"));
    //            int xx = 1;
    while (backwardSearch == 1 && (p.dist - b[0].dist <= Eps[0])) {
      //                prnl("\t------ backward " + xx++ + "---------");
      //                double x = p.dist-b[0].dist;
      //                prnl("\t\tp.dist - b.dist = " + p.dist + "-" + b[0].dist + "=" + x );
      //                prnl("\t\tEps=" + Eps[0]);
      //                prnl("\t\tp.dist-b.dist <= Eps " + (x < Eps[0]?"TRUE":"FALSE"));
      //                double[] xxx = p.getCoordinates();
      //                if (xxx[0] == 40.0 && xxx[1] == 165.0) {
      //                    int a = 100;
      //                }
      //                prn("Backward: " + Eps[0] + " " + (p.dist - b[0].dist));
      //    dist2 = Distance2(b, p);
      double dist = Distance.Distance(b[0], p);
      //                prnl("\t\tdist2 = Distance2(b,p) = " + dist);
      //    if dist2 < Eps2 then

      if (dist < Eps[0]) {
        //                    prnl("\t\tdist2 < Eps2 " + "TRUE");
        //        i = |{e in k-Neighborhood| e.dist2 = Eps2}};
        // int i = getI(k_Neighborhood, Eps[0]);
        int i = tn.getI(Eps[0]);
        //                    prnl("\t\ti=" + i);
        //        if |k-Neighborhood| - i >=  k - 1 then
        //                    prnl("\t\tk-Neighborhood|-i > k-1 = " + tn.size() + "-" + i + " >= " +
        // k + "-1 " + ((tn.size()-i>=k-1)?"TRUE":"FALSE"));
        if (tn.size() - i >= k - 1) {
          //            delete each element e with e.dist2 = Eps2
          //                from k-Neighborhood;
          // remove(k_Neighborhood, Eps[0]);
          tn.remove(Eps[0]);
          //              Eps2 = max({e.dist^2| e in k-Neighborhood});
          // getEps(k_Neighborhood, Eps);
          //              Eps = (Eps2)1/2;
          // Eps = Math.sqrt(Eps[0]);
          //	        endif

          // insertSorted(k_Neighborhood, dist, b[0]);
          tn.insertSorted(dist, b[0]);

          // Eps[0] = dist;
          // getEps(k_Neighborhood, Eps);
          tn.getEps(Eps);
          //                        prnl("\t\tEps=" + Eps[0]);
        } else {
          //        insert element e = (position of b, dist2) in
          //            k-Neighborhood holding it sorted wrt. e.dist2;
          // insertSorted(k_Neighborhood, dist, b[0]);
          tn.insertSorted(dist, b[0]);
        }
        //	    else if dist2 = Eps2
      } else if (dist == Eps[0]) {
        //                    prnl("\t\tdist2 == Eps2 " + "TRUE");
        //	    insert element e = (position of b, dist2) in
        //	        k-Neighborhood holding it sorted wrt. e.dist2
        // insertSorted(k_Neighborhood, dist, b[0]);
        tn.insertSorted(dist, b[0]);
        //	endif
      }
      //	    backwardSearch = PrecedingPoint(D, b)
      backwardSearch = PrecedingPoint(D, b);
      //                prnl("\t\tbackwardSearch=" + backwardSearch);
      //                prnl("\t\tb = " + b[0]);
      //                double x2 = p.dist - b[0].dist;
      //                prnl("\t\tp.dist - b.dist = " + p.dist + "-" + b[0].dist + "=" + x2 );
      //                prnl("\t\t" + ((backwardSearch == 1 && x2 <= Eps[0])?"next
      // iteration":"stop"));
      //	endwhile
    }
  }