gov.nasa.worldwind.geom.BarycentricQuadrilateral Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package gov.nasa.worldwind.geom;
import java.util.*;
import java.awt.*;
/**
* See http://www.cs.kuleuven.be/~ares/Publications/LagaeDutre2005AnEfficientRayQuadrilateralIntersectionTest/paper.pdf
* for a description of the calculations used to compute barycentric and bilinear coordinates.
*
* @author tag
* @version $Id: BarycentricQuadrilateral.java 1171 2013-02-11 21:45:02Z dcollins $
*/
public class BarycentricQuadrilateral extends BarycentricTriangle
{
protected Vec4 p11;
private double[] w11;
public BarycentricQuadrilateral(Vec4 p00, Vec4 p10, Vec4 p11, Vec4 p01)
{
super(p00, p10, p01);
this.p11 = p11;
this.w11 = this.getBarycentricCoords(this.p11);
}
public BarycentricQuadrilateral(LatLon p00, LatLon p10, LatLon p11, LatLon p01)
{
super(p00, p10, p01);
this.p11 = new Vec4(p11.getLongitude().getRadians(), p11.getLatitude().getRadians(), 0);
this.w11 = this.getBarycentricCoords(this.p11);
}
public BarycentricQuadrilateral(Point p00, Point p10, Point p11, Point p01)
{
super(p00, p10, p01);
this.p11 = new Vec4(p11.x, p11.y, 0);
this.w11 = this.getBarycentricCoords(this.p11);
}
public Vec4 getP11()
{
return p11;
}
@Override
public boolean contains(Vec4 p)
{
return this.invertBilinear(p) != null;
}
@SuppressWarnings({"UnnecessaryLocalVariable"})
public double[] getBilinearCoords(double alpha, double beta)
{
// TODO: this method isn't always finding the correct -- or any -- roots
double eps = 1e-9;
double u, v;
double alpha11 = this.w11[1];
double beta11 = this.w11[2];
if (Math.abs(alpha11 - 1) < eps) // if alpha11 == 1
{
u = alpha;
if (Math.abs(beta11 - 1) < eps) // if beta == 1
v = beta;
else
v = beta / (u * (beta11 - 1) + 1);
}
else if (Math.abs(beta11 - 1) < eps) // if beta = 1
{
v = beta;
u = alpha / (v * (alpha11 - 1) + 1);
}
else
{
double a = 1d - beta11;
double b = alpha * (beta11 - 1) - beta * (alpha11 - 1) - 1;
double c = alpha;
double b24ac = b * b - 4 * a * c;
if (a == 0 || b24ac < 0)
return new double[] {-1, -1}; // TODO: Warn.
double q = -0.5 * (b + (b != 0 ? Math.signum(b) : 1) * Math.sqrt(b24ac));
u = q / a;
double ualt = c / q;
u = Math.abs(u) <= Math.abs(ualt) ? u : ualt;
if (u < 0 || u > 1)
u = c / q;
v = u * (beta11 - 1) + 1;
v = Math.abs(v) >= eps ? beta / v : -1;
}
return new double[] {u, v};
}
public double[] getBilinearCoords(Vec4 point)
{
double[] w = this.getBarycentricCoords(point);
return this.getBilinearCoords(w[1], w[2]);
}
public double[] invertBilinear(Vec4 U)
{
return invertBilinear(U, this.p00, this.p10, this.p11, this.p01);
}
public static double[] invertBilinear(Vec4 U, Vec4 X, Vec4 Y, Vec4 Z, Vec4 W)
{
Vec4 s1 = W.subtract3(X);
Vec4 s2 = Z.subtract3(Y);
Vec4 UminX = U.subtract3(X);
Vec4 UminY = U.subtract3(Y);
Vec4 normal = Z.subtract3(X).cross3(W.subtract3(Y));
double A = s1.cross3(s2).dot3(normal);
double B = s2.cross3(UminX).dot3(normal) - s1.cross3(UminY).dot3(normal);
double C = UminX.cross3(UminY).dot3(normal);
double descriminant = B * B - 4d * A * C;
if (descriminant < 0)
return null;
descriminant = Math.sqrt(descriminant);
double beta = B > 0 ? (-B - descriminant) / (2d * A) : 2d * C / (-B + descriminant);
Vec4 Sbeta1 = Vec4.mix3(beta, X, W);
Vec4 Sbeta2 = Vec4.mix3(beta, Y, Z);
double alpha = U.subtract3(Sbeta1).dot3(Sbeta2.subtract3(Sbeta1)) / Sbeta2.subtract3(Sbeta1).dotSelf3();
return new double[] {alpha, beta};
}
//
// private static ArrayList makePoints(double x0, double y0, double x1, double y1)
// {
// ArrayList points = new ArrayList();
//
// for (double y = y0; y <= y1; y += 1)
// {
// for (double x = x0; x <= x1; x += 1)
// {
// points.add(new Vec4(x, y, 0));
// }
// }
//
// return points;
// }
// private static Vec4 g0 = new Vec4(-122.4126, 34.3674, 0);
// private static Vec4 g1 = new Vec4(-117.6527, 34.3674, 0);
// private static Vec4 g2 = new Vec4(-117.6527, 41.4899, 0);
// private static Vec4 g3 = new Vec4(-122.4126, 41.4899, 0);
// private static Vec4 g0 = new Vec4(-144, 18, 0);
// private static Vec4 g1 = new Vec4(-108, 18, 0);
// private static Vec4 g2 = new Vec4(-108, 54, 0);
// private static Vec4 g3 = new Vec4(-144, 54, 0);
private static Vec4 g0 = new Vec4(-180, -90, 0);
private static Vec4 g1 = new Vec4( 180, -90, 0);
private static Vec4 g2 = new Vec4( 180, 90, 0);
private static Vec4 g3 = new Vec4(-180, 90, 0);
// private static Vec4 i0 = new Vec4(-122.1594, 34.3680, 0);
// private static Vec4 i1 = new Vec4(-117.9151, 34.3674, 0);
// private static Vec4 i2 = new Vec4(-117.6527, 41.4891, 0);
// private static Vec4 i3 = new Vec4(-122.4126, 41.4899, 0);
private static Vec4 i0 = new Vec4(0d, 0d, 0d);
private static Vec4 i1 = new Vec4(1d, 0d, 0d);
private static Vec4 i2 = new Vec4(2d, 2d, 0d);
private static Vec4 i3 = new Vec4(0d, 1d, 0d);
private static ArrayList testPoints = new ArrayList(Arrays.asList(
g0, g1, g2, g3,
i0, i1, i2, i3,
new Vec4(-17, 0, 0)
// new Vec4(-122.4, 34.2, 0),
// new Vec4(-120.6, 34.2, 0),
// new Vec4(-120.6, 36, 0),
// new Vec4(-122.4, 36, 0)
));
public static void main(String[] args)
{
BarycentricPlanarShape bc = new BarycentricQuadrilateral(i0, i1, i2, i3);
for (Vec4 point : testPoints)
{
double[] w = bc.getBarycentricCoords(point);
Vec4 p = bc.getPoint(w);
double[] uv = bc.getBilinearCoords(w[1], w[2]);
System.out.printf("%s, %s: ( %f, %f, %f) : ( %f, %f), %s\n",
point, p, w[0], w[1], w[2], uv[0], uv[1], p.equals(point) ? "true" : "false");
}
//
// BarycentricPlanarShape bc = new BarycentricQuadrilateral(new Vec4(4, 3, 0), new Vec4(7, 1, 0),
// new Vec4(10, 5, 0), new Vec4(7, 7, 0));
//
// ArrayList points = makePoints(0, 0, 14, 10);
// for (Vec4 point : points)
// {
// double[] w = bc.getBarycentricCoords(point);
// Vec4 p = bc.getPoint(w);
// double[] uv = bc.getBilinearCoords(w[1], w[2]);
//
// System.out.printf("%s, %s: ( %f, %f, %f) : ( %f, %f), %s\n",
// point, p, w[0], w[1], w[2], uv[0], uv[1], p.equals(point) ? "true" : "false");
// }
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy