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" )
3131public 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