I am using the MPAndroidChart library to graph live sensor data in a line graph. I'm hoping to give the data a sort of 'buffer' on the right-hand end so that new data is in the centre of the screen. I've tried to illustrate what I mean below:
Basically, I have got it so the ViewPort scrolls and shows the most recent item in the right-most end of the screen, but I would like it in the centre. Thanks!
you need to set Xaxis maximum, set visibleXrange and last move the viewport
double range = 5; // how many data you want to show in view port
double maxX = 100; // your highest X value
chartView.getXAxis().setAxisMaximum(maxX + range/2);
chartView.setVisibleXRange(range, range);
chartView.moveViewToX(maxX);
chartView.notifyDataSetChanged();
Related
I need suggestion on how to limit the MpAndroid CandleStick chart combined with volume bar chart at the bottom so that volume bar max height can be limit to below 1/3 of chart area Yaxis . From the chart attached , this is somewhere Y Max at 3million region viewport in the left Axis. The current combined chart is ruin by the volume bar chart.
Thanks
setVisibleXRangeMaximum(float maxXRange): Sets the size of the area (range on the x-axis) that should be maximum visible at once. If this is e.g. set to 10, no more than 10 values on the x-axis can be viewed at once without scrolling.
setVisibleXRangeMinimum(float minXRange): Sets the size of the area (range on the x-axis) that should be minimum visible at once. If this is e.g. set to 10, it is not possible to zoom in further than 10 values on the x-axis.
setVisibleYRangeMaximum(float maxYRange, AxisDependency axis): Sets the size of the area (range on the y-axis) that should be maximum visible at once. You also need to provide the axis this constraint should apply to.
For more info Refer this
Thanks for your comment ,I do not think setting XrangeMax or Min will help , it only limit the x-axis down to certain visible display range instead of showing the full range of the dataset points . The chart shown above has about more than 4000 data points , I have narrowed the visible x-range using set chart.setVisibleXRangeMaximum(100) and also chart.moveViewToX(3000) to optimise performance. What I need is some functional procedure to set the max Y-axis (eg left Y-axis) at certain specific offset position , so that the lower portion of the chart could be restricted to the volume bar chart by clipping the specific rectangle viewports. I am not sure if that is possible , narrowing the YVsibleYrange is not what I have in mind. What I would like to have is
That is possible. All you need to do is plot the data against two different axes (as you are already doing), and then set the top space for each axis separately.
Customizing the axis range
setAxisMaxValue(float max): Set a custom maximum value for this axis. If set, this value will not be calculated automatically depending on the provided data.
setAxisMinValue(float min): Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on the provided data.
setSpaceTop(float percent): Sets the top spacing (in percent of the total axis-range) of the highest value in the chart in comparison to the highest value on the axis.
setSpaceBottom(float percent): Sets the bottom spacing (in percent of the total axis-range) of the lowest value in the chart in comparison to the lowest value on the axis.
More information in the documentation.
To workaround , I have coded the Y axis to be at 1/x1 of Y viewport height to mark the volume bar top at YMAX in the multiple of x1 where x1 variable can be ={3, 4 or 5} float ymax=barDataSet.getYMax(); float ymaxd=(float)Math.floor (ymax*x1); leftAxis.setLabelCount(x1,false); leftAxis.setAxisMaxValue(ymaxd);
I'm using the Android version of PDFNet 6.5.0.
I need to set the vertical scroll of the PDFViewCtrl to an absolute point in the pdf, expressed in PDF Canvas coordinates.
For example, say that I want to zoom to the middle of the second page.
I could get the y coordinate, in PDF Canvas position like:
int y = doc.getPage(1).getPageHeight() + (doc.getPage(2).getPageHeight() / 2)
How could I scroll to the y position?
I'm trying to do it with PDFViewCtrl#setVScrollPos(), but I don't know how to convert y to a valid parameter for this method.
Have you tried to use PDFViewCtrl#scrollTo(int, int)?
i.e. first convert points from PDF space to canvas space(PDFViewCtrl#convPagePtToCanvasPt), then scrollTo the position.
Although I have accepted Shirley G's answer I am posting this other answer for clarification.
The tricky bit is which number to pass as parameter to PDFViewCtrl#setVScrollPos(int) or PDFViewCtrl#scrollTo(int, int)
You need to use PDFViewCtrl#convPagePtToScreenPt() to convert the page position into a physical screen point.
But you also need to take into account the current scroll offset of the scroll view pdfViewCtrl#getVScrollPos()
So, given you want to scroll to verticalPosition in page:
public void scrollToDocPosition( final int verticalPosition, final int page) {
double[] screenPos = pdfViewCtrl.convPagePtToScreenPt(0, verticalPosition, page);
pdfViewCtrl.setVScrollPos((int) screenPos[1] + pdfViewCtrl.getVScrollPos());
}
I came to this thanks to https://groups.google.com/forum/?fromgroups#!searchin/pdfnet-sdk/scroll/pdfnet-sdk/7Wy00goWfyQ/t1tvApNDrr8J, where Thomas Hoffman explains:
The first thing to look at is the scroll position. y after
converting is in screen space, while SetX/YScrollPos is in the
coordinates of the scroll viewer. That is, the top left corner of the
PDFViewCtrl is at position (0, 0) in screen space, but at position
(GetHScrollPos and GetVScrollPos) in scroll coordinates
I am using Achartengine to generate TimeChart graph. The data set consists of dates form 1/15/2003 to 12/4/2040 (x-axis) with respective random values for Y-axis. I am displaying the graph dynamically where I keeps reading the values on background thread (AsyncTask) and repaints the graphview. I have 2 questions:
The view starts from Jan, 2, 1970(I dono why) and I have to scroll to 1/15/2003 to see the graph. What should I change to make it start from 1/15/2003 ?
Also I take 2 date values FROM and TO (Eg: FROM:2/17/2004 TO:6/23/2006) and I want to display the graph only in this range. Is there any way to do this?
I could solve the 1st one using mRenderer.setYAxisMin(new Date("1/15/2003 11:16:00 AM").getTime()) Although this is a deprecated method, but it did the work for me. Now when I display the graph its starts from given data not Jan, 2, 1970.
You can dynamically set Y axis min and max with values desired values, just before repainting.
And for the 1. question, maybe better option is to set pan limits, so you can't scroll to empty parts of your chart.
You can do it like this
mRenderer.setPanLimits(new double[]{xMin, xMax, yMin, yMax});
where you calculate limits like this
double xMin = minDate.getTime();
double xMax = maxDate.getTime();
I'm developing a cross platform mobile application that stores positions as geographic coordinates into a db, each of these points represent the top left corner of a graphical object.
This application contains a map control (radmap from telerik), that supports geographic coordinates, so, you just add the rectangle and it draws it correctly.
Due to licensing problem I cannot use the map control in the android version (google doesn't let us use the map control for business applications - https://developers.google.com/maps/faq#tos_commercial, for ios I still didn't check this out), so I will use an image to be used as background.
I've got the top left corner and bottom right geographic coordinates of the "map/image" and I've got to draw the graphical objects inside the area defined by the corners.
Could anyone help me to discover how to convert the geographic coordinates to screen coordinates.
Data example (X,Y):
GEO
Top left corner:
-0,00939846 -0,00504255
Bottom right corner:
0,009398461 -0,01281023
Points to draw:
-0.00464558,-0.00799298
-0.0046509,-0.00845432
-0.00386774,-0.00860988
-0.00344932,-0.00860452
SCREEN
Top left corner:
0 0
Bottom right corner:
? ?
Points to draw
? ?
Screen size
1024 * 768
Thanks for the help,
Luis Pinho
I'm most fluent in iOS so that's what my answers in. I tried to make as many variables as possible so that you could either manually/programmatically override them without changing too much of the other code.
- (CGPoint)convertGeoPoint:(CGPoint)point toView:(UIView*)view {
CGPoint geoTopLeft = CGPointMake(-0.00939846, -0.00504255);
CGPoint geoBottomRight = CGPointMake(0.009398461, -0.01281023);
CGFloat geoWidth = geoBottomRight.x - geoTopLeft.x;
CGFloat geoHeight = geoBottomRight.y - geoTopLeft.y;
// This is the block you would change to suit your needs
CGPoint viewTopLeft = CGPointMake(view.frame.origin.x, view.frame.origin.y);
CGFloat viewWidth = view.frame.size.width;
CGFloat viewHeight = view.frame.size.height;
return CGPointMake(viewTopLeft.x + (point.x-geoTopLeft.x)*viewWidth/geoWidth, viewTopLeft.y + (point.y-geoTopLeft.y)*viewHeight/geoHeight);
}
The basic idea is that you need to convert the point into the new coordinate system. To do this, you need to divide by the appropriate geographic dimension and multiply by the appropriate view dimension.
I need to apply click/touch events for only visible part of the View. Say for example a image of size 200X200. Apart from center 50X50, remaining part is transparent. I want to get touch events only for that 50X50 visible part Not on remaining transparent part.
In above image (its single image), only inner Diamond has got visible part. Apart from that Diamond is transparent area. So, if I touch Diamond then only I want to do something else ignore.
Edit :
Rachita's link helped me. I gone through that link and got idea how can I implement. But I could not understand some constants like 320, 240 etc while creating Points. In my case, I know the Diamond (in above image) x and y Ponits (hard coded values asctually). So, using those how can I determine, whether I touched inside Diamond or outside?
my Diamond points are as below
pointA = new Point(0, 183);
pointB = new Point(183, 0);
pointC = new Point(366, 183);
pointD = new Point(183, 366);
Edit :
Finally got solution from Luksprog. Its based on checking touched point pixel color. If color is 0 means, you touched transparent layer else you touched some colored part of the image. Simple, but very effective. Have a look at it here.
AFAIK you can not implement this with onclick listener or my any other direct way .You will have to use onTouchListener .
Firstly set your view dynamically at a specific (x,y) position using this How can I dynamically set the position of view in Android?
Calculate the region your diamond will occupy (you should khow the size of image inorder to calculate area of diamond)
3.Trigger a action in onTouchListener only when x, y fall in the required region. Use How to get the Touch position in android?
check this link to calculate if a given point lies in the required square
EDIT
To understand the coordinate system of android refer to this link How do android screen coordinates work?
Display mdisp = getWindowManager().getDefaultDisplay();
int maxX= mdisp.getWidth();
int maxY= mdisp.getHeight();
(x,y) :-
1) (0,0) is top left corner.
2) (maxX,0) is top right corner
3) (0,maxY) is bottom left corner
4) (maxX,maxY) is bottom right corner
here maxX and maxY are screen maximum height and width in pixels, which we have retrieved in above given code.
Remember if you want to support multiple devices with different screen sizes,make sure you use a relative value for x,y ie some ratio of screen height or width ,as different devices have different ppi
Check if touched point lies in the required polygon
I thinks these link might help you determining if the point touched (you can get x,y from onTouch event eg.event.getX()) lies in the required polygon whose points you have mentioned in the question . determine if a given point is inside the polygon and How can I determine whether a 2D Point is within a Polygon?