Подтвердить что ты не робот

Получить новое положение координаты после вращения с помощью матрицы

Мне интересно, как использовать матрицу для получения новой позиции координаты в прямоугольнике после вращения. Я хотел бы сделать следующее:

  • Определить прямоугольник
  • Определите координату внутри этого прямоугольника
  • Поверните прямоугольник
  • Получить новое положение координаты после поворота

Части, которые я не могу понять, - 2 и 4. Любые идеи?

4b9b3361

Ответ 1

Я создал для этого простой Демо. У этого есть немного больше, так что вы также можете увидеть, как использовать это в Drawing.

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>

И активность:

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) {}
}

Ответ 2

Используйте Matrix.mapPoints для преобразования 2D-точек по матрице.

Ответ 3

Долгое время я знаю, но это было то, что я тоже все еще путался. Вся эта область API кажется более сфокусированной на том, чтобы делать для нас что-то, а не позволять нам понять, что происходит на самом деле, без сомнения, потому что она действительно делает умные вещи за кулисами.

Настройка точек и их возврат довольно раздельны.

Существуют различные способы установки определенной точки, превосходный ответ Entreco показывает один из способов.

Чтобы вернуть точку, вы должны получить значения матрицы, связанной с этой точкой, а затем выбрать из нее правильные части. Это, также отлично, ответ (Android Matrix, что возвращает getValues ​​()?) очень четко объясняет, что происходит с матрицей, и вы можете видеть из этого, что x, y, которые вы хотите, - это элементы, индексированные на 2 и 5.

Ниже приведен (немного псевдо) код, который я использую для получения.

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

Я не очень доволен этим, но, похоже, более формальный способ сделать это не представляется.