How to make line with rounded (smooth) corners with AndroidPlot

后端 未结 5 2101
挽巷
挽巷 2020-12-05 08:27

I have a small problem with ploting my graph. On a picture below is what I have already done.


The graph should represent the actual signal strength of availabl

相关标签:
5条回答
  • 2020-12-05 09:04

    try this:

    symbol = new Path();
    paint = new Paint();
    paint.setAntiAlias(true);      
    paint.setStrokeWidth(2);
    paint.setColor(-7829368);  
    paint.setStrokeJoin(Paint.Join.ROUND);    // set the join to round you want
    paint.setStrokeCap(Paint.Cap.ROUND);      // set the paint cap to round too
    paint.setPathEffect(new CornerPathEffect(10) );
    paint.setStyle(Paint.Style.STROKE);       
    
    symbol.moveTo(50.0F, 230.0F);         
    symbol.lineTo(75.0F, 100.0F);
    symbol.lineTo(100.0F, 230.0F);
    

    most of the info found here

    0 讨论(0)
  • 2020-12-05 09:09

    Just use ChartFactory.getCubeLineChartView instead of ChartFactory.getLineChartView using achart engine

    0 讨论(0)
  • 2020-12-05 09:13

    There's always been a smooth line renderer in Androidplot: BezierLineAndPointRenderer, which like the implementations above uses Android's built in Bezier drawing routines cubicTo(...) & quadTo(...). The problem is that using Beziers to draw smooth lines in this way creates a false line that overshoots the actual control points by varying amounts, which you can see happening if you look closely at the image above.

    The solution is to use the Catmull-Rom spline interpolation, which is now finally supported by Androidplot. Details here: http://androidplot.com/smooth-curves-and-androidplot/

    0 讨论(0)
  • 2020-12-05 09:17

    1- I guess that you only use a few points to draw graphs of signals. All graph/chart applications try to connect points with direct lines and then your chart will be shown. So if you only use three points, your graph will looks like a triangle! If you want your graph to be curved, you have to add more points. Then it comes out like a curve.

    2- Or you can find any library that can draw sin graph, for example GraphView Library. Then try to draw this function:

    Enter image description here

    So it looks like to this:

    Enter image description here

    Then translate it to (a,0), so result seems like what you want.

    3- And another way, you can use built in Math.sin in Java:

    Chose for example 1000 point in range a to b and compute value of above function for each point and finally create a path and show them in a canvas.

    You can use quadTo (float x1, float y1, float x2, float y2) that simplify drawing quad curves for you. The documentation says:

    Add a quadratic bezier from the last point, approaching control point (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for this contour, the first point is automatically set to (0,0).

    Parameters

    x1 The x-coordinate of the control point on a quadratic curve
    y1 The y-coordinate of the control point on a quadratic curve
    x2 The x-coordinate of the end point on a quadratic curve
    y2 The y-coordinate of the end point on a quadratic curve

    Finally, I add a simple class that extends View and can draw a curve that looks like what you want:

    public class SinWave extends View {
    
        private float first_X = 50;
        private float first_Y = 230;
        private float end_X = 100;
        private float end_Y = 230;
        private float Max = 50;
    
        public SinWave(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Paint paint = new Paint() {
                {
                    setStyle(Paint.Style.STROKE);
                    setStrokeCap(Paint.Cap.ROUND);
                    setStrokeWidth(0.7f);
                    setAntiAlias(true);
                    setColor(0xFFFF00FF);
                }
            };
            final Path path = new Path();
            path.moveTo(first_X, first_Y);
            path.quadTo((first_X + end_X)/2, Max, end_X, end_Y);
            canvas.drawPath(path, paint);
        }
    }
    

    The result must look like this:

    Enter image description here

    You can add more methods to the class and change it to increase performance!

    0 讨论(0)
  • 2020-12-05 09:19

    You can use Path.cubicTo() method. It draws a line using cubic spline algorithm which results in the smoothing effect you want.

    Checkout the answer to a similar question here, where a guy is talking about cubic splines. There is a short algorithm showing how to calculate input parameters for Path.cubicTo() method. You can play with divider values to achieve required smoothness. For example, in the picture below I divided by 5 instead of 3. Hope this helps.

    Example of a polylyne drawn using Path.cubicTo() method

    I have spent some time and implemented a SplineLineAndPointFormatter class, which does the stuff you need in androidplot library. It uses same technics. Here is how androidplot example applications looks like. You just need to use it instead of LineAndPointFormatter.

    Androidplot example with SplineLineAndPointFormatter

    Here is code example and the class I wrote.

    f1 = new SplineLineAndPointFormatter(color.getColor(), null, 
          Color.argb(60, color.getRed(), color.getGreen(), color.getBlue()), null);
    plot.addSeries(series1, f1);
    

    Here is the class doing the magic. It is based on version 0.6.1 of androidplot library.

    package com.androidplot.xy;
    
    import android.graphics.Canvas;
    import android.graphics.Path;
    import android.graphics.PointF;
    import android.graphics.RectF;
    
    import com.androidplot.ui.SeriesRenderer;
    import com.androidplot.util.ValPixConverter;
    
    public class SplineLineAndPointFormatter extends LineAndPointFormatter {
    
        public SplineLineAndPointFormatter() { }
    
        public SplineLineAndPointFormatter(Integer lineColor, Integer vertexColor, Integer fillColor) {
            super(lineColor, vertexColor, fillColor, null);
        }
    
        public SplineLineAndPointFormatter(Integer lineColor, Integer vertexColor, Integer fillColor, FillDirection fillDir) {
            super(lineColor, vertexColor, fillColor, null, fillDir);
        }
    
        @Override
        public Class<? extends SeriesRenderer> getRendererClass() {
            return SplineLineAndPointRenderer.class;
        }
    
        @Override
        public SeriesRenderer getRendererInstance(XYPlot plot) {
            return new SplineLineAndPointRenderer(plot);
        }
    
        public static class SplineLineAndPointRenderer extends LineAndPointRenderer<BezierLineAndPointFormatter> {
    
            static class Point {
                public float x, y, dx, dy;
                public Point(PointF pf) { x = pf.x; y = pf.y; }
            }
    
            private Point prev, point, next;
            private int pointsCounter;
    
            public SplineLineAndPointRenderer(XYPlot plot) {
                super(plot);
            }
    
            @Override
            protected void appendToPath(Path path, final PointF thisPoint, PointF lastPoint) {
                pointsCounter--;
    
                if (point == null) {
                    point = new Point(thisPoint);
                    point.dx = ((point.x - prev.x) / 5);
                    point.dy = ((point.y - prev.y) / 5);
                    return;
    
                } else if (next == null) {
                    next = new Point(thisPoint);
                } else {
                    prev = point;
                    point = next;
                    next = new Point(thisPoint);
                }
    
                point.dx = ((next.x - prev.x) / 5);
                point.dy = ((next.y - prev.y) / 5);
                path.cubicTo(prev.x + prev.dx, prev.y + prev.dy, point.x - point.dx, point.y - point.dy, point.x, point.y);
    
                if (pointsCounter == 1) { // last point
                    next.dx = ((next.x - point.x) / 5);
                    next.dy = ((next.y - point.y) / 5);
                    path.cubicTo(point.x + point.dx, point.y + point.dy, next.x - next.dx, next.y - next.dy, next.x, next.y);
                }
    
            }
    
            @Override
            protected void drawSeries(Canvas canvas, RectF plotArea, XYSeries series, LineAndPointFormatter formatter) {
    
                Number y = series.getY(0);
                Number x = series.getX(0);
                if (x == null || y == null) throw new IllegalArgumentException("no null values in xyseries permitted");
    
                XYPlot p = getPlot();
                PointF thisPoint = ValPixConverter.valToPix(x, y, plotArea,
                        p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY());
    
                prev = new Point(thisPoint);
                point = next = null;
                pointsCounter = series.size();
    
                super.drawSeries(canvas, plotArea, series, formatter);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题