it-swarm-id.com

Dapatkan posisi koordinat baru setelah rotasi dengan Matrix

Saya bertanya-tanya bagaimana cara menggunakan Matrix untuk mendapatkan posisi baru dari koordinat dalam persegi panjang setelah rotasi. Yang ingin saya lakukan adalah: 

  1. Tentukan persegi panjang
  2. Tentukan koordinat dalam persegi panjang itu
  3. Putar persegi panjang
  4. Dapatkan posisi baru koordinat setelah rotasi

Bagian yang saya tidak tahu adalah 2 & 4. Ada ide?

27
DecodeGnome

Saya telah membuat Demo sederhana untuk ini. Ini memiliki sedikit tambahan, jadi Anda juga dapat melihat bagaimana menggunakan ini dalam Menggambar. 

main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/container"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">
    <SeekBar
        Android:id="@+id/seekBar1"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:layout_alignParentBottom="true"
        Android:layout_centerHorizontal="true" />
</RelativeLayout>

Dan Kegiatannya:

package nl.entreco.Android.testrotation;

import Android.app.Activity;
import Android.content.Context;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.graphics.Matrix;
import Android.graphics.Paint;
import Android.graphics.Point;
import Android.graphics.Rect;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.widget.RelativeLayout;
import Android.widget.SeekBar;
import Android.widget.SeekBar.OnSeekBarChangeListener;

public class RotationActivity extends Activity implements OnSeekBarChangeListener {


    private MyDrawing myDrawing;
    private SeekBar mSeekbar;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Rect rect = new Rect(150,150,440,630);

        int x = (int) (rect.left + Math.random() * rect.width());
        int y = (int) (rect.top + Math.random() * rect.height());
        Point coordinate = new Point(x, y);


        // To draw the rect we create a CustomView
        myDrawing = new MyDrawing(this, rect, coordinate);

        RelativeLayout rl = (RelativeLayout)findViewById(R.id.container);
        rl.addView(myDrawing);


        mSeekbar = (SeekBar)findViewById(R.id.seekBar1);
        mSeekbar.setMax(360);
        mSeekbar.setOnSeekBarChangeListener(this);
    }

    private class MyDrawing extends View
    {
        private Rect myRect;
        private Point myPoint;
        private Paint rectPaint;
        private Paint pointPaint;

        private Matrix transform;

        public MyDrawing(Context context, Rect rect, Point point)
        {
            super(context);

            // Store the Rect and Point
            myRect = rect;
            myPoint = point;

            // Create Paint so we can see something :)
            rectPaint = new Paint();
            rectPaint.setColor(Color.GREEN);
            pointPaint = new Paint();
            pointPaint.setColor(Color.YELLOW);

            // Create a matrix to do rotation
            transform = new Matrix();

        }


        /**
        * Add the Rotation to our Transform matrix.
        * 
        * A new point, with the rotated coordinates will be returned
        * @param degrees
        * @return
        */
        public Point rotate(float degrees)
        {
            // This is to rotate about the Rectangles center
            transform.setRotate(degrees, myRect.exactCenterX(),     myRect.exactCenterY());

            // Create new float[] to hold the rotated coordinates
            float[] pts = new float[2];

            // Initialize the array with our Coordinate
            pts[0] = myPoint.x;
            pts[1] = myPoint.y;

            // Use the Matrix to map the points
            transform.mapPoints(pts);

            // NOTE: pts will be changed by transform.mapPoints call
            // after the call, pts will hold the new cooridnates

            // Now, create a new Point from our new coordinates
            Point newPoint = new Point((int)pts[0], (int)pts[1]);

            // Return the new point
            return newPoint;
        }

        @Override
        public void onDraw(Canvas canvas)
        {
            if(myRect != null && myPoint != null)
            {
                // This is an easy way to apply the same transformation (e.g. rotation)
                // To the complete canvas.
                canvas.setMatrix(transform);

                // With the Canvas being rotated, we can simply draw
                // All our elements (Rect and Point) 
                canvas.drawRect(myRect, rectPaint);
                canvas.drawCircle(myPoint.x, myPoint.y, 5, pointPaint);
            }
        }
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {

        Point newCoordinates = myDrawing.rotate(progress);


        // Now -> our float[] pts contains the new x,y coordinates
        Log.d("test", "Before Rotate myPoint("+newCoordinates.x+","+newCoordinates.y+")");
        myDrawing.invalidate();

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {}

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {}
}
32
Entreco

Gunakan Matrix.mapPoints untuk mengubah titik 2D dengan matriks.

6
Pointer Null

Lama sekali saya tahu, tetapi ini adalah sesuatu yang saya juga masih bingung. Seluruh area API ini tampaknya lebih fokus pada melakukan hal-hal untuk kita daripada membiarkan kita memahami apa yang sebenarnya terjadi, tidak diragukan lagi karena melakukan hal-hal yang sangat pintar di belakang layar.

Pengaturan poin dan mendapatkannya kembali sangat terpisah.

Ada berbagai cara untuk menetapkan titik tertentu, jawaban sempurna Entreco menunjukkan satu cara.

Untuk mendapatkan kembali poin Anda harus mendapatkan nilai-nilai matriks yang terhubung ke titik itu dan kemudian mengambil bagian yang benar dari itu. Ini, juga sangat baik, menjawab ( Android Matrix, apa getValues ​​() kembali? ) menjelaskan dengan sangat jelas apa yang terjadi dengan matriks, dan Anda dapat melihat dari situ bahwa nilai x, y yang Anda inginkan adalah elemen yang diindeks oleh 2 dan 5.

Berikut ini adalah (sedikit pseudo-) kode yang saya gunakan untuk mendapatkannya.

float [] theArray = { <nine float zeroes> }
Matrix m = new Matrix();
boolean success = myPathMeasure.getMatrix(m, theArray, Matrix.MTRANS_X+Matrix.MTRANS_Y);
m.getValues(theArray);
x = theArray[2];
y = theArray[5];

Saya tidak terlalu senang dengan hal ini, tetapi sepertinya tidak ada cara yang lebih formal untuk melakukannya.

0
Markers