Drawing a line with asterisks on the console - java

How can I draw a line with asterisks on the console? I will accept the coordinates from the user (x1,y1), (x2,y2).

Assuming a reasonably capable console, you can combine the ANSI escape code for Horizontal and Vertical Position (HPV) with Bresenham's line drawing algorithm.
Addendum: As this is homework, Bresenham's algorithm is overkill. Because it's a common assignment, you might look at how others have approached the problem. In addition, you can edit your question to include your code and other details about the assignment.

I would first write a method that prints out a star at a given x-coordinate. Such as given an x coordinate 7, print out 6 spaces and then an asterisk.
I would then determine the slope (y2-y1)/(x2-x1) make sure that x1 is the point with the higher y value(on a higher line, but this might be a lower actual value). Then increment the x value by the slope on each iteration through a loop
for(i = y1; i<=y2;i++)
asteriskprintfunction(x1+(slope*i));
that should do it.
edit:
had accidentally made the loop with x values and since you want to go line by line, you should use the y values. also clarified how to pick which point is (x1,y1)

Related

Java bidimensional array divided by major diagonal

I'm using a bidimensional array in Java for a checkers game that is like Tile[8][8] to represent my board.
That bidimensioanal array (the board) can be divided diagonally by its major diagonal like this:
The positions that correspond to this are: (0,0); (1,1); (2,2); (3,3); (4,4); (5,5); (6,6); (7,7).
Given two pairs of coordinates (row_start, col_start) and (row_final, col_final), I need to understand if each other are in opposite sides (or right on the diagonal itself) of that diagonal line.
Thank you in advance.
This will help you see the pattern between x and y:
To check whether given x,y coordinates fall on the diagonal line from North-West to South-East:
public boolean isOnDiagonalLineNW_SE(int x1, int y1){
return x1 == y1;
}
To check whether it is above the diagonal line:
public boolean isAboveDiagonalLine(int x1, int y1){
return y1 > x1;
}
To check whether it is below the diagonal line:
public boolean isBelowDiagonalLine(int x1, int y1){
return x1 > y1;
}
For a point (x, y), test if x > y.
When coordinate x is equals to y, the point is over the diagonal. If x > Y, he is on the top triangle, else, he is in the low one...
If you test it for both points (start and final), you can check the situation (if they are in opposite side or in the same, for instance)...
It appears that there is a simple repeating pattern in this concept, that is, all integer numbers that repeat in both the column as well as the row are "on the diagonal"... because it's a square. The minute this is no longer a square, this calculation becomes useless and so it is absolutely not the "best" solution for this problem.
You could just do really simple checks like...
if(row_start == col_start || row_final == col_final). This shows you numbers that are ON the diagonal line. Once you know this information then you could say if(row_start > col_start) (then you know it's to the right of the diagonal) or if(row_start < col_start) (then you know it's to the left of the diagonal line)
If the board isn't a square or "could" be a rectangle, but cannot change after run-time, then a more dynamic approach could also be taken. First you could "discover" the diagonal you want to be remembered as a token placement on the board and store it in an array to remember it. You would use a loop to start at 0,0 and quickly iterate the length and width of the board to find the places you want to be the new diagonal. As you discover each position you would record the values into your array (a 2D array would work but I would suggest an array of objects maybe even enums so that the row/col of each can easily be stored). Now that you know your new diagonal line and have it stored in memory its incredibly easy to verify now if the line is on, above, below or beside the diagonal line. This variable should last the length of the view with this board on it and become a core application state variable in order to maintain a focus on this diagonal line for future rules and whatnot.

Intersection of Line and Segment in Java

Essentially I need to return a boolean if a line and a line segment intersect. For the line the information I have is the slope, xy coords for a random point, and xy for a y intercept. For the line segment I have the line segment and the two end point xy coordinates. Any ideas?
The line through (Xr, Yr) with slope S has equation D(X, Y):= (Y - Yr) - S (X - Xr) = 0.
Just check that D(Xa, Ya) and D(Xb, Yb) have opposite signs.
Implementing this is not terribly difficult, it's the conceptual part that seems the most difficult. I might code something up for this for fun later but this should be enough to get you started. Also, note that this is might be a really bad way to solve it (time/space wise) but it will definitely work.
If you want to find a good solution, use convert the line to vectors and use the implementation in the answer in the link below all my text.
Calculate the slope of the second line. If it's equal to the first, they're parallel and never intersect.
Calculate where the two lines would intersect if they do intersect. They can only intersect at one point. This is how you would check if they will intersect:
Find 2 distinct coordinates for each line at some arbitrary point.
Determine the distance between the two lines at each point.
Whichever point results in a smaller distance between the lines represents the direction you need to travel in to move closer to the intersection.
Keep checking the distance between the two lines until they start increasing (which means you need to reverse the direction again) or until the distance is 0. The xy coord at distance = 0 is the intersection.
If the x-value of the point where the two lines intersect is in between the two x-values for your line segment, the line and line fragment intersect.
This should be easier for you because you already have two xy coords for the first line and two end point coordinates for the line segment.
Check this answer out for a really nice solution with some examples in the comments: https://stackoverflow.com/a/565282/2142219

Java - Detect Straight Lines with given Coordinates

ADDED INFO:
I'm using the inside of a square as an arena. On start up, the square spawns in a random position, and rotation, and I can't access any of the squares attributes.
I then have a moving object inside the square, that I'm building AI for, and I want the object to 'learn' where the arena walls are. Every time the object bumps into a wall, I get a touch return, so I know if its hit or not. I'm using this to map the global position of where the object hit the wall and save it ... After 3 hits on the same wall, I want to mathematically 'draw a straight line' down those dots which will represent the arena walls - with this, I can tell my object not to go near these coordinates.
The reason for 3 dots? Well, if the object hit one side of a wall, then was to hit another side of a wall, I will have a line drawn from one side to another, giving false data about where the wall is.
If Java sees three (or more) dots inline, it knows that the object has hit the same wall (either being further up or so).
CONTINUED:
I'm trying to map out lines with given coordinate data. Basically I have an array that holds X and Y coordinates, and I want to be able to mathematically detect if it's they make up a straight line (give or take a few pixels). (The coordinate are a boarder of a square)
For example, the array might be like this:
[x0][y0] - 1,1
[x1][y1] - 2,2
[x2][y2] - 5,5
Which will present a diagonal line of on side of the square, like so:
But sometimes I might get one coordinate of one side of the square, and then another side, all mixed up (and not necessarily on a 90 degree angle either!). So I want to be able to run through the array, and detect what coordinates make a line (or the boarder side of the square), like so:
So right now, I have a 2D array:
private double wallLocations[][] = new double[10][10];
and a while loop that doesn't do the job. I don't really know where to even start with this one:
for(int r = 0; r < wallIndex; r++){
for(int c = 0; c < wallIndex; c++){
int index = 0;
if(wallLocations[r][index] == wallLocations[r][c] && wallLocations[r][index + 1] == wallLocations[r][c] &&
wallLocations[r][index + 2] == wallLocations[r][c]){
System.out.println("***** Wall Here! *****");
index++;
}
}
}
---- UPDATE ----
Heres a better example in what I'm looking for. The red dots represent the coordinates coming in, a line is detected when 3 or more dots line up (if it was 2 dots, then it would detect any and ever dot) ... You notice that this is starting to look like the boarder of a square?
This seems to essentially be a clustering problem, and those can be generally pretty hard. Part of a reason clustering is hard is that there may be more than one applicable mapping.
For instance (please forgive my bad ascii art):
X X X
X X X
X X X X
could be mapped
X---X---X X X X
\ / \ / \
X---X---X or X X X
/ \ / \ \
X---X---X---X X X X X
I've seen uses of the Expectation Maximization algorithm using mixed Gaussian models used for this kind of thing (when there were a lot of points but only a few expected lines) but you generally do have to give that algorithm a definite number of clusters, and while its results are good, it's a pretty slow algorithm requiring possibly many iterations. I'm kinda thinking I've seen something generally faster that's some sort of image processing algorithm but I'd have to do some research.
I'm kinda wondering about something where you find y=mx+b for every pair of points and them sort them over m and b. It might be advantageous to find the angle θ in [0,pi) for each pair instead and sort over the angles instead of m, or maybe beter cluster by cos(2θ)-- the point of that being that the group of lines {y= -0.0001x + 1, y =1, and y=0.0001x + 1} are very similar, the group of lines {y= -10000x + 10, x = 0, and y=10000x - 10} are also very similar, but cos(2θ) should put them as far apart as possible, as any two pairs between each group should be nearly perpendicular.
Also note, in my example, b doesn't matter much for the lines nearly perpendicular to the x axis, so "b" might not be so useful for direct clustering.
I guess, perhaps, there may be some utilizable measure of "distance" between two lines, I'm just not sure what it would be. Two lines that are nearly parallel that converge "on screen" (where the points generally are) might ought to be considered "closer" than if they converge a trillion units a way from the screen--or should they? Purely speaking, three lines can never pairwise be considered closer to one another if none of them are parallel (If they're on a plane, they'll all meet somewhere), but intuitively, if we have two lines that are generally one inch apart in the area we're concerned with, we'd pick that pair as closer over two identically pointed lines that are a mile apart in the area of concern. That makes me think maybe the area between the lines,as bound by our area* ought to be used as a metric.
Sorry, I'm not sure how useful all that brainstorming might be, but it might put a different light on things.
Edit: You know what, a better answer might possibly be found by researching this:
http://en.wikipedia.org/wiki/Hough_transform
Edit II & III:
Ok,... the situation you've just described is a lot simpler and less generic (although, to be honest, I think I misread your initial query to be more generic than it really was).
You've got 4 candidate walls. Let your AI bounce around until it finds three co-linear points. That should be a simple test of combinations. Assign those three points a wall. Depending upon what other points you have, you actually might be able to determine or at least estimate the other three walls (assuming it is a square). If you have 5 points with 3 on separate walls, you should be able to calculate the distance between walls, and therefore the likely position of the 4th wall. To test if the other two points are on separate walls, make sure they're pair-wise not co-linear with a line perpendicular or parallel to the line defined by your wall, or if they are on a line parallel, test to see if the distance between them is less than the distance between the wall and them (if that's the case, they're on the wall opposite of the first candidate wall). Given that they are on separate walls, either one is facing the first found wall, or they're on walls perpendicular to that wall. Either way you can find the lines defining the walls with a little tricky geometry.
(and actually, to determine the dimensions, I don't think you need to even test to see that you have 3 co-linear points... I think you just need to test to see that you've made two turns... which takes 4 points minimum but likely more if you're unlucky. two of the points would have to be determinable to be on a different wall from the other two, which means really big bounces!)
There's a bit of math involved, and I'm a bit too tired to explain further tonight, and I don't know how much of the geometry of points around a square you want to take advantage of, because you wouldn't be able to use those properties in a more general case, so I'll leave it at that, and maybe also remove some of my other previous brainstorm cruft later.
If you have two points you can calculate the slope of the connecting line with Math.atan2.

scaling operations on a 2D graph, size of output sequence must not be the same as input

I am looking for an open source package (preferably Java but R or other languages would be ok too) that provides these 2 functions
1) points output_seq[] SCALE(points input_seq[], double factor)
In other words a sequence of doubles (x1,y1), (x2,y2)... is given as input that represents a graph (each point is connected to the next by a straight line) and a scaling factor is given. Then it returns a similar sequence as output. The catch is that the output sequence may have fewer or more elements than the input. For example, if I request magnification by a factor of 2.012 then the output sequence may have twice as many elements as the input. The scaling factor should be a double, not an integer.
Lastly, it's important to return the output sequence as points (doubles), I have very little interest in the actual drawing on a screen beyond proving that it does the right thing.
2) points output_seq[] ROTATE(points input_seq[], double angle)
same as above, except there is no scaling but just rotation, the angle is from 0 to 359.9999 and is given in radians.
The size of the output is always the same as the size of the input.
Again the emphasis is on getting the output sequence as doubles, not so much on the actual drawing on a screen.
If you know the right terminology I should have used then let me know.
Thank you so much.
In Java, Path2D is suitable for 2D floating point coordinates. The lineTo() method will add straight lines to the path. Because Path2D implements the Shape interface, rotate and scale are possible via createTransformedShape(). One approach to interpolation, using PathIterator, is shown here.

How can I reliably move a character between an array of points?

I currently have an array of points (x,y) from the result of an A* pathfinding function. This array is set up so that the first index is the point closest to the character and the next one is the next point that needs to be traveled in the path.
These points are on a grid (currently 8 pixels between each point on the grid, this is changable.)
My current strategy is to move the character to the first point, when he has arrived at that point, then move to the next one, simple as that.
I move to the first point by creating a vector from the character to that point and find how far it is. Then I find the angle and move in that direction.
// How the character is moved
double xMove = Math.cos(charAngle * (Math.PI / 180)) * 0.1 * delta;
double yMove = Math.sin(charAngle * (Math.PI / 180)) * 0.1 * delta;
x += xMove;
y += yMove;
absVx -= Math.abs(xMove);
absVy -= Math.abs(yMove);
absVX and absVy store the absolute distance left to go and it is decremented after each movement. If they are both below or equal to zero, then we have reached our destination, we remove it from the array and recalculate everything again with the next point.
I have two issues.
Sometimes the character skips over a point and then he just travels forever. This is most likely due to the delta the game engine adds to the movement (slick) and the character moves too far, I'm not sure on this one though.
This works fine when I single click the destination but what I need is to be able to hold down the mouse button. Currently the character just "stands still" on the first point if I hold the mouse down.
I had an idea for a solution to the 2nd problem but I'm not sure it's a good one. It is to store the location you want to go from the last mouse click but not actually calculate it untill you have passed the point you were moving to.
So, I hope someone really smart and fun can have a little conversation with me about this :D
About 1, the most probably cause is a rounding issue; adding these xMove / yMove introduce an small error and the x and y never really get the value of the destination, so the algorithm keeps running.
Ways to solve:
1 Define "reaching destination" so it allows a degree of error
2 Find out how many "ticks" will take to the character to arrive to destination, when it "arrives", force the character position to its destination (this allows to correct accumulated error).
Also, I would go back to graphics theory. IIRC, your path moving between points should be equal to Bresenham's line drawing algorithm. For later stages, your character could follow a B-Spline along his path.

Categories

Resources