Jak narysować wypełniony trójkąt na płótnie Androida?

87

Więc rysuję ten trójkąt na mapach Androida, używając poniższego kodu w mojej metodzie rysowania:

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 to współrzędne, które otrzymuję z pól. Zasadniczo są to szerokości i długości geograficzne. Rezultatem jest ładny trójkąt, ale insider jest pusty i dlatego widzę mapę. Czy jest sposób, aby to jakoś wypełnić?

Pavel
źródło
Jak napisałem w mojej odpowiedzi, po prostu nie moveTo () po każdej linii lineTo (), to wszystko.
oli.G
Wiem, że to stare pytanie, na które już (niepoprawna) została zaakceptowana odpowiedź, a także opublikowałeś swoje ostateczne rozwiązanie, które działa ... ale nie mówisz, dlaczego to działa i mam nadzieję, że mój komentarz może zaoszczędzić komuś czas Właśnie na to spędziłem :)
oli.G

Odpowiedzi:

41

Prawdopodobnie musisz zrobić coś takiego:

Paint red = new Paint();

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

I użyj tego koloru na swojej ścieżce zamiast ARGB. Upewnij się, że ostatni punkt twojej ścieżki kończy się na pierwszym, to też ma sens.

Powiedz mi, czy to działa, proszę!

Nicolas C.
źródło
Niestety to nie pomaga
oli.G
@Nicolas Czego użyć zamiast ARGB, jeśli musimy dostosować kolor za pomocą wartości RGB zamiast używać wstępnie zdefiniowanych wartości?
pallav bohara
75

Ok, zrobiłem to. Udostępniam ten kod na wypadek, gdyby ktoś go potrzebował:

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;

Dzięki za podpowiedź Nicolas!

Pavel
źródło
7
Jestem prawie pewien, że nie potrzebujesz ostatniego lineTo(). close()robi to automatycznie.
Timmmm,
@Timmmm Testowałem, masz rację, nie ma potrzeby ostatniej liniiTo (). Dziękuję.
banxi1988,
Dziękuję bardzo. Nie wiem, dlaczego miałem tyle problemów z rysowaniem trójkąta, ale spędziłem ostatnie 20 minut z różnymi błędami przy tym małym problemie.
Achal Dave
1
Oto prosta metoda kopiowania i wklejania (oparta na kodzie @ Pavel): gist.github.com/ZirconCode/59cae1e2615279eafb29
ZirconCode
1
jeśli zmienisz pathna zmienną instancji, pamiętaj, aby wywołać path.reset()after canvas.drawPath().
Sira Lam
11

możesz także użyć 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());
GBouerat
źródło
2
Myślę, że to rozwiązanie nie obsługuje wypełnionych kształtów. (nie mogę przetestować, nie mam w tej chwili swojego IDE)
Nicolas C.
3
Wydaje się, że jest to bardziej wydajne rozwiązanie, ale niestety ta metoda nie jest obsługiwana w widokach przyspieszanych sprzętowo. Możesz wyłączyć akcelerację sprzętową, ale wtedy tracisz wzrost wydajności: developer.android.com/guide/topics/graphics/hardware-accel.html
SurlyDre
8

wprowadź opis obrazu tutaj

ta funkcja pokazuje, jak utworzyć trójkąt z mapy bitowej. Oznacza to, że utwórz przycięty obraz w kształcie trójkąta. Wypróbuj poniższy kod lub pobierz przykład demo

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

Powyższa funkcja zwraca trójkątny obraz narysowany na płótnie. Czytaj więcej

Daniel Nyamasyo
źródło
7

Używając odpowiedzi @ Pavel jako przewodnika, oto metoda pomocnicza, jeśli nie masz punktów, ale masz początek x, y oraz wysokość i szerokość. Potrafię również rysować odwrócony / do góry nogami - co jest dla mnie przydatne, ponieważ był używany jako koniec pionowego wykresu słupkowego.

 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);
    }
scottyab
źródło
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);

}
Faakhir
źródło
To działa! Nie zapomnij użyć paint.setAntiAlias ​​(true), aby uzyskać gładki trójkąt.
Boldijar Paul
2
Czego wymaga drawVertices?
PsiX,
3

Musisz usunąć path.moveTo po pierwszym inicjału.

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();
kaftanati
źródło
Nie mam 3 punktów, ale mam tylko jeden punkt x nad y, jak mogę narysować trójkąt z tego punktu.
Pranav
2

Nie moveTo()po każdymlineTo()

Innymi słowy, usuń wszystkie moveTo()oprócz pierwszego.

Poważnie, jeśli po prostu skopiuję i wkleję kod OP i usunę niepotrzebne moveTo()wywołania, to działa.

Nic więcej nie trzeba robić.


EDYCJA: Wiem, że OP opublikował już swoje „ostateczne rozwiązanie robocze”, ale nie powiedział, dlaczego to działa. Faktyczny powód był dla mnie dość zaskakujący, więc poczułem potrzebę dodania odpowiedzi.

oli.G
źródło
Powinieneś był dodać komentarz do tego. To nie jest odpowiedź.
Angad Singh