I need to draw a line from two points and what I did so far is using drawLine(x1,y1,x2,y2). But what I want to do is draw a line that intersects with these two points (x1,y1) and (x2,y2).
I don't want to just draw a line between them, here's an image of what I have and what I want to do:
you could use some mathematik. get the increase of your line. You should know the function
f(x) = mx + b. With your two points,which you allready got, you can calculate two other Points at the Border of your frame, and draw a line between them
You'll need to calculate the coordinates at which your line meets the boundaries of your graphics context.
If you have (x1,y1) and (x2,y2), calculate the x_a and y_a such that (x_a,0) and (0,y_a) lie on the line.
If x_a = 0, the line will start from the left edge. If y_a = 0, the line will start from the top edge.
Repeat for the bottom/right coords of the line.
Bresenham's line algorithm
private int sign (int x) {
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
public void drawBresenhamLine (int xstart, int ystart, int xend, int yend, Graphics g){
int x, y, dx, dy, incx, incy, pdx, pdy, es, el, err;
dx = xend - xstart;
dy = yend - ystart;
incx = sign(dx);
incy = sign(dy);
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
if (dx > dy){
pdx = incx; pdy = 0;
es = dy; el = dx;
} else {
pdx = 0; pdy = incy;
es = dx; el = dy;
}
x = xstart;
y = ystart;
err = el/2;
g.drawLine (x, y, x, y);
for (int t = 0; t < el; t++)//if I multiply el a line will be longer
{
err -= es;
if (err < 0) {
err += el;
x += incx;
y += incy;
} else {
x += pdx;
y += pdy;
}
g.drawLine (x, y, x, y);
}
}
Related
I want to plot a given character into a console application, shaping an ellipse.
The problem I don't know how to solve is that I only know where to draw a character once I know the angle and the radius (with Sin and Cos functions), but then I may leave gaps.
It's even more complex, because I want to "draw" a filled ellipse, not only the border.
How can I do it?
The method I want is like this:
DrawEllipse(char ch, int centerX, int centerY, int width, int height)
Just an idea: I may write a loop with an inner loop in the rectangle area of the ellipse and determine if a position is inside or outside the area of the ellipse.
This will be a reasonable approximation.
public static void DrawEllipse( char c, int centerX, int centerY, int width, int height )
{
for( int i = 0; i < width; i++ )
{
int dx = i - width / 2;
int x = centerX + dx;
int h = (int) Math.Round( height * Math.Sqrt( width * width / 4.0 - dx * dx ) / width );
for( int dy = 1; dy <= h; dy++ )
{
Console.SetCursorPosition( x, centerY + dy );
Console.Write( c );
Console.SetCursorPosition( x, centerY - dy );
Console.Write( c );
}
if( h >= 0 )
{
Console.SetCursorPosition( x, centerY );
Console.Write( c );
}
}
}
To start off, here is how to draw a filled circle (assuming a 80x25 console window). Someone else might know the maths to allow width and height parameters.
static void DrawCircle(char ch, int centerX, int centerY, int radius)
{
for(int y = 0; y < 25; y++)
{
for(int x = 0; x < 80; x++)
{
char c = ' ';
var dX = x - centerX;
var dY = y - centerY;
if(dX * dX + dY * dY < (radius * radius))
{
c = ch;
}
Console.Write(c);
}
}
}
A image (here the node named hero) is moved according to the KEY pressed in keyboard. But a method named getBoundsInLocal() is used. I can't truly understand the purpose of this method . Does it helps to get the width and height of the image ?
private void moveHeroBy(int dx, int dy) {
if (dx == 0 && dy == 0) return;
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
double x = cx + hero.getLayoutX() + dx;
double y = cy + hero.getLayoutY() + dy;
moveHeroTo(x, y);
}
private void moveHeroTo(double x, double y) {
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
if (x - cx >= 0 &&
x + cx <= W &&
y - cy >= 0 &&
y + cy <= H) {
hero.relocate(x - cx, y - cy);
}
}
This method is called by an AnimationTimer by this way:
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
int dx = 0, dy = 0;
if (goNorth) dy -= 1;
if (goSouth) dy += 1;
if (goEast) dx += 1;
if (goWest) dx -= 1;
if (running) { dx *= 3; dy *= 3; }
moveHeroBy(dx, dy);
}
};
timer.start();
I have found similar method named getBoundsInParent() . what do these two methods do & what are the differences ?
getBoundsInLocal returns the bounds of a Node in it's own coordinate system.
getBoundsInParent returns the bounds after adjusting them with depending on transforms/layoutX/layoutY.
Both can be used to determine the size, but which size you need is determined by the coordinate system you're using...
Example
Rectangle rect = new Rectangle(100, 200);
rect.setLayoutX(11);
rect.setLayoutY(33);
rect.setScaleX(2);
Pane root = new Pane();
root.getChildren().add(rect);
System.out.println(rect.getBoundsInLocal());
System.out.println(rect.getBoundsInParent());
prints
BoundingBox [minX:0.0, minY:0.0, minZ:0.0, width:100.0, height:200.0, depth:0.0, maxX:100.0, maxY:200.0, maxZ:0.0]
BoundingBox [minX:-39.0, minY:33.0, minZ:0.0, width:200.0, height:200.0, depth:0.0, maxX:161.0, maxY:233.0, maxZ:0.0]
For a untransformed ImageView you can determine the size by using the viewport's size or if this property is set to null the width/height of the image used with the ImageView
I have a program that generates a .ppm file with a bunch of black dots on it. What I want to do is to draw lines between these dots to build a graph, but instead of using some swing method I want to know if there is a way to do it by directly manipulating the .ppm's matrix.
I assume it would require some nested loops, but how would I identify which positions I need to change to create the line between two dots?
(for those who don't know, a .ppm file is basically a giant matrix with 3 RGB values for each of it's positions, allowing you to draw stuff pixel by pixel)
Single pixel thickness:
void drawline(Color pixels[][], int width, int height,
int x1, int x2, int y1, int y2, Color line)
{
int dx = x1 - x2;
int dy = y1 - y2;
if (dx != 0 || dy != 0)
{
int n = Math.Max(Math.Abs(dx), Math.Abs(dy));
double inv = 1.0 / (double)(n + 1);
double dxdn = (double)dx * inv;
double dydn = (double)dy * inv;
double x = (double)x1, y = (double)y1;
for (int i = 0; i <= n; i++)
{
int xi = (int)x, yi = (int)y;
if (xi >= 0 || xi < width || yi >= 0 || yi < height)
pixels[yi][xi] = line;
x += dxdn; y += dydn;
}
}
}
(NB this is in C# syntax; you may need minor changes to convert it to Java)
I am trying to flip a square image inside a picture with user input variables. After running the code nothing happens at all. In other attempts I was able to make a small thin rectangle appear. How do I fix this?
public void flipHorizontal (int x, int y, int size)
{
int half = size / 2;
int x1 = x - half;
int y1 = y - half;
int x2 = x + half;
int y2 = y + half;
Pixel sourcePixel = getPixel (x1,y1);
Pixel targetPixel = getPixel (x1, y1 + half);
//loop through columns
for (x = x; x < x2; x++)
{
//loop from 0 to before mirror point
for (y = y; y < y2 + half; y++)
{
Color friend = sourcePixel.getColor();
sourcePixel = getPixel (x1,y1);
targetPixel = getPixel (x1, y1 + half);
targetPixel.setColor (friend);
}
}
}
So I'm supposed to make a program where a ball bounces around a drawingpanel for 10 seconds. The ball has to bounce off the sides of the panel if it hits them. Right now when the ball hits the bottom panel instead of bouncing it appears in the middle of the screen and moves in the opposite direction until it hits the top and disappears.
I'm pretty sure the problem is in this part of my code...
(Earlier in the code I declared x to 1, y to 250, dx to 1, and dy to 1)
//Changes dirction
public static int newDirection1(int x, int dx, int size){
if (x < 0 || x > 500 || (x + size) < 0 || (x + size) > 500) {
dx *= -1;
return dx;
} else {
return dx;
}
}
//Changes direction
public static int newDirection2(int y, int dy, int size){
if (y < 0 || y > 500 || (y + size) < 0 || (y + size) > 500) {
dy *= -1;
return dy;
} else {
return dy;
}
}
//Moves ball one step
public static void move(Graphics g, Color color, int size, int x1, int y1, int x2, int y2){
g.setColor(Color.WHITE);
g.fillOval(x1, y1, size, size);
g.setColor(color);
g.fillOval(x2, y2, size, size);
}
//Pauses for 10ms
public static void sleep(int millis, DrawingPanel panel){
panel.sleep(millis);
}
public static void bounceLoop(DrawingPanel panel, Graphics g, Color color, int size, int x, int dx, int y, int dy, int millis){
int x1 = x + dx;
int x2 = x + dx;
int y1 = y + dy;
int y2 = y + dy;
for (int i = 0; i < 1000; i++) {
x1 = x + dx * i;
x2 = (x + dx * i) + dx;
y1 = y + dy * i;
y2 = (y + dy * i) + dy;
dx = newDirection1(x2, dx, size);
dy = newDirection2(y2, dy, size);
move(g, c, size, x1, y1, x2, y2);
sleep(millis, panel);
}
}
}
in the loop don't use:
x1 = x + dx * i
use
x1 = x1 + dx
(same for y)
because whenever dx is going to change, and multiply by -1, instead of continuing from where it was, and go to the other direction, it's going to continue from the other side of your panel, or a point that is really off.
Also a few things that could possibly fix the coding:
1- you don't need a dx parameter for your getNewDirection, you only need the coordinate.
2- the boundry conditions may give you errors, give it a small offset that can't be visible to the naked eye to avoid errors with creating objects outside the created panel or whatever you are using