Nano Hash - криптовалюты, майнинг, программирование

получить четыре координаты прямоугольника, холст android

Привет, я хочу создать собственное представление, в котором я загружаю растровое изображение с черной рамкой, а справа | вверху есть кнопка закрытия

поэтому, когда пользователь нажимает эту кнопку закрытия, это изображение должно быть удалено

Для рисования таких вещей я сделал следующий код

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();
    }

Теперь мой вопрос: когда я поворачиваю изображение, кнопка RED-Close также перемещается

Я хочу просто получить координаты КРАСНОГО КРУГА или, скажем, координаты второго угла прямоугольника

Я проверил ссылку ниже, но не смог добиться успеха

Получить новую позицию координаты после поворота с помощью Matrix

28.04.2015

Ответы:


1

Поскольку у вас уже есть информация о ротации, это хорошо. Все, что вам нужно сделать сейчас, это применить матрицу вращения к исходной центральной точке вашего круга (как оригинал, я имею в виду точку, которая уже переведена, и ее угол поворота равен 0 ° ... у вас есть эта информация в вашем коде). Как вы можете видеть на веб-странице, которую я вам предоставил, уравнение для получения текущих значений x и y будет выглядеть так:

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

Примечание. Функции sin и cos принимают угловой параметр, который находится в RADians. Как я вижу, вы выполняли некоторые преобразования самостоятельно, вы можете использовать Math.toDegrees(двойные радианы) и Math.toRadians(двойные градусы)

Вы можете использовать тот же принцип для остальных трех точек, если они вам нужны.

РЕДАКТИРОВАТЬ: объяснить, что не так с вашим кодом, и вставить простое решение

Загрузите исходный код ЗДЕСЬ

В вашем коде неправильные две вещи.

  • Холст вращает объект по часовой стрелке, что противоположно тому, как математика определяет вращение. (Если вы видите это и знаете парня, который сделал это таким образом, дайте ему пощечину от моего имени). Чтобы исправить это, вы должны использовать отрицательный угол поворота.
  • Вы вращаете свою точку вокруг центра изображения, но используете сенсорные значения в системе координат Android. Эти два смещены, как показано на этом изображении (я знаю, я ужасен с изображениями. Извините)

введите здесь описание изображения

Это означает, что если вы преобразуете точку из системы координат 0 в 1, вы будете использовать уравнения

x1 = x0 - размер_просмотра / 2
y1 = -y0 + размер_просмотра / 2

Вот обещанный код. Сначала создайте собственное представление с именем 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>

И Activity

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) {

    }
}

Вот окончательный результат.

введите здесь описание изображения

Надеюсь, я не напугал вас математикой и этими уравнениями :/

01.05.2015
  • Ksneman... что значит x_original? это мМакс? а y_original означает = mMinY? 04.05.2015
  • Это математически доказанные уравнения, и они работают, если вы используете их неправильно. Эти уравнения делают вращение в точке, вам нужно применить их к mMaxX и mMinY с вращением в RAD. И вращение должно быть общим углом, на который в данный момент повернуто полотно. 04.05.2015
  • Большое спасибо за ваш ответ, если вы мне немного поможете, может быть, моя проблема будет решена, я обновляю свой вопрос, просто проверьте его. 04.05.2015
  • Я помогу тебе, когда вернусь домой, я ухожу на работу. 04.05.2015
  • Я прочитал ваш вопрос и сделал простой проект. Извините за задержку :) 04.05.2015
  • Я инженер-электрик, в настоящее время работаю разработчиком Android. Думаю, два года. 05.05.2015
  • Неужто ты такой умный... У тебя глубокие знания!! Я был так впечатлен вашими знаниями 05.05.2015
  • про Canvas у меня нет глубоких познаний, вы читали из книги? Поскольку документы также не предоставляют хорошей информации... не могли бы вы предложить мне? 05.05.2015
  • Я не читал никаких книг, это опыт, делая много пользовательских представлений. Вы можете проверить мои другие сообщения, связанные с холстом, возможно, они помогут вам stackoverflow.com/questions/29876100/ stackoverflow.com/questions/29492449/ stackoverflow.com/questions/29727842/ 05.05.2015
  • Привет @BojanKseneman, спасибо за пост :). Можете ли вы также помочь мне с проблемой в моем холсте. У меня есть растровое изображение, которое вращается с использованием матрицы. Я не могу синхронизировать x и y из основного представления с x и y внутри растрового изображения после его поворота. За исключением масштабирования и перевода, это работает. ссылка 08.11.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..