Как нарисовать заполненный треугольник на холсте Android?


87

Итак, я рисую этот треугольник на картах Android, используя приведенный ниже код в моем методе рисования:

paint.setARGB(255, 153, 29, 29);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);

Path path = new Path();
path.moveTo(point1_returned.x, point1_returned.y);
path.lineTo(point2_returned.x, point2_returned.y);
path.moveTo(point2_returned.x, point2_returned.y);
path.lineTo(point3_returned.x, point3_returned.y);
path.moveTo(point3_returned.x, point3_returned.y);
path.lineTo(point1_returned.x, point1_returned.y);
path.close();

canvas.drawPath(path, paint);

PointX_returned - это координаты, которые я получаю из полей. Это в основном широта и долгота. В результате получился красивый треугольник, но инсайдер пуст, поэтому я могу видеть карту. Есть способ как-нибудь его залить?


Как я написал в своем ответе, просто не перемещайте moveTo () после каждой lineTo (), это все, что есть.
oli.G

Я знаю, что это старый вопрос, на который уже есть (неправильный) принятый ответ, и вы также опубликовали свое окончательное решение, которое работает ... но вы не указываете, почему оно работает, и я надеюсь, что мой комментарий может сэкономить кому-то время, которое я только что потратил на это :)
oli.G

Ответы:


41

Вероятно, вам нужно сделать что-то вроде:

Paint red = new Paint();

red.setColor(android.graphics.Color.RED);
red.setStyle(Paint.Style.FILL);

И используйте этот цвет для своего пути, а не для ARGB. Убедитесь, что последняя точка вашего пути заканчивается первой, это тоже имеет смысл.

Подскажите пожалуйста, работает ли!


К сожалению, это не помогает
oli.G

@Nicolas Что использовать вместо ARGB, если нам нужно настроить цвет с помощью значения RGB вместо использования заранее определенных значений?
pallav bohara

75

Хорошо, я сделал это. Я делюсь этим кодом на случай, если он понадобится кому-то еще:

super.draw(canvas, mapView, true);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

paint.setStrokeWidth(2);
paint.setColor(android.graphics.Color.RED);     
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);

Point point1_draw = new Point();        
Point point2_draw = new Point();    
Point point3_draw = new Point();

mapView.getProjection().toPixels(point1, point1_draw);
mapView.getProjection().toPixels(point2, point2_draw);
mapView.getProjection().toPixels(point3, point3_draw);

Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(point1_draw.x,point1_draw.y);
path.lineTo(point2_draw.x,point2_draw.y);
path.lineTo(point3_draw.x,point3_draw.y);
path.lineTo(point1_draw.x,point1_draw.y);
path.close();

canvas.drawPath(path, paint);

//canvas.drawLine(point1_draw.x,point1_draw.y,point2_draw.x,point2_draw.y, paint);

return true;

Спасибо за подсказку, Николас!


7
Я почти уверен, что последнее тебе не нужно lineTo(). close()делает это автоматически.
Timmmm

@Timmmm Я тестировал, вы правы, последний lineTo () не нужен. Спасибо.
banxi1988

Огромное спасибо. Я не знаю, почему у меня было так много проблем с рисованием треугольника, но последние 20 минут я провел с различными ошибками в этой крошечной проблеме.
Ахал Дэйв

1
Вот простой метод копирования-вставки (на основе кода @ Pavel): gist.github.com/ZirconCode/59cae1e2615279eafb29
ZirconCode

1
если вы перешли pathна переменную экземпляра, не забудьте позвонить path.reset()позже canvas.drawPath().
Сира Лам

11

вы также можете использовать vertice:

private static final int verticesColors[] = {
    Color.LTGRAY, Color.LTGRAY, Color.LTGRAY, 0xFF000000, 0xFF000000, 0xFF000000
};
float verts[] = {
    point1.x, point1.y, point2.x, point2.y, point3.x, point3.y
};
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, verts.length, verts, 0, null, 0, verticesColors,   0, null, 0, 0, new Paint());

2
Я не думаю, что это решение обрабатывает заполненные формы. (не могу протестировать, у меня сейчас нет IDE)
Николас С.

3
Это кажется более производительным решением, но, к сожалению, этот метод не поддерживается в представлениях с аппаратным ускорением. Вы можете отключить аппаратное ускорение, но тогда вы потеряете его прирост производительности: developer.android.com/guide/topics/graphics/hardware-accel.html
SurlyDre

8

введите описание изображения здесь

эта функция показывает, как создать треугольник из растрового изображения. То есть создать обрезанное изображение треугольной формы. Попробуйте приведенный ниже код или загрузите демонстрационный пример

 public static Bitmap getTriangleBitmap(Bitmap bitmap, int radius) {
        Bitmap finalBitmap;
        if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
            finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                    false);
        else
            finalBitmap = bitmap;
        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                finalBitmap.getHeight());

        Point point1_draw = new Point(75, 0);
        Point point2_draw = new Point(0, 180);
        Point point3_draw = new Point(180, 180);

        Path path = new Path();
        path.moveTo(point1_draw.x, point1_draw.y);
        path.lineTo(point2_draw.x, point2_draw.y);
        path.lineTo(point3_draw.x, point3_draw.y);
        path.lineTo(point1_draw.x, point1_draw.y);
        path.close();
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawPath(path, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        return output;
    }

Функция выше возвращает треугольное изображение, нарисованное на холсте. Прочитайте больше


7

Используя ответ @Pavel в качестве руководства, вот вспомогательный метод, если у вас нет точек, но есть начало x, y, а также высота и ширина. Также могу рисовать перевернутый / перевернутый - что полезно для меня, так как оно использовалось в конце вертикальной гистограммы.

 private void drawTriangle(int x, int y, int width, int height, boolean inverted, Paint paint, Canvas canvas){

        Point p1 = new Point(x,y);
        int pointX = x + width/2;
        int pointY = inverted?  y + height : y - height;

        Point p2 = new Point(pointX,pointY);
        Point p3 = new Point(x+width,y);


        Path path = new Path();
        path.setFillType(Path.FillType.EVEN_ODD);
        path.moveTo(p1.x,p1.y);
        path.lineTo(p2.x,p2.y);
        path.lineTo(p3.x,p3.y);
        path.close();

        canvas.drawPath(path, paint);
    }

4
private void drawArrows(Point[] point, Canvas canvas, Paint paint) {

    float [] points  = new float[8];             
    points[0] = point[0].x;      
    points[1] = point[0].y;      
    points[2] = point[1].x;      
    points[3] = point[1].y;         
    points[4] = point[2].x;      
    points[5] = point[2].y;              
    points[6] = point[0].x;      
    points[7] = point[0].y;

    canvas.drawVertices(VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
    Path path = new Path();
    path.moveTo(point[0].x , point[0].y);
    path.lineTo(point[1].x,point[1].y);
    path.lineTo(point[2].x,point[2].y);
    canvas.drawPath(path,paint);

}

Это работает! Не забудьте использовать paint.setAntiAlias ​​(true), чтобы получить гладкий треугольник.
Boldijar Paul

2
Для чего нужны drawVertices?
PsiX

3

Вам нужно удалить path.moveTo после первого инициала.

Path path = new Path();
path.moveTo(point1_returned.x, point1_returned.y);
path.lineTo(point2_returned.x, point2_returned.y);
path.lineTo(point3_returned.x, point3_returned.y);
path.lineTo(point1_returned.x, point1_returned.y);
path.close();

У меня нет трех точек, но есть только одна точка x и y, как я могу нарисовать треугольник из этой точки.
Пранав 05

2

Не moveTo()после каждогоlineTo()

Другими словами, удалите все, moveTo()кроме первого.

Серьезно, если я просто скопирую код OP и удалю ненужные moveTo() вызовы, это сработает.

Больше ничего делать не нужно.


РЕДАКТИРОВАТЬ: Я знаю, что OP уже опубликовал свое «окончательное рабочее решение», но он не указал, почему оно работает. Фактическая причина была для меня довольно неожиданной, поэтому я почувствовал необходимость добавить ответ.


Вы должны были добавить к этому комментарий. Это не ответ.
Ангад Сингх
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.