コード例 #1
0
  /** @param args */
  public static void main(String[] args) {

    VoronoiCore core = new VoronoiCore();
    OpenList sites = new OpenList();
    Random rand = new Random(100);
    int amount = 200;

    PolygonSimple rootPolygon = new PolygonSimple();
    int width = 500;
    int height = 500;
    rootPolygon.add(0, 0);
    rootPolygon.add(width, 0);
    rootPolygon.add(width, height);
    rootPolygon.add(0, height);
    for (int i = 0; i < amount; i++) {
      Site site = new Site(rand.nextInt(width), rand.nextInt(width));
      site.setPercentage(1);
      sites.add(site);
    }
    sites.get(0).setPercentage(3);

    core.setDebugMode();
    //		core.setOutputMode();
    core.normalizeSites(sites);
    // ArrayList<Site> sites = TestConvergence.getSites(100, rectangle,
    // true);
    // core.setErrorAreaThreshold(0.00);
    // core.setUseExtrapolation(false);
    // normalizeSites(sites);
    core.setSites(sites);
    core.setClipPolygon(rootPolygon);
    long start = System.currentTimeMillis();

    core.setUseNegativeWeights(true);
    core.setCancelOnAreaErrorThreshold(true);
    core.doIterate(5000);

    long end = System.currentTimeMillis();
    double diff = (end - start) / 1000.0D;
    System.out.println("NeededTime: " + diff);
    // }
  }
コード例 #2
0
  public void iterate() {
    currentMaxNegativeWeight = 0;
    currentEuclidChange = 0;
    currentAreaError = 0;
    currentMaxError = 0;
    // long start=System.currentTimeMillis();

    // move the sites to their center
    completeArea = clipPolygon.getArea();
    drawCurrentState(false);
    double errorArea = 0;

    /** Extrapolation */
    int amount = 0;
    if (isUseExtrapolation() && !preflowFinished) {
      Site[] array = sites.array;
      int size = sites.size;
      for (int z = 0; z < size; z++) {
        Site site = array[z];
        PolygonSimple poly = site.getPolygon();
        double percentage = site.getPercentage();
        double wantedArea = completeArea * percentage;
        double currentArea = poly.getArea();
        double increase = wantedArea / currentArea;
        /** Extrapolation */
        if (percentage >= getPreflowPercentage() && increase >= getPreflowIncrease()) {
          // System.out.println("Percentage:" + percentage
          // + "\t Increase:" + preflowIncrease);
          amount++;
          double radiusIncrease = Math.sqrt(increase);
          double radiusCurrent = Math.sqrt(site.getWeight());
          double deltaRadius = radiusCurrent * (radiusIncrease) - radiusCurrent;

          for (int y = 0; y < size; y++) {
            Site other = array[y];
            if (other != site && other.getPercentage() < getPreflowPercentage()) {
              Point2D vector = new Point2D();
              // Vector2d vector=new Vec
              vector.x = other.getX() - site.getX();
              vector.y = other.getY() - site.getY();

              double length = vector.length();
              double linearDistanceScaledDeltaRadius =
                  deltaRadius * (1 - ((length - radiusCurrent) / maxDelta));
              double scale = linearDistanceScaledDeltaRadius / length;
              // double scale = deltaRadius
              // / length;
              vector.scale(scale);

              other.preflowVector.x += vector.x;
              other.preflowVector.y += vector.y;
            }
          }
        }
      }
    }
    if (amount == 0) {
      preflowFinished = true;
    }

    /** move to centers */
    Site[] array = sites.array;
    int size = sites.size;
    for (int z = 0; z < size; z++) {
      Site point = array[z];
      // point.preflowVector.scale(1.0/(double)amount);

      double error = 0;

      double percentage = point.getPercentage();
      PolygonSimple poly = point.getPolygon();
      if (poly != null) {
        Point2D centroid = poly.getCentroid();
        double centroidX = centroid.getX();
        double centroidY = centroid.getY();
        double dx = centroidX - point.getX();
        double dy = centroidY - point.getY();
        currentEuclidChange += dx * dx + dy * dy;
        double currentArea = poly.getArea();
        double wantedArea = completeArea * point.getPercentage();
        double increase = (wantedArea / currentArea);
        error = Math.abs(wantedArea - currentArea);
        double minDistanceClipped = poly.getMinDistanceToBorder(centroidX, centroidY);
        minDistanceClipped = minDistanceClipped * nearlyOne;
        // scale preflow vector to have minDistanceClipped length
        double rootBorder = clipPolygon.getMinDistanceToBorder(point.getX(), point.getY());
        // if (isUseExtrapolation() && !preflowFinished &&
        // rootBorder>maxDelta/Math.sqrt(sites.size()))) {
        if (isUseExtrapolation() && !preflowFinished) {
          if (point.preflowVector.length() != 0) {
            point.preflowVector.scale(minDistanceClipped / point.preflowVector.length());
            if (point.preflowVector.length() > 5) {
              centroidX += point.preflowVector.x;
              centroidY += point.preflowVector.y;
            }
            point.preflowVector.x = 0;
            point.preflowVector.y = 0;
          }

          /** This could also be used as further speedup, but is not 100% stable */
          // if (point.preflowVector.length()!=0){
          // Point2D centroidNew = poly.getRelativePosition(new
          // Point2D.Double(point.preflowVector.x,
          // point.preflowVector.y));
          // centroidX=centroidNew.getX();
          // centroidY=centroidNew.getY();
          // }

        }
        double minDistance = point.nonClippedPolyon.getMinDistanceToBorder(centroidX, centroidY);

        /** radius has to be at most the minimal distance to the border segments of the polygon */
        double weight = Math.min(point.getWeight(), minDistance * minDistance);
        if (weight < 0.00000001) {
          weight = 0.00000001;
        }

        // set new position to the centroid
        point.setXYW(centroidX, centroidY, weight);
      }

      error = error / (completeArea * 2);

      errorArea += error;
      // System.out.println("ErrorArea:"+error);
    }
    // if (site 0) {
    // errorArea = 1;
    // } else {
    // errorArea = errorArea / (completeArea * 2);
    currentAreaError += errorArea;
    // }
    // drawCurrentState(false);
    // System.out.println("Area Error: "+errorArea);
    voroDiagram();
    // drawCurrentState(false);
    // try to improve the radius of the circle so that the wanted area gets
    // improved
    // int a = 0;
    // if (a == 0)
    // ;

    /** adapt weights */
    /** if activated also allow negative weights */
    /** compute the ordinary Voronoi diagram */
    OpenList sitesCopy = null;
    if (guaranteeInvariant) {
      sitesCopy = sites.cloneWithZeroWeights();
      diagram.setSites(sitesCopy);
      diagram.setClipPoly(clipPolygon);
      diagram.computeDiagram();
    }
    for (int z = 0; z < size; z++) {
      Site point = array[z];

      PolygonSimple poly = point.getPolygon();
      double completeArea = clipPolygon.getArea();
      double currentArea = poly.getArea();
      double wantedArea = completeArea * point.getPercentage();

      double currentRadius = Math.sqrt(currentArea / Math.PI);
      double wantedRadius = Math.sqrt(wantedArea / Math.PI);
      double deltaCircle = currentRadius - wantedRadius;

      double increase = wantedArea / currentArea;
      if (getAggressiveMode() == false) {
        increase = Math.sqrt(increase);
      }

      // get the minimal distance to the neighbours. otherwise the
      // neighbours could be dominated

      double minDistance = 0;
      if (guaranteeInvariant) {
        Site pointOrdinary = sitesCopy.array[z];
        minDistance = getMinNeighbourDistance(pointOrdinary);
      } else {
        minDistance = getMinNeighbourDistance(point);
      }
      minDistance = minDistance * nearlyOne;
      // minDistance = Math.max(1, minDistance);
      // change the radius of the circles
      /** we have to take care that the radius doesn't get to big to dominate other sites. */
      double radiusOld = Math.sqrt(point.getWeight());

      double radiusNew = radiusOld * increase;

      double deltaRadius = radiusNew - radiusOld;
      if (radiusNew > minDistance) {
        radiusNew = minDistance;
      }
      double finalWeight = radiusNew * radiusNew;
      if (useNegativeWeights) {
        Point2D center = poly.getCentroid();
        double distanceBorder = poly.getMinDistanceToBorder(center.x, center.y);
        double maxDelta = Math.min(distanceBorder, deltaCircle);
        if (finalWeight < 0.0001) {
          double radiusNew2 = radiusNew - maxDelta;
          if (radiusNew2 < 0) {
            finalWeight = -(radiusNew2 * radiusNew2);
            if (finalWeight < currentMaxNegativeWeight) {
              currentMaxNegativeWeight = finalWeight;
            }
          }
        }
      }

      point.setWeight(finalWeight);
    }

    /** make weights non negative again by adding the smallest negative value */
    if (useNegativeWeights) {

      if (currentMaxNegativeWeight < 0) {
        currentMaxNegativeWeight += (1 - nearlyOne);
        currentMaxNegativeWeight = -currentMaxNegativeWeight;
        for (int z = 0; z < size; z++) {
          Site s = array[z];
          double w = s.getWeight();
          w += currentMaxNegativeWeight;
          s.setWeight(w);
        }
      }
    }
    // drawCurrentState(false);
    voroDiagram();
    drawCurrentState(false);
    // drawCurrentState(false);
    /** compute the maximal error of the area. */
    currentMaxError = 0;
    array = sites.array;
    size = sites.size;
    for (int z = 0; z < size; z++) {
      Site site = array[z];
      PolygonSimple poly = site.getPolygon();
      double percentage = site.getPercentage();

      double wantedArea = completeArea * percentage;
      double currentArea = poly.getArea();
      double singleError = Math.abs(1 - (currentArea / wantedArea));
      if (singleError > currentMaxError) {
        currentMaxError = singleError;
      }
    }
    lastEuclidChange = currentEuclidChange / size;
    lastSumErrorChange = Math.abs(lastAreaError - currentAreaError);
    lastAreaError = currentAreaError;
    lastMaxError = currentMaxError;
    lastAVGError = currentAreaError / size;
    // long ende=System.currentTimeMillis();
    // System.out.println((ende-start));
  }
コード例 #3
0
  public void doIterate(final int iterationAmount) {
    //		solveDuplicates(this.sites);

    // if there is just one side we don't have to do anything
    if (sites.size == 1) {
      PolygonSimple p = (PolygonSimple) clipPolygon.clone();
      Site site = sites.get(0);
      site.setPolygon(p);
      return;
    }
    if (firstIteration) {
      voroDiagram();
      drawCurrentState(false);
    }
    //		long start = System.nanoTime();

    int k = 0;
    for (int i = 0; i < iterationAmount; i++) {
      iterate();

      //			long end = System.nanoTime();
      //			 System.out.println("Time in MilliSeconds,Iter "+i+":" + ((double)(end - start))/10E6);
      //			start=end;

      // for (Site site : polygons.keySet()) {
      // NPoly poly=polygons.get(site);
      // /**
      // * the the resulting polygon
      // */
      // if (site.cellObject != null) {
      // site.cellObject.setVoroPolygon(poly.clone());
      // }
      // }
      drawCurrentState(false);

      if (isCancelOnAreaErrorThreshold() && lastMaxError < errorAreaThreshold) {
        //				 System.out.println("AreaError:" + lastAreaError);
        //				 System.out.println("Iterations:" + i);
        break;
      }
    }
    // System.out.println("AreaError:"+errorArea);

    // now its finish so give the cells a hint
    drawCurrentState(true);

    /** TODO remove cellObject notification */
    Site[] array = sites.array;
    int size = sites.size;
    for (int z = 0; z < size; z++) {
      Site site = array[z];
      PolygonSimple poly = site.getPolygon();
      if (site.cellObject != null) {
        site.cellObject.setVoroPolygon(poly);
        site.cellObject.doFinalWork();
      }
    }
    //		long end = System.currentTimeMillis();
    //		 System.out.println("Time in MilliSeconds:" + (end - start));
    // System.out.println("LastErrorArea:" + lastAreaError);
    // System.out.println("LastErrorArea:" + lastAreaError/sites.size());
  }
コード例 #4
0
 /**
  * Adds a site, which is a voronoi cell to the list
  *
  * @param site
  */
 public void addSite(Site site) {
   sites.add(site);
 }