Commit 843bfece authored by John Robert McDonough's avatar John Robert McDonough
Browse files

Update MyCanvas.java

parent 4332b7ad
Loading
Loading
Loading
Loading
Loading
+83 −6
Original line number Diff line number Diff line
// referencing: https://stackoverflow.com/questions/15882202/minimum-number-of-circles-with-radius-r-to-cover-n-points

package edu.bu.ec504.hw3.p2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class MyCanvas extends Canvas {

@@ -17,12 +22,84 @@ public class MyCanvas extends Canvas {

  @Override
  public ArrayList<CanvasPoint> generateCovering() {
    // This demo implementation generates a trivial covering, where there is
    // a circle around each point.
    ArrayList<CanvasPoint> centers = new ArrayList<>();
    for (CanvasPoint pnt: this) {
      centers.add(new CanvasPoint(pnt.x, pnt.y));

    ArrayList<CanvasPoint> coveredPoints = new ArrayList<>();
    ArrayList<CanvasPoint> selectedCircles = new ArrayList<>();
    Map<CanvasPoint, ArrayList<CanvasPoint>> circleCandidates = new HashMap<>();

    // generate 10 circles for each point whose center is within a radius distance from the point
    for (CanvasPoint point : this) {
      // store generated circles in list
      ArrayList<CanvasPoint> circlesForPoint = new ArrayList<>();
      for (int i = 0; i < 10; i++) {
        // generate random distance, angle of new circle from current point
        double angle = rand.nextDouble() * 2 * Math.PI;
        double distance = rand.nextDouble();

        // generate the center of the new circle based on the angle, distance, and current point
        double centerX = point.x + distance * Math.cos(angle);
        double centerY = point.y + distance * Math.sin(angle);
        CanvasPoint circleCenter = new CanvasPoint(centerX, centerY);
        circlesForPoint.add(circleCenter);
      }
      // add all generated circles for a given point to HashMap
      circleCandidates.put(point, circlesForPoint);
    }

    // trim the list of circles to the minimum number that covers all points
    while (coveredPoints.size() < this.points.size()) {

      // find the current circle that covers most points
      CanvasPoint bestCircle = null;
      int maxCover = 0;

      // for every proposed circle...
      for (Map.Entry<CanvasPoint, ArrayList<CanvasPoint>> entry : circleCandidates.entrySet()) {
        // ... track the number of points it covers...
        for (CanvasPoint candidateCenter : entry.getValue()) {
          // ... and update the number of new points it covers
          int coverCount = 0;
          for (CanvasPoint point : this.points) {
            if (!coveredPoints.contains(point) && _distance(candidateCenter, point) < 1.0f) {
              coverCount++;
            }
          }

          // track the circle found to cover the most points
          if (coverCount > maxCover) {
            maxCover = coverCount;
            bestCircle = candidateCenter;
          }
        }
    return centers;
      }

      // find the points covered by the selected circle
      // add the circle to the list to return and update the points that are covered
      if (bestCircle != null) {
        selectedCircles.add(bestCircle); // Add the center of the selected circle to the list
        for (CanvasPoint point : this.points) {
          if (_distance(bestCircle, point) < 1.0f && !coveredPoints.contains(point)) {
            coveredPoints.add(point);
          }
        }
      }

      // exit if no new circle was found
      else {
        break;
      }
    }

    return selectedCircles;
  }

  private double _distance(CanvasPoint pnt1, CanvasPoint pnt2) {
    return Math.sqrt(
            Math.pow(pnt1.x - pnt2.x,2) +
                    Math.pow(pnt1.y - pnt2.y,2)
    );
  }

  //FIELDS
  private final Random rand = new Random();
}