如何使AndroidPlot与圆angular(平滑)的angular落

绘制我的graphics有一个小问题。 在下面的图片是我已经做了。


该图应表示可用Wi-Finetworking的实际信号强度。 这是一个简单的XYPlot这里的数据用SimpleXYSeries表示(数值是dynamic创build的)。

这是一小段代码(仅举例):

 plot = (XYPlot) findViewById(R.id.simplexyPlot); series1 = new SimpleXYSeries(Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Link 1"); f1 = new LineAndPointFormatter(color.getColor(), null, Color.argb(60, color.getRed(), color.getGreen(), color.getBlue()), null); plot.addSeries(series1, f1); 

图中的例子是dB变化的dynamic模拟。 我想,一切正常,但我想要实现的是有“圆angular”(见图片看我的意思)线。

我已经尝试过自定义LineFormatter:

 f1.getFillPaint().setStrokeJoin(Join.ROUND); f1.getFillPaint().setStrokeWidth(8); 

但是这并没有如预期的那样奏效。

在这里输入图像说明

注意: Wifi分析器应用程序有一个类似的graphics,它的graphics有我想要的圆angular。 它看起来像这样:

在这里输入图像说明

    您可以使用Path.cubicTo()方法。 它使用三次样条algorithm绘制一条线,从而产生所需的平滑效果。

    在这里检查一个类似的问题的答案,一个人在谈论三次样条。 有一个简短的algorithm显示如何计算Path.cubicTo()方法的input参数。 您可以使用分频器值来获得所需的平滑度。 例如,在下面的图片中,我除以5而不是3。希望这有助于。

    使用Path.cubicTo()方法绘制的polylyne示例

    我花了一些时间,并实现了一个SplineLineAndPointFormatter类,它可以完成你在androidplot库中所需要的东西。 它使用相同的工艺。 这是androidplot示例应用程序的样子。 您只需要使用它而不是LineAndPointFormatter

    带有SplineLineAndPointFormatter的Androidplot示例

    这里是代码示例和我写的类。

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

    这是做魔术课。 它基于androidplot库的0.6.1版本。

     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); } } } 

    1-我猜你只用了几个点来绘制信号图。 所有图表/图表应用程序尝试用直线连接点,然后显示您的图表。 所以如果你只使用三点,你的graphics将看起来像一个三angular形! 如果你想要你的graphics是弯曲的,你必须添加更多的点。 然后它就像曲线一样出来。

    2-或者你可以find任何可以绘制sin图的库,例如GraphView Library 。 然后尝试画这个function:

    在这里输入图像说明

    所以看起来像这样:

    在这里输入图像说明

    然后将其翻译为(a,0) ,所以结果看起来像你想要的。

    3-另一种方法,你可以使用Java中内置的Math.sin

    在范围abselect例如1000点,并为每个点计算上述函数的值,最后创build一个path并将其显示在canvas上。

    您可以使用quadTo(float x1,float y1,float x2,float y2)来简化绘制quad curves 。 该文件说:

    从最后一个点开始,接近控制点(x1,y1),结束于(x2,y2),添加一个二次贝塞尔曲线。 如果此轮廓未进行moveTo()调用,则第一个点将自动设置为(0,0)。

    参数

    x1二次曲线上控制点的x坐标
    y1二次曲线上控制点的y坐标
    x2二次曲线上终点的x坐标
    y2二次曲线上终点的y坐标

    最后,我添加一个扩展View的简单类,并绘制一条看起来像你想要的曲线:

     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); } } 

    结果必须如下所示:

    在这里输入图像说明

    你可以添加更多的方法,并改变它来提高性能!

    在Androidplot中总是有一个stream畅的线条渲染器:BezierLineAndPointRenderer,就像上面的实现一样,它使用了Bezier中绘制的例程cubicTo(…)quadTo(…) 。 问题在于,用这种方法使用贝塞尔来画平滑的线条会产生一个虚假的线条,通过改变金额来超过实际的控制点,如果仔细观察上面的图像,就会发现这一点。

    解决scheme是使用现在最终由Androidplot支持的Catmull-Rom样条插值。 详情在这里: http : //androidplot.com/smooth-curves-and-androidplot/

    只需使用ChartFactory.getCubeLineChartView而不是使用Achart引擎的ChartFactory.getLineChartView

    尝试这个:

     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); 

    大部分信息在这里find