So glätten Sie den Zeichenpfad beim Zeichnen mit variabler Strichbreite

Ich habe eine Beispiel-Zeichen-App erstellt, in der Benutzer mit variabler Strichbreite zeichnen können. Bisher funktioniert der Zeichenpfad mit variablem Strich, aber die gezeichneten Linien sind nicht glatt. Der Code, den ich verwendet habe, um das zu erreichen, ist unten gezeigt.

Helfen Sie mir, das in den letzten zwei Tagen zu klären.

Code zum Zeichnen des Pfads mit variabler Strichbreite

public class FingerPaint extends GraphicsActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }

    public void colorChanged(int color)  {
    }

    public class MyView extends View {

        private static final float STROKE_WIDTH = 5f;    
        private Paint paint = new Paint();
        private Path mPath = new Path();
        ArrayList<Path> mPaths = new ArrayList<Path>();
        ArrayList<Integer> mStrokes = new ArrayList<Integer>();

        private float lastTouchX;
        private float lastTouchY;
        private final RectF dirtyRect = new RectF();
        private int lastStroke = -1;
        int variableWidthDelta = 0;

        private static final float STROKE_DELTA = 0.0001f; // for float comparison
        private static final float STROKE_INCREMENT = 0.01f; // amount to interpolate
        private float currentStroke = STROKE_WIDTH;
        private float targetStroke = STROKE_WIDTH;

        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;

        public MyView(Context context)  {
            super(context);

            paint.setAntiAlias(true);
            paint.setDither(true);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeJoin(Paint.Join.ROUND);
            paint.setStrokeCap(Paint.Cap.ROUND);    
            paint.setStrokeWidth(STROKE_WIDTH);
        }

        public void clear() {
            mPath.reset();
            // Repaints the entire view.
            invalidate();
        }

        @Override
        protected void onDraw(Canvas canvas)  {
            for(int i=0; i<mPaths.size();i++) {
                paint.setStrokeWidth(mStrokes.get(i));
                canvas.drawPath(mPaths.get(i), paint);
            }
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float eventX = event.getX();
            float eventY = event.getY();
            int historySize = event.getHistorySize();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    resetDirtyRect(eventX, eventY);
//                  mPath.reset();
                    mPath.moveTo(eventX, eventY);
                    mX = eventX;
                    mY = eventY;
                    break;                  
                }
                case MotionEvent.ACTION_MOVE: {                 
                    if (event.getPressure()>=0.00 && event.getPressure()<0.05) {
                        variableWidthDelta = -2;
                    } else if (event.getPressure()>=0.05 && event.getPressure()<0.10) {
                        variableWidthDelta = -2;
                    } else if (event.getPressure()>=0.10 && event.getPressure()<0.15) {
                        variableWidthDelta = -2;
                    } else if (event.getPressure()>=0.15 && event.getPressure()<0.20) {
                        variableWidthDelta = -2;
                    } else if (event.getPressure()>=0.20 && event.getPressure()<0.25) {
                        variableWidthDelta = -2;
                    } else if (event.getPressure() >= 0.25 && event.getPressure()<0.30) {
                        variableWidthDelta = 1;
                    } else if (event.getPressure() >= 0.30 && event.getPressure()<0.35) {
                        variableWidthDelta = 2;
                    } else if (event.getPressure() >= 0.35 && event.getPressure()<0.40) {
                        variableWidthDelta = 3;
                    } else if (event.getPressure() >= 0.40 && event.getPressure()<0.45) {
                        variableWidthDelta = 4;
                    } else if (event.getPressure() >= 0.45 && event.getPressure()<0.60) {
                        variableWidthDelta = 5;
                    }                                          

                    // if current not roughly equal to target
                    if( Math.abs(targetStroke - currentStroke) > STROKE_DELTA ) 
                    {
                        // move towards target by the increment
                        if( targetStroke > currentStroke)
                        {
                            currentStroke = Math.min(targetStroke, currentStroke + STROKE_INCREMENT);
                        }
                        else
                        {
                            currentStroke = Math.max(targetStroke, currentStroke - STROKE_INCREMENT);
                        }

                    } 
                    mStrokes.add((int) currentStroke);

                    targetStroke = variableWidthDelta;

                    float dx = Math.abs(eventX - mX);
                    float dy = Math.abs(eventY - mY);

                    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                        if(lastStroke != variableWidthDelta) {
                            mPath.lineTo(mX, mY);

                            mPath = new Path();
                            mPath.moveTo(mX,mY);
                            mPaths.add(mPath);
                        }

                        mPath.quadTo(mX, mY, (eventX + mX)/2, (eventY + mY)/2);
                        mX = eventX;
                        mY = eventY;
                    }

                    for (int i = 0; i < historySize; i++) {
                        float historicalX = event.getHistoricalX(i);
                        float historicalY = event.getHistoricalY(i);
                        expandDirtyRect(historicalX, historicalY);
                    }
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    for (int i = 0; i < historySize; i++) {
                        float historicalX = event.getHistoricalX(i);
                        float historicalY = event.getHistoricalY(i);
                        expandDirtyRect(historicalX, historicalY);
                    }
                   mPath.lineTo(mX, mY);                   
                   break;
                }
            }

            // Include half the stroke width to avoid clipping.
            invalidate();

            lastTouchX = eventX;
            lastTouchY = eventY;
            lastStroke = variableWidthDelta;

            return true;
        }

        private void expandDirtyRect(float historicalX, float historicalY) {
            if (historicalX < dirtyRect.left) {
                dirtyRect.left = historicalX;
            }  else if (historicalX > dirtyRect.right) {
                dirtyRect.right = historicalX;
            }
            if (historicalY < dirtyRect.top) {
                dirtyRect.top = historicalY;
            } else if (historicalY > dirtyRect.bottom) {
                dirtyRect.bottom = historicalY;
            }
        }

        /**
         * Resets the dirty region when the motion event occurs.
         */
        private void resetDirtyRect(float eventX, float eventY) {
            // The lastTouchX and lastTouchY were set when the ACTION_DOWN
            // motion event occurred.
            dirtyRect.left = Math.min(lastTouchX, eventX);
            dirtyRect.right = Math.max(lastTouchX, eventX);
            dirtyRect.top = Math.min(lastTouchY, eventY);
            dirtyRect.bottom = Math.max(lastTouchY, eventY);
        }
    }
}

Ausgabeergebnis, das ich bekam

Ausgabe, die ich erzielen möchte

Antworten auf die Frage(2)

Ihre Antwort auf die Frage