I've been struggling with this for a while now, but I can't find a way to have an x axis, with its labels, lie at the position y = 0. This is important when I have both positive and negative values- I don't want to put the axis at the defaults given by AndroidMPChart (TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE), as none of these apply.
I have managed to edit the xAxisRenderer, and have been able to pass the ratio of my maxY value to my minY value, hoping to manually find the position to set the axis. The issue with this, however, is that I need the position of the highest Y bar and lowest Y bar. I can find the position of the lowest Y bar no problem, using mViewPortHandler.contentBottom(), but using
mViewPortHandler.contentTop() does not give me the top of the Y bar for some reason.
List<Float> floatList = new ArrayList<>();
floatList.add(0f);
floatList.add(mViewPortHandler.contentTop());
floatList.add(mViewPortHandler.offsetTop()+mViewPortHandler.getScaleY());
floatList.add(mViewPortHandler.getContentCenter().y);
floatList.add(mViewPortHandler.contentBottom());
floatList.add(mViewPortHandler.getChartHeight());
if (mDebug) {
for (int i=0; i<floatList.size(); i++) {
Paint paint = new Paint();
paint.setColor(getRandomColorInColorFormPrintString("i = " + i));
paint.setStrokeWidth(3);
c.drawLine(mViewPortHandler.contentLeft()+15*i,
floatList.get(i), mViewPortHandler.contentRight()+15*i,
floatList.get(i), paint);
}
}
Notice how contentBottom (yellow) nails the bottom of the bar, but content top and offset top (pink/red) are not accurate in finding the top of the content. I've tried this with many different values, contentBottom is consistently accurate, whereas contentTop/offsetTop are not, and are not offset by the height of the value label (I already tried this as well).
All I really need is a dynamic way to set the position of the x axis right between positive and negative values. I am so surprised that this option doesn't come with Android MP Charts. If it does, please let me know if I am overcomplicating things.
If there is no way to set this through Android MP Charts, please let me know if you know what I'm doing wrong in trying to get the top of the Y bar.
This is how I solved the problem--
in the renderAxisLine function =>
MPPointD pos = mTrans.getPixelForValues(0f, 0f);
c.drawLine(mViewPortHandler.contentLeft(),
(float)pos.y, mViewPortHandler.contentRight(),
(float)pos.y, mAxisLinePaint);
Related
I am using MPAndroidChart to display my charts, in the barchart it displays some values perfectly but for some other values, the bar is visible and can be highlighted but its value is not visible.
Any clue please on how to fix this ?
This is a picture to clarify what I am saying. The red areas is where the bar is visible but not its value.
Before setting the data (sorry I couldn't find the data in your question):
graph.setVisibleYRangeMaximum(barDataSet.getYMax() + 20, YAxis.AxisDependency.LEFT);
replacing 20 with the height of your custom layout.
I've had the same problem and this is how I've solved it.
float maxValue = barSet.getYMax();
int extraSpace = (int) (maxValue / (yVals.size() + 3));
chart.getAxisLeft().mAxisMaximum = (int) maxValue + (extraSpace < 1 ? 1 : extraSpace);
yVals is the list of Y axis values, while you can play with +3 so the whole chart view seems OK according to your layout.
How do I know what margins to use in an AChartEngine chart to prevent the y-axis labels from being displayed outside the chart when it is set to fill a layout? Can I automatically resize the chart so that the y-axis labels always are visible, even if they contain more than 2-3 digits?
/Markus
You cannot do this automatically, but you can tweak the values until it looks good. You can also rotate the labels when you have several digits values.
This is what I used to deal with Y axis labels that can have differing numbers of digits. Find your max Y value, round it to an int, convert to string and then count the length of the string. The length of the string can be used to calculate a value for the Left margin.
//**** Find max y value of dataset
Ymax = getMaxValue(U_Limit);
if(Ymax < 10){
Ymax = 10;
}else{
Ymax = Ymax*1.1;
}
//**** Find int value of number of digits in max y value
int PLAY_FACTOR = text_label_size*.5 // you may have to play around with this value
int leftMargin = (Double.toString(Math.round(Ymax)).length())*PLAY_FACTOR;
int margins[] = { 26, leftMargin, botMargin, 14 }; // Top,Left,Bottom,Right
renderer.setMargins(margins);
Found a better solution, if you use setYLabelsVerticalPadding with a negative value you can move a little bit down the label... in this way the upper Y label will be visible no matter what.
Hope it helps.
Hint: Here is a similar post with HTML.
In the current tablet implementation of my app, I have a fullscreen MapView with some informations displayed in a RelativeLayout on a left panel, like this:
(My layout is quite trivial, and I guess there is no need to post it for readability)
The problem comes when I want to center the map on a specific point... If I use this code:
mapController.setCenter(point);
I will of course get the point in the center of the screen and not in the center of the empty area.
I have really no idea where I could start to turn the offset of the left panel into map coordinates...
Thanks a lot for any help or suggestion
You can achive your objective by getting the map coordinates from top-left and bottom-right corners and divide it by the screen size, to get the value per pixel.
Then you just need to multiply by the offset and add it to the original center.
Example code:
private void centerMap(GeoPoint center, int offX, int offY){
GeoPoint tl = mapView.getProjection().fromPixels(0, 0);
GeoPoint br = mapView.getProjection().fromPixels(mapView.getWidth(), mapView.getHeight());
int newLon = offX * (br.getLongitudeE6() - tl.getLongitudeE6()) / mapView.getWidth() + center.getLongitudeE6();
int newLat = offY * (br.getLatitudeE6() - tl.getLatitudeE6()) / mapView.getHeight() + center.getLatitudeE6();
mapController.setCenter(new GeoPoint(newLat, newLon));
}
To use, you call the above method with your original center and both offsets (x and Y) to apply.
Note: as written, the code above move map left for positive offset values, and right for negative offset values. From the screen in your question you will need to use negative offset, to move map left, and a zero offset for Y.
Regards
See image below:
illustration http://img28.imageshack.us/img28/5286/pic1we.png
Assume it's on android device screen. Dot #1 is the current position. I want to get the (x,y) position of Dot #2 following the linear blue line (let's say the range between dot #2 and dot #1 is 50dp). The black box is the source point of the blue line.
What is the term for this? Translation?
Is there anyone know the algorithm?
I developed android application using AndEngine, if you know there is built-in function for that, please let me know. Same too for android openGL ES library.
Note: I'm not looking for a way to move object using MoveModifier.
Thx in advance.
Authman's answer is good, but doesn't include how to get a specific distance away. If you're looking for p2 along the line, IMO it's easier to think about this in vectors. First you find the vector along the blue line, which is similar to the process that Authman describes above. If the black box has position v0 = (x0, y0) and the first dot has position v1 = (x1, y1), then your "direction vector" is going to be v1 - v0 = (x1 - x0, y1 - y0). This is a vector that points along the blue line. Once you have that, you normalize it so that the length is 1, and then multiply it by your desired distance, in your case 50. If you want to do it component-wise, here's some quick pseudocode:
find_v2(x0, y0, x1, y1):
direction_x = x1 - x0
direction_y = y1 - y0
norm = sqrt(direction_x^2 + direction_y^2)
direction_x *= 50 / norm
direction_y *= 50 / norm
x2 = x1 + direction_x
y2 = y1 + direction_y
Hope that helps! I'm not sure how comfortable you are with vector math, but if you're doing graphics stuff, it can be really, really useful for problems like this; I'd recommend checking out some of the Khan Academy Linear Algebra courses.
The term you are looking for is extrapolation.
If the black dot is dot '0', then you first calculate your line equation's slope:
m = ( (d0.y-d1.y) / (d0.x-d1.x) )
Then you can extrapolate along that line, either positively (away from point 0) or negatively (towards it, until you get to it, and then eventually again away from in continuing in the line of motion).
dot2.x = d0.x + m*percentage
dot2.y = d0.y + m*percentage
Where percentage is how close you are to dot 1. Thus 1 (eg 100%) would put you on dot 1 exactly. percentage=0 would put you on dot 0 exactly. >1, would put you closer to dot 2. <1 would move you past dot 0, etc.
--
Slight correction there:
dot2.y = d0.x + m*percentage
dot2.x = (dot2.y - dot0.y) / m
The slope as i set it up is only useful for calculating the y coordinate of dot2. Since you already have the equation of the line, you can solve for dot2's x-coord directly using it.
I want to be able to assign a shape a random direction to go in at a regular speed.
I tried assigning a random number to the x and y values of a translation but that caused the shape to sometimes move way too fast or just blip off the screen.
Is there a way to choose a random direction for a shape to move in without rotating the shape (at least as far as the user can tell)?
Also is there a way of re-genereating the random number when an event is called (ie: button click) which would allow a change in direction?
EDIT: Just checked. Using the rotate function with a random angle will shoot the square off in a random direction, but still is there a way to do this without altering the orientation of the shape?
Ok, so you want a shape to move in either the postive or negative x, y or z directions?
If you want this to be random then use the Random class. From this you can use Random.nextInt(1) which will either be 0 or 1, if the result is 0 then set the value to be -1.
The +1 or -1 is now used for your direction.
Now you know which way the object travels you can simply multiply this by the speed of your object
Here is some rough code
Random rand = new Random(); int direction = rand.nextInt(1);
if(direction == 0) direction = -1;
Shape theShape.position.x += direction * theShape.speed
This may not be how your interface is setup (such as theShape.position or theShape.speed) but the idea is the same
After reading this again I think you are trying to rotate your shape lol, rotation is not just adding to the x and y values. Do you use matrices in your application? If not your should use trig to figure out what the x and y values will be after a rotation of x degrees