2011-10-17 38 views
26

Tôi đang tự hỏi cách sử dụng Ma trận để có được vị trí mới của tọa độ trong một hình chữ nhật sau khi xoay. Những gì tôi muốn làm là:Nhận vị trí mới của tọa độ sau khi xoay với Ma trận

  1. Xác định một hình chữ nhật
  2. Xác định tọa độ trong đó hình chữ nhật
  3. Xoay hình chữ nhật
  4. Lấy vị trí mới có toạ độ sau khi xoay

Các bộ phận tôi không thể tìm ra là 2 & 4. Bất kỳ ý tưởng nào?

Trả lời

32

Tôi đã tạo Bản trình diễn đơn giản cho việc này. Nó có thêm một chút, vì vậy bạn cũng có thể xem cách sử dụng tính năng này trong Bản vẽ.

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> 

Và Hoạt động:

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); tôi đã nhận lỗi trong dòng này –

6

Sử dụng Matrix.mapPoints để chuyển đổi điểm 2D theo ma trận.

+0

Cảm ơn câu trả lời, nhưng tôi đã xem xét điều này và vẫn không hiểu cách thiết lập tọa độ và sau đó lấy nó sau khi xoay. – DecodeGnome

+0

Tôi có cùng một vấn đề: ( – donmj

+0

xin vui lòng đọc 'điểm công cộng xoay (float độ)' của câu trả lời của Entreco –

0

Một thời gian dài cuối tôi biết, nhưng đây là một cái gì đó tôi cũng vẫn còn nhầm lẫn về. Toàn bộ khu vực API này dường như tập trung hơn vào việc làm mọi thứ cho chúng tôi hơn là cho phép chúng tôi hiểu được những gì đang diễn ra, không nghi ngờ gì bởi vì nó đang làm những thứ thực sự thông minh đằng sau hậu trường.

Đặt điểm và nhận lại chúng khá riêng biệt.

Có nhiều cách khác nhau để đặt một điểm cụ thể, câu trả lời tuyệt vời của Entreco hiển thị một cách.

Để lấy lại điểm, bạn phải lấy giá trị của ma trận được liên kết đến điểm đó và sau đó chọn các phần chính xác của nó. Câu trả lời này cũng xuất sắc (Android Matrix, what does getValues() return?) giải thích rõ ràng những gì đang diễn ra với ma trận, và bạn có thể thấy rằng giá trị x, y bạn muốn là các phần tử được lập chỉ mục bởi 2 và 5.

Sau đây là (hơi pseudo-) mã tôi sử dụng để có được ở họ.

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

Tôi không hài lòng về điều này, nhưng dường như không có cách nào chính thức hơn để làm điều đó.

Các vấn đề liên quan