Is there any way to get the endpoints of a line when using Path class?

放肆的年华 提交于 2021-02-11 13:00:53

问题


I am building an app where a user can draw lines in a custom canvas with a finger (multiple fragments have a canvas and this works) using the Path class.

I also managed to use SharedPreferences to save and load the drawn lines but when loaded the lines start from the top left (i.e (0, 0)) and the shape has changed to lines with a slight curve at the start (I say start because I found that the line ends from where the touch started).

The start points are kept in Path but from what I can see there are no endpoints kept. Is there any way I can get the endpoints?

I have previously tried passing the required variables to another ArrayList that uses another constructor with the endpoints (found with a method used for when the finger stops touching the screen) but the drawings no longer showed on the canvas unlike before.

Edit

I have changed to finding multiple points as I believe that getting the endpoint won't be enough and have altered the shown code to show my attempt with getPosTan but no drawings get shown as the elements in testing are null for some reason, so it won't go in the else.

Update

I found that pathMeasure.getLength() produces 0.0 so it isn't going into the while and therefore resulting in null elements but I don't know why it's producing 0.0 as somePath isn't null

PaintView.java

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;



public class PaintView extends View {

public static int BRUSH_SIZE = 10;
public static final int DEFAULT_COLOR = Color.WHITE;
public static int DEFAULT_BG_COLOR = Color.GRAY;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private static ArrayList<FingerPath> paths = new ArrayList<>();
private int currentColor;
private int backgroundColor = DEFAULT_BG_COLOR;
private int strokeWidth;
private boolean emboss;
private boolean blur;
private MaskFilter mEmboss;
private MaskFilter mBlur;
private Bitmap mBitmap;
public Canvas mCanvas;
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);



public PaintView(Context context) {
    this(context, null);

}

public PaintView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);

    mPaint.setColor(DEFAULT_COLOR);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setXfermode(null);
    mPaint.setAlpha(0xff);

    mEmboss = new EmbossMaskFilter(new float[] {1, 1, 1}, 0.4f, 6, 3.5f);
    mBlur = new BlurMaskFilter(5, BlurMaskFilter.Blur.NORMAL);

}

public ArrayList getPaths() {
    return paths;

}

public ArrayList setPaths(ArrayList<FingerPath> list) {


    return this.paths = list;
}

public void init(DisplayMetrics metrics) {
    int height = metrics.heightPixels;
    int width = metrics.widthPixels;

    mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);

    loadDrawing(mCanvas);

    currentColor = DEFAULT_COLOR;
    strokeWidth = BRUSH_SIZE;
}

public void normal() {
    emboss = false;
    blur = false;

}



public void clear() {
    backgroundColor = DEFAULT_BG_COLOR;
    paths.clear();
    normal();
    invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.save();
    mCanvas.drawColor(backgroundColor);

        for (FingerPath fp : paths) {

            mPaint.setColor(fp.color);
            mPaint.setStrokeWidth(fp.strokeWidth);
            mPaint.setMaskFilter(null);

            if (fp.emboss)
                mPaint.setMaskFilter(mEmboss);
            else if (fp.blur)
                mPaint.setMaskFilter(mBlur);

            mCanvas.drawPath(fp.path, mPaint);
        }




    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

    canvas.restore();
}

private void touchStart(float x, float y) {
    mPath = new Path();
    FingerPath fp = new FingerPath(currentColor, emboss, blur, strokeWidth, mPath, x, y);

    paths.add(fp);

    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
}

private void touchMove(float x, float y) {
    float dx = Math.abs(x-mX);
    float dy = Math.abs(y-mY);

    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        mX = x;
        mY = y;
    }
}

private void touchUp() {mPath.lineTo(mX, mY);}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN :
            touchStart(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE :
            touchMove(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP :
            touchUp();
            invalidate();
            break;
    }

    return true;
}

private FloatPoint[] getPoint(Path somePath, float x, float y){
    FloatPoint[] pointArray = new FloatPoint[20];
    PathMeasure pathMeasure = new PathMeasure(somePath, false);
    float length = pathMeasure.getLength();
    float distance = 0f;
    float speed = length / 20;
    int counter = 0;
    float[] aCoordinates = {x, y};

    while ((distance < length) && (counter < 20)) {
        pathMeasure.getPosTan(distance, aCoordinates, null);
        pointArray[counter] = new FloatPoint(aCoordinates[0], 
aCoordinates[1]);
        counter++;
        distance = distance + speed;
    }



    return pointArray;
}

public void loadDrawing(Canvas canvas) {
    if (mCanvas != null) {


        currentColor = DEFAULT_COLOR;
        strokeWidth = BRUSH_SIZE;
        if (! paths.isEmpty()) {
            canvas.save();
            mCanvas.drawColor(backgroundColor);




            for (FingerPath fp : paths) {
                mPaint.setColor(fp.color);
                mPaint.setStrokeWidth(fp.strokeWidth);
                mPaint.setMaskFilter(null);

                if (fp.emboss)
                    mPaint.setMaskFilter(mEmboss);
                else if (fp.blur)
                    mPaint.setMaskFilter(mBlur);

                  

                FloatPoint[] testing = getPoint(fp.path, fp.x, fp.y);

                    //need to figure out how to for loop testing
                float sectionTestX = 0.0f;
                float sectionTestY = 0.0f;

                for (FloatPoint testingPoint : testing) {
                    if (sectionTestX == 0.0f && sectionTestY == 0.0f) {
                        sectionTestX = testingPoint.getX();
                        sectionTestY = testingPoint.getY();
                        continue;
                    } else {

                        fp.path.quadTo(sectionTestX, sectionTestY, 
testingPoint.getX(), testingPoint.getY());

                        sectionTestX = testingPoint.getX();
                        sectionTestY = testingPoint.getY();
                    }

                }

                    /*xTest = fp.x;
                    yTest = fp.y;*/

            }




            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

            canvas.restore();
        }

    }
}




}

FloatPoint.java

public class FloatPoint {

static float x, y;

public FloatPoint(float x, float y) {
    this.x = x;
    this.y = y;
}

public static float getX() {
    return x;
}

public static float getY() {
    return y;
}
}

来源:https://stackoverflow.com/questions/65039195/is-there-any-way-to-get-the-endpoints-of-a-line-when-using-path-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!