A hatching algorithm using lines parallel to X-axis - java

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).

Related

How to make bigger Polygon

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.

cubic interpolation in java

For a Java program I'm making I need to interpolate 4 points, to calculate the y-value of a 5th point, at given x-value.
Say I have the following points:
p1(0, 0)
p2(1, 2)
p3(2, 4)
p4(3, 3)
// The x-values will always be 0, 1, 2, and 3
Now I want to interpolate these points to find what the y-value should be for given x, say x=1.2 (this x value will always be between point 2 and point 3)
Can anyone help me to make a Java method for finding the y coordinate of this fifth point?
Generally given two points (x0,y0) and (x1,y1), for x0 < x < x1, by interpolation,
y = y0 + (x - x0)/(x1 - x0) * (y1 - y0)
Here,
y = 2 + (x-1) * 2
There are an infinite number of lines that can go through all four of your points.
For example, you could assume that at each point the slope is zero and then draw simple s shaped curves between them, or you could assume that the slope is calculated from the neighboring points (with some special decisions about the ends), or you could assume that the slope at the points is 2, etc.
And it doesn't stop there, you could effectively draw a curve that will encapsulate your points and any other point you could imagine while still meeting the requirement of being continuous (as you call, smooth).
I think you need to start off with a formula you wish to fit against the points, and then choose the technique you use to minimize the error of the fit. Without you making more decisions, it is very likely that it will be very hard to give more direction.

Collision Handling... Confused where to go

So, I'm working on a 2D physics engine, and I have an issue. I'm having a hard time conceptualizing how you would calculate this:
Take two squares:They move, collide, and at some vector based off of the velocity of the two + the shape of them.
I have two vector lists(2D double lists) that represent these two shapes, how does one get the normal vector?
The hit vector is just (s1 is the first shape, s2 the second) s2 - s1 in terms of the position of the center of mass.
Now, I know a normal vector is one perpendicular to an edge, and I know that you can get the perpendicular vector of a line by 90 degrees, but what edge?
I read in several places, it is the edge a corner collided on. How do you determine this?
It just makes no sense to me, how you would mathematically or programmatically determine what edge.
Can anyone point out what I'm doing wrong in my understanding? Sorry for providing no code to explain this, as I'm having an issue writing the code for it in the first place.
Figure1: In 2D the normal vector is perpendicular to the tangent line:
Figure2: In 3D the normal vector is perpindicular to the tangent plane
Figure3: For a square the normal vector is easy if you are not at a corner; It is just perpendicular to the side of the square (in the image above, n = 1 i + 0 j, for any point along the right side of the square).
However, at a corner it becomes a little more difficult because the tangent is not well-defined (in terms of derivatives, the tangent is discontinuous at the corner, so perpendicular is ambiguous).
Even though the normal vector is not defined at a corner, it is defined directly to the left and right of it. Therefore, you can use the average of those two normals (n1 and n2) as the normal at a corner.
To be less technical, the normal vector will be in the direction from the center of the square to the corner of the collision.
EDIT: To answer the OP's further questions in the chat below: "How do you calculate the normal vector for a generic collision between two polygons s1 and s2 by only knowing the intersecting vertices."
In general, you can calculate the norm like this (N is total verts, m is verts inside collision):
vcenter = (∑N vi) / N
vcollision = (∑m vi) / m
n = vcollision - vcenter
Fig. 1 - vcollision is only a single vertex.
Fig. 2 - vcollision is avg of two verts.
Fig. 3 - vcollision for generic polygon intersection.

Using a QuadTree to get all points within a bounding circle

I have a set of 100 to 200 points (x,y). I have to check which ones fall within a particular distance of the others. The particular distance is fixed for the entire program, say 50. Say point 1 falls within the range of points 5,7,25,90,96,105...etc. Similarly point 2 falls within range of 23,45, etc...
Storing objects for locating by x,y coordinates
Here QuadTree is suggested, but it can be used to get all the points within a bounding rectangle. But how to get all points within a bounding circle? there is a method which returns a point closest to a lat/long within a maximum distance, but how to get all the points within the distance?
http://openmap.bbn.com/doc/api/com/bbn/openmap/util/quadtree/QuadTree.html#QuadTree(float, float, float, float, int)
one way maybe to remove each point from the tree as I get it, then query for the closest point again, until i get null. is that the only way?
Suppose that you have a circle centered at (x, y) with radius r and want to find all points in a quadtree that are in the circle. One idea is as follows:
Construct the bounding box inscribing the circle. This is the smallest rectangle containing the circle, which has upper-left corner (x - r, y - r) and lower-right corner (x + r, y + r). Any point in the circle must also be in the square, but not the other way around.
Query the quadtree for the set of points lying in that rectangle. Let these points be P.
For each point in P which is known to be in the rectangle, see if it is also in the circle. You can do this by checking whether the distance from that point to (x, y) is no greater than r. In other words, given a point (x0, y0), you would compute (x - x0)2 + (y - y0)2, and if this value is less than or equal to r2, then the point is contained in the circle.
Although this may seem inefficient, it's actually quite fast. The ratio of the area of the square to the area of the circle is 4 / π &approx; 1.27. In other words, assuming that your points are distributed somewhat evenly, you'll only find about 27% more points than you need to.

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