Я использую следующий код, чтобы нарисовать путь на основе изменений ширины переменной на холсте. Пока все работает отлично, и я могу легко рисовать путь с помощью этого кода.Кривые сломаны при рисовании пути в холсте
Но нарисованный путь не является гладким, особенно когда я рисую изогнутый путь, все линии выглядят сломанными. Почему это происходит? Что-то не так в моем коде?
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 implements OnTouchListener
{
private static final float STROKE_WIDTH = 3f;
private Paint paint = new Paint();
private Path mPath = new Path();
ArrayList<Path> mPaths = new ArrayList<Path>();
private Canvas m_CanvasView;
private Bitmap m_CanvasBitmap;
int variableWidthDelta = 1;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
ArrayList<Point> points = new ArrayList<Point>(64);
public MyView(Context context)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
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);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
m_CanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
m_CanvasView = new Canvas(m_CanvasBitmap);
}
@Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(m_CanvasBitmap, 0f, 0f, null);
m_CanvasView.drawPath(mPath, paint);
}
public boolean onTouch(View arg0, MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
break;
}
case MotionEvent.ACTION_MOVE:
{
if (event.getPressure()>=0.00 && event.getPressure()<0.05)
{
variableWidthDelta = 1;
}
else if (event.getPressure()>=0.05 && event.getPressure()<0.10)
{
variableWidthDelta = 1;
}
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 = 1;
}
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 = 2;
}
else if (event.getPressure() >= 0.40 && event.getPressure()<0.45)
{
variableWidthDelta = 3;
}
else if (event.getPressure() >= 0.45 && event.getPressure()<0.50)
{
variableWidthDelta = 4;
}
paint.setStrokeWidth(STROKE_WIDTH + variableWidthDelta);
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
points.add(new Point(event.getX(), event.getY()));
mPath = new Path();
mPath = generatePath();
}
break;
}
case MotionEvent.ACTION_UP:
{
break;
}
}
invalidate();
return true;
}
class Point
{
public final float x;
public final float y;
public Point(float x, float y)
{
this.x = x;
this.y = y;
}
}
public Path generatePath()
{
final float tangentScale = 0.3F;
int pointcount = points.size();
mPath.moveTo(points.get(0).x, points.get(0).y);
mPath.cubicTo(
points.get(0).x + (points.get(1).x - points.get(0).x)*tangentScale,
points.get(0).y + (points.get(1).y - points.get(0).y)*tangentScale,
points.get(1).x - (points.get(2).x - points.get(0).x)*tangentScale,
points.get(1).y - (points.get(2).y - points.get(0).y)*tangentScale,
points.get(1).x, points.get(1).y
);
for(int p=2; p<pointcount-1; p++)
{
mPath.cubicTo(
points.get(p-1).x + (points.get(p).x - points.get(p-2).x)*tangentScale,
points.get(p-1).y + (points.get(p).y - points.get(p-2).y)*tangentScale,
points.get(p).x - (points.get(p+1).x - points.get(p-1).x)*tangentScale,
points.get(p ).y - (points.get(p+1).y - points.get(p-1).y)*tangentScale,
points.get(p).x, points.get(p).y
);
}
mPath.cubicTo(
points.get(pointcount-2).x + (points.get(pointcount-1).x - points.get(pointcount-3).x)*tangentScale,
points.get(pointcount-2).y + (points.get(pointcount-1).y - points.get(pointcount-3).y)*tangentScale,
points.get(pointcount-1).x - (points.get(pointcount-1).x - points.get(pointcount-2).x)*tangentScale,
points.get(pointcount-1).y - (points.get(pointcount-1).y - points.get(pointcount-2).y)*tangentScale,
points.get(pointcount-1).x, points.get(pointcount-1).y
);
return mPath;
}
}
}
Я делаю некоторые изменения, как вы упоминаете, и да, есть какая-то гладкость в строке, но все же не идеальная. Можете ли вы посмотреть мой отредактированный код, если я что-то пропущу. – AndroidDev
У вас есть возможность увидеть мои изменения. На самом деле я застрял в этом вопросе на прошлой неделе, но могу получить любое правильное решение. – AndroidDev
@Anshuman Попробуйте реализовать некоторую интерполяцию между значениями, я не уверен на 100% о том, как вы оцениваете значения x/HistoricalX. Если этого недостаточно, попробуйте включить аппаратное ускорение, если вы используете уровень API за 10 лет. Также попробуйте оптимизировать ваш код onTouch для повышения скорости. Вы также можете рассмотреть возможность использования второго потока для обработки событий. – Jave