Point Distribution Algorithm

An algorithm in the point distribution scenario needs to take in a "scenario" and output a set of points representing the new positions of the input points. The following is an example that demonstrates one simple (and not very good) algorithm:

public Point2D.Double[] getNewPositions(DistributionScenarioInterface scenario) {
    // these are the points in the old scenario
    Point2D.Double[] oldPoints = scenario.getPoints();
 
    // here we initialize a new array for the new locations of the points
    Point2D.Double[] newPoints = new Point2D.Double[oldPoints.length];
 
    // this is the maximum change in distance from old position to new position
    double MAX_STEP_DISTANCE = .01;
 
    // here we loop over all the points in the scenario
    for (int i = 0; i < oldPoints.length; i++) {
        // here we iterate over all the neighbors of the current point
        //    to find the one with maximum area
        Point2D.Double bestNbr = null;
        double bestArea = 0.0;
        for (Point2D.Double nbr : scenario.getPointsAdjacentTo(oldPoints[i])) {
        double area = scenario.getArea(nbr);
        if (area > bestArea) {
            bestNbr = nbr;
            bestArea = area;
        }
    }
 
    // once the point with maximum area is known,
    //    we head directly towards that point
    double nbrDist = bestNbr.distance(oldPoints[i]);
    // this is a unit vector pointing from oldPoints[i] to bestNbr
    Point2D.Double posChange = new Point2D.Double(
        (bestNbr.x - oldPoints[i].x)/nbrDist, 
        (bestNbr.y - oldPoints[i].y)/nbrDist);
    // this is the new location
    newPoints[i] = new Point2D.Double(
        oldPoints[i].x + MAX_STEP_DISTANCE * posChange.x, 
        oldPoints[i].y + MAX_STEP_DISTANCE * posChange.y);
    }
 
    // this returns the computed value
    return newPoints;
}

Detailed Explanation of Java

Here is a line-by-line description of the underlying Java code.

public Point2D.Double[] getNewPositions(DistributionScenarioInterface scenario) {
    ...
}

This declares the method, with input variable scenario of type DistributionScenarioInterface, and output variable of type Point2D.Double[]. Every variable in Java has a certain type, and that is being specified explicitly here. The brackets [] indicate that the output is an array. The public is a "modifier" that allows the method to be accessed from external classes. The curly braces { and } are used to specify the start and finish of the method.
Point2D.Double[] oldPoints = scenario.getPoints();

This declares a variable oldPoints of type Point2D.Double[], and sets it to the value returned by the method scenario.getPoints(). Here scenario is the variable argument that was passed into the method, and the . is used to access a method that "belongs" to scenario.

In Java, variables will often have "properties" and "methods". Properties store additional variables that belong to the variable, whereas methods might operate on those variables or return something of interest. In this case, the getPoints() method simply returns an array of points that represents the points within the scenario.

Point2D.Double[] newPoints = new Point2D.Double[oldPoints.length];

This creates a new array of points. In Java, the length of the array must be specified when it is first created… here the length is oldPoints.length, or the length of the array oldPoints. Arrays are indexed by a number between 0 and length-1, e.g. an array created by the code "int[] var = new int[3];" will have three values accessed by int[0], int[1], and int[2]. See http://java.sun.com/docs/books/tutorial/java/nutsandbolts/arrays.html.

The new keyword is used whenever a variable is created for the first time. This is not used above for oldPoints since the array already existed in memory inside scenario.

for (int i = 0; i < oldPoints.length; i++) {
    ...
}

Here we iterate over all points within oldPoints. This is the standard way of iterating over an array. Inside the parentheticals, the first argument int i=0; sets up the counter prior to the first run through the loop; the second argument i < oldPoints.length; describes the termination condition… as long as the condition is true, the loop will keep running; the third argument i++ says what to do after each iteration through the loop. Since arrays in Java start at 0, the resulting values of i will be 0,…,(oldPoints.length-1). Within a loop, the current point is accessible by oldPoints[i]. See http://java.sun.com/docs/books/tutorial/java/nutsandbolts/for.html.
Point2D.Double bestNbr = null;
double bestArea = 0.0;
for (Point2D.Double nbr : scenario.getPointsAdjacentTo(oldPoints[i])) {
    double area = scenario.getArea(nbr);
    if (area > bestArea) {
        bestNbr = nbr;
        bestArea = area;
    }
}

This code block finds the neighbor with the largest area. Two variables are set up to keep track of the "current" best, bestNbr and bestArea. Since we are trying to maximize the area, the initial value of bestArea is 0. The variable bestNbr begins as a null, which means it stores no point value.

The iteration structure here is slightly different… this is known as the "for-each" construction, where the colon is interpreted as the "each". So the loop statement may be interpreted as "for each point nbr in the set of points returned by the method scenario.getPointsAdjacentTo(oldPoints[i])". Within the loop, that point is accessible by the variable nbr. See http://java.sun.com/docs/books/tutorial/java/nutsandbolts/for.html.

The if statement says that if a larger area is found, we should ubdate the best-so-far. See http://java.sun.com/docs/books/tutorial/java/nutsandbolts/if.html.

double nbrDist = bestNbr.distance(oldPoints[i]);
Point2D.Double posChange = new Point2D.Double(
    (bestNbr.x - oldPoints[i].x)/nbrDist, 
    (bestNbr.y - oldPoints[i].y)/nbrDist);
newPoints[i] = new Point2D.Double(
    oldPoints[i].x + MAX_STEP_DISTANCE * posChange.x, 
    oldPoints[i].y + MAX_STEP_DISTANCE * posChange.y);

This code sets the value of newPoints[i], the ith point in the array, to be a new point which is a little distance from the old point. The distance method returns the distance between two points. In the second line, the posChange variable is used to store the unit vector pointing from oldPoints[i] to bestNbr. The new keyword is used to construct a new point. In this case, a new point is created by the code new Point2D.Double(x,y), where x and y are the coordinates. These values are in turn retrieved by statements such as bestNbr.x and bestNbr.y.
return newPoints;

The final statement in any method that returns a value should be a return statement. In this case, it returns what was guaranteed by the definition of the method, an array of points.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License