JFreeChart BarChart - Category Markers - java

I'm creating a BarChart that contains multiple frequency bands as the category axis. What I want to do is to show a visible grouping of these frequency bands:
For example:
Freq x1 ~ Freq x2 = Band y (so the domain axis has values for category x1, x1.1, x1.2 till x2)
Freq x3 ~ Freq x4 = Band z (x3, x3.1 .....x4)
What I want to do is show markers for Band Y and Band Z in the graph. Note that based on the dataset that I may get, not all categories may be present. Say, for the 1st example, I've got values for x1 to x1.6 and so the band marker would be from x1 till x1.6
I hope I could explain my requirement. Is this possible in JFreeChart? If so, how may I go about achieving this?
Just to clarify a little more, here's a picture of something that I want to achieve:

Do your Bands corresponded to Categories? If they do you can use a CategoryMarker
CategoryMarker marker = new CategoryMarker("Category 3");
marker.setLabel("Band Y");
marker.setPaint(Color.red);
marker.setOutlinePaint(Color.red);
marker.setAlpha(0.5f);
marker.setLabelAnchor(RectangleAnchor.TOP);
marker.setLabelTextAnchor(TextAnchor.TOP_CENTER);
marker.setLabelOffsetType(LengthAdjustmentType.CONTRACT);
plot.addDomainMarker(marker, Layer.BACKGROUND);
I can't work out how to create a Mutli-CategoryMarker but you can create something similer by
adjusting the ItemMargin and CategoryMargin and adding additional CategoryMarkers
{
CategoryMarker marker = new CategoryMarker("Category 2");
marker.setLabel("Band X");
marker.setLabelAnchor(RectangleAnchor.TOP);
marker.setLabelTextAnchor(TextAnchor.TOP_CENTER);
marker.setLabelOffsetType(LengthAdjustmentType.CONTRACT);
plot.addDomainMarker(marker, Layer.BACKGROUND);
}
{
CategoryMarker marker = new CategoryMarker("Category 3");
plot.addDomainMarker(marker, Layer.BACKGROUND);
}
renderer.setItemMargin(0.0);
CategoryAxis axis = plot.getDomainAxis();
axis.setCategoryMargin(0);
}
You could create a method to add multiple markers e.g
private void addMarkers(List<Comparable> keys){
...
A more correct solution may be to write your own implementation of the Renderer and accociated code

Related

MPAndroidChart Display Label Over Horizontal Line on Graph

Is it possible to display custom text centered between 2 points on the graph?
I've got MPAndroidChart setup to display a step function type graph (representing hours spent doing a specific task) with horizontal and vertical lines only. What I would like to be able to do is show a label over the horizontal sections indicating the size of the section (aka the time spent calculated by taking the difference between the x values). Is there a way to do this? I've been look into modifying the library but I can't seem to figure out where would be the correct place to do so.
My best guess would be some changes in BarLineChartBase onDraw() method or maybe in the LineChartRenderer drawLinear() method.
Here is what I am able to produce:
Here is an example of what I am trying to produce:
Figured it out! Just add a new method drawTime() to the LineChart class at the end of onDraw() right after drawDescription(). Since each horizontal line is described by 2 Entry points I simply loop through 2 entries at a time for my single data set and calculate the difference:
protected void drawTime(Canvas c)
{
Paint timePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
timePaint.setTextSize(Utils.convertDpToPixel(16));
timePaint.setColor(Color.BLUE);
timePaint.setTextAlign(Paint.Align.CENTER);
MPPointD position;
LineData data = this.getLineData();
ILineDataSet dataSet = data.getDataSetByIndex(0);
for (int i = 1; i < dataSet.getEntryCount(); i+=2)
{
Entry e1 = dataSet.getEntryForIndex(i-1);
Entry e2 = dataSet.getEntryForIndex(i);
float time = e2.getX() - e1.getX();
position = getPixelForValues(e1.getX() + time/2, e1.getY() - 0.05f, YAxis.AxisDependency.LEFT);
c.drawText(String.valueOf(time), (float)position.x, (float)position.y, timePaint);
}
}
The resulting graph looks like this

How to draw a series of connected lines in Libgdx?

I'm using polygon on shape renderer and the problem is that the user should be able to add vertex whenever they want, basically the vertices are not set by me but by the user. What I did is whenever the user add a point, I add them to an arrayList.
ArrayList<Float> v = new ArrayList<Float>();
public void ontouch(screenX, screenY){
v.add(screenX);
v.add(screenY)
}
And then I have this problem when I try to render a polygon on a shapeRenderer
for(int i = 0; i < v.size; i++){
float[] vertices = new float[v.size()]
vertices[i - 1] = v.get(i - 1);
vertices[i] = v.get(i);
}
sr.polygon(v);
But I just get errors.
I am trying to achieve something like this, if you know a different way of doing this then that would be really helpful. By the way I'm also using box2d and this does not need to have collision it's just for the user visual.
The way I would personally do it is by having an LinkedList with Vector2 objects. Vector2 objects store two floats, so for every click, you get the x and y coordinates and make a new Vector2 object. By storing them in the LinkedList, you can retrieve the points at any time in the correct order so you can connect a line.
LinkedList<Vector2> v = new LinkedList<Vector2>();
public void ontouch(screenX, screenY){
v.add(new Vector2(screenX, screenY)); // add Vector2 into LinkedList
}
How you want to draw the lines or connect the points is up to you.
Another was is to just only keep the two most recent points that were clicked, and throw the others away. This would mean storing the lines instead of the points. If the lines are objects, then you can do this:
Vector2 previousPoint;
Vector2 currentPoint;
ArrayList<MyLineClass> lines = new ArrayList<MyLineClass>();
public void ontouch(screenX, screenY){
if(previousPoint == null){
previousPoint = new Vector2(screenX, screenY);
}else{
previousPoint = currentPoint;
currentPoint = new Vector2(screenX, screenY);
lines.add(new MyLineClass(currentPoint, previousPoint)
}
}
I wrote this off the cuff but I believe this example should work.
EDIT:
Good thing LibGDX is open source. If you want to use an array of float numbers, the method simply gets an x and y coordinate in alternating order. So for each index:
0 = x1
1 = y1
2 = x2
3 = y2
4 = x3
5 = y3
etc.
It's an odd method, but I suppose it works.

Query all Object within n kilometer Radius with Hibernate Spatial?

I use hibernate spatial attach a geolocation to a car. My card domain class looks like this:
import com.vividsolutions.jts.geom.Point
class Card {
String name
Point location
}
My program is in Grails so the samples I gave are in Groovy. I found a similar post here which does not really answer the most important question on how to specify the radius correctly to set n kilimeter for the radius.
Here is how I compute a circle Geometry:
private static Geometry createCircle(double x, double y, final double RADIUS) {
GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
shapeFactory.setNumPoints(1000);
shapeFactory.setCentre(new Coordinate(x, y))
shapeFactory.setSize( (RADIUS * 2)/88.1)
return shapeFactory.createCircle().getBoundary()
}
The size of the circle is divided by 88.1 the is just a dirty fix to get an approximate dimension but it is still wrong.
My query is done like this:
double radius = 40
Geometry filter = createCircle(car.location.x, car.location.y, radius)
Session session = sessionFactory.currentSession
Query q = session.createQuery("select c from Car c where within(c.location, ?) = true")
q.setParameter(0, filter, GeometryUserType.TYPE)
q.list()
This works not very accurate. Some of the cars which should be outside circle are returned from this query.
Here is an example. My center is Hamburg and the radius is 40km. I made a google maps visualization.
Here is when I set radius = 40:
You can see that at the top left one car which has a location outside of the circle is still drawn. This should not be the case. It appears to me that the circle I draw with google maps is not equal to the circle Geometry I draw in code for my query.
Here is when I set radius = 30:
You see that the cars at the bottom right disappear which is correct, but the car at the top left still remains in the query.
When I draw the circle I created with createCircle I get the following (using getCoordinates() to get the coordinates of the circle):
How can I query all cars within a radius of 40km?
Try to compute the distance between the geometries instead. You can use dwithin function (see Hibernate spatial documentation ):
select c from Car c where dwithin(c.location, :geom, :dist) = true
or just distance:
select c from Car c where distance(c.location, :geom) < :dist
Also, don't forget transform distance measure to degrees (for WGS84 SRS).
edited:
Use geom the centre of your imaginary circle, so you don't have to generate a geometry, just filter by distance.
P.D.: In this post you can found a description about the problem of transformation of degrees and meters
Good luck!.
Chema.

finding cells in a grid that intersect a given rectangle

(I'll tag this for both Java and language-agnostic, since I think the idea doesn't really require Java, but that's my specific application, so IDK which of the two tags is appropriate).
Let's say I have a grid with an arbitrary number of rows and columns, and and arbitrary cell size.
This grid represents a 2d space. Now let's say I have a rectangle somewhere in that 2d space - in the past, I remember being able to get back all the cells that intersected the rectangle, (without having to loop), but the math is escaping me at the moment.
To firm up the example, lets say there are 12 rows and 10 columns. Cells are 256 square (so rows at 256 tall, and columns are 256 wide). If there was a rectangle at x:400, y:300 that was 200x200, I know that it would intersect the second and third columns in the second row.
So if cell structure was defined like so:
// reference[rows][columns]
SomeCellClass[][] cells = SomeCellClass[12][10]
Then the intersections would be SomeCellClass[1][1] and SomeCellClass[1][2]
And ideally the return would be something like
private SomeCellClass[] blah(){
// do work
SomeCellClass[] product = new SomeCellClass[total];
SomeCellClass[0] = // first one that intersects...
SomeCellClass[1] = // second one that intersects...
// etc...
}
I remember it has something do do with dividing the rectangle position and dimension by cell size and flooring/ceiling to get back the index, but can't get my head around the specifics. Again, I get how to do this with a loop but would like to be able to use just math and array indices.
Any help would be appreciated.
TYIA.
Looks like it's basically this:
int startingColumn = Math.floor( rect.left / columnWidth );
int endingColumn = Math.ceil( rect.right / columnWidth );
int startingRow = Math.floor( rect.top / rowHeight );
int endingRow = Math.ceil( rect.bottom / rowHeight );
Then obviously loop from startingColunn/Row through endingColumn/Row.

Java Recursion Triangle with Deviation

Hello I am fairly new to programming and I am trying, in Java, to create a function that creates recursive triangles from a larger triangles midpoints between corners where the new triangles points are deviated from the normal position in y-value. See the pictures below for a visualization.
The first picture shows the progression of the recursive algorithm without any deviation (order 0,1,2) and the second picture shows it with(order 0,1).
I have managed to produce a working piece of code that creates just what I want for the first couple of orders but when we reach order 2 and above I run into the problem where the smaller triangles don't use the same midpoints and therefore looks like the picture below.
So I need help with a way to store and call the correct midpoints for each of the triangles. I have been thinking of implementing a new class that controls the calculation of the midpoints and stores them and etc, but as I have said I need help with this.
Below is my current code
The point class stores a x and y value for a point
lineBetween creates a line between the the selected points
void fractalLine(TurtleGraphics turtle, int order, Point ett, Point tva, Point tre, int dev) {
if(order == 0){
lineBetween(ett,tva,turtle);
lineBetween(tva,tre,turtle);
lineBetween(tre,ett,turtle);
} else {
double deltaX = tva.getX() - ett.getX();
double deltaY = tva.getY() - ett.getY();
double deltaXtre = tre.getX() - ett.getX();
double deltaYtre = tre.getY() - ett.getY();
double deltaXtva = tva.getX() - tre.getX();
double deltaYtva = tva.getY() - tre.getY();
Point one;
Point two;
Point three;
double xt = ((deltaX/2))+ett.getX();
double yt = ((deltaY/2))+ett.getY() +RandomUtilities.randFunc(dev);
one = new Point(xt,yt);
xt = (deltaXtre/2)+ett.getX();
yt = (deltaYtre/2)+ett.getY() +RandomUtilities.randFunc(dev);
two = new Point(xt,yt);
xt = ((deltaXtva/2))+tre.getX();
yt = ((deltaYtva/2))+tre.getY() +RandomUtilities.randFunc(dev);
three = new Point(xt,yt);
fractalLine(turtle,order-1,one,tva,three,dev/2);
fractalLine(turtle,order-1,ett,one,two,dev/2);
fractalLine(turtle,order-1,two,three,tre,dev/2);
fractalLine(turtle,order-1,one,two,three,dev/2);
}
}
Thanks in Advance
Victor
You can define a triangle by 3 points(vertexes). So the vertexes a, b, and c will form a triangle. The combinations ab,ac and bc will be the edges. So the algorithm goes:
First start with the three vertexes a,b and c
Get the midpoints of the 3 edges p1,p2 and p3 and get the 4 sets of vertexes for the 4 smaller triangles. i.e. (a,p1,p2),(b,p1,p3),(c,p2,p3) and (p1,p2,p3)
Recursively find the sub-triangles of the 4 triangles till the depth is reached.
So as a rough guide, the code goes
findTriangles(Vertexes[] triangle, int currentDepth) {
//Depth is reached.
if(currentDepth == depth) {
store(triangle);
return;
}
Vertexes[] first = getFirstTriangle(triangle);
Vertexes[] second = getSecondTriangle(triangle);
Vertexes[] third = getThirdTriangle(triangle);;
Vertexes[] fourth = getFourthTriangle(triangle)
findTriangles(first, currentDepth+1);
findTriangles(second, currentDepth+1);
findTriangles(third, currentDepth+1);
findTriangles(fourth, currentDepth+1);
}
You have to store the relevant triangles in a Data structure.
You compute the midpoints of any vertex again and again in the different paths of your recursion. As long as you do not change them by random, you get the same midpoint for every path so there's no problem.
But of course, if you modify the midpoints by random, you'll end with two different midpoints in two different paths of recursion.
You could modify your algorithm in a way that you not only pass the 3 corners of the triangle along, but also the modified midpoints of each vertex. Or you keep them in a separate list or map or something and only compute them one time and look them up otherwise.

Categories

Resources