I was developing an task when I decided to use java.awt.Rectangle to calculate the intersection between two rectangles.
I realised that the output is different from what I expected. I'm not sure if I understood how this method works or not.
For the values in the example here
java.awt.Rectangle[x=0,y=10,width=5,height=8]
java.awt.Rectangle[x=3,y=15,width=17,height=14]
I expect the intersection to be java.awt.Rectangle[x=3,y=10,width=2,height=8] but the program prints java.awt.Rectangle[x=3,y=15,width=2,height=3] instead!
here is my code:
public void printIntersection(){
Rectangle r1 = new Rectangle(0, 10, 5, 8);
Rectangle r2 = new Rectangle(3, 15, 17, 14);
Rectangle r3 = r1.intersection(r2);
System.out.println(r1);
System.out.println(r2);
System.out.println(r3);
}
Can anyone help me by pointing out what am I missing here?
UPDATE:
The source of my confusion is that the code treats the (x,y) values in the constructor as the bottom-left corner, while the class doc suggests that they are the upper-left corner!
The answer you are getting is correct.
The method works like this.
1st Rectangle:
X co-ordinates: 0
Y co-ordinates: 10
Width: 5
Height: 8
2nd Rectangle:
X co-ordinates: 3
Y co-ordinates: 15
Width: 17
Height: 14
For the intersection the X and Y co-ordinates are same as 2nd rectangle. Width is 5-3=2 and Height is 18-15=3
I also had trouble with this. The way I think about it is that the grid used is inverted on the y axis. Because point 0.0 is at the top left of the screen with point 0,1 being below rather than above that point you can get the answer you are expecting by inverting the the y axis in your original code.
For example.
public void printIntersection(){
Rectangle r1 = new Rectangle(0, 10 * -1 , 5, 8);
Rectangle r2 = new Rectangle(3, 15 * -1, 17, 14);
Rectangle r3 = r1.intersection(r2);
System.out.println(r1);
System.out.println(r2);
System.out.println(r3);
}
This should give you the answer you are expecting
The opposite corners of your rectangles are (0,10),(5,18) and (3,15),(20,29), so the intersection is (3,15),(5,18), so I think the result is the expected one. Notice the opposite corners of the resultant one are the bottom-right of the first one and the top-left of the second one.
Edit: The way it works is: the starting point is (x,y), and the sides are calculated adding the widthand height to the starting point, so the opposite corner will be (x+width,y+height)
Final note: (0,0) is the upper-left corner of the canvas:
Here is an example: (0,0,4,4) and (2,2,4,4) intersection is (2,2,2,2): (2,2) is the upper-left one and (2+2,2+2) is opposite corner
Related
I am trying to create a Shape with the centre of the ship being in the middle.
one.x and one.z is the X and Z positions of the ship. The ship size is about 100 on the X, and 50 on the Z.
Shape my = new Rectangle(
(int) one.x - disToLeft, // upper-left corner X
(int) one.z - disToTop, // upper-left corner Y
disToLeft + disToRight, // width
disToTop + disToBottom // height
);
I'm then rotating the Shape, to of course be facing the correct way. This appears to work:
int rectWidth = (disToLeft + disToRight);
int rectHeight = (disToTop + disToBottom);
AffineTransform tr = new AffineTransform();
// rotating in central axis
tr.rotate(
Math.toRadians(one.rotation),
x + (disToLeft + disToRight) / 2,
z + (disToTop + disToBottom) / 2
);
my = tr.createTransformedShape(my);
I am then doing the exact same thing with another Shape, and testing for intersection. This works.
However, it feels like the Shape is the incorrect dimensions. Or something. My ship is colliding very far out to one side (outside where it graphically exists), but through the other side, I can almost go right through the ship before any collision is detected!
Basically the Shapes are simply intersecting at the wrong location. And I cannot work out why. Either the shape, the location, or the rotation must be wrong.
int disToLeft = 100;
int disToRight = 100;
int disToTop = 150;
int disToBottom = 100;
These are the distance from the centre to the left, right, top, and bottom sides.
I am using Z instead of Y because my game is in a 3D world and the sea level is pretty much the same (hence I don't need to worry about Y axis collision!).
Update:
After doing a lot of testing, I have discovered that the top of the rectangle is in the middle! I have done a lot of messing around, but without being able to graphically see the squares, it's been very hard to test.
This means that the box is on the side of the ship, like this:
Obviously when the ship on the left rotates to what it's like in this picture, a collision is detected.
It seems that your rotation is wrong. From my understanding of math it should be
tr.rotate(Math.toRadians(one.rotation), x + (disToRight - disToLeft) /2, z + (disToBottom - disToTop) /2);
Note the signs and the order of the variables
Edit:
Let's take apart the formula:
Your Rectangle is defined like this:
x-coordinate (x): one.x-disToLeft
y-coordinate (y): one.z-disToTop
width: disToLeft+disToRight
height: disToTop+disToBottom
The centre of the Rectangle (where you are rotating) is therefore:
(x+width/2)
(y+height/2)
if you replace x, width, y and height with the declarations above you get
(one.x-disToLeft + (disToLeft+disToRight)/2)
(one.z-disToTop + (disToTop+disToBottom)/2)
This is already the point you need, but it can be simplyfied:
one.x- disToLeft + (disToLeft+disToRight)/2
is equal to
one.x-(2*disToLeft/2)+(disToLeft/2)+(disToRight/2)
is equal to
one.x-(distoLeft/2) + (disToRight/2)
is equal to
one.x+(disToRight-disToLeft)/2
The other coordinate works exactly the same.
I would like to create a Rectangle that has got one side different than the other.
(All lines depicted are meant to be straight lines)
The normal rectangle is generated like new Rectangle(50 /*LocationX*/, 50 */LocationY*/, 50 /*SizeX*/, 100 /*SizeY*/);, and looks like this:
However, I want a constructor like new Rectangle(50 /*LocationX*/, 50 */LocationY*/, 25 /*25 from the centre point for the red line*/, 30 /*30 from the centre point for the blue line*/, 50 /*50 from centre for green line*/, 100 /*100 from centre for yellow line*/);
In other words, I effectively want to keep the shape the same but move the centre point.
How can I do that?
In java, rectangles are defined by upper-left corner coordinates, width and height.
If I understand your question here what describes your rectangle:
pointX, pointY coordinates of a point in the rectangle. Named the point.
distanceToTop distance from the point to the top of the rectangle (green line).
distanceToBottom distance from the point to the bottom of the rectangle (yellow line).
distanceToLeft distance from the point to the left of the rectangle (red line).
distanceToRight distance from the point to the right of the rectangle (blue line).
That given. The upper-left corner of the rectangle has for coordinates:
(pointX - distanceToLeft, pointY - distanceToTop)
And the whole rectangle has for size (width, height):
(distanceToLeft + distanceToRight, distanceToTop + distanceToBottom)
So your instance will be:
Rectangle r = new Rectangle(
pointX - distanceToLeft, // upper-left corner X
pointY - distanceToTop, // upper-left corner Y
distanceToLeft + distanceToRight, // width
distanceToTop + distanceToBottom // height
);
Rectangle rEnemy = new Rectangle();
rEnemy.setBounds(0,0,40,40);
Rectangle rPlayer = new Rectangle();
rPlayer.setBounds(200,0,40,40);
my question: how can i make detection/intersection for rPlayer using something like "line" long for 100px?
example: rEnemy is at (0,0), rPlayer is at (100,0) and now rPlayer is intersecting line. there is a method rPlayer.intersect(rEnemy); but i what keep them 100px away from each other and get detection. of course i mean line which is aplicable for others positions of our rectangles because rPlayer and rEnemy are still in move.
I'm not exactly sure what you want, it sounds like you want to check if they are 100px away but intersecting on the x (or y) coordinate, not a 100px radius.
If you're trying to detect if they are within that bounds, you could merely make 1 or 2 rectangles that extend 100px in the x and y coordinates of either the enemy or player and check if the other piece intersects that.
But it would probably be better to just add 100px to the x coordinate of the enemy and check if the player comes within that boundary, that way you aren't drawing more rectangles. I just mentioned that before because I thought it might be easier to visualize.
I just slove this by creating 3rd rect starting from rEnemy cords and making it width and height to rPlayer cords, then:
double calculate = Math.pow(Math.abs(rPlayer.x-rEnemy.x-Camera.posX), 2)+Math.pow(Math.abs(rEnemy.y-rPlayer.y+Camera.posY), 2);
int distance = (int)Math.sqrt(calculate);
variable distance is value of px which separate rPlayer and rEnemy at any position in shortest way.
There is a Rectangle2D.Double object named rect2d and a Line2D.Double object named line2d.
Please consider the following situation:
Question 1:
What will this line of code return?
boolean intersect = line2d.getBounds2D().intersects(rect2d);
Question 2:
The width/thickness of line2d is 1 pixel. It's height/length is 20 pixels.
What would be the width and height values of the Rectangle2D object returned by line2d.getBounds2D()?
It will return:
false
java.awt.geom.Rectangle2D$Double[x=10.0,y=10.0,w=0.0,h=20.0]
With this code:
Line2D.Double line2d = new Line2D.Double(10, 10, 10, 30);
Rectangle2D.Double rect2d = new Rectangle2D.Double(0, 0, 100, 100);
boolean intersect = line2d.getBounds2D().intersects(rect2d);
System.out.println(intersect);
System.out.println(line2d.getBounds2D());
Although, it's useless to say that a line is 1 pixel, because it can't be other way using Line2D.Double.
Indeed, for Java, this vertical line as a 0-pixel width boundary, so that's why it will never intersect with any other shape. With a non-vertical and non-horizontal line, its bounds intersect.
Do not use bounds to compute intersection, but directly the Shape:
boolean intersect = line2d.intersects(rect2d);
You may check RectangularShape.intersects() Javadoc for more information on how this method computes intersection.
From the docs, here and here, the first would return false and the second a bounding box at least the size of the dimensions of the line.
I need to plot a polynomial given a start point and an end point. I've looked at using the paincomponent to do do it, but I'm getting confused because the origin is in the top left corner and I need my grid lines to be dynamic.
How do I make it so I can create a dynamic scale and what java class is best used for plotting a function?
For example if the user were to enter -2 2 x^2 the plotter would need to create a grid that goes from -2 has 0 in the middle and 2 on the right for the x coordinates. However if the user enters x^3 we have negative coordinates in the y plane and I'll need to slide the line containing the x coordinates up to accomidate.
Thanks!
The way I think you could do this(and I may be wrong) is to draw the y-line and x-line of your graph, and label the values for x and y using drawString at the correct position.
To illustrate this I did this example for you:
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Point2D.Double from = new Point2D.Double(300, 100);
Point2D.Double to = new Point2D.Double(300, 300);
Line2D.Double line = new Line2D.Double(from, to);
g2.draw(line);
Point2D.Double from2 = new Point2D.Double(150, 200);
Point2D.Double to2 = new Point2D.Double(450, 200);
Line2D.Double line2 = new Line2D.Double(from2, to2);
g2.draw(line2);
g2.drawString("-1", 290, 215);
}
The drawString method would draw "-1" below 0. So you could use the same thing to draw -2 below -1, etc.
I know this sounds inefficient, but it's the only way I can think of.
Hope someone else will have a better solution for you.
It shouldn't be too difficult to transform the y-coordinate if you know the size of area you want to paint to. But to be honest, why don't you use one of the plotting libs like JFreeChart, ...?