给定是一个旋转的矩形,它被刻在另一个矩形中
两个矩形都有自己的坐标系
在题写&旋转的矩形有一个点 P ,其坐标相对于这个矩形(红色)
想要的是这些点相对于外部矩形的坐标(绿色):
编辑:给定的还有两个矩形的宽度和高度+旋转角度
概述图片:
我对变换矩阵(setRotate()& setScale())的尝试失败了,而且使用三角函数我都没有使用它。
如何计算点 P 相对于外部矩形的位置?
提前致谢!
答案 0 :(得分:0)
可能有点过分,但JTS(Java拓扑套件)提供了大量有用的功能来处理2D坐标。
答案 1 :(得分:0)
EDIT2:我的一位朋友指出了一个更优雅的解决方案(谢谢!)。这是:
@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中用于拖放旋转和缩放查看对象:
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°的旋转有效 如果有人有更清洁或更简单的解决方案,我仍然对它感兴趣。
编辑:以下是我处理View对象丢弃的代码。
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);
}