Как получить общую площадь при рисовании на холсте андроида?
Im, используя ниже код, чтобы нарисовать линию на холсте растрового изображения, пока движение пальца коснется... здесь я опубликовал частичный код, и он отлично работает.
Как показано на рисунке ниже, черно-белое растровое изображение стирается при касании. Я сделал холст прозрачным, так что становится понятным исходный макет (цветное изображение).
Я хочу знать, сколько области стерто (например, 50% или 60% растрового изображения). Есть ли способ найти это?
![enter image description here]()
//Erasing paint
mDrawPaint = new Paint();
mDrawPaint.setAntiAlias(true);
mDrawPaint.setDither(true);
mDrawPaint.setStyle(Paint.Style.STROKE);
mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
mDrawPaint.setStrokeWidth(50);
mDrawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
BlurMaskFilter mBlur = new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL);
mDrawPaint.setMaskFilter(mBlur);
private void doDraw(Canvas c) {
c.drawBitmap(mBitmap, 0, 0,null );
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 1;
void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
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;
}
canvas.drawPath(mPath, mDrawPaint ); //Erasing Black and white image
}
void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mDrawPaint);
// kill this so we don't double draw
mPath.reset();
}
Ответы
Ответ 1
Попробуйте использовать метод Монте-Карло, чтобы оценить процент прозрачной области. Я думаю, что это самый быстрый и простой способ сделать это. Возьмите около 50 (в зависимости от требуемой точности) случайных пикселей на маске прозрачности и проверьте их цвет. Затем выполните вычисление ans = TransparentPixelsCount/TestPixelCount.
Очень сложно вычислить квадрат пользовательских чертежей, используя координаты пути. И довольно долго, чтобы перебирать все пиксели. Итак, IMHO Monte Carlo - ваш выбор.
Ответ 2
Чтобы получить точный (и медленный) ответ, вам нужно проверить каждый пиксель и подсчитать количество прозрачных и разделить на общее количество пикселей. Если ваши требования позволяют оценить, вероятно, лучше всего пробовать изображение.
Вы можете уменьшить размер изображения и выполнить и описанную выше процедуру на меньшем изображении. Это имеет тот недостаток, что операция масштабирования может проходить через все пиксели, что замедляет работу. Я бы рекомендовал выборку сетки, она похожа на сокращение, но пропускает пиксели. В принципе, мы равномерно размещаем x выборок точек на сетке над изображением. Затем подсчитайте количество прозрачных точек выборки. Оценка прозрачного процента - это суммарные прозрачные образцы/количество прозрачных образцов. Вы можете получить разумную точность (обычно в пределах 5%) с небольшим количеством, скажем, 100 образцов. Вот функция кода, которая реализует этот метод - bm - это Bitmap
и scale
- количество выборок на ось, поэтому установка scale = 10
дает 100 общих выборок (сетка для выборки 10x10 по изображению).
static public float percentTransparent(Bitmap bm, int scale) {
final int width = bm.getWidth();
final int height = bm.getHeight();
// size of sample rectangles
final int xStep = width/scale;
final int yStep = height/scale;
// center of the first rectangle
final int xInit = xStep/2;
final int yInit = yStep/2;
// center of the last rectangle
final int xEnd = width - xStep/2;
final int yEnd = height - yStep/2;
int totalTransparent = 0;
for(int x = xInit; x <= xEnd; x += xStep) {
for(int y = yInit; y <= yEnd; y += yStep) {
if (bm.getPixel(x, y) == Color.TRANSPARENT) {
totalTransparent++;
}
}
}
return ((float)totalTransparent)/(scale * scale);
}
Для справки, медленный метод, который даст вам результаты путем подсчета каждого пикселя, приведен ниже. Его можно использовать для справки при тестировании вышеуказанной оценки.
static public float percentTransparent(Bitmap bm) {
final int width = bm.getWidth();
final int height = bm.getHeight();
int totalTransparent = 0;
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
if (bm.getPixel(x, y) == Color.TRANSPARENT) {
totalTransparent++;
}
}
}
return ((float)totalTransparent)/(width * height);
}
Ответ 3
Другой подход к этому: вы можете рассчитать размер каждого пути, используя ComputeBounds. Тогда это должно быть просто сравнить это с размером вашего вида и решить% чертежа.
Jus вам нужно иметь в виду, что путь можно нарисовать над собой, поэтому вам нужно быть осторожным и обрабатывать это при вычислении.
Ответ 4
Сохраните все значения x и y точки в двух разных отсортированных наборах, один для x значения точки и другой для значения y для точки.
Конечным значением вашей привязки будет точка (min_x, min_y) и точка (max_x, max_y).
Ответ 5
Вам нужно определить точки, лежащие внутри вытянутого многоугольника.
Вот функции, которые принимают массив, содержащий всю вытащенную точку, а второй параметр - это сами точки, т.е. X, y.
// Return true if the dot { x,y } is within any of the polygons in the list
function pointInPolygons( polygons, dot )
for (i=1, [polygons count] i++)
{
if (pointInPolygon( polygons[i], dot ))
return true
}
return false
end
// Returns true if the dot { x,y } is within the polygon
//defined by points table { {x,y},- --{x,y},{x,y},... }
function pointInPolygon( points, dot )
local i, j = #points, #points
local oddNodes = false
for i=1, #points do
if ((points[i].y < dot.y and points[j].y>=dot.y
or points[j].y< dot.y and points[i].y>=dot.y) and (points[i].x<=dot.x
or points[j].x<=dot.x)) then
if (points[i].x+(dot.y-points[i].y)/(points[j].y-points[i].y)*(points[j].x-points[i].x)<dot.x) then
oddNodes = not oddNodes
end
end
j = i
end
return oddNodes
end