得到的矩形四坐标,帆布机器人 [英] get four co-ordinates of rectangle, canvas android

查看:184
本文介绍了得到的矩形四坐标,帆布机器人的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好我想打在我加载位图,其中有黑色边框和右边的自定义视图|顶面有关闭按钮

Hi I want to make an custom view in that I am loading bitmap which has black border and right|top side there is close button

所以当用户过preSS的关闭按钮图像应删除

so when ever user press that close button that image should be removed

有关绘制这样的事情我已经做了以下code

For drawing this kind of things I have done following code

public void draw(Canvas canvas) {
        canvas.save();

        float dx = (mMaxX + mMinX) / 2;
        float dy = (mMaxY + mMinY) / 2;

        mDrawable.setBounds((int) mMinX, (int) mMinY, (int) mMaxX, (int) mMaxY);

        canvas.translate(dx, dy);
        float rotation = mAngle * 180.0f / (float) Math.PI;
        canvas.rotate(rotation);
        canvas.translate(-dx, -dy);

        canvas.drawRect(mMinX - 10, mMinY - 10, mMaxX + 10, mMaxY + 10,
                paintBoundry);

        mDrawable.draw(canvas);
        canvas.drawCircle(mMaxX, mMinY, (mMaxX - mMinX) / 8, paintBoundry);

        canvas.restore();
    }

现在我的问题是,当我旋转图像红,关闭按钮也将移动

Now my question is when I rotate image that RED-Close button will also moved

我想刚刚获得红圆的统筹,也可以说矩形的第二个角统筹

我已经检查下面的链接,但不能得到成功。

I have checked below link but could not get success

<一个href=\"http://stackoverflow.com/questions/7795028/get-new-position-of-coordinate-after-rotation-with-matrix\">Get与矩阵旋转后的坐标的新职位

推荐答案

既然你已经有关于旋转的信息,这是好的。所有你现在需要做的是应用旋转矩阵您圆的原始中心点(原为,我指的是已经翻译了点,它的旋转角度为0°...你有你的code的信息)。你可以从我只要你的网页看到,方程获取当前的 X 值将是:

Since you already have the information about the rotation, that is good. All you need to do now is apply rotation matrix to the original center point of your circle (as original, I am referring to the point that is already translated and it's rotation angle is 0°... you have that information in your code). As you can see from the webpage I provided you, the equation to get current x and y values would be:

x_new = x_original * Math.cos(mAngle) - y_original * Math.sin(mAngle);
y_new = x_original * Math.sin(mAngle) + y_original * Math.cos(mAngle);

请注意: COS 函数接受一个角度参数,它是在弧度 。我可以看到你在做一些自己的转换,你可以使用的 Math.toDegrees(双弧度) Math.toRadians(双学位)

Note: sin and cos functions take an angular parameter that is in RADians. As I can see you were doing some converting on your own, you can use Math.toDegrees(double radians) and Math.toRadians(double degrees)

您可以使用相同的原则,其他三个点,如果你需要他们。

You can use the same principle for the other three points if you need them.

编辑:解释什么是错的code和粘贴一个简单的解决方案

下载源这里

有两件事情错了你的code。

There are two things wrong with your code.


  • 帆布在顺时针方向,这是数学如何限定旋转相反的旋转对象。 (如果你看到这一点,知道做这种方式的家伙,让他在我的名字一巴掌在脸上)。为了解决这个问题,你必须使用旋转角度为负。

  • 您正在旋转的角度约于视图的中心,但你在Android的坐标系中采用触摸值。这两者是这样的形象示人的偏移(我知道,我最不善于用图像。对不起)

也就是说,如果从坐标系0转换点1你可以使用公式

Meaning that if you convert a point from the coordinate system 0 to 1 you would use equations

X1 = X0 - view_size / 2

Y1 = -y0 + view_size / 2

下面是承诺的code。首先创建一个名为自定义视图的 RotationSquare

Here is the promised code. First create a custom view named RotationSquare

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;


public class RotationSquare extends View {


    private int squareBorderColor = 0xFF000000; // black
    private int innerCircleColor = 0xFFFF0000; // red
    private int outerCircleColor = 0xFF000000; // black

    private Paint squarePaint, innerCirclePaint, outerCirclePaint;
    private RectF squareRect;

    private int measuredDimenson;

    private float rotation = 0;

    // Circle parameters that should be remembered
    private float innerRadius, outerRadius, centerX, centerY;
    boolean touchedInsideCircle;


    public RotationSquare(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RotationSquare(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RotationSquare(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attributeSet, int defStyle) {


        squareRect = new RectF();

        squarePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        squarePaint.setColor(squareBorderColor);
        squarePaint.setStyle(Paint.Style.STROKE);

        innerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        innerCirclePaint.setColor(innerCircleColor);
        innerCirclePaint.setStyle(Paint.Style.FILL);

        outerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        outerCirclePaint.setColor(outerCircleColor);
        outerCirclePaint.setStyle(Paint.Style.FILL);


    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

        // Make a square
        measuredDimenson = Math.min(measuredHeight, measuredWidth);


        squareRect.set(0.25f * measuredDimenson, 0.25f * measuredDimenson, 0.85f * measuredDimenson, 0.85f * measuredDimenson);
        squarePaint.setStrokeWidth(0.025f * measuredDimenson);

        centerX = squareRect.right;
        centerY = squareRect.top;
        innerRadius = 0.07f * measuredDimenson;
        outerRadius = 0.08f * measuredDimenson;


        setMeasuredDimension((int) (measuredDimenson * 1f), (int) (measuredDimenson * 1f));
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (measuredDimenson <= 0) {
            return;
        }

        canvas.save(Canvas.MATRIX_SAVE_FLAG);

        canvas.rotate(rotation, measuredDimenson / 2, measuredDimenson / 2);

        canvas.drawCircle(centerX, centerY, outerRadius, outerCirclePaint);
        canvas.drawCircle(centerX, centerY, innerRadius, innerCirclePaint);
        canvas.drawRect(squareRect, squarePaint);
        canvas.restore();

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX(0);
        float y = event.getY(0);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchedInsideCircle = isTouchInsideCircle(x, y);
                return true;
            case MotionEvent.ACTION_MOVE:
                return true;
            case MotionEvent.ACTION_UP:
                if (touchedInsideCircle && isTouchInsideCircle(x, y)) {
                    Toast.makeText(getContext(), "Clicked the circle", Toast.LENGTH_SHORT).show();
                }
                return true;
            default:
                return super.onTouchEvent(event);
        }

    }

    public void setRotation(int rotation) {
        this.rotation = rotation;
        invalidate();
    }


    private boolean isTouchInsideCircle(float x, float y) {
        double angleRad = Math.toRadians(rotation);

        // Convert to the centered coordinate system
        double centerXConverted = centerX - measuredDimenson / 2;
        double centerYConverted = -centerY + measuredDimenson / 2;

        // Use the negative angle
        double currentCenterX = centerXConverted * Math.cos(-angleRad) - centerYConverted * Math.sin(-angleRad);
        double currentCenterY = centerXConverted * Math.sin(-angleRad) + centerYConverted * Math.cos(-angleRad);

        // Convert to the centered coordinate system
        x = x - measuredDimenson / 2;
        y = -y + measuredDimenson / 2;

        double squareRadius = outerRadius * outerRadius;
        double squaredXDistance = (x - currentCenterX) * (x - currentCenterX);
        double squaredYDistance = (y - currentCenterY) * (y - currentCenterY);

        return (squaredXDistance + squaredYDistance) < squareRadius;
    }
}

请活动布局

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <some.package.that.you.must.change.RotationSquare
        android:id="@+id/rotatingSquare"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"/>

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:max="360"/>

    <TextView
        android:id="@+id/tvRotation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/seekBar"
        android:gravity="center_horizontal"
        android:text="Rotation: 0°"
        android:textSize="15sp"/>

</RelativeLayout>

以及活动

public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {

    private SeekBar seekBar;
    private RotationSquare rotationSquare;
    private TextView tvRotation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rotationSquare = (RotationSquare) findViewById(R.id.rotatingSquare);
        seekBar = (SeekBar) findViewById(R.id.seekBar);
        seekBar.setOnSeekBarChangeListener(this);

        tvRotation = (TextView) findViewById(R.id.tvRotation);
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        rotationSquare.setRotation(i);
        tvRotation.setText("Rotation: " + i + "°");
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
}

下面是最后的结果。


Here is the final result.

希望我没有吓跑你的数学和这些方程:/

Hope I didn't scare you off with the math and these equations :/

这篇关于得到的矩形四坐标,帆布机器人的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆