📄 location.java
字号:
/** Get the name of the location. */ public String getName() { return name; } /** * Set the name of this location. */ public void setName(String name) { this.name = name; if (label != null) { label.setData(name); } } /** * Set the details for the location. This should be the contents * to be displayed in a web browser. */ public void setDetails(String det) { details = det; } /** * Get the details for the location. */ public String getDetails() { return details; } /** * Fire a browser to display the location details. */ public void showDetails(Layer layer) { if (details != null) layer.fireRequestBrowserContent(details); } /** * Set whether you want to allow the label for this location to be * decluttered. * * @param allow if true, label will be decluttered if declutter * matrix is available. */ public void setAllowDecluttering(boolean allow) { allowDecluttering = allow; } /** * Get the decluttering allowance setting for this label. */ public boolean isAllowDecluttering() { return allowDecluttering; } /** * Set the pixel distance that the label will be moved to the * right, to clear space for the graphic marking the location. */ public void setHorizontalLabelBuffer(int buffer) { horizontalLabelBuffer = buffer; } /** * Get the pixel distance that the label will be moved to the * right, to clear space for the graphic marking the location. */ public int getHorizontalLabelBuffer() { return horizontalLabelBuffer; } //////////////////////////////////////////////////// /////////// OMGraphic methods //////////////////// //////////////////////////////////////////////////// /** * Generate the location, and use the declutter matrix to place * the label is a spot so that it doesn't interset with other * labels. * * @param proj projection of the map. * @param declutterMatrix DeclutterMatrix for the map. */ public boolean generate(Projection proj, DeclutterMatrix declutterMatrix) { // Call generate(proj) first, to get the original position // set. Then, declutter the text. boolean ret = generate(proj); if (declutterMatrix != null && label != null && allowDecluttering) { declutterLabel(declutterMatrix, proj); } return ret; } /** * Set the pixel distance that us used by the declutter matrix in * trying to find a place for the label. If it can't find a place * within this pixel limit, it woun't draw it. */ public void setDeclutterLimit(int value) { if (value < 0 && value != DECLUTTER_LOCALLY) { declutterLimit = DECLUTTER_ANYWHERE; } else { declutterLimit = value; } } /** * Get the declutter pixel distance limit. */ public int getDeclutterLimit() { return declutterLimit; } protected int currentFontDescent = 0; /** * Prepare the graphic for rendering. This must be done before * calling <code>render()</code>! If a vector graphic has * lat-lon components, then we project these vertices into x-y * space. For raster graphics we prepare in a different fashion. * <p> * If the generate is unsuccessful, it's usually because of some * oversight, (for instance if <code>proj</code> is null), and * if debugging is enabled, a message may be output to the * controlling terminal. * <p> * * @param proj Projection * @return boolean true if successful, false if not. */ public boolean generate(Projection proj) { if (label != null) { label.setY(origYLabelOffset); label.setX(origXLabelOffset); } java.awt.Graphics g = DeclutterMatrix.getGraphics(); if (g != null && label != null) { g.setFont(label.getFont()); // Now set the vertical offset to the original place based // off the height of the label, so that the location place // is halfway up the text. That way, it looks like a // label. int height = g.getFontMetrics().getAscent(); currentFontDescent = g.getFontMetrics().getDescent(); label.setX(label.getX() + horizontalLabelBuffer); label.setY(label.getY() + (height / 2) - 2); } if (label != null) { label.generate(proj); label.prepareForRender(g); } if (location != null) location.generate(proj); return true; } /** * Paint the graphic and the name of the location. This should * only be used if the locations are pretty spread out from each * other. If you think you need to declutter, you should render * all the graphics, and then render the names, so that the * graphics don't cover up the names. * <P> * This paints the graphic into the Graphics context. This is * similar to <code>paint()</code> function of * java.awt.Components. Note that if the graphic has not been * generated, it will not be rendered. This render will take into * account the layer showNames and showLocations settings. * * @param g Graphics context to render into. */ public void render(Graphics g) { renderLocation(g); renderName(g); } /** * Paint the graphic label (name) only. This paints the graphic * into the Graphics context. This is similar to * <code>paint()</code> function of java.awt.Components. Note * that if the graphic has not been generated, it will not be * rendered. This render will take into account the layer * showNames and showLocations settings. * * @param g Graphics context to render into. */ public void renderName(Graphics g) { if (shouldRenderName()) { label.render(g); } } /** * Paint the graphic location graphic only. This paints the * graphic into the Graphics context. This is similar to * <code>paint()</code> function of java.awt.Components. Note * that if the graphic has not been generated, it will not be * rendered. This render will take into account the layer * showNames and showLocations settings. * * @param g Graphics context to render into. */ public void renderLocation(Graphics g) { if (shouldRenderLocation()) { location.render(g); } } /** * Convenience method to see if handler/global settings dictate * that the location label should be rendered. * * @return true if the name label should be rendered. */ protected boolean shouldRenderName() { boolean globalShowNames = false; boolean forceGlobal = false; if (handler != null) { globalShowNames = handler.isShowNames(); forceGlobal = handler.isForceGlobal(); } return label != null && ((forceGlobal && globalShowNames) || (!forceGlobal && showName)); } /** * Convenience method to see if handler/global settings dictate * that the location icon should be rendered. * * @return true of the location marker should be rendered. */ protected boolean shouldRenderLocation() { boolean globalShowLocations = false; boolean forceGlobal = false; if (handler != null) { globalShowLocations = handler.isShowLocations(); forceGlobal = handler.isForceGlobal(); } return location != null && ((forceGlobal && globalShowLocations) || (!forceGlobal && showLocation)); } /** * Return the shortest distance from the graphic to an XY-point. * * @param x X coordinate of the point. * @param y Y coordinate of the point. * @return float distance from graphic to the point */ public float distance(int x, int y) { float labelDist = Float.MAX_VALUE; float locationDist = Float.MAX_VALUE; if (shouldRenderLocation()) { locationDist = location.distance(x, y); } if (shouldRenderName()) { labelDist = label.distance(x, y); } return (locationDist > labelDist ? labelDist : locationDist); } /** * Given the label is this location has a height and width, find a * clean place on the map for it. Assumes label is not null. * * @param declutter the DeclutterMatrix for the map. */ protected void declutterLabel(DeclutterMatrix declutter, Projection proj) { if (Debug.debugging("locationdetail")) { Debug.output("\nLocation::RepositionText => " + label.getData()); } // Right now, I think this method takes some presumptutous // actions, assuming that you want the graphics to take up // space in the declutter mattrix. We might want to delete // this showLocation code, and let people create their own // location subclasses that define how the graphic should be // handled in the declutter matrix. // I think I will. This stuff is commented out for the // reasons stated above. // if (isShowLocation()) { // Point lp; // // Take up space with the label // if (location instanceof OMRasterObject) { // lp = ((OMRasterObject)location).getMapLocation(); // // This location is the upper left location of the // // declutter matrix. The decutter matrix works from // // lower left to upper right. // if (lp != null) { // int locHeight = ((OMRasterObject)location).getHeight(); // int locWidth = ((OMRasterObject)location).getWidth(); // // Need to get this right for the DeclutterMatrix // // space, but changing lp changes where the // // location will appear - fix this later. // lp.y += locHeight; // declutter.setTaken(lp, locWidth, locHeight); // // Reset it to the original projected location. // lp.y -= locHeight; // } // } else if (renderType != RENDERTYPE_XY) { // lp = proj.forward(lat,lon); // lp.x += xOffset-1; // lp.y += yOffset-1; // declutter.setTaken(lp, 3, 3); // } else { // lp = new Point(x-1, y-1); // declutter.setTaken(lp, 3, 3); // } // } if (isShowName() || (handler != null && handler.isShowNames())) { if (label == null || label.getPolyBounds() == null) { // Why bother going further?? return; } Rectangle bounds = label.getPolyBounds().getBounds(); int height = (int) ((float) (bounds.getHeight() - currentFontDescent / 2)); int width = (int) bounds.getWidth(); // Projected location of label on the screen Point p = label.getMapLocation(); if (Debug.debugging("locationdetail")) { Debug.output("old point X Y =>" + p.x + " " + p.y + " height = " + height + " width = " + width); } int limit; if (declutterLimit == DECLUTTER_LOCALLY) { limit = height * 2; } else { limit = declutterLimit; } // newpoint is the new place on the map to put the label Point newpoint = declutter.setNextOpen(p, width, height, limit); if (Debug.debugging("locationdetail")) { Debug.output("new point X Y =>" + newpoint.x + " " + newpoint.y); } label.setMapLocation(newpoint); } } /** * A simple conversion method for the common String represention * of decimal degree coordinates, which is a letter denoting the * globle hemisphere (N or S for latitudes, W or E for longitudes, * and then a number string. For latitudes, the first two numbers * represent the whole degree value, and the rest of the numbers * represent the fractional protion. For longitudes, the first * three numbers represent the whole degree value. For instance * N2443243 equals 24.43243 degrees North, and S2443243 results in * -24.43243 degrees. Likewise, w12423443 results in -124.23443 * degrees. * * @param coord the coordinate string representing the decimal * degree value, following the format [NSEW]XXXXXXXXX. * @return the decimal degrees for the string. There is no * notation for you to know whether it's a latitude or * longitude value. */ public static float convertCoordinateString(String coord) throws NumberFormatException { float ret = 0f; String mantissa; char direction = coord.charAt(0); if (direction == 'N' || direction == 'S' || direction == 'n' || direction == 's') { float whole = new Float(coord.substring(1, 3)).floatValue(); ret += whole; mantissa = coord.substring(3); } else if (direction == 'W' || direction == 'E' || direction == 'w' || direction == 'e') { ret += new Float(coord.substring(1, 4)).floatValue(); mantissa = coord.substring(4); } else { // Don't know the format!! throw new NumberFormatException("Location.convertCoordinateString wants <[NSWE]XXXXXXXX>, not getting it."); } ret += new Float(mantissa).floatValue() / (float) (Math.pow(10, mantissa.length())); if (direction == 'W' || direction == 'S' || direction == 'w' || direction == 's') { ret *= -1f; } return ret; } /** * We're using the main function for Location to test the * convertCoordinateString function. */ public static void main(String[] args) { if (args.length < 1) { Debug.output(" usage: java com.bbn.openmap.layer.location.Location <[NSWE]XXXXXXXX>"); return; } float ret = Location.convertCoordinateString(args[0]); System.out.println(ret); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -