在Canvas上沿着路径绘制位图

3
我正在尝试创建一款绘画应用程序,该应用程序能够在屏幕上沿着触摸路径绘制不同的画笔纹理。
我已经完成的部分:
这是我的自定义视图的代码:
public class TestDrawingView extends View{

private Bitmap mBitmapBrush;
private Vector2 mBitmapBrushDimensions;

private List<Vector2> mPositions = new ArrayList<Vector2>(100);

public TestDrawingView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub

    // load your brush here
    mBitmapBrush = BitmapFactory.decodeResource(context.getResources(), R.drawable.test_sand_brush);
    mBitmapBrushDimensions = new Vector2(10, 10);

    setBackgroundColor(0xffffffff);

}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    for (Vector2 pos : mPositions) {
        canvas.drawBitmap(mBitmapBrush, pos.x, pos.y, null);
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    int action = event.getAction();
    switch (action) {
    case MotionEvent.ACTION_MOVE:
        final float posX = event.getX();
        final float posY = event.getY();
        mPositions.add(new Vector2(posX - mBitmapBrushDimensions.x / 2, posY - mBitmapBrushDimensions.y / 2));
        invalidate();
    }

    return true;
}

private static final class Vector2 {
    public Vector2(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public final float x;
    public final float y;

}
}

我从这个问题中获取了这个示例代码:如何在Android中为画布制作自定义画笔? 我使用的纹理图像如下:
enter image description here 我得到的结果如下:
enter image description here 我想要实现的结果如下:
enter image description here 非常感谢任何帮助。

@aoeu(http://stackoverflow.com/users/905619/aoeu)请分享您的看法。 - Salman Khakwani
1个回答

4
在每个注册的触摸位置上绘制一个位图是一个好的开始,但为了创建类似于您在此处看到的平滑效果,您需要在这里有更多的逻辑。我将为您概述一些步骤:
  1. 您将需要更多的位图。一个(或可能是几个)位图将表示您正在尝试绘制的实际线条。如果有更多,则效果将更好,因为线条的每个段看起来都不同。然后,另一个用于线条边缘的位图。
  2. 确保按照您收到的输入对顶点列表进行排序(不确定您是否已经执行此操作)。此外,您应该检查列表,如果相邻两点之间的距离小于您正在绘制的位图的半径,则应将该点忽略,因为它对您的绘图没有太大影响。您可能希望在将点插入列表时处理此问题,因为它将在渲染过程中节省一些计算时间。
  3. 在第一个顶点点中,放置一个“边缘”位图,然后根据列表中第一个顶点到第二个顶点之间的角度进行旋转。您可以根据以下公式找出角度:Math.atan2(p2.y - p1.y, p2.x - p1.x);
  4. 在第一个点之后的每两个点之间,您需要绘制N个位图,其中N是点i和点i-1之间距离除以位图半径。您需要一个内部循环来运行这么多步,并为每一步生成一个新的X/Y坐标。您可以通过从2个点创建一个归一化向量({p2.x - p1.x,p2.y - p1.y},然后规范化),并在递增步骤中将其添加到p1中来完成此操作。在每个步骤中,绘制一个位图,并根据步骤3中的逻辑进行旋转。如果对于内部线条有多个位图,则随机选择1个。
  5. 在最后一个顶点处,绘制另一个边缘位图,并再次根据步骤3的逻辑进行旋转。
这应该让您开始了解,尽管您可能希望在线条相交的情况下实现更复杂的逻辑-在这种情况下,您可能希望拥有(或构造)一个“交叉”位图,并使用更多逻辑来确定何时发生这种情况以及如何相应地旋转位图。

感谢您的快速回复,您的答案似乎非常有帮助。我正在尝试所有这些提到的步骤。 - Salman Khakwani
1
你的回答非常有帮助。但如果您能提供一些示例代码,那将更加有帮助。 - user7235627

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接