2011-10-17 19 views
26

Zastanawiam się, jak użyć Matrixa, aby uzyskać nową pozycję współrzędnej w prostokącie po obrocie. Co chciałbym zrobić, to:Zdobądź nową pozycję współrzędnej po obrocie z Matrix

  1. Zdefiniuj prostokąt
  2. zdefiniować koordynować w ramach tego prostokąta
  3. obracać prostokąta
  4. Pobierz nową pozycję współrzędnych po obrocie

Części, których nie mogę określić to: 2 & 4. Jakieś pomysły?

Odpowiedz

32

Stworzyłem prosty demo do tego. Ma trochę więcej, więc możesz zobaczyć, jak tego użyć w rysunku.

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> 

A aktywny:

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

rl.addView (myDrawing); mam błąd w tej linii –

6

Skorzystaj z Matrix.mapPoints, aby przekształcić punkty 2D według macierzy.

+0

Dzięki za odpowiedź, ale spojrzałem na to i nadal nie rozumiem, jak ustawić współrzędne, a następnie uzyskać po rotacji. – DecodeGnome

+0

Mam ten sam problem :( – donmj

+0

proszę przeczytać 'publiczny punkt obracania (stopnie float)' odpowiedzi Entreco –

0

Dawno późno wiem, ale to było coś, co było jeszcze zbyt zagubiony. Cały ten obszar API wydaje się bardziej skupiony na robieniu rzeczy, niż pozwalaniu nam na to, co się dzieje, bez wątpienia, ponieważ robi naprawdę sprytne rzeczy za kulisami.

Ustawianie punktów i ich przywracanie są zupełnie oddzielne.

Istnieje kilka sposobów na ustawienie konkretnego punktu, doskonała odpowiedź Entreco pokazuje w jedną stronę.

Aby odzyskać punkt, należy uzyskać wartości macierzy powiązane z tym punktem, a następnie wybrać odpowiednie części z niego. Ta, również doskonała, odpowiedź (Android Matrix, what does getValues() return?) wyjaśnia bardzo wyraźnie, co dzieje się z matrycą, i widać z niej, że żądane wartości x, y to elementy indeksowane przez 2 i 5.

Poniżej znajduje się (pseudo-) kod używam, aby się do nich dostać.

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

Nie jestem strasznie szczęśliwy z tego powodu, ale nie wydaje się, że jest to bardziej formalny sposób.

Powiązane problemy