简体   繁体   English

位图围绕错误的枢轴旋转

[英]Bitmap rotating about the wrong pivot

I'm adding a compass overlay to my mapping application. 我在我的地图应用程序中添加了指南针叠加层。 I've decided to create a fairly complicated compass rose and have that drawn to a bitmap in the overlay's constructor just once, rather than on every draw. 我决定创建一个相当复杂的罗盘玫瑰,并在覆盖的构造函数中将其绘制到位图上一次,而不是在每次绘制时。 In the overlay's draw I just rotate the bitmap according to the magnetic sensor's value with a Matrix. 在叠加层的绘图中,我只是根据磁传感器的值使用Matrix旋转位图。

In short, it is incorrect when the rotation is anything other than 90, 180 or 270 degrees - it appears not to rotate about the centre. 简而言之,当旋转角度不是90度,180度或270度时,它是不正确的-它似乎不围绕中心旋转。

I've created a minimal sample which reproduces the problem which is shown below together with screen shots of the 0, 45 and 90 degree rotations that I see. 我创建了一个最小的示例,该示例再现了下面显示的问题以及我看到的0、45和90度旋转的屏幕截图。 The overlay shape is much simpler than the real version and some values have been hard coded to cut down the post size, but this uses the same principles as the real app. 覆盖形状比真实版本要简单得多,并且一些值已经过硬编码以减小帖子大小,但这使用了与真实应用相同的原理。

public class BasicMapOverlayActivity extends MapActivity {

    private MapController mMapCtrlr;
    private MapView mMapVw;
    private int mStartLat = 53500000;
    private int mStartLon = -3000000; 
    private float mBearing = 0.0f;
    private static final int COMPASS_OVL_SIZE = 100;
    private Bitmap mCompassRoseBmap;
    private Canvas mCompassRoseCanvas;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mMapVw = (MapView) findViewById(R.id.map);
        mMapCtrlr = mMapVw.getController();
        mMapCtrlr.setZoom(14);
        mMapVw.setSatellite(true);
        mMapVw.setBuiltInZoomControls(true);
        GeoPoint startGpt = new GeoPoint(mStartLat, mStartLon);
        mMapCtrlr.setCenter(startGpt);
        mCompassRoseCanvas = new Canvas();
        mCompassRoseBmap = Bitmap.createBitmap(COMPASS_OVL_SIZE, COMPASS_OVL_SIZE, Bitmap.Config.ARGB_8888);
        mCompassRoseCanvas.setBitmap(mCompassRoseBmap);
        List<Overlay> listOfOverlays = mMapVw.getOverlays();
        CompassOverlay compassOverlay = new CompassOverlay(mCompassRoseCanvas);
        listOfOverlays.add(compassOverlay);
    }
    public void myClickHandler(View target) {

        switch (target.getId()) {
            case R.id.TurnZeroButton:
                mBearing = 0;
                break;
            case R.id.TurnThirtyButton:
                mBearing = 30;
                break;
            case R.id.Turn45Button:
                mBearing = 45;
                break;
            case R.id.TurnNinetyButton:
                mBearing = 90;
                break;
            case R.id.Turn180Button:
                mBearing = 180;
                break;
        }
        EditText et = (EditText) findViewById(R.id.editText1);
        NumberFormat formatter = new DecimalFormat("##0");
        et.setText(formatter.format(mBearing));
        mMapVw.invalidate();
    }
    @Override
    protected boolean isRouteDisplayed() {return false;}

    public class CompassOverlay extends com.google.android.maps.Overlay {

        private Paint overlayPaint;
        private RectF oRec;

        public CompassOverlay(Canvas canvas) {
            super();
            createRose(canvas, COMPASS_OVL_SIZE);
        }

        public void createRose(Canvas canvas, int overlaySize) {

            float scale = (float) overlaySize;
            canvas.scale(scale, scale);
            overlayPaint = new Paint();
            overlayPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            overlayPaint.setColor(Color.YELLOW);
            overlayPaint.setAntiAlias(true);
            oRec = new RectF();
            oRec.set(0.0f, 0.0f, 1.0f, 1.0f);
            // draw rectangle edges and diagonals
            canvas.drawLine(oRec.left, oRec.top, oRec.right, oRec.bottom, overlayPaint);
            canvas.drawLine(oRec.left, oRec.bottom, oRec.right, oRec.top, overlayPaint);
            canvas.drawLine(oRec.left, oRec.top, oRec.right, oRec.top, overlayPaint);
            canvas.drawLine(oRec.right, oRec.top, oRec.right, oRec.bottom, overlayPaint);
            canvas.drawLine(oRec.right, oRec.bottom, oRec.left, oRec.bottom, overlayPaint);
            canvas.drawLine(oRec.left, oRec.bottom, oRec.left, oRec.top, overlayPaint);
            // draw red vertical line as a direction indicator
            overlayPaint.setColor(Color.RED);
            canvas.drawLine(0.5f, oRec.top, 0.5f, oRec.bottom/2, overlayPaint);// vertical line
            overlayPaint.setColor(Color.YELLOW);
        }
        @Override
        public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {

            Bitmap rBitmap = rotateCompassBitmap(mBearing);
            canvas.drawBitmap(rBitmap, 160, 70, null);
            rBitmap.recycle();
            return false;
        }

        private Bitmap rotateCompassBitmap(float rotationDegrees) {
            Matrix matrix = new Matrix();
            matrix.postRotate(rotationDegrees);
            Bitmap rotatedBitmap = Bitmap.createBitmap(mCompassRoseBmap, 0, 0,
                     mCompassRoseBmap.getWidth(), mCompassRoseBmap.getHeight(), matrix, true); 
            return  rotatedBitmap;
        }
    }
}

The layout is just a simple map, with some buttons which apply a rotation by means of a clickListener. 布局只是一个简单的地图,其中包含一些按钮,这些按钮通过clickListener进行旋转。 The rotation applied is shown in an EditText. 所应用的旋转显示在EditText中。

Zero rotation 零旋转 零旋转

45 degrees 45度 45度

90 degrees 90度 90度

Any help would be much appreciated, as I'm the first to admit that I'm not the world's best when it comes to graphics. 我们将不胜感激,因为我是第一个承认图形方面我不是世界上最好的人。

使用postRotate旋转一个点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM