Libgdx Test if line intersects with rectangle - java

Is there a way I can test if a Rectangle object collides with a line? Thanks!
EDIT :
public boolean overlapsLineNodes(Vector2 point1, Vector2 point2) {
boolean collide = false;
MapObjects mapObjects = play.getWorld().level.getCurrentLevel().getLayers().get("collidable").getObjects();
Tools.shapeRenderer.setAutoShapeType(true);
Tools.shapeRenderer.setProjectionMatrix(play.getCamera().combined);
Tools.shapeRenderer.begin();
for (RectangleMapObject rectangleObject : mapObjects.getByType(RectangleMapObject.class)) {
rectangle.setX(rectangleObject.getRectangle().x * 1/64f);
rectangle.setY(rectangleObject.getRectangle().y * 1/64f);
rectangle.setWidth(rectangleObject.getRectangle().width * 1/64f);
rectangle.setHeight(rectangleObject.getRectangle().height * 1/64f);
float x1 = rectangle.x, y1 = rectangle.y + rectangle.height,
x2 = rectangle.x + rectangle.width, y2 = rectangle.y + rectangle.height,
x3 = rectangle.x + rectangle.width, y3 = rectangle.y,
x4 = rectangle.x, y4 = rectangle.y;
Vector2 start = point1, end = point2;
float[] floatArray = new float[]{x1, y1, x2, y2, x3, y3, x4, y4};
polygon.setVertices(floatArray);
if (Intersector.intersectLinePolygon(start, end, polygon)) {
Tools.shapeRenderer.setColor(Color.GREEN);
collide = true;
}
Tools.shapeRenderer.line(point1.x, point1.y, point2.x, point2.y);
Tools.shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
Tools.shapeRenderer.setColor(Color.WHITE);
}
I do this, but it seems not to give me correct results. I am rending all of the rectanglemapobjects in white, and if one collides with the line, then I render it in green. It randomly renders some in green and I cant figure out why.

The problem was that intersectLinePolygon is the wrong method! I should have been using intersectSegmentPolygon.

Compute the intersection of the line with the line defining one edge of the rectangle, determine the whether the intersection point lies between the endpoints of the edge. Repeat with the opposite edge. If you get "yes" to either, they intersect.
You do not need to test all 4 edges; just two opposite edges.
If rectangle edges are parallel to the axis ... [x1,y1]-[x2,y1]-[x2,y2]-[x1,y2] ... and your line in question is y = m*x + b, then this becomes simply:
ya = m*x1 + b;
yb = m*x2 + b;
collision = ((ya < y1) ^ (ya < y2)) || ((yb < y1) ^ (yb < y2));
Or, if you order "ya < yb", you can get more precise over whether just touching a corner is considered a collision:
collision = ((ya <= y1) && (y1 <= yb)) || ((ya <= y2) && (y2 <= yb));

Assuming that you know start and end point of your line and also vertices of rectangle (which you must know to be honest :) ) you can use Intersector's intersectLinePolygon() method just like
//definition of variables - of course you can keep your x... y... in float[] array
float x1 = 0, x2 = 0, x3 = 0, x4 = 0, y1 = 0, y2 = 0, y3 = 0, y4 = 0;
Vector2 start = null, end = null;
//...
//updateing vertices and line start/end points
//...
Intersector.intersectLinePolygon(start, end, new Polygon(new float[]{x1, y1, x2, y2, x3, y3, x4, y4}));
If you are using this in render() method it is not good to create new Polygon() instance every time - better keep one instance somewhere
Polygon p = new Polygon();
and then just update it with vertices just before collision checking
p.setVertices(...);

Related

How to create jigsaw puzzle pieces using openGL and bezier curve?

I am trying to create a jigsaw puzzle demo, and I would like to know of alternative ways of creating puzzle pieces without using mask. Currently I have jigsaw pieces by taking a full image, breaking that image up into four pieces (lets say the puzzle is 2x2) and then storing and applying a mask to each piece. It looks like the below
// create standard puzzle pieces
arryPieceEndPos = new int[mCols][mRows];
arryPieceImg = new Bitmap[mCols * mRows];
arryIsPieceLocked = new boolean[mCols * mRows];
int pos = 0;
for (int c = 0; c < mCols; c++) {
for (int r = 0; r < mRows; r++) {
arryPieceImg[pos] = Bitmap.createBitmap(mBitmap,
c * mPieceWidth, r * mPieceHeight,
mPieceWidth, mPieceHeight);
arryIsPieceLocked[pos] = false;
arryPieceEndPos[c][r] = pos;
pos++;
}
}
I then use a helper method to apply a mask to each piece
private Bitmap maskMethod(Bitmap bmpOriginal, Bitmap bmpMask) {
// adjust mask bitmap if size is not the size of the puzzle piece
if (bmpMask.getHeight() != mPieceHeight ||
bmpMask.getWidth() != mPieceWidth) {
Log.e("TEST", "Resize Error :: H (mask): " + bmpMask.getHeight() + " // W (mask): " +
bmpMask.getWidth());
Log.d("TEST", "Resize Error :: H (norm): " + mPieceHeight + " // W (norm): " +
mPieceWidth);
}
Canvas canvas = new Canvas();
Bitmap combine = Bitmap.createBitmap(bmpOriginal.getWidth(), bmpOriginal.getHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(combine);
Paint paint = new Paint();
paint.setFilterBitmap(false);
canvas.drawBitmap(bmpOriginal, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(bmpMask, 0, 0, paint);
paint.setXfermode(null);
return combine;
}
I have been reading up on bezier curves and openGL. Neither of these I am very familiar with and they are very complex. I would like some help with forming a jigsaw puzzle piece, so that I can have an example of how it can be done.
Bezier curves can be complex, but we can "cheat" by defining the puzzle heads using Catmul-Rom curves first (which have the nice property of actually passing through their control points) and then trivially converting them to Bezier curves instead (since they're both plain Hermite splines).
So: let's do this. An example image:
All we've done is split it up so far, using fairly simple rules. In sort-of-code (technically: Processing):
int hx = width/4;
int hy = height/4;
for(int x = hx; x<width; x+=hx) {
line(x,0,x,height);
for(int y = hy; y<height; y+=hy) {
line(0,y,width,y);
}
}
And other than a fun image, it's not very exciting, so let's invent some puzzle joins. First off, we mark the centers of those cuts:
Again not really exciting:
for(int x = hx/2; x<width; x+=hx) {
for(int y = hy/2; y<height; y+=hy) {
ellipse(x + hx/2,y,5,5);
ellipse(x,y + hy/2,5,5);
}
}
But, we can make it exciting. For each of those centers, we can pick points to the left/right or up/down (depending on the edge) and decide whether to have the piece extend to the left or right, and then invent some points "around the center" to give us our Catmull-Rom curve:
for(int x = hx/2; x<width; x+=hx) {
for(int y = hy/2; y<height; y+=hy) {
// horizontal
ellipse(x-5, y+hy/2, 2,2);
ellipse(x+5, y+hy/2, 2,2);
boolean up = random(1) < 0.5;
if(up) {
ellipse(x-random(5,10), y+hy/2 - random(10,20), 2,2);
ellipse(x+random(5,10), y+hy/2 - random(10,20), 2,2);
} else {
ellipse(x-random(5,10), y+hy/2 + random(10,20), 2,2);
ellipse(x+random(5,10), y+hy/2 + random(10,20), 2,2);
}
// vertical
ellipse(x+hx/2, y-5, 2,2);
ellipse(x+hx/2, y+5, 2,2);
boolean left = random(1) < 0.5;
if(left) {
ellipse(x+hx/2-random(10,20), y-random(5,10), 2,2);
ellipse(x+hx/2-random(10,20), y+random(5,10), 2,2);
} else {
ellipse(x+hx/2+random(10,20), y-random(5,10), 2,2);
ellipse(x+hx/2+random(10,20), y+random(5,10), 2,2);
}
}
}
We're over-generating here, so I'll leave it to you to figure out how to prevent the "piece joiner" coordinates from being computed for the right-most and lowest-most edges (which should be fairly easy).
Now then: let's turn this into a coordinate grid, because that's looking pretty good, and we should get pretty nice piece joiners using Catmull-Rom:
Beauty.
for (int x = hx/2; x<width; x+=hx) {
for (int y = hy/2; y<height; y+=hy) {
// horizontal
int xs = x-hx/2,
ym = y+hy/2,
xe = x+hx/2;
float x3, x4, y1, y2,
x1 = x-5,
x2 = x+5;
boolean up = random(1) < 0.5;
x3 = x - random(5, 10);
x4 = x + random(5, 10);
if (up) {
y1 = y+hy/2 - random(10, 20);
y2 = y+hy/2 - random(10, 20);
} else {
y1 = y+hy/2 + random(10, 20);
y2 = y+hy/2 + random(10, 20);
}
curve(xs, ym, x1, ym, x3, y1, x4, y2);
curve(x1, ym, x3, y1, x4, y2, x2, ym);
curve(x3, y1, x4, y2, x2, ym, xe, ym);
// vertical
int ys = y-hy/2,
xm = x+hx/2,
ye = y+hy/2;
y1 = y-5;
y2 = y+5;
float y3, y4;
boolean left = random(1) < 0.5;
y3 = y - random(5, 10);
y4 = y + random(5, 10);
if (left) {
x1 = x+hx/2 - random(10, 20);
x2 = x+hx/2 - random(10, 20);
} else {
x1 = x+hx/2 + random(10, 20);
x2 = x+hx/2 + random(10, 20);
}
curve(xm, ys, xm, y1, x1, y3, x2, y4);
curve(xm, y1, x1, y3, x2, y4, xm, y2);
curve(x1, y3, x2, y4, xm, y2, xm, ye);
}
}
It should be relatively obvious where you need to do perform your cuts to end up with these pieces now, but if you're working with a system that can't do Catmull-Rom but can only do Bezier curves, the conversion is really straight forward. The preceding code's been using
curve(x1,x2,y1,y2,x3,y3,x4,y4);
but that's a Catmull-Rom curve. To get the equivalent curve, we can use a Bezier segment of the form:
bezier(
x2, y2,
x2 - (x3-x1)/6, y2 - (y3-y1)/6,
x3 + (x4-x2)/6, y3 + (y4-y2)/6,
x3, y3
)
And let's get puzzling.

Java Code Visual Representation of Slope in 3D Space

My last question involved getting the syntax right, this question is:
How should I best go about showing a 3D representation of a line between 2 points? I've calculated the slope, now I simply want to make a window appear and display a cube like this: http://www.wolframalpha.com/input/?i=slope+between+%282%2C6%2C1%29+and+%283%2C5%2C0%29
public static double calcSlope(Point p1, Point p2){
//math to calculate the slope
double slope1 = (p2.getY()- p1.getY())/(p2.getX()-p1.getX());
double angle1 = Math.atan(slope1);
double distance1 = (p2.getY()-p1.getY())/Math.sin(angle1);
System.out.println("distance: " + distance1);
double slopeFinal = 1/distance1;
return slopeFinal;
}
public static void main(String[]args){
double x1, x2, y1, y2, z1, z2;
x1 = 5;
x2 = 7.5;
y1 = 3.25;
y2 = 4;
z1 = 0;
z2 = 1;
Point point1 = new Point(x1, y1, z1);
//declaring new variables of class Point
Point point2 = new Point(x2, y2, z2);
//in Point y2 is = y, but y1 is also = y Point (x,y,z) serves as a placeholder where "x" is just
//a placeholder
double slope = calcSlope(point1, point2);
double angle = Math.atan(slope);
System.out.println("Your Slope is " + slope);
System.out.println("Angle of entry is " + angle);
}
Thats a BIG question, you're going to have to use some 3rd party library for 3D graphics as java doesn't natively support it*. I would suggest you look at jmonkey engine but thats just my personal preference: http://jmonkeyengine.com/.
*technically java3D does exist but it still doesn't come with java as standard and it is a largely abandoned project

Java method to find the rectangle that is the intersection of two rectangles using only left bottom point, width and height?

I have found the solution but wanted to ensure my logic is the most efficient. I feel that there is a better way. I have the (x,y) coordinate of the bottom left corner, height and width of 2 rectangles, and i need to return a third rectangle that is their intersection. I do not want to post the code as i feel it is cheating.
I figure out which is furthest left and highest on the graph.
I check if one completely overlaps the other, and reverse to see if the other completely overlaps the first on the X axis.
I check for partial intersection on the X axis.
I basically repeat steps 2 and 3 for the Y axis.
I do some math and get the points of the rectangle based on those conditions.
I may be over thinking this and writing inefficient code. I already turned in a working program but would like to find the best way for my own knowledge. If someone could either agree or point me in the right direction, that would be great!
Why not use JDK API to do this for you?
Rectangle rect1 = new Rectangle(100, 100, 200, 240);
Rectangle rect2 = new Rectangle(120, 80, 80, 120);
Rectangle intersection = rect1.intersection(rect2);
To use java.awt.Rectangle class, the parameters of the constructor are: x, y, width, height, in which x, y are the top-left corner of the rectangle. You can easily convert the bottom-left point to top-left.
I recommend the above, but if you really want to do it yourself, you can follow the steps below:
say (x1, y1), (x2, y2) are bottom-left and bottom-right corners of Rect1 respectively,
(x3, y3), (x4, y4) are those of Rect2.
find the larger one of x1, x3 and the smaller one of x2, x4, say xL,
xR respectively
if xL >= xR, then return no intersection else
find the larger one of y1, y3 and the smaller one of y2, y4, say yT,
yB respectively
if yT >= yB, then return no intersection else
return (xL, yB, xR-xL, yB-yT).
A more Java-like pseudo code:
// Two rectangles, assume the class name is `Rect`
Rect r1 = new Rect(x1, y2, w1, h1);
Rect r2 = new Rect(x3, y4, w2, h2);
// get the coordinates of other points needed later:
int x2 = x1 + w1;
int x4 = x3 + w2;
int y1 = y2 - h1;
int y3 = y4 - h2;
// find intersection:
int xL = Math.max(x1, x3);
int xR = Math.min(x2, x4);
if (xR <= xL)
return null;
else {
int yT = Math.max(y1, y3);
int yB = Math.min(y2, y4);
if (yB <= yT)
return null;
else
return new Rect(xL, yB, xR-xL, yB-yT);
}
As you see, if your rectangle was originally defined by two diagonal corners, it will be easier, you only need to do the // find intersection part.
My variation of determining intersection of two rectangles in a small utility function.
//returns true when intersection is found, false otherwise.
//when returning true, rectangle 'out' holds the intersection of r1 and r2.
private static boolean intersection2(Rectangle r1, Rectangle r2,
Rectangle out) {
float xmin = Math.max(r1.x, r2.x);
float xmax1 = r1.x + r1.width;
float xmax2 = r2.x + r2.width;
float xmax = Math.min(xmax1, xmax2);
if (xmax > xmin) {
float ymin = Math.max(r1.y, r2.y);
float ymax1 = r1.y + r1.height;
float ymax2 = r2.y + r2.height;
float ymax = Math.min(ymax1, ymax2);
if (ymax > ymin) {
out.x = xmin;
out.y = ymin;
out.width = xmax - xmin;
out.height = ymax - ymin;
return true;
}
}
return false;
}
You can also use the Rectangle source code to compare with your own algorithm:
/**
* Computes the intersection of this <code>Rectangle</code> with the
* specified <code>Rectangle</code>. Returns a new <code>Rectangle</code>
* that represents the intersection of the two rectangles.
* If the two rectangles do not intersect, the result will be
* an empty rectangle.
*
* #param r the specified <code>Rectangle</code>
* #return the largest <code>Rectangle</code> contained in both the
* specified <code>Rectangle</code> and in
* this <code>Rectangle</code>; or if the rectangles
* do not intersect, an empty rectangle.
*/
public Rectangle intersection(Rectangle r) {
int tx1 = this.x;
int ty1 = this.y;
int rx1 = r.x;
int ry1 = r.y;
long tx2 = tx1; tx2 += this.width;
long ty2 = ty1; ty2 += this.height;
long rx2 = rx1; rx2 += r.width;
long ry2 = ry1; ry2 += r.height;
if (tx1 < rx1) tx1 = rx1;
if (ty1 < ry1) ty1 = ry1;
if (tx2 > rx2) tx2 = rx2;
if (ty2 > ry2) ty2 = ry2;
tx2 -= tx1;
ty2 -= ty1;
// tx2,ty2 will never overflow (they will never be
// larger than the smallest of the two source w,h)
// they might underflow, though...
if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
}

Generating fractal Swirl [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I need to draw a fractal swirl using the algorithm Iterated Function System.
There are coefficients for this fractal:
0.745455 -0.459091 0.406061 0.887121 1.460279 0.691072 0.912675
-0.424242 -0.065152 -0.175758 -0.218182 3.809567 6.741476 0.087325
And here is my code:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Surface extends JPanel {
double a1 = 0.745455;
double b1 = -0.459091;
double d1 = 0.406061;
double e1 = 0.887121;
double c1 = 1.460279;
double f1 = 0.691072;
double p1 = 0.912675;
double a2 = -0.424242;
double b2 = -0.065152;
double d2 = -0.175758;
double e2 = -0.218182;
double c2 = 3.809567;
double f2 = 6.741476;
double p2 = 0.087325;
double x1(double x, double y) {
return a1 * x + b1 * y + c1;
}
double y1(double x, double y) {
return d1 * x + e1 * y + f1;
}
double x2(double x, double y) {
return a2 * x + b2 * y + c2;
}
double y2(double x, double y) {
return d2 * x + e2 * y + f2;
}
public void paint(Graphics g) {
drawFractal(g);
}
void drawFractal(Graphics g) {
double x1 = 300;
double y1 = 300;
double x2 = 0;
double y2 = 0;
g.fillOval(300 + (int) x1, 300 + (int) y1, 3, 3);
for (int i = 0; i < 10000; i++) {
double p = Math.random();
if (p < 0.91675) {
x2 = x1(x1, y1);
y2 = y1(x1, y1);
g.fillOval(300 + (int) x2, 300 + (int) y2, 3, 3);
x1 = x2;
y1 = y2;
} else {
x2 = x2(x1, y1);
y2 = y2(x1, y1);
g.fillOval(300 + (int) x2, 300 + (int) y2, 3, 3);
x1 = x2;
y1 = y2;
}
}
}
}
Unfortunately, with this code I get a wrong picture:
It would be great if someone could point out my mistake.
Your generation seems correct (i.e. don't do x1 = x2 +300; y1 = y2 +300;), but your problem is you're way off the scale for the purposes of rendering. This means there are very few points that fall outside very center of the image.
Your window is [0..600]x[0..600]. Try multiplying x2 and y2 with 50, so that you're rendering the [-6..6]x[-6..6] region instead of the [-300..300]x[-300..300] region of space.
Note that it should be sufficient to draw single pixels (as lines to itself) instead of 3x3 ovals.
int xp = 300 + (int) (x2 * scale);
int yp = 300 + (int) (y2 * scale);
g.drawLine(xp, yp, xp, yp);
Depending on what gets rendered, you might need to adjust the scale slightly to get the entire image with reasonable bounds. Note the second transformation offsets by -6.7, so a scale of 30 should be about right.
Also note that by using x1 = x2 +300; y1 = y2 +300; you change the transformations and get a different fractal (at a scale at which you expect).
This is great, I was wrong thinking that exponential runtime required! The fractals appeared more dimensional than my imagination!
Thanks #Jan Dvorak!
The following also works (in my coordinates, xcenter=300, ycenter=100 and radius=50 are global drawing parameters) and works faster:
void drawFractal2(Graphics g) {
double x1 = 0;
double y1 = 0;
double x2 = 0;
double y2 = 0;
double p;
g.fillOval(xcenter + (int) (x1 * radius), ycenter + (int) (y1 * radius), 3, 3);
for(int i=0; i<100000; ++i) {
p = Math.random();
if (p < p1) {
x2 = x1(x1, y1);
y2 = y1(x1, y1);
}
else {
x2 = x2(x1, y1);
y2 = y2(x1, y1);
}
g.fillOval(xcenter + (int) (x2 * radius), ycenter + (int) (y2 * radius), 3, 3);
x1 = x2;
y1 = y2;
}
}
and the picture is better
BELOW IS MY INCORRECT ANSWER
But it show how fractals are bigger than the intuition, so I keep it.
I guess your algorithm should be tree-like (recursive) while your one is linear. You are just drawing one chain of points, transforming it one after one. So you get some spiral-like chain. It can't generate any fractal picture in principle.
I GOT YOUR PICTURE
You have 2 mistakes:
1) you pass 300 both into iteration and as drawing shift. This is minor.
2) You algorithm is linear. Linear algorithm can't draw tree-like picture. If you use random values, you should run algorithm multiple times. One chain draws only one random portion of the picture.
I got your picture with following recursive algorithm. It works slow but you are to improve it.
void drawFractal(Graphics g, double x1, double y1, int depth) {
double x2 = 0;
double y2 = 0;
if( depth > 20 ) {
return;
}
g.fillOval(xcenter + (int) (x1 * radius), ycenter + (int) (y1 * radius), 3, 3);
x2 = x1(x1, y1);
y2 = y1(x1, y1);
drawFractal(g, x2, y2, depth+1);
x2 = x2(x1, y1);
y2 = y2(x1, y1);
drawFractal(g, x2, y2, depth+1);
}
to run it I used
public void paint(Graphics g) {
//drawFractal(g);
drawFractal(g, 0, 0, 0);
}
parameters are
int xcenter = 300;
int ycenter = 100;
int radius = 50;
the picture is follows:

Algorithm to move mouse from one point to another in a straight line

I am trying to make a small program that will move the mouse from the current position to the given position. Here is a method that i can use which will move the mouse from one point to another but without animation:
moveMouse(int x, int y);
This will move the mouse from the current coordinates to x,y on screen without animation. Now my job is to move the mouse to that coordinate, but it should also show the mouse moving one pixel at a time. I need to create a loop which moves the mouse cursor few pixels x and y at a time so that Here is what i have been thinking:
public void moveMouseAnimation(x,y){
//Integers x2 and y2 will be the current position of the mouse cursor
boolean isRunning = true;
while(isRunning){
delay(10); // <- 10 Milliseconds pause so that people can see the animation
x2 -= 1;
y2 -= 1;
moveMouse(x2,y2);
if(x2 == x && y2 == y) isRunning = false; //Ends loop
}
}
Now i need to find correct x2 and y2 values so that the mouse moves in a straight line and reaches x and y at last. Could someone help me.
You want the Bresenham's line algorithm. It is commonly used to draw a line between two points, but you, instead of drawing a line, will move the mouse along it.
Below is the code to do that. This code uses Bresenham Line Algo. For more ref on soln try http://en.wikipedia.org/wiki/Bresenham's_line_algorithm if you are looking not to have jagged lines
boolean steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
if (steep) {
int t;
// swap(x0, y0);
t = x0;
x0 = y0;
y0 = t;
// swap(x1, y1);
t = x1;
x1 = y1;
y1 = t;
}
if (x0 > x1) {
int t;
// swap(x0, x1);
t = x0;
x0 = x1;
x1 = t;
// swap(y0, y1);
t = y0;
y0 = y1;
y1 = t;
}
int deltax = x1 - x0;
int deltay = Math.abs(y1 - y0);
int error = deltax / 2;
int ystep;
int y = y0;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (int x = x0; x < x1; x++) {
if (steep)
moveMouse(y, x);
else
moveMouse(x, y);
error = error - deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
The problem that you are attempting to solve is that of linear interpolation, in that you have a linear function, that of a line between the starting point (x0, y0) and the ending point (x1, y1).
Luckily the solution is simple. The Wikipedia article gives examples almost exactly what you're trying to do.
http://en.wikipedia.org/wiki/Linear_interpolation
You could interpolate a straight line....basically fitting y=mx+b to the given points.

Categories

Resources