- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在用 Java 编写一个需要大量几何图形的应用程序。我大量使用了现有的类,并且到目前为止我的计算都是 double 的(因此我使用例如 Point2D.Double、Line2D.Double 并使用后者编码了凸多边形类...)。
我遇到了与 double 计算相关的几个问题,这些问题使我的应用程序有时不稳定,我考虑切换到 BigDecimal,但这意味着使用 BigDecimal 等创建我自己的 Point2D、Line2D 类,并重写几个函数。另一种解决方案是接受不精确性并加以处理。即,点实际上是一个小正方形,一条线是一个无限带,如果正方形和带相交,则点位于线上,等等。虽然这个解决方案可以快速实现,但我的代码会被像 (Math.abs(x) < precision) (表示 x == 0)这样分散的语句破坏。
有人知道在 Java 中进行精确几何图形的好干净的方法吗?
最佳答案
我试图将其(部分)压缩到评论中,但它不适合。您不应该将其视为“THE”答案,但我想在此列出一些要点。
每当有人提到 BigDecimal
或 float
的精度问题时,使用 double
的建议就很常见,令人恼火,但在这种情况下同样不合适。除了极少数情况外,在所有情况下,double
的有限精度根本不相关。
除非,也许您正在编写应该计算即将发送到火星的载人航天器的轨迹的软件,或者进行其他高度科学的计算。
此外,用 double
替换 BigDecimal
往往只会用几个大问题替换一个小问题。例如,您必须考虑 RoundingMode
和“scale”,这可能很棘手。最终,您会注意到像 1.0/3.0
这样的简单值也不能用 BigDecimal
表示。
对于您的特定应用案例,还有更多注意事项:
即使使用基于 BigDecimal
的 Point2D
实现,数据仍然会通过 double
/getX()
方法公开为 getY()
。例如,像 Line2D#ptLineDistSq 这样的方法仍将使用 double
值。只有当您从头开始编写与计算相关的所有内容,真正到处使用BigDecimal
时,才能避免这种情况。
但即使你这样做了:你也无法计算从点 (-1,0) 到点 (2,1) 的直线的斜率,也无法说出这条直线与 y 轴相交的位置。您可以在这里尝试一些有理数表示,但是单位正方形的对角线长度仍然存在这个问题 - 这是一个无理数。
double
的不精确性很烦人。您可以计算一个点是在线的左侧还是在线的右侧。由于精度问题,很可能两者都是。使用“数学上”应该相等但因一些小的浮点误差而不同的点进行计算可能会导致虚假结果(我也在 one of my libraries 中偶然发现了这一点)。
正如您在问题中已经提到的:一些在纯数学中起作用的概念在以有限的精度实现时必须重新考虑。任何 ==
比较都是不允许的,其他比较应该仔细验证,考虑到可能的舍入误差。
但是使用一些基于“epsilon”的比较是处理这个问题的常用方法。当然,它们使代码变得更加笨拙。但将其与 BigDecimal
的一些“任意精度”代码进行比较:
BigDecimal computeArea(BigDecimal radius) {
// Let's be very precise here....
BigDecimal pi = new BigDecimal("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198938095257201065485863278865936153381827968230301952035301852968995773622599413891249721775283479131515574857242454150695950829533116861727855889075098381754637464939319");
BigDecimal radiusSquared = radius.multiply(radius);
BigDecimal area = radiusSquared.multiply(pi);
return area;
}
对比。
double computeArea(double radius) {
return Math.PI * radius * radius;
}
此外,基于 epsilon 的比较仍然容易出错并引发一些问题。最突出的是:这个“epsilon”应该有多大?基于 epsilon 的比较应该在哪里进行?然而,现有的实现,比如 http://www.geometrictools.com/ 中的几何算法,可能会给出一些如何做到这一点的想法(尽管它们是用 C++ 实现的,并且在最新版本中可读性稍差)。它们经过了时间的考验,并且已经展示了如何应对许多与精度相关的问题。
关于java - Java 中的精确几何,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36106933/
我想知道是否可以将简单的位图转换为几何对象 最佳答案 是的,您可以使用跟踪。 Potrace是一个开源的位图到矢量跟踪器库。 然而,位图追踪并不完美。对于高质量的矢量图像,line tracer 一般
这类似于this question,但是却相反。 我有两个地理位置(纬度,经度)A和B。假设它们相距40海里。我想计算在A和B之间的直线上,从A点起10海里处的坐标。数学(我每天使用的其他一些数学),
我想计算一个点到由 2 个点定义的直线的距离。 我正在使用 javascript,这就是我使用维基百科得出的结论:https://en.wikipedia.org/wiki/Distance_from
我对 boost::geomentry 有疑问。 #include #include #include #include int main(){ typedef boost::geometry
我有一个问题。我想将四边形与四边形相交。 int main(){ typedef boost::geometry::model::point_xy TBoostPoint; typedef b
我无法在 OpleGL 中获得正确的转换。 我有 point3D - P(X,Y,Z) 和投影矩阵 M,它等于 K*(R|T) 其中 K - 相机标定矩阵 (R|T)——点(物)坐标系变换(R——旋转
我想做一个凸面(由一些直线或圆弧组成)围绕它的几何中心(Cx,Cy)旋转。同时凸面两侧有两个圆(由半径给出:R 和左中心:(Lx,Cy),右中心:(Rx,Cy))。表示与几何(Cy) X 轴相同的圆心
我有一个 DrawingVisual表示路径的元素,该路径的几何描述由此 syntax : "m106,59.3c0-1.98,0,0-4.95,0.989-3.96,0.989-13.8,3.96-
如何将我自己的数据集转换为可供 pytorch 几何图形神经网络使用的数据集? 所有教程都使用已转换为 pytorch 可用的现有数据集。例如,如果我有自己的点云数据集,我如何使用它来训练图神经网络的
我正在使用 PyQt5 和 OpenCV。我想创建一个读取视频帧并执行橡皮筋拉伸(stretch)以生成几何图形的类,该几何图形将由不同的类用于裁剪视频流(此示例中不包括第二类)。 在此示例中,从网络
我们有两个 (PostgreSQL 9.2) 表。第一城市: loc_id | integer | not null name | character
我有一张 table : create table if not exists places( id bigserial not null constraint places_pkey primary
我在 postgresql 中有一个带有 PostGIS geometry(point, 4326) 列(位置,使用 SRID 4326)的表,我有一个使用 SQL Alchemy 更新表(其余列)的
我开始使用 c++11 并尝试使用 boost geometry 运行一些示例代码 #include #include #include #include BOOST_GEOMETRY_REG
我有一个存储为 csv 文件的数据框,其中一列是多边形对象。但是,此列存储为字符串而不是 GeoPandas 几何对象。如何将此列转换为 Geopandas 几何对象以便执行地理分析? 这是我的数据的
我从两台相同品牌的相机拍摄的两张图像相距一定距离,拍摄相同的场景。我想计算两个相机之间的真实世界旋转和平移。为了实现这一点,我首先提取了两个图像的 SIFT 特征并匹配它们。 我现在有了基本矩阵以及单
我目前正在使用 boost 几何/空间索引库,以便对 3d 边界框执行范围查询。例如,我能够获得与查询边界框重叠的所有边界框的列表。 文档 ( http://www.boost.org/doc/lib
boost::geometry::model::point 将点的维度作为编译时参数。例如, typedef bg::model::point point; 有没有什么方法可以在运行时指定维度,比如说
我一直在寻找一种在 three.js 中将 uv 映射添加到我的自定义几何体的方法。我找到了这样做的方法,但我找到的解决方案都没有用。谁能解释一下 uv-mapping 的工作原理以及如何正确使用它?
在我的应用程序中,用户可以使用 iPhone 的 GPS 定义足球场的三个角落,方法是一个接一个地走到角落,然后点击按钮。这很好用,我可以在屏幕上绘制生成的矩形,类似于它在 Google map 中的
我是一名优秀的程序员,十分优秀!