【问题标题】:Get new position of coordinate after rotation with Matrix使用 Matrix 旋转后获取新坐标位置
【发布时间】:2011-12-09 08:24:11
【问题描述】:

我想知道如何使用矩阵在旋转后获取矩形内坐标的新位置。我想做的是:

  1. 定义一个矩形
  2. 在该矩形内定义一个坐标
  3. 旋转矩形
  4. 获取旋转后坐标的新位置

我无法弄清楚的部分是 2 和 4。 有什么想法吗?

【问题讨论】:

    标签: android matrix rotation coordinates


    【解决方案1】:

    我为此创建了一个简单的演示。 它有一些额外的东西,所以你也可以在绘图中看到如何使用它。

    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通过矩阵变换二维点。

      【讨论】:

      • 谢谢解答,不过我看了这个还是不明白怎么设置坐标,然后旋转后获取。
      • 我也有同样的问题 :(
      • 请阅读 Entreco 的回答 public Point rotate(float degrees)
      【解决方案3】:

      我知道很晚了,但这也是我仍然困惑的事情。 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];
      

      我对此并不十分满意,但似乎没有更正式的方式来做到这一点。

      【讨论】:

        猜你喜欢
        • 2010-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 2013-05-10
        • 1970-01-01
        • 1970-01-01
        • 2021-08-12
        相关资源
        最近更新 更多