collections.sort did not sort arraylist - java

public class RectangleComparator implements Comparator<Rectangle2D> {
double x1;
double x2;
double y1;
double y2;
double w1;
double w2;
double h1;
double h2;
#Override
public int compare(Rectangle2D o1, Rectangle2D o2) {
x1 = o1.getX();
x2 = o2.getX();
y1 = o1.getY();
y2 = o2.getY();
w1 = o1.getWidth();
w2 = o2.getWidth();
h1 = o1.getHeight();
h2 = o2.getHeight();
int result = -1;
if (x1 == x2)
result = 0;
if (result == 0)
{
if (y1 == y2)
result = 0;
}
if (result == 0)
{
if (w1 == w2)
result = 0;
}
if (result == 0)
{
if (h1 == h2)
result = 0;
}
return result;
}
public class RectangleTester {
public static void main(String[] args)
{
ArrayList <Rectangle2D> rect = new ArrayList<Rectangle2D>();
rect.add(new Rectangle2D.Double(20,15,14, 10));
rect.add(new Rectangle2D.Double(20,16,11, 5));
rect.add(new Rectangle2D.Double(17,28,90, 100));
rect.add(new Rectangle2D.Double(15,9,60, 75));
rect.add(new Rectangle2D.Double(41,56,21, 19));
Collections.sort(rect, new RectangleComparator());
for (Rectangle2D temp : rect)
System.out.println(temp.toString());
}
}
}
Hi, I'm trying to learn comparator by writing a small program to sort the list of rectangles. However, when I run this the output was the reverse of the original list instead of a sorted list. I don't quite understand comparator, I would really appreciate if you guys can provide some help, thanks.

Your comaparator is bad. It kind of handles equality but nothing else.
Try something more like:
result = x2-x1;
if (result == 0) {
result = y2-y1;
if (result == 0) {
result = w2-w1;
and so on.

I think you should use some other calculation like "area" to compare it would be more meaningful comparison of rectangles:
something like:
area1 = o1.getWidth() * o1.getHeight();
area2 = o2.getWidth() * o2.getHeight();
if (area1 == area2)
return 0;
else if (area > area2)
return -1;
else if (area1 < area2)
return 1;
so this will sort on area of rectangle

Related

Java StackOverflowException when calling java.util.ArrayList.grow

I am writing an A* path finding algorithm for class. It works perfectly, I am able to click my character and move them to the correct location. However, after running for about 30 seconds of enemies also calling out to the A* algorithm it throws a java.lang.StackOverflowError.
The call directly before this is to the ArrayList library function grow. I can't imagine what I am doing wrong, as I am instantiating the object and am just calling ArrayList.add(Node);
What I am thinking is happening is that there are many ai characters that rely on this functionality, and after many of them calling to it, the program runs out of memory and surpasses the maximum stack size allocated for the program. However, Eclipse is not saying that Java ran out of memory or anything like this, which I would imagine would happen if the program actually ran out of memory.
Is there something that I am doing wrong? Or am I running out of memory? If so, is there a way to increase my allocated memory (I can see that I have tons of RAM left)? Or is there a better way that I could be storing my data to reduce memory loads?
Thanks! Here is the code I have currently written up, please let me know if there is any more information needed.
public class AStar {
class Node
{
public double x, y, g, h;
public Node parent;
public Node(double _x, double _y, double _g, double _h, Node _parent)
{
x = _x;
y = _y;
g = _g;
h = _h;
parent = _parent;
}
}
double start_x, start_y, goal_x, goal_y;
private double heuristic(double s_x, double s_y)
{
double x = Math.abs(s_x - goal_x);
double y = Math.abs(s_y - goal_y);
return x + y;
}
private Node GenerateRelativeNode(Node origin, double dX, double dY, List<Node> closed, List<Node> open)
{
double newX = origin.x + dX;
double newY = origin.y + dY;
Node temp = new Node(newX, newY, origin.g+1, heuristic(newX, newY), origin);
for(int i = 0; i < closed.size(); ++i)
{
if(closed.get(i).x == temp.x && closed.get(i).y == temp.y)
return null;
}
for(int i = 0; i < open.size(); ++i)
{
if(open.get(i).x == temp.x && open.get(i).y == temp.y)
{
return null;
}
}
return temp;
}
private int GetLowestFIndex(List<Node> set)
{
double min = 1000000;
int index = -1;
for(int i = 0; i < set.size(); ++i)
{
double f = set.get(i).h + set.get(i).g;
if(f < min)
{
min = f;
index = i;
}
}
return index;
}
private List<Pair<Double, Double>> PathFromNode(Node _n)
{
List<Pair<Double, Double>> path = new ArrayList<Pair<Double, Double>>();
List<Node> nodes = new ArrayList<Node>();
Node curr = _n;
while(curr.parent != null)
{
nodes.add(curr);
curr = curr.parent;
}
//now need to reverse the list.
for(int i = nodes.size()-1; i >= 0; --i)
{
Pair<Double, Double> pair = pairFromNode(nodes.get(i));
path.add(pair);
}
return path;
}
private Pair<Double, Double> pairFromNode(Node _n)
{
return new Pair<Double, Double>(new Double(_n.x), new Double(_n.y));
}
public static int pathDistance(double start_x, double start_y, double goal_x, double goal_y,
S3PhysicalEntity i_entity, S3 the_game) {
AStar a = new AStar(start_x,start_y,goal_x,goal_y,i_entity,the_game);
List<Pair<Double, Double>> path = a.computePath();
if (path!=null) return path.size();
return -1;
}
public AStar(double sX, double sY, double gX, double gY,
S3PhysicalEntity i_entity, S3 the_game) {
start_x = sX;
start_y = sY;
goal_x = gX;
goal_y = gY;
}
public List<Pair<Double, Double>> computePath() {
double start_h = heuristic(start_x, start_y);
Node start = new Node(start_x, start_y, 0, start_h, null);
List<Node> OpenSet = new ArrayList<>();
List<Node> ClosedSet = new ArrayList<>();
OpenSet.add(start);
while(!OpenSet.isEmpty())
{
int index = GetLowestFIndex(OpenSet);
Node N = OpenSet.get(index);
OpenSet.remove(index);
if(N.x == goal_x && N.y == goal_y)
{
return PathFromNode(N);
}
ClosedSet.add(N);
Node Up = GenerateRelativeNode(N, 0, 1, ClosedSet, OpenSet);
Node Left = GenerateRelativeNode(N, -1, 0, ClosedSet, OpenSet);
Node Right = GenerateRelativeNode(N, 1, 0, ClosedSet, OpenSet);
Node Down = GenerateRelativeNode(N, 0, -1, ClosedSet, OpenSet);
if(Up != null)
OpenSet.add(Up);
if(Left != null)
OpenSet.add(Left);
if(Right != null)
OpenSet.add(Right);
if(Down != null)
OpenSet.add(Down);
}
return null;
}
}
Here is the stack at the time of the StackOverflow
The WPeasant(WTroop).moveTowardsTarget(S3, int, int) line: 202 gets called thousands of times in a row at this point. The code for this function is not in any kind of while loop or for loop or anything.
This could be getting called multiple times however, due to the game object colliding with something, as I have not taken obstructions into account in the pathfinding.
It is hard to say for sure that this is the issue, as I wrote none of this engine, I only have to implement the A*. I can try and include obstacle avoidance and see if this fixes things.

Intersection of Rectangles for Java (Freeze Tag)

**Edited still not getting the right response **
I am not quite understanding how to figure out the intersection aspect of my project. So far I have determined the top, bottom, left and right but I am not sure where to go from there.
The main driver should call to check if my moving rectangles are intersecting and if the rectangle is froze the moving one intersecting with it should unfreeze it and change its color. I understand how to unfreeze it and change the color but for whatever the reason it isn't returning the value as true when they are intersecting and I know this code is wrong. Any helpful tips are appreciated.
*CLASS CODE*
import edu.princeton.cs.introcs.StdDraw;
import java.util.Random;
import java.awt.Color;
public class MovingRectangle {
Random rnd = new Random();
private int xCoord;
private int yCoord;
private int width;
private int height;
private int xVelocity;
private int yVelocity;
private Color color;
private boolean frozen;
private int canvas;
public MovingRectangle(int x, int y, int w, int h, int xv, int yv, int canvasSize) {
canvas = canvasSize;
xCoord = x;
yCoord = y;
width = w;
height = h;
xVelocity = xv;
yVelocity = yv;
frozen = false;
int c = rnd.nextInt(5);
if (c == 0) {
color = StdDraw.MAGENTA;
}
if (c == 1) {
color = StdDraw.BLUE;
}
if (c == 2) {
color = StdDraw.CYAN;
}
if (c == 3) {
color = StdDraw.ORANGE;
}
if (c == 4) {
color = StdDraw.GREEN;
}
}
public void draw() {
StdDraw.setPenColor(color);
StdDraw.filledRectangle(xCoord, yCoord, width, height);
}
public void move() {
if (frozen == false) {
xCoord = xCoord + xVelocity;
yCoord = yCoord + yVelocity;
}
else {
xCoord +=0;
yCoord +=0;
}
if (xCoord >= canvas || xCoord < 0) {
xVelocity *= -1;
this.setRandomColor();
}
if (yCoord >= canvas || yCoord < 0) {
yVelocity *= -1;
this.setRandomColor();
}
}
public void setColor(Color c) {
StdDraw.setPenColor(color);
}
public void setRandomColor() {
int c = rnd.nextInt(5);
if (c == 0) {
color = StdDraw.MAGENTA;
}
if (c == 1) {
color = StdDraw.BLUE;
}
if (c == 2) {
color = StdDraw.CYAN;
}
if (c == 3) {
color = StdDraw.ORANGE;
}
if (c == 4) {
color = StdDraw.GREEN;
}
}
public boolean containsPoint(double x, double y) {
int bottom = yCoord - height / 2;
int top = yCoord + height / 2;
int left = xCoord - width / 2;
int right = xCoord + width / 2;
if (x > left && x < right && y > bottom && y < top) {
color = StdDraw.RED;
return true;
} else {
return false;
}
}
public boolean isFrozen() {
if (frozen) {
return true;
} else {
return false;
}
}
public void setFrozen(boolean val) {
frozen = val;
}
public boolean isIntersecting(MovingRectangle r) {
int top = xCoord + height/2;
int bottom = xCoord - height/2;
int right = yCoord + width/2;
int left = yCoord - width/2;
int rTop = r.xCoord + r.height/2;
int rBottom = r.xCoord - r.height/2;
int rRight = r.yCoord + r.width/2;
int rLeft = r.yCoord - r.width/2;
if(right <= rRight && right >= rLeft || bottom <= rBottom && bottom
>= rTop){
return true;
} else {
return false;
}
}
}
Here is my main driver as well, because I might be doing something wrong here too.
import edu.princeton.cs.introcs.StdDraw;
import java.util.Random;
public class FreezeTagDriver {
public static final int CANVAS_SIZE = 800;
public static void main(String[] args) {
StdDraw.setCanvasSize(CANVAS_SIZE, CANVAS_SIZE);
StdDraw.setXscale(0, CANVAS_SIZE);
StdDraw.setYscale(0, CANVAS_SIZE);
Random rnd = new Random();
MovingRectangle[] recs;
recs = new MovingRectangle[5];
boolean frozen = false;
for (int i = 0; i < recs.length; i++) {
int xv = rnd.nextInt(4);
int yv = rnd.nextInt(4);
int x = rnd.nextInt(400);
int y = rnd.nextInt(400);
int h = rnd.nextInt(100) + 10;
int w = rnd.nextInt(100) + 10;
recs[i] = new MovingRectangle(x, y, w, h, xv, yv, CANVAS_SIZE);
}
while (true) {
StdDraw.clear();
for (int i = 0; i < recs.length; i++) {
recs[i].draw();
recs[i].move();
}
if (StdDraw.mousePressed()) {
for (int i = 0; i < recs.length; i++) {
double x = StdDraw.mouseX();
double y = StdDraw.mouseY();
if (recs[i].containsPoint(x, y)) {
recs[i].setFrozen(true);
}
}
}
for (int i = 0; i < recs.length; i++) {
//for 0
if(recs[0].isFrozen() && recs[0].isIntersecting(recs[1])){
recs[0].setFrozen(false);
}
if(recs[0].isFrozen() && recs[0].isIntersecting(recs[2])){
recs[0].setFrozen(false);
}
if(recs[0].isFrozen() && recs[0].isIntersecting(recs[3])){
recs[0].setFrozen(false);
}
//for 1
if(recs[1].isFrozen() && recs[1].isIntersecting(recs[2])){
recs[1].setFrozen(false);
}
if(recs[1].isFrozen() && recs[1].isIntersecting(recs[3])){
recs[1].setFrozen(false);
}
if(recs[1].isFrozen() && recs[1].isIntersecting(recs[4])){
recs[1].setFrozen(false);
}
//for 2
if(recs[2].isFrozen() && recs[2].isIntersecting(recs[0])){
recs[2].setFrozen(false);
}
if(recs[2].isFrozen() && recs[2].isIntersecting(recs[1])){
recs[2].setFrozen(false);
}
if(recs[2].isFrozen() && recs[2].isIntersecting(recs[3])){
recs[2].setFrozen(false);
}
if(recs[2].isFrozen() && recs[2].isIntersecting(recs[4])){
recs[2].setFrozen(false);
}
//for 3
if(recs[3].isFrozen() && recs[3].isIntersecting(recs[0])){
recs[3].setFrozen(false);
}
if(recs[3].isFrozen() && recs[3].isIntersecting(recs[1])){
recs[3].setFrozen(false);
}
if(recs[3].isFrozen() && recs[3].isIntersecting(recs[2])){
recs[3].setFrozen(false);
}
if(recs[3].isFrozen() && recs[3].isIntersecting(recs[4])){
recs[3].setFrozen(false);
}
//for 4
if(recs[4].isFrozen() && recs[4].isIntersecting(recs[0])){
recs[4].setFrozen(false);
}
if(recs[4].isFrozen() && recs[4].isIntersecting(recs[1])){
recs[4].setFrozen(false);
}
if(recs[4].isFrozen() && recs[4].isIntersecting(recs[3])){
recs[4].setFrozen(false);
}
if(recs[4].isFrozen() && recs[4].isIntersecting(recs[2]))
recs[4].setFrozen(false);
}
if (recs[0].isFrozen() && recs[1].isFrozen() &&
recs[2].isFrozen() && recs[3].isFrozen()
&& recs[4].isFrozen()) {
StdDraw.text(400, 400, "YOU WIN");
}
StdDraw.show(20);
}
}
}
Keep in mind you're using the OR operator here. So if right is less than rLeft, your intersector will return true. This isn't how it should work.
You need to check if right is INSIDE the rectangles bounds so to speak.
if(right <= rRight && right >= rLeft || the other checks here)
The above code checks if right is less than the rectangle's right, but also that the right is bigger than rectangle's left, which means it's somewhere in middle of the rectangle's left and right.
If this becomes too complicated you can simply use java's rectangle class, as it has the methods contains and intersects

Grid line collision checking

Lately I've been working on a grid line detection system, I know that there was an algorithm out there that did excactly what I wanted it to do, but I'm that kind of person who wants to make stuff themselves. ;)
So I've had some succes when checking with 1 line, but now that I use a grid of 20x20 to check the lines it doesn't work anymore.
The problem is found somewhere in the collision class I made for this system.
Somehow the numbers get out of the grid array and I don't know why
here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
*
* beschrijving
*
* #version 1.0 van 22-6-2016
* #author
*/
public class gridline extends JApplet {
// Begin variabelen
int[][] grid = new int[20][20];
int[] light = new int[2];
int[][] line = new int[2][2];
// Einde variabelen
public void init() {
Container cp = getContentPane();
cp.setLayout(null);
cp.setBounds(0, 0, 600, 600);
// Begin componenten
for (int a=0; a<20; a++) {
for (int b=0; b<20; b++) {
grid[a][b] = (int) (Math.random()*10);
} // end of for
} // end of for
line[0][0] = (int) (Math.random()*20);
line[0][1] = (int) (Math.random()*20);
line[1][0] = (int) (Math.random()*20);
line[1][1] = (int) (Math.random()*20);
light[0] = (int) (Math.random()*20);
light[1] = (int) (Math.random()*20);
// Einde componenten
} // end of init
//Custom classes
private boolean collide(int x1, int y1,int x2, int y2) {
boolean collide = true;
int tempx = x1 - x2;
int tempy = y1 - y2;
int sx = 0;
int sy = 0;
int x = 0;
int y = 0;
if (tempx == 0) {
tempx = 1;
sx = 1;
} // end of if
if (tempy == 0) {
tempy = 1;
sy = 1;
} // end of if
if (sx == 0) {
x = tempx + tempx/Math.abs(tempx);
} // end of if
else {
x = tempx;
} // end of if-else
if (sy == 0) {
y = tempy + tempy/Math.abs(tempy);
} // end of if
else {
y = tempy;
} // end of if-else
int absx = Math.abs(x);
int absy = Math.abs(y);
int nex = x/absx;
int ney = y/absy;
int off = 0;
float count = 0;
float step = 0;
if (absx != absy) {
if (absx == Math.min(absx,absy)) {
step = (float) absx/absy;
calc1: for (int a=0; a<absy; a++) {
count += step;
if (count > 1 && x1+off != x2) {
count -= 1;
off += nex;
} // end of if
if (grid[x1+off][y1+a*ney] == 9) {
collide = false;
break calc1;
} // end of if
} // end of for
} // end of if
else{
step = (float) absy/absx;
calc2: for (int a=0; a<absx; a++) {
count += step;
if (count > 1 && y1+off != y2) {
count -= 1;
off += ney;
} // end of if
if (grid[x1+a*nex][y1+off] == 9) {
collide = false;
break calc2;
} // end of if
} // end of for
}
} // end of if
else {
calc3: for (int a=0; a<absx; a++) {
if (grid[x1+a*nex][y1+a*ney] == 9) {
collide = false;
break calc3;
} // end of if
} // end of for
} // end of if-else
return collide;
}
private int length(int x1, int y1, int x2, int y2) {
double distance = Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
return (int) distance;
}
// Begin eventmethoden
public void paint (Graphics g){
boolean draw = true;
Color col;
for (int a=0; a<20; a++) {
for (int b=0; b<20; b++) {
draw = collide(a,b,light[0],light[1]);
if (draw) {
int len = Math.max(255-length(a*30+15,b*30+15,light[0]*30+15,light[1]*30+15),0);
col = new Color(len,len,len);
g.setColor(col);
g.fillRect(a*30,b*30,30,30);
} // end of if
else{
col = new Color(0,0,0);
g.setColor(col);
g.fillRect(a*30,b*30,30,30);
}
} // end of for
} // end of for
}
// Einde eventmethoden
} // end of class gridline
I'll understand it if nobody wants to look through a code as big as this, but it could be helpful for your own projects and I'm completely okay with it if you copy and paste my code for your projects.
Many thanks in advace.

Point in Polygon Android

I am developing an android application. In the application I have integrated map with polygon. Now I want to check whether the given marker is inside the polygon or not. Help Me please.
Following function is used to check the lat long in the polygon
pnpoly(no_of_vertex, lat, lng,(float) (point.latitude),(float) (point.longitude))
boolean pnpoly(int nvert, float vertx[], float verty[], float testx, float testy)
{
int i, j;
boolean c = false;
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ((verty[i]>testy) != (verty[j]>testy)) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c =true;
}
return c;
}
I got the solution to my question following is the code
**private boolean isPointInPolygon(LatLng tap, ArrayList<LatLng> vertices) {
int intersectCount = 0;
for(int j=0; j<vertices.size()-1; j++) {
if( LineIntersect(tap, vertices.get(j), vertices.get(j+1)) ) {
intersectCount++;
}
}
return (intersectCount%2) == 1; // odd = inside, even = outside;
}
private boolean LineIntersect(LatLng tap, LatLng vertA, LatLng vertB) {
double aY = vertA.latitude;
double bY = vertB.latitude;
double aX = vertA.longitude;
double bX = vertB.longitude;
double pY = tap.latitude;
double pX = tap.longitude;
if ( (aY>pY && bY>pY) || (aY<pY && bY<pY) || (aX<pX && bX<pX) ) {
return false; }
double m = (aY-bY) / (aX-bX);
double bee = (-aX) * m + aY; // y = mx + b
double x = (pY - bee) / m;
return x > pX;
}**

Java: Bukkit: Getting blocks in a line

I'm working on a plugin for the minecraft server api known as Bukkit.
My issues are getting the blocks as I don't know how to achieve this.
At the moment, I have the following:
public boolean loadSigns(Location loc1, Location loc2){
Selection selection = new Selection(loc1, loc2);
if(selection.getMax().getBlockY() - selection.getMin().getBlockY() != 0){
return false;
}
if ((selection.getMax().getBlockX() - selection.getMin().getBlockX()) != 0 && (selection.getMin().getBlockZ() - selection.getMax().getBlockZ() != 0)) {
return false;
}
World w = loc1.getWorld();
Integer x1 = loc1.getBlockX();
Integer y1 = loc1.getBlockY();
Integer z1 = loc1.getBlockZ();
Integer x2 = loc2.getBlockX();
Integer z2 = loc2.getBlockZ();
#SuppressWarnings("deprecation")
int dir = new Location(w, x1, y1, z1).getBlock().getData();
if (x1 - x2 == 0) {
for (int a = Math.max(x1, x2); a >= Math.min(x1, x2); a--) {
Location l = new Location(w, a, y1, z1);
BlockState b = l.getBlock().getState();
if (b instanceof Sign) {
signs.add((Sign) b);
} else {
return false;
}
}
} else {
for (int a = Math.min(z1, z2); a <= Math.max(z1, z2); a++) {
Location l = new Location(w, x1, y1, a);
BlockState b = l.getBlock().getState();
if (b instanceof Sign) {
signs.add((Sign) b);
} else {
return false;
}
}
}
if (dir == 3 || dir == 5) {
Collections.reverse(signs);
}
update();
return true;
}
loc1 is the left/start of the sign row; loc2 is the end/right of the sign row.
The problem with this is that any sign facing east or west only gets the first/start sign and not any of the others. If you need to see any other code, please say so.
P.S. new Selection(Location, Location); is just a cuboid region.
Instead of posting here where most of the people have no idea how the Bukkit api works, ask here --> https://forums.bukkit.org/forums/plugin-development.5/
Because here the community is WAY nicer, and all questions are answered, even the ones that are just one sentence

Categories