Search code examples
androidcanvaspathtouch-event

how to draw brushes or shape using path when moving finger fast in andorid canvas (generate missing point when user move finger fast)


Im really confuse that how can i draw professional brushes in android, im drawing circle using path when user moves its finger on screen but when user move its finger slow the number of circle increase and when user move finger fast the number of circle is very less, suppose user moves it finger very fast ther will be only 6 7 circle on that path but if user moves it finger slowly ther will be 30/40 or more circle on the path, which seems very buggy, is this is possible that moveing finger fast stores less points? but if i talk about line , the line on canvas draw prefectly while user moves it finger fast or slow, im sharing my code below

    private void DrawCircleBrush(List<PointF> points) {
    PointF p1 = points.get(0);
    PointF p2 = points.get(1);

    Path path = new Path();
    path.moveTo(p1.x, p1.y);

    for (int i = 1; i < points.size(); i++) {
        int rc = (int) (20 +(this.paintStrokeWidth/5));
        path.addCircle(p1.x, p1.y, (float) rc, Path.Direction.CCW);
    }

    this.invalidate();

}

I call DrawCircleBrush Fucnion on action_move like this

path.reset();
points.add(new PointF(x, y));
DrawCircleBrush(points);

You can see the difference of fast moving and slow moving finger in attached picture.

here is the difference of fast moving finger and slow moving finger

What i want to Achive you can see in this photo, as the brush draw same in this app when i move finger fast or slow,

This is what i want to achive


Solution

  • Ok At last i find solution. this is how im getting all the points , note that this a theorem called Bresenham's line algorithm and its only works with integer, this is how im getting all the point , move finger fast or slow point will always be same :D

    //x0,y0 , is the starting point and x1,y1 are current points
    
    public List<PointF> findLine( int x0, int y0, int x1, int y1)
    {
        List<PointF> line = new ArrayList<PointF>();
    
        int dx = Math.abs(x1 - x0);
        int dy = Math.abs(y1 - y0);
    
        int sx = x0 < x1 ? 1 : -1;
        int sy = y0 < y1 ? 1 : -1;
    
        int err = dx-dy;
        int e2;
    
        while (true)
        {
    
            line.add(new PointF(x0,y0));
    
            if (x0 == x1 && y0 == y1)
                break;
    
            e2 = 2 * err;
            if (e2 > -dy)
            {
                err = err - dy;
                x0 = x0 + sx;
            }
    
            if (e2 < dx)
            {
                err = err + dx;
                y0 = y0 + sy;
            }
        }
        return line;
    }
    

    How im using this function for my brush,

                 //radius of circle
                int rc = (int) (20 +(this.paintStrokeWidth/5));
                //getting the points of line
                List<PointF> pointFC =findLine((int)this.startX,(int) this.startY,(int) x, 
                (int) y);
                //setting the index of first point
                int p1 = 0;
                //will check if change occur
                boolean change = false;
    
                for(int l=1; l<pointFC.size(); l++){
    
                    //getting distance between two pints 
                    float d = distanceBetween(pointFC.get(p1),pointFC.get(l));
                    if(d>rc){
                        // we will add this point for draw
                        //point is a list of PointF //declared universally
                        points.add(new PointF(pointFC.get(l).x,pointFC.get(l).y));
                        we will change the index of last point
                        p1 = l-1;
                        change = true;
    
                    }
                }
                if(points.size() >0){
                    path.reset();
                    DrawCircleBrush(points);
                }
    
                if(change){
                    we will cahnge the starts points, //set them as last drawn points
                    this.startX = points.get(points.size()-1).x;
                    this.startY = points.get(points.size()-1).y;
                }
    
       //Distance betwenn points
       private float distanceBetween(PointF point1,PointF point2) {
            return (float) Math.sqrt(Math.pow(point2.x - point1.x, 2) +  
            Math.pow(point2.y - point1.y, 2));
        }
    
    //this is how im drawing my circle brush
    private void DrawCircleBrush(List<PointF> points) {
    
            Path path = this.getCurrentPath();
            path.moveTo(points.get(0).x, points.get(0).y);
    
            for (int i = 1; i < points.size(); i++) {
                PointF pf = points.get(i);
                int rc = (int) (20 +(this.paintStrokeWidth/5));
                path.addCircle(pf.x, pf.y, (float) rc, Path.Direction.CCW);
    
            }
        }
    

    Result: brush is same even move finger fast or slow Moving finger fast or slow no difference