/**
   * draws a circle
   *
   * @param center
   * @param v1
   * @param v2
   * @param radius
   */
  public void circle(GgbVector center, GgbVector v1, GgbVector v2, double radius) {

    length = (float) (2 * Math.PI * radius); // TODO use integer to avoid bad dash cycle connection

    int longitude = 60;

    GgbVector vn1;
    GgbVector vn2 = v1.crossProduct(v2);

    float dt = (float) 1 / longitude;
    float da = (float) (2 * Math.PI * dt);
    float u = 0, v = 1;

    setTextureX(0);
    vn1 = (GgbVector) v1.mul(u).add(v2.mul(v));
    down((GgbVector) center.add(vn1.mul(radius)), vn1, vn2);

    for (int i = 1; i <= longitude; i++) {
      u = (float) Math.sin(i * da);
      v = (float) Math.cos(i * da);

      setTextureX(i * dt);
      vn1 = (GgbVector) v1.mul(u).add(v2.mul(v));
      moveTo((GgbVector) center.add(vn1.mul(radius)), vn1, vn2);
    }
  }
  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);
  }