Package com.bbn.openmap.omGraphics

Source Code of com.bbn.openmap.omGraphics.OMLine

// **********************************************************************
//
// <copyright>
//
//  BBN Technologies
//  10 Moulton Street
//  Cambridge, MA 02138
//  (617) 873-8000
//
//  Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/omGraphics/OMLine.java,v $
// $RCSfile: OMLine.java,v $
// $Revision: 1.7.2.5 $
// $Date: 2008/01/29 02:21:01 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.omGraphics;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.GeneralPath;
import java.io.Serializable;
import java.util.ArrayList;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.omGraphics.geom.NonRegional;
import com.bbn.openmap.omGraphics.util.ArcCalc;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.Debug;

/**
* Graphic object that represents a simple line.
* <p>
* The OMLine is used to create simple lines, from one point on the
* window to the other. If you want to have a line with several parts,
* use OMPoly as a polyline with no fillColor.
* <h3>NOTE:</h3>
* See the <a
* href="com.bbn.openmap.proj.Projection.html#line_restrictions">
* RESTRICTIONS </a> on Lat/Lon lines. Not following the guidelines
* listed may result in ambiguous/undefined shapes! Similar
* assumptions apply to the other vector graphics that we define:
* circles, ellipses, rects, polys.
* <p>
*
* @see OMPoly
*/
public class OMLine extends OMAbstractLine implements Serializable, NonRegional {

    protected boolean isPolyline = false;

    /** latlons is a array of 4 floats - lat1, lon1, lat2, lon2. */
    protected float[] latlons = null;

    /** pts is an array of 4 ints - px1, py1, px2, py2. */
    protected int[] pts = null;

    /**
     * For x-y and offset lines, there is the ability to put a curve
     * in the line. This setting is the amount of an angle, limited to
     * a semi-circle (PI) that the curve will represent. In other
     * words, the arc between the two end points is going to look like
     * a 0 degrees of a circle (straight line, which is the default),
     * or 180 degrees of a circle (full semi-circle). Given in
     * radians, though, not degrees. The ArcCalc object handles all
     * the details.
     */
    protected ArcCalc arc = null;

    public final static int STRAIGHT_LINE = 0;
    public final static int CURVED_LINE = 1;

    /** Generic constructor, attributes need to filled later. */
    public OMLine() {
        super(RENDERTYPE_UNKNOWN, LINETYPE_UNKNOWN, DECLUTTERTYPE_NONE);
    }

    /**
     * Create a line from lat lon points.
     *
     * @param lat_1 latitude of first point, decimal degrees.
     * @param lon_1 longitude of first point, decimal degrees.
     * @param lat_2 latitude of second point, decimal degrees.
     * @param lon_2 longitude of second point, decimal degrees.
     * @param lineType a choice between LINETYPE_STRAIGHT,
     *        LINETYPE_GREATCIRCLE or LINETYPE_RHUMB.
     */
    public OMLine(float lat_1, float lon_1, float lat_2, float lon_2,
            int lineType) {
        this(lat_1, lon_1, lat_2, lon_2, lineType, -1);
    }

    /**
     * Create a line from lat lon points.
     *
     * @param lat_1 latitude of first point, decimal degrees.
     * @param lon_1 longitude of first point, decimal degrees.
     * @param lat_2 latitude of second point, decimal degrees.
     * @param lon_2 longitude of second point, decimal degrees.
     * @param lineType a choice between LINETYPE_STRAIGHT,
     *        LINETYPE_GREATCIRCLE or LINETYPE_RHUMB.
     * @param nsegs number of segment points (only for
     *        LINETYPE_GREATCIRCLE or LINETYPE_RHUMB line types, and
     *        if &lt; 1, this value is generated internally)
     */
    public OMLine(float lat_1, float lon_1, float lat_2, float lon_2,
            int lineType, int nsegs) {
        super(RENDERTYPE_LATLON, lineType, DECLUTTERTYPE_NONE);
        latlons = new float[4];
        latlons[0] = lat_1;
        latlons[2] = lat_2;
        latlons[1] = lon_1;
        latlons[3] = lon_2;
        this.nsegs = nsegs;
    }

    /**
     * Create a line between two xy points on the window.
     *
     * @param x1 the x location of the first point, in pixels from the
     *        left of the window.
     * @param y1 the y location of the first point, in pixels from the
     *        top of the window.
     * @param x2 the x location of the second point, in pixels from
     *        the left of the window.
     * @param y2 the y location of the second point, in pixels from
     *        the top of the window.
     */
    public OMLine(int x1, int y1, int x2, int y2) {
        super(RENDERTYPE_XY, LINETYPE_STRAIGHT, DECLUTTERTYPE_NONE);
        pts = new int[4];
        pts[0] = x1;
        pts[1] = y1;
        pts[2] = x2;
        pts[3] = y2;
    }

    /**
     * Create a line between two x-y points on the window, where the
     * x-y points are offsets from a lat-lon point. It assumes that
     * you'll want a straight window line between the points, so if
     * you don't, use the setLineType() method to change it.
     *
     * @param lat_1 the latitude of the reference point of the line,
     *        in decimal degrees.
     * @param lon_1 the longitude of the reference point of the line,
     *        in decimal degrees.
     * @param x1 the x location of the first point, in pixels from the
     *        longitude point.
     * @param y1 the y location of the first point, in pixels from the
     *        latitude point.
     * @param x2 the x location of the second point, in pixels from
     *        the longitude point.
     * @param y2 the y location of the second point, in pixels from
     *        the latitude point.
     */
    public OMLine(float lat_1, float lon_1, int x1, int y1, int x2, int y2) {

        super(RENDERTYPE_OFFSET, LINETYPE_STRAIGHT, DECLUTTERTYPE_NONE);
        latlons = new float[4];
        pts = new int[4];
        latlons[0] = lat_1;
        latlons[1] = lon_1;
        pts[0] = x1;
        pts[1] = y1;
        pts[2] = x2;
        pts[3] = y2;
    }

    /**
     * Set the lat lon values of the end points of the line from an
     * array of floats - lat1, lon1, lat2, lon2. This does not look at
     * the line render type, so it acts accordingly. LL1 is only used
     * in RENDERTYPE_LATLON, RENDERTYPE_OFFSET, and LL2 is only used
     * in RENDERTYPE_LATLON.
     *
     * @param lls array of floats - lat1, lon1, lat2, lon2
     */
    public void setLL(float[] lls) {
        latlons = lls;
        setNeedToRegenerate(true);
    }

    /**
     * Get the lat lon values of the end points of the line in an
     * array of floats - lat1, lon1, lat2, lon2. Again, this does not
     * look at the line render type, so it acts accordingly. LL1 is
     * only used in RENDERTYPE_LATLON, RENDERTYPE_OFFSET, and LL2 is
     * only used in RENDERTYPE_LATLON.
     *
     * @return the lat lon array, and all are decimal degrees.
     */
    public float[] getLL() {
        return latlons;
    }

    /**
     * Set the xy values of the end points of the line from an array
     * of ints - x1, y1, x2, y2 . This does not look at the line
     * render type, so it acts accordingly. p1 and p2 are only used in
     * RENDERTYPE_XY, RENDERTYPE_OFFSET.
     *
     * @param xys array of ints for the points - x1, y1, x2, y2
     */
    public void setPts(int[] xys) {
        pts = xys;
        setNeedToRegenerate(true);
    }

    /**
     * Get the xy values of the end points of the line in an array of
     * ints - x1, y1, x2, y2 . This does not look at the line render
     * type, so it acts accordingly. p1 and p2 are only used in
     * RENDERTYPE_XY, RENDERTYPE_OFFSET.
     *
     * @return the array of x-y points, and all are pixel values
     */
    public int[] getPts() {
        return pts;
    }

    /**
     * Check to see if this line is a polyline. This is a polyline if
     * it is LINETYPE_GREATCIRCLE or LINETYPE_RHUMB for
     * RENDERTYPE_LATLON polys.
     *
     * @return true if polyline false if not
     */
    public boolean isPolyline() {
        return isPolyline;
    }

    /**
     * Set the number of segments of the lat/lon line. (This is only
     * for LINETYPE_GREATCIRCLE or LINETYPE_RHUMB line types, and if
     * &lt; 1, this value is generated internally).
     *
     * @param nsegs number of segment points
     */
    public void setNumSegs(int nsegs) {
        this.nsegs = nsegs;
    }

    /**
     * Get the number of segments of the lat/lon line. (This is only
     * for LINETYPE_GREATCIRCLE or LINETYPE_RHUMB line types).
     *
     * @return int number of segment points
     */
    public int getNumSegs() {
        return nsegs;
    }

    /**
     * Set the arc that is drawn between the points of a x-y or offset
     * line.
     */
    public void setArc(ArcCalc ac) {
        arc = ac;
    }

    /**
     * Return the arc angle set for this line. Will only be set if it
     * was set externally.
     *
     * @return arc angle in radians.
     */
    public ArcCalc getArc() {
        return arc;
    }

    /**
     * Prepare the line for rendering.
     *
     * @param proj Projection
     * @return true if generate was successful
     */
    public boolean generate(Projection proj) {
        setShape(null);

        if (proj == null) {
            Debug.message("omgraphic", "OMLine: null projection in generate!");
            return false;
        }

        // reset the internals
        isPolyline = false;
        initLabelingDuringGenerate();

        switch (renderType) {
        case RENDERTYPE_XY:
            if (arc != null) {
                xpoints = new int[1][];
                ypoints = new int[1][];
                arc.generate(pts[0], pts[1], pts[2], pts[3]);
                xpoints[0] = arc.getXPoints();
                ypoints[0] = arc.getYPoints();
            } else {
                xpoints = new int[1][2];
                ypoints = new int[1][2];

                if (pts == null)
                    return false;

                xpoints[0][0] = pts[0];
                ypoints[0][0] = pts[1];
                xpoints[0][1] = pts[2];
                ypoints[0][1] = pts[3];
            }
            shape = createShape(xpoints[0], ypoints[0], false);
            break;
        case RENDERTYPE_OFFSET:
            if (!proj.isPlotable(latlons[0], latlons[1])) {
                setNeedToRegenerate(true);// HMMM not the best flag
                return false;
            }
            Point p1 = proj.forward(latlons[0], latlons[1]);
            if (arc != null) {
                xpoints = new int[1][];
                ypoints = new int[1][];
                arc.generate(p1.x + pts[0], p1.y + pts[1], p1.x + pts[2], p1.y
                        + pts[3]);

                xpoints[0] = arc.getXPoints();
                ypoints[0] = arc.getYPoints();
            } else {
                xpoints = new int[1][2];
                ypoints = new int[1][2];

                xpoints[0][0] = p1.x + pts[0];
                ypoints[0][0] = p1.y + pts[1];
                xpoints[0][1] = p1.x + pts[2];
                ypoints[0][1] = p1.y + pts[3];
            }
            shape = createShape(xpoints[0], ypoints[0], false);
            break;
        case RENDERTYPE_LATLON:
            if (arc != null) {
                p1 = proj.forward(latlons[0], latlons[1]);
                Point p2 = proj.forward(latlons[2], latlons[3]);
                xpoints = new int[1][];
                ypoints = new int[1][];
                arc.generate(p1.x, p1.y, p2.x, p2.y);

                xpoints[0] = arc.getXPoints();
                ypoints[0] = arc.getYPoints();

                shape = createShape(xpoints[0], ypoints[0], false);

                isPolyline = true;

            } else {
                ArrayList lines = proj.forwardLine(new LatLonPoint(latlons[0], latlons[1]),
                        new LatLonPoint(latlons[2], latlons[3]),
                        lineType,
                        nsegs);
                int size = lines.size();

                xpoints = new int[(int) (size / 2)][0];
                ypoints = new int[xpoints.length][0];

                for (int i = 0, j = 0; i < size; i += 2, j++) {
                    int[] xps = (int[]) lines.get(i);
                    int[] yps = (int[]) lines.get(i + 1);

                    xpoints[j] = xps;
                    ypoints[j] = yps;

                    GeneralPath gp = createShape(xps, yps, false);
                    if (shape == null) {
                        shape = gp;
                    } else {
                        ((GeneralPath) shape).append(gp, false);
                    }
                }
                isPolyline = (lineType != LINETYPE_STRAIGHT);
            }
            break;
        case RENDERTYPE_UNKNOWN:
            System.err.println("OMLine.generate: invalid RenderType");
            return false;
        }

        setLabelLocation(shape);

        if (arrowhead != null) {
            arrowhead.generate(this);
        }

        if (arc != null) {
            // This will only do something if debugging is on.
            arc.generate(proj);
        }

        setNeedToRegenerate(false);
        return true;
    }

    /**
     * Paint the line.
     *
     * @param g Graphics context to render into
     */
    public void render(Graphics g) {

        if (!isRenderable()) {
            return;
        }

        // Just to draw the matting for the arrowhead. The matting
        // for the rest of the line will be taken care of in
        // super.render().
        if (arrowhead != null && isMatted() && g instanceof Graphics2D
                && stroke instanceof BasicStroke) {
            ((Graphics2D) g).setStroke(new BasicStroke(((BasicStroke) stroke).getLineWidth() + 2f));
            setGraphicsColor(g, Color.black);
            arrowhead.render(g);
        }

        super.render(g);

        if (arrowhead != null) {
            setGraphicsForEdge(g);
            arrowhead.render(g);
        }

        if (arc != null) {
            // This is a debugging thing, most times does nothing.
            arc.render(g);
        }

    }

    /**
     * The OMLine should never render fill. It can think it does, if
     * the geometry turns out to be curved. Returning false affects
     * distance() and contains() methods.
     */
    public boolean shouldRenderFill() {
        return false;
    }

    /**
     * This takes the area out of OMLines that may look like they have
     * area, depending on their shape. Checks to see what
     * shouldRenderFill() returns (false by default) to decide how to
     * measure this. If shouldRenderFill == true, the super.contains()
     * method is returned, which assumes the line shape has area if it
     * is curved. Otherwise, it returns true if the point is on the
     * line.
     */
    public boolean contains(int x, int y) {
        if (shouldRenderFill()) {
            return super.contains(x, y);
        } else {
            return (distance(x, y) == 0);
        }
    }

}
TOP

Related Classes of com.bbn.openmap.omGraphics.OMLine

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.