📄 omarc.java
字号:
return; off_x = value; setNeedToRegenerate(true); } /** * Set the y offset from the center. This will be meaningful only * if the render type is RENDERTYPE_OFFSET. * * @param value the y position of center. */ public void setOffY(int value) { if (off_y == value) return; off_y = value; setNeedToRegenerate(true); } /** * Set the latitude and longitude of the center point. This is * meaningful only if the rendertype is RENDERTYPE_LATLON or * RENDERTYPE_OFFSET. * * @param lat latitude in decimal degrees * @param lon longitude in decimal degrees */ public void setLatLon(float lat, float lon) { setCenter(new LatLonPoint(lat, lon)); } /** * Set the latitude and longitude of the center point. This is * meaningful only if the rendertype is RENDERTYPE_LATLON or * RENDERTYPE_OFFSET. * * @param p LatLonPoint of center. */ public void setCenter(LatLonPoint p) { if (p.equals(center)) return; center = p; setNeedToRegenerate(true); } /** * Get the center LatLonPoint. */ public LatLonPoint getCenter() { return center; } /** * Set the radius. This is meaningful only if the render type is * RENDERTYPE_LATLON. Note that while the radius is specified as * decimal degrees, it only means the distance along the ground * that that number of degrees represents at the equator, *NOT* a * radius of a number of degrees around a certain location. There * is a difference. * * @param radius float radius in decimal degrees */ public void setRadius(float radius) { this.radius = Length.DECIMAL_DEGREE.toRadians(radius); setNeedToRegenerate(true); } /** * Set the radius with units. This is meaningful only if the * render type is RENDERTYPE_LATLON. * * @param radius float radius * @param units Length specifying unit type. */ public void setRadius(float radius, Length units) { this.radius = units.toRadians(radius); setNeedToRegenerate(true); } /** * Set the horizontal pixel diameter of the arc. This is * meaningful only if the render type is RENDERTYPE_XY or * RENDERTYPE_OFFSET. * * @param value the horizontial pixel diamter of the arc. */ public void setWidth(int value) { if (width == value) return; width = value; setNeedToRegenerate(true); } /** * Set the vertical pixel diameter of the arc. This is meaningful * only if the render type is RENDERTYPE_XY or RENDERTYPE_OFFSET. * * @param value the vertical pixel diameter of the arc. */ public void setHeight(int value) { if (height == value) return; height = value; setNeedToRegenerate(true); } /** * Set the starting angle the arc. * * @param value the starting angle of the arc in decimal degrees. */ public void setStart(float value) { if (start == value) return; start = value; setNeedToRegenerate(true); } /** * Set the angular extent of the arc. * * @param value the angular extent of the arc in decimal degrees. * For LATLON rendertype arcs, positive extents go in the * clockwise direction, matching the OpenMap convention in * coordinate space. For XY and OFFSET rendertype arcs, * positive extents go in the clockwise direction, matching * the java.awt.geom.Arc2D convention. */ public void setExtent(float value) { if (extent == value) return; extent = value; setNeedToRegenerate(true); } /** * Set the number of vertices of the lat/lon arc. This is * meaningful only if the render type is RENDERTYPE_LATLON and for * LINETYPE_GREATARC or LINETYPE_RHUMB line types. If < 1, this * value is generated internally. * * @param nverts number of segment points */ public void setNumVerts(int nverts) { this.nverts = nverts; } /** * Set the ArcType, either Arc2D.OPEN (default), Arc2D.PIE or * Arc2D.CHORD. * * @see java.awt.geom.Arc2D */ public void setArcType(int type) { if (type == Arc2D.PIE || type == Arc2D.CHORD) { arcType = type; } else { arcType = Arc2D.OPEN; } } /** * Get the ArcType. * * @see java.awt.geom.Arc2D */ public int getArcType() { return arcType; } /** * Set the angle by which the arc is to rotated. * * @param angle the number of radians the arc is to be rotated. * Measured clockwise from horizontal. Positive numbers * move the positive x axis toward the positive y axis. */ public void setRotationAngle(double angle) { this.rotationAngle = angle; setNeedToRegenerate(true); } /** * Get the current rotation of the arc. * * @return the arc rotation. */ public double getRotationAngle() { return rotationAngle; } public void setNeedToRegenerate(boolean value) { super.setNeedToRegenerate(value); if (value) { polarShapeLine = null; correctFill = false; } } /** * Get the polar-fill-correction-flag. * * @return boolean * @see #setPolarCorrection */ public boolean getPolarCorrection() { return correctPolar; } /** * Set the polar-fill-correction-flag. We don't correctly render * *filled* arcs/polygons which encompass a pole in Cylindrical * projections. This method will toggle support for correcting * this problem. You should only set this on arcs that encompass a * pole and are drawn with a fill color. You do not need to set * this if you're only drawing the arc outline. * * @param value boolean * @see OMGraphic#setLineColor * @see OMGraphic#setFillColor */ public void setPolarCorrection(boolean value) { correctPolar = value; setNeedToRegenerate(true); } /** * Helper function that helps the generate method figure out if * the center point should be in the generate shape - if it's not, * the code knows that there is a problem with the poles, and the * polar correction code needs to be run. */ protected boolean shouldCenterBeInShape() { // It won't be for CHORD or OPEN arcs return arcType == Arc2D.PIE; } /** * Prepare the arc for rendering. * * @param proj Projection * @return true if generate was successful */ public boolean generate(Projection proj) { setShape(null); polarShapeLine = null; correctFill = false; if (proj == null) { Debug.message("omgraphic", "OMArc: null projection in generate!"); return false; } GeneralPath gp, gp1, gp2; PathIterator pi; AffineTransform af = null; switch (renderType) { case RENDERTYPE_OFFSET: if (!proj.isPlotable(center)) { setNeedToRegenerate(true);//HMMM not the best flag return false; } Point p1 = proj.forward(center.radlat_, center.radlon_, new Point(), true); x1 = p1.x + off_x; y1 = p1.y + off_y; case RENDERTYPE_XY: float fwidth = (float) width; float fheight = (float) height; float transx = (float) x1; float transy = (float) y1; float x = transx - fwidth / 2f; float y = transy - fheight / 2f; Shape arcShape = createArcShape(x, y, fwidth, fheight); if (rotationAngle != DEFAULT_ROTATIONANGLE) { af = new AffineTransform(); af.rotate(rotationAngle, transx, transy); } pi = arcShape.getPathIterator(af); gp = new GeneralPath(); gp.append(pi, false); // In X/Y or Offset RenderType, there is only one shape. setShape(gp); break; case RENDERTYPE_LATLON: ArrayList coordLists = getCoordLists(proj, center, radius, nverts); Point p = proj.forward(center.radlat_, center.radlon_, new Point(), true); x1 = p.x; y1 = p.y; int size = coordLists.size(); GeneralPath tempShape = null; for (int i = 0; i < size; i += 2) { int[] xpoints = (int[]) coordLists.get(i); int[] ypoints = (int[]) coordLists.get(i + 1); gp = createShape(xpoints, ypoints, (arcType != Arc2D.OPEN || (arcType == Arc2D.OPEN && !isClear(fillPaint)))); if (shape == null) { setShape(gp); } else { ((GeneralPath) shape).append(gp, false); } correctFill = proj instanceof Cylindrical && ((shouldCenterBeInShape() && !shape.contains(x1, y1)) || correctPolar); if (correctFill) { int[][] alts = doPolarFillCorrection(xpoints, ypoints, (center.radlat_ > 0f) ? -1 : proj.getWidth() + 1); int gp2length = alts[0].length - 2; gp1 = createShape(alts[0], alts[1], true); gp2 = createShape(alts[0], alts[1], 0, gp2length, false); if (tempShape == null || polarShapeLine == null) { tempShape = gp1; polarShapeLine = gp2; } else { tempShape.append(gp1, false); polarShapeLine.append(gp2, false); } } } if (tempShape != null) { setShape(tempShape); } break; case RENDERTYPE_UNKNOWN: System.err.println("OMArc.generate(): invalid RenderType"); return false; } setNeedToRegenerate(false); return true; } /** * An internal method designed to fetch the Shape to be used for * an XY or OFFSET OMArc. This method is smart enough to take the * calculated position information and make a call to Arc2D.Float * with start, extent and arcType information. */ protected Shape createArcShape(float x, float y, float fwidth, float fheight) { return new Arc2D.Float(x, y, fwidth, fheight, start, extent, arcType); } /** * An internal method designed to fetch the ArrayList for LATLON * OMArcs. This method is smart enough to take the calculated * position information and make a call to Projection.forwardArc() * with start, extent and arcType information. */ protected ArrayList getCoordLists(Projection proj, LatLonPoint center, float radius, int nverts) { int at = (arcType == Arc2D.OPEN && !isClear(fillPaint) ? Arc2D.CHORD : arcType); return proj.forwardArc(center, /* radians */ true, radius, nverts, ProjMath.degToRad(start), ProjMath.degToRad(extent), at); } /** * Return the java.awt.Shape (GeneralPath) that reflects a arc * that encompases a pole. Used when the projection is * Cylindrical. * * @return a GeneralPath object, or null if it's not needed (which * is probably most of the time, if the arc doesn't * include a pole or the projection isn't Cylindrical). */ public GeneralPath getPolarShapeLine() { return polarShapeLine; } /** * Create alternate x,y coordinate arrays for rendering graphics * the encompass a pole in the Cylindrical projection. * * @return a two dimensional array of points. The [0] array is the * x points, the [1] is the y points. */ private int[][] doPolarFillCorrection(int[] xpoints, int[] ypoints, int y1) { int[][] ret = new int[2][]; int len = xpoints.length; int[] alt_xpts = new int[len + 2]; int[] alt_ypts = new int[len + 2]; System.arraycopy(xpoints, 0, alt_xpts, 0, len); System.arraycopy(ypoints, 0, alt_ypts, 0, len); alt_xpts[len] = alt_xpts[len - 1]; alt_xpts[len + 1] = alt_xpts[0]; alt_ypts[len] = y1; alt_ypts[len + 1] = alt_ypts[len]; ret[0] = alt_xpts; ret[1] = alt_ypts; return ret; } /** * Paint the arc. * * @param g Graphics context to render into */ public void render(Graphics g) { if (!isRenderable()) return; if (!correctFill) { // super will catch a null shape... super.render(g); } else { // The polarShapeLine will be there only if a shape was // generated. // This is getting kicked off because the arc is // encompassing a pole, so we need to handle it a little // differently. if (shouldRenderFill()) { setGraphicsForFill(g); fill(g); } // BUG There is still a bug apparent when, in a // cylindrical projection, and drawing a arc around the // south pole. If the center of the arc is below any // part of the edge of the arc, with the left lower dip // of the arc on the screen, you get a line drawn from // the right dip to the left dip. Not sure why. It's an // unusual case, however. if (shouldRenderEdge()) { setGraphicsForEdge(g); ((Graphics2D) g).draw(polarShapeLine); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -