Пример #1
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);
  }