WorldWind Sphere Line Intersection Bug?

Jas*_*son 6 java intersection computational-geometry worldwind

我看到了WorldWind的Sphere -Line 交叉逻辑中看似矛盾的行为.我创建了一个Sphere和Line并且它们相交但是然后交集返回null(扫描代码用于注释://***这是它变得糟糕的地方).

这是视觉上发生的事情(线条是灰色的,但很难看到): 球面相交

public class WWTest extends ApplicationTemplate {

    public static class VisualizationFrame extends ApplicationTemplate.AppFrame {

        public VisualizationFrame() {
            super(new Dimension(1200, 1024));
            final Globe globe = getWwd().getModel().getGlobe();

            //Create a sphere at 0,0 on the surface of the Earth wtih a 60 NMi radius
            final Vec4 sphereCenter = globe.computePointFromLocation(LatLon.ZERO);
            final Sphere sphere = new Sphere(sphereCenter, 111120);
            // Draw the sphere
            final RenderableLayer sphereLayer = new RenderableLayer();
            sphereLayer.addRenderable(sphere);

            final RenderableLayer pathLayer = new RenderableLayer();
            // Create a line at 10k feet (3048 meters) that starts outside the sphere at (2,-2) and proceeds into the sphere at (0.5, 0.5)
            final Position lineStart = Position.fromDegrees(2, -2, 3048);
            final Position lineEnds = Position.fromDegrees(0.5, 0.5, 3048);
            final Path asPath = new Path(lineStart, lineEnds);
            pathLayer.addRenderable(asPath);

            // Now that we've visualized the line, let's do some intersection math
            final Vec4 lineStartsAsVec = globe.computePointFromPosition(lineStart);
            final Vec4 lineEndsAsVec = globe.computePointFromPosition(lineEnds);
            final Line asLine = Line.fromSegment(lineStartsAsVec, lineEndsAsVec);

            // *** This is where it gets whacky - true, but no intersection?
            final boolean doesIntersect = sphere.intersects(asLine);
            final Intersection[] intersection = sphere.intersect(asLine);
            //outputs: Intersection found: null
            System.out.println(doesIntersect ? "Intersection found: " + Arrays.toString(intersection) : "No intersection, Why Not!?!?"); 

            insertBeforeCompass(getWwd(), sphereLayer);
            insertBeforeCompass(getWwd(), pathLayer);
            getWwd().getView().setEyePosition(Position.fromDegrees(0, 0, 500_000));
            getLayerPanel().update(getWwd());
        }
    }

    public static void main(String[] args) {
        ApplicationTemplate.start("World Wind Sphere-Line Intersection", VisualizationFrame.class);

    }
}
Run Code Online (Sandbox Code Playgroud)

以下是我宣布将WorldWind引入我的maven项目的依赖项(我也尝试过版本'2.0.0-986',但这似乎没有帮助):

<dependency>
    <groupId>gov.nasa</groupId>
    <artifactId>worldwind</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>gov.nasa</groupId>
    <artifactId>worldwindx</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>org.jogamp.gluegen</groupId>
    <artifactId>gluegen-rt-main</artifactId>
    <version>2.2.4</version>
</dependency>
<dependency>
    <groupId>org.jogamp.jogl</groupId>
    <artifactId>jogl-all-main</artifactId>
    <version>2.2.4</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

要彻底彻底,这里是代码导入:

import gov.nasa.worldwind.geom.Intersection;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Line;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Sphere;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.Path;
import gov.nasa.worldwindx.examples.ApplicationTemplate;
import static gov.nasa.worldwindx.examples.ApplicationTemplate.insertBeforeCompass;
import java.awt.Dimension;
import java.util.Arrays;
Run Code Online (Sandbox Code Playgroud)

Chr*_*s K 2

如果您查看它的实现,Sphere#intersect()则期望坐标线以球体原点(而不是地球的原点)为中心,这几乎肯定是一个错误。您应该能够执行以下操作:

final Vec4 pa = lineStartsAsVec.subtract3(sphereCenter);
final Vec4 pb = lineEndsAsVec.subtract3(sphereCenter);
final Line asLine2 = Line.fromSegment(pa, pb);
final Intersection[] intersection = sphere.intersect(asLine2);
Run Code Online (Sandbox Code Playgroud)

请记住,返回的交点仍然处于以球体原点为中心的笛卡尔坐标系中,因此要将它们转换回世界风笛卡尔坐标系,您需要执行以下操作:

final Vec4 intersectionPos = intersection[0].getIntersectionPoint().add3(sphereCenter);
Run Code Online (Sandbox Code Playgroud)

该实现还认为该线是无限长的,因此它将返回两个点,而不是一个。

intersect()实现您自己的在正常坐标下工作并考虑线条长度的版本将非常简单,请参见此处