All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.metsci.glimpse.worldwind.tile.GlimpseResizingSurfaceTile Maven / Gradle / Ivy

There is a newer version: 3.2.0
Show newest version
/*
 * Copyright (c) 2016, Metron, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Metron, Inc. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL METRON, INC. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.metsci.glimpse.worldwind.tile;

import static com.metsci.glimpse.util.logging.LoggerUtils.logInfo;

import java.util.List;
import java.util.logging.Logger;

import com.metsci.glimpse.axis.Axis2D;
import com.metsci.glimpse.layout.GlimpseLayout;
import com.metsci.glimpse.util.geo.projection.GeoProjection;

import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.render.DrawContext;

public class GlimpseResizingSurfaceTile extends GlimpseDynamicSurfaceTile
{
    private static final Logger logger = Logger.getLogger( GlimpseResizingSurfaceTile.class.getName( ) );

    // the maximum allowed size for the offscreen canvas
    protected int maxWidth;
    protected int maxHeight;

    // the current size of the offscreen canvas (all of which might not be being used)
    protected int currentWidth;
    protected int currentHeight;

    // the dimensions of the offscreen canvas currently being used
    // invariant: maxWidth >= currentWidth >= requestedWidth
    protected int calculatedWidth;
    protected int calculatedHeight;

    // the percentage of the offscreen buffer filled by the texture
    protected float scaleX = 1.0f;
    protected float scaleY = 1.0f;

    protected double preferredPixelCount;

    public GlimpseResizingSurfaceTile( GlimpseLayout layout, Axis2D axes, GeoProjection projection, int preferredWidth, int preferredHeight, double minLat, double maxLat, double minLon, double maxLon )
    {
        this( layout, axes, projection, 8192, 8192, preferredWidth, preferredHeight, minLat, maxLat, minLon, maxLon );
    }

    public GlimpseResizingSurfaceTile( GlimpseLayout layout, Axis2D axes, GeoProjection projection, int preferredWidth, int preferredHeight, List corners )
    {
        this( layout, axes, projection, 8192, 8192, preferredWidth, preferredHeight, corners );
    }

    public GlimpseResizingSurfaceTile( GlimpseLayout layout, Axis2D axes, GeoProjection projection, int maxWidth, int maxHeight, int preferredWidth, int preferredHeight, double minLat, double maxLat, double minLon, double maxLon )
    {
        super( layout, axes, projection, preferredWidth, preferredHeight, minLat, maxLat, minLon, maxLon );

        this.maxWidth = maxWidth;
        this.maxHeight = maxHeight;
        this.preferredPixelCount = width * height;
    }

    public GlimpseResizingSurfaceTile( GlimpseLayout layout, Axis2D axes, GeoProjection projection, int maxWidth, int maxHeight, int preferredWidth, int preferredHeight, List corners )
    {
        super( layout, axes, projection, preferredWidth, preferredHeight, corners );

        this.maxWidth = maxWidth;
        this.maxHeight = maxHeight;
        this.preferredPixelCount = width * height;
    }

    public void setPreferredDimensions( int width, int height )
    {
        this.width = width;
        this.height = height;
        this.preferredPixelCount = width * height;
    }

    // modify the pixel dimensions of the canvas so that they approximately match the
    // dimensions of the tile which the texture will be drawn onto
    // this makes sure that things drawn in pixel space (like GL_POINTS) will
    // not appear distorted (much) when tiled onto WorldWind
    @Override
    protected void updateGeometry( DrawContext dc )
    {
        super.updateGeometry( dc );

        if ( bounds != null && tile != null )
        {
            double latSpan = bounds.maxLat - bounds.minLat;
            double lonSpan = bounds.maxLon - bounds.minLon;

            double ratio = ( latSpan / lonSpan );

            double fcalculatedHeight = Math.sqrt( preferredPixelCount * ratio );
            double fcalculatedWidth = preferredPixelCount / fcalculatedHeight;

            calculatedHeight = ( int ) fcalculatedHeight;
            calculatedWidth = ( int ) fcalculatedWidth;

            if ( calculatedHeight > maxHeight )
            {
                calculatedHeight = maxHeight;
                calculatedWidth = ( int ) Math.min( maxWidth, calculatedHeight * ratio );
            }
            else if ( calculatedWidth > maxWidth )
            {
                calculatedWidth = maxWidth;
                calculatedHeight = ( int ) Math.min( maxHeight, calculatedWidth * ( 1 / ratio ) );
            }

            if ( currentWidth < calculatedWidth || currentHeight < calculatedHeight )
            {
                // when we have to resize the canvas, do a bit more than necessary
                // to leave room for possible future growth
                int bufferedWidth = ( int ) ( Math.max( currentWidth, calculatedWidth ) * 1.1 );
                int bufferedHeight = ( int ) ( Math.max( currentHeight, calculatedHeight ) * 1.1 );

                currentWidth = Math.min( maxWidth, bufferedWidth );
                currentHeight = Math.min( maxHeight, bufferedHeight );
                resizeCanvas( currentWidth, currentHeight );
            }

            resizeLayout( calculatedWidth, calculatedHeight );

            scaleX = ( float ) calculatedWidth / ( float ) currentWidth;
            scaleY = ( float ) calculatedHeight / ( float ) currentHeight;

            setTextureScale( tile );
        }
    }

    @Override
    protected TextureSurfaceTile newTextureSurfaceTile( int textureHandle, Iterable corners )
    {
        TextureSurfaceTile tile = new TextureSurfaceTile( textureHandle, corners );
        setTextureScale( tile );
        tile.setOpacity( getOpacity( ) );
        return tile;
    }

    protected void setTextureScale( TextureSurfaceTile tile )
    {
        setTextureScale( tile, scaleX, scaleY );
    }

    protected void setTextureScale( TextureSurfaceTile tile, float scaleX, float scaleY )
    {
        if ( tile != null ) tile.setTextureScale( scaleX, scaleY );
    }

    protected void resizeLayout( int width, int height )
    {
        mask.setLayoutData( String.format( "pos 0 0 %d %d", width, height ) );
        background.invalidateLayout( );
    }

    protected void resizeCanvas( int width, int height )
    {
        logInfo( logger, "Resizing Offscreen Renderbuffer (%d x %d)", width, height );

        offscreenCanvas.resize( width, height );
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy