I want to the difference between two integers is +1 or -1. I think my code below is very clumsy to write. Is there any shorter way to check if two integers are just 1 apart? This seems like a simple solution, but I have 2d array of coordinates I want to check if two coordinates in the direct vicinity (either north, east, west, or south) of each other are selected.
Yes they are standard coordinates as the top left corner is 0,0, and the bottom right is 7,7. Essentially if one coordinate is selected, I wanted to check if there exists another coordinate where x or y differs by (+-) one.
//Since it's a 2d array, I am doing a nested loop. But comparison is below
int x1 = range(0,8); //all ints are range from 0 to 7
int y1 = range(0,8); //represent the current indices from the loop
int x2 = ...; //x2 represents the x index value of the previous loop
int y2 = ...; //y2 represents the y index value of the previous loop
if(x1+1 == x2){
Found an existing X coord just larger by one
}else if (x1-1 == x2){
Found an existing X coord smaller, and differ by one
}else if(y1+1 == y2){
Found an existing Y coord just 1 larger
}else if(y-1 == y2){
Found an existing Y coord just 1 smaller
}
Since we don't care whether the difference between x1 and x2 is 1 or -1, we can use the absolute value:
if (Math.abs(x1 - x2) == 1){
// x coordinates differ by 1
} else if (Math.abs(y1 - y2) == 1){
// y coordinates differ by 1
}
This works because if x1 is less than x2, then Math.abs(x1 - x2) = Math.abs(-1) = 1.
The simplest way I can think of is:
boolean differenceOfOne = Math.abs(n1 - n2) == 1;
Where n1 and n2 are numbers.
How about:
Math.abs(difference)==1
You can use Math.abs to evaluate the difference:
boolean isDifferenceOne = Math.abs(x1 - x2) == 1 && Math.abs(y1 - y2) == 1
Related
I'm making a game with libGDX in Java. I'm trying to make a collision detection. As you can see in the image, I have a line which is a wall and a player with specified radius. The desired position is the next location which the player is trying to be in. But because there is a wall, he's placed in the Actual Position which is on the Velocity vector, but more closer to the prev location. I'm trying to figure out how can I detect that closer position?
My attempt:
private void move(float deltaTime) {
float step;
beginMovementAltitude();
if (playerComponent.isWalking())
step = handleAcceleration(playerComponent.getSpeed() + playerComponent.getAcceleration());
else step = handleDeacceleration(playerComponent.getSpeed(), playerComponent.getAcceleration());
playerComponent.setSpeed(step);
if (step == 0) return;
takeStep(deltaTime, step, 0);
}
private void takeStep(float deltaTime, float step, int rotate) {
Vector3 position = playerComponent.getCamera().position;
float x = position.x;
float y = position.y;
int radius = playerComponent.getRadius();
auxEnvelope.init(x, x + radius, y, y + radius);
List<Line> nearbyLines = lines.query(auxEnvelope);
float theta;
int numberOfIntersections = 0;
float angleToMove = 0;
Gdx.app.log(step + "", "");
for (Line line : nearbyLines) {
VertexElement src = line.getSrc();
VertexElement dst = line.getDst();
auxVector3.set(playerComponent.getCamera().direction);
auxVector3.rotate(Vector3.Z, rotate);
float nextX = x + (step * deltaTime) * (auxVector3.x);
float nextY = y + (step * deltaTime) * playerComponent.getCamera().direction.y;
float dis = Intersector.distanceLinePoint(src.getX(), src.getY(), dst.getX(), dst.getY(), nextX, nextY);
boolean bodyIntersection = dis <= 0.5f;
auxVector21.set(src.getX(), src.getY());
auxVector22.set(dst.getX(), dst.getY());
auxVector23.set(nextX, nextY);
if (bodyIntersection) {
numberOfIntersections++;
if (numberOfIntersections > 1) {
return;
}
theta = auxVector22.sub(auxVector21).nor().angle();
float angle = (float) (180.0 / MathUtils.PI * MathUtils.atan2(auxVector23.y - position.y, auxVector23.x - position.x));
if (angle < 0) angle += 360;
float diff = (theta > angle) ? theta - angle : angle - theta;
if (step < 0) step *=-1;
angleToMove = (diff > 90) ? theta + 180 : theta;
}
}
if (numberOfIntersections == 0) {
moveCameraByWalking(deltaTime, step, rotate);
} else {
moveCameraInDirection(deltaTime, step, angleToMove);
}
}
The idea is to find intersection of path of object center and the line moved by radius of the circle, see that picture.
At first, you need to find a normal to the line. How to do it, depends on how the line is defined, if it's defined by two points, the formula is
nx = ay - by
ny = bx - ax
If the line is defined by canonical equation, then coefficients at x and y define normal, if I remembered correctly.
When normal is found, we need to normalize it - set length to 1 by dividing coordinates by vector length. Let it be n.
Then, we will project starting point, desired point and randomly chosen point on line to n, treating them as radius vectors.
Projection of vector a to vector b is
project (a, b) = scalar_product (a, b) / length (b)**2 * b
but since b is n which length equals 1, we will not apply division, and also we want to only find length of the result, we do not multiply by b. So we only compute scalar product with n for each of three aforementioned points, getting three numbers, let s be the result for starting point, d for desired point, l for chosen point on the line.
Then we should modify l by radius of the circle:
if (s < d) l -= r;
else if (s > d) l += r;
If s = d, your object moves in parallel along the line, so line can't obstruct its movement. It's highly improbable case but should be dealt with.
Also, that's important, if l was initially between s and d but after modifying is no longer between then, it's a special case you may want to handle (restrict object movement for example)
Ather that, you should compute (d - s) / (l - s).
If the result is greater or equals 1, the object will not reach the line.
If the result is between 0 and 1, the line obstructs movement and the result indicates part of the path the object will complete. 0.5 means that object will stop halfway.
If the result is negative, it means the line is behind the object and will not obstruct movement.
Note that when using floating point numbers the result will not be perfectly precise, that's why we handle that special case. If you want to prevent this from happening at all, organize loop and try approximations until needed precision is reached.
I am currently trying to put together an algorithm where I can know if there is an obstruction between two defined points in a plane.
Here is an example image.
We can see with the image that point 1, 2, 3, & 6 are all accessible from the origin point. Points 4 and 5 are not. You pass through the polygon.
The code I am using is the following. pStartPoint and pEndPoint is the line from the origin to the point in question. The function checks all edges to see if the line passes through the edge.
public double GetSlopeOfLine(Point a, Point b){
double x = b.y - a.y;
double y = b.x - a.x;
return (x / y);
}
public double GetOffsetOfLine(double x, double y, double slope){
return (y - (slope * x));
}
public boolean IsPointAccessable(Point pStartPoint, Point pEndPoint){
//Define the equation of the line for these points. Once we have slope and offset the equation is
//y = slope * x + offset;
double slopeOfLine = GetSlopeOfLine(pStartPoint, pEndPoint);
double offSet = GetOffsetOfLine(pStartPoint.x, pStartPoint.y, slopeOfLine);
//Collision detection for each side of each obstacle. Once we get the point of collision, does it lie on the
//line in between the two points? If so, collision, and I can't reach that point yet.
for (Iterator<Obstacles> ObstacleIt = AdjustedObstaclesList.iterator(); ObstacleIt.hasNext();) {
Obstacles pObstacle = ObstacleIt.next();
int NumberOfEdges = pObstacle.getPoints().size();
for(int i=0; i<NumberOfEdges; i++){
//Get Edge[i];
int index = i;
Point pFirstPoint = (Point)pObstacle.getPoints().get(index);
if(i >= NumberOfEdges - 1)
index = 0;
else
index = i+1;
Point pNextPoint = (Point)pObstacle.getPoints().get(index);
double slopeOfEdge = GetSlopeOfLine(pFirstPoint, pNextPoint);
double offsetEdge = GetOffsetOfLine(pNextPoint.x, pNextPoint.y, slopeOfEdge);
int x = Math.round((float) ((-offSet + offsetEdge) / (slopeOfLine - slopeOfEdge)));
int y = Math.round((float) ((slopeOfLine * x) + offSet));
//If it lies on either point I could be looking at two adjacent points. I can still reach that point.
if(x > pStartPoint.x && x < pEndPoint.x && y > pStartPoint.y && y < pEndPoint.y &&
x > pFirstPoint.x && x < pNextPoint.x && y > pFirstPoint.y && y < pNextPoint.y){
return false;
}
}
}
return true;
}
If the line passes through and the point where the lines cross is found between pStartPoint and pEndPoint I am assuming that pEndPoint cannot be reached.
This function is not working and I am wondering if it has something to do with the fact that the origin is not at the bottom left but at the top left and that (width, height) of my window is located in the bottom right. Therefore the coordinate plane is messed up.
My mind must be mush because I cannot think how to adjust for this and if that is truly my mistake as I cannot seem to fix the error. I thought adjusting the slope and offset by multiplying each by -1 might have been the solution but that doesn't seem to work.
Is my solution the right one? Does my code seem correct in checking for an intersect point? Is there a better solution to see if a point is accessible.
There is also going to be the next step after this where once I determine what points are accessible if I am now on one of the points of the polygon. For example, from point 1 what points are accessible without crossing into the polygon?
First, I would like to say that using slopes for this kind of task is do-able, but also difficult due to the fact that they are very volatile in the sense that they can go from negative infinity to infinity with a very small change in the point. Here's a slightly different algorithm, which relies on angles rather than slopes. Another advantage of using this is that the coordinate systems don't really matter here. It goes like this (I reused as much of your existing code as I could):
public boolean IsPointAccessable(Point pStartPoint, Point pEndPoint) {
//Collision detection for each side of each obstacle. Once we get the point of collision, does it lie on the
//line in between the two points? If so, collision, and I can't reach that point yet.
for (Iterator<Obstacles> ObstacleIt = AdjustedObstaclesList.iterator(); ObstacleIt.hasNext();) {
Obstacles pObstacle = ObstacleIt.next();
int NumberOfEdges = pObstacle.getPoints().size();
for(int i=0; i<NumberOfEdges; i++){
//Get Edge[i];
int index = i;
Point pFirstPoint = (Point)pObstacle.getPoints().get(index);
if(i >= NumberOfEdges - 1)
index = 0;
else
index = i+1;
Point pNextPoint = (Point)pObstacle.getPoints().get(index);
// Here is where we get a bunch of angles that encode in them important info on
// the problem we are trying to solve.
double angleWithStart = getAngle(pNextPoint, pFirstPoint, pStartPoint);
double angleWithEnd = getAngle(pNextPoint, pFirstPoint, pEndPoint);
double angleWithFirst = getAngle(pStartPoint, pEndPoint, pFirstPoint);
double angleWithNext = getAngle(pStartPoint, pEndPoint, pNextPoint);
// We have accumulated all the necessary angles, now we must decide what they mean.
// If the 'start' and 'end' angles are different signs, then the first and next points
// between them. However, for a point to be inaccessible, it also must be the case that
// the 'first' and 'next' angles are opposite sides, as then the start and end points
// Are between them so a blocking occurs. We check for that here using a creative approach
// This is a creative way of checking if two numbers are different signs.
if (angleWithStart * angleWithEnd <= 0 && angleWithFirst * angleWithNext <= 0) {
return false;
}
}
}
return true;
}
Now, all that is left to do is find a method that calculates the signed angle formed by three points. A quick google search yielded this method (from this SO question):
private double getAngle(Point previous, Point center, Point next) {
return Math.toDegrees(Math.atan2(center.x - next.x, center.y - next.y)-
Math.atan2(previous.x- center.x,previous.y- center.y));
}
Now, this method should work in theory (I am testing to be sure and will edit my answer if I find any issues with signs of angles or something like that). I hope you get the idea and that my comments explain the code well enough, but please leave a comment/question if you want me to elaborate further. If you don't understand the algorithm itself, I recommend getting a piece of paper out and following the algorithm to see what exactly is going on. Hope this helps!
EDIT: To hopefully aid in better understanding the solution using angles, I drew a picture with the four base cases of how the start, end, first, and next could be oriented, and have attached it to this question. Sorry for the sloppiness, I drew it rather quickly, but this should in theory make the idea clearer.
If you have a low segment count (for instance, your example only shows 12 segments for three shapes, two shapes of which we know we can ignore (because of bounding box checks), then I would recommend simply performing line/line intersection checking.
Point s = your selected point;
ArrayList<Point> points = polygon.getPoints();
ArrayList<Edge> edges = polygon.getEdges();
for(Point p: points) {
Line l = new Line(s, p);
for(Edge e: edges) {
Point i = e.intersects(l);
if (i != null) {
System.out.println("collision", i.toString());
}
}
}
With an intersects method that is pretty straight forward:
Point intersects(Line l) {
// boring variable aliassing:
double x1 = this.p1.x,
y1 = this.p1.y,
x2 = this.p2.x,
y2 = this.p2.y,
x3 = l.p1.x,
y2 = l.p1.y,
x3 = l.p2.x,
y2 = l.p2.y,
// actual line intersection algebra:
nx = (x1 * y2 - y1 * x2) * (x3 - x4) -
(x1 - x2) * (x3 * y4 - y3 * x4),
ny = (x1 * y2 - y1 * x2) * (y3 - y4) -
(y1 - y2) * (x3 * y4 - y3 * x4),
d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (d == 0) return null;
return new Point(nx/d, ny/d);
}
This question is a bit hard to formulate so I'll start by showing this image:
I want to test if points (such as p1 and p2 on the image) are within the dotted lines that are perpendicular to the line at its limits. I know the coordinates of the points to test and the line's limits.
So for p1 it would be false, and for p2 it would be true.
What would be the most computationaly efficient way to calculate this?
I'm working with floats in Java.
This can be very efficiently done with the dot product:
This is positive if A has a component parallel to B, and negative if anti-parallel.
Therefore if you have a line segment defined by points A and B, and a test point P, you only need two dot product operations to test:
dot(A - B, P - B) >= 0 && dot(B - A, P - A) >= 0
EDIT: a graphical explanation:
The dot product can be shown to be:
Thus if θ > 90 then dot(A, B) < 0, and vice versa. Now for your problem:
In case 1, when dot(A - B, P - B) > 0 we say that P is on the correct side of the dotted line at B, and vice versa in case 2. By symmetry we can then do the same operation at A, by swapping A and B.
If the point to test (tp), together with start point (sp) and end point (ep) of the range, form an obtuse triangle and you can conclude that it is out of range.
https://en.wikipedia.org/wiki/Acute_and_obtuse_triangles
A special case would be tp is same slope as sp and ep, then you calculate the 2 distances:
distSpAndTp - distance between sp and tp
distEpAndTp - distance between ep and tp
If the sum of these 2 distances = distance between sp and ep, then tp is in range, otherwise it is out of range.
The best approach would be to first create a rectangle Rect (of android.graphics package), with x and width being the beginning and end of line, and y and height being the beginning and end of screen height.
Then use the Rect method Rect.contains(int x, int y) to check if the point coordinates lie within.
For floats, use RectF class instead.
This approach involves using 2D vectors (which you should have been using anyway, makes working in any coordinate system a lot easier) and the dot (scalar) product. It does not require any relatively expensive operations like the square root or trignometic functions, and therefore is very performant.
Let A and B be the start and end points (by point I mean a vector representing a position in 2D space) of the line segment, in any order. If P is the point to test, then:
If dot(PA, AB) and dot(PB, AB) have the same sign, the point lies outside the region (like p1 in your example).
If the dot products above have opposite signs, the point lies inside the region (like p2).
Where PA = A - P, PB = B - P and AB = B - A.
This condition can be surmised as follows:
if dot(PA, AB) * dot(PB, AB) <= 0 {
// Opposite signs, inside region
// If the product is equal to zero, the point is on one of the dotted lines
}
else {
// Same signs, outside region
}
Let's say, x1 is the beginning of the line and x2 is the end. Then ax is the dot in an horizontal plan and; y1, y2 and ay in vertical plan.
if((ax >= x1 && ax <= x2) && (ay >= y1 && ay <= y2)){ // do your work
}
There are a few answers already but there is another solution that will give you the unit distance on the line segment that the points is perpendicular to.
Where then line is x1,y1 to x2,y2 and the point is px,py
Find the vector from line start to end
vx = x2 - x1;
vy = y2 - y1;
And the vector from the line start (or end) to the point
vpx = px - x1;
vpy = py - y1;
And then divide the dot product of the two vectors by the length squared of the line.
unitDist = (vx * vpx + vy * vpy) / (vx * vx + vy * vy);
If the perpendicular intercept is on the line segment then unitDist will be 0 <= unitDist <= 1
In shortened form
x2 -= x1;
y2 -= y1;
unitDist = (x2 * (px - x1) + y2 * (py - y1)) / (x2^2 + y2^2);
if (unitDist >= 0 && unitDist <= 1) {
// point px,py perpendicular to line segment x1,y1,x2,y2
}
You also get the benefit of being able to get the point on the line where the intercept is.
p2x = vx * unitDist + x1;
p2y = vy * unitDist + y1;
And thus the distance that the point is from the line (note not line segment but line)
dist = hypot(p2x - px, p2y - py);
Which is handy if you are using a point to select from many lines by using the minimum distance to determine the selected line.
This can be solved nicely using complex numbers.
Let a and b the endpoints of the segment. We use the transformation that maps the origin 0 to a and the point 1 to b. This transformation is a similarity and its expresion is simply
p = (b - a) q + a
as you can verify by substituting q=0 or q=1. It maps the whole stripe perpendicular to the given segment to the stripe perpendicular to the segment 0-1.
Now the inverse transform is obviously
q = (p - a) / (b - a),
and the desired condition is
0 <= Re((p - a) / (b - a)) <= 1.
To avoid the division, you can rewrite
0 <= Re((p - a) (b - a)*) <= |b-a|²
or
0 <= (px - ax)(bx - ax) + (py - ay)(by - ay) <= (bx - ax)² + (by - ay)².
Imagine a Cartesian plane and every Cell object represents a point in the plane (the plane will be the maze). When building my maze, I want to figure out whether a Cell object is a vertex (the four corner points) or just a border point (any cell that is on the edge of the maze, vertex points are also border points).
I need to know so that I can add neighboring cells as neighbors of the particular cell (I am creating a graph structure with nodes). Different borders have different requirements for what cells are neighbors (a top-right vertex for example cannot have a neighbor that is y + 1 or x + 1 as it is outside of the maze, whereas a bottom-left vertex cannot have y - 1 or x - 1).
How I tried to implement this was through a slew of if statements which I feel isn't a really good practice. So I wanted to ask whether there is a better way to know what type of coordinate a point is?
Here is how I did it:
private String typeOfBorderCell(Cell cell){
if (!isBorderCell(cell)){
throw new IllegalArgumentException("cell is not a border cell");
}
double x = cell.getCoordinate().getX();
double y = cell.getCoordinate().getY();
// Vertices
if (x == 0 && y == 0){
return "bottom-left";
}
else if (x == 0 && y == height - 1){
return "top-left";
}
else if (x == width - 1 && y == 0){
return "bottom-right";
}
else if (x == width - 1 && y == height - 1){
return "top-right";
}
// Non-Vertices
else if (x == 0 && (y > 0 && y < height - 1)){
return "left";
}
// and so on for the other three non-vertex borders
}
The height/width are the size of the maze, but I had to subtract 1 as the maze coordinates start at origin (0,0) thus a 5x5 maze goes up to a max of 4 for its y and 4 for its x.
Doing this, I would get a total of 8 conditional statements (and the method that uses this method would require a switch statement with 8 cases as well). Is there a more efficient way to do this without a bunch of conditional statements?
I find enums a reasonably elegant alternative to a long set of if statements. Here's an example (using Java 8):
enum CellType {
OTHER(1, (x, y) -> true),
TOP(2, (x, y) -> y == HEIGHT - 1),
BOTTOM(2, (x, y) -> y == 0),
LEFT(2, (x, y) -> x == 0),
RIGHT(2, (x, y) -> x == WIDTH - 1),
TOP_LEFT(3, TOP, LEFT),
BOTTOM_RIGHT(3, BOTTOM, RIGHT),
TOP_RIGHT(3, TOP, RIGHT),
BOTTOM_LEFT(3, BOTTOM, LEFT);
private static final int HEIGHT = 5;
private static final int WIDTH = 5;
private final int precedence;
private final BiPredicate<Integer, Integer> test;
private CellType(int precedence, BiPredicate<Integer, Integer> test) {
this.precedence = precedence;
this.test = test;
}
private CellType(int precedence, CellType type1, CellType type2) {
this(precedence, type1.test.and(type2.test));
}
public static CellType valueOf(int x, int y) {
assert x >= 0 && x < WIDTH && y >= 0 && y < WIDTH;
return Arrays.stream(values())
.filter(ct -> ct.test.test(x, y))
.max(Comparator.comparingInt(ct -> ct.precedence))
.orElse(OTHER);
}
}
You can use this with code like CellType.valueOf(0, 4) which will return CellType.TOP_LEFT.
I prefer this idiom to sets of if statements because it puts the predicates in one place and makes them easy to identify and change.
It also will result in your 'cell type' not being a string which is a good idea if you later want to add logic to it. For example, you can avoid the switch statement you mention in your question by adding the logic to process the cell type to the enum itself. Also, comparing to strings is pretty error prone. You could change the string in one place and end up with hard to detect bugs. If you change an enum you get an immediate syntax error.
Here's a brief explanation of how it works. A BiPredicate is a functional interface that takes two ints (x and y) and returns a boolean. Each of the CellType members has a predicate that tests whether a given x and y represent a cell of that type. For the edge cell types, a lambda expression is used to provide the condition. For the vertices, the constructor takes two edge cell types and constructs a new predicate by testing if the cell satisfies both edge conditions. For example, TOP_LEFT tests if the cell is on both the top and left edges.
The valueOf method finds all cell types that satisfy a given cell then returns the one with the highest precedence. The precedence ensures that vertices are returned rather than edges. If no cell types match then it returns OTHER (for non-edge non-vertix).
I'm making an ellipsoid out of voxels, and I have an implementation, but it's not working correctly, for the past few hours I've been trying things with no success.
Here's how it works:
It draws 2D ellipses down the Z axis using the Bresenham circle algorithm
It calculates the coordinates of a circle going forward and one going side to side
It uses those coordinates as radii for X and Y
Here's what works:
Spheres are perfect
Ellipsoids are perfect when
z > x and z > y
x == y
Here's what doesn't:
Ellipsoids when x != y
Example when y > x http://postimage.org/image/gslvykrgd/
The same thing happens when x > y only flipped
I'm guessing its because I'm drawing the slices from center to front every time, but I don't know. Below is my implementation, it's a mess. I quickly cleaned it up a bit so it's understandable to some degree. Also I'm saving optimisations for later, I just want it working now.
I won't show my implementation of the circle algorithm itself, because I KNOW that it works and it would just make this question longer. So I'll explain the two functions for it instead.
private List<Integer> getSlice(int rx, int ry) gets the raw result from a run of the Bresenham circle algorithm, no symmetry needed. It returns the result as a list of the x, y results in that order.
public void generateEllipse(int z, int cx, int cy, int cz, int rx, int ry) generates an ellipse with the given information and plots down the coordinates using symmetry, these will be rendered on the screen.
ArrayList<Integer> s = getSlice(rz, rx);
ArrayList<Integer> s2 = getSlice(rz, ry);
int cap = Math.max(s2.size(), s.size());
while (s.size() > 1)
{
int x = 0;
int z = 0;
int z2 = 0;
int y2 = 0;
int i = cap - 2;
if (s.size() > i)
{
z = s.get(i);
x = s.get(i + 1);
s.remove(i + 1);
s.remove(i);
}
if (s2.size() > i)
{
z2 = s2.get(i);
y2 = s2.get(i + 1);
s2.remove(i + 1);
s2.remove(i);
}
if (x != 0 && y2 != 0)
generateEllipse(z, cx, cy, cz, x, y2);
cap = Math.max(s2.size(), s.size());
I asked a similar question a week or two back (yeah I've been having problems for that long :() and got an answer, I implemented it and it worked, but I wasn't satisfied, I want to avoid floating point numbers all together. See 3D Ellipsoid out of discrete units.
With that I was having problems with rounding off the numbers and getting uneven slices, so spheres were impossible. Ironically, now spheres are the only thing possible (other than front to back ellipses).
EDIT:
I got x > y working by adding
else if (y2 < x && ry - y2 != 0)
generateEllipse(z, cx, cy, cz, x, ry - y2);
and || r - y2 == 0 to the first test at the bottom.
I'm not too sure why that worked, I'm figuring that out now. But I'm still having problems with y > x. Anyone?
EDIT2:
Now that I look at it, it's different than the y = x ellipsoid, back to the drawing board.
EDIT3:
Last night I was thinking about this and I think I've figured it out, this isn't an answer to my own question, but I guess pointing out what I'm seeing to be wrong. I'm testing for the first list and drawing coordinates decrementally from the size of the largest list.
That's badness because the two lists aren't guaranteed equal lengths, that's a failure on my part for trying to rush an algorithm.
In the picture, you can't see, but the little ellipse is actually a few blocks away from the big ellipse. This is caused when from ellipses not being drawn, which is caused by lists not having data. The actual little ellipse big ellipse is caused because the algorithm draws two octants, both of which are stored into the list from getSlice(...).
So how can I fix this problem? I haven't implemented anything yet and probably won't for a while (it's early) but this is what my brain cranked out. Again, this is not an answer to the question, just thoughts.
I iterate for while(!s.isEmpty()) and define two new values outside the loop: incX = s.size and incY = s1.size I test to see if their z values match, if not, then I correct it. I'm thinking I'll get the values, test the largest list and if they don't match then decrement the inc value of the smallest list by two and get the old values.
I test for !s.isEmpty() because the two lists will be empty at the same time. Also drawing ellipses, I'll use whichever one z value, because, again, they both should be equal.
If that's wrong, then I guess I have this document I found to go through: http://www.cs.sunysb.edu/vislab/wordpress/pdf/398.pdf.
Thank you for anyone who viewed this (even though I didn't get any replies :(), I'm setting this answer because the problem is solved, the code is as follows:
ArrayList<Integer> s = getSlice(rz, rx);
ArrayList<Integer> s2 = getSlice(rz, ry);
boolean yMax = Math.max(s2.size(), s.size()) == s2.size();
int decX = s.size() - 1;
int decY = s2.size() - 1;
boolean done = false;
while (!done)
{
int x = 0;
int z = 0;
int z2 = 0;
int y = 0;
y = s2.get(decY--);
z2 = s2.get(decY--);
x = s.get(decX--);
z = s.get(decX--);
if (z != z2)
{
if (yMax)
{
decX += 2;
x = s.get(decX);
s2.remove(decY + 2);
s2.remove(decY + 1);
}
else
{
decY += 2;
y = s2.get(decY);
s.remove(decX + 2);
s.remove(decX + 1);
}
z = z < z2 ? z : z2;
}
else
{
s.remove(decX + 2);
s.remove(decX + 1);
s2.remove(decY + 2);
s2.remove(decY + 1);
}
if (y != 0 && x != 0)
generateEllipse(z, cx, cy, cz, x, y);
done = yMax ? s2.isEmpty() : s.isEmpty();
}
All that needs to be done now is optimisation. I'm still going to read that paper, it covers other topics that are interesting and useful for my program :).
The issue was that I was not accounting for the different sizes of each list, if a curve is less steep than the other it will have more coordinates. Z will always be the same when rx == ry. This allowed me to draw spheres and forward to back ellipsoids.
When they are not the same the z will change because the curve will be faster / slower. When this happened while I was testing for the first list it would ignore those because iteration would stop before it got to them.
The big ellipse, little ellipse was caused because they were drawn backwards, so the outer octant was drawn first which happens to have less total values.
In the near future I will put up a much more detailed answer and a much more elegant implementation. I'm just putting up this answer to let any passersby know that the problem is resolved. I want no one to ever go through the frustration I did trying to figure this whole thing out! It's amazing how the most difficult problems are caused by the silliest things.