001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.mapgraphic.grid;
016:
017: import java.awt.Point;
018:
019: import net.refractions.udig.mapgraphic.MapGraphic;
020: import net.refractions.udig.mapgraphic.MapGraphicContext;
021: import net.refractions.udig.mapgraphic.MapGraphicPlugin;
022: import net.refractions.udig.mapgraphic.internal.Messages;
023: import net.refractions.udig.project.ILayer;
024: import net.refractions.udig.ui.graphics.ViewportGraphics;
025:
026: import org.geotools.referencing.CRS;
027: import org.geotools.referencing.crs.DefaultGeographicCRS;
028: import org.opengis.referencing.FactoryException;
029: import org.opengis.referencing.crs.CoordinateReferenceSystem;
030: import org.opengis.referencing.operation.MathTransform;
031:
032: import com.vividsolutions.jts.geom.Coordinate;
033: import com.vividsolutions.jts.geom.Envelope;
034:
035: /**
036: * Draws the grid on the map.
037: *
038: * @author Jesse
039: * @since 1.1.0
040: */
041: public class GridMapGraphic implements MapGraphic {
042:
043: public void draw(MapGraphicContext context) {
044: ViewportGraphics graphics = context.getGraphics();
045: GridStyle style = getStyle(context.getLayer());
046:
047: graphics.setColor(style.getColor());
048: graphics.setStroke(style.getLineStyle(), style.getLineWidth());
049:
050: switch (getStyle(context.getLayer()).getType()) {
051: case SCREEN:
052: screenMapGraphic(context);
053: break;
054: case WORLD:
055: worldMapGraphic(context);
056: break;
057:
058: default:
059: throw new AssertionError(
060: "Should be impossible to reach here: "
061: + getStyle(context.getLayer()).getType());
062:
063: }
064: }
065:
066: /**
067: * Draws grid so that x/y rows/columns show up on the screen
068: *
069: * @param context
070: */
071: private void screenMapGraphic(MapGraphicContext context) {
072: GridStyle style = getStyle(context.getLayer());
073: final double[] gridSize = style.getGridSize();
074: final int dx = (int) gridSize[0];
075: final int dy = (int) gridSize[1];
076:
077: int width = context.getMapDisplay().getWidth();
078: int height = context.getMapDisplay().getHeight();
079:
080: ViewportGraphics g = context.getGraphics();
081:
082: int x = 0, y = 0;
083:
084: while (x < width) {
085: x += dx;
086: g.drawLine(x, 0, x, height);
087: }
088:
089: while (y < height) {
090: y += dy;
091: g.drawLine(0, y, width, y);
092: }
093:
094: }
095:
096: /**
097: * Draws Grid so that there is a line ever so many degrees. Number of degrees is declared in the style.
098: *
099: * @param context
100: */
101: private void worldMapGraphic(MapGraphicContext context) {
102: GridStyle style = getStyle(context.getLayer());
103: double[] gridSize = style.getGridSize();
104: try {
105: MathTransform mt = CRS.findMathTransform(
106: DefaultGeographicCRS.WGS84, context.getCRS(), true);
107:
108: if (!mt.isIdentity()) {
109: double x = gridSize[0] / 2.0;
110: double y = gridSize[1] / 2.0;
111: double[] toTransform = new double[] { -x, -y, x, y };
112: double[] dest = new double[4];
113: mt.transform(toTransform, 0, dest, 0, 2);
114: gridSize = new double[] { Math.abs(dest[2] - dest[0]),
115: Math.abs(dest[3] - dest[1]) };
116: }
117: } catch (Exception e) {
118: MapGraphicPlugin.log("", e); //$NON-NLS-1$
119: }
120:
121: Envelope bounds = context.getViewportModel().getBounds();
122: double newx = Math.round(bounds.getMinX() / gridSize[0])
123: * gridSize[0];
124: double newy = Math.round(bounds.getMaxY() / gridSize[1])
125: * gridSize[1];
126: Coordinate coord = new Coordinate(newx, newy);
127: while (context.worldToPixel(coord).x < 0) {
128: coord.x += gridSize[0];
129: }
130: while (context.worldToPixel(coord).y < 0) {
131: coord.y -= gridSize[1];
132: }
133: ViewportGraphics graphics = context.getGraphics();
134: Point pixel = null;
135: while (true) {
136: pixel = context.worldToPixel(coord);
137: coord.x += gridSize[0];
138: coord.y -= gridSize[1];
139: Point next = context.worldToPixel(coord);
140: if (next.x - pixel.x < 2 || next.y - pixel.y < 2) {
141: context.getLayer().setStatus(ILayer.WARNING);
142: context.getLayer().setStatusMessage(
143: Messages.GridMapGraphic_grids_too_close);
144: break;
145: }
146: if ((pixel.x >= context.getMapDisplay().getWidth() && pixel.y >= context
147: .getMapDisplay().getHeight()))
148: break;
149:
150: if (pixel.x < context.getMapDisplay().getWidth())
151: graphics.drawLine(pixel.x, 0, pixel.x, context
152: .getMapDisplay().getHeight());
153: if (pixel.y < context.getMapDisplay().getHeight())
154: graphics.drawLine(0, pixel.y, context.getMapDisplay()
155: .getWidth(), pixel.y);
156: pixel = next;
157: }
158: }
159:
160: private GridStyle getStyle(ILayer layer) {
161: GridStyle gridStyle = (GridStyle) layer.getStyleBlackboard()
162: .get(GridStyle.ID);
163: if (gridStyle == null) {
164: return GridStyle.DEFAULT_STYLE;
165: }
166: return gridStyle;
167: }
168:
169: /**
170: * calculates the closest point to x,y.
171: *
172: * @param x x coord in screen coords
173: * @param y y coord in screen coords
174: * @param layer layer containing this map graphic
175: * @return the closest point on the grid in map coords
176: * @throws FactoryException
177: */
178: public double[] closest(int x, int y, ILayer layer)
179: throws FactoryException {
180: switch (getStyle(layer).getType()) {
181: case SCREEN:
182:
183: return screenClosest(x, y, layer);
184: case WORLD:
185: return worldClosest(x, y, layer);
186: default:
187: AssertionError e = new AssertionError(
188: "Should be impossible to reach here: "
189: + getStyle(layer).getType());
190: MapGraphicPlugin.log(null, e);
191: throw e;
192: }
193: }
194:
195: private double[] screenClosest(int x, int y, ILayer layer) {
196: double[] gridSize = getStyle(layer).getGridSize();
197:
198: double newx = Math.round(x / gridSize[0]) * gridSize[0];
199: double newy = Math.round(y / gridSize[1]) * gridSize[1];
200:
201: Coordinate result = layer.getMap().getViewportModel()
202: .pixelToWorld((int) newx, (int) newy);
203: return new double[] { result.x, result.y };
204: }
205:
206: private double[] worldClosest(int x1, int y1, ILayer layer)
207: throws FactoryException {
208: Coordinate coord = layer.getMap().getViewportModel()
209: .pixelToWorld(x1, y1);
210: CoordinateReferenceSystem crs = layer.getMap()
211: .getViewportModel().getCRS();
212: MathTransform mt = CRS.findMathTransform(
213: DefaultGeographicCRS.WGS84, crs);
214:
215: double[] gridSize = getStyle(layer).getGridSize();
216: try {
217:
218: if (!mt.isIdentity()) {
219: double tx = gridSize[0] / 2.0;
220: double ty = gridSize[1] / 2.0;
221: double[] toTransform = new double[] { -tx, -ty, tx, ty };
222: double[] dest = new double[4];
223: mt.transform(toTransform, 0, dest, 0, 2);
224: gridSize = new double[] { Math.abs(dest[2] - dest[0]),
225: Math.abs(dest[3] - dest[1]) };
226: }
227: } catch (Exception e) {
228: MapGraphicPlugin.log("", e); //$NON-NLS-1$
229: }
230: double newx = Math.round(coord.x / gridSize[0]) * gridSize[0];
231: double newy = Math.round(coord.y / gridSize[1]) * gridSize[1];
232: return new double[] { newx, newy };
233: }
234:
235: }
|