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

gov.nasa.worldwind.layers.GraticuleSupport 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.layers;

import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.Logging;

import java.awt.*;
import java.util.*;

/**
 * @author dcollins
 * @version $Id: GraticuleSupport.java 2372 2014-10-10 18:32:15Z tgaskins $
 */
public class GraticuleSupport
{
    private static class Pair
    {
        final Object a;
        final Object b;

        Pair(Object a, Object b)
        {
            this.a = a;
            this.b = b;
        }

        @Override
        public boolean equals(Object o)
        {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;

            Pair pair = (Pair) o;

            if (a != null ? !a.equals(pair.a) : pair.a != null)
                return false;
            if (b != null ? !b.equals(pair.b) : pair.b != null)
                return false;

            return true;
        }

        @Override
        public int hashCode()
        {
            int result = a != null ? a.hashCode() : 0;
            result = 31 * result + (b != null ? b.hashCode() : 0);
            return result;
        }
    }

    private Collection renderables = new HashSet(); // a set to avoid duplicates in multi-pass (2D globes)
    private Map namedParams = new HashMap();
    private Map namedShapeAttributes = new HashMap();
    private AVList defaultParams;
    private GeographicTextRenderer textRenderer = new GeographicTextRenderer();

    public GraticuleSupport()
    {
        this.textRenderer.setEffect(AVKey.TEXT_EFFECT_SHADOW);
        // Keep labels separated by at least two pixels
        this.textRenderer.setCullTextEnabled(true);
        this.textRenderer.setCullTextMargin(1);
        // Shrink and blend labels as they get farther away from the eye
        this.textRenderer.setDistanceMinScale(.5);
        this.textRenderer.setDistanceMinOpacity(.5);
    }

    public void addRenderable(Object renderable, String paramsKey)
    {
        if (renderable == null)
        {
            String message = Logging.getMessage("nullValue.ObjectIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.renderables.add(new Pair(renderable, paramsKey));
    }

    public void removeAllRenderables()
    {
        this.renderables.clear();
    }

    public void render(DrawContext dc)
    {
        this.render(dc, 1);
    }

    public void render(DrawContext dc, double opacity)
    {
        if (dc == null)
        {
            String message = Logging.getMessage("nullValue.DrawContextIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.namedShapeAttributes.clear();

        // Render lines and collect text labels
        Collection text = new ArrayList();
        for (Pair pair : this.renderables)
        {
            Object renderable = pair.a;
            String paramsKey = (pair.b != null && pair.b instanceof String) ? (String) pair.b : null;
            GraticuleRenderingParams renderingParams = paramsKey != null ? this.namedParams.get(paramsKey) : null;

            if (renderable != null && renderable instanceof Path)
            {
                if (renderingParams == null || renderingParams.isDrawLines())
                {
                    applyRenderingParams(paramsKey, renderingParams, (Path) renderable, opacity);
                    ((Path) renderable).render(dc);
                }
            }
            else if (renderable != null && renderable instanceof GeographicText)
            {
                if (renderingParams == null || renderingParams.isDrawLabels())
                {
                    applyRenderingParams(renderingParams, (GeographicText) renderable, opacity);
                    text.add((GeographicText) renderable);
                }
            }
        }

        // Render text labels
        this.textRenderer.render(dc, text);
    }

    public GraticuleRenderingParams getRenderingParams(String key)
    {
        if (key == null)
        {
            String message = Logging.getMessage("nullValue.KeyIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        GraticuleRenderingParams value = this.namedParams.get(key);
        if (value == null)
        {
            value = new GraticuleRenderingParams();
            initRenderingParams(value);
            if (this.defaultParams != null)
                value.setValues(this.defaultParams);

            this.namedParams.put(key, value);
        }

        return value;
    }

    public Collection> getAllRenderingParams()
    {
        return this.namedParams.entrySet();
    }

    public void setRenderingParams(String key, GraticuleRenderingParams renderingParams)
    {
        if (key == null)
        {
            String message = Logging.getMessage("nullValue.KeyIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        initRenderingParams(renderingParams);
        this.namedParams.put(key, renderingParams);
    }

    public AVList getDefaultParams()
    {
        return this.defaultParams;
    }

    public void setDefaultParams(AVList defaultParams)
    {
        this.defaultParams = defaultParams;
    }

    private AVList initRenderingParams(AVList params)
    {
        if (params == null)
        {
            String message = Logging.getMessage("nullValue.AVListIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (params.getValue(GraticuleRenderingParams.KEY_DRAW_LINES) == null)
            params.setValue(GraticuleRenderingParams.KEY_DRAW_LINES, Boolean.TRUE);

        if (params.getValue(GraticuleRenderingParams.KEY_LINE_COLOR) == null)
            params.setValue(GraticuleRenderingParams.KEY_LINE_COLOR, Color.WHITE);

        if (params.getValue(GraticuleRenderingParams.KEY_LINE_WIDTH) == null)
            //noinspection UnnecessaryBoxing
            params.setValue(GraticuleRenderingParams.KEY_LINE_WIDTH, new Double(1));

        if (params.getValue(GraticuleRenderingParams.KEY_LINE_STYLE) == null)
            params.setValue(GraticuleRenderingParams.KEY_LINE_STYLE, GraticuleRenderingParams.VALUE_LINE_STYLE_SOLID);

        if (params.getValue(GraticuleRenderingParams.KEY_DRAW_LABELS) == null)
            params.setValue(GraticuleRenderingParams.KEY_DRAW_LABELS, Boolean.TRUE);

        if (params.getValue(GraticuleRenderingParams.KEY_LABEL_COLOR) == null)
            params.setValue(GraticuleRenderingParams.KEY_LABEL_COLOR, Color.WHITE);

        if (params.getValue(GraticuleRenderingParams.KEY_LABEL_FONT) == null)
            params.setValue(GraticuleRenderingParams.KEY_LABEL_FONT, Font.decode("Arial-Bold-12"));

        return params;
    }

    private void applyRenderingParams(AVList params, GeographicText text, double opacity)
    {
        if (params != null && text != null)
        {
            // Apply "label" properties to the GeographicText.
            Object o = params.getValue(GraticuleRenderingParams.KEY_LABEL_COLOR);
            if (o != null && o instanceof Color)
            {
                Color color = applyOpacity((Color) o, opacity);
                float[] compArray = new float[4];
                Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), compArray);
                int colorValue = compArray[2] < .5f ? 255 : 0;
                text.setColor(color);
                text.setBackgroundColor(new Color(colorValue, colorValue, colorValue, color.getAlpha()));
            }

            o = params.getValue(GraticuleRenderingParams.KEY_LABEL_FONT);
            if (o != null && o instanceof Font)
            {
                text.setFont((Font) o);
            }
        }
    }

    private void applyRenderingParams(String key, AVList params, Path path, double opacity)
    {
        if (key != null && params != null && path != null)
        {
            path.setAttributes(this.getLineShapeAttributes(key, params, opacity));
        }
    }

    private ShapeAttributes getLineShapeAttributes(String key, AVList params, double opacity)
    {
        ShapeAttributes attrs = this.namedShapeAttributes.get(key);
        if (attrs == null)
        {
            attrs = createLineShapeAttributes(params, opacity);
            this.namedShapeAttributes.put(key, attrs);
        }
        return attrs;
    }

    private ShapeAttributes createLineShapeAttributes(AVList params, double opacity)
    {
        ShapeAttributes attrs = new BasicShapeAttributes();
        attrs.setDrawInterior(false);
        attrs.setDrawOutline(true);
        if (params != null)
        {
            // Apply "line" properties.
            Object o = params.getValue(GraticuleRenderingParams.KEY_LINE_COLOR);
            if (o != null && o instanceof Color)
            {
                attrs.setOutlineMaterial(new Material(applyOpacity((Color) o, opacity)));
                attrs.setOutlineOpacity(opacity);
            }

            Double lineWidth = AVListImpl.getDoubleValue(params, GraticuleRenderingParams.KEY_LINE_WIDTH);
            if (lineWidth != null)
            {
                attrs.setOutlineWidth(lineWidth);
            }

            String s = params.getStringValue(GraticuleRenderingParams.KEY_LINE_STYLE);
            // Draw a solid line.
            if (GraticuleRenderingParams.VALUE_LINE_STYLE_SOLID.equalsIgnoreCase(s))
            {
                attrs.setOutlineStipplePattern((short) 0xAAAA);
                attrs.setOutlineStippleFactor(0);
            }
            // Draw the line as longer strokes with space in between.
            else if (GraticuleRenderingParams.VALUE_LINE_STYLE_DASHED.equalsIgnoreCase(s))
            {
                int baseFactor = (int) (lineWidth != null ? Math.round(lineWidth) : 1.0);
                attrs.setOutlineStipplePattern((short) 0xAAAA);
                attrs.setOutlineStippleFactor(3 * baseFactor);
            }
            // Draw the line as a evenly spaced "square" dots.
            else if (GraticuleRenderingParams.VALUE_LINE_STYLE_DOTTED.equalsIgnoreCase(s))
            {
                int baseFactor = (int) (lineWidth != null ? Math.round(lineWidth) : 1.0);
                attrs.setOutlineStipplePattern((short) 0xAAAA);
                attrs.setOutlineStippleFactor(baseFactor);
            }
        }
        return attrs;
    }

    private Color applyOpacity(Color color, double opacity)
    {
        if (opacity >= 1)
            return color;

        float[] compArray = color.getRGBComponents(null);
        return new Color(compArray[0], compArray[1], compArray[2], compArray[3] * (float) opacity);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy