我看到的似乎是世界风的球体-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);
}
}下面是我声明的使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>要彻底了解,以下是代码导入:
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;发布于 2016-02-26 23:20:54
如果您查看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);请记住,返回的交叉口仍然是以球体原点为中心的笛卡尔坐标,因此要将它们转换回世界风笛卡尔,您需要这样做:
final Vec4 intersectionPos = intersection[0].getIntersectionPoint().add3(sphereCenter);实现还认为这条线是无限长的,因此它将返回两个点,而不是一个。
实现您自己版本的intersect()是非常直接的,它在正常坐标下工作,并考虑了直线的长度,参见这里。
发布于 2016-02-27 12:09:19
如果您查看Worldwind源代码,特别是Sphere类的intersects()和intersect()方法,并以您的代码作为输入进行遍历,您将看到以下内容:
方法:
public boolean intersects(Line line)返回true,因为从球体中心到直线的距离小于球体的半径,正如预期的那样。
对于该方法:
public final Intersection[] intersect(Line line)结果表明,二次型的判别式小于零(即二次方程没有实根--两个不同的复根)。
WorldWind API引用是这里。
所涉及的具体方法如下:
/**
* 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;
}以及:
/**
* 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)};
}
}它使用:
/**
* 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;
}在这种情况下,您的代码失败了:
if (discriminant < 0)测试。
看起来我回答这个问题的速度有点慢,同时克里斯·K指出,这是因为intersect()方法,希望线坐标在球体的原点,而不是地球的中心。
正如Chris所说,这似乎是一个bug,可能应该与这个源代码的维护人员一起记录。
https://stackoverflow.com/questions/35392853
复制相似问题