Package org.geotools.renderer.windbarbs

Source Code of org.geotools.renderer.windbarbs.WindBarb

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2014, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/
package org.geotools.renderer.windbarbs;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geotools.util.Utilities;

/**
* A WindBarb object made of reference speed in knots, and related number of longBarbs (10 kts), shortBarbs (5 kts) and pennants (50 kts).
*
* @author Daniele Romagnoli, GeoSolutions SAS
*/
class WindBarb {

    /** The logger. */
    private static final Logger LOGGER = org.geotools.util.logging.Logging
            .getLogger(WindBarb.class);

    /**
     * A WindBarbDefinition contains parameters used to build the WindBarb, such as the main vector length, the elements Spacing, the length of long
     * barbs...
     *
     * @author Daniele Romagnoli, GeoSolutions SAS
     *
     */
    static class WindBarbDefinition {

        public WindBarbDefinition(final int vectorLength, final int basePennantLength,
                final int elementsSpacing, final int longBarbLength, final int zeroWindRadius) {
            // checks
            if (vectorLength <= 0) {
                throw new IllegalArgumentException("Invalid vectorLength:" + vectorLength);
            }
            if (basePennantLength <= 0) {
                throw new IllegalArgumentException("Invalid basePennantLength:" + vectorLength);
            }
            if (elementsSpacing <= 0) {
                throw new IllegalArgumentException("Invalid elementsSpacing:" + vectorLength);
            }
            if (vectorLength < elementsSpacing + basePennantLength) {
                throw new IllegalArgumentException(
                        "Invalid vectorLength<elementsSpacing+basePennantLength : " + vectorLength);
            }
            if (longBarbLength <= 0) {
                throw new IllegalArgumentException("Invalid longBarbLength:" + vectorLength);
            }
            if (zeroWindRadius <= 0) {
                throw new IllegalArgumentException("Invalid zeroWindRadius:" + vectorLength);
            }

            // code
            this.vectorLength = vectorLength;
            this.basePennantLength = basePennantLength;
            this.elementsSpacing = elementsSpacing;
            this.longBarbLength = longBarbLength;
            this.shortBarbLength = longBarbLength / 2;
            this.zeroWindRadius = zeroWindRadius;
        }

        /** The main vector length */
        int vectorLength;

        /** The length of the base of the pennant (the triangle) */
        int basePennantLength;

        /** The distance between multiple barbs, and pennants */
        int elementsSpacing;

        /** The length of a long barb */
        int longBarbLength;

        /** The length of a short barb (is always half the length of a long barb) */
        int shortBarbLength;

        int zeroWindRadius;

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("WindBarbDefinition [vectorLength=");
            builder.append(vectorLength);
            builder.append(", basePennantLength=");
            builder.append(basePennantLength);
            builder.append(", elementsSpacing=");
            builder.append(elementsSpacing);
            builder.append(", longBarbLength=");
            builder.append(longBarbLength);
            builder.append(", shortBarbLength=");
            builder.append(shortBarbLength);
            builder.append(", zeroWindRadius=");
            builder.append(zeroWindRadius);
            builder.append("]");
            return builder.toString();
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + basePennantLength;
            result = prime * result + elementsSpacing;
            result = prime * result + longBarbLength;
            result = prime * result + shortBarbLength;
            result = prime * result + vectorLength;
            result = prime * result + zeroWindRadius;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof WindBarbDefinition)) {
                return false;
            }
            WindBarbDefinition other = (WindBarbDefinition) obj;
            if (basePennantLength != other.basePennantLength) {
                return false;
            }
            if (elementsSpacing != other.elementsSpacing) {
                return false;
            }
            if (longBarbLength != other.longBarbLength) {
                return false;
            }
            if (shortBarbLength != other.shortBarbLength) {
                return false;
            }
            if (vectorLength != other.vectorLength) {
                return false;
            }
            if (zeroWindRadius != other.zeroWindRadius) {
                return false;
            }
            return true;
        }
    }

    int knots;

    int pennants;

    int longBarbs;

    int shortBarbs;

    int squares;

    static int DEFAULT_BARB_LENGTH = 20;

    static int DEFAULT_BASE_PENNANT_LENGTH = 5;

    static int DEFAULT_ELEMENTS_SPACING = 5;

    static int DEFAULT_FLAGPOLE_LENGTH = 40;

    static int DEFAULT_ZERO_WIND_RADIUS = 5;

    /** A {@link WindBarbDefinition} instance reporting structural values for a WindBarb (vector length, sizes, ...) */
    WindBarbDefinition windBarbDefinition;

    static WindBarbDefinition DEFAULT_WINDBARB_DEFINITION = new WindBarbDefinition(
            WindBarb.DEFAULT_FLAGPOLE_LENGTH, WindBarb.DEFAULT_BASE_PENNANT_LENGTH,
            WindBarb.DEFAULT_ELEMENTS_SPACING, WindBarb.DEFAULT_BARB_LENGTH,
            WindBarb.DEFAULT_ZERO_WIND_RADIUS);

    public WindBarb(final int knots) {
        this(DEFAULT_WINDBARB_DEFINITION, knots);
    }

    public WindBarb(final WindBarbDefinition definition, final int knots) {
        Utilities.ensureNonNull("definition", definition);
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine("Creating WindBarb for knots: " + knots + " and WindBarbDefinition:"
                    + definition.toString());
        }
        this.windBarbDefinition = definition;
        this.knots = knots;
        if (knots == -1) {
            return;
        } else {
            if (knots < 0) {
                throw new IllegalArgumentException("Illegal wind speeds(kn): " + knots);
            }
            if (knots > 100) {
                throw new IllegalArgumentException("Illegal wind speeds(kn): " + knots
                        + ", max allowed value is 100");
            }
        }
        squares = knots / 100;
        if (squares > 1) {
            throw new IllegalArgumentException(
                    "We can't render wind speeds that require more than 1 square!");
        }
        pennants = (knots - (squares * 100)) / 50;
        longBarbs = (knots - (squares * 100) - (pennants * 50)) / 10;
        shortBarbs = (knots - (squares * 100) - (pennants * 50) - (longBarbs * 10)) / 5;
    }

    /**
     * Build a {@Shape} WindBarb
     *
     * @return
     */
    Shape build() {
        if (knots < 0) {
            return buildAbsentModule();
        } else {
            return buildStandardBarb();
        }

    }

    /**
     * @return
     *
     */
    private Shape buildStandardBarb() {
        int positionOnPath = -windBarbDefinition.vectorLength;

        // Base barb
        Path2D path = new Path2D.Double();

        // Initialize Barb
        if (knots < 5) {
            // let's use a circle for Calm
            return new Ellipse2D.Float(-windBarbDefinition.zeroWindRadius / 2.0f, // the X coordinate of the upper-left corner of the specified
                                                                                  // rectangular area
                    -windBarbDefinition.zeroWindRadius / 2.0f, // the Y coordinate of the upper-left corner of the specified rectangular area
                    windBarbDefinition.zeroWindRadius, windBarbDefinition.zeroWindRadius);
        } else {

            // draw wind barb line
            path.moveTo(0, 0);
            path.lineTo(0, positionOnPath);
        }
        // pennants management
        if (squares > 0) {
            positionOnPath = drawSquare(path, positionOnPath);
            positionOnPath += windBarbDefinition.elementsSpacing; // add spacing
        }

        // pennants management
        if (pennants > 0) {
            positionOnPath = drawPennants(path, positionOnPath);
            positionOnPath += windBarbDefinition.elementsSpacing; // add spacing
        }

        // long barbs management
        if (longBarbs > 0) {
            positionOnPath = drawLongBarbs(path, positionOnPath);
            positionOnPath += windBarbDefinition.elementsSpacing; // add spacing
        }

        // short barbs management
        if (shortBarbs > 0) {
            positionOnPath = drawShortBarb(path, positionOnPath);
        }

        // FLIP for geotools
        final Shape createTransformedShape = path.createTransformedShape(AffineTransform
                .getScaleInstance(1, -1));
        return createTransformedShape;

    }

    /**
     * Build a {@Shape} WindBarb
     *
     * @return
     */
    Shape buildAbsentModule() {

        // Base barb
        Path2D path = new Path2D.Double();
        int positionOnPath = 0;

        // draw wind barb line
        path.moveTo(0, positionOnPath);
        positionOnPath -= windBarbDefinition.vectorLength;
        path.lineTo(0, positionOnPath);

        path.moveTo(windBarbDefinition.shortBarbLength / 2.0f, positionOnPath
                - windBarbDefinition.shortBarbLength / 2.0f);
        path.lineTo(-windBarbDefinition.shortBarbLength / 2.0f, positionOnPath
                + windBarbDefinition.shortBarbLength / 2.0f);

        path.moveTo(-windBarbDefinition.shortBarbLength / 2.0f, positionOnPath
                - windBarbDefinition.shortBarbLength / 2.0f);
        path.lineTo(windBarbDefinition.shortBarbLength / 2.0f, positionOnPath
                + windBarbDefinition.shortBarbLength / 2.0f);

        // FLIP for geotools
        final Shape createTransformedShape = path.createTransformedShape(AffineTransform
                .getScaleInstance(1, -1));
        return createTransformedShape;
    }

    /**
     * @param path
     * @param positionOnPath
     * @return
     */
    private int drawSquare(Path2D path, int positionOnPath) {
        if (squares <= 0) {
            return positionOnPath;
        }

        for (int elements = 0; elements < squares; elements++) {
            // move forward one pennant at a time

            // draw pennant
            path.moveTo(0, positionOnPath);
            path.lineTo(windBarbDefinition.longBarbLength / 2.0d, positionOnPath); // first edge
            positionOnPath += windBarbDefinition.longBarbLength / 2.0d;
            path.lineTo(windBarbDefinition.longBarbLength / 2.0d, positionOnPath); // second edge
            path.lineTo(0, positionOnPath);
            path.closePath();

            // squares are drawn one after the other
        }
        return positionOnPath;
    }

    /**
     * Add short barbs to the shape
     *
     * @param path
     * @param positionOnPath
     * @return
     */
    private int drawShortBarb(Path2D path, int positionOnPath) {
        if (pennants == 0 && longBarbs == 0) {
            positionOnPath = -windBarbDefinition.vectorLength + DEFAULT_ELEMENTS_SPACING;
        }

        path.moveTo(0, positionOnPath);
        path.lineTo(windBarbDefinition.shortBarbLength, positionOnPath
                - windBarbDefinition.basePennantLength / 4.0);
        return positionOnPath;
    }

    /**
     * Add long barbs to the shape
     *
     * @param path
     * @param positionOnPath
     * @return
     */
    private int drawLongBarbs(Path2D path, int positionOnPath) {
        if (longBarbs <= 0) {
            return positionOnPath;
        }
        for (int elements = 0; elements < longBarbs; elements++) {

            if (elements >= 1) {
                // spacing if neede
                positionOnPath += windBarbDefinition.elementsSpacing;
            }
            // draw long barb
            path.moveTo(0, positionOnPath);
            path.lineTo(windBarbDefinition.longBarbLength, positionOnPath
                    - windBarbDefinition.basePennantLength / 2.0);

        }
        return positionOnPath;
    }

    /**
     * add Pennants to the shape
     *
     * @param path
     * @param positionOnPath
     * @return
     */
    private int drawPennants(Path2D path, int positionOnPath) {
        if (pennants <= 0) {
            return positionOnPath;
        }

        for (int elements = 0; elements < pennants; elements++) {
            // move forward one pennant at a time

            // draw pennant
            path.moveTo(0, positionOnPath);
            positionOnPath += windBarbDefinition.basePennantLength / 2.0;
            path.lineTo(windBarbDefinition.longBarbLength, positionOnPath); // first edge
            positionOnPath += windBarbDefinition.basePennantLength / 2.0;
            path.lineTo(0, positionOnPath); // second edge
            path.closePath();

            // only one square
        }
        return positionOnPath;
    }
}
TOP

Related Classes of org.geotools.renderer.windbarbs.WindBarb

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.