0

这实际上是我们的论文,我们需要使用 Ramer-Douglas-Peucker 算法来简化行,任何人都可以帮助我如何在 Android 应用程序中实现这一点。

我只想知道如何从我绘制的线中获取点串,并通过减少总数来简化线。根据下面给定的代码点?

这是主要课程。

public class SketchTimeNewActivity extends GraphicsView implements ColorOption.OnColorChangedListener {

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

    myPaint = new Paint();
    myPaint.setAntiAlias(true);
    myPaint.setDither(true);
    myPaint.setColor(Color.CYAN);
    myPaint.setStyle(Paint.Style.STROKE);
    myPaint.setStrokeJoin(Paint.Join.ROUND);
    myPaint.setStrokeCap(Paint.Cap.ROUND);
    myPaint.setStrokeWidth(12); 
}

private Paint       myPaint;    

    public void colorChanged(int color) {
    myPaint.setColor(color);
}


public class MyView extends View {

    private static final float MINP = 0.25f;
    private static final float MAXP = 0.75f;

    private Bitmap  mBitmap;
    private Canvas  mCanvas;
    private Path    mPath;
    private Paint   mBitmapPaint;

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

        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
    protected void onSizeChanged(int width, int height, int oldwidth, int oldheight) {
        super.onSizeChanged(width, height, oldwidth, oldheight);
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(color.black);

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

        canvas.drawPath(mPath, myPaint);
    }

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

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }
    private void touch_move(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 touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, myPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

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

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
        }
        return true;
    }
}

private static final int COLOR_MENU_ID = Menu.FIRST;
private static final int EXISTING_MENU_ID = Menu.FIRST + 2;
private static final int ENHANCED_MENU_ID = Menu.FIRST + 3;
private static final int ERASE_MENU_ID = Menu.FIRST + 1;


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('1', 'c');
    menu.add(0, EXISTING_MENU_ID, 0, "Enhanced").setShortcut('2', 's');
    menu.add(0, ENHANCED_MENU_ID, 0, "Existing").setShortcut('3', 'z');
    menu.add(0, ERASE_MENU_ID, 0, "Erase").setShortcut('4', 'z');

    return true;
}



@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    return true;
}



@Override
public boolean onOptionsItemSelected(MenuItem item) {
    myPaint.setXfermode(null);
    myPaint.setAlpha(0xFFAAAAAA);

单击现有菜单时,它将简化正在绘制的线并显示具有较少点的线或已简化的线。我打算为它创建一个新类,但我不知道如何从画布中绘制的线中获取点串。

    switch (item.getItemId()) {

        case COLOR_MENU_ID:
            new ColorOption(this, this, myPaint.getColor()).show();
            return true;

  /**      case EXISTING_MENU_ID:

            return true;

        case ENHANCED_MENU_ID:

            return true;*/

        case ERASE_MENU_ID:{

                  myPaint.setColor(color.black);
                  myPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                  return true;
              }

    }

    return super.onOptionsItemSelected(item);
}

}
4

1 回答 1

0

从我的原始评论中复制粘贴以获取某些上下文:

您正在从 onTouchEvent 生成线上的点,因此与其尝试在之后查询 Canvas,为什么不简单地保留这些创建点的列表?您可以在绘制每个新线段时添加一个点。

就代码而言,您最基本的示例将如下所示:

List<Point> mPoints = new ArrayList<Point>();

private void touch_up() {
    // save this point on the line
    mPoints.add(new Point(mX, mY);
    // add point to path
    mPath.lineTo(mX, mY);
    // commit the path to our offscreen
    mCanvas.drawPath(mPath, myPaint);
    // kill this so we don't double draw
    mPath.reset();
}

我在这里假设 touch_up() 是将每个线段的起点或终点添加到路径的位置。

//编辑:再次阅读您的问题后,我觉得您可能会要求您绘制的线上的所有点 - 因为您的代码片段包含曲线?我的猜测是,实现这一点的唯一方法是使用不同的基础数学方程评估每个 (x,y) 并存储每个点的结果。换句话说:通过编写自己的 lineTo 和 quadTo 函数。

对于直线,这相对微不足道,但曲线会增加难度。您可能想查看 Path 的源代码,它在内部将大部分工作委托给了一个java.awt.geom.GeneralPath对象。

于 2011-12-23T21:18:56.340 回答