当前位置: 首页 > 知识库问答 >
问题:

Java:坐标变换 - 旋转

竺捷
2023-03-14

给定的是一个旋转的矩形,该矩形内接到另一个矩形中<两个矩形都有自己的坐标系
在该区域中

我对变换矩阵的尝试(setRotate()

如何计算P点相对于外矩形的位置?

提前感谢!

共有2个答案

龙飞
2023-03-14

编辑2:我的一个朋友指出了一个更好的解决方案(谢谢!).这是:

@Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
{
    shadowSize.set((int) width + 1, (int) height + 1);

    float x = offsetX - w / 2, y = offsetY - h / 2;
    shadowTouchPoint.x = Math.round(x * c - y * s * sFac + w / 2 + (width - w) / 2);
    shadowTouchPoint.y = Math.round(x * s * sFac + y * c + h / 2 + (height - h) / 2);
}

sFac定义为:

float sFac = (float) Math.signum(rotationRad);

好吧,我设法用三角学解决了它。
对于任何感兴趣的人,这里是我的自定义DragShadowBuilder的源代码,它在Android中用于拖放旋转和缩放的View对象:

public class TargetDragShadowBuilder extends View.DragShadowBuilder
{
    ImageView view;
    float offsetX, offsetY;

    double rotationRad;
    float w;
    float h;
    double s;
    double c;
    float width;
    float height;

    public TargetDragShadowBuilder(final ImageView view, float offsetX, float offsetY)
    {
        super(view);
        this.view = view;
        this.offsetX = offsetX * view.getScaleX();
        this.offsetY = (int) (offsetY * view.getScaleY());

        rotationRad = Math.toRadians(view.getRotation());
        w = view.getWidth() * view.getScaleX();
        h = (int) (view.getHeight() * view.getScaleY());
        s = Math.abs(Math.sin(rotationRad));
        c = Math.abs(Math.cos(rotationRad));
        width = (int) (w * c + h * s);
        height = (int) (w * s + h * c);
    }

    @Override
    public void onDrawShadow(Canvas canvas)
    {
        canvas.scale(view.getScaleX(), view.getScaleY(), width / 2, height / 2);
        canvas.rotate(view.getRotation(), width / 2, height / 2);
        canvas.translate((width - view.getWidth()) / 2, (height - view.getHeight()) / 2);

        super.onDrawShadow(canvas);
    }

    @Override
    public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
    {
        shadowSize.set((int) width + 1, (int) height + 1);

        double x = offsetX, y = offsetY;
        if(rotationRad < 0)
        {
            final double xC = offsetX / c;
            x = xC + s * (offsetY - xC * s);
            final double yC = offsetY / c;
            y = yC + s * (w - offsetX - yC * s);
        }
        else if(rotationRad > 0)
        {
            final double xC = offsetX / c;
            x = xC + s * (h - offsetY - xC * s);
            final double yC = offsetY / c;
            y = yC + s * (offsetX - yC * s);
        }

        shadowTouchPoint.x = (int) Math.round(x);
        shadowTouchPoint.y = (int) Math.round(y);
    }
}

它适用于从-90°到90°的旋转。
如果有人有更干净或更简单的解决方案,我仍然对它感兴趣。

编辑:这是我如何处理视图对象的删除的代码。

private class TargetDragListener implements OnDragListener
{
    @Override
    public boolean onDrag(View v, DragEvent e)
    {
        switch(e.getAction())
        {
            case DragEvent.ACTION_DRAG_STARTED:
                break;
            case DragEvent.ACTION_DRAG_ENTERED:
                break;
            case DragEvent.ACTION_DRAG_EXITED:
                break;
            case DragEvent.ACTION_DROP:
                if(e.getLocalState() instanceof TargetItem)
                {
                    TargetItem target = (TargetItem) e.getLocalState();
                    dropTarget(target, e.getX(), e.getY());
                }
                break;
            case DragEvent.ACTION_DRAG_ENDED:
                ((DragableItem) e.getLocalState()).setVisibility(View.VISIBLE);
            default:
                break;
        }
        return true;
    }
}

private void dropTarget(TargetItem target, float x, float y)
{
    target.setDragged(false);
    target.setVisibility(View.VISIBLE);
    target.bringToFront();

    final float scaleX = target.getScaleX(), scaleY = target.getScaleY();
    double rotationRad = Math.toRadians(target.getRotation());
    final float w = target.getWidth() * scaleX;
    final float h = target.getHeight() * scaleY;
    float s = (float) Math.abs(Math.sin(rotationRad));
    float c = (float) Math.abs(Math.cos(rotationRad));
    float sFac = (float) -Math.signum(rotationRad);

    target.offsetX *= scaleX;
    target.offsetY *= scaleY;

    x += -target.offsetX * c - target.offsetY * s * sFac;
    y += target.offsetX * s * sFac - target.offsetY * c;
    float[] pts = { x, y };
    float centerX = x + c * w / 2f + sFac * s * h / 2f;
    float centerY = y - sFac * s * w / 2f + c * h / 2f;

    transform.setRotate(-target.getRotation(), centerX, centerY);
    transform.mapPoints(pts);

    target.setX(pts[0] + (w - target.getWidth()) / 2);
    target.setY(pts[1] + (h - target.getHeight()) / 2);
}
高泳
2023-03-14

可能有点过分,但JTS(Java拓扑套件)提供了大量用于处理2D坐标的有用功能

 类似资料:
  • 5.1.4 多坐标变换 需求描述: 现有坐标系统,父级坐标系统 world,下有两子级系统 son1,son2,son1 相对于 world,以及 son2 相对于 world 的关系是已知的,求 son1原点在 son2中的坐标,又已知在 son1中一点的坐标,要求求出该点在 son2 中的坐标 实现分析: 首先,需要发布 son1 相对于 world,以及 son2 相对于 world 的坐标

  • 5.1 TF坐标变换 机器人系统上,有多个传感器,如激光雷达、摄像头等,有的传感器是可以感知机器人周边的物体方位(或者称之为:坐标,横向、纵向、高度的距离信息)的,以协助机器人定位障碍物,可以直接将物体相对该传感器的方位信息,等价于物体相对于机器人系统或机器人其它组件的方位信息吗?显示是不行的,这中间需要一个转换过程。更具体描述如下: 场景1:雷达与小车 现有一移动式机器人底盘,在底盘上安装了一雷

  • 我一直在使用Peter Kovesi的MatLab函数进行机器视觉(如果你不知道的话,这些函数非常出色) 我一直在使用极坐标变换将图像转换为极坐标。Peter Kovesi的函数名为“PolarTrans”,可在此处找到-http://www.peterkovesi.com/matlabfns/#syntheticimages 该函数将图像漂亮地转换为极坐标。然而,我也希望发生相反的情况。Pete

  • 我正在尝试对图像执行对数极坐标变换,以便进行图像配准。换句话说,我正在努力实现这一点:输入图像- 我需要用Java从头开始编写代码,因为我将使用OpenCL Java绑定在GPU端完成这项工作,而不能使用库。这方面有多个线程,但没有一个能真正帮助我,主要是因为它们都使用内置的MATLAB函数,我无法复制。 为了让它发挥作用,我一直在尝试Polar Transform而不是Log-Polar Tra

  • 在文档 场景编辑器 和 节点和组件 中,我们介绍了可以通过 变换工具 和编辑 属性检查器 中节点的属性来变更节点的显示行为。这篇文档我们将会深入了解节点所在场景空间的坐标系,以及节点的 位置(Position)、旋转(Rotation)、缩放(Scale)、尺寸(Size) 四大变换属性的工作原理。而 3D 节点相比 2D 节点,在变换属性的 API 用法上做了一些改动,具体内容可参考 3D 节点

  • 5.1.3 动态坐标变换 所谓动态坐标变换,是指两个坐标系之间的相对位置是变化的。 需求描述: 启动 turtlesim_node,该节点中窗体有一个世界坐标系(左下角为坐标系原点),乌龟是另一个坐标系,键盘控制乌龟运动,将两个坐标系的相对位置动态发布。 结果演示: 实现分析: 乌龟本身不但可以看作坐标系,也是世界坐标系中的一个坐标点 订阅 turtle1/pose,可以获取乌龟在世界坐标系的 x