In my program, I am attempting to find the closest point from the starting position (0,0), then "move" again to the next point. The points are read in through a file. The next point I am trying to move to is the "closest" point. I use the Pythagorean Theorem to find the distance. But what can I do to "check" the point I am going to to determine if I have already have visited it. For instance, if the point is 0,0, and then it goes to 1,1, how do check to "tell" the program that 0,0 is no longer an option?
public class PointsNStuff {
public static void main(String [] args) {
final int P = StdIn.readInt();
double [] x = new double[P];
double [] y = new double[P];
double [] visit= new double[P]; //Set an array that stores points that have been visited already
double [] math= new double[P]; //Set an array that stores the distance to all the points
for( int i= 0; i< P; i++){ //Store the values from the text file
x[i] = StdIn.readDouble();
y[i] = StdIn.readDouble();
}
double lowX = x[0];
double lowY = y[0];
double highX = x[0];
double highY = y[0];
//Find the lowest X and the lowest Y values:
for (int i = 0; i < P; i++){
if (lowX > x[i])
lowX = x[i];
}for (int i = 0; i < P; i++){
if (lowY > y[i])
lowY = y[i];
}
for (int i = 0; i < P; i++){
if (highX < x[i])
highX = x[i];
}
for (int i = 0; i < P; i++){
if (highY < y[i])
highY = y[i];
}
System.out.println(lowX + " " + lowY);
System.out.println(highX + " " + highY);
System.out.println("");
System.out.println(P);
//Determine the closest point
double xCoord=0.0;
double yCoord=0.0;
double dist = -1.0;
for (int i= 0; i < P; i ++){ //Repeat entire section for all P (number of points)
for (int j = 0; j < P; j++){ //Find the distance between current point and all other points. Go through all points (do the math).
xCoord = x[j]; // # x point
yCoord = y[j]; // # y point
double save= Math.sqrt( ( (xCoord+x[j]) * (xCoord+x[j]) ) + ( (yCoord + y[j]) * (yCoord + y[j]) ) ); //Pythagorean theorem
save = math[j]; //store the distance in the array slot
}
for (int j = 0; j < P; j++){
if (dist < math[j]){
dist = math[j];
//What boolean check can I put here to double check whether I have visited this point already?
xCoord = x[j]; // set the two points to what number they should be at.
yCoord = y[j];
}
}
System.out.println(xCoord + " " + yCoord);
}
}
}
I have not used any points into the Array I named "visit". Any and all help is appreciated! Thanks!
Use ArrayList to Store points,
ArrayList<Double> x = new ArrayList<Double>();
ArrayList<Double> y = new ArrayList<Double>();
add points to arraylist,
for( int i= 0; i< P; i++){ //Store the values from the text file
x.add(StdIn.readDouble());
y.add(StdIn.readDouble());
}
select point from araylist,
x.get(i); insted of x[i];
y.get(i); insted of y[i];
and remove already used points,
x.remove(new Double(used_x_value));
y.remove(new Double(used_y_value));
see Class ArrayList
What you have here is a perfect candidate for encapsulation! I would start by thinking about another object to encapsulate the 'point' concept you keep referring to:
class Point {
private final double x;
private final double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
One minor caveat: this assumes that you will not have duplicate x,y pairs in the input file. If you do, you may need to override hashcode and equals. But if not, this should do it. Then you can put these Points into a data structure ( see HashSet ) like this:
import java.util.Set;
import java.util.HashSet;
public class PointsNStuff {
public static void main(String args[]) {
Set<Point> pointsVisited = new HashSet<>();
//when you visit a point, put it in the set like this
//the numbers are just for example
Point currentPoint = new Point(10.0, 12.0);
pointsVisited.add(currentPoint);
//now in the future you can check if you 'visited' this point
if(!pointsVisited.contains(currentPoint)) {
System.out.println("Haven't been to current point yet...");
}
}
}
Related
I'm trying to create two classes, one to define a point and another for array operations. I'm trying to create a method to sort an array of coordinates in ascending order based on y coordinates. I've tried following examples, but I keep running into a runtime error where the array is only partially sorted.
public class Point
{
private double x;
private double y;
public Point(double x_coord, double y_coord)
{
x = x_coord;
y = y_coord;
}
public boolean lessThan(Point anotherPoint)
{
if(y < anotherPoint.y)
{
if(x < anotherPoint.x)
{
return true;
}
}
return false;
}
}
public class PointArray
{
private Point[] points = new Point[count];
public PointArray(double[] doubleArray)
{
if(doubleArray.length % 2 == 0)
{
for(int i = 0, j = 0; i < 3; i++, j += 2)
{
double x = doubleArray[j];
double y = doubleArray[j + 1];
points[i] = new Point(x, y);
}
}
else
{
System.out.println("Error: The given array must be even.");
System.exit(0);
}
}
public void sort()
{
double x = 0;
double y = 0;
Point newPoint = new Point(x, y);
Point temp = new Point(x, y);
for (int i = 0; i < points.length - 1; i++)
{
for(int j = i + 1; j < points.length; j++)
{
int minIndex = i;
if(points[minIndex].lessThan(points[j]) == false)
{
temp = points[minIndex];
points[minIndex] = points[j];
points[j] = temp;
}
}
}
}
This code causes the array {5.6, 7.1, 4.9, 13.17, 9.3, 2.9} to first be stored as ordered pairs {(5.6, 7.1), (4.9, 13.17), (9.3, 2.9)}. but it does not sort them properly. After the first and third points are swapped, the second and third are not, even though the y coordinate of the third is smaller.
[(9.3, 2.9), (4.9, 13.17), (5.6, 7.1)]
EDIT: Another issue appeared related to the same assignment. This method is supposed to take two PointArray objects and compare them for equality by the x and y components. My idea was to sort both arrays and then compare the components using a method in the Point class, but I'm not sure how to define each PointArray in terms of an (x, y) point.
public boolean equals(Point anotherPoint)
{
if(x == anotherPoint.x && y == anotherPoint.y)
{
return true;
}
return false;
}
public boolean equals(PointArray anotherPointArray)
{
double x = 0;
double y = 0;
double xAnother = 0;
double yAnother = 0;
Point newPoint = new Point(x, y);
Point newAnotherPoint = new Point(xAnother, yAnother);
anotherPointArray.sort();
for(int i = 0; i < points.length; i++)
{
for(int j = 0; i < points.length; j++)
{
if(newPoint.equals(newAnotherPoint))
{
return true;
}
}
}
return false;
}
Your current lessThan method will give true only if both x and y are smaller. To sort by y alone use
public boolean lessThan(Point anotherPoint)
{
return y < anotherPoint.y;
}
I have a program which reads in a pair of integers from a file and stores that in a Point class which i have created. The first integer is the x coordinate and the second is the y coordinate on each line of the file. All valid points have x-coordinates in the range [0, 40] and y-coordinates in the range [1, 20].
The input file contains data like this:
I performed some validation checks so that my program ignores invalid data or out of range data.
I then have to plot a regression line on top of those points. I have to use 2D arrays of chars and would prefer to do it this way insetad of using Point2D class of java or some other graphical classes of java.
"X"s is used to represent the points, "-"s the regression line segments, and ""s where a line segment and a point are located at the same spot*
Th formula used for regression line is this:
# Edit #
Below is the code snippet that i got from #sprinter:
initializeArray(charArray);
int xySum = 0;
int xSqSum = 0;
int xSum = 0;
int ySum = 0;
for (Point points: point) {
xySum += points.getX() * points.getY();
xSqSum += points.getX() * points.getX();
xSum += points.getX();
ySum += points.getY();
}
int xMean = xSum / count;
int yMean = ySum / count;
int n = point.size();
int slope = (xySum - n* xMean * yMean) / (xSqSum - n * xMean * xMean);
for (Point points: point) {
charArray[points.getX()][points.getY()] = 'X';
}
// plot the regression line
for (int x = 0; x <charArray.length; x++) {
int y = yMean + slope * (x - xMean); // calculate regression value
charArray[x][y] = charArray[x][y] == 'X' ? '*' : '-';
}
This is my program's output after i ran sprinter's code.:
whereas i want output like this:
Also this is how i am initializing the charArray:
public static void initializeArray(char[][] charArray) {
for(int k =0; k< charArray.length; k++) {
for(int d = 0; d<charArray[k].length;d++) {
charArray[k][d] = ' ';
}
}
}
This is the new output:
I'm finding it hard to understand what the fillArray function is supposed to do. You could have multiple 'y' values for each 'x' value in your list of points so i assume you are calling this once for each point. But the regression line has lots of 'x' values that aren't in the list of points which means you would have to call this once for each regression point. You also don't need to return the array after filling the value.
Your slope calculation doesn't seem to match the formula at all. This would make more sense to me:
float xySum = 0;
float xSqSum = 0;
float xSum = 0;
float ySum = 0;
for (Point point: points) {
xySum += point.x * point.y;
xSqSum += point.x * point.x;
xSum += point.x;
ySum += point.y;
}
float xMean = xSum / count;
float yMean = ySum / count;
float n = points.size();
float slope = (xySum - n* xMean * yMean) / (xSqSum - n * xMean * xMean);
I suspect you would be much better off plotting all the points then plotting the regression line.
List<Point> points = ...;
// first plot the points
for (Point point: points) {
array[point.x][point.y] = 'X';
}
// now plot the regression line
for (int x = 0; x < 40; x++) {
int y = Math.round(yMean + slope * (x - xMean));
array[x][y] = array[x][y] == 'X' ? '*' : '-';
}
By the way, if you are familiar with Java 8 streams then you could use:
double n = points.size();
double xySum = points.stream().mapToDouble(p -> p.x * p.y).sum();
double xSqSum = points.stream().mapToDouble(p -> p.x * p.x).sum();
double xMean = points.stream().mapToDouble(p -> p.x).sum() / n;
double yMean = points.stream().mapToDouble(p -> p.y).sum() / n;
Finally, your x dimension is the first and y dimension second. So to print you need to iterate through y first, not x:
for (int y = 0; y < 20; y++) {
for (int x = 0; x < 40; x++) {
System.out.print(array[x][20-y-1]);
}
System.out.println();
}
I'm trying to create an algorithm that returns the closest pair from randomly generated points. I have finished the algorithm, however the divide and conquer method of the algorithm is not much faster than the brute-force method. What can I do to optimize the code so that it returns at (n log n) time?
import java.util.*;
import java.lang.*;
import static java.lang.Math.min;
import static java.lang.StrictMath.abs;
public class closestPair {
private static Random randomGenerator; // for random numbers
public static class Point implements Comparable<Point> {
public long x, y;
// Constructor
public Point(long x, long y) {
this.x = x;
this.y = y;
}
public int compareTo(Point p) {
// compare this and p and there are three results: >0, ==0, or <0
if (this.x == p.x) {
if (this.y == p.y)
return 0;
else
return (this.y > p.y)? 1 : -1;
}
else
return (this.x > p.x)? 1 : -1;
}
public String toString() {
return " ("+Long.toString(this.x)+","+Long.toString(this.y)+")";
}
public double distance(Point p) {
long dx = (this.x - p.x);
long dy = (this.y - p.y);
return Math.sqrt(dx*dx + dy*dy);
}
}
public static Point[] plane;
public static Point[] T;
public static Point[] Y;
public static int N; // number of points in the plane
public static void main(String[] args) {
// Read in the Size of a maze
Scanner scan = new Scanner(System.in);
try {
System.out.println("How many points in your plane? ");
N = scan.nextInt();
}
catch(Exception ex){
ex.printStackTrace();
}
scan.close();
// Create plane of N points.
plane = new Point[N];
Y = new Point[N];
T = new Point[N];
randomGenerator = new Random();
for (int i = 0; i < N; ++i) {
long x = randomGenerator.nextInt(N<<6);
long y = randomGenerator.nextInt(N<<6);
plane[i] = new Point(x, y);
}
Arrays.sort(plane); // sort points according to compareTo.
for (int i = 1; i < N; ++i) // make all x's distinct.
if (plane[i-1].x >= plane[i].x) plane[i].x = plane[i-1].x + 1;
//for (int i = 1; i < N; i++)
// if (plane[i-1].y >= plane[i].y) plane[i].y = plane[i-1].y + 1;
//
//
System.out.println(N + " points are randomly created.");
System.out.println("The first two points are"+plane[0]+" and"+plane[1]);
System.out.println("The distance of the first two points is "+plane[0].distance(plane[1]));
long start = System.currentTimeMillis();
// Compute the minimal distance of any pair of points by exhaustive search.
double min1 = minDisSimple();
long end = System.currentTimeMillis();
System.out.println("The distance of the two closest points by minDisSimple is "+min1);
System.out.println("The running time for minDisSimple is "+(end-start)+" mms");
// Compute the minimal distance of any pair of points by divide-and-conquer
long start1 = System.currentTimeMillis();
double min2 = minDisDivideConquer(0, N-1);
long end1 = System.currentTimeMillis();
System.out.println("The distance of the two closest points by misDisDivideConquer is "+min2);
System.out.println("The running time for misDisDivideConquer is "+(end1-start1)+" mms");
}
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
if (plane[i].distance(plane[j]) < midDis){
midDis = plane[i].distance(plane[j]);
}
}
}
return midDis;
}
static void exchange(int i, int j) {
Point x = plane[i];
plane[i] = plane[j];
plane[j] = x;
}
static double minDisDivideConquer(int low, int high) {
// Initialize necessary values
double minIntermediate;
double minmin;
double minDis;
if (high == low+1) { // two points
if (plane[low].y > plane[high].y) exchange(low, high);
return plane[low].distance(plane[high]);
}
else if (high == low+2) { // three points
// sort these points by y-coordinate
if (plane[low].y > plane[high].y) exchange(low, high);
if (plane[low].y > plane[low+1].y) exchange(low, low+1);
else if (plane[low+1].y > plane[high].y) exchange(low+1, high);
// compute pairwise distances
double d1 = plane[low].distance(plane[high]);
double d2 = plane[low].distance(plane[low+1]);
double d3 = plane[low+1].distance(plane[high]);
return ((d1 < d2)? ((d1 < d3)? d1 : d3) : (d2 < d3)? d2 : d3); // return min(d1, d2, d3)
} else { // 4 or more points: Divide and conquer
int mid = (high + low)/2;
double lowerPartMin = minDisDivideConquer(low,mid);
double upperPartMin = minDisDivideConquer(mid+1,high);
minIntermediate = min(lowerPartMin, upperPartMin);
int k = 0;
double x0 = plane[mid].x;
for(int i = 1; i < N; i++){
if(abs(plane[i].x-x0) <= minIntermediate){
k++;
T[k] = plane[i];
}
}
minmin = 2 * minIntermediate;
for (int i = 1; i < k-1; i++){
for(int j = i + 1; j < min(i+7,k);j++){
double distance0 = abs(T[i].distance(T[j]));
if(distance0 < minmin){
minmin = distance0;
}
}
}
minDis = min(minmin, minIntermediate);
}
return minDis;
}
}
Use the following method with the change for minDisSimple. You can get more performance.
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
double temp;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
temp = plane[i].distance(plane[j]);
if (temp < midDis) {
midDis = temp;
}
}
}
return midDis;
}
Performance wise for small amount of points simple method is good but larger amount of points Divide and Conquer is good. Try number of points with 10, 100, 1000, 10000, 100000, 1000000.
One critical aspect in the minDisDivideConquer() is that the loop that constructs the auxiliary array T iterates through all the N points. Since there are O(N) recursive calls in total, making this pass through all the N points every time leads to a complexity of O(N^2), equivalent to that of the simple algorithm.
The loop should actually only consider the points with indices between low and high. Furthermore, it could be split into two separate loops that start from mid (forward and backward), and break when the checked distance is already too large.
Another possible improvement for the minDisDivideConquer() method, in the "4 or more points" situation is to prevent looking into pairs that were already considered in the recursive calls.
If my understanding is correct, the array T contains those points that are close enough on x axis to the mid point, so that there is a chance that a pair of points in T generates a distance smaller than those from the individual half sets.
However, it is not necessary to look into points that are both before mid, or both after mid (since these pairs were already considered in the recursive calls).
Thus, a possible optimization is to construct two lists T_left and T_right (instead of T) and check distances between pairs of points such that one is on the left of mid, and the other to the right.
This way, instead of computing |T| * (|T| - 1) / 2 distances, we would only look into |T_left| * |T_right| pairs, with |T_left| + |T_right| = |T|. This value is at most (|T| / 2) * (|T| / 2) = |T| ^ 2 / 4, i.e. around 2 times fewer distances than before (this is in the worst case, but the actual number of pairs can also be much smaller, inclusively zero).
I want to ask a question about Processing. I have a user defined object class, Point, and it have two data members x and y both declared as float. I have another class Recognizer. I need to create the constructor of Recognizer and inside it define the object of Point[] point0, Point[] point1, etc... dynamically.
Point [] point0={new Point(137,139),new Point(50,63),..., new Point(78,5)};
so is point1[],point2[],...,pointn[]
How else can I add the values into point0 having the values of corresponding x and y coordinate.
Also note that the size of each object point1,point2,..., pointn are different.
How can I achieve the above goal?
How about using a 2 dimensional array ?
Point [] points0={new Point(137,139),new Point(50,63),new Point(78,5)};
Point [] points1={new Point(147,139),new Point(60,63),new Point(79,5)};
Point [] points2={new Point(157,139),new Point(70,63),new Point(80,5)};
void setup(){
Point[][] pointLists = {points0,points1,points2};
Recognizer r = new Recognizer(pointLists);
}
class Point{
float x,y;
Point(float x,float y){
this.x = x;
this.y = y;
}
String toString(){
return "Point("+x+","+y+")";
}
}
class Recognizer{
Point[][] data;
Recognizer(Point[][] data){
this.data = data;
for(int i = 0 ; i < data.length; i++){
println("processing points list" + i);
for(int j = 0; j < data[i].length; j++){
println("processing point["+j+"] of list " + i + " : "+data[i][j]);
}
}
}
}
and the ArrayList version:
import java.util.Arrays;
ArrayList<Point> points0 = new ArrayList<Point>(Arrays.asList(new Point[]{new Point(137,139),new Point(50,63),new Point(78,5)}));
ArrayList<Point> points1 = new ArrayList<Point>(Arrays.asList(new Point[]{new Point(147,139),new Point(60,63),new Point(79,5)}));
ArrayList<Point> points2 = new ArrayList<Point>(Arrays.asList(new Point[]{new Point(157,139),new Point(70,63),new Point(80,5)}));
void setup(){
ArrayList<ArrayList<Point>> pointLists = new ArrayList<ArrayList<Point>>();
pointLists.add(points0);
pointLists.add(points1);
pointLists.add(points2);
Recognizer r = new Recognizer(pointLists);
}
class Point{
float x,y;
Point(float x,float y){
this.x = x;
this.y = y;
}
String toString(){
return "Point("+x+","+y+")";
}
}
class Recognizer{
ArrayList<ArrayList<Point>> data;
Recognizer(ArrayList<ArrayList<Point>> data){
this.data = data;
for(int i = 0 ; i < data.size(); i++){
println("processing points list" + i);
for(int j = 0; j < data.get(i).size(); j++){//write this in a nicer way, too many get calls, might want a reusable variable here
println("processing point["+j+"] of list " + i + " : "+data.get(i).get(j));
}
}
}
}
I've written a java program which which uses the divide and conquer algorithm to find the convex hull of a polygon in a cartesian coordination.
I have a class Coord which has two "double" fields X and y and "this" which I'm using the method on, is a collection of coordinates (set).
my method should return the hull (Collection) of the polygon
My code is like this:
public Collection<Coord> territoire()
{
Collection<Coord> sommets = new ArrayList<Coord>();
ArrayList<Coord> thisToArrList = new ArrayList<Coord>();
for(Coord c : this)
thisToArrList.add(c);
ArrayList<Coord> sortedPointsByX = new ArrayList<Coord>();
int n = this.size();
if (n <= 2)
return this;
//sorting the points by their X coordinates
sortedPointsByX = sortedArrayByX(thisToArrList);
//>>>>>>>>>>>>>>>>>> works good till here <<<<<<<<<<<<<<<<<<<<<<<<
// now sortedPointsByX array contains the points with increasing X
// splitting the sortedPointsByX into two arrays
ArrayList<Coord> firstPart = new ArrayList<Coord>();
ArrayList<Coord> secondPart = new ArrayList<Coord>();
// if the number of the points is prime, the leftmost and the rightmost half
// both have same number of points
if(sortedPointsByX.size() % 2 == 0)
{
for(int i = 0; i < sortedPointsByX.size()/2; i++)
{
firstPart.add(sortedPointsByX.get(i));
}
for(int i = sortedPointsByX.size()/2; i < sortedPointsByX.size(); i++)
{
secondPart.add(sortedPointsByX.get(i));
}
}
//>>>>>>>>>>>>>>>>>>>>>works good till here<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// if the number of points is odd, the leftmost half have the extra points
else
{
for(int i = 0; i < sortedPointsByX.size()/2+1; i++)
{
firstPart.add(sortedPointsByX.get(i));
}
for(int i = sortedPointsByX.size()/2+1; i < sortedPointsByX.size(); i++)
{
secondPart.add(sortedPointsByX.get(i));
}
}
//>>>>>>>>>>>>>>>>>>>>>>>works good till here<<<<<<<<<<<<<<<<<<<<<<<<<
CoordSet firstSet = new CoordSet(firstPart);
CoordSet secondSet = new CoordSet(secondPart);
// converting the arrays to list of coordinates in order to use recursion over them
//recursion for sub coordsets
Collection<Coord> firstSetSommet = firstSet.territoire();
Collection<Coord> secondSetSommet = secondSet.territoire();
ArrayList<Coord> firstHull = new ArrayList<Coord>(firstSetSommet);
ArrayList<Coord> secondHull = new ArrayList<Coord>(secondSetSommet);
sommets = mergeHulls(firstHull, secondHull);
return sommets;
}
public Collection<Coord> mergeHulls(ArrayList<Coord> firstHull, ArrayList<Coord> secondHull)
{
Collection<Coord> pointsInside = new ArrayList<Coord>();
Collection<Coord> sommets = new ArrayList<Coord>();
//********************upper tangent***************
//find the highest point of the leftmost part
Coord firstPartHighestPoint = getMaxY(firstHull);
//find the highest point of the rightmost part
Coord secondPartHighestPoint = getMaxY(secondHull);
for(int i = 0; i< firstHull.size(); i++)
{
// check if the points lie on the line between highest point in leftmost and in rightmost
// if true, the current point is above the line
if(isCollinear(firstPartHighestPoint, secondPartHighestPoint, firstHull.get(i))>0)
{
// the current point is above the line
firstPartHighestPoint = firstHull.get(i);
}
pointsInside.add(firstPartHighestPoint);
}
for(int i = 0; i < secondHull.size(); i++)
{
if(isCollinear(firstPartHighestPoint, secondPartHighestPoint, secondHull.get(i))>0)
{
// the current point is above the line
secondPartHighestPoint = secondHull.get(i);
}
pointsInside.add(secondPartHighestPoint);
}
//******************lower tangent***************
//find the lowest point of the leftmost part
Coord firstPartLowestPoint = getMinY(firstHull);
// find the lowest point of the rightmost part
Coord secondPartLowestPoint = getMinY(secondHull);
for(int i = 0; i< firstHull.size(); i++)
{
// check if the points lie on the line between highest point in leftmost and in rightmost
// if true, the current point is above the line
if(isCollinear(firstPartLowestPoint, secondPartLowestPoint, firstHull.get(i)) < 0)
{
// the current point is above the line
firstPartLowestPoint = firstHull.get(i);
}
pointsInside.add(firstPartLowestPoint);
}
for(int i = 0; i < secondHull.size(); i++)
{
if(isCollinear(firstPartLowestPoint, secondPartLowestPoint, secondHull.get(i)) < 0)
{
// the current point is above the line
secondPartLowestPoint = secondHull.get(i);
}
pointsInside.add(firstPartLowestPoint);
}
sommets.addAll(firstHull);
sommets.addAll(secondHull);
sommets.removeAll(pointsInside);
return sommets;
}
//**********************************Auxiliary méthods****************************************************
// if the equation is equal to 0, the points are collinear
// the method returns the determinant of the point matrix
// This determinant tells how far point 'c' is from vector ab and on which side
// it is
// < 0 if the point 'c' is below the line (assumption : horizontal line)
// > 0 if the point 'c' is above the line
public double isCollinear(Coord a, Coord b, Coord c)
{
return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x));
}
//************************************** line equation ************************************************
// find the slope of the line between two points
public static double findSlope(Coord point1, Coord point2)
{
return (point2.y - point1.y)/(point2.x-point1.x);
}
// finding the constant 'b' of the line equation y = xm + b
public static double constantB(Double slope, Coord point)
{
return point.y - slope* point.x;
}
//*************************************** Minimum and Maximum "Y" *****************************************
// the point with maximum Y
public static Coord getMaxY(ArrayList<Coord> points)
{
double maxY = points.get(0).y; // start with the first value
Coord maxPoint = points.get(0);
for (int i=1; i<points.size(); i++) {
if (points.get(i).y > maxY)
{
maxY = points.get(i).y; // new maximum
maxPoint = points.get(i);
}
}
return maxPoint;
}
// a method to find the Point with the minimum y
public static Coord getMinY(ArrayList<Coord> points)
{
double minValue = points.get(0).y;
Coord minPoint = points.get(0);
for(int i=1;i<points.size();i++){
if(points.get(i).y < minValue)
{
minPoint = points.get(i);
minValue = points.get(i).y;
}
}
return minPoint;
}
//************************************** sorting the points ********************************************
//sorting the points by their x in ascending order
public static ArrayList<Coord> sortedArrayByX(ArrayList<Coord> arrayOfPoints)
{
//double minval = arrayOfPoints[0].x;
Coord temp = null;
for(int i = 0; i< arrayOfPoints.size(); i++)
{
for(int j = 0; j< arrayOfPoints.size()-1; j++)
{
if(arrayOfPoints.get(j+1).x < arrayOfPoints.get(j).x)
{
temp = arrayOfPoints.get(j+1);
arrayOfPoints.set(j+1, arrayOfPoints.get(j));
arrayOfPoints.set(j, temp);
}
}
}
return arrayOfPoints;
}
I can't get why when I run the program, the following message shows up:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
at miniprojet2.CoordSet.getMaxY(CoordSet.java:270)
at miniprojet2.CoordSet.mergeHulls(CoordSet.java:154)
at miniprojet2.CoordSet.territoire(CoordSet.java:139)
at miniprojet2.CalculeTerritoire.main(CalculeTerritoire.java:36)
I'll be so glad if you tell me where I've made a mistake
NOTE: I'm assuming your code fails at firstPart.add(sortedPointsByX.get(i)). If you post an SSCCE, I could provide better assistance.
sortedPointsByX has zero size.
Your code:
for(int i = 0; i < sortedPointsByX.size()/2+1; i++) {
firstPart.add(sortedPointsByX.get(i));
}
thus evaluates to:
for (int i=0; i<(0 / 2) + 1; i++) {
firstPart.add(sortedPointsByX.get(i));
}
which is:
for (int i=0; i<1; i++) {
firstPart.add(sortedPointsByX.get(i));
}
which is, in turn, equivalent to:
firstPart.add(sortedPointsByX.get(0));
However, you can't get the zeroeth element of sortedPointsByX because it is empty.
You can tell all this from your error:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
An IndexOutOfBoundsException means you tried to access some index i such that i < 0 or i >= size(). The error reports that the size is zero and that you tried to access index 0; thus, 0 ≥ 0 and your code fails.