Java 如何查找阵列列表中的哪些二维点共线
我有一个存储二维点的arrayList。将这些点连接在一起时,它们表示一条路线。我想找出哪些点在同一条线上(共线),这样我就可以知道转弯/转角发生在哪些点上。例如:Java 如何查找阵列列表中的哪些二维点共线,java,arraylist,geometry,Java,Arraylist,Geometry,我有一个存储二维点的arrayList。将这些点连接在一起时,它们表示一条路线。我想找出哪些点在同一条线上(共线),这样我就可以知道转弯/转角发生在哪些点上。例如: ArrayList<Point> positions = new ArrayList<Point>(); positions.add(Point(0,0)); positions.add(Point(0,1)); positions.add(Point(0,2)); positions.add(Point(1
ArrayList<Point> positions = new ArrayList<Point>();
positions.add(Point(0,0));
positions.add(Point(0,1));
positions.add(Point(0,2));
positions.add(Point(1,2));
positions.add(Point(2,2));
positions.add(Point(3,3));
ArrayList positions=new ArrayList();
位置。添加(点(0,0));
增加(第(0,1)点);
增加(第(0,2)点);
增加(第(1,2)点);
增加(第(2,2)点);
增加(第(3,3)点);
示例图片:
我想知道在这个例子中,点C
、D
、E
和G
是发生“转弯”的地方,而点A、B、C
、C、D
、D、E
、E、F、G
和G、H
是共线的
我的想法是首先采样三个点并检查坡度。如果斜率不匹配,我知道第三个点与前两个点不共线。如果它们是共线的,我知道它们是共线的,我会检查更多点,直到斜率不匹配为止。然后我知道第一行的终点,第二行的起点,以及转弯的位置。我重复这个过程。然而,我还不知道如何实现这一点。我真的很感激任何帮助
编辑:我只有整数坐标,两个连续点的切比雪夫距离始终为1。感谢@Marco13.通过计算列表中每个相邻对的斜率变化
你可以得到发生“转弯”的点
Java可以通过将斜率计算为“无穷大”来处理垂直线,
所以不用担心
public static void main(String[] args) {
ArrayList<Point> positions = new ArrayList<Point>();
positions.add(new Point(1,0));
positions.add(new Point(1,1));
positions.add(new Point(1,2));
positions.add(new Point(2,2));
positions.add(new Point(3,1));
positions.add(new Point(4,1));
positions.add(new Point(5,1));
positions.add(new Point(5,2));
ArrayList<Point> turns = new ArrayList<Point>();
for (int i = 0; i < positions.size(); i++) {
turns.add(null);
}
int counter = 0;
if (positions.size() > 2) {
Point base = positions.get(0);
Point next = positions.get(1);
int x = (next.x - base.x);
double slope = 1.0 * (next.y - base.y) / (next.x - base.x);
for (int i = 2; i < positions.size(); i++) {
Point newpoint = positions.get(i);
double newslope = 1.0 * (newpoint.y - next.y) / (newpoint.x - next.x);
if (newslope != slope) {
counter++;
turns.set(i - 1, positions.get(i - 1));
slope = newslope;
}
next = newpoint;
}
}
System.out.println("Collinear points:");
for (int i = 0; i < positions.size(); i++) {
System.out.print("(" + positions.get(i).x + ", " + positions.get(i).y + ") ");
if (turns.get(i) != null) {
System.out.println();
System.out.print("(" + positions.get(i).x + ", " + positions.get(i).y + ") ");
}
}
System.out.println();
System.out.println();
if (counter > 0) {
System.out.println("Turns at these points: ");
for (Point p : turns) {
if (p != null)
System.out.print("(" + p.x + ", " + p.y + ") ");
}
} else {
System.out.println("There are no turns!");
}
}
当涉及垂直线时,应而不是计算坡度 从图像和描述中,我假设您只有整数坐标,并且两个连续点的值始终为1。(如果不是这样,您应该编辑您的答案并包含更多信息) 那么,一个点(xi,yi)就是一个转折点
- X-1–席!席+ 1—席<强>和
- yi-1-yi!=易+1-易
- 当同一点多次出现时,您不会遇到麻烦
- 当您有索引时,您可以很容易地在列表中查找点
- 可以使用连续转折点索引计算共线点的子列表
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class TurningPoints
{
public static void main(String[] args)
{
List<Point> points = new ArrayList<Point>();
points.add(createPoint("A", 1, 0));
points.add(createPoint("B", 1, 1));
points.add(createPoint("C", 1, 2));
points.add(createPoint("D", 2, 2));
points.add(createPoint("E", 3, 1));
points.add(createPoint("F", 4, 1));
points.add(createPoint("G", 5, 1));
points.add(createPoint("H", 5, 2));
List<Integer> indices = computeTurningPointIndices(points);
System.out.println("Turning points are at " + indices);
List<Point> turningPoints = indices.stream().map(i -> points.get(i))
.collect(Collectors.toList());
System.out.println("They are " + turningPoints);
System.out.println("Collinear:");
indices.add(0, 0);
indices.add(points.size() - 1);
for (int i = 0; i < indices.size() - 1; i++)
{
int i0 = indices.get(i);
int i1 = indices.get(i + 1);
List<Point> collinear = points.subList(i0, i1 + 1);
System.out.println(" " + collinear);
}
}
private static List<Integer> computeTurningPointIndices(List<Point> points)
{
List<Integer> indices = new ArrayList<Integer>();
for (int i = 1; i < points.size() - 1; i++)
{
Point prev = points.get(i - 1);
Point curr = points.get(i);
Point next = points.get(i + 1);
int dxPrev = prev.x - curr.x;
int dyPrev = prev.y - curr.y;
int dxNext = next.x - curr.x;
int dyNext = next.y - curr.y;
if (dxPrev != dxNext && dyPrev != dyNext)
{
indices.add(i);
}
}
return indices;
}
private static Point createPoint(String name, int x, int y)
{
// Only for this example. You should usually not do this!
return new Point(x, y)
{
@Override
public String toString()
{
return name + "(" + x + "," + y + ")";
}
};
}
}
所有点都有整数坐标吗?由3个共线点构成的两个向量的叉积等于零:例如,从您的绘图中:ABxAC=0=>点A、B、C是共线的。是的,除以零非常感谢。我最终选择了另一种解决方案,但我也非常感谢。非常感谢!出于某种原因,我在查找带有索引的转折点的线路上得到了
错误:不兼容类型:列表无法转换为int
。我不确定发生了什么事。我认为I
应该是int
,对吗?@CalvinXu我发布的程序可以编译并运行。你改变了什么?@Marcu13我很抱歉,我正在做的Android项目似乎有问题。现在它起作用了。再次感谢!
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class TurningPoints
{
public static void main(String[] args)
{
List<Point> points = new ArrayList<Point>();
points.add(createPoint("A", 1, 0));
points.add(createPoint("B", 1, 1));
points.add(createPoint("C", 1, 2));
points.add(createPoint("D", 2, 2));
points.add(createPoint("E", 3, 1));
points.add(createPoint("F", 4, 1));
points.add(createPoint("G", 5, 1));
points.add(createPoint("H", 5, 2));
List<Integer> indices = computeTurningPointIndices(points);
System.out.println("Turning points are at " + indices);
List<Point> turningPoints = indices.stream().map(i -> points.get(i))
.collect(Collectors.toList());
System.out.println("They are " + turningPoints);
System.out.println("Collinear:");
indices.add(0, 0);
indices.add(points.size() - 1);
for (int i = 0; i < indices.size() - 1; i++)
{
int i0 = indices.get(i);
int i1 = indices.get(i + 1);
List<Point> collinear = points.subList(i0, i1 + 1);
System.out.println(" " + collinear);
}
}
private static List<Integer> computeTurningPointIndices(List<Point> points)
{
List<Integer> indices = new ArrayList<Integer>();
for (int i = 1; i < points.size() - 1; i++)
{
Point prev = points.get(i - 1);
Point curr = points.get(i);
Point next = points.get(i + 1);
int dxPrev = prev.x - curr.x;
int dyPrev = prev.y - curr.y;
int dxNext = next.x - curr.x;
int dyNext = next.y - curr.y;
if (dxPrev != dxNext && dyPrev != dyNext)
{
indices.add(i);
}
}
return indices;
}
private static Point createPoint(String name, int x, int y)
{
// Only for this example. You should usually not do this!
return new Point(x, y)
{
@Override
public String toString()
{
return name + "(" + x + "," + y + ")";
}
};
}
}
Turning points are at [2, 3, 4, 6]
They are [C(1,2), D(2,2), E(3,1), G(5,1)]
Collinear:
[A(1,0), B(1,1), C(1,2)]
[C(1,2), D(2,2)]
[D(2,2), E(3,1)]
[E(3,1), F(4,1), G(5,1)]
[G(5,1), H(5,2)]