Sphere Line WorldWind intersection error?

I see what seems to be conflicting behavior from WorldWind Sphere - line crossing logic. I create a sphere and a line and they intersect, but then the intersection returns null (scan code for comment: // *** This is where it gets drunk).

Here's what happens visually (the line is gray, but it's hard to see there): Sphere-Line Intersection

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 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); } } 

And here are the dependencies that I declared to get WorldWind in my maven project (I also tried the version "2.0.0-986", but that didn't seem to help):

 <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> 

To be completely complete, here is the import code:

 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; 
+6
source share
2 answers

If you look at the implementation of Sphere#intersect() , you expect a line in coordinates centered on the origin of the sphere (and not on Earth), which is almost certainly a mistake. You must be able to:

 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); 

Keep in mind that the returned intersections are still in Cartesian coordinates centered at the beginning of the sphere, so to convert them back to World Wind Cartesian you need to do:

 final Vec4 intersectionPos = intersection[0].getIntersectionPoint().add3(sphereCenter); 

The implementation also believes that the line is infinitely long, so it will return two points, not one.

It would be quite simple to implement our own version of intersect() , which works in normal coordinates and takes into account the length of the string, see here .

+2
source

If you look at the source code of Worldwind , in particular the intershere () and intersect () methods of Sphere and go through their code as input, you will see the following:

Method:

 public boolean intersects(Line line) 

returns true, since the distance from the center of the sphere to the line is less than the radius of the sphere, as expected.

For the method:

 public final Intersection[] intersect(Line line) 

it turns out that the quadratic discriminant is less than zero (i.e. there are no real roots of the quadratic equation - two different complex roots).

Link to WorldWind API here .

Specific methods:

  /** * Tests for intersection with a <code>Line</code>. * * @param line the <code>Line</code> with which to test for intersection * * @return true if <code>line</code> intersects or makes a tangent with the surface of this <code>Sphere</code> * * @throws IllegalArgumentException if <code>line</code> is null */ public boolean intersects(Line line) { if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } return line.distanceTo(this.center) <= this.radius; } 

and

  /** * Obtains the intersections of this sphere with a line. The returned array may be either null or of zero length if * no intersections are discovered. It does not contain null elements and will have a size of 2 at most. Tangential * intersections are marked as such. <code>line</code> is considered to have infinite length in both directions. * * @param line the <code>Line</code> with which to intersect this <code>Sphere</code> * * @return an array containing all the intersections of this <code>Sphere</code> and <code>line</code> * * @throws IllegalArgumentException if <code>line</code> is null */ public final Intersection[] intersect(Line line) { if (line == null) { String message = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } double a = line.getDirection().getLengthSquared3(); double b = 2 * line.selfDot(); double c = line.getOrigin().getLengthSquared3() - this.radius * this.radius; double discriminant = Sphere.discriminant(a, b, c); if (discriminant < 0) return null; double discriminantRoot = Math.sqrt(discriminant); if (discriminant == 0) { Vec4 p = line.getPointAt((-b - discriminantRoot) / (2 * a)); return new Intersection[] {new Intersection(p, true)}; } else // (discriminant > 0) { Vec4 near = line.getPointAt((-b - discriminantRoot) / (2 * a)); Vec4 far = line.getPointAt((-b + discriminantRoot) / (2 * a)); return new Intersection[] {new Intersection(near, false), new Intersection(far, false)}; } } 

which uses:

  /** * Calculates a discriminant. A discriminant is useful to determine the number of roots to a quadratic equation. If * the discriminant is less than zero, there are no roots. If it equals zero, there is one root. If it is greater * than zero, there are two roots. * * @param a the coefficient of the second order pronumeral * @param b the coefficient of the first order pronumeral * @param c the constant parameter in the quadratic equation * * @return the discriminant "b squared minus 4ac" */ private static double discriminant(double a, double b, double c) { return b * b - 4 * a * c; } 

in this case, your code will not be able to execute the command:

 if (discriminant < 0) 

test.

It seems that I was a little slow to answer this question, and in the meantime, Chris K. indicated that this was due to the intersect () method, which expects the coordinates of the lines to be centered at the origin of the sphere, not the Earth.

As Chris K. said, this seems like a mistake and should probably be recorded with the maintainers of this source code.

+2
source

All Articles