答
有一个非常简单的解决方案,如果你知道:
-45 < roundedRect.angle < 45
roundedRect.size.height > roundedRect.size.width
如果这是真的,那么按顺时针顺序排列的点将始终按以下顺序排列:
pts[0], pts[3], pts[2], pts[1]
顺便说一句,如果它不会对你的程序造成太大的伤害,那么积分将按逆时针顺序传递,从左上角开始...那么你就不必做任何重新排序/排序。
其他情况:
-
height > width && 135 < roundedRect.angle < 225
- 从左上角开始的顺时针顺序为
2,3,0,1
- 左上角的反时针顺序为 。
2,1,0,3
-
width > height && -135 < roundedRect.angle < -45
- 从左上角开始的顺时针顺序为
3,2,1,0
- 左上角的逆时针顺序为
3,0,1,2
-
width > height && 45 < roundedRect.angle < 135
- 从左上角开始的顺时针顺序为
1,0,3,2
- 左上角的逆时针顺序为
1,2,3,0
其余情况都意味着矩形从左到右比从上到下大,这在你的方案中不会发生。此外,如果角度在这些范围之外,则可以连续添加或减去 360 以获得这些范围之一中的角度。
解释
(博士)
我们从OpenCV如何计算这些点的值中知道这一点。你可以通过一些实验来解决这个问题。这是我写的一个小程序来演示它:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.opencv.core.Point;
import org.opencv.core.RotatedRect;
import org.opencv.core.Size;
public class TestFrame extends JFrame {
public static void main(String... args) {
final TestFrame frame = new TestFrame();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
frame.setVisible(true);
}
});
}
private RectComponent rect;
public TestFrame() {
JPanel containerPane = new JPanel(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
rect = new RectComponent();
containerPane.add(rect);
setContentPane(containerPane);
setSize(400,400);
new Timer(100, rect).start();
}
public class RectComponent extends JComponent implements ActionListener {
private RotatedRect rect = new RotatedRect(new Point(0,0), new Size(1, 3), 0);
private final Point[] pts = new Point[4];
@Override
protected void paintComponent(Graphics g) {
rect.points(pts);
printPoints();
Dimension size = getSize();
drawRectLine(g, pts[0], pts[1], size);
drawRectLine(g, pts[1], pts[2], size);
drawRectLine(g, pts[2], pts[3], size);
drawRectLine(g, pts[0], pts[3], size);
}
private void printPoints() {
System.out.format("A: %d, TL: %s, TR: %s, BR: %s, BL%s%n",
(int) (rect.angle + (rect.angle < 0 ? -1e-6 : 1e-6)), // Stupid doubles, stupid rounding error
pointToString(pts[0]),
pointToString(pts[3]),
pointToString(pts[2]),
pointToString(pts[1]));
}
private String pointToString(Point p) {
return String.format("{%.2f,%.2f}",p.x, p.y);
}
private void drawRectLine(Graphics g, Point left, Point right, Dimension size) {
g.drawLine(scale(left.x, size.width), scale(left.y, size.height),
scale(right.x, size.width), scale(right.y, size.height));
}
private int scale(double value, int coord) {
return (int) (value * coord) / 4 + coord / 2;
}
@Override
public void actionPerformed(ActionEvent e) {
rect.angle += 1;
if(rect.angle > 44) rect.angle = -44;
repaint();
}
}
}