Skip to content

Commit 8b5b40e

Browse files
committed
Repaired SurfacePolygon display of application images when the polygon contains either the North pole or the South pole.
1 parent 86e7c64 commit 8b5b40e

File tree

1 file changed

+90
-42
lines changed

1 file changed

+90
-42
lines changed

src/gov/nasa/worldwind/render/SurfacePolygon.java

Lines changed: 90 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
/**
2727
* @author dcollins
28-
* @version $Id: SurfacePolygon.java 3430 2015-10-01 04:27:40Z dcollins $
28+
* @version $Id: SurfacePolygon.java 3436 2015-10-28 17:43:24Z tgaskins $
2929
*/
3030
@SuppressWarnings("unchecked")
3131
public class SurfacePolygon extends AbstractSurfaceShape implements Exportable
@@ -297,8 +297,8 @@ protected void doDrawGeographic(DrawContext dc, SurfaceTileDrawContext sdc)
297297

298298
if (shapeData == null)
299299
{
300-
double edgeIntervalsPerDegree = this.computeEdgeIntervalsPerDegree(sdc);
301-
List<List<Vertex>> contours = this.assembleContours(edgeIntervalsPerDegree);
300+
Angle degreesPerInterval = Angle.fromDegrees(1.0 / this.computeEdgeIntervalsPerDegree(sdc));
301+
List<List<Vertex>> contours = this.assembleContours(degreesPerInterval);
302302
shapeData = this.tessellateContours(contours);
303303

304304
if (shapeData == null)
@@ -349,7 +349,8 @@ protected void applyInteriorState(DrawContext dc, SurfaceTileDrawContext sdc, Sh
349349
{
350350
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
351351
OGLUtil.applyBlending(gl, true);
352-
OGLUtil.applyColor(gl, attributes.getInteriorMaterial().getDiffuse(), attributes.getInteriorOpacity(), true);
352+
OGLUtil.applyColor(gl, attributes.getInteriorMaterial().getDiffuse(), attributes.getInteriorOpacity(),
353+
true);
353354

354355
if (this.explicitTexture.bind(dc))
355356
{
@@ -365,7 +366,7 @@ protected void applyInteriorState(DrawContext dc, SurfaceTileDrawContext sdc, Sh
365366
}
366367
}
367368

368-
protected List<List<Vertex>> assembleContours(double edgeIntervalsPerDegree)
369+
protected List<List<Vertex>> assembleContours(Angle maxEdgeLength)
369370
{
370371
List<List<Vertex>> result = new ArrayList<List<Vertex>>();
371372

@@ -391,21 +392,21 @@ protected List<List<Vertex>> assembleContours(double edgeIntervalsPerDegree)
391392

392393
// Interpolate the contour vertices according to this polygon's path type and number of edge intervals.
393394
this.closeContour(contour);
394-
List<Vertex> interpolated = this.interpolateContour(contour, edgeIntervalsPerDegree);
395+
this.subdivideContour(contour, maxEdgeLength);
395396

396397
// Modify the contour vertices to compensate for the spherical nature of geographic coordinates.
397-
String pole = LatLon.locationsContainPole(interpolated);
398+
String pole = LatLon.locationsContainPole(contour);
398399
if (pole != null)
399400
{
400-
result.add(this.clipWithPole(interpolated, pole));
401+
result.add(this.clipWithPole(contour, pole, maxEdgeLength));
401402
}
402-
else if (LatLon.locationsCrossDateLine(interpolated))
403+
else if (LatLon.locationsCrossDateLine(contour))
403404
{
404-
result.addAll(this.clipWithDateline(interpolated));
405+
result.addAll(this.clipWithDateline(contour));
405406
}
406407
else
407408
{
408-
result.add(interpolated);
409+
result.add(contour);
409410
}
410411
}
411412

@@ -420,39 +421,45 @@ protected void closeContour(List<Vertex> contour)
420421
}
421422
}
422423

423-
protected List<Vertex> interpolateContour(List<Vertex> contour, double edgeIntervalsPerDegree)
424+
protected void subdivideContour(List<Vertex> contour, Angle maxEdgeLength)
424425
{
425-
List<Vertex> result = new ArrayList<Vertex>();
426-
Vertex prev = null;
426+
List<Vertex> original = new ArrayList<Vertex>(contour.size());
427+
original.addAll(contour);
428+
contour.clear();
427429

428-
for (Vertex cur : contour)
430+
for (int i = 0; i < original.size() - 1; i++)
429431
{
430-
if (prev != null)
431-
{
432-
Angle pathLength = LatLon.pathDistance(this.pathType, prev, cur);
433-
double edgeIntervals = WWMath.clamp(edgeIntervalsPerDegree * pathLength.degrees,
434-
this.minEdgeIntervals, this.maxEdgeIntervals);
435-
int numEdgeIntervals = (int) Math.ceil(edgeIntervals);
432+
Vertex begin = original.get(i);
433+
Vertex end = original.get(i + 1);
434+
contour.add(begin);
435+
this.subdivideEdge(begin, end, maxEdgeLength, contour);
436+
}
436437

437-
for (int j = 1; j <= numEdgeIntervals; j++)
438-
{
439-
double amount = j / (double) (numEdgeIntervals + 1);
440-
LatLon location = LatLon.interpolate(this.pathType, amount, prev, cur);
441-
Vertex vertex = new Vertex(location);
442-
vertex.u = prev.u * (1 - amount) + cur.u * amount;
443-
vertex.v = prev.v * (1 - amount) + cur.v * amount;
444-
result.add(vertex);
445-
}
446-
}
438+
Vertex last = original.get(original.size() - 1);
439+
contour.add(last);
440+
}
447441

448-
result.add(cur);
449-
prev = cur;
450-
}
442+
protected void subdivideEdge(Vertex begin, Vertex end, Angle maxEdgeLength, List<Vertex> result)
443+
{
444+
Vertex center = new Vertex(LatLon.interpolate(this.pathType, 0.5, begin, end));
445+
center.u = 0.5 * (begin.u + end.u);
446+
center.v = 0.5 * (begin.v + end.v);
447+
center.edgeFlag = begin.edgeFlag || end.edgeFlag;
451448

452-
return result;
449+
Angle edgeLength = LatLon.linearDistance(begin, end);
450+
if (edgeLength.compareTo(maxEdgeLength) > 0)
451+
{
452+
this.subdivideEdge(begin, center, maxEdgeLength, result);
453+
result.add(center);
454+
this.subdivideEdge(center, end, maxEdgeLength, result);
455+
}
456+
else
457+
{
458+
result.add(center);
459+
}
453460
}
454461

455-
protected List<Vertex> clipWithPole(List<Vertex> contour, String pole)
462+
protected List<Vertex> clipWithPole(List<Vertex> contour, String pole, Angle maxEdgeLength)
456463
{
457464
List<Vertex> newVertices = new ArrayList<Vertex>();
458465

@@ -481,12 +488,30 @@ protected List<Vertex> clipWithPole(List<Vertex> contour, String pole)
481488
// | |
482489
// 1 | v 4
483490
// --->---- ------>
484-
Vertex one = new Vertex(lat, thisSideLon, 0, 0);
485-
Vertex two = new Vertex(poleLat, thisSideLon, 0, 0);
486-
Vertex three = new Vertex(poleLat, otherSideLon, 0, 0);
487-
Vertex four = new Vertex(lat, otherSideLon, 0, 0);
488-
one.edgeFlag = two.edgeFlag = three.edgeFlag = four.edgeFlag = false;
489-
newVertices.addAll(Arrays.asList(one, two, three, four));
491+
Vertex in = new Vertex(lat, thisSideLon, 0, 0);
492+
Vertex inPole = new Vertex(poleLat, thisSideLon, 0, 0);
493+
Vertex centerPole = new Vertex(poleLat, Angle.ZERO, 0, 0);
494+
Vertex outPole = new Vertex(poleLat, otherSideLon, 0, 0);
495+
Vertex out = new Vertex(lat, otherSideLon, 0, 0);
496+
in.edgeFlag = inPole.edgeFlag = centerPole.edgeFlag = outPole.edgeFlag = out.edgeFlag = false;
497+
498+
double vertexDistance = LatLon.linearDistance(vertex, in).degrees;
499+
double nextVertexDistance = LatLon.linearDistance(nextVertex, out).degrees;
500+
double a = vertexDistance / (vertexDistance + nextVertexDistance);
501+
in.u = out.u = WWMath.mix(a, vertex.u, nextVertex.u);
502+
in.v = out.v = WWMath.mix(a, vertex.v, nextVertex.v);
503+
504+
double[] uv = this.uvWeightedAverage(contour, centerPole);
505+
inPole.u = outPole.u = centerPole.u = uv[0];
506+
inPole.v = outPole.v = centerPole.v = uv[1];
507+
508+
newVertices.add(in);
509+
newVertices.add(inPole);
510+
this.subdivideEdge(inPole, centerPole, maxEdgeLength, newVertices);
511+
newVertices.add(centerPole);
512+
this.subdivideEdge(centerPole, outPole, maxEdgeLength, newVertices);
513+
newVertices.add(outPole);
514+
newVertices.add(out);
490515
}
491516
}
492517
vertex = nextVertex;
@@ -496,6 +521,29 @@ protected List<Vertex> clipWithPole(List<Vertex> contour, String pole)
496521
return newVertices;
497522
}
498523

524+
protected double[] uvWeightedAverage(List<Vertex> contour, Vertex vertex)
525+
{
526+
double[] weight = new double[contour.size()];
527+
double sumOfWeights = 0;
528+
for (int i = 0; i < contour.size(); i++)
529+
{
530+
double distance = LatLon.greatCircleDistance(contour.get(i), vertex).degrees;
531+
weight[i] = 1 / distance;
532+
sumOfWeights += weight[i];
533+
}
534+
535+
double u = 0;
536+
double v = 0;
537+
for (int i = 0; i < contour.size(); i++)
538+
{
539+
double factor = weight[i] / sumOfWeights;
540+
u += contour.get(i).u * factor;
541+
v += contour.get(i).v * factor;
542+
}
543+
544+
return new double[] {u, v};
545+
}
546+
499547
protected List<List<Vertex>> clipWithDateline(List<Vertex> contour)
500548
{
501549
List<Vertex> result = new ArrayList<Vertex>();

0 commit comments

Comments
 (0)