I need some help regarding an assignment that I've received through school. I've been stuck on a specific part of the assignment, detecting whether a rectangle is overlapping another. I tried to create an If-statement for the cases when the two rectangles aren't overlapping, but the teacher said that it would be easier doing the opposite and gave me a picture of seven scenarios that I should create If-statements for. I'm not looking for an complete answer, just maybe a solution to one of the cases so I get an idea of how I should think, or maybe just a tip. Thanks!
here is the picture,
The program language is Java. The rectangles have the dimensions: dx(width), dy(height). They each have coordinates: x, y. Which are located on the top left of each rectangle.
Try to solve it for one dimension first, then the other and combine the results.
Line A would overlap line B if start of A is before end of B while at the same time end of A is after start of B.
So if these two criterions match for the horizontal coordinates, perform the same check for the vertical coordinates. Only when you have overlap both horizontally and vertically the rectangles have a common area.
In code:
boolean isOverlap(java.awt.Rectangle A, java.awt.Rectangle B) {
if ((A.x <= B.x+B.width) && (A.x+A.width >= B.x)) {
// overlap horizontally, now check vertical
if ((A.y <= B.y+B.height) && (A.y+A.height >= B.y)) {
// overlap also vertically
return true;
}
}
return false;
}
Related
So what I'm trying to make is a function where I input the location of a moving circle and its target location, the location of a stationary circle and both of their radiuses, and I want to return the point at which they intersected if they did and the target location if they didn't.
The starting position of both circles, their radiuses and the end position of the moving circle are all known.
In this example I want to in a single frame move circle A from point Start to point End, if A collides with B I want to return the point where they touch closest to Start. In between Start and End there is a vector that can be calculated through End-Start which I'll call V and use in my attempt at solving this.
I will to refer the point Start as S and the position of B as P, the radius of A as Ra and the radius of B as Rb as seen in this image: variables.
So this is how far I've got:
When the two circles are just about touching the distance between them should be their radiuses combined like in this image: radiuses combined.
Therefore Ra+Rb = length of P-C which becomes (Ra+Rb)² = (P.x-C.x)² + (P.y-C.y)² according to Pythagoras (I squared both sides to remove the square root)
C can be described as the point S plus the vector V scaled by some constant t, C = S + tV so for example the point half way between Start and End could be described as S + 0.5V.
So the equation would then become (Ra+Rb)² = (P.x-(S.x+tV.x))² + (P.y-(S.y+tV.y))²
I have not gotten further than that since I cant isolate t which I need to find C
Any help is greatly appreciated! Sorry if I made any mistakes, its my first time posting.
(If anyone has code in Java for this that would be amazing)
You would probably have received a better answer for your question over at math.stackexchange.com, since this really seems to be a question about the maths related to your program.
But anyhow, this problem can be solved in a few steps:
1. Projection of a point onto a line:
Let Q be a projected point on V. Is the distance P-Q larger than the sum of Ra and Rb? If so, there is no collision, else proceed:
2. Pythagoras:
You now know the distance P-Q, and as you noted yourself, the circles will intersect at a distance Ra+Rb - if they collide. So, now if we find the distance Q-C, we can find where C is, since we already know where Q is from the projection onto V.
So, what is the distance Q-C: Sqrt((B-Q)^2 - (B-C)^2)
3. Find C by translating Q by distance Q-C
Now, you just need to make sure that you translate Q in the right direction: toward S.
As for the coding part of your problem, there was never a question asked, so there's nothing to respond to...
[Edit: fixed #3 Translate->Find]
I have a rectangle Object with x, y, width and height. I have a list of these rectangles which are displayed on a screen. It is guaranteed that none of them overlap. Given a user's click position (x and y coordinates), I want to see which of these rectangles were clicked (since they do not overlap, there is a maximum of one rect that can be clicked).
I can obviously look through all of them and check for each one if the user clicked it but this is very slow because there are many on the screen. I can use some kind of comparison to keep the rectangles sorted when I insert a new one into the list. Is there some way to use something similar to binary search in order to decrease the time it takes to find which rect was clicked?
Note: the rectangles can be any size.
Thanks:)
Edit: To get an idea of what I am making visit koalastothemax.com
It highly depends upon your application and details we're not quite aware of yet for what the best solution would be. BUT, with as little as I know, I'd say you can make a 2D array that points to your rectangles. That 2D array would map directly to the pixels on the screen. So if you make the array 10x20, then the coordinate x divided by screen width times 10 (casted to int) will be the first index and y divided screen height times 20 would be your y index. With your x and y index, you can map directly to the rectangle that it points to. Some indexes might be empty and some might point to more than one rectangle if they're not perfectly laid out, but that seems the easiest way to me without knowing much about the application.
I have tackled a very similar problem in the past when developing a simulation. In my case the coordinates were doubles (so no integer indexing was possible) and there could be hundreds of millions of them that needed to be searched.
My solution was to create an Axis class to represent each axis as a sequence of ranges. The ranges were guaranteed to go from a minimum to a maximum and the class was smart enough to split itself into pieces when new ranges were added. Each range has a single generic object stored. The class used a binary search to find a range quickly.
So roughly the class looks like:
class Axis<T> {
public Axis(double min, double max, Supplier<T> creator);
public Stream<T> add(double from, double to);
public T get(double coord);
}
The add method needs to return a stream because the added range may cover several ranges.
To store rectanges:
Axis<Axis<Rectangle>> rectanges = new Axis<>(0.0, 100.0,
() -> new Axis<>(0.0, 100.0, Rectangle::new));
rectangles.add(x, x + w).forEach(r -> r.add(y, y + h).forEach(Rectangle::setPresent));
And to find a rectangle:
rectangles.get(x).get(y);
Note that there's always an object stored so you need a representation such as Rectangle.NULL for 'not present'. Or you could make it Optional<Rectangle> (though that indirection eats a lot of memory and processing for large numbers of rectangles).
I've just given the high level design here rather than any implementation details so let me know if you want more info on how to make it work. Getting the logic right on the range splits is not trivial. But I can guarantee that it's very fast even with very large numbers of rectangles.
The fastest way I can come up with is definitely not the most memory efficient. This works by exploiting the fact that an amortized hash table has constant lookup time. It will map every point that a rectangle has to that rectangle. This is only really effective if your are using integers. You might be able to get it to work with floats if you use a bit of rounding.
Make sure that the Point class has a hash code and equals function.
public class PointCheck
{
public Map<Point, Rect> pointMap;
public PointCheck()
{
pointMap = new HashMap<>();
}
/**
* Map all points that contain the rectangle
* to the rectangle.
*/
public void addRect(Rect rect)
{
for(int i = rect.x; i < rect.x + rect.width; ++i)
{
for(int j = rect.y; j < rect.y + rect.height; ++i)
{
pointMap.put(new Point(i, j), rect);
}
}
}
/**
* Returns the rectangle clicked, null
* if there is no rectangle.
*/
public Rect checkClick(Point click)
{
return pointMap.get(click);
}
}
Edit:
Just thought I should mention this: All of the rectangles held in the value of the hash map are references to the original rectangle, they are not clones.
I have a 3x3 array of integers (0 or 1): int[][] matrix. The goal is to get through the maze (matrix) of 0's and 1's by assuming the 0's are walls. I'm not sure how to go about checking the neighbors.
For example, starting at [0][0] and checking above it, I need to do something like:
if (currentPosition.getColumn()-1 != null && !checkIfWall[getRow()][getColumn()-1]) {
//do stuff
}
Where checkIfWall is a boolean 2D array of walls or not wall. The problem is that checkIfWall returns ArrayOutOfBounds if any of the values are -1. Additionally, I have to write three other if statements to check below, left, and right, which seems tedious. Is there a better way to do this?
The way I would do it is assume that any location outside the array is a wall - so then you can create a function to do a collision test and check the bounds inside that.
boolean isWall(int x, int y) {
if (x<0||x>3)
return true;
if (y<0||y>3)
return true;
return data[x][y]==0;
}
Now you can just call isWall for any co-ordinates you like and it will never error, and so you don't need to worry about where you are in all your other algorithms - anything outside the maze is always treated as a wall.
First of all, I think you're confusing the directions ... you think about "up" as "-1", but usually what happens in a 2d array is that the top left corner is 0,0. and as "y" grows, it's going "down".
In any case, regarding your question, I would solve this by having a method that simply gets the current location and a direction (up,down, right, left, either strings, or better enums). You should have in your file a global variable for the size, so you can verify you are in a "valid" state, and if you're trying to check a value "outside" the array, it should return false (treat as a wall, since you can't go that way).
This will have the benefits of making your code readable as well. for example: if (isValid(this, up)) go up... and so on...
I am currently working on designing abstract classes for a possible chess game.
I needed help regarding how to move different pieces(for example queen, knight)
public class MyPiece extends Piece {
#Override
public boolean canMove(int x, int y) {
return (this.x != x && Math.abs(this.y - y) == 1);
}
}
The above code displays a sample for some piece that can just move up and down. It is not a valid chess move. So if i were to move a queen how would i go about?To simply things we are just assuming that we already have a board of matrix (x,y) 8 by 8.
Especially for chess queen it is not so simple. You have to:
determine that the move straight, i.e. horizontal, vertical, or diagonal.
That there are no other pieces on the way.
So,
To determine that move is horizontal check this.x == x && this.y != y
To determine that move is vertical check this.y == y && this.x != x
To determine diagonal check Math.abs(this.x - x) == Math.abs(this.y - y)
Now chose the direction, iterate over the way and check that your matrix does not contain elements in cells that are going to be passed by queen during this move.
You need to think in terms of "Given piece P on location (x,y) on the board which coordinates can the piece move to?". I.e. for a rook on (1,1) you can move to (1,2)..(1,8) and (2,1)..(8,1).
Unfortunately there are additional restrictions, for example:
Most pieces cannot pass other pieces. Hence, you need to know the coordinates of pieces on the board.
Kings cannot move into a check. Hence, you need to know the locations of where the opponents pieces can move to.
Kings can castle if they have not moved (it is not enough to be in the original position). Hence you need to know the history of the game.
Modelling a chess game is an interesting exercise, but perhaps you should try checkers first to get accustomed to working with an abstract representation of a physical game, and then have a second go at chess?
Quick though:
Introduce an interface called "Moveable". Your figure classes (you call them "pieces") will be defined like this. Extract your canMove() method into this interface and add move() method returning some unchecked exception if it fails.
public class MyPiece extends Piece implements Moveable{
//your code goes here
}
Create enum called MovementPossibilities. Here you should store all possible movements. Each movement possibility consists of possible directions (binary status, just on/off, true/false, can move in that direction/cannot). For every direction, introduce three integers -> minStep, maxStep, stride. Obviously, they tell you how much your figure can move in given direction.
This attemp is good in one thing - it first lets you test if your figure can move in that direction. If no, no other tests are needed.
I need to examine each pixel inside an oval with Java.
For drawing, I am currently using:
drawOval(x,y,r*2,R*2).
However, since I need to get each pixel inside the Oval, I would like to create a loop that iterates inside it (assuming I have x,y,r and R). Is there any built in functionality for this purpose?
Thanks,
Joel
Java's Ellipse2D implements the Shape interface, so you can use one of the latter's contains() methods as required. It's also possible to render the Shape into a BufferedImage and traverse its WritableRaster.
simple canonical implicit equation for Oval is (with center 0; 0)
So yo can iterate throw all possible coordinates and check it using this equation.
I don't think there's any built in functionality for this.
Let's go through this step by step.
Assuming that your ellipse's center is at (0,0), one radius is a, other is b, the canonical equation is
x^2/a^2+y^2/b^2=1
Multiplying both sides with a^2 and b^2, you get
x^2*b^2+y^2*a^2=a^2*b^2
Now, you must do a double for loop. a and b must be positive. Pseudocode:
for x = -a; x <= a; ++x:
for y = -b; y <= b; ++y:
if(x^2*b^2+y^2*a^2 <= a^2*b^2)
// you're in your ellipse, do as you please
Of course, this will work only if center is at (0,0), so if you want this algorithm to work, shift your points appropriately using translation. If you leave the center somewhere else, this algorithm will get messier.
Note: didn't test this. If somebody sees a mistake, please point it out.