วิธีการวาดสามเหลี่ยมเต็มในผืนผ้าใบ Android


88

ฉันวาดสามเหลี่ยมนี้ในแผนที่ 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 () หลังแต่ละบรรทัดถึง () นั่นคือทั้งหมดที่มี
oli.G

ฉันรู้ว่ามันเป็นคำถามเก่าที่มีคำตอบที่ยอมรับแล้ว (ไม่ถูกต้อง) และคุณยังโพสต์วิธีแก้ปัญหาสุดท้ายของคุณซึ่งใช้งานได้ ... แต่คุณไม่ได้ระบุว่าทำไมมันถึงได้ผลและฉันหวังว่าความคิดเห็นของฉันจะช่วยใครบางคนได้ในเวลาที่ฉัน ' เพิ่งใช้ไปกับสิ่งนี้ :)
oli.G

คำตอบ:


42

คุณอาจต้องทำบางสิ่งเช่น:

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;

ขอบคุณสำหรับคำใบ้ Nicolas!


7
lineTo()ผมค่อนข้างมั่นใจว่าคุณไม่จำเป็นต้องสุดท้าย close()ทำโดยอัตโนมัติ
Timmmm

@Timmmm ฉันทดสอบแล้วคุณพูดถูกไม่จำเป็นต้องมีบรรทัดสุดท้ายถึง () ขอบคุณ
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 ในขณะนี้)
Nicolas C.

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 ​​(จริง) เพื่อให้ได้รูปสามเหลี่ยมที่ราบรื่น
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 ฉันจะวาดสามเหลี่ยมจากจุดนั้นได้อย่างไร
Pranav

2

อย่าmoveTo()หลังละlineTo()

กล่าวอีกนัยหนึ่งคือลบทุกรายการmoveTo()ยกเว้นรายการแรก

อย่างจริงจังถ้าฉันแค่คัดลอกและวางรหัสของ OP และลบการmoveTo()โทรที่ไม่จำเป็นออกก็ใช้งานได้

ไม่มีอะไรต้องทำอีก


แก้ไข: ฉันรู้ว่า OP ได้โพสต์ "โซลูชันการทำงานขั้นสุดท้าย" ของเขาแล้ว แต่เขาไม่ได้ระบุว่าเหตุใดจึงได้ผล เหตุผลที่แท้จริงนั้นค่อนข้างน่าแปลกใจสำหรับฉันดังนั้นฉันจึงรู้สึกว่าจำเป็นต้องเพิ่มคำตอบ


คุณควรเพิ่มความคิดเห็นสำหรับสิ่งนี้ นี่ไม่ใช่คำตอบ
Angad Singh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.