How to make bigger Polygon - java

I have polygon from class Polygon. How can I make it bigger or smaller. I'm looking for function like grow(int,int) for rectangle.I haven't got any idea how can I do that.
Thanks in advance!
#sorry for my stupid question without any details.
I'm making polygon using:
private int[] xCoord = new int[50], yCoord= new int[50]; //Arrays containing the points of the polygon
private int pointCt=0; //The number of points that have been input
I'm clicking mouse on a certain place, then draw a line
xCoord[pointCt] = arg0.getX();
yCoord[pointCt] = arg0.getY();
pointCt++;
private void putLine(int x1,int y1,int x2,int y2)
{
Graphics g= getGraphics();
g.drawLine(x1, y1, x2, y2);
g.dispose();
}
polygon=new MyPolygon(xCoord,yCoord,pointCt);
I dont exactly know which line of my code should I post but I hope its enought. I just need an advice how to make bigger polygon having cusps in a table.
Thanks!

These are operations that are best covered by linear algebra. You'd be well served by brushing up on translation, rotation, and scaling of a body. But...
If you have all the vertex data, and the object is at origin (0, 0, 0) you can just multiply all vertices by a number - 2.0 will make the object twice as big, 3.0 will make it three times as big, 0.5 will shrink it by half, etc. Make sure to do this to all components, so if you have a two-dimensional object, make sure that you multiply both the X and the Y values of each of its vertices by the same number.
If the object is not at origin, you can find the center of the object (by getting the average of all vertices), translate that to origin (by subtracting the center from each of the vertices' position), perform your scaling (by multiplying as in the previous paragraph), and add the center back to each vertex.
This is the best way to do what you're after - no need to much around with distances or matrices.

If you have access to the position data for the vertices then just calculate the distance between all the vertices and multiply it by whatever you want the scale to be. (Ex. 20% larger multiply all distances by 1.20). You can do this using the Distance Formula.
Math.sqrt((x2-x1)^2 + (y2-y1)^2)
Once you get the new distance just add the difference between the old distance and new distance to x2 and y2 and you have your new vertex coordinates, and do this for every vertex of the polygon. If your polygon is at the origin (0, 0) you can just multiply the vertices by whatever you want the scale to be, but otherwise I'd recommend the scaling based on vertices distances.

Related

A hatching algorithm using lines parallel to X-axis

I need an algorithm for hatching a random polygon with parallel to X-axis lines.
I started writing what I think is a solution.
My algorithm implementation is something like this (bolded step probably not correct):
Determine the Y-axis levels for the lines using minY and maxY of the polygon
For each Y-axis level determine X coordinates of crossing points.
Sort the Xs of the crossing points for each level
Draw lines on each level for each pair of Xs
This is the result: result
I need a way to determine what is inside the polygon and what is not or at least what is the algorithm.
(I know this is an existing alogirthm but I cannot find it anywhere)
Determine the Y-axis levels for the lines using minY and maxY of the polygon
For each Y-axis level determine X coordinates of crossing points.
Sort the Xs of the crossing points for each level
Draw lines on each level for each pair of Xs
You have the right idea. Let's say that for step #3, you have a list of xs = [x0, x1, x2, x3]. Then you need to draw lines from (x0, y) to (x1, y) and from (x2, y) to (x3, y). You don't want to draw a line from (x1, y) to (x2, y).
If you look closely at the pattern, you should be able to generalize an algorithm to draw the line segments.
For a bullet-proof solution:
For all equally spaced Y in the range Ymin to Ymax:
Try all edges PiPj in turn (j is the successor of i):
if (Y >= Yi) != (Y >= Yj):
There is an intersection, compute and store the corresponding X
Sort the X's left to right
Draw all segments (X[2i], Y) to (X[2i+1], Y)
Be sure to write the intersection condition as above, this will guarantee an even number in all cases.
For a polygon of many sides, this is pretty inefficient as you scan the whole polygon for every level. A more efficient way is using a sweepline approach: sort the edges by increasing ordinate of the lowest endpoint. Then as you go increasing Y, you will maintain a list of edges that intersect the current Y. Every time you increase Y, you remove the edges with a lower upper endpoint, and insert the edges with a lower lower endpoint (if an edge meets the two conditions, it is just skipped).

Calculate Angle for OpenGL Rotation

I'm having a little trouble calculating this angle and I'm hoping one of you geniuses can help me.
I have a game with a cannon that can be at any spot in the game world. Using OpenGL's matrix transformations, I want the cannon's texture to rotate to face in whatever direction the player puts his finger. To do this, I need to calculate an angle to send to the rotation matrix.
Currently I'm having a little trouble calculating the angle correctly.
See the figure:
Legend:
A) A constant unit vector that always points toward the top of the screen.
B) A point that is set based on where the user clicks the screen.
theta) the angle I need to measure
As you can see, I'm using a constant unit vector that always points up as a baseline (A). What my algorithm needs to do is correctly measure the angle (theta) between A and B.
Here's the code that sets the target's position:
public void setTarget(Vector2 targetPos) {
//calculate target's position relative to cannon
targetPos = sub(targetPos, this.position);
//replace target
this.target = targetPos;
//calculate new angle
//This is broken
this.cannonAngle = findAngleBetweenTwoVectors(POINT_UP, target);
The "findAngleBetweenTwoVectors" method is what doesn't seem to be working. It's code is here:
public static float findAngleBetweenTwoVectors(Vector2 baseVec, Vector2 newVec) {
//first, make copies of the vectors
Vector2 baseCopy = new Vector2(baseVec);
Vector2 newCopy = new Vector2(newVec);
//next, ensure they're normalized
baseCopy.nor();
newCopy.nor();
//the arc-cosine is the angle between the two vectors
//this is used as the "cannonAngle" value (does not work)
return (float) Math.acos(newCopy.dot(baseCopy));
}
I know this is likely a vector math problem, I just can't seem to get the angle calculation right.
Thanks in advance for the help.
Get the coordinates of B and subtract the coordinates of the cannon from them, giving a vector pointing in the desired direction. The Java atan2 function can be used to get the angle of the vector in radians. To get the angle relative to the up vector, going clockwise, pass the arguments to atan2 in the order x,y rather than y,x (which gives a result going anticlockwise from a right-pointing vector).
So you need something like this:
double dx = b_x - cannon_x;
double dy = b_y - cannon_y;
double angle_in_degrees = Math.toDegrees(Math.atan2(dx,dy));
This answer assumes that the A vector points up, as you said, and is thus (0,1). If the A vector is arbitrary, then your original answer looks almost correct, but you need to convert to degrees as a commenter said, and possibly also check that your answer is clockwise or anticlockwise.

How can I rotate the CannonBall around the ship?

Sorry about the bad title, but I could not think of anything else.
Let me explain: I have got 2 ships. The ship in the collision world, and the ship in the real world.
Now the ship in the real world is rotating, however I am unable to rotate the ship in the collision world (Or move it), which means that the collision objects must be rotated around the ship in the collision world.
When a CannonBall is near the ship, I get the distance from the CannonBall to the ship (for x, y, and z) and then compare that to a triple array of coordinates which are the collision points (About 2000+) - If the result from the triple array is "1", then they have collided. In other words, the collision ship does not move, but in the collision code the CannonBall's location is the same as the distance to the real-world ship and the real-world CannonBall.
Now here is the problem: If the ship is rotated, I need to rotate the CannonBall around the ship, because the ship cannot rotate.
How would I do this? What sort of mathematical formula?
Note: I have - Ship's rotation, x, y, and z coordinates, and the CannonBall's x, y, and z coordinates.
Thanks if anybody can give me an answer!
Edit: Lets make this more clear.
In the real world, ship1 could fire a CannonBall at ship2. If I refer to "The ship", I mean ship2.
When the CannonBall gets near to the ship, I want it to check for collisions. To do this,(Physics world) I check if array[CannonBall.distance(ship).x][CannonBall.distance(ship).y][CannonBall.distance(ship).z] returns a "1", and if it does, it collides.
However, because I cannot change an array without a large amount of processing, I cannot change the ship's rotation. Therefore, I must rotate the CannonBall around it so that it is relative to the CannonBall's true rotation compared to the ship.
If I got you right, then you are having a ship (e.g. in the middle of the screen) that has a canon ball rotating around it in order to aim towards another ship that is movable. All of that in 3D(?). Assuming that is what you mean, here is an answer ;) :
Lets do that in a 2 Dimensional Space first. What you need first is a formula to calculate a circle. As a function can only have one y-Value for each x-Value, you will actually need two. The smartest thing to do would probably divide the direction your canon ball is facing from the static ship into the common 360°, then have the formula calculate x and y coordinates. One approach could work with the formula for a circle (+/-r²=x²+y², with r being the radius), but I think a approach with cos and sin would be easier. Therefore:
You might want to have an input of an angle. If this angle is 90°, then your cannon ball is to the right of the ship. 180° would be underneath your ship, and 270° to the left, 0°/360° would be above. I would then take that input and add 90° to it, so that you can start to the left of your ship (IMPORTANT for cos and sin to work!). What we know now is the angle of the cannon ball, and the radius of the circle. Assuming that you know the coordinates of the middle of the ship, you can then imagine yourself in a coordinate system, with your ship being the origin. Now you need to calculate x. This can be done by:
x = -cos^-1(ANGLE)*radius. The result will be your x-Coordinate, that you have to subtract from the middle of the ship coordinate. Then, with x and the Angle being known, you can calculate y= x/tan-1(ANGLE). If the original angle is greater then 90°, you have to multiply the y coordinate with -1.
The method for this would be:
public void calculateCordinates(int degrees, int r){
degrees = degrees+90;
while(degrees>=360){degrees=degrees-360;}//ensures that degree < 360°
double x;
double y;
x = Math.acos(Math.toRadians((double)degrees))*r;
y = x/Math.atan(Math.toRadians((double)degrees));
}
The Coordinates are now in double as the results are most of the time not going to be whole numbers. Round them to ints before you subtract them from the origin coordinates.
If you want to do this in 3D, you can calculate the y coordinate by using the same method. This time, the angle you enter is your 3rd Dimension angle, so "the angle that you look at as in into the screen, out of the screen, with your right ear on the screen and so on" (sorry, didn't know how to describe that better). Of course you can combine the Methods to one as well, would look something like that:
public void calculateCordinates(int degrees, int degrees3D, int r){
degrees = degrees+90;
while(degrees>=360){degrees=degrees-360;}
double x;
double y;
double z;
x = Math.acos(Math.toRadians((double)degrees))*r;
y = x/Math.atan(Math.toRadians((double)degrees));
z = x/Math.atan(Math.toRadians((double)degrees3D));
}
I hope this is what you asked for, and I hope it helps!

xy position at a certain z depth

In processing (java dialect) there are the methods screenX, screenY (and screenZ but we skip that for now).
Let's say i have a object at xyz = 50, 100, 500. Then with screenX and screenY you can now where they will apear on the canvas.
float x = screenX(50, 100, 500);
float y = screenY(50, 100, 500);
here is the reference:
http://processing.org/reference/screenX_.html
What i'm interested in is like a inverse method.
For example, i want a sphere to apear on the canvas on x=175 and y=100. The sphere should have a z of 700. Then what would the actual x and y position be at z=700 to make it apear on the canvas at 175,100?
So the method would be float unscreenX(float x, float y, float z) and it would return the x value.
My math / programming skills is not so advanced (let's call it bad) (i'm more a designer) so i'm looking for some help. I all ready asked at the processing board but often there are more people here with deeper knowledge about matrixes etc.
The normal screenX method from processing can be found here:
https://github.com/processing/processing/blob/master/core/src/processing/opengl/PGraphicsOpenGL.java
public float screenX(float x, float y, float z) {
return screenXImpl(x, y, z);
}
protected float screenXImpl(float x, float y, float z) {
float ax =
modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03;
float ay =
modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13;
float az =
modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23;
float aw =
modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33;
return screenXImpl(ax, ay, az, aw);
}
protected float screenXImpl(float x, float y, float z, float w) {
float ox =
projection.m00*x + projection.m01*y + projection.m02*z + projection.m03*w;
float ow =
projection.m30*x + projection.m31*y + projection.m32*z + projection.m33*w;
if (nonZero(ow)) {
ox /= ow;
}
float sx = width * (1 + ox) / 2.0f;
return sx;
}
Of corse there is also for the y and for the z (i don't understand the z but let's ignore that).
I thought this might give some insight in how to inverse it.
modelview and projection is a 3d matrix, the code is here:
https://github.com/processing/processing/blob/master/core/src/processing/core/PMatrix3D.java
But i guess it's pretty basic and common.
I also made a post on the processing board since you never know. It explains a litle bit different what i want.
http://forum.processing.org/topic/unscreenx-and-unscreeny
For the tags describing this post, i didn't went to specific cause i can imagine a programmer who never worked with java but did work with c++ for example and has experience in matrixes is still able to provide a good answer.
hope someone can help.
I highly recommend you study some linear algebra or matrix math for 3d graphics. It's fun and easy, but a bit longer than a SO answer. I'll try though :) Disclaimer: I have no idea about the API you are using!
It looks like you are returning 3 coordinate for a position (often called a vertex). But you also mention a projection matrix and that function has 4 coordinates. Usually a shader or API will take 4 coordinates for a vertex. x,y,z,w. To get them on screen it does something like this:
xscreen = x/w
yscreen = y/w
zbuffer = z/w
This is useful because you get to pick w. If you are just doing 2d drawing you can just put w=1. But if you are doing 3d and want some perspective effect you want to divide by distance from the camera. And that's what the projection matrix is for. It mainly takes the z of your point where z means distance to camera and puts it into w. It also might scale things around a bit, like field of view.
Looking back at the code you posted this is exactly what the last ScreenXImpl function does.
It applies a projection matrix, which mostly just moves z into w, and then divides by w. At the end it does an extra scale and offset from (-1,1) to (0,widhtinpixels) but we can ignore that.
Now, why am I rambling on about this stuff? All you want to do is to get the x,y,z coordinates for a given xscreen, yscreen, zbuffer, right? Well, the trick is just going backwards. In in order to do that you need to have a firm grasp on going forward :)
There are two problems with going backwards: 1) Do you really know or care for the zbuffer value? 2) Do you know what the projection matrix did?
For 1) Let's say we don't care. There's many possible values for that, so we might just pick one. For 2) You will have to look at what it does. Some projection matrices might just take (x,y,z,w) and output (x,y,z,1). That would be 2d. Or (x,y+z,z,1) which would be isometric. But in perspective it usually does (x,y,1,z). Plus some scaling and so on.
I just noticed your second screenXImpl already passes x,y,z,w to the next stage. That is useful sometimes, but for all practical cases that w will be 1.
At this point I realize that I am terrible at explaining things. :) You really should pick up that linear algebra book, I learned from this one: http://www.amazon.com/Elementary-Linear-Algebra-Howard-Anton but it came with a good lecture, so I don't know how useful it is on it's own.
Anyhow! Let's get more practical. Back to your code: the last function of screenXImpl. We now know that the input w=1 and that ow=~z and ox=~x; The squiggly line here means times some scale plus some offset. And the screen x we have to begin with is ~ox/ow. (+1/2,*width.. that's what squiggly lines are for). And now we are back at 1)... if you want a special oz - pick one now. Otherwise, we can pick any. For rendering it probably makes sense to pick anything in front of the camera and easy to work with. Like 1.
protected float screenXImpl(float x, float y, float z, float w==1) {
float ox = 1*x + 0*y + 0*z + 0*w; // == x
float ow = 0*x + 0*y + 1*z + 0*w; // == z == 1
ox /= ow; // == ox
float sx = width * (1 + ox) / 2.0f;
return sx;
}
WTF? sx = width * (1+ox)/2 ? Why didn't I just say so? Well, all the zeros I put in there are probably not zero. But it's going to end up just as simple. Ones might not be ones. I tried to show the important assumptions you have to make to be able to go back. Now it should be as easy as going back from sx to ox.
That was the hard part! But you still have to go from the last function to the second one. I guess the second to the first is easy. :) That function is doing a linear matrix transform. Which is good for us. It takes an input of four values (x,y,z) and (w=1) implicit and outputs four other values (ax,ay,az,aw). We could figure out how to go back there manually! I had to do that in school.. four unknowns, four equations. You know ax,ay,az,aw... solve for x,y,z and you get w=1 for free! Very possible and a good exercise but also tedious. The good news is that the way those equations are written is called a matrix. (x,y,z,1) * MODELMATRIX = (ax,ay,az,aw). Really convenient because we can find MODELMATRIX^-1. It's called the inverse! Just like 1/2 is the inverse of 2 for multiplying real numbers or -1 is the inverse of 1 for addition. You really should read up on this it's fun and not hard, btw :).
Anyhow, use any standard library to get the inverse of your model matrix. Probably something like modelView.Inverse(). And then do the same function with that and you go backwards. Easy!
Now, why did we not do the same thing with the PROJECTION matrix earlier? Glad you asked! That one takes 4 inputs(x,y,z,w) and spits out only three outputs (screenx,screeny,zbufferz). So without making some assumptions we could not solve it! An intuitive way to look at that is that if you have a 3d point, that you project on a 2d screen, there's going to be a lot of possible solutions. So we have to pick something. And we can not use the convenient matrix inverse function.
Let me know if this was somewhat helpful or not. I have a feeling that it's not, but I had fun writing it! Also google for unproject in processing gives this: http://forum.processing.org/topic/read-3d-positions-gluunproject
You'd need to know the project matrix before you can make this work, which Processing doesn't supply you with. However, we can work it out ourselves by checking the screenX/Y/Z values for for the three vectors (1,0,0), (0,1,0) and (0,0,1). From those we can work out what the plane formula is for our screen (which is technically just a cropped flat 2D surface running through the 3D space). Then, given an (x,y) coordinate on the "screen" surface, and a predetermined z value, we could find the intersection between the normal line through our screen plane, and the plane at z=....
However, this is not what you want to do, because you can simply reset the coordinate system for anything you want to do. Use pushMatrix to "save" your current 3D transforms, resetMatrix to set everything back to "straight", and then draw your sphere based on the fact that your world axes and view axes are aligned. Then when you're done, call popMatrix to restore your earlier world transform and done. Save yourself the headache of implementing the math =)
You can figure this out with simple trigonometry. What you need is, h, the distance of the eye from the center of the canvas, and the cx and cy representing the center of the canvas. For simplicity, assume cx and cy are 0. Note that it is not the distance of your actual eye but the distance of the virtual eye used to construct the perspective on your 3d scene.
Next, given sx and sy, compute the distance to center, b = sqrt(sx * sx + sy * sy)
Now, you have a right-angled triangle with base b and height h. This triangle is formed by the "eye", the center on canvas, and the desired position of the object on the screen: (sx, sy).
This triangle forms the top part of another right-angled triangle formed by the "eye", the center on canvas pushed back by given depth z and the object itself: (x, y).
The ratio of the base and height of the triangles is exactly the same, so it should be trivial to calculate the base of the larger triangle bb given its height hh = z or hh = h + z depending on whether the z value is from the eye or from the canvas. The equation to use is b / h = bb / hh where you know b, h and hh
From there you can easily compute (x, y) because the two bases are at the same angle from the horizontal. I. e. sy / sx = y / x.
The only messy part will be to extract the distance of eye to canvas and the center of the canvas from the 3d setup.
Overview of Transforming 3d point onto your 2d screen
When you have a 3d representation of your object (x,y,z), you want to 'project' this onto your monitor, which is in 2d. To do this, there is a transformation function that takes in your 3d coordinates, and spits out the 2d coordinates. Under the hood, (at least in openGL), the transformation function that takes place is a special matrix. To do the transformation, you take your point (represented by a vector), and do a simple matrix multiplication.
For some nice fancy diagrams, and a derivation (if you are curious, it isn't necessary), check this out: http://www.songho.ca/opengl/gl_projectionmatrix.html
To me, screenXImpl looks like it is doing the matrix multiplication.
Doing the reverse
The reverse transformation is simply the inverse matrix of the original transformation.

How does this Quaternion rotation code work?

I'm trying to understand how the quaternion rotations work, I found this mini tutorial http://www.julapy.com/blog/2008/12/22/quaternion-rotation/ but He makes some assumptions that I can't workout, like how can I do "work out the rotation vectors around each axis, simply by rotating the vector around an axis." and how does he calculate angleDegreesX, angleDegreesY and angleDegreesZ?
Can some one provide a working example or explanation?
The shortest possible summary is that a quaternion is just shorthand for a rotation matrix. Whereas a 4x4 matrix requires 16 individual values, a quaternion can represent the exact same rotation in 4.
For the mathematically inclined, I am fully aware that the above is super over-simplified.
To provide a little more detail, let's refer to the Wikipedia article:
Unit quaternions provide a convenient
mathematical notation for representing
orientations and rotations of objects
in three dimensions. Compared to Euler
angles they are simpler to compose and
avoid the problem of gimbal lock.
Compared to rotation matrices they are
more numerically stable and may be
more efficient
What isn't clear from that opening paragraph is that a quaternion is not only convenient, it's unique. If you have a particular orientation of an object, twisting on any number of axes, there exists a single unique quaternion that represents that orientation.
Again, for the mathematically inclined, my uniqueness comment above assumes right-handed rotations. There is an equivalent left-handed quaternion that rotates in the opposite direction around the opposite axis.
For the purpose of simple explanation, that is something of a distinction without a difference.
If you'd like to make a simple quaternion that represents rotation about an axis, here's a short series of steps that will get you there:
Pick your axis of rotation v = {x, y, z}. Just for politeness, please pick a unit vector: if it's not already of length 1, divide all the components by the length of v.
Pick an angle of rotation that you'd like to turn about this axis and call that theta.
The equivalent unit quaternion can be computed using the sample code below:
Quaternion construction:
q = { cos(theta/2.0), // This is the angle component
sin(theta/2.0) * x, // Remember, angle is in radians, not degrees!
sin(theta/2.0) * y, // These capture the axis of rotation
sin(theta/2.0) * z};
Note those divisions by two: those ensure that there's no confusion in the rotation. With a normal rotation matrix, rotating to the right 90 degrees is the same as rotating to the left by 270. The quaternions that are equivalent to those two rotations are distinct: you can't confuse one with the other.
EDIT: responding to the question in the comments:
Let's simplify the problem by setting the following frame of reference:
Pick the center of the screen as the origin (we're going to rotate around that).
X axis points to the right
Y axis points up (top of the screen)
Z axis points out of the screen at your face (forming a nice right handed coordinate system).
So, if we have an example object (say an arrow) that starts by pointing to the right (positive x axis). If we move the mouse up from the x axis, the mouse will provide us with a positive x and positive y. So, working through the series of steps:
double theta = Math.atan2(y, x);
// Remember, Z axis = {0, 0, 1};
// pseudo code for the quaternion:
q = { cos(theta/2.0), // This is the angle component
sin(theta/2.0) * 0, // As you can see, the zero components are ignored
sin(theta/2.0) * 0, // Left them in for clarity.
sin(theta/2.0) * 1.0};
You need some basic math to do what you need. Basically, you rotate a point around an axis by multiyplying the matrix representing that point with a rotation matrix. The result is the rotated matrix represantation of that point.
The line
angleX = angleDegreesX * DEGTORAD;
just converts the degrees representation into a radians reprensentation by a simple formular (see this Wikipedia entry on Radians)
You can find some more information and examples of rotation matrizes here: Rotation around arbitrary axes
There are probably tools in your programming framework to do that rotation work and retrieve the matrices. Unfortunately, I cannot help you with the quaternions but your problems seem to be a little bit more basic.

Categories

Resources