/**
   * set coords to origin O and vector (I-O). If I (or O) is infinite, I is used as direction
   * vector.
   *
   * @param O origin point
   * @param I unit point
   */
  public void setCoord(GeoPointND O, GeoPointND I) {

    startPoint = O;
    endPoint = I;

    if (I.isInfinite())
      if (O.isInfinite()) setUndefined(); // TODO infinite line
      else setCoord(O.getCoordsInD(3), I.getCoordsInD(3));
    else if (O.isInfinite()) setCoord(I.getCoordsInD(3), O.getCoordsInD(3));
    else setCoord(O.getCoordsInD(3), I.getCoordsInD(3).sub(O.getCoordsInD(3)));
  }
  public void pointChanged(GeoPointND P) {

    boolean done = false;

    // project P on line
    double t = 0;
    if (((GeoElement) P).isGeoElement3D()) {
      if (((GeoPoint3D) P).getWillingCoords() != null) {
        if (((GeoPoint3D) P).getWillingDirection() != null) {
          // project willing location using willing direction
          // GgbVector[] project = coordsys.getProjection(P.getWillingCoords(),
          // P.getWillingDirection());

          GgbVector[] project =
              ((GeoPoint3D) P)
                  .getWillingCoords()
                  .projectOnLineWithDirection(
                      coordsys.getOrigin(),
                      coordsys.getVx(),
                      ((GeoPoint3D) P).getWillingDirection());

          t = project[1].get(1);
          done = true;
        } else {
          // project current point coordinates
          // Application.debug("ici\n getWillingCoords=\n"+P.getWillingCoords()+"\n
          // matrix=\n"+getMatrix().toString());
          GgbVector preDirection =
              ((GeoPoint3D) P)
                  .getWillingCoords()
                  .sub(coordsys.getOrigin())
                  .crossProduct(coordsys.getVx());
          if (preDirection.equalsForKernel(0, Kernel.STANDARD_PRECISION))
            preDirection = coordsys.getVy();

          GgbVector[] project =
              ((GeoPoint3D) P)
                  .getWillingCoords()
                  .projectOnLineWithDirection(
                      coordsys.getOrigin(),
                      coordsys.getVx(),
                      preDirection.crossProduct(coordsys.getVx()));

          t = project[1].get(1);
          done = true;
        }
      }
    }

    if (!done) {
      // project current point coordinates
      // Application.debug("project current point coordinates");
      GgbVector preDirection =
          P.getCoordsInD(3).sub(coordsys.getOrigin()).crossProduct(coordsys.getVx());
      if (preDirection.equalsForKernel(0, Kernel.STANDARD_PRECISION))
        preDirection = coordsys.getVy();

      GgbVector[] project =
          P.getCoordsInD(3)
              .projectOnLineWithDirection(
                  coordsys.getOrigin(),
                  coordsys.getVx(),
                  preDirection.crossProduct(coordsys.getVx()));

      t = project[1].get(1);
    }

    if (t < getMinParameter()) t = getMinParameter();
    else if (t > getMaxParameter()) t = getMaxParameter();

    // set path parameter
    PathParameter pp = P.getPathParameter();

    pp.setT(t);

    // udpate point using pathChanged
    pathChanged(P);
  }