Як намалювати заповнений трикутник на полотні андроїда?


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);

ТочкаX_returned - це координати, які я отримую з полів. В основному це широти та довготи. Результат - гарний трикутник, але інсайдер порожній, і тому я бачу карту. Чи є спосіб якось заповнити це?


Як я писав у своїй відповіді, просто не рухайтеTo () після кожного рядкаTo (), це все, що є.
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 Я протестував, ти маєш рацію, не потрібно останнього рядкаTo (). Дякую.
banxi1988

Дуже дякую. Не знаю, чому у мене було так багато проблем із малюванням трикутника, але останні 20 хвилин я витратив на різні помилки над цією крихітною проблемою.
Achal Dave

1
Ось простий спосіб копіювання (на основі коду @ Pavel): gist.github.com/ZirconCode/59cae1e2615279eafb29
ZirconCode

1
якщо ви перейшли pathна змінну екземпляра, не забудьте зателефонувати path.reset()після canvas.drawPath().
Сіра Лам

11

Ви також можете використовувати вершину:

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();

Я не маю 3 точки, але маю лише одну точку x nad y, як я можу намалювати трикутник із цієї точки.
Пранав

2

Не слід moveTo()після кожногоlineTo()

Іншими словами, видаліть усі, moveTo()крім першого.

Серйозно, якщо я просто скопіюю-встав код ОП і видалю непотрібні moveTo()дзвінки, це працює.

Більше нічого робити не потрібно.


EDIT: Я знаю, що OP вже розмістив своє "остаточне робоче рішення", але він не зазначив, чому це працює. Фактична причина була для мене досить дивною, тому я відчув потребу додати відповідь.


Вам слід було додати коментар до цього. Це не відповідь.
Ангад Сінгх,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.