예제 #1
0
 // for AlgoElement
 @Override
 protected void setInputOutput() {
   if (param == null) {
     input = new GeoElement[1];
     input[0] = path.toGeoElement();
   } else {
     input = new GeoElement[2];
     input[0] = path.toGeoElement();
     input[1] = param.toGeoElement();
   }
   setOutputLength(1);
   setOutput(0, P);
   setDependencies(); // done by AlgoElement
 }
예제 #2
0
  // for AlgoElement
  protected void setInputOutput() {

    input = new GeoElement[1];
    input[0] = (GeoElement) path.toGeoElement();

    output = new GeoElement[1];
    output[0] = P;
    setDependencies(); // done by AlgoElement
  }
예제 #3
0
  // for AlgoElement
  @Override
  protected void setInputOutput() {
    // it is inefficient to have Q and P as input
    // let's take all independent parents of Q
    // and the path as input
    TreeSet<GeoElement> inSet = new TreeSet<GeoElement>();
    inSet.add((GeoElement) path.toGeoElement());

    // we need all independent parents of Q PLUS
    // all parents of Q that are points on a path
    Iterator<GeoElement> it = Qin.iterator();
    while (it.hasNext()) {
      GeoElement geo = it.next();
      if (geo.isIndependent() || geo.isPointOnPath()) {
        inSet.add(geo);
      }
    }
    // remove P from input set!
    inSet.remove(movingPoint);

    efficientInput = new GeoElement[inSet.size()];
    it = inSet.iterator();
    int i = 0;
    while (it.hasNext()) {
      efficientInput[i] = (GeoElement) it.next();
      i++;
    }

    // the standardInput array should be used for
    // the dependency graph
    standardInput = new GeoElement[2];
    standardInput[0] = locusPoint;
    standardInput[1] = movingPoint;

    setOutputLength(1);
    setOutput(0, locus);

    // handle dependencies
    setEfficientDependencies(standardInput, efficientInput);
  }
예제 #4
0
  // compute locus line
  @Override
  public final void compute() {
    if (!movingPoint.isDefined() || macroCons == null || !path.toGeoElement().isDefined()) {
      locus.setUndefined();
      return;
    }

    locus.clearPoints();
    clearCache();
    pointCount = 0;
    useCache = 0;
    countUpdates = 0;
    lastX = Double.MAX_VALUE;
    lastY = Double.MAX_VALUE;
    maxTimeExceeded = false;
    foundDefined = false;
    boolean prevQcopyDefined = false;
    int max_runs;

    // continuous kernel?
    continuous = kernel.isContinuous();
    macroKernel.setContinuous(continuous);

    // update macro construction with current values of global vars
    resetMacroConstruction();
    macroCons.updateConstruction();

    // use current position of movingPoint to start Pcopy
    pathMover.init(Pcopy);

    if (continuous) {
      // continous constructions may need several parameter run throughs
      // to draw all parts of the locus
      max_runs = GeoLocus.MAX_PATH_RUNS;
    } else {
      max_runs = 1;
    }

    // update Pcopy to compute Qcopy
    pcopyUpdateCascade();
    prevQcopyDefined = Qcopy.isDefined() && !Qcopy.isInfinite();

    // move Pcopy along the path
    // do this until Qcopy comes back to its start position
    // for continuous constructions
    // this may require several runs of Pcopy along the whole path

    int runs = 1;
    int MAX_LOOPS = 2 * PathMover.MAX_POINTS;
    int whileLoops = 0;

    do {
      boolean finishedRun = false;
      while (!finishedRun
          && !maxTimeExceeded
          && pointCount <= PathMover.MAX_POINTS
          && whileLoops <= MAX_LOOPS) {
        whileLoops++;

        // lineTo may be false due to a parameter jump
        // i.e. param in [0,1] gets bigger than 1 and thus jumps to 0
        boolean parameterJump = !pathMover.getNext(Pcopy);
        boolean stepChanged = false;

        // update construction
        pcopyUpdateCascade();

        // Qcopy DEFINED
        if (Qcopy.isDefined() && !Qcopy.isInfinite()) {
          // STANDARD CASE: no parameter jump
          if (!parameterJump) {
            // make steps smaller until distance ok to connect with last point
            while (Qcopy.isDefined()
                && !Qcopy.isInfinite()
                && !distanceOK(Qcopy)
                && !maxTimeExceeded) {
              // go back and try smaller step
              boolean smallerStep = pathMover.smallerStep();
              if (!smallerStep) break;

              stepChanged = true;
              pathMover.stepBack();
              pathMover.getNext(Pcopy);

              // update construction
              pcopyUpdateCascade();
            }

            if (Qcopy.isDefined() && !Qcopy.isInfinite()) {
              // draw point
              insertPoint(Qcopy.inhomX, Qcopy.inhomY, distanceSmall(Qcopy));
              prevQcopyDefined = true;
            }
          }

          // PARAMETER jump: !lineTo
          else {
            // draw point
            insertPoint(Qcopy.inhomX, Qcopy.inhomY, distanceSmall(Qcopy));
            prevQcopyDefined = true;
          }
        }

        // Qcopy NOT DEFINED
        else {
          // check if we moved from defined to undefined case:
          // step back and try with smaller step
          if (prevQcopyDefined && !parameterJump) {
            pathMover.stepBack();
            // set smallest step
            if (!pathMover.smallerStep()) {
              prevQcopyDefined = false;
            } else stepChanged = true;
          }

          // add better undefined case support for continuous curves
          // maybe change orientation of path mover
        }

        // if we didn't decrease the step width increase it
        if (!stepChanged) {
          pathMover.biggerStep();
        }

        // end of run: the next step would pass the start position
        if (!pathMover.hasNext()) {
          if (distanceSmall(QstartPos)) {
            // draw line back to first point when it's close enough
            insertPoint(QstartPos.inhomX, QstartPos.inhomY, true);
            finishedRun = true;
          } else {
            // decrease step until another step is possible
            while (!pathMover.hasNext() && pathMover.smallerStep()) ;

            // no smaller step possible: run finished
            if (!pathMover.hasNext()) finishedRun = true;
          }
        }
      }

      // calculating the steps took too long, so we stopped somewhere
      if (maxTimeExceeded) {
        System.err.println("AlgoLocus: max time exceeded");
        return;
      } else {
        // make sure that Pcopy is back at startPos now
        // look at Qcopy at startPos
        Pcopy.set((GeoElement) PstartPos);
        pcopyUpdateCascade();
        if (Qcopy.inhomX != lastX || Qcopy.inhomY != lastY)
          insertPoint(Qcopy.inhomX, Qcopy.inhomY, distanceSmall(Qcopy));

        //	    		 Application.debug("run: " + runs);
        //	    		 Application.debug("pointCount: " + pointCount);
        //		       	 Application.debug("  startPos: " + QstartPos);
        //		       	 Application.debug("  Qcopy: " + Qcopy);

        // we are finished with all runs
        // if we got back to the start position of Qcopy
        // AND if the direction of moving along the path
        // is positive like in the beginning
        if (pathMover.hasPositiveOrientation()) {
          kernel.setMinPrecision();
          boolean equal = QstartPos.isEqual(Qcopy);
          kernel.resetPrecision();
          if (equal) break;
        }
      }

      pathMover.resetStartParameter();
      runs++;
    } while (runs < max_runs);

    // set defined/undefined
    locus.setDefined(foundDefined);

    //    	System.out.println("  first point: " + locus.getMyPointList().get(0));
    //    	ArrayList list = locus.getMyPointList();
    //    	for (int i=list.size()-10; i < list.size()-1; i++) {
    //    		System.out.println("      point: " + list.get(i));
    //    	}
    //    	System.out.println("  last  point: " + locus.getMyPointList().get(pointCount-1));

    // Application.debug("LOCUS COMPUTE updateCascades: " + countUpdates + ", cache used: " +
    // useCache);
  }