I need to plot a polynomial given a start point and an end point. I've looked at using the paincomponent to do do it, but I'm getting confused because the origin is in the top left corner and I need my grid lines to be dynamic.
How do I make it so I can create a dynamic scale and what java class is best used for plotting a function?
For example if the user were to enter -2 2 x^2 the plotter would need to create a grid that goes from -2 has 0 in the middle and 2 on the right for the x coordinates. However if the user enters x^3 we have negative coordinates in the y plane and I'll need to slide the line containing the x coordinates up to accomidate.
Thanks!
The way I think you could do this(and I may be wrong) is to draw the y-line and x-line of your graph, and label the values for x and y using drawString at the correct position.
To illustrate this I did this example for you:
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Point2D.Double from = new Point2D.Double(300, 100);
Point2D.Double to = new Point2D.Double(300, 300);
Line2D.Double line = new Line2D.Double(from, to);
g2.draw(line);
Point2D.Double from2 = new Point2D.Double(150, 200);
Point2D.Double to2 = new Point2D.Double(450, 200);
Line2D.Double line2 = new Line2D.Double(from2, to2);
g2.draw(line2);
g2.drawString("-1", 290, 215);
}
The drawString method would draw "-1" below 0. So you could use the same thing to draw -2 below -1, etc.
I know this sounds inefficient, but it's the only way I can think of.
Hope someone else will have a better solution for you.
It shouldn't be too difficult to transform the y-coordinate if you know the size of area you want to paint to. But to be honest, why don't you use one of the plotting libs like JFreeChart, ...?
Related
I am sitting with my son, trying to implement a school homework. The task is to write a program that draws X and Y axis and functions, e.g. Sinus or x² into a awt.Canvas. The issue we are struggeling with is that the root, Point(0,0) of the Canvas is designed to be in the upper left corner. The cartesian coordinate system that we have to have, has the origin in the lower left corner. So we tried to apply a AffineTransform and translate in the paint method of the Canvas, which in essence works but has two issues:
1st, for whatever reason the related translation doesn't really moves the origin to the bottom but about 100 pixels to high (see image).
When we put in the below code an additional offset of about 100 pixels with tx.translate(0, -(getHeight()+100)); it looks about right.Same issue seems to be true on the right side. There is also unintended free space. We colored the background of the containing Frame in black and the Canvas in grey to exclude an artefact between these two containers. But doesn't seem to be the case.
2nd, and that concerns us more, is the side effect that all text, when e.g. adding values to the axes will also be fliped, as you see at our debug info in the plotAxes method.
Here is what we have done so far..
public class PlotterView extends Canvas {
protected int MINWIDTH = 500;
protected int MINHEIGHT = 400;
Point[][] lines;
public PlotterView() {
Dimension dim = new Dimension(MINWIDTH, MINHEIGHT);
setPreferredSize(dim);
setBackground(Color.LIGHT_GRAY);
}
protected void plotAxes(Graphics2D g) {
Color defaultColor = g.getColor(); // save to restore defaults in the end
int originX = 5; // x origin of both axes - shift right
int originY = 5; // y origin of both axis - shift up
// Debug info to compare
g.setColor(Color.BLACK);
g.drawString("X: " + originX + "; Y: " + originY, originX, originY);
// X-Axis
g.setColor(Color.RED);
g.drawLine(originX, originY, MINWIDTH-20, originY);
g.drawLine(MINWIDTH-20, originY, MINWIDTH-30, originY-5);
g.drawLine(MINWIDTH-20, originY, MINWIDTH-30, originY+5);
// Y-Axis
g.setColor(Color.BLUE);
g.drawLine(originX, originY, originX, MINHEIGHT-20);
g.drawLine(originX, MINHEIGHT-20, originX-5, MINHEIGHT-30);
g.drawLine(originX, MINHEIGHT-20, originX+5, MINHEIGHT-30);
// Restore defaults
g.setColor(defaultColor);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -getHeight());
g2.setTransform(tx);
plotAxes(g2);
}
}
One alternative would be to implement a method that "adjusts" every x-value from upper left to lower left, but that feels like a kind of botch job.
How to solve this right? Thank you in advance
Thank you for the feedback. I figured out that issue number 1 is born by using the AffineTransform. If I apply the scale and translate on the g2 directly the issue disappears.
Issue number 2 is a conflict of interest. We couldn't manage to find and apply the "three magic lines of code" (or whatever number would be required) to from thereon programm in a cartesian coordinate system. Instead we are converting all y-values into this top-level-origin coordinate system. Makes the code hard to read, but with the help debugging we managed.
When creating a Circle object with JavaFX and is using Graphic Context to stroke the Oval I want it to expand outside of the first created oval. So it will be larger than the last one and go around the first if that makes sense to you.
Here is a picture of what it is now:
Here is a picture of what I would like it to do. As well as the fillOval method too:
Canvas canvas = new Canvas(400, 200);
GraphicsContext gc;
gc = canvas.getGraphicsContext2D();
gc.setLineWidth(1);
Circle c = new Circle();
canvas.setOnMousePressed(e ->
{
c.setCenterX(e.getX());
c.setCenterY(e.getY());
});
canvas.setOnMouseDragged(e ->
{
c.setRadius((Math.abs(e.getX() - c.getCenterX()) + Math.abs(e.getY() - c.getCenterY())) / 2);
gc.strokeOval(c.getCenterX(), c.getCenterY(), c.getRadius(), c.getRadius());
}
});
For some reason it begins at the left corner. I cant understand why it does that. It doesnt make any sense to me.
It seems to me your assumption on how strokeOval is defined is wrong.
public void strokeOval(double x, double y, double w, double h)
The parameters define a bounding rectangle and not, as you assume, a center and a radius. Just have a look at the documentation for more details.
So I have this program to test the possibility of an object to slide down in a ramp given its friction, object mass and ramp angle. However I need to animate the box if the force is positive. Just a simple animation moving the box from that point to the end of the ramp. But I can't. Please help
private void drawTransform(Graphics g, double modifier) {
// redtowhite = new GradientPaint(0,0,color.RED,100, 0,color.WHITE);
Rectangle rect = new Rectangle(130,350, 350, 15);
Rectangle box = new Rectangle((int) (rect.getX()+300), 300, 50, 50);
AffineTransform at = new AffineTransform();
at.rotate(-Math.toRadians(modifier), rect.getX(), rect.getY() + rect.height);
// Transform the shape and draw it to screen
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.DARK_GRAY);
// g2d.fillRect(0, 0, 350, 600);
g2d.fill(at.createTransformedShape(rect));
g2d.draw(at.createTransformedShape(box));
}
Screenshot:
If all you want to do is move the box, this can be done by simply updating it's X position. You should be able to manipulate the rectangle's X position directly using something like "box.x++". Alternatively you could create a variable and reference that to provide the initial X co-ordinate, then updating that variable will "move" the box. One issue is this will only move the box along the X axis, hence you will also need some kind of constant downward force acting as gravity. This is easy to achieve, just minus the box's Y position value when it is not colliding with the ground, or your ramp.
Another approach is velocity based movement using vectors, however you mentioned that the animation should be simple. If you do want a smoother animation velocity based movement will provide this but you will need to perform a little research first.
So, my situation is that I am drawing a lot of concentric circles, and to make this more efficient I am wanting to only draw 1/8 of the circle and then mirror/rotate the rest of the drawing. To be clear, let's say I have the following code:
for(int i = 0; i < end; i++) {
posX = calcX(i);
posY = calcY(i);
length = calcLength(i);
g2.fillArc(posX, posY, length, length, 0, 45);
}
// mirror/rotate 7 times...
Is this even possible? I know you can for an Image, but this seems a lot more tricky.
Thanks in advance for your help!
EDIT: g2 is a Graphics2D object.
EDIT 2: So, lets say I have the following slice. Is there a way to take this whole slide (drawn with "fillArc") and copy it 7 times and make a full circle:
EDIT 3: Fixed code to match what I'm saying.
I think g2 is a Graphics2D object?
Then you can use
g2.setTransformation();
And use a AffineTransformation to rotate the image. Altough it should be more efficient to use
g2.drawOval(...);
in order to draw circles.
Ok dear folks, i've got this question and i don't really know a certain way to solve it.
I'm doing like a "Paint application" in java, i know everything is ready, but I need to paint the shapes with Computer Graphics Algorithms.
So, the thing is, once the shape is painted in the container how could I convert it like sort of an "Object" to be able to select the shape and move it around (I have to move it with another algorithm) I just want to know how could I know that some random point clicked in the screen belongs to an object, knowing that, I would be able to fill it(with algorithm).
I was thinking that having a Point class, and a shape class, if i click on the screen, get the coordinates and look within all the shapes and their points, but this may not be very efficient.
Any ideas guys ?
Thanks for the help.
Here is some of my code:
public class Windows extends JFrame{
private JPanel panel;
private JLabel etiqueta,etiqueta2;
public Windows() {
initcomp();
}
public void initcomp()
{
panel = new JPanel();
panel.setBounds(50, 50, 300, 300);
etiqueta = new JLabel("Circulo Trigonometrico");
etiqueta.setBounds(20, 40, 200, 30);
etiqueta2 = new JLabel("Circulo Bresenham");
etiqueta2.setBounds(150, 110, 200, 30);
panel.setLayout(null);
panel.add(etiqueta);
panel.add(etiqueta2);
panel.setBackground(Color.gray);
this.add(panel);
this.setLayout(null);
this.setVisible(true);
this.setSize(400,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
g2d.setStroke(new BasicStroke(2));
dibujarCirculo_bresenham(g2d, 50, 260, 260);
dibujarCirculo_trigonometrico(g2d, 50, 130, 200);
}
/*This functions paints a Circle*/
public void dibujarCirculo_trigonometrico(Graphics g,int R,int xc,int yc)
{
int x,y;
for (int i = 0; i < 180; i++) {
double angulo = Math.toRadians(i);
x = (int) (Math.cos(angulo)*R);
y = (int) (Math.sin(angulo)*R);
g.drawLine(x+xc, y+yc, x+xc, y+yc);
g.drawLine((-x+xc), (-y+yc), (-x+xc), (-y+yc));
}
}
I assume that any image is a valid (isn't constrained to a particular set of shapes). To get an contiguous area with similar properties, try using a flood fill.
To colour in or move a particular shape around, you can use flood fill to determine the set of pixels and manipulate the set accordingly. You can set a tolerance for similar hue, etc so that it's not as rigid as in Paint, and becomes more like the magic selection tool in Photoshop.
There are a couple of approaches to take here depending on what precisely you want.
1) is to have objects, one for each drawn thing on screen, with classes like Circle and Rectangle and Polygon so on. They would define methods like paint (how to draw them on screen), isCLickInsideOf (is a click at this point on screen contained by this shape, given size/position/etc?) and so on. Then, to redraw the screen draw each object, and to test if an object is being clicked on ask each object what it thinks.
2) is, if objects have the property of being uniform in colour, you can grab all pixels that make up a shape when the user clicks on one of the pixels by using a floodfill algorithm. Then you can load these into some kind of data structure, move them around as the user moves the mouse around, etc. Also, if every object is guaranteed to have a unique colour, you can test which object is being clicked on by just looking at colour. (Libraries like OpenGL use a trick like this sometimes to determine what object you have clicked on - drawing each object as a flat colour on a hidden frame and testing what pixel colour under the mouse pointer is)