Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas.drawLines displaying disjointed segments [duplicate]

Possible Duplicate:
Android How to draw a smooth line following your finger

I'm new to Android and java programming and have been playing around a bit with mobile app development. I recently created a View which simply keeps draws lines in step with the user's finger movements. However, I've been having some trouble with the Canvas.drawLines method.

Instead of getting a continuous set of lines between all points I am getting more of a dashed pattern with breaks between segments:

Broken Line Segments in Canvas.DrawLines

Here is a sample set of data and simple code to reproduce the issue (point data was taken from a real finger swipe):

public class SomeView extends android.view.View 
{
    private float[] _data = { 292.36545f, 104.37576f, 285.3567f, 112.39249f, 274.34293f, 113.39456f, 254.3179f, 115.39874f, 248.3104f, 116.40082f, 228.28535f, 118.405f, 214.26784f, 119.407104f, 211.26408f, 119.407104f, 204.25533f, 120.40918f, 202.25282f, 120.40918f, 201.25157f, 121.411255f, 199.24907f, 124.41754f, 197.24657f, 125.41962f, 196.24532f, 130.43005f, 195.24406f, 139.44885f, 197.24657f, 144.45929f };
    private Paint _paint;

    public SomeView( Context c, AttributeSet attrs)
    {
        super( c, attrs );
        _paint = new Paint();
        _paint.setColor(Color.BLUE);
        _paint.setStrokeWidth(6);   
    }   

    @Override
    public void onDraw(Canvas canvas)
    {       
        canvas.drawLines( _data, _paint);
    }           
}

After plotting out each point and overlaying it atop the line I realized that the problem is actually that each point is not being connected, only every two points. Instead of connecting point 1 to point 2 to point 3 and so on, the method is connecting 1 to 2 and then 3 to 4 as shown below:

enter image description here

I can almost get what I want by drawing calling drawLines again and providing an offset this time so that the other pairs are drawn together as well, but this seems inefficient and generally clunky to me, and the line still isn't completely smooth (gets slightly choppy on corners).

So, my question is; what am I doing wrong and how can I draw a simple, smooth line given some number of points? Heck, forget the points, if there is a better way to trace the user's finger with a line I am all ears. Thanks in advance.

like image 245
Ed S. Avatar asked May 29 '11 10:05

Ed S.


2 Answers

What you get is exactly what is specified in the drawLines documentation.

One way of doing what you want would be to construct a Path from that data, and use drawPath rather than drawLines. Something like:

Path _path = new Path();
_path.moveTo(_data[0], _data[1]);
for (int i=2; i<_data.length; i+=2) {
  _path.lineTo(_data[i], _data[i+1]);
}

Then draw it with:

_canvas.drawPath(_path, _paint)

From the Path docs:

The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style)

So you might have to change you're paint's style to get the right effect.

like image 66
Mat Avatar answered Sep 18 '22 14:09

Mat


I just ran into this issue tonight. For anyone else facing this, the problem is that Android doesn't draw from point 1 to point 2, then point 2 to point 3, point 3 to point 4, etc. It will draw point 1 to 2, then point 3 to 4, etc. So you can also push the previous point twice into whatever data structure you use (I used Vector). So:

private Vector<Float> mPoints = new Vector<Float>();
private float mLastX = Float.NaN;
private float mLastY = Float.NaN;

public void addPoint(float x, float y) {
    if (mLastX == Float.NaN || mLastY == Float.NaN) {
        mLastX = x;
        mLastY = y;
    } else {
        mPoints.add(mLastX);
        mPoints.add(mLastY);
        mPoints.add(x);
        mPoints.add(y);

        mLastX = x;
        mLastY = y;
    }
}

Then just make sure to convert your mPoints to a float[] and pass that to canvas.drawLines().

like image 35
MCLLC Avatar answered Sep 20 '22 14:09

MCLLC