HibernateException:位置在 2D 中共线

HibernateException: Positions are collinear in 2D

我使用 Hibernate Spatial verion 5.0.7.Final 作为 ORM。有时,当我使用 Geometry 作为命名参数执行查询时,会出现以下异常:

org.hibernate.HibernateException: Positions are collinear in 2D

我知道有时我的几何图形是 共线Geolatte 库中的 NumericalMethods 模块正在检查我的几何图形是否 isCounterClockwise,它会引发此异常。

我想知道它为什么这样做,但更重要的是,我可以做些什么来避免这个 错误。

NumericalMethods.java 下面的 Hibernate 代码只检查前三个坐标。在我的例子中,有时这三个第一个坐标是共线的,但第四个坐标会使它成为一个有效的多边形。我不明白为什么它不遍历其余坐标来判断它是否逆时针。

完整堆栈跟踪:

org.hibernate.HibernateException: Positions are collinear in 2D
at org.hibernate.spatial.dialect.oracle.SDOGeometryValueBinder.toNative(SDOGeometryValueBinder.java:71)
at org.hibernate.spatial.dialect.oracle.SDOGeometryValueBinder.bind(SDOGeometryValueBinder.java:52)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:257)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:252)
at org.hibernate.param.NamedParameterSpecification.bind(NamedParameterSpecification.java:52)
at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:627)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1944)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1897)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1875)
at org.hibernate.loader.Loader.doQuery(Loader.java:919)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
at org.hibernate.loader.Loader.doList(Loader.java:2611)
at org.hibernate.loader.Loader.doList(Loader.java:2594)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423)
at org.hibernate.loader.Loader.list(Loader.java:2418)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:501)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1326)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)

正如所评论的那样,它看起来像是 Hibernate 中的一个错误。尝试创建具有共线纬度的多边形时,hibernate spatial 会引发异常。它被注册为 Jira 票证:

https://hibernate.atlassian.net/browse/HHH-10410

看起来罪魁祸首是 Geolatte 库 NumericalMethods.java 中的 isCounterClockwise 函数。可能从 Hibernate 5 的第一个版本开始就是这样。

如果有人觉得它有用,我将在代码下方粘贴以创建您自己的此库的自定义版本,以防止发生此错误。如果他们考虑将它(或类似的东西)合并到他们的主人,我也会提交一个拉取请求:

https://github.com/GeoLatte/geolatte-geom/pull/43

/**
 * Determines whether the specified {@code PositionSequence} is counter-clockwise.
 * <p/>
 * <p>Only the first three positions, are inspected to determine whether the sequence is counter-clockwise.
 * In case are less than three positions in the sequence, the method returns true.</p>
 *
 * @param positions a {@code PositionSequence}
 * @return true if the positions in the specified sequence are counter-clockwise, or if the sequence contains
 * less than three elements.
 */
public static boolean isCounterClockwise(PositionSequence<?> positions) {
    if (positions.size() < 3) return true;
    Position p0 = positions.getPositionN(0);
    Position p1 = positions.getPositionN(1);
    double det = 0;
    int positionsSize = positions.size();
    int i = 2;
    while(i < positionsSize && det == 0) {
        Position p2 = positions.getPositionN(i);
        det = deltaDeterminant(p0, p1, p2);
        i++;
    }
    if (det == 0) {
        throw new IllegalArgumentException("Positions are collinear in 2D");
    }
    return det > 0;
}

更新 : pull request被合并到master,所以最终会发布。