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);
}
}
}
Related
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
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
So to my eyes this code looks fine but I can't really tell is it good because it freezes the whole painting loop. it worked fine before without all that offset hassling.
int offsetX = 0;
int offsetY = 0;
for(int y = 0, canvasY = offsetY + y, x = 0, canvasX = offsetX + x; canvasY < mapHeight + offsetY && canvasX < mapWidth + offsetX; y++, x++) {
int tileToPaint = canvasX + (canvasY * mapWidth);
tileObject = getObject(tileToPaint);
int locationX = tileSize * x;
int locationY = tileSize * y;
draw(tileObject, locationX, locationY);
}
The problem is that it's infinite.
Your condition:
canvasY < mapHeight + offsetY && canvasX < mapWidth + offsetX
Will always be false, since none of those values ever change.
What I believe you want to do is to call these after the draw call.
canvasY = offsetY + y;
canvasX = offsetX + x;
I am trying to convert some (ugly looking) code into functions, such that everything is better managable. However I have come to a problem, current code:
int red = card.getColor().getRed();
int green = card.getColor().getGreen();
int blue = card.getColor().getBlue();
Color color = new Color(red, green, blue);
int width;
int height;
int xOffset;
int yOffset;
int border;
//Whole card
width = CARD_DIMENSION.width;
height = CARD_DIMENSION.height;
xOffset = 0;
yOffset = 0;
border = 5;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int dx = Math.min(x, width - 1 - x);
int dy = Math.min(y, height - 1 - y);
if (dx < border || dy < border) {
g2d.setColor(new Color(red, green, blue, 255 - Math.min(dx, dy)));
}
else {
g2d.setColor(new Color(red, green, blue, 192 - Math.min(dx, dy)));
}
g2d.drawLine(x + xOffset, y + yOffset, x + xOffset, y + yOffset);
}
}
I would have to copy this everytime I want to draw some new rectangle. At first sight it isn't hard to put it in a function, however these lines:
if (dx < border || dy < border) {
g2d.setColor(new Color(red, green, blue, 255 - Math.min(dx, dy)));
}
else {
g2d.setColor(new Color(red, green, blue, 192 - Math.min(dx, dy)));
}
They make it hard since I use dx and dy there.
Now I have come up with a proposed solution which I would want to use with anonymous inner classes and overriding the two functions:
private abstract class CustomRectangle {
protected final int width;
protected final int height;
protected final int xOffset;
protected final int yOffset;
protected final int borderSize;
public CustomRectangle(final int width, final int height, final int xOffset, final int yOffset, final int borderSize) {
this.width = width;
this.height = height;
this.xOffset = xOffset;
this.yOffset = yOffset;
this.borderSize = borderSize;
}
abstract void inBorder();
abstract void outBorder();
public void draw(Graphics2D g2d) {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int dx = Math.min(x, width - 1 - x);
int dy = Math.min(y, height - 1 - y);
if (dx < borderSize || dy < borderSize) {
inBorder();
}
else {
outBorder();
}
g2d.drawLine(x + xOffset, y + yOffset, x + xOffset, y + yOffset);
}
}
}
}
But I am still afraid that it will be hard if not impossible to put in a formula using dx and dy (two local variables to the for loops).
I would appreciate it if anyone has any suggestions on either the general problem or on my own approach, because having several codeblocks that do essentially the same is just not acceptable.
Regards.
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);
}
}