Comment dessiner un triangle rempli dans une toile Android?

87

Je dessine donc ce triangle dans des cartes Android en utilisant le code ci-dessous dans ma méthode de dessin:

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

Les pointX_returned sont les coordonnées que j'obtiens des champs. Ce sont essentiellement des latitudes et des longitudes. Le résultat est un joli triangle mais l'initié est vide et donc je peux voir la carte. Y a-t-il un moyen de le remplir d'une manière ou d'une autre?

Pavel
la source
Comme je l'ai posté dans ma réponse, ne déplacez pasTo () après chaque lineTo (), c'est tout ce qu'il y a.
oli.G
Je sais que c'est une vieille question qui a déjà une réponse acceptée (incorrecte), et vous avez également publié votre solution finale qui fonctionne ... mais vous ne dites pas pourquoi cela fonctionne, et j'espère que mon commentaire pourra faire gagner du temps à quelqu'un. Je viens de passer dessus :)
oli.G

Réponses:

41

Vous devez probablement faire quelque chose comme:

Paint red = new Paint();

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

Et utilisez cette couleur pour votre chemin, au lieu de votre ARVB. Assurez-vous que le dernier point de votre chemin se termine sur le premier, cela a également du sens.

Dites-moi si cela fonctionne s'il vous plaît!

Nicolas C.
la source
Malheureusement, cela n'aide pas
oli.G
@Nicolas Que faut-il utiliser au lieu d'ARVB, si nous devons personnaliser la couleur avec une valeur RVB au lieu d'utiliser des valeurs prédéfinies?
pallav bohara
75

Ok je l'ai fait. Je partage ce code au cas où quelqu'un d'autre en aurait besoin:

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;

Merci pour l'indice Nicolas!

Pavel
la source
7
Je suis sûr que vous n'avez pas besoin du dernier lineTo(). close()fait cela automatiquement.
Timmmm
@Timmmm J'ai testé, tu as raison, pas besoin de la dernière ligneTo (). Merci.
banxi1988
Merci beaucoup. Je ne sais pas pourquoi j'ai eu tant de problèmes à dessiner un triangle, mais j'ai passé les 20 dernières minutes avec divers bugs sur ce petit problème.
Achal Dave
1
Voici la méthode simple pour copier-coller (basée sur le code de @ Pavel): gist.github.com/ZirconCode/59cae1e2615279eafb29
ZirconCode
1
si vous êtes passé pathà une variable d'instance, n'oubliez pas d'appeler path.reset()après canvas.drawPath().
Sira Lam
11

vous pouvez également utiliser 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
la source
2
Je ne pense pas que cette solution gère les formes remplies. (impossible de tester, je n'ai pas mon IDE pour le moment)
Nicolas C.
3
Cela semble être la solution la plus performante, mais malheureusement, cette méthode n'est pas prise en charge sur les vues accélérées par le matériel. Vous pouvez désactiver l'accélération matérielle, mais vous perdez alors ses gains de performances: developer.android.com/guide/topics/graphics/hardware-accel.html
SurlyDre
8

entrez la description de l'image ici

cette fonction montre comment créer un triangle à partir d'un bitmap. Autrement dit, créez une image recadrée de forme triangulaire. Essayez le code ci-dessous ou téléchargez un exemple de démonstration

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

La fonction ci-dessus renvoie une image triangulaire dessinée sur toile. Lire la suite

Daniel Nyamasyo
la source
7

En utilisant la réponse de @ Pavel comme guide, voici une méthode d'aide si vous n'avez pas les points mais que vous avez un début x, y et une hauteur et une largeur. Peut également dessiner inversé / à l'envers - ce qui est utile pour moi car il a été utilisé comme fin de graphique à barres vertical.

 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
la source
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
la source
Cela fonctionne! N'oubliez pas d'utiliser paint.setAntiAlias ​​(true) pour obtenir un triangle lisse.
Boldijar Paul
2
À quoi sert l'appel drawVertices?
PsiX
3

Vous devez supprimer path.moveTo après la première initiale.

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();
caftanati
la source
Je n'ai pas 3 points mais un seul point x nad y comment puis-je dessiner un triangle à partir de ce point.
Pranav
2

Ne pas moveTo()après chaquelineTo()

En d'autres termes, supprimez tous moveTo()sauf le premier.

Sérieusement, si je viens de copier-coller le code d'OP et de supprimer les moveTo()appels inutiles , cela fonctionne.

Il n'y a rien d'autre à faire.


EDIT: Je sais que l'OP a déjà publié sa "solution de travail finale", mais il n'a pas expliqué pourquoi cela fonctionne. La raison réelle m'était assez surprenante, alors j'ai ressenti le besoin d'ajouter une réponse.

oli.G
la source
Vous devriez avoir ajouté un commentaire pour cela. Ce n'est pas une réponse.
Angad Singh