public void enclose(boolean e) { setEnclosed(e); if (polyGrabPoints == null) { return; } OffsetGrabPoint gb0 = (OffsetGrabPoint) polyGrabPoints.get(0); OffsetGrabPoint ogb; if (e) { // If they should be enclosed... if (!syncEnclosed()) { // And they are not already, then add a point, joined // to the beginning. ogb = new OffsetGrabPoint(gb0.getX(), gb0.getY()); // Add the new point to end of the poly addPoint(ogb); syncEnclosed(); repaint(); } // Else nothing to do... } else { // They shouldn't be hooked up, so check to see if they // are, and disconnect if necessary. if (unsyncEnclosed()) { deletePoint(); // Delete attached duplicate point repaint(); } // else nothing to do. } }
/** * This method adds all the GrabPoints associated with the polygon nodes and adds them to the * offset GrabPoint representing the lat/lon anchor point. */ protected void addPolyGrabPointsToOGP(OffsetGrabPoint ogp) { if (ogp == null) return; // Reset the points to the offset point. int count = 0; for (GrabPoint gb : polyGrabPoints) { if (gb != null) { ogp.addGrabPoint(gb); count++; } } ogp.updateOffsets(); }
/** * Generate the grab points, checking the OMGraphic to see if it contains information about what * the grab points should look like. * * @param proj */ protected void generateGrabPoints(Projection proj) { DrawingAttributes grabPointDA = null; Object obj = poly.getAttribute(EditableOMGraphic.GRAB_POINT_DRAWING_ATTRIBUTES_ATTRIBUTE); if (obj instanceof DrawingAttributes) { grabPointDA = (DrawingAttributes) obj; } int index = 0; // Generate all the grab points, but also check to make sure the drawing // attributes are right for (GrabPoint gb : polyGrabPoints) { if (gb != null) { if (selectNodeIndex == index) { Object daobj = poly.getAttribute(EditableOMGraphic.SELECTED_GRAB_POINT_DRAWING_ATTRIBUTES_ATTRIBUTE); if (daobj instanceof DrawingAttributes) { ((DrawingAttributes) daobj).setTo(gb); } } else if (grabPointDA != null) { grabPointDA.setTo(gb); } else { gb.setDefaultDrawingAttributes(GrabPoint.DEFAULT_RADIUS); } gb.generate(proj); } index++; } if (gpo != null) { if (grabPointDA != null) { grabPointDA.setTo(gpo); } else { gpo.setDefaultDrawingAttributes(GrabPoint.DEFAULT_RADIUS); } gpo.generate(proj); gpo.updateOffsets(); } }
/** * Draw the EditableOMPoly parts into the java.awt.Graphics object. The grab points are only * rendered if the poly machine state is PolySelectedState.POLY_SELECTED. * * @param graphics java.awt.Graphics. */ public void render(java.awt.Graphics graphics) { Debug.message("eomg", "EditableOMPoly.render()"); State state = getStateMachine().getState(); if (poly != null && !(state instanceof PolyUndefinedState)) { poly.setVisible(true); poly.render(graphics); poly.setVisible(false); } else { Debug.message("eomg", "EditableOMPoly.render: null or undefined poly."); return; } // Render the points actually on the polygon if (state instanceof GraphicSelectedState || state instanceof PolyAddNodeState || state instanceof PolyDeleteNodeState) { for (GrabPoint gb : polyGrabPoints) { if (gb != null) { gb.setVisible(true); gb.render(graphics); gb.setVisible(false); } } } // In certain conditions, render the offset grab point. if (state instanceof GraphicSelectedState || state instanceof GraphicEditState /* * || * state * instanceof * PolySetOffsetState */) { if (gpo != null && poly.getRenderType() == OMGraphic.RENDERTYPE_OFFSET) { gpo.setVisible(true); gpo.render(graphics); gpo.setVisible(false); } } }
/** * 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(MouseEvent e) { // Need to check to see if the OffsetGrabPoint is currently // being used. If not, just use it, otherwise, will need to // create a special one for the move. Point2D pnt = getProjectionPoint(e); int x = (int) pnt.getX(); int y = (int) pnt.getY(); if (poly.getRenderType() == OMGraphic.RENDERTYPE_OFFSET) { gpm = new OffsetGrabPoint(x, y); gpm.clear(); } else { gpm = gpo; gpm.clear(); gpm.set(x, y); } // Move all the other points along with the offset point... addPolyGrabPointsToOGP(gpm); movingPoint = gpm; }
/** * Method disconnects the last point from the first point. Make sure they are both * OffsetGrabPoints. */ protected boolean unsyncEnclosed() { try { OffsetGrabPoint gb0 = (OffsetGrabPoint) polyGrabPoints.get(0); OffsetGrabPoint ogb = (OffsetGrabPoint) polyGrabPoints.get(polyGrabPoints.size() - 1); // disconnect them... if (gb0.getX() == ogb.getX() && gb0.getY() == ogb.getY()) { gb0.removeGrabPoint(ogb); ogb.removeGrabPoint(gb0); return true; } } catch (ClassCastException cce) { } catch (ArrayIndexOutOfBoundsException aioobe) { } return false; }
/** * Method connects the last point to the first point. Make sure they are both OffsetGrabPoints. * Return true if the points cover the same pixel and if they were successfully joined. */ protected boolean syncEnclosed() { try { OffsetGrabPoint gb0 = (OffsetGrabPoint) polyGrabPoints.get(0); OffsetGrabPoint ogb = (OffsetGrabPoint) polyGrabPoints.get(polyGrabPoints.size() - 1); // Check to see if they are over the same point. if (gb0.getX() == ogb.getX() && gb0.getY() == ogb.getY()) { // Cross connect them... gb0.addGrabPoint(ogb); ogb.addGrabPoint(gb0); return true; } } catch (ClassCastException cce) { } catch (IndexOutOfBoundsException ioobe) { } return false; }
/** * Given a MouseEvent, check the source, and if it's a MapBean, then grab the projection and * java.awt.Graphics from it to use for generation and rendering of the EditableOMGraphic objects. * * @param e MouseEvent * @param firmPaint true if the graphic is being rendered at rest, with fill colors and true * colors, with the grab point if the state allows it. If false, then the fill color will not * be used, and just the graphic will be drawn. Use false for graphics that are moving. */ public void redraw(MouseEvent e, boolean firmPaint, boolean drawXOR) { if (DEBUG) { Debug.output("EditableOMGraphic.redraw(" + (firmPaint ? "firmPaint)" : ")")); } if (e == null) { if (lastMouseEvent == null) { return; } e = lastMouseEvent; } Object obj = e.getSource(); if (!(obj instanceof MapBean)) { return; } MapBean map = (MapBean) obj; Graphics g = map.getGraphics(); OMGraphic graphic = getGraphic(); if (firmPaint) { // So, with a firm paint, we want to clean the screen. If // the map is being buffered, we need to clean out the // buffer, which is why we set the Request paint to true, // to get the image rebuilt. Otherwise, a copy of the // graphic remains. map.setBufferDirty(true); graphic.generate(getProjection()); map.repaint(); } else { // If we get here, we are painting a moving object, so we // only want to do the outline to make it as fast as // possible. holder.setFrom(graphic); DrawingAttributes.DEFAULT.setTo(graphic); modifyOMGraphicForEditRender(); graphic.regenerate(getProjection()); if (drawXOR) { g.setXORMode(Color.lightGray); g.setColor((Color) graphic.getDisplayPaint()); render(g); } GrabPoint gp = getMovingPoint(); if (gp != null) { gp.set(e.getX(), e.getY()); if (gp instanceof OffsetGrabPoint) { ((OffsetGrabPoint) gp).moveOffsets(); } setGrabPoints(); } } if (!firmPaint) { generate(getProjection()); render(g); holder.setTo(graphic); } resetOMGraphicAfterEditRender(); g.dispose(); lastMouseEvent = e; }
/** * Delete a point at a certain point in the polygon coordinate list. If the position is less than * zero, the deleted point will be the starting point. If the position is greater than the list of * current points, the point will be deleted from the end of the poly. */ public void deletePoint(int position) { int renderType = poly.getRenderType(); boolean needToHookUp = false; if (position <= 0 && isEnclosed()) { // if the position is 0 and the polygon is enclosed, we // need to disengage the two points, then reattach. enclose(false); needToHookUp = true; } if (renderType == OMGraphic.RENDERTYPE_LATLON) { Debug.message("eomg", "EditableOMPoly: removing point from lat/lon poly"); if (projection != null) { double[] ll = poly.getLatLonArray(); double[] newll = new double[ll.length - 2]; int actualPosition = (position == Integer.MAX_VALUE ? ll.length : position * 2); if (actualPosition >= ll.length) { // Pull the new points off the end System.arraycopy(ll, 0, newll, 0, ll.length - 2); position = (ll.length - 2) / 2; } else if (actualPosition <= 0) { // Pull the new points off the beginning System.arraycopy(ll, 2, newll, 0, ll.length - 2); position = 0; } else { // actualPosition because there are 2 floats for // every // position. System.arraycopy(ll, 0, newll, 0, actualPosition); System.arraycopy( ll, actualPosition + 2, newll, actualPosition, ll.length - actualPosition - 2); } poly.setLocation((double[]) newll, poly.getUnits()); } } else { // Grab the projected endpoints Debug.message("eomg", "EditableOMPoly: removing point from x/y or offset poly"); int currentLength = poly.xs.length; int[] newxs = new int[currentLength - 1]; int[] newys = new int[currentLength - 1]; if (position >= currentLength) { // Pull the points from the end... System.arraycopy(poly.xs, 0, newxs, 0, currentLength - 1); System.arraycopy(poly.ys, 0, newys, 0, currentLength - 1); position = currentLength - 1; } else if (position <= 0) { // Pull the points from the beginning... System.arraycopy(poly.xs, 1, newxs, 0, currentLength - 1); System.arraycopy(poly.ys, 1, newys, 0, currentLength - 1); position = 0; } else { System.arraycopy(poly.xs, 0, newxs, 0, position); System.arraycopy(poly.xs, position + 1, newxs, position, currentLength - position - 1); System.arraycopy(poly.ys, 0, newys, 0, position); System.arraycopy(poly.ys, position + 1, newys, position, currentLength - position - 1); } if (poly.getRenderType() == OMGraphic.RENDERTYPE_OFFSET) { poly.setLocation(poly.lat, poly.lon, poly.getUnits(), newxs, newys); } else { poly.setLocation(newxs, newys); } } if (projection != null) { poly.regenerate(projection); } // Remove the GrabPoint for the deleted spot. GrabPoint gp = (GrabPoint) polyGrabPoints.remove(position); if (gpo != null && gp != null) { gpo.removeGrabPoint(gp); } if (needToHookUp) { enclose(true); } }
/** * Add a point at a certain point in the polygon coordinate list. If the position is less than * zero, the point will be the starting point. If the position is greater than the list of current * points, the point will be added to the end of the poly. This method is convenient because it * lets you define the GrabPoint object to use for the node, in case you need a special type of * GrabPoint. * * @return the index for the point in the polygon, starting with 0. */ public int addPoint(GrabPoint gp, int position) { if (gp == null) { return -1; } int x = gp.getX(); int y = gp.getY(); int renderType = poly.getRenderType(); boolean rads = (poly.getUnits() == OMGraphic.RADIANS); if (renderType == OMGraphic.RENDERTYPE_LATLON) { Debug.message("eomg", "EditableOMPoly: adding point to lat/lon poly"); if (projection != null) { double[] ll = poly.getLatLonArray(); int actualPosition = (position == Integer.MAX_VALUE ? ll.length : position * 2); LatLonPoint llpnt = projection.inverse(x, y, new LatLonPoint.Double()); if (Debug.debugging("eomp")) { Debug.output( "EditableOMPoly: adding point to lat/lon poly at " + x + ", " + y + ": " + llpnt + ", at the end of "); for (int j = 0; j < ll.length; j += 2) { Debug.output(ll[j] + ", " + ll[j + 1]); } } double[] newll = new double[ll.length + 2]; double newlat; double newlon; if (rads) { newlat = llpnt.getRadLat(); newlon = llpnt.getRadLon(); } else { newlat = llpnt.getY(); newlon = llpnt.getX(); } if (actualPosition >= ll.length) { // Put the new points at the end if (ll.length != 0) { System.arraycopy(ll, 0, newll, 0, ll.length); } newll[ll.length] = newlat; newll[ll.length + 1] = newlon; position = ll.length / 2; } else if (actualPosition <= 0) { // Put the new point at the beginning System.arraycopy(ll, 0, newll, 2, ll.length); newll[0] = newlat; newll[1] = newlon; position = 0; } else { // actualPosition because there are 2 floats for // every // position. newll[actualPosition] = newlat; newll[actualPosition + 1] = newlon; System.arraycopy(ll, 0, newll, 0, actualPosition); System.arraycopy( ll, actualPosition, newll, actualPosition + 2, ll.length - actualPosition); } poly.setLocation((double[]) newll, poly.getUnits()); } } else if (renderType == OMGraphic.RENDERTYPE_XY) { // Grab the projected endpoints Debug.message("eomg", "EditableOMPoly: adding point to x/y poly"); int currentLength = poly.xs.length; int[] newxs = new int[currentLength + 1]; int[] newys = new int[currentLength + 1]; if (position >= currentLength) { // Put the new points at the end System.arraycopy(poly.xs, 0, newxs, 0, currentLength); System.arraycopy(poly.ys, 0, newys, 0, currentLength); newxs[currentLength] = x; newys[currentLength] = y; position = currentLength; } else if (position <= 0) { // Put the new points at the beginning System.arraycopy(poly.xs, 0, newxs, 1, currentLength); System.arraycopy(poly.ys, 0, newys, 1, currentLength); newxs[0] = x; newys[0] = y; position = 0; } else { newxs[position] = x; newys[position] = y; System.arraycopy(poly.xs, 0, newxs, 0, position); System.arraycopy(poly.xs, position, newxs, position + 1, currentLength - position); System.arraycopy(poly.ys, 0, newys, 0, position); System.arraycopy(poly.ys, position, newys, position + 1, currentLength - position); } poly.setLocation(newxs, newys); } else { // Rendertype is offset... // Grab the projected endpoints Debug.message("eomg", "EditableOMPoly: adding point to offset poly"); int currentLength = poly.xs.length; int[] newxs = new int[currentLength + 1]; int[] newys = new int[currentLength + 1]; if (position >= currentLength) { // Put the new points at the end position = currentLength; System.arraycopy(poly.xs, 0, newxs, 0, currentLength); System.arraycopy(poly.ys, 0, newys, 0, currentLength); } else if (position <= 0) { // Put the new points at the beginning position = 0; System.arraycopy(poly.xs, 0, newxs, 1, currentLength); System.arraycopy(poly.ys, 0, newys, 1, currentLength); } else { System.arraycopy(poly.xs, 0, newxs, 0, position); System.arraycopy(poly.xs, position, newxs, position + 1, currentLength - position); System.arraycopy(poly.ys, 0, newys, 0, position); System.arraycopy(poly.ys, position, newys, position + 1, currentLength - position); } int offsetX; int offsetY; if (gpo.getX() == -1 && gpo.getY() == -1) { offsetX = projection.getWidth() / 2; offsetY = projection.getHeight() / 2; } else { offsetX = gpo.getX(); offsetY = gpo.getY(); } if (poly.coordMode == OMPoly.COORDMODE_ORIGIN || position == 0) { // cover // the // first // point newxs[position] = x - offsetX; newys[position] = y - offsetY; } else { // CMode Previous offset deltas newxs[position] = x - offsetX - newxs[position - 1]; newys[position] = y - offsetY - newys[position - 1]; } if (position == 0) { // Could call projection.getCenter() but that might // break if/when we make other projection // libraries/paradigms active. LatLonPoint llpnt = projection.inverse(offsetX, offsetY, new LatLonPoint.Double()); if (rads) { poly.lat = llpnt.getRadLat(); poly.lon = llpnt.getRadLon(); } else { poly.lat = llpnt.getY(); poly.lon = llpnt.getX(); } } poly.setLocation(poly.lat, poly.lon, poly.getUnits(), newxs, newys); } // Need to reset the arrowhead when an end point is added, // removing it from the shape when the point gets added. // Otherwise, you end up with a arrowhead at each junction of // the polygon. OMArrowHead omah = poly.getArrowHead(); poly.setArrowHead(null); // Reset the arrowhead so it will get drawn on the new // segment. poly.setArrowHead(omah); polyGrabPoints.add(position, gp); if (gpo != null) { gpo.addGrabPoint(gp); } // This is the standard call that needs to be made here, the // arrowhead changes are around this. poly.regenerate(projection); gp.generate(projection); return position; }
/** * Take the current location of the GrabPoints, and modify the location parameters of the OMPoly * with them. Called when you want the graphic to change according to the grab points. */ public void setGrabPoints() { int i; GrabPoint gb; // just to use a temp marker LatLonPoint llp = new LatLonPoint.Double(); int renderType = poly.getRenderType(); if (renderType == OMGraphic.RENDERTYPE_LATLON) { if (projection != null) { double[] radCoords = new double[polyGrabPoints.size() * 2]; // OK, this code resets the location of every point slightly to // the inverse location of the grab points. So if you grab one // node and move it, all of the precise values of each node // actually changes. As we go through the array of grab points, // we can check the corresponding projected location of the // current node and it matches the grab point, just use the // current poly value. double[] currentCoords = poly.getLatLonArray(); Point2D testPoint = new Point2D.Double(); for (i = 0; i < polyGrabPoints.size(); i++) { gb = (GrabPoint) polyGrabPoints.get(i); boolean useGrabPointLocation = true; try { double radLat = currentCoords[i * 2]; double lat = Math.toDegrees(radLat); double radLon = currentCoords[i * 2 + 1]; double lon = Math.toDegrees(radLon); testPoint = projection.forward(lat, lon, testPoint); if (testPoint.getX() == gb.getX() && testPoint.getY() == gb.getY()) { // The projected location of the current node is the // same as the grab point, use that location. radCoords[2 * i] = radLat; radCoords[2 * i + 1] = radLon; useGrabPointLocation = false; } } catch (Exception e) { // If anything goes wrong, don't worry about it, just // use the // projected inverse of grab point } if (useGrabPointLocation) { projection.inverse(gb.getX(), gb.getY(), llp); radCoords[2 * i] = llp.getRadLat(); radCoords[2 * i + 1] = llp.getRadLon(); } } poly.setLocation(radCoords, OMGraphic.RADIANS); } else { Debug.message( "eomg", "EditableOMPoly.setGrabPoints: projection is null, can't figure out LATLON points for poly."); } } else if (renderType == OMGraphic.RENDERTYPE_OFFSET) { // Do the offset point. if (projection != null) { projection.inverse(gpo.getX(), gpo.getY(), llp); } else { Debug.message( "eomg", "EditableOMPoly.setGrabPoints: projection is null, can't figure out LATLON points for poly offset."); } } if (renderType == OMGraphic.RENDERTYPE_XY || renderType == OMGraphic.RENDERTYPE_OFFSET) { int[] ints = new int[polyGrabPoints.size() * 2]; if (renderType == OMGraphic.RENDERTYPE_OFFSET && gpo != null) { // If offset rendertype, the x-y have to be offset // distances, not screen pixel locations. For the // polygon, you also need to take into account that // the ints can represent 2 different things: distance // from the origin (Offset) or distance from the // previous point. Need to check with the poly to // find out which to do. GrabPoint previous = gpo; for (i = 0; i < polyGrabPoints.size(); i++) { gb = (GrabPoint) polyGrabPoints.get(i); if (poly.coordMode == OMPoly.COORDMODE_PREVIOUS) { ints[2 * i] = gb.getX() - previous.getX(); ints[2 * i + 1] = gb.getY() - previous.getY(); previous = gb; } else { ints[2 * i] = gb.getX() - gpo.getX(); ints[2 * i + 1] = gb.getY() - gpo.getY(); } } double newlat = llp.getRadLat(); double newlon = llp.getRadLon(); poly.setLocation(newlat, newlon, OMGraphic.RADIANS, ints); } else { for (i = 0; i < polyGrabPoints.size(); i++) { gb = (GrabPoint) polyGrabPoints.get(i); ints[2 * i] = gb.getX(); ints[2 * i + 1] = gb.getY(); } poly.setLocation(ints); } } }
/** * 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 points of the graphic. */ public void setGrabPoints(OMGraphic graphic) { if (!(graphic instanceof OMPoly)) { return; } assertGrabPoints(); polyGrabPoints.clear(); arrayCleared = true; gpo.clear(); OMPoly poly = (OMPoly) graphic; boolean ntr = poly.getNeedToRegenerate(); int renderType = poly.getRenderType(); Point p = new Point(); GrabPoint gb; int i; int npts; boolean geoProj = projection instanceof GeoProj; if (ntr == false) { if (renderType == OMGraphic.RENDERTYPE_LATLON) { Debug.message("eomg", "EditableOMPoly: modifying lat/lon line"); if (projection != null) { double[] ll = poly.getLatLonArray(); boolean rads = poly.getUnits() == OMGraphic.RADIANS; gb = null; // reset for this loop for (i = 0; i < ll.length; i += 2) { if (geoProj) { ((GeoProj) projection).forward(ll[i], ll[i + 1], p, rads); } else { projection.forward(ll[i], ll[i + 1], p); } // Need to add a grab point for this // coordinate gb = new OffsetGrabPoint((int) p.getX(), (int) p.getY()); polyGrabPoints.add(gb); } } } else if (renderType == OMGraphic.RENDERTYPE_OFFSET) { // Grab the projected endpoints Debug.message("eomg", "EditableOMPoly: modifying offset poly"); int x; int y; npts = poly.xs.length; // Check to see if the poly is a offset poly, and set // the // offset grab point accordingly. if (projection != null) { if (geoProj) { ((GeoProj) projection).forward(poly.lat, poly.lon, p, true); } else { projection.forward(poly.lat, poly.lon, p); } gpo.set((int) p.getX(), (int) p.getY()); if (poly.coordMode == OMPoly.COORDMODE_ORIGIN) { for (i = 0; i < npts; i++) { x = (int) (poly.xs[i] + p.getX()); y = (int) (poly.ys[i] + p.getY()); gb = new OffsetGrabPoint(x, y); polyGrabPoints.add(gb); } } else { // CMode Previous offset deltas int lastX = (int) p.getX(); int lastY = (int) p.getY(); for (i = 0; i < npts; i++) { x = poly.xs[i] + lastX; y = poly.ys[i] + lastY; gb = new OffsetGrabPoint(x, y); polyGrabPoints.add(gb); lastX += x; lastY += y; } } } } else { npts = poly.xs.length; Debug.message("eomg", "EditableOMPoly: modifying x/y poly"); for (i = 0; i < npts; i++) { gb = new OffsetGrabPoint(poly.xs[i], poly.ys[i]); polyGrabPoints.add(gb); } } // Add the || to maintain manualEnclosed if it was // externally set before the OMPoly is actually defined, // indicating that the user wants to draw a polygon. setEnclosed(syncEnclosed() || isEnclosed()); addPolyGrabPointsToOGP(gpo); } else { Debug.message("eomg", "EditableOMPoly.setGrabPoints: graphic needs to be regenerated "); } }
/** * 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); }
/** * 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); }