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
Related
I have custom View for color picking and I want to restrict selector be inside circle cardview in the center.
Selector is moving by ACTION_MOVE and ACTION_UP.Coordinates change via this function:
private void updateSelector(float eventX, float eventY) {
float x = eventX - centerX;
float y = eventY - centerY;
double r = Math.sqrt(x * x + y * y);
if (r > radius) {
x *= radius / r;
y *= radius / r;
}
currentPoint.x = x + centerX;
currentPoint.y = y + centerY;
selector.setCurrentPoint(currentPoint);
}
I've also written this helper function to check if selector inside cardview and it's correctly works, but I've no idea how to restrict selector go in.
private boolean isInBounds(float x, float y) {
return Math.sqrt(x - centerX) + Math.sqrt(y - centerY) <= Math.sqrt(cardradius);
}
I really have no idea why the x and y values wont go to the drawLines function
float x, x1, x2;
float y, y1, y2;
float rad; //radius
int lines = 30; //number of lines
int colorNumber = 1;
void setup() {
background(#FFFFFF);
size (800, 600);
rad = 8;
}
void draw() {
}
This creates the three dots or vertices of the mathematical envelope
void mouseClicked() {
float x = mouseX;
float x1 = mouseX;
float x2 = mouseX;
float y = mouseY;
float y1 = mouseY;
float y2 = mouseY;
if (colorNumber == 1) {
fill(#9393ff);
ellipse(x, y, rad, rad);
} else if (colorNumber == 2) {
fill(#FF9393);
ellipse(x1, y1, rad, rad);
} else if (colorNumber == 3) {
fill(#93ff93);
ellipse(x2, y2, rad, rad);
}
}
This is supposed to draw the envelope using the coordinates of the vertices
void drawLines(int numLines) {
for (int i = 0; i < numLines; i = i + 1) {
float x = mouseX;
float x1 = mouseX;
float x2 = mouseX;
float y = mouseY;
float y1 = mouseY;
float y2 = mouseY;
float t = (float) i/(numLines-1);
float startX = x + t * (x1 - x);
float startY = y + t * (y1 - y);
float endX = x1 + t * (x2 - x1);
float endY = y1 + t * (y2 - y1);
line (startX, startY, endX, endY);
}
}
void mouseReleased() {
colorNumber++;
if (colorNumber == 4) {
colorNumber = 1;
}
println(colorNumber);
}
void keyPressed() {
if (keyPressed == true) {
background(#FFFFFF);
}
}
this last stuff just tells the code if you press a key, it will reset the backround
I understand your intention with using mouseX and mouseY to specify the coordinates of one of the 3 points of the envelope on click. The current issue is that all 3 points are being set to the same coordinate with each click. You need to introduce a variable to keep track of which coordinate to set on-click, such that only one pair is set. Then, only once all 3 coordinates are set, drawLines() can be called.
I propose the following:
Introduce 2 variables, one to keep track of which point is being modified; the other an array of PVectors (just to make it cleaner).
int index = 0;
PVector[] coords = new PVector[3];
Modify mouseClicked() to include the following:
void mouseClicked() {
ellipse(mouseX, mouseY, 8, 8);
coords[index] = new PVector(mouseX, mouseY);
index += 1;
if (index == 3) {
drawLines(lines);
}
index %= 3;
}
drawLines() becomes:
void drawLines(int numLines) {
for (int i = 0; i < numLines; i = i + 1) {
x = coords[0].x;
x1 = coords[1].x;
x2 = coords[2].x;
y = coords[0].y;
y1 = coords[1].y;
y2 = coords[2].y;
float t = (float) i / (numLines - 1);
float startX = x + t * (x1 - x);
float startY = y + t * (y1 - y);
float endX = x1 + t * (x2 - x1);
float endY = y1 + t * (y2 - y1);
line(startX, startY, endX, endY);
}
}
Finally, since your drawing on a black background, and the default stroke colour is black, use strokeColour() to change the colour of the lines so that you can see the envelope once its drawn.
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);
}
}
}
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
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);
}
}