public int getDefaultType(GeoElement geo) {

    switch (geo.getGeoClassType()) {
      case POINT3D:
        if (geo.isIndependent()) {
          return DEFAULT_POINT3D_FREE;
        } else {
          GeoPoint3D p = (GeoPoint3D) geo;
          if (p.hasPath()) return DEFAULT_POINT3D_ON_PATH;
          else if (p.hasRegion()) return DEFAULT_POINT3D_IN_REGION;
          else return DEFAULT_POINT3D_DEPENDENT;
        }

      case ANGLE3D:
        return DEFAULT_ANGLE3D;

      case LINE3D:
        if (((GeoLine3D) geo).isIntersection()) return DEFAULT_LINE3D_INTERSECTION;
        else return DEFAULT_LINE3D;
      case SEGMENT3D:
        if (((GeoSegment3D) geo).isIntersection()) return DEFAULT_SEGMENT3D_INTERSECTION;
        else return DEFAULT_SEGMENT3D;
      case RAY3D:
        if (((GeoRay3D) geo).isIntersection()) return DEFAULT_RAY3D_INTERSECTION;
        else return DEFAULT_RAY3D;
      case AXIS3D:
        return DEFAULT_AXIS3D;
      case VECTOR3D:
        return DEFAULT_VECTOR3D;
      case CONIC3D:
        if (((GeoConic3D) geo).isIntersection()) return DEFAULT_CONIC3D_INTERSECTION;
        else return DEFAULT_CONIC3D;
      case CURVECARTESIAN3D:
        return DEFAULT_CURVECARTESIAN3D;
      case PLANE3D:
        return DEFAULT_PLANE3D;
      case POLYGON3D:
        return DEFAULT_POLYGON3D;
      case POLYHEDRON:
        return DEFAULT_POLYHEDRON;
      case QUADRIC:
      case QUADRIC_PART:
        return DEFAULT_QUADRIC;
      case QUADRIC_LIMITED:
        return DEFAULT_QUADRIC_LIMITED;
      case FUNCTION_NVAR:
        return DEFAULT_FUNCTION_NVAR;
      case SURFACECARTESIAN3D:
        return DEFAULT_SURFACECARTESIAN3D;

      default:
        return super.getDefaultType(geo);
    }
  }
  /**
   * processes valid expression.
   *
   * @param ve
   * @param redefineIndependent == true: independent objects are redefined too
   * @throws MyError
   * @throws Exception
   * @return
   */
  public GeoElement[] processValidExpression(ValidExpression ve, boolean redefineIndependent)
      throws MyError, Exception {

    // check for existing labels
    String[] labels = ve.getLabels();
    GeoElement replaceable = null;
    if (labels != null && labels.length > 0) {
      boolean firstTime = true;
      for (int i = 0; i < labels.length; i++) {
        GeoElement geo = kernel.lookupLabel(labels[i]);
        if (geo != null) {
          if (geo.isFixed()) {
            String[] strs = {
              "IllegalAssignment", "AssignmentToFixed", ":\n", geo.getLongDescription()
            };
            throw new MyError(app, strs);
          } else {
            // replace (overwrite or redefine) geo
            if (firstTime) { // only one geo can be replaced
              replaceable = geo;
              firstTime = false;
            }
          }
        }
      }
    }

    GeoElement[] ret;
    boolean oldMacroMode = cons.isSuppressLabelsActive();
    if (replaceable != null) cons.setSuppressLabelCreation(true);

    // we have to make sure that the macro mode is
    // set back at the end
    try {
      ret = doProcessValidExpression(ve);

      if (ret == null) { // eg (1,2,3) running in 2D
        Application.debug("Unhandled ValidExpression : " + ve);
        throw new MyError(app, app.getError("InvalidInput") + ":\n" + ve);
      }
    } finally {
      cons.setSuppressLabelCreation(oldMacroMode);
    }

    //	try to replace replaceable geo by ret[0]
    if (replaceable != null && ret != null && ret.length > 0) {
      // a changeable replaceable is not redefined:
      // it gets the value of ret[0]
      // (note: texts are always redefined)
      if (!redefineIndependent && replaceable.isChangeable() && !(replaceable.isGeoText())) {
        try {
          replaceable.set(ret[0]);
          replaceable.updateRepaint();
          ret[0] = replaceable;
        } catch (Exception e) {
          String errStr =
              app.getError("IllegalAssignment")
                  + "\n"
                  + replaceable.getLongDescription()
                  + "     =     "
                  + ret[0].getLongDescription();
          throw new MyError(app, errStr);
        }
      }
      // redefine
      else {
        try {
          // SPECIAL CASE: set value
          // new and old object are both independent and have same type:
          // simply assign value and don't redefine
          if (replaceable.isIndependent()
              && ret[0].isIndependent()
              && replaceable.getGeoClassType() == ret[0].getGeoClassType()) {
            replaceable.set(ret[0]);
            replaceable.updateRepaint();
            ret[0] = replaceable;
          }

          // STANDARD CASE: REDFINED
          else {
            GeoElement newGeo = ret[0];
            cons.replace(replaceable, newGeo);

            // now all objects have changed
            // get the new object with same label as our result
            String newLabel = newGeo.isLabelSet() ? newGeo.getLabel() : replaceable.getLabel();
            ret[0] = kernel.lookupLabel(newLabel, false);
          }
        } catch (CircularDefinitionException e) {
          throw e;
        } catch (Exception e) {
          e.printStackTrace();
          throw new MyError(app, "ReplaceFailed");
        } catch (MyError e) {
          e.printStackTrace();
          throw new MyError(app, "ReplaceFailed");
        }
      }
    }

    return ret;
  }