Search code examples
javaandroidplot

How to move the first domain label one step from origin


I've implemented AndroidPlot in my app and it works fine however I need the first value one step after origin since the date is not clear.

I tried the suggested solution in the asked questions here where they add the setDomainValueFormat method however error message displays:

"method can't resolve "

andriodplot

Any suggestion how to start x axis domain one step after origin?

plot = (XYPlot) findViewById(R.id.plot);

        XYSeries series = new SimpleXYSeries(Arrays.asList(dates_in_m_seconds), Arrays.asList(values_as_numbers), "BP Status");

        LineAndPointRenderer and configure them
        LineAndPointFormatter seriesFormat = new LineAndPointFormatter(Color.RED, Color.GREEN,null, null);


               plot.addSeries(series, seriesFormat);

        // Specify x and y axes labels amount
        plot.setRangeStep(StepMode.SUBDIVIDE,3);
        plot.setDomainStep(StepMode.SUBDIVIDE,dates.size());

               plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
            @Override

            public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {


                Date date_Label = new Date(Math.round(((Number) obj).doubleValue()));

                return format.format(date_Label, toAppendTo, pos);
            }

            @Override
            public Object parseObject(String source, ParsePosition pos) {
                return null;
            }
        });



        plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).setFormat(new Format() {


            @Override

            public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {

                Number num = (Number) obj;
                switch (num.intValue()) {
                    case 0:
                        toAppendTo.append("Low");
                        break;
                    case 1:
                        toAppendTo.append("Normal");
                        break;
                    case 2:
                        toAppendTo.append("High");
                        break;

                    default:
                        toAppendTo.append("Unknown");
                        break;
                }
                return toAppendTo;

            }

            @Override
            public Object parseObject(String source, ParsePosition pos) {
                return null;
            }
        });


            }

Solution

  • There are a few ways you can approach this problem. On the surface, it seems like maintaining strict uniform spacing between xVals is desirable, however because your xVals are not only timestamps but are rounded versions of the raw inputs, you're only going to get an approximately uniform spacing. If you want to fully solve that problem you could instantiate your XYSeries using Y_VALS_ONLY and then use dates_as_m_seconds as a lookup table to render labels in your domain Format instance.

    Having said that, I've included a solution that should work with your existing code. I didnt try to compile or run it so there might be typos, but the general idea will work:

    1. Manually set the domain boundaries of your plot to include some extra space before the first element in your timestamp data.
    2. When you subdivide the domain area, add an extra element to make room for a new invisible step
    3. Modify your domain label Format instance to skip over values < the first timestamp in your data, effectively making the new first element invisible.

    Code:

                // this value must be final in order to be visible to the anonymous inner class instance
                // of Format below.  Note that this will fail miserably if you try to plot a series of
                // size < 2.
                final double firstX = Math.round(((Number) series.getX(0)).doubleValue());
                double secondX = Math.round(((Number) series.getX(1)).doubleValue());
                double lastX = Math.round(((Number) series.getX(series.size() - 1)).doubleValue());
    
                // assuming the step interval is uniform, this is the distance between each xVal:
                double stepInterval = secondX - firstX;
    
                // add in extra space for the first "invisible index" by setting the starting
                // domain boundary exactly one interval before the first actual element:
                plot.setDomainBoundaries(firstX - stepInterval, lastX, BoundaryMode.FIXED);
    
                // add an extra "invisible index":
                plot.setDomainStep(StepMode.SUBDIVIDE,dates.size() + 1);
    
                ...
    
                plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
    
                    @Override
                    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
                        double timestampMs = Math.round(((Number) obj).doubleValue());
    
                        // only render indices corresponding to values in the series:
                        if(timestampMs >= firstX) {
                            Date date_Label = new Date();
                            return format.format(date_Label, toAppendTo, pos);
                        }
                    }
    
                    @Override
                    public Object parseObject(String source, ParsePosition pos) {
                        return null;
                    }
                });