jFreeChart: How to draw the y-axis in a line chart - java

With Java, is there any way of drawing the y-axis in a line chart with JFreeChart?
I need to show both the x-axis and the y-axis, and I already draw the x-axis with the flowing code:
LineFunction2D x_axis = new LineFunction2D(0, 0);
XYDataset xdataset = DatasetUtilities.sampleFunction2D(
x_axis, min_x-min_x/15, max_x+max_x/15, 100, "X-Axis");
xyplot.setDataset(1, xdataset);
I think it's impossible to draw the line x = 0 with LineFunction2D, which take the value of a and b of the equation y = ax + b.
Maybe there is a function to call to show the axis because I have seen a demo showing this.

There is a method in the XYPlot class:
public void setDomainZeroBaselineVisible(boolean visible);
...that will show a line at the zero value on the domain (x) axis.

Y=aX+b can be displayed using ChartFactory.createLineChart. This way, you get your series, the X and Y axis in one go.

Related

How to draw circle on JavaFX chart

I develop a JavaFX application and I am struggling with solving this problem:
I have an array of points (x, y) that I am plotting over a scatter chart, you can see in the picture below they appear as a small gray points.
Those points I'd like to enclose with the smallest circle, so for that I have a function called minimalCircle that receives an array of points and while using the Welzl's algorithm it returns the minimal enclosing circle (radius + center point)
Circle c = minimalCircle(points);
The problem occurs when I am trying to plot the circle I retrieve from the function, I make a series containing 1 point which is the center of the circle, and applying a circle shape with the radius of the circle
private XYChart.Series<Number, Number> minimalCircleSeries(Point[] points) {
XYChart.Series series = new XYChart.Series();
Circle c = minimalCircle(points);
javafx.scene.shape.Circle pointCircle = new javafx.scene.shape.Circle(c.center.x, c.center.y, c.r);
XYChart.Data data = new XYChart.Data(c.center.x, c.center.y);
data.setNode(pointCircle);
series.getData().add(data);
return series;
}
Unfortunately when it draws the circle it refers the radius size by pixels while its actually suppose to be real units on the graph, and that cause the circle in the picture below to not be the smallest enclosing circle.
I am trying to find a way to convert the radius scale so the circle will be plotted correctly or to find another way to plot a circle over a scatter chart
Thank you very much for your help !
Example image of the chart

MPAndroidChart how to draw y-axis limit line and set view point to bottom

MPAndroidChart is very awesome library.I am very thankful to.
But now, I have 3 problems.
The version I used is...
compile 'com.github.PhilJay:MPAndroidChart:v2.2.5'
And my problem is,...
Left: now -> Right: want to be
1.
How to draw limit a Y value line on line chart or bar chart?
e.g. I want to draw value y=200 line on Image.
(e.g. attached image top.shown in red)
2.
How to set viewpoint to bottom and get y-axis mint limit to bottom value?
(e.g. attached image bottom)
I want to set viewpoint to bottom.
I tried this code ,But still,there is some padding.
XAxis xAxis = mBarChart.getXAxis();
xAxis.setAxisMinValue(0);
I want to trim this padding.
*Edited
This works well. Thank you!
mChart.getAxisLeft().setAxisMinValue(0);
3.How to remove point of graph on line chart?
A line chart, the bottom image, has lots of marker.
So I want to remove these plot point.
1) You need to add a LimitLine
int maxCapacity = 100;
LimitLine ll = new LimitLine(maxCapacity, "Max Capacity");
chart.getAxisLeft().addLimitLine(ll);
You can also style the line by:
ll.setLineWidth(4f);
ll.setTextSize(12f);
2) This method may be useful:
chart.setViewPortOffsets(float left, float top, float right, float bottom);
You can read the documentation here.
3) This method is what you need:
lineDataSet.setDrawCircles(false);
Once again, its all available in the documentation.
For Kotlin
You can use LimitLine
val limitValue = 100
val nameLimitLine = LimitLine(limitValue.toFloat(), "Limit").apply{
enableDashedLine(10f, 15f, 0f) //For "- - - -"
lineWidth = 2f
}
chart.axisLeft.addLimitLine(nameLimitLine)

Bounding box doesn't follow sprite correctly. (Java)

In a Java 2D game, I have a rectangular sprite of a tank. The sprite can rotate in any angle, and travel in the direction of that angle.
This sprite needs to have a bounding box, so I can detect collision to it.
This bounding box needs to:
Follow the sprite around the screen.
Rotate when the sprite rotates.
Obviously it should be invisible, but right now I'm drawing the box on the screen to see if it works. It doesn't.
My problem is this:
When the sprite travels parallel to the x axis or y axis, the box follows correctly and keeps 'wrapping' the sprite precisely.
But when the sprites travles diagonaly, the box doesn't follow the sprite correctly.
Sometimes it moves too much along the x axis and too little along the y axis. Sometimes the opposite. And maybe sometimes too much both or too little on both. Not sure.
Could you look at my code and tell me if you see anything wrong?
(Please note: The bounding box most of the time is actually just two arrays of coordinates, each one containing 4 values. The coordinates are used to form a Polygon when collision is checked, or when the box is drawn to the screen).
Relevant code from the Entity class, the superclass of Tank:
int[] xcoo = new int[4]; // coordinates of 4 vertices of the bounding box.
int[] ycoo = new int[4];
double x,y; // current position of the sprite.
double dx,dy; // how much to move the sprite, and the vertices of the bounding box.
double angle; // current angle of movement and rotation of sprite and bounding-box.
// Returns a Polygon object, that's the bounding box.
public Polygon getPolyBounds(){ return new Polygon(xcoo,ycoo,xcoo.length) ; }
public void move(){
// Move sprite
x += dx;
y += dy;
// Move vertices of bounding box.
for(int i=0;i<4;i++){
xcoo[i] += dx;
ycoo[i] += dy;
}
// Code to rotate the bounding box according to the angle, will be added later.
// ....
}
Relevant code from the Board class, the class that runs most of the game.
This is from the game-loop.
// keysPressed1 is an array of flags to tell which key is currently pressed.
// if left arrow is pressed
if(keysPressed1[0]==true)
tank1.setAngle(tank1.getAngle()-3);
// if right arrow is pressed
if(keysPressed1[1]==true)
tank1.setAngle(tank1.getAngle()+3);
// if up arrow is pressed (sets the direction to move, based on angle).
if(keysPressed1[2]==true){
tank1.setDX(2 * Math.cos(Math.toRadians(tank1.getAngle())));
tank1.setDY(2 * Math.sin(Math.toRadians(tank1.getAngle())));
tank1.move(); // should move both the sprite, and it's bounding box.
}
Thanks a lot for your help. If you need me to explain something about the code so you can help me, please say so.
Your sprite is using doubles and your bounding box is using ints, see these declarations:
int[] xcoo = new int[4];
double x, y
And the following updates:
(double dx, dy, showing it is a double)
x += dx
xcoo[i] += dx
In the latter (the bounding box) you are adding an int to a double which causes it to drop it's decimal places as it is being cast to an integer.
Hence why they do not follow the sprite exactly, as an int can never follow a double.
To solve this you need xcoo, ycoo and corresponding methods to work with double instead of int.
Update: So Polygon only takes Integers appereantly, to solve that take a look at the following question: Polygons with Double Coordinates
You should be using Path2D.Double

Draw a curved path on Canvas?

How could I draw a quadratic curve or a trigonometric curve (such as sin(x)) on a Canvas?
Like you, I needed to draw a curved line from point(x1, y1) to point (x2, y2). I did some searching around which lead me to the Path class (android.graphics.Path). Path has numerous methods for drawing lines. Once you have created a path you use a draw method to make the actual line. The paths can be rotated, transformed, saved, and added to. There are arcs, circles, and rectangles that be drawn with this class too.
http://developer.android.com/reference/android/graphics/Path.html
Set start point of path → mPath.moveTo(x1, y1);
Set constant and end points → mPath.quadTo(cx, cy, x2, y2);
Convert path to line → canvas.drawPath(mPath, mPaint);
Here is a drawEquation() method I wrote for a Graph class - I think it may help. The basic idea to create a method that accepts an equation (which is basically just a function) like
function(x) = Math.sin(x);
and then loop through the bounds of the graph and draws small segments connecting each point. The transformContext() just inverts the canvas context so that increasing values of y go upwards and not downwards:
Graph.prototype.transformContext = function(){
var canvas = this.canvas;
var context = this.context;
// move context to center of canvas
this.context.translate(this.centerX, this.centerY);
// stretch grid to fit the canvas window, and
// invert the y scale so that that increments
// as you move upwards
context.scale(this.scaleX, -this.scaleY);
};
Graph.prototype.drawEquation = function(equation, color, thickness){
var canvas = this.canvas;
var context = this.context;
context.save();
this.transformContext();
context.beginPath();
context.moveTo(this.minX, equation(this.minX));
for (var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) {
context.lineTo(x, equation(x));
}
context.restore();
context.lineJoin = "round";
context.lineWidth = thickness;
context.strokeStyle = color;
context.stroke();
};
Most drawing APIs dont provide such functions, you will have to calculate the pixels of your desired curve in pixels and draw piece by piece on the canvas using one or more calls to the canvas API.
Use Canvas.drawPath and Path.quadTo.
I'm going to assume that you are familiar with drawing basic lines on a canvas, if not then respond back and we can delve further back. However, as far as just drawing a sine function there is a function within the Math class that has just what you need.
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html#sin%28double%29
From there you just need to pass your x variable(in radians) into the function and save it's output as a y variable. This represent a point on your graph. Now increment the x1 variable by a small amount (perhaps 1/100 of your graph, though you will need to adjust this to taste), run it through the function again and save those variables(x2 and y2) as your second point. Draw a line between these two points. Save your x2,y2 variables as x1, y1 and increment your x value again to find the third point, so on and so forth. This is not a "true" curve as it is really just a series of lines which approximate the function, a calculus approach if you will.
So:
x1 = x; // where x is some point on the x axis which you would like to start graphing at.
y1 = sin(x);
x2 = x1 + increment;
y2 = sin(x2);
//Draw a line here
x1 = x2;
y1 = y2;
//return to top, this code would obviously be in a loop in which uses increment as it's own increment with the initial value being equal to the amount you want to increment each time(let's say....5) and the "next" statement being increment = increment + 5.
There is also a GraphCanvas class which I am unfamiliar with which appears to take those same points and draw the curve between them, though I am unsure what sort of transform is being used to draw the curve and how accurate that is. Here is the Class:
http://www.java2s.com/Code/Java/Swing-Components/GraphCanvas.htm

How to position a Node along a circular orbit around a fixed center based on mouse coordinates (JavaFX)?

Im trying to get into some basic JavaFX game development and I'm getting confused with some circle maths.
I have a circle at (x:250, y:250) with a radius of 50.
My objective is to make a smaller circle to be placed on the circumference of the above circle based on the position of the mouse.
Where Im getting confused is with the coordinate space and the Trig behind it all.
My issues come from the fact that the X/Y space on the screen is not centered at 0,0. But the top left of the screen is 0,0 and the bottom right is 500,500.
My calculations are:
var xpos:Number = mouseEvent.getX();
var ypos:Number = mouseEvent.getY();
var center_pos_x:Number = 250;
var center_pos_y:Number = 250;
var length = ypos - center_pos_y;
var height = xpos - center_pos_x;
var angle_deg = Math.toDegrees(Math.atan(height / length));
var angle_rad = Math.toRadians(angle_deg);
var radius = 50;
moving_circ_xpos = (radius * Math.cos(angle_rad)) + center_pos_x;
moving_circ_ypos = (radius * Math.sin(angle_rad)) + center_pos_y;
I made the app print out the angle (angle_deg) that I have calculated when I move the mouse and my output is below:
When the mouse is (in degrees moving anti-clockwise):
directly above the circle and horizontally inline with the center, the angle is -0
to the left and vertically centered, the angle is -90
directly below the circle and horizontally inline with the center, the angle is 0
to the right and vertically centered, the angle is 90
So, what can I do to make it 0, 90, 180, 270??
I know it must be something small, but I just cant think of what it is...
Thanks for any help
(and no, this is not an assignment)
atan(height/length) is not enough to get the angle. You need to compensate for each quadrant, as well as the possibility of "division-by-zero". Most programming language libraries supply a method called atan2 which take two arguments; y and x. This method does this calculation for you.
More information on Wikipedia: atan2
You can get away without calculating the angle. Instead, use the center of your circle (250,250) and the position of the mouse (xpos,ypos) to define a line. The line intersects your circle when its length is equal to the radius of your circle:
// Calculate distance from center to mouse.
xlen = xpos - x_center_pos;
ylen = ypos - y_center_pos;
line_len = sqrt(xlen*xlen + ylen*ylen); // Pythagoras: x^2 + y^2 = distance^2
// Find the intersection with the circle.
moving_circ_xpos = x_center_pos + (xlen * radius / line_len);
moving_circ_ypos = y_center_pos + (ylen * radius / line_len);
Just verify that the mouse isn't at the center of your circle, or the line_len will be zero and the mouse will be sucked into a black hole.
There's a great book called "Graphics Gems" that can help with this kind of problem. It is a cookbook of algorithms and source code (in C I think), and allows you to quickly solve a problem using tested functionality. I would totally recommend getting your hands on it - it saved me big time when I quickly needed to add code to do fairly complex operations with normals to surfaces, and collision detections.

Categories