// Distance d'un point � ce polyhedron (r�cursif)
  public double distance(Point_3 p) {
    // Cas terminal : zero ou une seule face
    if (nFacets == 0) {
      return 1e16;
    } else if (nFacets == 1) {
      Face<Point_3> f = facets.get(0);
      return Utils.distance(p, f);
    }
    // if (distanceMin == null) System.out.println("FAILLL") ;
    distanceMin =
        Math.min(
            distanceMin,
            p.distanceFrom(facets.get(0).getEdge().getVertex().getPoint()).doubleValue());
    // A chaque instance, on sait que la distance � poly est <=

    // On regarde dans les sous-arbres
    double distanceToLeft =
        Math.max(p.getCartesian(cutDim).doubleValue() - left.boundingBox[cutDim][1], 0);
    double distanceToRight =
        Math.max(right.boundingBox[cutDim][0] - p.getCartesian(cutDim).doubleValue(), 0);
    // System.out.println("DistanceToLeft = " + distanceToLeft + " --- DistanceToRight = " +
    // distanceToRight) ;

    double currentDistanceLeft = 1e18;
    double currentDistanceRight = 1e15;
    if (distanceToLeft <= distanceMin) currentDistanceLeft = left.distance(p);
    if (distanceToRight <= distanceMin) currentDistanceRight = right.distance(p);
    return Math.min(currentDistanceLeft, currentDistanceRight);
  }
  // Construction de l'arbre
  public void computeTree() {
    // On recherche la valeur de coupure
    int n = 0;
    double cutValue = 0;
    Iterator<Face<Point_3>> it = facets.iterator();
    while (it.hasNext()) {
      Face<Point_3> f = it.next();
      Halfedge<Point_3> he = f.getEdge(), premier = he;
      boolean debut = true;
      while (debut || premier != he) {
        debut = false;
        cutValue += he.getVertex().getPoint().getCartesian(cutDim).doubleValue();
        n++;
        he = he.getNext();
      }
    }
    cutValue = cutValue / n;
    this.cutValue = cutValue;

    // Separation
    ArrayList<Face<Point_3>> facesLeft = new ArrayList<Face<Point_3>>();
    ArrayList<Face<Point_3>> facesRight = new ArrayList<Face<Point_3>>();
    // double[][] boxLeft = new double[3][2] ; // 3 : coordonn�es, 2 : min et max
    double limitLeft = -1e7;
    double limitRight = 1e7;
    // double[][] boxRight = new double[3][2] ; // 3 : coordonn�es, 2 : min et max
    it = facets.iterator();
    boolean lastLeft = (Math.random() < 0.5); // Pour la r�partition des faces � cheval
    while (it.hasNext()) {
      Face<Point_3> f = it.next();
      boolean gauche = false, droite = false;
      // Limite haute et basse de la face selon cutDim
      double faceMin = 1e7, faceMax = -1e7;

      // On regarde la position de la face (� gauche, � droite, � cheval)
      Halfedge<Point_3> he = f.getEdge(), premier = he;
      do {
        double coord = he.getVertex().getPoint().getCartesian(cutDim).doubleValue();
        if (coord <= cutValue) gauche = true;
        else droite = true;
        if (coord < faceMin) faceMin = coord;
        if (coord > faceMax) faceMax = coord;
        he = he.getNext();
      } while (premier != he);

      // On ajoute � l'arbre de gauche ou de droite (si � cheval, une fois l'un une fois l'autre)
      if (gauche && (!droite || !lastLeft)) {
        lastLeft = true;
        facesLeft.add(f);
        if (faceMax > limitLeft) limitLeft = faceMax;
      } else {
        lastLeft = false;
        facesRight.add(f);
        if (faceMin < limitRight) limitRight = faceMin;
      }
      // tour++ ;
    }

    // Construction des arbres
    // System.out.println("Sous-Tailles : " + facesLeft.size() + " : " + facesRight.size()) ;
    left = new PolyhedronBoxTree(poly, facesLeft, (cutDim + 1) % 3);
    right = new PolyhedronBoxTree(poly, facesRight, (cutDim + 1) % 3);
    // if (this.distanceMin == null) System.out.println("Fail !!!") ;
    left.distanceMin = this.distanceMin;
    right.distanceMin = this.distanceMin;
    if (left.nFacets > 1) left.computeTree();
    if (right.nFacets > 1) right.computeTree();

    // Bounding Boxes
    for (int i = 0; i < 3; i++) {
      left.boundingBox[i][0] = boundingBox[i][0];
      right.boundingBox[i][1] = boundingBox[i][0];

      if (i == cutDim) {
        left.boundingBox[i][1] = limitLeft;
        right.boundingBox[i][0] = limitRight;
      } else {
        left.boundingBox[i][0] = boundingBox[i][0];
        right.boundingBox[i][0] = boundingBox[i][0];
      }
    }
  }