Search Results for

    Show / Hide Table of Contents

    Axis APIs - Convert Pixel to Data coordinates

    SciChart Android provides a clean and simple API to transform pixels to data-values and vice versa via the following methods:

    • getCoordinate(Comparable value) - expects a chart data-value and returns the corresponding pixel coordinate.
    • getDataValue(float pixelCoordinate) - expects a coordinate in pixels and returns the closest data value to that coordinate.

    It is also possible, to perform such conversion using our CoordinateCalculator APIs

    Where Pixel Coordinates are measured from

    It is important to note when converting Pixels to Data Coordinates and vice versa that pixels are measured from the top-left inside corner of the chart. So, let's see correspondence of the pixel coordinate and data-values in the table below:

    Pixel Coordinate Data-Value
    [0, 0] [xAxis.getVisibleRange().getMin(), yAxis.getVisibleRange().getMax()]
    [width, height] [xAxis.getVisibleRange().getMax(), yAxis.getVisibleRange().getMin()]
    Note

    Learn more about getVisibleRange() and how to use this property at the Axis Ranging - VisibleRange and DataRange article.

    Pixels vs Data-Coordinates

    Converting between Pixels and Data Coordinates

    As mentioned above - data-values are converted to pixel coordinates via the getCoordinate(Comparable value) method. Also, Coordinates in pixels are converted back to chart data-values via the getDataValue(float pixelCoordinate) method.

    You can find simple examples how to do the conversions below.

    NumericAxis conversions

    • Java
    • Java with Builders API
    • Kotlin
    float coordinate = xAxis.getCoordinate(1.2);
    
    // Convert back:
    Comparable dataValue = xAxis.getDataValue(coordinate);
    
    float coordinate = xAxis.getCoordinate(1.2);
    
    // Convert back:
    Comparable dataValue = xAxis.getDataValue(coordinate);
    
    val coordinate = xAxis.getCoordinate(1.2)
    
    // Convert back:
    val dataValue = xAxis.getDataValue(coordinate)
    

    DateAxis conversions

    • Java
    • Java with Builders API
    • Kotlin
    final DateAxis xAxis = new DateAxis(getContext());
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.MAY, 1);
    final Date date = calendarDate.getTime();
    
    float coordinate = xAxis.getCoordinate(date);
    // Convert back:
    Comparable dataValue = xAxis.getDataValue(coordinate);
    
    final DateAxis xAxis = sciChartBuilder.newDateAxis().build();
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.MAY, 1);
    final Date date = calendarDate.getTime();
    
    float coordinate = xAxis.getCoordinate(date);
    
    // Convert back:
    Comparable dataValue = xAxis.getDataValue(coordinate);
    
    val xAxis = DateAxis(context)
    
    val calendarDate = Calendar.getInstance()
    calendarDate[2011, Calendar.MAY] = 1
    val date = calendarDate.time
    
    val coordinate = xAxis.getCoordinate(date)
    
    // Convert back:
    val dataValue = xAxis.getDataValue(coordinate)
    

    CategoryDateAxis conversions

    • Java
    • Java with Builders API
    • Kotlin
    final CategoryDateAxis xAxis = new CategoryDateAxis(getContext());
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.OCTOBER, 5);
    final Date date = calendarDate.getTime();
    
    float coordinate = xAxis.getCoordinate(date);
    
    // Convert back:
    Comparable dataValue = xAxis.getDataValue(coordinate);
    
    final CategoryDateAxis xAxis = sciChartBuilder.newCategoryDateAxis().build();
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.OCTOBER, 5);
    final Date date = calendarDate.getTime();
    
    float coordinate = xAxis.getCoordinate(date);
    
    // Convert back:
    Comparable dataValue = xAxis.getDataValue(coordinate);
    
    val xAxis = CategoryDateAxis(context)
    
    val calendarDate = Calendar.getInstance()
    calendarDate[2011, Calendar.OCTOBER] = 5
    
    val date = calendarDate.time
    
    val coordinate = xAxis.getCoordinate(date)
    
    // Convert back:
    val dataValue = xAxis.getDataValue(coordinate)
    

    Getting a CoordinateCalculator instance

    There is a currentCoordinateCalculator property, which is readonly, and which provides a coordinate calculator instance which is valid for the current render pass.

    Note

    If the getVisibleRange() changes, the data changes, or the viewport size changes - then the ICoordinateCalculator will be recreated under the hood.

    ICoordinateCalculator API

    Like IAxisCore, ICoordinateCalculator has the following methods:

    • getCoordinate(Comparable value) - expects a double representation of data-value and returns the corresponding pixel coordinate.
    • getDataValue(float pixelCoordinate) - expects a coordinate in pixels and returns the closest data value to that coordinate (represented in double).

    But in addition to the above, coordinate calculators API, provides methods, to perform conversions in batches via the following:

    • getCoordinates(double[] dataValues, float[] coordinates, int count)
    • getDataValues(float[] coordinates, double[] dataValues, int count)

    As you might guess, converting Pixels to Data-Coordinates and vise versa slightly differs for different axis types due to difference in underlying data-types. In particular the following ones:

    • NumericAxis
    • DateAxis
    • CategoryDateAxis

    Read on to get better understanding of such conversions.

    NumericAxis conversions

    The simplest case is the NumericAxis. ICoordinateCalculator for NumericAxis works the data-value as double. So let's take our Digital Line Chart example, and try do some conversions

    • Java
    • Java with Builders API
    • Kotlin
    final NumericAxis xAxis = new NumericAxis(getContext());
    
    final ICoordinateCalculator calculator = xAxis.getCurrentCoordinateCalculator();
    float coordinate = calculator.getCoordinate(1.2);
    
    // Convert back:
    double dataValue = calculator.getDataValue(coordinate);
    
    final NumericAxis xAxis = sciChartBuilder.newNumericAxis().build();
    
    final ICoordinateCalculator calculator = xAxis.getCurrentCoordinateCalculator();
    float coordinate = calculator.getCoordinate(1.2);
    
    // Convert back:
    double dataValue = calculator.getDataValue(coordinate);
    
    val xAxis = NumericAxis(context)
    
    val calculator = xAxis.currentCoordinateCalculator
    val coordinate = calculator.getCoordinate(1.2)
    
    // Convert back:
    val dataValue = calculator.getDataValue(coordinate)
    
    VisibleRange = [1, 1.25], Data-Value = 1.2, Pixel-Coordinate = 272.8
    Note

    The exact data-values and coordinates might differ depending on your visibleRange, viewport etc...

    DateAxis conversions

    Similarly to NumericAxis - the DateAxis is quite simple with one difference - it's ICoordinateCalculator works with long representation of Date, which is getTime(). So let's take our Mountain Line Chart as an example, and try do some conversions.

    Note

    Since the ICoordinateCalculator works with long representation of Date in getTime(), you will need to do all the needed conversions on your own. See the code below:

    • Java
    • Java with Builders API
    • Kotlin
    final DateAxis xAxis = new DateAxis(getContext());
    
    final ICoordinateCalculator calculator = xAxis.getCurrentCoordinateCalculator();
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.MAY, 5);
    final Date date = calendarDate.getTime();
    
    float coordinate = calculator.getCoordinate(date.getTime());
    
    // Convert back:
    double dateInMillis = calculator.getDataValue(coordinate);
    Date dateValue = new Date((long) dateInMillis);
    
    final DateAxis xAxis = sciChartBuilder.newDateAxis().build();
    
    final ICoordinateCalculator calculator = xAxis.getCurrentCoordinateCalculator();
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.MAY, 5);
    final Date date = calendarDate.getTime();
    
    float coordinate = calculator.getCoordinate(date.getTime());
    
    // Convert back:
    double dateInMillis = calculator.getDataValue(coordinate);
    Date dateValue = new Date((long) dateInMillis);
    
    val xAxis = DateAxis(context)
    val calculator = xAxis.currentCoordinateCalculator
    
    val calendarDate = Calendar.getInstance()
    calendarDate[2011, Calendar.MAY] = 5
    val date = calendarDate.time
    
    val coordinate = calculator.getCoordinate(date.time.toDouble())
    
    // Convert back:
    val dateInMillis = calculator.getDataValue(coordinate)
    val dateValue = Date(dateInMillis.toLong())
    
    VisibleRange = [2010-09-28, 2011-12-09], Data-Value = "2011-05-01", Pixel-Coordinate = 374.658417
    Note

    The exact data-values and coordinates might differ depending on your visibleRange, viewport etc...

    CategoryDateAxis conversions

    CategoryDateAxis is slightly different. It's ICoordinateCalculator conversion methods works with an integers, which is the index of a data points inside an appropriate IDataSeries<TX,TY>. You can convert Date to index and vice versa through the ICategoryLabelProvider. So let's work with our Candlestick Chart as an example, since is has CategoryDateAxis.

    Note

    Conversion from Date to Index and vice versa can be performed using the ICategoryLabelProvider. See the code below:

    • Java
    • Java with Builders API
    • Kotlin
    final CategoryDateAxis xAxis = new CategoryDateAxis(getContext());
    final ICoordinateCalculator calculator = xAxis.getCurrentCoordinateCalculator();
    
    // get ICategoryLabelProvider to convert Date value to Index
    final ICategoryLabelProvider labelProvider = (ICategoryLabelProvider) xAxis.getLabelProvider();
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.OCTOBER, 5);
    Date date = calendarDate.getTime();
    
    double index = (double) labelProvider.transformDataToIndex(date.getTime());
    double coordinate = calculator.getCoordinate(index);
    
    // Convert back:
    index = (int) calculator.getDataValue((float) coordinate);
    // use the ICategoryLabelProvider instance to convert index to Date value
    date = new Date((long) labelProvider.transformIndexToData((int)index));
    
    final CategoryDateAxis xAxis = sciChartBuilder.newCategoryDateAxis().build();
    final ICoordinateCalculator calculator = xAxis.getCurrentCoordinateCalculator();
    
    // get ICategoryLabelProvider to convert Date value to Index
    final ICategoryLabelProvider labelProvider = (ICategoryLabelProvider) xAxis.getLabelProvider();
    
    final Calendar calendarDate = Calendar.getInstance();
    calendarDate.set(2011, Calendar.OCTOBER, 5);
    Date date = calendarDate.getTime();
    
    int index = labelProvider.transformDataToIndex(date.getTime());
    double coordinate = calculator.getCoordinate(index);
    
    // Convert back:
    index = (int) calculator.getDataValue((float) coordinate);
    // use the ICategoryLabelProvider instance to convert index to Date value
    date = new Date((long) labelProvider.transformIndexToData(index));
    
    val xAxis = CategoryDateAxis(context)
    val calculator = xAxis.currentCoordinateCalculator
    
    // get ICategoryLabelProvider to convert Date value to Index
    val labelProvider = xAxis.labelProvider as ICategoryLabelProvider
    
    val calendarDate = Calendar.getInstance()
    calendarDate[2011, Calendar.OCTOBER] = 5
    var date = calendarDate.time
    
    var index = labelProvider.transformDataToIndex(date.time.toDouble())
    val coordinate = calculator.getCoordinate(index.toDouble()).toDouble()
    
    // Convert back:
    index = calculator.getDataValue(coordinate.toFloat()).toInt()
    // use the ICategoryLabelProvider instance to convert index to Date value
    date = Date(labelProvider.transformIndexToData(index).toLong())
    
    VisibleRange(IndexRange) = [223, 253], Data-Value = "2011-10-05" (index = 231), Pixel-Coordinate = 203.466675
    Note

    The exact data-values and coordinates might differ depending on your visibleRange, viewport etc...

    Transforming Pixels to the Inner Viewport

    If you subscribe to listen to touch events on a SciChartSurface, the touch coordinates you will receive will be relative to the SciChartSurface itself. Before the Coordinate Transformation API can be used, it's important to ensure that such coordinates are transformed relative to the viewport (the central area).

    The view to translate relative to can be obtained calling either the getModifierSurface() or getRenderableSeriesArea(), depending on the context. By default, both occupy the same area, but this can be changed if a custom LayoutManager is provided:

    Pixels vs Data-Coordinates

    The transformation can be done via the translatePoint(PointF point, IHitTestable hitTestable) method of your SciChartSurface instance. For instance let's take a look at the code snippet from our Hit-Test API example:

    • Java
    • Java with Builders API
    • Kotlin
    SciChartSurface surface = new SciChartSurface(getActivity());
    surface.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // the touch point relative to the SciChartSurface
            PointF touchPoint = new PointF(event.getX(), event.getY());
    
            // translate the touch point relative to RenderableSeriesArea or ModifierSurface
            surface.translatePoint(touchPoint, surface.getRenderableSeriesArea());
    
            //OR surface.translatePoint(touchPoint, surface.getModifierSurface());
            // the translated point can be used for looking for data values
            double dataValue = (Double)xAxis.getDataValue(touchPoint.x);
    
            return true;
        }
    });
    
    SciChartSurface surface = new SciChartSurface(getActivity());
    surface.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // the touch point relative to the SciChartSurface
            PointF touchPoint = new PointF(event.getX(), event.getY());
    
            // translate the touch point relative to RenderableSeriesArea or ModifierSurface
            surface.translatePoint(touchPoint, surface.getRenderableSeriesArea());
    
            //OR surface.translatePoint(touchPoint, surface.getModifierSurface());
            // the translated point can be used for looking for data values
            double dataValue = (Double)xAxis.getDataValue(touchPoint.x);
    
            return true;
        }
    });
    
    val surface = SciChartSurface(activity)
    surface.setOnTouchListener { v, event -> // the touch point relative to the SciChartSurface
        val touchPoint = PointF(event.x, event.y)
    
        // translate the touch point relative to RenderableSeriesArea or ModifierSurface
        surface.translatePoint(touchPoint, surface.renderableSeriesArea)
    
        //OR surface.translatePoint(touchPoint, surface.getModifierSurface());
        // the translated point can be used for looking for data values
        val dataValue = xAxis.getDataValue(touchPoint.x) as Double
    
        true
    }
    
    Back to top © 2011-2025 SciChart. All rights reserved. | sitemap.xml