Java Comparable<Object> 能否在 max/min 交叉比较中失败?
Can Java Comparable<Object> fail on a max/min cross-comparison?
我正在研究深度排序问题,这是我构造的示例
有两个平面,一个悬停在另一个平面之上,它们被分割成矩形多边形。每个多边形都由其 'real-world' 坐标定义,并使用相机和视图投影定义以生成透视图,如图所示。示例多边形的跟踪打印输出生成
Zn = -0.225, Zf = -0.432
v0 (13, 33, 32.7) (-0.358, -0.065, -0.295, 180.737)
v1 (29, 33, 32.7) (-0.192, -0.142, -0.225, 173.247)
v2 (29, 33, 7.2) ( 0.011, 0.023, -0.375, 190.239)
v3 (13, 33, 7.2) (-0.148, 0.087, -0.432, 197.730)
这个样本属于绿色平面y=33
,非投影顶点是v0 to v4 = (13,33,32.7),(29,33,32,7),(29, 33,7.2) and (13,33,7.2)
使用标准相机和视图模型的投影坐标如下所示。如果 p(i)
是投影坐标,则 -1 < p(i).x,p(i).z,p(i).z < 1
。第四个值是准备渲染时的齐次W坐标,分为每个p(i)(x,y,z)
,它作为参考值保留,因为它给出了从'camera'到给定顶点的垂直平面的距离。
第二组括号中的第三列是投影的 Z 值,重要的是 对于这个问题 值 Zn=depth of nearest vertex
和 Zf=depth of farthest vertex
问题
这个问题是出于上述所有原因,但也独立于任何图形渲染知识。我的动机是主要根据 Z 值
对四边形多边形进行深度排序
根据 Painter's algorithm,对两个多边形之间的渲染顺序的第一个检查是 Z-near 和 Z-far 是否分开并且应该意味着明确的空间分离。
比较的简化摘录
class Extent implements Comparable<Extent> {
double Zn;
double Zf;
@Override
public int compareTo(Extent ext2) {
if (Zn < ext2.Zf) return 1;
if (ext2.Zn < Zf) return -1;
return 0;
}
}
我的问题
当我 运行 与一大组多边形进行比较时,有时我会得到
java.lang.IllegalArgumentException: Comparison method violates its general contract
异常。虽然通常渲染看起来像上面一样好,但有时会失败。但是为什么,我一直没能找到一个失败案例,并且不应该以这种方式比较两个最大值,最小值总是短暂的?
有谁知道经过这种比较会失败的示例集?或许,您能发现我的方法中的逻辑错误吗? (虽然深入了解比较方法的内部结构是主要查询,但如果您熟悉 3d 深度排序,请随时发表评论)
你的算法不满足compareTo contract,因为传递失败;您没有定义总排序。考虑三个 Extents
p1(0,3) p2(0,1) p3(2,3)
实施者必须确保p1.compareTo(p2) == 0
意味着
sgn(p1.compareTo(p3)) == sgn(p2.compareTo(p3))
所有其他点。
p1.compareTo(p2)
为 0。
p1.compareTo(p3)
为 0,但 p2.compareTo(p3)
为 -1。
"best" 对范围进行排序的方式将取决于您要对排序后的列表执行的确切操作,但您很可能最终会根据近值、远值或中心值进行排序。
您应该使用外部 Comparator
进行比较,而不是尝试实施 Comparable
对于复杂的对象,这几乎总是错误的做法。
Comparable
非常适合具有单个或很少属性且需要在所有情况下都相同的对象。就像一个复杂的对象,具有唯一的 ID
,这是唯一被比较的东西。
它不适用于在所有情况下都没有考虑所有属性的复杂情况。在那些时候,您可以使用 Comparator
或更好的 Ordering
from the Guava library,这样您就可以进行优雅的链接和合成。
对三角形进行排序也使这项练习变得微不足道,因为它们永远不可能是非平面的,而且要比较的点少了一个。
我正在研究深度排序问题,这是我构造的示例
有两个平面,一个悬停在另一个平面之上,它们被分割成矩形多边形。每个多边形都由其 'real-world' 坐标定义,并使用相机和视图投影定义以生成透视图,如图所示。示例多边形的跟踪打印输出生成
Zn = -0.225, Zf = -0.432
v0 (13, 33, 32.7) (-0.358, -0.065, -0.295, 180.737)
v1 (29, 33, 32.7) (-0.192, -0.142, -0.225, 173.247)
v2 (29, 33, 7.2) ( 0.011, 0.023, -0.375, 190.239)
v3 (13, 33, 7.2) (-0.148, 0.087, -0.432, 197.730)
这个样本属于绿色平面y=33
,非投影顶点是v0 to v4 = (13,33,32.7),(29,33,32,7),(29, 33,7.2) and (13,33,7.2)
使用标准相机和视图模型的投影坐标如下所示。如果 p(i)
是投影坐标,则 -1 < p(i).x,p(i).z,p(i).z < 1
。第四个值是准备渲染时的齐次W坐标,分为每个p(i)(x,y,z)
,它作为参考值保留,因为它给出了从'camera'到给定顶点的垂直平面的距离。
第二组括号中的第三列是投影的 Z 值,重要的是 对于这个问题 值 Zn=depth of nearest vertex
和 Zf=depth of farthest vertex
问题
这个问题是出于上述所有原因,但也独立于任何图形渲染知识。我的动机是主要根据 Z 值
根据 Painter's algorithm,对两个多边形之间的渲染顺序的第一个检查是 Z-near 和 Z-far 是否分开并且应该意味着明确的空间分离。
比较的简化摘录
class Extent implements Comparable<Extent> {
double Zn;
double Zf;
@Override
public int compareTo(Extent ext2) {
if (Zn < ext2.Zf) return 1;
if (ext2.Zn < Zf) return -1;
return 0;
}
}
我的问题
当我 运行 与一大组多边形进行比较时,有时我会得到
java.lang.IllegalArgumentException: Comparison method violates its general contract
异常。虽然通常渲染看起来像上面一样好,但有时会失败。但是为什么,我一直没能找到一个失败案例,并且不应该以这种方式比较两个最大值,最小值总是短暂的?
有谁知道经过这种比较会失败的示例集?或许,您能发现我的方法中的逻辑错误吗? (虽然深入了解比较方法的内部结构是主要查询,但如果您熟悉 3d 深度排序,请随时发表评论)
你的算法不满足compareTo contract,因为传递失败;您没有定义总排序。考虑三个 Extents
p1(0,3) p2(0,1) p3(2,3)
实施者必须确保p1.compareTo(p2) == 0
意味着
sgn(p1.compareTo(p3)) == sgn(p2.compareTo(p3))
所有其他点。
p1.compareTo(p2)
为 0。
p1.compareTo(p3)
为 0,但 p2.compareTo(p3)
为 -1。
"best" 对范围进行排序的方式将取决于您要对排序后的列表执行的确切操作,但您很可能最终会根据近值、远值或中心值进行排序。
您应该使用外部 Comparator
进行比较,而不是尝试实施 Comparable
对于复杂的对象,这几乎总是错误的做法。
Comparable
非常适合具有单个或很少属性且需要在所有情况下都相同的对象。就像一个复杂的对象,具有唯一的 ID
,这是唯一被比较的东西。
它不适用于在所有情况下都没有考虑所有属性的复杂情况。在那些时候,您可以使用 Comparator
或更好的 Ordering
from the Guava library,这样您就可以进行优雅的链接和合成。
对三角形进行排序也使这项练习变得微不足道,因为它们永远不可能是非平面的,而且要比较的点少了一个。