2011-10-17 109 views
26

我想知道如何使用矩陣在旋轉後獲得矩形內的座標的新位置。我想這樣做的是:使用矩陣旋轉後獲得新的座標位置

  1. 定義的矩形
  2. 定義一個矩形
  3. 旋轉矩形
  4. 內的座標獲取的座標旋轉後
新位置

我找不到的部分是2 & 4. 任何想法?

回答

32

我已經爲此創建了一個簡單的演示。 它有一點額外的,所以你也可以看到如何在繪圖中使用它。

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

rl.addView(myDrawing);我在這一行中的錯誤 – 2012-02-06 08:50:21

6

使用Matrix.mapPoints按矩陣轉換2D點。

+0

感謝您的回答,但我已經看了這個,仍然不明白如何設置座標,然後得到它在旋轉後。 – DecodeGnome

+0

我有同樣的問題:( – donmj

+0

請閱讀'公共點旋轉(浮點數)'的Entreco的答案 –

0

很長一段時間晚了,我知道,但這是我太仍然感到困惑。 API的整個領域似乎更關注於爲我們做事情,而不是讓我們瞭解實際發生的事情,毫無疑問,因爲它在幕後做了非常聰明的事情。

設置點並讓它們返回是非常分離的。

有很多種方法可以設置特定的點,Entreco的優秀答案顯示了一種方法。

要找回一個點,必須獲取與該點相關聯的矩陣的值,然後從中選擇正確的零件。這也是非常好的答案(Android Matrix, what does getValues() return?)非常清楚地解釋了矩陣的情況,你可以看到你想要的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]; 

我對此並不滿意,但似乎沒有更正式的方法來做到這一點。