Package com.bbn.openmap.omGraphics

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

// **********************************************************************
//
// <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/EditableOMCircle.java,v $
// $RCSfile: EditableOMCircle.java,v $
// $Revision: 1.5.2.3 $
// $Date: 2008/01/29 02:21:01 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.omGraphics;

import java.awt.event.MouseEvent;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.layer.util.stateMachine.State;
import com.bbn.openmap.omGraphics.editable.CircleStateMachine;
import com.bbn.openmap.omGraphics.editable.GraphicEditState;
import com.bbn.openmap.omGraphics.editable.GraphicSelectedState;
import com.bbn.openmap.omGraphics.editable.GraphicSetOffsetState;
import com.bbn.openmap.proj.GreatCircle;
import com.bbn.openmap.proj.Length;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.Debug;

/**
* The EditableOMCircle encompasses an OMCircle, providing methods for modifying
* or creating it. This class only modifies circles in lat/lon space
* (RENDERTYPE_LATLON) - and ellipses in screen space (RENDERTYPE_XY or
* RENDERTYPE_OFFSET). When you grab at the circle, you change the radius of the
* entire circle. Grabbing the center point moves the circle. If there is an
* offset point, moving the center point changes the circle's position in
* relation to the offset point. Moving the offset point moves the circle,
* keeping the distance to the center point constant.
*/
public class EditableOMCircle extends EditableOMGraphic {

    protected VerticalGrabPoint gpn;
    protected HorizontalGrabPoint gpw;
    protected VerticalGrabPoint gps;
    protected HorizontalGrabPoint gpe;
    protected GrabPoint gpnw;
    protected GrabPoint gpne;
    protected GrabPoint gpsw;
    protected GrabPoint gpse;
    protected OffsetGrabPoint gpc;
    protected GrabPoint gpr;
    protected OffsetGrabPoint gpo; // offset
    protected OffsetGrabPoint gpm; // for grabbing the circle and
    // changing the radius during creation.

    protected OMCircle circle;

    public final static int CENTER_POINT_INDEX = 0;
    public final static int NW_POINT_INDEX = 1;
    public final static int N_POINT_INDEX = 2;
    public final static int NE_POINT_INDEX = 3;
    public final static int W_POINT_INDEX = 4;
    public final static int E_POINT_INDEX = 5;
    public final static int SW_POINT_INDEX = 6;
    public final static int S_POINT_INDEX = 7;
    public final static int SE_POINT_INDEX = 8;
    public final static int RADIUS_POINT_INDEX = 9;
    public final static int OFFSET_POINT_INDEX = 10;

    /**
     * Create the EditableOMCircle, setting the state machine to create the
     * circle off of the gestures.
     */
    public EditableOMCircle() {
        createGraphic(null);
    }

    /**
     * Create an EditableOMCircle with the circleType and renderType parameters
     * in the GraphicAttributes object.
     */
    public EditableOMCircle(GraphicAttributes ga) {
        createGraphic(ga);
    }

    /**
     * Create the EditableOMCircle with an OMCircle already defined, ready for
     * editing.
     *
     * @param omc OMCircle that should be edited.
     */
    public EditableOMCircle(OMCircle omc) {
        setGraphic(omc);
    }

    /**
     * Create and initialize the state machine that interprets the modifying
     * gestures/commands, as well as ititialize the grab points. Also allocates
     * the grab point array needed by the EditableOMCircle.
     */
    public void init() {
        setCanGrabGraphic(false);
        Debug.message("eomg", "EditableOMCircle.init()");
        setStateMachine(new CircleStateMachine(this));
        gPoints = new GrabPoint[11];
    }

    /**
     * Set the graphic within the state machine. If the graphic is null, then
     * one shall be created, and located off screen until the gestures driving
     * the state machine place it on the map.
     */
    public void setGraphic(OMGraphic graphic) {
        init();
        if (graphic instanceof OMCircle) {
            circle = (OMCircle) graphic;
            stateMachine.setSelected();
            setGrabPoints(circle);
        } else {
            createGraphic(null);
        }
    }

    /**
     * Create and set the graphic within the state machine. The
     * GraphicAttributes describe the type of circle to create.
     */
    public void createGraphic(GraphicAttributes ga) {
        init();
        stateMachine.setUndefined();
        int renderType = OMGraphic.RENDERTYPE_UNKNOWN;

        if (ga != null) {
            renderType = ga.getRenderType();
        }

        if (Debug.debugging("eomc")) {
            Debug.output("EditableOMCircle.createGraphic(): rendertype = "
                    + renderType);
        }

        switch (renderType) {
        case (OMGraphic.RENDERTYPE_LATLON):
            circle = new OMCircle(90f, -180f, 0f);
            break;
        case (OMGraphic.RENDERTYPE_OFFSET):
            circle = new OMCircle(90f, -180f, 0, 0, 1, 1);
            break;
        default:
            circle = new OMCircle(-1, -1, 1, 1);
        }

        if (ga != null) {
            ga.setTo(circle, true);
        }
    }

    /**
     * Get whether a graphic can be manipulated by its edges, rather than just
     * by its grab points.
     */
    public boolean getCanGrabGraphic() {
        return canGrabGraphic
                || circle.renderType == OMGraphic.RENDERTYPE_LATLON;
    }

    /**
     * Get the OMGraphic being created/modified by the EditableOMCircle.
     */
    public OMGraphic getGraphic() {
        return circle;
    }

    /**
     * Attach to the Moving OffsetGrabPoint so if it moves, it will move this
     * EditableOMGraphic with it. EditableOMGraphic version doesn't do anything,
     * each subclass has to decide which of its OffsetGrabPoints should be
     * attached to it.
     */
    public void attachToMovingGrabPoint(OffsetGrabPoint gp) {
        gp.addGrabPoint(gpo);
    }

    /**
     * Detach from a Moving OffsetGrabPoint. The EditableOMGraphic version
     * doesn't do anything, each subclass should remove whatever GrabPoint it
     * would have attached to an OffsetGrabPoint.
     */
    public void detachFromMovingGrabPoint(OffsetGrabPoint gp) {
        gp.removeGrabPoint(gpo);
    }

    /**
     * Set the GrabPoint that is in the middle of being modified, as a result of
     * a mouseDragged event, or other selection process.
     */
    public void setMovingPoint(GrabPoint gp) {
        super.setMovingPoint(gp);
        // set as a flag that the graphic is being moved, and it's
        // parameters should not be adjusted.
        gpm = null;
    }

    /**
     * Given a MouseEvent, find a GrabPoint that it is touching, and set the
     * moving point to that GrabPoint.
     *
     * @param e MouseEvent
     * @return GrabPoint that is touched by the MouseEvent, null if none are.
     */
    public GrabPoint getMovingPoint(MouseEvent e) {

        movingPoint = null;

        GrabPoint[] gb = getGrabPoints();
        int x = e.getX();
        int y = e.getY();

        for (int i = gb.length - 1; i >= 0; i--) {

            if (i != RADIUS_POINT_INDEX && gb[i] != null
                    && gb[i].distance(x, y) == 0) {

                setMovingPoint(gb[i]);
                // in case the points are on top of each other, the
                // last point in the array will take precidence.
                break;
            }
        }
        return movingPoint;
    }

    protected int lastRenderType = -1;

    /**
     * Check to make sure the grab points are not null. If they are, allocate
     * them, and them assign them to the array.
     */
    public void assertGrabPoints() {
        int rt = getGraphic().getRenderType();
        if (rt != lastRenderType) {
            clearGrabPoints();
            lastRenderType = rt;
        }

        if (gpr == null) {
            gpr = new GrabPoint(-1, -1);
            gPoints[RADIUS_POINT_INDEX] = gpr;
        }
        if (gpnw == null) {
            gpnw = new GrabPoint(-1, -1);
            gPoints[NW_POINT_INDEX] = gpnw;
        }
        if (gpn == null) {
            gpn = new VerticalGrabPoint(-1, -1);
            gPoints[N_POINT_INDEX] = gpn;
        }
        if (gpne == null) {
            gpne = new GrabPoint(-1, -1);
            gPoints[NE_POINT_INDEX] = gpne;
        }
        if (gpw == null) {
            gpw = new HorizontalGrabPoint(-1, -1);
            gPoints[W_POINT_INDEX] = gpw;
        }
        if (gpe == null) {
            gpe = new HorizontalGrabPoint(-1, -1);
            gPoints[E_POINT_INDEX] = gpe;
        }
        if (gpsw == null) {
            gpsw = new GrabPoint(-1, -1);
            gPoints[SW_POINT_INDEX] = gpsw;
        }
        if (gps == null) {
            gps = new VerticalGrabPoint(-1, -1);
            gPoints[S_POINT_INDEX] = gps;
        }
        if (gpse == null) {
            gpse = new GrabPoint(-1, -1);
            gPoints[SE_POINT_INDEX] = gpse;
        }

        if (gpc == null) {
            gpc = new OffsetGrabPoint(-1, -1);
            gPoints[CENTER_POINT_INDEX] = gpc;
            if (getGraphic().getRenderType() != OMGraphic.RENDERTYPE_LATLON) {
                gpc.addGrabPoint(gpnw);
                gpc.addGrabPoint(gpn);
                gpc.addGrabPoint(gpne);
                gpc.addGrabPoint(gpw);
                gpc.addGrabPoint(gpe);
                gpc.addGrabPoint(gpsw);
                gpc.addGrabPoint(gps);
                gpc.addGrabPoint(gpse);
            }
        }

        if (gpo == null) {
            gpo = new OffsetGrabPoint(-1, -1);
            gPoints[OFFSET_POINT_INDEX] = gpo;
            gpo.addGrabPoint(gpc);
        }
    }

    protected void clearGrabPoints() {

        gpc = null;
        gpr = null;
        gpnw = null;
        gpn = null;
        gpne = null;
        gpw = null;
        gpe = null;
        gpsw = null;
        gps = null;
        gpse = null;
        gpo = null;

        gPoints[CENTER_POINT_INDEX] = gpc;
        gPoints[RADIUS_POINT_INDEX] = gpr;
        gPoints[NW_POINT_INDEX] = gpnw;
        gPoints[N_POINT_INDEX] = gpn;
        gPoints[NE_POINT_INDEX] = gpne;
        gPoints[W_POINT_INDEX] = gpw;
        gPoints[E_POINT_INDEX] = gpe;
        gPoints[SW_POINT_INDEX] = gpsw;
        gPoints[S_POINT_INDEX] = gps;
        gPoints[SE_POINT_INDEX] = gpse;
        gPoints[OFFSET_POINT_INDEX] = gpo;

    }

    /**
     * Set the grab points for the graphic provided, setting them on the extents
     * of the graphic. Called when you want to set the grab points off the
     * location of the graphic.
     */
    public void setGrabPoints(OMGraphic graphic) {
        if (!(graphic instanceof OMCircle)) {
            return;
        }

        assertGrabPoints();

        OMCircle circle = (OMCircle) graphic;
        boolean ntr = circle.getNeedToRegenerate();
        int renderType = circle.getRenderType();

        int centerx = 0;
        int centery = 0;

        if (ntr == false) {

            if (renderType == OMGraphic.RENDERTYPE_LATLON
                    || renderType == OMGraphic.RENDERTYPE_OFFSET) {

                if (projection != null) {
                    LatLonPoint center = circle.getLatLon();
                    java.awt.Point p = projection.forward(center);
                    centerx = (int) p.getX();
                    centery = (int) p.getY();
                }
                if (renderType == OMGraphic.RENDERTYPE_OFFSET) {
                    gpo.setX(centerx);
                    gpo.setY(centery);

                    centerx += circle.getOffX();
                    centery += circle.getOffY();
                }

            } else if (renderType == OMGraphic.RENDERTYPE_XY) {
                centerx = circle.getX();
                centery = circle.getY();
            }

            if (renderType == OMGraphic.RENDERTYPE_LATLON) {
                Debug.message("eomg",
                        "EditableOMCircle: modifying lat/lon circle");
                if (projection != null) {
                    gpc.set(centerx, centery);
                }

                // Note that we really don't handle this situation
                // well, if there isn't a projection. We kind of
                // assume later that there is one, and although there
                // shouldn't be massive meltdowns, data could look
                // funky on the screen if the projection is
                // unavailable.

            } else {
                // Grab the projected endpoints
                Debug.message("eomg",
                        "EditableOMCircle: modifying x/y or offset standard circle");
                int height = circle.getHeight() / 2;
                int width = circle.getWidth() / 2;
                gpc.set(centerx, centery);

                gpe.set(centerx + width, centery, true);
                gps.set(centerx, centery + height, true);
                gpw.set(centerx - width, centery, true);
                gpn.set(centerx, centery - height, true);

                gpne.set(gpe.getX(), gpn.getY());
                gpnw.set(gpw.getX(), gpn.getY());
                gpse.set(gpe.getX(), gps.getY());
                gpsw.set(gpw.getX(), gps.getY());
                gpc.updateOffsets();

                // Debug.output("***\nheight:" + height + ", width:" +
                // width +
                // "\n EditableOMCircle: east at x: " + gpe.getX() +
                // ", y:" + gpe.getY());
                // Debug.output(" EditableOMCircle: north at x: " +
                // gpn.getX() +
                // ", y:" + gpn.getY());
                // Debug.output(" EditableOMCircle: northeast at x: "
                // + gpne.getX() +
                // ", y:" + gpne.getY());
                // Debug.output(" EditableOMCircle: center at x: " +
                // centerx +
                // ", y:" + centery);
            }

            // Check to see if the circle is a offset circle, and set
            // the
            // offset grab point offsets accordingly.
            if (circle.getRenderType() == OMGraphic.RENDERTYPE_OFFSET) {
                gpo.updateOffsets();
            }

        } else {
            Debug.message("eomg",
                    "EditableOMCircle.setGrabPoints: graphic needs to be regenerated");
        }

    }

    /**
     * Take the current location of the GrabPoints, and modify the location
     * parameters of the OMCircle with them. Called when you want the graphic to
     * change according to the grab points.
     */
    public void setGrabPoints() {

        int renderType = circle.getRenderType();

        // If the gpm is a movement GP or the gpc, then we need to
        // update all the grab points relative location to the gpm,
        // and then use the code below.

        // If the gpm is the gpo, then the circle moves, too. That's
        // OK, because if the gpo is moving, then the other points
        // have been moved already.

        // If the gpm is one of the other GPs, then we need to update
        // the radius or height and width based on that point, as well
        // as the other GP locations.

        Debug.message("eomg", "EditableOMCircle.setGrabPoints()");

        // Do center point for lat/lon or offset circles
        if (renderType == OMGraphic.RENDERTYPE_LATLON
                || renderType == OMGraphic.RENDERTYPE_OFFSET) {

            GrabPoint llgp;
            // OK, to set the center, if the rendertype is offset,
            // then the center lat/lon has to be set to the offset
            // point. When the circle is initially defined, this is
            // OK because the offset x and y are 0, and the render
            // method knows not to render the point yet.
            if (// movingPoint == gpo ||
            renderType == OMGraphic.RENDERTYPE_OFFSET) {
                llgp = gpo;
            } else {
                // If the moving point is the radius, the the center
                // grab point is the lat/lon point.
                llgp = gpc;
            }

            if (projection != null) {
                LatLonPoint llp = projection.inverse(llgp.getX(), llgp.getY());

                circle.setLatLon(llp.getLatitude(), llp.getLongitude());

                // Do the radius for LATLON circles.
                if (renderType == OMGraphic.RENDERTYPE_LATLON
                        && movingPoint == gpr) {

                    LatLonPoint llpm = projection.inverse(gpr.getX(),
                            gpr.getY());

                    float radius = Length.DECIMAL_DEGREE.fromRadians((float) GreatCircle.spherical_distance(llpm.radlat_,
                            llpm.radlon_,
                            llp.radlat_,
                            llp.radlon_));

                    setRadius(radius);

                }

            } else {
                Debug.message("eomg",
                        "EditableOMCircle.setGrabPoints: projection is null, can't figure out LATLON points for circle.");
            }
        }

        boolean settingOffset = getStateMachine().getState() instanceof GraphicSetOffsetState
                && movingPoint == gpo;

        // If the center point is moving, the offset distance changes
        if (renderType == OMGraphic.RENDERTYPE_OFFSET
                && (settingOffset || movingPoint == gpc)) {
            // Do the offset point.
            circle.setOffX(gpc.getX() - gpo.getX());
            circle.setOffY(gpc.getY() - gpo.getY());
            Debug.message("eomg",
                    "EditableOMCircle: updating offset distance, ox:"
                            + circle.getOffX() + ", oy:" + circle.getOffY());
        }

        // Do the circle height and width for XY and OFFSET render
        // types.
        if (renderType == OMGraphic.RENDERTYPE_XY
                || (renderType == OMGraphic.RENDERTYPE_OFFSET && !settingOffset)) {

            if (renderType == OMGraphic.RENDERTYPE_XY) {
                circle.setX(gpc.getX());
                circle.setY(gpc.getY());
            }

            if (movingPoint instanceof HorizontalGrabPoint) {
                // Must be the left or right...
                circle.setWidth(Math.abs(movingPoint.getX() - gpc.getX()) * 2);

            } else if (movingPoint instanceof VerticalGrabPoint) {
                // Must be the top or bottom...
                circle.setHeight(Math.abs(movingPoint.getY() - gpc.getY()) * 2);

            } else if (movingPoint != gpo && movingPoint != gpc) {
                // Must be one of the corners...
                circle.setWidth(Math.abs(movingPoint.getX() - gpc.getX()) * 2);
                circle.setHeight(Math.abs(movingPoint.getY() - gpc.getY()) * 2);
            }

            // Debug.output("EditableOMCircle.setGrabPoints():
            // movingPoint x:" +
            // movingPoint.getX() + ", y:" + movingPoint.getY() +
            // ", gpc.x:" + gpc.getX() + ", gpc.y:" + gpc.getY());
        }

        if (projection != null) {
            regenerate(projection);
        }
    }

    /**
     * To be overloaded if needed when setting circle's radius.
     *
     * @param radius in DECIMAL_DEGREES
     */
    protected void setRadius(float radius) {
        if (circle != null) {
            circle.setRadius(radius);
        }
    }

    /**
     * Called to set the OffsetGrabPoint to the current mouse location, and
     * update the OffsetGrabPoint with all the other GrabPoint locations, so
     * everything can shift smoothly. Should also set the OffsetGrabPoint to the
     * movingPoint. Should be called only once at the beginning of the general
     * movement, in order to set the movingPoint. After that, redraw(e) should
     * just be called, and the movingPoint will make the adjustments to the
     * graphic that are needed.
     */
    public void move(java.awt.event.MouseEvent e) {
        if (getGraphic().getRenderType() == OMGraphic.RENDERTYPE_LATLON
                && getGraphic().distanceToEdge(e.getX(), e.getY()) < 2) {
            if (gpr == null) {
                gpr = new GrabPoint(-1, -1);
            }
            gpr.set(e.getX(), e.getY());
            movingPoint = gpr;
        }
    }

    /**
     * Use the current projection to place the graphics on the screen. Has to be
     * called to at least assure the graphics that they are ready for rendering.
     * Called when the graphic position changes.
     *
     * @param proj com.bbn.openmap.proj.Projection
     * @return true
     */
    public boolean generate(Projection proj) {
        Debug.message("eomg", "EditableOMCircle.generate()");
        if (circle != null)
            circle.generate(proj);

        for (int i = 0; i < gPoints.length; i++) {
            GrabPoint gp = gPoints[i];
            if (gp != null) {
                gp.generate(proj);

                // Why is this here???
                // if (gp instanceof OffsetGrabPoint) {
                // ((OffsetGrabPoint)gpo).updateOffsets();
                // }
            }
        }
        return true;
    }

    /**
     * Given a new projection, the grab points may need to be repositioned off
     * the current position of the graphic. Called when the projection changes.
     */
    public void regenerate(Projection proj) {
        Debug.message("eomg", "EditableOMCircle.regenerate()");
        if (circle != null)
            circle.regenerate(proj);

        setGrabPoints(circle);
        generate(proj);
    }

    /**
     * Draw the EditableOMCircle parts into the java.awt.Graphics object. The
     * grab points are only rendered if the circle machine state is
     * CircleSelectedState.CIRCLE_SELECTED.
     *
     * @param graphics java.awt.Graphics.
     */
    public void render(java.awt.Graphics graphics) {
        Debug.message("eomg", "EditableOMCircle.render()");

        State state = getStateMachine().getState();

        // All the rotation stuff isn't ready for primetime, yet.
        // Need to translate the mouse events, too.

        // graphics = graphics.create();
        // double rotationAngle = OMGraphic.DEFAULT_ROTATIONANGLE;

        if (circle != null) {
            circle.setVisible(true);
            circle.render(graphics);
            circle.setVisible(false);

            // rotationAngle = circle.getRotationAngle();
        } else {
            Debug.message("eomg", "EditableOMCircle.render: null circle.");
        }

        int renderType = circle.getRenderType();

        // if (rotationAngle != OMGraphic.DEFAULT_ROTATIONANGLE) {
        // ((java.awt.Graphics2D)graphics).rotate(rotationAngle,
        // circle.getX(), circle.getY());
        // }

        if (state instanceof GraphicSelectedState
                || state instanceof GraphicEditState) {

            for (int i = 0; i < gPoints.length; i++) {
                GrabPoint gp = gPoints[i];
                if (gp != null) {
                    if (i == RADIUS_POINT_INDEX)
                        continue;

                    if (renderType == OMGraphic.RENDERTYPE_LATLON
                            && i != CENTER_POINT_INDEX)
                        continue;

                    if ((i == OFFSET_POINT_INDEX
                            && renderType == OMGraphic.RENDERTYPE_OFFSET && movingPoint == gpo)
                            ||

                            (state instanceof GraphicSelectedState && ((i != OFFSET_POINT_INDEX && renderType != OMGraphic.RENDERTYPE_OFFSET) || (renderType == OMGraphic.RENDERTYPE_OFFSET)))

                    ) {

                        gp.setVisible(true);
                        gp.render(graphics);
                        gp.setVisible(false);
                    }
                }
            }
        }
    }

    /**
     * If this EditableOMGraphic has parameters that can be manipulated that are
     * independent of other EditableOMGraphic types, then you can provide the
     * widgets to control those parameters here. By default, returns the
     * GraphicAttributes GUI widgets. If you don't want a GUI to appear when a
     * widget is being created/edited, then don't call this method from the
     * EditableOMGraphic implementation, and return a null Component from
     * getGUI.
     *
     * @param graphicAttributes the GraphicAttributes to use to get the GUI
     *        widget from to control those parameters for this EOMG.
     * @return java.awt.Component to use to control parameters for this EOMG.
     */
    public java.awt.Component getGUI(GraphicAttributes graphicAttributes) {
        Debug.message("eomg", "EditableOMCircle.getGUI");
        if (graphicAttributes != null) {
            return graphicAttributes.getColorAndLineGUI();
        } else {
            return null;
        }
    }

}
TOP

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

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.