it-swarm.com.de

Wie zeichnet man einen Bogen zwischen zwei Punkten auf der Leinwand?

Ich habe zwei Punkte auf der Leinwand, jetzt kann ich mit diesen Punkten eine Linie zwischen den Punkten wie diesem unter dem Bild zeichnen 

Dieser Code canvas.drawLine(p1.x, p1.y, p2.x, p2.y, Paint);enter image description here

Ich möchte den Bogen zwischen zwei Punkten wie unter dem Bild zeichnen.

enter image description here

Wie kann ich so zeichnen?.

43

Endlich bekam ich die Lösung aus diesem Code:

float radius = 20;
final RectF oval = new RectF();
oval.set(point1.x - radius, point1.y - radius, point1.x + radius, point1.y+ radius);
Path myPath = new Path();
myPath.arcTo(oval, startAngle, -(float) sweepAngle, true);

Um startAngle zu berechnen, verwenden Sie diesen Code:

int startAngle = (int) (180 / Math.PI * Math.atan2(point.y - point1.y, point.x - point1.x));

Hier bedeutet point1, wo Sie mit dem Zeichnen des Bogens beginnen möchten. sweepAngle bezeichnet den Winkel zwischen zwei Linien. Wir müssen das berechnen, indem wir zwei Punkte wie die blauen Punkte in meinem Fragenbild verwenden.

46

Tun Sie so etwas:

@Override
protected void onDraw(Canvas canvas) {      
    Paint p = new Paint();
    RectF rectF = new RectF(50, 20, 100, 80);
    p.setColor(Color.BLACK);
    canvas.drawArc (rectF, 90, 45, true, p);
}
18
Adil Soomro

Ich habe versucht, etwas anders zu machen, und es geht nur darum, die Schwenk- und Startwinkel zu berechnen.

Ich wollte einen Bogen zeigen, der den Fortschritt auf einem Kreis darstellt, der von oben nach unten verläuft.

Ich hatte also einen Fortschrittswert von 0 ... 100 und möchte einen Bogen zeigen, der von oben nach unten beginnt, um den Kreis zu füllen, wenn der Fortschritt 100 beträgt.

Zur Berechnung des sweepAngle verwende ich:

    int sweepAngle = (int) (360 * (getProgress() / 100.f));

Als nächstes berechnen Sie den StartAngle

    int startAngle = 270 - sweepAngle / 2;

Der Startwinkel wird auf folgende Weise berechnet:

  1. Es beginnt immer von links nach oben, von oben nach unten. Der Startwinkel an der Spitze entspricht also 270 (Beachte, dass er im Uhrzeigersinn geht und 0 = 3 Uhr ist, also 12 Uhr 270 Grad entspricht).
  2. Als Nächstes möchte ich berechnen, wie weit ich von meinem Startpunkt entfernt werde (270). Dazu berechne ich nur die Hälfte des Schwenkwinkels, da sich nur die Hälfte des Bogens auf der linken und die andere Hälfte befindet die richtige Seite.

Wenn man bedenkt, dass ich einen Fortschritt von 25% habe

sweepAngle = 90 degrees (90 degrees is quarter of a circle)
start angle = 225 (45 degrees away from 270)

Wenn Sie möchten, dass der Fortschritt von anderen Seiten (von links nach rechts, von rechts nach links usw.) verläuft, müssen Sie nur 270 durch den Start des Winkels ersetzen.

4
Ahmad Baraka

eine Probe für den Zeichenbogen.

public static Bitmap clipRoundedCorner(Bitmap bitmap, float r, boolean tr, boolean tl, boolean bl, boolean br)
{
    int W = bitmap.getWidth();
    int H = bitmap.getHeight();

    if (r < 0)
        r = 0;

    int smallLeg = W;

    if(H < W )
        smallLeg = H;

    if (r > smallLeg)
        r = smallLeg / 2;

    float lineStop = r/2;

    Path path = new Path();
    path.moveTo(0,0);

    if(tr)
    {
        path.moveTo(0, lineStop);
        path.arcTo(new RectF(0,0, r,r), 180, 90, false);
    }

    path.lineTo(W-lineStop, 0);

    if(tl)
        path.arcTo(new RectF(W-r,0, W,r), 270, 90, false);
    else
        path.lineTo(W, 0);

    path.lineTo(W, H-lineStop);

    if(bl)
        path.arcTo(new RectF(W-r,H-r, W,H), 0, 90, false);
    else
        path.lineTo(W, H);

    path.lineTo(lineStop, H);

    if(br)
        path.arcTo(new RectF(0,H-r, r,H), 90, 90, false);
    else
        path.lineTo(0,H);

    if(tr)
        path.lineTo(0,lineStop);
    else
        path.lineTo(0,0);


    Bitmap output = Bitmap.createBitmap(W, H, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    Paint.setColor(Color.BLACK);
    canvas.drawPath(path, Paint);

    Paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    canvas.drawBitmap(bitmap, 0, 0, Paint);

    return output;
}
0
Ali Bagheri

Ich kann zu spät antworten, aber ich habe mehr Informationen.

Nach Android Lollipop Es gibt zwei Möglichkeiten, um dieses Problem zu beheben

public void drawArc (RectF oval, float startAngle, float sweepAngle, Boolean useCenter, Paint paint)

public void drawArc (Float links, Float oben, Float rechts, Float unten, Float StartAngle, Float SweepAngle, Boolean UseCenter, Paint Paint)

Verwendung:

   RectF rectF = new RectF(left, top, right, bottom);

    // method 1
    canvas.drawArc (rectF, 90, 45, true,  paints[0]);

    // method 2
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]);
    }

Der Schwenkwinkel ist nichts anderes als der Winkel des Sektors, der im Uhrzeigersinn gezeichnet wird, z. für untenstehenden Code

private void drawArcs(Canvas canvas) {
    RectF rectF = new RectF(left, top, right, bottom);

    // white arc
    canvas.drawArc (rectF, 90, 45, true,  paints[0]);

    // Green arc
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]);
    }

    // Red stroked arc
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        canvas.drawArc (left, top, right, bottom, 180, 45, true,  paints[2]);
    }
}

Das Ergebnis wird so aussehen

enter image description here

Dasselbe kann erreicht werden, indem Pfade definiert und dann in der onDraw-Methode über sie iteriert werden, wie in diesem Snippet dargestellt:

 public class ArcDrawable extends Drawable {

    private int left, right, top, bottom;
    private  Paint[] paints = new Paint[3];
    private HashMap<Path, Paint> pathMap = new HashMap();


    public ArcDrawable() {

        // white Paint
        Paint whitePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        whitePaint.setColor(Color.WHITE);
        paints[0]= whitePaint;

        // green Paint
        Paint greenPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        greenPaint.setColor(Color.GREEN);
        paints[1]= greenPaint;

        // red Paint
        Paint redPaint =new Paint(Paint.ANTI_ALIAS_FLAG);
        redPaint.setColor(Color.RED);
        redPaint.setStyle(Paint.Style.STROKE);
        paints[2]= redPaint;
    }

    @Override
    public void draw(Canvas canvas) {

        //----------USE PATHS----------
        // Define and use custom  Path
        for (Map.Entry<Path, Paint> entry : pathMap.entrySet()) {
            // Draw Path on respective Paint style
            canvas.drawPath(entry.getKey(),  entry.getValue());

        }

        // -------OR use conventional Style---------
        //drawArcs(canvas);

    }


    //Same result
    private void drawArcs(Canvas canvas) {
        RectF rectF = new RectF(left, top, right, bottom);

        // method 1
        canvas.drawArc (rectF, 90, 45, true,  paints[0]);

        // method 2
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
            canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]);
        }

        // method two with stroke
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
            canvas.drawArc (left, top, right, bottom, 180, 45, true,  paints[2]);
        }
    }


    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);

        int width = bounds.width();
        int height = bounds.height();

        left = bounds.left;
        right = bounds.right;
        top = bounds.top;
        bottom = bounds.bottom;

        final int size = Math.min(width, height);
        final int centerX = bounds.left + (width / 2);
        final int centerY = bounds.top + (height / 2);

        pathMap.clear();
        //update pathmap using new bounds
        recreatePathMap(size, centerX, centerY);
        invalidateSelf();
    }


    private Path recreatePathMap(int size, int centerX, int centerY) {

        RectF rectF = new RectF(left, top, right, bottom);

        // first arc
        Path arcPath = new Path();
        arcPath.moveTo(centerX,centerY);
        arcPath.arcTo (rectF, 90, 45);
        arcPath.close();
        // add to draw Map
        pathMap.put(arcPath, paints[0]);

        //second arc
        arcPath = new Path();
        arcPath.moveTo(centerX,centerY);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
          arcPath.arcTo (rectF, 0, 45);
        }
        arcPath.close();
        // add to draw Map
        pathMap.put(arcPath, paints[1]);

        // third arc
        arcPath = new Path();
        arcPath.moveTo(centerX,centerY);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
            arcPath.arcTo (rectF, 180, 45);

        }
        arcPath.close();
        // add to draw Map
        pathMap.put(arcPath, paints[2]);

        return arcPath;

    }

    @Override
    public void setAlpha(int alpha) {

    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return 0;
    }


}

Vollständiger Quellcode:

https://github.com/hiteshsahu/Arc-Drawable

0
Hitesh Sahu

Eine einfache Lösung wurde vorgeschlagen hier von Langkiller. Dies zeichnet eine kubische Linie vom Startpunkt über den Kontrollpunkt zum Endpunkt.

Path path = new Path();
float startX = 0;
float startY = 2;
float controlX = 2;
float controlY = 4;
float endX = 4
float endY = 2
conePath.cubicTo(startX, startY, controlX, controlY,endX, endY);

Paint paint = new Paint();
Paint.setARGB(200, 62, 90, 177);
Paint.setStyle(Paint.Style.FILL);

canvas.drawPath(path, Paint)
0
Petterson