计算两条直线是否对称
Calculate if two lines are symmetrical
我正在开发一个应用程序来检查平局是否对称。所有用户行都存储在一个由点列表组成的 ArrayList 中,结构化为:
private ArrayList<ArrayList<Pair<Float,Float>>> segments = new ArrayList<>();
这是我构建绘图区的方式:
黑色的形状是背景的一部分,当我必须检查对称性时不需要考虑它。我只需要它的中心(我将其存储为单个坐标),因为我需要考虑检查它的对称性。由于抽签是由 children 绘制的,我还需要考虑一些灵活性,因为线条永远不会完全对称。我实现了一种方法,将每个段分成 10 个部分,然后检查每个部分的坐标是否具有相似性 increase/decrease:
private boolean checkShape (int z, ArrayList<Pair<Float,Float>> points) {
ArrayList<Pair<Float,Float>> copia = segments.get(z);
int nGroupsFirstShape = (segments.get(z).size()*10)/100;
int nValuesFirstShape[] = new int[10];
for (int j=0, j2=0; j<10; j++, j2+=nGroupsFirstShape) {
int sumValues=0;
sumValues+=copia.get(j2).first-copia.get(j2+nGroupsFirstShape-1).first;
sumValues+=copia.get(j2).second-copia.get(j2+nGroupsFirstShape-1).second;
nValuesFirstShape[j] = sumValues;
}
ArrayList<Pair<Float,Float>> copia2 = points;
int nGroupSecondShape = (copia2.size()*10)/100;
int nValuesSecondShape[] = new int[10];
for (int j=0, j2=0; j<10; j++, j2+=nGroupSecondShape) {
int sumValues=0;
sumValues+=copia2.get(j2).first-copia2.get(j2+nGroupSecondShape-1).first;
sumValues+=copia2.get(j2).second-copia2.get(j2+nGroupSecondShape-1).second;
nValuesSecondShape[j] = sumValues;
}
int differences[] = new int[10];
int numberOf = 0;
for (int index=0; index<10; index++) {
differences[index] = nValuesFirstShape[index] - nValuesSecondShape[index];
if (differences[index]<0) differences[index] = -differences[index];
if (differences[index]<nGroupsFirstShape*2.5) numberOf++;
}
if (numberOf>=6) return true; else return false;
}
如果至少有 6 个部分验证了这一点,那么我可以认为这些段是对称的。这种方法的巨大问题是线条可以有不同的大小。您知道计算绘图区域对称性的任何方法吗?由于我把图片保存为位图,所以我也试过找直接在图片文件上计算的方法,但是没找到
我已经 Java 多年没有编写代码了,现在也没有那么多时间。因为这个答案不包含 运行 Java 代码,而只包含想法和一些伪代码。无论如何,我希望这对你有帮助。
一个给出了两个curvescurve1
和curve2
,以及一个反射中心c
。
您想要计算一条曲线是否是另一条曲线在给定阈值内的点反射 maxDist
.
计算这个的函数可能如下所示:
function checkSymmetry(Curve curve1, Curve curve2, Vector c, float maxDist) {
// reflect one curve
Curve curve2refl = reflect(curve2, c);
// compute curve distance
float d = dist(curve1, curve2refl);
// check if distance is below threshold
return d < maxDist;
(我确实介绍了一些 类 而不是你的 ArrayLists of ArrayLists of Pairs of … 为了更好的可读性。我建议你在你的代码中做同样的事情。)
点反射
一个点反射的公式可以在Wikipedia上找到:一个点p
以反射中心c
的反射是:2*c - p
.
要反映一条曲线,您必须反映它的所有顶点。
距离曲线–曲线
当两条红色曲线(几乎)对称时,在其中一条反射后它们应该(几乎)相同,即距离(几乎)为零。但是两条曲线的距离是多少?
在数学集合论中存在一个Hausdorff distance。对于非数学家来说有点复杂。但它给出了定义曲线距离的想法:一条曲线的顶点到另一条曲线的最大距离:
function dist(Curve curve1, Curve curve2) {
d = 0;
for (Vector p : curve1.vertices) {
d = max(d, dist(curve2, p));
}
for (Vector p : curve2.vertices) {
d = max(d, dist(curve1, p));
}
return d;
}
距离点-曲线
所以我们确实减少了计算点到曲线距离的问题。这是点到任何曲线段的最小距离:
function dist(Curve curve, Vector p) {
d = dist(p, curve.vertices.get(0));
for (int i = 1, n = curve.vertices.size(); i < n; ++i) {
Vector p1 = curve.vertices.get(i-1);
Vector p2 = curve.vertices.get(i);
d = min(d, dist(new Segment(p1, p2), p));
}
return d;
}
距离点–段
对于点到线段的距离,您可以在 Whosebug 上找到很多问题,这些问题都有很好的答案,例如here.
我认为这是很好的数学算法:
第一步:
将每一行分成N个部分。 (图中的正方形)
线上的点数可能会有所不同,但零件的数量现在是相同的。
比如1条线100分,分成10份,每份10分。
第二个90分,将得到10分9分
计算每个部分的中点。
fig1
第 2 步:
在两条线的每个中点之间,我们找到中间点。 (图中的黑点)
fig2
第 3 步:
我们建立一条与这些点的偏差最小的线。 (图中红线)
fig3
第 4 步:
估计中点与直线的偏差。通过平均偏差和最大偏差,可以衡量线条的相似程度。
祝你好运
我正在开发一个应用程序来检查平局是否对称。所有用户行都存储在一个由点列表组成的 ArrayList 中,结构化为:
private ArrayList<ArrayList<Pair<Float,Float>>> segments = new ArrayList<>();
这是我构建绘图区的方式:
黑色的形状是背景的一部分,当我必须检查对称性时不需要考虑它。我只需要它的中心(我将其存储为单个坐标),因为我需要考虑检查它的对称性。由于抽签是由 children 绘制的,我还需要考虑一些灵活性,因为线条永远不会完全对称。我实现了一种方法,将每个段分成 10 个部分,然后检查每个部分的坐标是否具有相似性 increase/decrease:
private boolean checkShape (int z, ArrayList<Pair<Float,Float>> points) {
ArrayList<Pair<Float,Float>> copia = segments.get(z);
int nGroupsFirstShape = (segments.get(z).size()*10)/100;
int nValuesFirstShape[] = new int[10];
for (int j=0, j2=0; j<10; j++, j2+=nGroupsFirstShape) {
int sumValues=0;
sumValues+=copia.get(j2).first-copia.get(j2+nGroupsFirstShape-1).first;
sumValues+=copia.get(j2).second-copia.get(j2+nGroupsFirstShape-1).second;
nValuesFirstShape[j] = sumValues;
}
ArrayList<Pair<Float,Float>> copia2 = points;
int nGroupSecondShape = (copia2.size()*10)/100;
int nValuesSecondShape[] = new int[10];
for (int j=0, j2=0; j<10; j++, j2+=nGroupSecondShape) {
int sumValues=0;
sumValues+=copia2.get(j2).first-copia2.get(j2+nGroupSecondShape-1).first;
sumValues+=copia2.get(j2).second-copia2.get(j2+nGroupSecondShape-1).second;
nValuesSecondShape[j] = sumValues;
}
int differences[] = new int[10];
int numberOf = 0;
for (int index=0; index<10; index++) {
differences[index] = nValuesFirstShape[index] - nValuesSecondShape[index];
if (differences[index]<0) differences[index] = -differences[index];
if (differences[index]<nGroupsFirstShape*2.5) numberOf++;
}
if (numberOf>=6) return true; else return false;
}
如果至少有 6 个部分验证了这一点,那么我可以认为这些段是对称的。这种方法的巨大问题是线条可以有不同的大小。您知道计算绘图区域对称性的任何方法吗?由于我把图片保存为位图,所以我也试过找直接在图片文件上计算的方法,但是没找到
我已经 Java 多年没有编写代码了,现在也没有那么多时间。因为这个答案不包含 运行 Java 代码,而只包含想法和一些伪代码。无论如何,我希望这对你有帮助。
一个给出了两个curvescurve1
和curve2
,以及一个反射中心c
。
您想要计算一条曲线是否是另一条曲线在给定阈值内的点反射 maxDist
.
计算这个的函数可能如下所示:
function checkSymmetry(Curve curve1, Curve curve2, Vector c, float maxDist) {
// reflect one curve
Curve curve2refl = reflect(curve2, c);
// compute curve distance
float d = dist(curve1, curve2refl);
// check if distance is below threshold
return d < maxDist;
(我确实介绍了一些 类 而不是你的 ArrayLists of ArrayLists of Pairs of … 为了更好的可读性。我建议你在你的代码中做同样的事情。)
点反射
一个点反射的公式可以在Wikipedia上找到:一个点p
以反射中心c
的反射是:2*c - p
.
要反映一条曲线,您必须反映它的所有顶点。
距离曲线–曲线
当两条红色曲线(几乎)对称时,在其中一条反射后它们应该(几乎)相同,即距离(几乎)为零。但是两条曲线的距离是多少?
在数学集合论中存在一个Hausdorff distance。对于非数学家来说有点复杂。但它给出了定义曲线距离的想法:一条曲线的顶点到另一条曲线的最大距离:
function dist(Curve curve1, Curve curve2) {
d = 0;
for (Vector p : curve1.vertices) {
d = max(d, dist(curve2, p));
}
for (Vector p : curve2.vertices) {
d = max(d, dist(curve1, p));
}
return d;
}
距离点-曲线
所以我们确实减少了计算点到曲线距离的问题。这是点到任何曲线段的最小距离:
function dist(Curve curve, Vector p) {
d = dist(p, curve.vertices.get(0));
for (int i = 1, n = curve.vertices.size(); i < n; ++i) {
Vector p1 = curve.vertices.get(i-1);
Vector p2 = curve.vertices.get(i);
d = min(d, dist(new Segment(p1, p2), p));
}
return d;
}
距离点–段
对于点到线段的距离,您可以在 Whosebug 上找到很多问题,这些问题都有很好的答案,例如here.
我认为这是很好的数学算法:
第一步: 将每一行分成N个部分。 (图中的正方形) 线上的点数可能会有所不同,但零件的数量现在是相同的。
比如1条线100分,分成10份,每份10分。 第二个90分,将得到10分9分
计算每个部分的中点。 fig1
第 2 步: 在两条线的每个中点之间,我们找到中间点。 (图中的黑点) fig2
第 3 步: 我们建立一条与这些点的偏差最小的线。 (图中红线) fig3
第 4 步: 估计中点与直线的偏差。通过平均偏差和最大偏差,可以衡量线条的相似程度。
祝你好运