svn-document-layout / trunk / org.gvsig.app.document.layout2.app / org.gvsig.app.document.layout2.app.mainplugin / src / main / java / org / gvsig / app / project / documents / layout / fframes / FFrameGrid.java @ 344
History | View | Annotate | Download (32.7 KB)
1 |
/* gvSIG. Geographic Information System of the Valencian Government
|
---|---|
2 |
*
|
3 |
* Copyright (C) 2007-2008 Infrastructures and Transports Department
|
4 |
* of the Valencian Government (CIT)
|
5 |
*
|
6 |
* This program is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU General Public License
|
8 |
* as published by the Free Software Foundation; either version 2
|
9 |
* of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This program is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 |
* GNU General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU General Public License
|
17 |
* along with this program; if not, write to the Free Software
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 |
* MA 02110-1301, USA.
|
20 |
*
|
21 |
*/
|
22 |
package org.gvsig.app.project.documents.layout.fframes; |
23 |
|
24 |
import java.awt.Color; |
25 |
import java.awt.Dimension; |
26 |
import java.awt.Font; |
27 |
import java.awt.Graphics2D; |
28 |
import java.awt.font.TextLayout; |
29 |
import java.awt.geom.AffineTransform; |
30 |
import java.awt.geom.Point2D; |
31 |
import java.awt.geom.Rectangle2D; |
32 |
import java.awt.image.BufferedImage; |
33 |
import java.text.DecimalFormat; |
34 |
import java.text.DecimalFormatSymbols; |
35 |
|
36 |
import org.gvsig.andami.PluginServices; |
37 |
import org.gvsig.compat.print.PrintAttributes; |
38 |
import org.gvsig.fmap.geom.Geometry; |
39 |
import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
40 |
import org.gvsig.fmap.geom.Geometry.TYPES; |
41 |
import org.gvsig.fmap.geom.GeometryLocator; |
42 |
import org.gvsig.fmap.geom.GeometryManager; |
43 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
44 |
import org.gvsig.fmap.geom.primitive.Curve; |
45 |
import org.gvsig.fmap.geom.primitive.Envelope; |
46 |
import org.gvsig.fmap.mapcontext.MapContextLocator; |
47 |
import org.gvsig.fmap.mapcontext.ViewPort; |
48 |
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol; |
49 |
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager; |
50 |
import org.gvsig.gui.awt.text.RotatedTextUtils; |
51 |
import org.gvsig.math.intervals.IntervalUtils; |
52 |
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol; |
53 |
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol; |
54 |
import org.gvsig.tools.ToolsLocator; |
55 |
import org.gvsig.tools.dynobject.DynStruct; |
56 |
import org.gvsig.tools.locator.LocatorException; |
57 |
import org.gvsig.tools.persistence.PersistenceManager; |
58 |
import org.gvsig.tools.persistence.PersistentState; |
59 |
import org.gvsig.tools.persistence.exception.PersistenceException; |
60 |
|
61 |
/**
|
62 |
* FFrame para introducir una cuadr?cula sobre una vista en el Layout.
|
63 |
*
|
64 |
* @author Vicente Caballero Navarro
|
65 |
*/
|
66 |
public class FFrameGrid extends AbstractFFrameViewDependence implements |
67 |
IFFrameViewDependence { |
68 |
private static final GeometryManager GEOMETRY_MANAGER = GeometryLocator.getGeometryManager(); |
69 |
|
70 |
private static final int OFFSET_IN_PIXELS = 5; |
71 |
|
72 |
public static final String PERSISTENCE_DEFINITION_NAME = "FFrameGrid"; |
73 |
|
74 |
private static final String SYMBOLLINE_FIELD = "symbolLine"; |
75 |
private static final String SYMBOLPOINT_FIELD = "symbolPoint"; |
76 |
private static final String FONT_FIELD = "font"; |
77 |
private static final String INTERVALX_FIELD = "intervalX"; |
78 |
private static final String INTERVALY_FIELD = "intervalY"; |
79 |
private static final String ISLINE_FIELD = "isLine"; |
80 |
private static final String FONTSYZE_FIELD = "fontsize"; |
81 |
private static final String TEXTCOLOR_FIELD = "textColor"; |
82 |
private static final String USE_NUM_DIVISIONS_FIELD = "useNumDivisions"; |
83 |
private static final String NUM_DIV_HORIZ_FIELD = "numDivHoriz"; |
84 |
private static final String NUM_DIV_VERT_FIELD = "numDivVret"; |
85 |
private static final String LABEL_FORMAT_FIELD = "labelFormat"; |
86 |
private static final String HORIZ_LABEL_ROTATION_FIELD = "horizLabelRotation"; |
87 |
private static final String VERT_LABEL_ROTATION_FIELD = "vertLabelRotation"; |
88 |
private static final String LABEL_ANCHOR = "LabelAnchor"; |
89 |
|
90 |
|
91 |
/**
|
92 |
* Use a fixed distance (intervalX and intervalY)
|
93 |
* to calculate the position of grid lines
|
94 |
*/
|
95 |
public static final int FIXED_DISTANCE_MODE = 0; |
96 |
/**
|
97 |
* Use a specific number of horizontal divisions in order
|
98 |
* to calculate the position of grid lines
|
99 |
*/
|
100 |
public static final int NUM_DIVISIONS_HORIZ_MODE = 1; |
101 |
/**
|
102 |
* Use a specific number of vertical divisions in order to calculate
|
103 |
* the position of grid lines
|
104 |
*/
|
105 |
public static final int NUM_DIVISIONS_VERT_MODE = 2; |
106 |
|
107 |
private double defaultInterval = 100000; |
108 |
private Double intervalX = null; |
109 |
private Double intervalY = null; |
110 |
|
111 |
private Color textColor = Color.black; |
112 |
private boolean isLine; |
113 |
private int sizeFont = 8; |
114 |
private int useNumDivisions = FIXED_DISTANCE_MODE; |
115 |
private int numDivHoriz = 4; |
116 |
private int numDivVert = 4; |
117 |
private DecimalFormat labelFormat = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance()); |
118 |
private double horizLabelRotation = 0.0; |
119 |
private double vertLabelRotation = 0.0; |
120 |
/**
|
121 |
* {@link RotatedTextUtils.ANCHOR_CENTER} or {@link RotatedTextUtils.ANCHOR_CORNER}
|
122 |
*/
|
123 |
private int labelAnchor = RotatedTextUtils.ANCHOR_CORNER; |
124 |
|
125 |
// private boolean print=false;
|
126 |
private SymbolManager symbolManager = MapContextLocator.getSymbolManager();
|
127 |
private ILineSymbol symbolLine = (ILineSymbol) symbolManager
|
128 |
.createSymbol(ILineSymbol.SYMBOL_NAME); |
129 |
private IMarkerSymbol symbolPoint = (IMarkerSymbol) symbolManager
|
130 |
.createSymbol(IMarkerSymbol.SYMBOL_NAME); |
131 |
private Font font = new Font("Arial", Font.PLAIN, sizeFont); |
132 |
|
133 |
public void draw(Graphics2D g, AffineTransform at, Rectangle2D rv, |
134 |
BufferedImage imgBase) {
|
135 |
try {
|
136 |
Rectangle2D.Double r = getBoundingBox(at);
|
137 |
Rectangle2D rView = fframeViewDependence.getBoundingBox(at);
|
138 |
if (r==null || rView==null) { |
139 |
//extent may be null, for instance if no layer has been loaded on the view
|
140 |
return;
|
141 |
} |
142 |
ViewPort vp = (ViewPort) fframeViewDependence.getMapContext().getViewPort().clone(); |
143 |
|
144 |
vp.setOffset(new Point2D.Double(rView.getMinX(), rView.getMinY())); |
145 |
vp.setImageSize(new Dimension((int)Math.round(rView.getWidth()), (int)Math.round(rView.getHeight()))); |
146 |
vp.refreshExtent(); |
147 |
|
148 |
Envelope envelope = vp.getAdjustedEnvelope(); |
149 |
AffineTransform mapTransform = vp.getAffineTransform();
|
150 |
updateIntervals(envelope); |
151 |
double intervalX = getIntervalX();
|
152 |
double intervalY = getIntervalY();
|
153 |
|
154 |
g.rotate(Math.toRadians(getRotation()), r.x + (r.width / 2), r.y + (r.height / 2)); |
155 |
|
156 |
double minX = envelope.getMinimum(0); |
157 |
double minY = envelope.getMinimum(1); |
158 |
double maxX = envelope.getMaximum(0); |
159 |
double maxY = envelope.getMaximum(1); |
160 |
|
161 |
// init point, in map coordinates
|
162 |
double initPointGridWCX = Math.ceil(minX / intervalX)*intervalX; |
163 |
double initPointGridWCY = Math.ceil(minY / intervalY)*intervalY; |
164 |
|
165 |
ISymbol symbolForMargins = null;
|
166 |
if (isLine){
|
167 |
symbolForMargins = symbolLine; |
168 |
}else{
|
169 |
try {
|
170 |
symbolForMargins = (ISymbol)symbolLine.clone(); |
171 |
symbolForMargins.setColor(symbolPoint.getColor()); |
172 |
} catch (CloneNotSupportedException e) { |
173 |
LOG.error("Symbol desn't support the clone method", e);
|
174 |
} |
175 |
} |
176 |
|
177 |
//Draw the box
|
178 |
drawBox(rView, g, symbolForMargins); |
179 |
|
180 |
//Draw the margins
|
181 |
double myScale = at.getScaleX() * 0.0234; // FIXME: 0.0234?? Should this depend on output resolution? |
182 |
int scaledFontSize = (int) (myScale * sizeFont); |
183 |
Font font = new Font( |
184 |
this.font.getFamily(),
|
185 |
this.font.getStyle(),
|
186 |
scaledFontSize); |
187 |
|
188 |
drawLabels(rView, |
189 |
initPointGridWCX, |
190 |
initPointGridWCY, |
191 |
maxX, |
192 |
maxY, |
193 |
intervalX, |
194 |
intervalY, |
195 |
mapTransform, |
196 |
g, |
197 |
font, |
198 |
symbolForMargins); |
199 |
|
200 |
//Draw the lines or the points
|
201 |
if (isLine) {
|
202 |
drawLines(rView, |
203 |
initPointGridWCX, |
204 |
initPointGridWCY, |
205 |
maxX, |
206 |
maxY, |
207 |
intervalX, |
208 |
intervalY, |
209 |
mapTransform, |
210 |
g); |
211 |
} else {
|
212 |
drawPoints(initPointGridWCX, |
213 |
initPointGridWCY, |
214 |
maxX, |
215 |
maxY, |
216 |
intervalX, |
217 |
intervalY, |
218 |
mapTransform, |
219 |
g); |
220 |
} |
221 |
|
222 |
g.rotate(Math.toRadians(-getRotation()), r.x + (r.width / 2), r.y |
223 |
+ (r.height / 2));
|
224 |
} catch (CloneNotSupportedException e1) {} |
225 |
} |
226 |
|
227 |
/**
|
228 |
* Draw the grid as point symbols
|
229 |
*
|
230 |
* @param minGridX The starting grid point on the x axis, in map coordinates
|
231 |
* @param minGridY The starting grid point on the y axis, in map coordinates
|
232 |
* @param maxGridX The maximum map point on the x axis, in map coordinates.
|
233 |
* It may be bigger than the maximum grid point
|
234 |
* @param maxGridY The maximum map point on the y axis, in map coordinates.
|
235 |
* It may be bigger than the maximum grid point
|
236 |
* @param intervalGridX The grid interval on the x axis, in map coordinates
|
237 |
* @param intervalGridY The grid interval on the y axis, in map coordinates
|
238 |
* @param mapTransform Transforms map coordinates to screen coordinates
|
239 |
* @param g The graphics object to draw on
|
240 |
*/
|
241 |
private void drawPoints( |
242 |
double minGridX,
|
243 |
double minGridY,
|
244 |
double maxGridX,
|
245 |
double maxGridY,
|
246 |
double intervalGridX,
|
247 |
double intervalGridY,
|
248 |
AffineTransform mapTransform,
|
249 |
Graphics2D g) {
|
250 |
|
251 |
Point2D currentPoint = new Point2D.Double(minGridX, minGridY); |
252 |
Point2D screenPoint = new Point2D.Double(); |
253 |
while (currentPoint.getX() < maxGridX) {
|
254 |
while (currentPoint.getY() < maxGridY) {
|
255 |
mapTransform.transform(currentPoint, screenPoint); |
256 |
drawPoint(g, screenPoint); |
257 |
currentPoint.setLocation(currentPoint.getX(), currentPoint.getY()+intervalGridY); |
258 |
} |
259 |
currentPoint.setLocation(currentPoint.getX()+intervalGridX, minGridY); |
260 |
} |
261 |
} |
262 |
|
263 |
/**
|
264 |
* Draw the grid as line symbols
|
265 |
*
|
266 |
* @param rView The rectangle of the view, on screen coordinates
|
267 |
* @param minGridX The starting grid point on the x axis, in map coordinates
|
268 |
* @param minGridY The starting grid point on the y axis, in map coordinates
|
269 |
* @param maxGridX The maximum map point on the x axis, in map coordinates.
|
270 |
* It may be bigger than the maximum grid point
|
271 |
* @param maxGridY The maximum map point on the y axis, in map coordinates.
|
272 |
* It may be bigger than the maximum grid point
|
273 |
* @param intervalGridX The grid interval on the x axis, in map coordinates
|
274 |
* @param intervalGridY The grid interval on the y axis, in map coordinates
|
275 |
* @param mapTransform Transforms map coordinates to screen coordinates
|
276 |
* @param g The graphics object to draw on
|
277 |
*/
|
278 |
private void drawLines(Rectangle2D rView, |
279 |
double minMapX,
|
280 |
double minMapY,
|
281 |
double maxMapX,
|
282 |
double maxMapY,
|
283 |
double intervalMapX,
|
284 |
double intervalMapY,
|
285 |
AffineTransform mapTransform,
|
286 |
Graphics2D g) {
|
287 |
double minX = rView.getMinX();
|
288 |
double maxX = rView.getMaxX();
|
289 |
double minY = rView.getMinY();
|
290 |
double maxY = rView.getMaxY();
|
291 |
double xMap = minMapX;
|
292 |
double yMap = minMapY;
|
293 |
|
294 |
// transform to screen coordinates
|
295 |
Point2D currentPoint = new Point2D.Double(minMapX, minMapY); |
296 |
// transform from map coordinates to screen (pixels) coordinates
|
297 |
mapTransform.transform(currentPoint, currentPoint); |
298 |
|
299 |
//Draw the vertical lines
|
300 |
while (xMap < maxMapX) {
|
301 |
drawLine(currentPoint.getX(), minY, currentPoint.getX(), maxY, g, symbolLine); |
302 |
xMap = xMap + intervalMapX; |
303 |
currentPoint.setLocation(xMap, minMapY); |
304 |
// from map coordinates to screen (pixels)
|
305 |
mapTransform.transform(currentPoint, currentPoint); |
306 |
} |
307 |
//Draw the horizontal lines
|
308 |
while (yMap < maxMapY) {
|
309 |
drawLine(minX, currentPoint.getY(), maxX , currentPoint.getY(), g, symbolLine); |
310 |
yMap = yMap + intervalMapY; |
311 |
currentPoint.setLocation(minMapX, yMap); |
312 |
// from map coordinates to screen (pixels)
|
313 |
mapTransform.transform(currentPoint, currentPoint); |
314 |
} |
315 |
} |
316 |
|
317 |
/**
|
318 |
* Draws the labels and the tick marks of labels
|
319 |
*
|
320 |
* @param rView The rectangle of the view, on screen coordinates
|
321 |
* @param minGridX The starting grid point on the x axis, in map coordinates
|
322 |
* @param minGridY The starting grid point on the y axis, in map coordinates
|
323 |
* @param maxGridX The maximum map point on the x axis, in map coordinates.
|
324 |
* It may be bigger than the maximum grid point
|
325 |
* @param maxGridY The maximum map point on the y axis, in map coordinates.
|
326 |
* It may be bigger than the maximum grid point
|
327 |
* @param intervalGridX The grid interval on the x axis, in map coordinates
|
328 |
* @param intervalGridY The grid interval on the y axis, in map coordinates
|
329 |
* @param mapTransform Transforms map coordinates to screen coordinates
|
330 |
* @param g The graphics object to draw on
|
331 |
* @param font
|
332 |
* @param symbolForMargins
|
333 |
*/
|
334 |
private void drawLabels(Rectangle2D rView, |
335 |
double minGridX,
|
336 |
double minGridY,
|
337 |
double maxGridX,
|
338 |
double maxGridY,
|
339 |
double intervalGridX,
|
340 |
double intervalGridY,
|
341 |
AffineTransform mapTransform,
|
342 |
Graphics2D g,
|
343 |
Font font,
|
344 |
ISymbol |
345 |
symbolForMargins) { |
346 |
AffineTransform defaultAt = g.getTransform();
|
347 |
|
348 |
double minX = rView.getMinX();
|
349 |
double maxX = rView.getMaxX();
|
350 |
double minY = rView.getMinY();
|
351 |
double maxY = rView.getMaxY();
|
352 |
double xMap = minGridX;
|
353 |
double yMap = minGridY;
|
354 |
|
355 |
// transform to screen coordinates
|
356 |
Point2D initGridPx = new Point2D.Double(minGridX, minGridY); |
357 |
mapTransform.transform(initGridPx, initGridPx); |
358 |
|
359 |
double xPx = initGridPx.getX();
|
360 |
|
361 |
double angle = RotatedTextUtils.normalizeAngle(Math.toRadians(getVertLabelRotation())); |
362 |
int anchor = getLabelAnchor();
|
363 |
// Draw vertical ticks and labels
|
364 |
while (xMap < maxGridX) {
|
365 |
// bottom tick
|
366 |
drawLine(xPx, maxY + OFFSET_IN_PIXELS, xPx , maxY, g, symbolForMargins); |
367 |
// top tick
|
368 |
drawLine(xPx, minY, xPx, minY - OFFSET_IN_PIXELS, g, symbolForMargins); |
369 |
|
370 |
g.rotate(angle); |
371 |
g.setColor(textColor); |
372 |
|
373 |
// bottom label
|
374 |
Point2D p1 = new Point2D.Double(xPx, maxY+OFFSET_IN_PIXELS); // bottom |
375 |
TextLayout textaux = new TextLayout(this.labelFormat.format(xMap), font, g.getFontRenderContext()); |
376 |
Point2D rotatedP1 = RotatedTextUtils.getPosition(p1, textaux, angle, RotatedTextUtils.PLACEMENT_BOTTOM, anchor);
|
377 |
textaux.draw(g, (int) (rotatedP1.getX()), (int) rotatedP1.getY()); |
378 |
|
379 |
// top label
|
380 |
Point2D p2 = new Point2D.Double(xPx, minY-OFFSET_IN_PIXELS); |
381 |
Point2D rotatedP2 = RotatedTextUtils.getPosition(p2, textaux, angle, RotatedTextUtils.PLACEMENT_TOP, anchor);
|
382 |
textaux.draw(g, (int) (rotatedP2.getX()),(int) rotatedP2.getY()); |
383 |
g.setTransform(defaultAt); |
384 |
|
385 |
|
386 |
xMap = xMap + intervalGridX; |
387 |
|
388 |
initGridPx.setLocation(xMap, minGridY); |
389 |
mapTransform.transform(initGridPx, initGridPx); |
390 |
xPx = initGridPx.getX(); |
391 |
} |
392 |
double yPx = initGridPx.getY();
|
393 |
angle = RotatedTextUtils.normalizeAngle(Math.toRadians(getHorizLabelRotation()));
|
394 |
// horizontal ticks and labels
|
395 |
while (yMap < maxGridY) {
|
396 |
|
397 |
// left tick
|
398 |
drawLine(minX - OFFSET_IN_PIXELS, yPx, minX , yPx, g, symbolForMargins); |
399 |
// right tick
|
400 |
drawLine(maxX, yPx, maxX + OFFSET_IN_PIXELS, yPx, g, symbolForMargins); |
401 |
|
402 |
g.rotate(angle); |
403 |
g.setColor(textColor); |
404 |
TextLayout textaux = new TextLayout(this.labelFormat.format(yMap), font, g.getFontRenderContext()); |
405 |
|
406 |
// left label
|
407 |
Point2D p1 = new Point2D.Double(minX-OFFSET_IN_PIXELS, yPx); |
408 |
Point2D rotatedP1 = RotatedTextUtils.getPosition(p1, textaux, angle, RotatedTextUtils.PLACEMENT_LEFT, anchor);
|
409 |
textaux.draw(g, (int) (rotatedP1.getX()), (int) rotatedP1.getY()); |
410 |
// right label
|
411 |
Point2D p2 = new Point2D.Double(maxX+OFFSET_IN_PIXELS, yPx); |
412 |
Point2D rotatedP2 = RotatedTextUtils.getPosition(p2, textaux, angle, RotatedTextUtils.PLACEMENT_RIGHT, anchor);
|
413 |
textaux.draw(g, (int) (rotatedP2.getX()),(int) rotatedP2.getY()); |
414 |
g.setTransform(defaultAt); |
415 |
yMap = yMap + intervalGridY; |
416 |
|
417 |
initGridPx.setLocation(minGridX, yMap); |
418 |
mapTransform.transform(initGridPx, initGridPx); |
419 |
yPx = initGridPx.getY(); |
420 |
} |
421 |
} |
422 |
|
423 |
private void drawBox(Rectangle2D mapRectangle, Graphics2D g, ISymbol symbol){ |
424 |
try {
|
425 |
// FIXME: We are adding 1 extra pixel for correct adjustment when exporting to PDF.
|
426 |
// However, this creates 1 blank pixel on the right side when drawing on screen.
|
427 |
// Probably this is caused by some rounding.
|
428 |
// Separating the implementation of print and draw methods should help, too.
|
429 |
Curve curve = (Curve) GEOMETRY_MANAGER.create(TYPES.CURVE, SUBTYPES.GEOM2D); |
430 |
curve.addMoveToVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMinX()-1, mapRectangle.getMinY()-1, SUBTYPES.GEOM2D)); |
431 |
curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMinX()-1, mapRectangle.getMaxY()+1, SUBTYPES.GEOM2D)); |
432 |
curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMaxX()+1, mapRectangle.getMaxY()+1, SUBTYPES.GEOM2D)); |
433 |
curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMaxX()+1, mapRectangle.getMinY()-1, SUBTYPES.GEOM2D)); |
434 |
curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMinX()-1, mapRectangle.getMinY()-1, SUBTYPES.GEOM2D)); |
435 |
symbol.draw(g, null, curve, null, null); |
436 |
} catch (CreateGeometryException e) {
|
437 |
LOG.error("Error drawing the box", e);
|
438 |
} |
439 |
} |
440 |
|
441 |
/**
|
442 |
* Draws a point using the configured symbol
|
443 |
*
|
444 |
* @param g The graphics object to draw on
|
445 |
* @param point Point to draw, in map coordinates
|
446 |
* @param mapTransform Transforms from map coordinates to screen coordinates
|
447 |
*/
|
448 |
private void drawPoint(Graphics2D g, Point2D point){ |
449 |
try {
|
450 |
Geometry geom = |
451 |
createPoint((int) point.getX(), (int) point.getY()); |
452 |
symbolPoint.draw(g, null, geom, null, null); |
453 |
} catch (LocatorException e) {
|
454 |
LOG.error("Error drawing the grid", e);
|
455 |
} catch (CreateGeometryException e) {
|
456 |
LOG.error("Error drawing the grid", e);
|
457 |
} |
458 |
} |
459 |
|
460 |
private void drawLine(double startX, double startY, double endX, double endY, Graphics2D g, ISymbol symbolLine){ |
461 |
try {
|
462 |
Geometry geom = |
463 |
createLine((int) startX, (int)startY, (int) endX, (int) endY); |
464 |
symbolLine.draw(g, null, geom, null, null); |
465 |
} catch (LocatorException e) {
|
466 |
LOG.error("Error drawing the grid", e);
|
467 |
} catch (CreateGeometryException e) {
|
468 |
LOG.error("Error drawing the grid", e);
|
469 |
} |
470 |
} |
471 |
|
472 |
private Geometry createLine(int i, int j, int k, int l) |
473 |
throws LocatorException, CreateGeometryException {
|
474 |
Curve curve = (Curve)GEOMETRY_MANAGER.create(Geometry.TYPES.CURVE, SUBTYPES.GEOM2D); |
475 |
curve.addMoveToVertex(GEOMETRY_MANAGER.createPoint(i, j, SUBTYPES.GEOM2D)); |
476 |
curve.addVertex(GEOMETRY_MANAGER.createPoint(k, l, SUBTYPES.GEOM2D)); |
477 |
return curve;
|
478 |
} |
479 |
|
480 |
private Geometry createPoint(int i, int j) throws LocatorException, |
481 |
CreateGeometryException { |
482 |
return GeometryLocator.getGeometryManager().createPoint(i, j,
|
483 |
SUBTYPES.GEOM2D); |
484 |
} |
485 |
|
486 |
public String getNameFFrame() { |
487 |
return PluginServices.getText(this, "cuadricula") + num; |
488 |
} |
489 |
|
490 |
public String getName() { |
491 |
return PERSISTENCE_DEFINITION_NAME;
|
492 |
} |
493 |
|
494 |
public void setFFrameDependence(IFFrame f) { |
495 |
super.setFFrameDependence(f);
|
496 |
fframeViewDependence.refresh(); |
497 |
} |
498 |
|
499 |
public void setIntervalX(double d) { |
500 |
intervalX = d; |
501 |
} |
502 |
|
503 |
public void setIntervalY(double d) { |
504 |
intervalY = d; |
505 |
} |
506 |
|
507 |
public double getIntervalX() { |
508 |
if (intervalX!=null) { |
509 |
return intervalX;
|
510 |
} |
511 |
intervalX = intervalY = getReasonableInterval(); |
512 |
return intervalX;
|
513 |
} |
514 |
|
515 |
private double getReasonableInterval() { |
516 |
if (fframeViewDependence!=null |
517 |
&& fframeViewDependence.getMapContext()!=null
|
518 |
&& fframeViewDependence.getMapContext().getViewPort().getAdjustedEnvelope()!=null) {
|
519 |
Envelope env = fframeViewDependence.getMapContext().getViewPort().getAdjustedEnvelope(); |
520 |
return IntervalUtils.roundIntervalDivision(env.getLength(0), 5); |
521 |
} |
522 |
return defaultInterval;
|
523 |
} |
524 |
|
525 |
|
526 |
public double getIntervalY() { |
527 |
if (intervalX!=null) { |
528 |
return intervalX;
|
529 |
} |
530 |
intervalX = intervalY = new Double(getReasonableInterval()); |
531 |
return intervalY;
|
532 |
} |
533 |
|
534 |
public void setTextColor(Color textcolor) { |
535 |
textColor = textcolor; |
536 |
} |
537 |
|
538 |
public void setIsLine(boolean b) { |
539 |
isLine = b; |
540 |
} |
541 |
|
542 |
public boolean isLine() { |
543 |
return isLine;
|
544 |
} |
545 |
|
546 |
public Color getFontColor() { |
547 |
return textColor;
|
548 |
} |
549 |
|
550 |
public int getSizeFont() { |
551 |
return sizeFont;
|
552 |
} |
553 |
|
554 |
public void setSizeFont(int sizeFont) { |
555 |
this.sizeFont = sizeFont;
|
556 |
} |
557 |
|
558 |
public Rectangle2D.Double getBoundingBox(AffineTransform at) { |
559 |
if ((fframeViewDependence == null) || (fframeViewDependence.getMapContext() == null)){ |
560 |
return super.getBoundingBox(at); |
561 |
} |
562 |
Rectangle2D.Double r = fframeViewDependence.getBoundingBox(at);
|
563 |
Envelope extent = |
564 |
fframeViewDependence.getMapContext().getViewPort() |
565 |
.getAdjustedEnvelope(); |
566 |
if (extent==null) { |
567 |
//extent may be null, for instance if no layer has been loaded on the view
|
568 |
return null; |
569 |
} |
570 |
double extentX = extent.getMaximum(0); |
571 |
double extentY = extent.getMaximum(1); |
572 |
int lengthX = String.valueOf((long) extentX).length(); |
573 |
double myScale = at.getScaleX() * 0.0234; |
574 |
int scaledFontSize = (int) (myScale * sizeFont); |
575 |
int pixelsX = (int) (lengthX * scaledFontSize * 0.7); |
576 |
int lengthY = String.valueOf((long) extentY).length(); |
577 |
int pixelsY = (lengthY * scaledFontSize);
|
578 |
return new Rectangle2D.Double(r.getMinX() - pixelsX, r.getMinY() - pixelsY, |
579 |
r.getWidth() + pixelsX * 2, r.getHeight() + pixelsY * 2); |
580 |
} |
581 |
|
582 |
public Rectangle2D getMovieRect(int difx, int dify) { |
583 |
return this.getBoundingBox(null); |
584 |
} |
585 |
|
586 |
public void refreshDependence(IFFrame fant, IFFrame fnew) { |
587 |
if (fframeViewDependence.equals(fant)) {
|
588 |
fframeViewDependence = (FFrameView) fnew; |
589 |
fframeViewDependence.refresh(); |
590 |
} |
591 |
} |
592 |
|
593 |
public void drawHandlers(Graphics2D g) { |
594 |
g.setColor(Color.gray);
|
595 |
super.drawHandlers(g);
|
596 |
g.setColor(Color.black);
|
597 |
} |
598 |
|
599 |
public Rectangle2D getLastMoveRect() { |
600 |
return getBoundBox();
|
601 |
} |
602 |
|
603 |
public ISymbol getSymbolLine() {
|
604 |
return symbolLine;
|
605 |
} |
606 |
|
607 |
public void setSymbolLine(ISymbol symbolLine) { |
608 |
this.symbolLine = (ILineSymbol) symbolLine;
|
609 |
} |
610 |
|
611 |
public ISymbol getSymbolPoint() {
|
612 |
return symbolPoint;
|
613 |
} |
614 |
|
615 |
public void setSymbolPoint(ISymbol symbolPoint) { |
616 |
this.symbolPoint = (IMarkerSymbol) symbolPoint;
|
617 |
} |
618 |
|
619 |
public Font getFont() { |
620 |
return font;
|
621 |
} |
622 |
|
623 |
public void setFont(Font m_font) { |
624 |
this.font = m_font;
|
625 |
} |
626 |
|
627 |
public int getFontSize() { |
628 |
return font.getSize();
|
629 |
} |
630 |
|
631 |
/**
|
632 |
* Defines whether a number of divisions is used to calculate the
|
633 |
* location of grid lines,
|
634 |
* or a distance (intervalX and intervalY) is used to
|
635 |
* calculate them.
|
636 |
*
|
637 |
* @param useNumDivisions One of {@link #FIXED_DISTANCE_MODE},
|
638 |
* {@link #NUM_DIVISIONS_HORIZ_MODE} or {@link #NUM_DIVISIONS_HORIZ_MODE}.
|
639 |
* @return
|
640 |
*/
|
641 |
public void setUseNumDivisions(int mode) { |
642 |
this.useNumDivisions = mode;
|
643 |
} |
644 |
|
645 |
protected void updateIntervals() { |
646 |
if (fframeViewDependence.getMapContext()!=null |
647 |
&& fframeViewDependence.getMapContext().getViewPort()!=null) {
|
648 |
Envelope env = fframeViewDependence.getMapContext().getViewPort().getAdjustedEnvelope(); |
649 |
updateIntervals(env); |
650 |
} |
651 |
} |
652 |
|
653 |
protected void updateIntervals(Envelope env) { |
654 |
if (useNumDivisions==NUM_DIVISIONS_HORIZ_MODE) {
|
655 |
double division = IntervalUtils.roundIntervalDivision(env.getLength(0), numDivHoriz); |
656 |
intervalX = division; |
657 |
intervalY = division; |
658 |
} |
659 |
else if (useNumDivisions==NUM_DIVISIONS_VERT_MODE) { |
660 |
double division = IntervalUtils.roundIntervalDivision(env.getLength(1), numDivVert); |
661 |
intervalX = division; |
662 |
intervalY = division; |
663 |
} |
664 |
} |
665 |
|
666 |
/**
|
667 |
* Returns true if a number of divisions is used to calculate the
|
668 |
* location of grid lines,
|
669 |
* or false if a distance (intervalX and intervalY) is used to
|
670 |
* calculate them.
|
671 |
*
|
672 |
* @return One of {@link #FIXED_DISTANCE_MODE},
|
673 |
* {@link #NUM_DIVISIONS_HORIZ_MODE} or {@link #NUM_DIVISIONS_VERT_MODE}.
|
674 |
*/
|
675 |
public int getUseNumDivisions() { |
676 |
return this.useNumDivisions; |
677 |
} |
678 |
|
679 |
public void setNumDivisionsHoriz(int nx) { |
680 |
this.numDivHoriz = nx;
|
681 |
} |
682 |
|
683 |
public void setNumDivisionsVert(int ny) { |
684 |
this.numDivVert = ny;
|
685 |
} |
686 |
|
687 |
public int getNumDivisionsHoriz() { |
688 |
return this.numDivHoriz; |
689 |
} |
690 |
|
691 |
public int getNumDivisionsVert() { |
692 |
return this.numDivVert; |
693 |
} |
694 |
|
695 |
public void setLabelFormat(DecimalFormat f) { |
696 |
this.labelFormat = f;
|
697 |
} |
698 |
|
699 |
public DecimalFormat getLabelFormat() { |
700 |
return this.labelFormat; |
701 |
} |
702 |
|
703 |
/**
|
704 |
* Sets the rotation of the labels corresponding to horizontal lines
|
705 |
*
|
706 |
* @param labelRotation Label rotation, measured in arc degrees
|
707 |
*/
|
708 |
public void setHorizLabelRotation(double labelRotation) { |
709 |
this.horizLabelRotation = labelRotation;
|
710 |
} |
711 |
|
712 |
/**
|
713 |
* Sets the rotation of the labels corresponding to vertical lines
|
714 |
*
|
715 |
* @param labelRotation Label rotation, measured in arc degrees
|
716 |
*/
|
717 |
public void setVertLabelRotation(double labelRotation) { |
718 |
this.vertLabelRotation = labelRotation;
|
719 |
} |
720 |
|
721 |
/**
|
722 |
* Gets the rotation of the labels corresponding to horizontal lines
|
723 |
*
|
724 |
* @param labelRotation Label rotation, measured in arc degrees
|
725 |
*/
|
726 |
public double getHorizLabelRotation() { |
727 |
return this.horizLabelRotation; |
728 |
} |
729 |
|
730 |
/**
|
731 |
* Defines the alignment of the grid label compared with the
|
732 |
* associated grid tick
|
733 |
*
|
734 |
* @param anchor {@link RotatedTextUtils.ANCHOR_CORNER} or
|
735 |
* {@link RotatedTextUtils.ANCHOR_CENTER}
|
736 |
*/
|
737 |
public int getLabelAnchor() { |
738 |
return this.labelAnchor; |
739 |
} |
740 |
|
741 |
/**
|
742 |
* Gets the alignment of the grid labels. ANCHOR_CORNER aligns
|
743 |
* the corner of the label with the grid tick, while ANCHOR_CENTER
|
744 |
* aligns the label center with the grid tick.
|
745 |
*
|
746 |
* @param anchor {@link RotatedTextUtils.ANCHOR_CORNER} or
|
747 |
* {@link RotatedTextUtils.ANCHOR_CENTER}
|
748 |
*/
|
749 |
public void setLabelAnchor(int anchor) { |
750 |
// ensure a coherent value
|
751 |
if (anchor==RotatedTextUtils.ANCHOR_CENTER) {
|
752 |
this.labelAnchor = anchor;
|
753 |
} |
754 |
else {
|
755 |
this.labelAnchor = RotatedTextUtils.ANCHOR_CORNER;
|
756 |
} |
757 |
} |
758 |
|
759 |
/**
|
760 |
* Gets the rotation of the labels corresponding to vertical lines
|
761 |
*
|
762 |
* @param labelRotation Label rotation, measured in arc degrees
|
763 |
*/
|
764 |
public double getVertLabelRotation() { |
765 |
return this.vertLabelRotation; |
766 |
} |
767 |
|
768 |
public void print(Graphics2D g, AffineTransform at, Geometry shape, |
769 |
PrintAttributes properties) { |
770 |
draw(g, at, null, null); |
771 |
} |
772 |
|
773 |
public static void registerPersistent() { |
774 |
PersistenceManager manager = ToolsLocator.getPersistenceManager(); |
775 |
if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) { |
776 |
DynStruct definition = |
777 |
manager.addDefinition(FFrameGrid.class, |
778 |
PERSISTENCE_DEFINITION_NAME, |
779 |
"FFrameGrid persistence definition", null, null); |
780 |
|
781 |
definition |
782 |
.extend(manager |
783 |
.getDefinition(AbstractFFrameViewDependence.PERSISTENCE_DEFINITION_NAME)); |
784 |
|
785 |
definition.addDynFieldObject(SYMBOLLINE_FIELD) |
786 |
.setClassOfValue(ILineSymbol.class).setMandatory(true);
|
787 |
definition.addDynFieldObject(SYMBOLPOINT_FIELD) |
788 |
.setClassOfValue(IMarkerSymbol.class).setMandatory(true);
|
789 |
definition.addDynFieldObject(FONT_FIELD) |
790 |
.setClassOfValue(Font.class).setMandatory(true); |
791 |
definition.addDynFieldDouble(INTERVALX_FIELD).setMandatory(false);
|
792 |
definition.addDynFieldDouble(INTERVALY_FIELD).setMandatory(false);
|
793 |
definition.addDynFieldBoolean(ISLINE_FIELD).setMandatory(true);
|
794 |
definition.addDynFieldInt(FONTSYZE_FIELD).setMandatory(true);
|
795 |
definition.addDynFieldObject(TEXTCOLOR_FIELD) |
796 |
.setClassOfValue(Color.class).setMandatory(true); |
797 |
definition.addDynFieldInt(USE_NUM_DIVISIONS_FIELD).setMandatory(false);
|
798 |
definition.addDynFieldInt(NUM_DIV_HORIZ_FIELD).setMandatory(false);
|
799 |
definition.addDynFieldInt(NUM_DIV_VERT_FIELD).setMandatory(false);
|
800 |
definition.addDynFieldObject(LABEL_FORMAT_FIELD) |
801 |
.setClassOfValue(DecimalFormat.class).setMandatory(false); |
802 |
definition.addDynFieldDouble(VERT_LABEL_ROTATION_FIELD).setMandatory(false);
|
803 |
definition.addDynFieldDouble(HORIZ_LABEL_ROTATION_FIELD).setMandatory(false);
|
804 |
definition.addDynFieldInt(LABEL_ANCHOR).setMandatory(false);
|
805 |
} |
806 |
} |
807 |
|
808 |
|
809 |
@Override
|
810 |
public void loadFromState(PersistentState state) |
811 |
throws PersistenceException {
|
812 |
super.loadFromState(state);
|
813 |
symbolLine = (ILineSymbol) state.get(SYMBOLLINE_FIELD); |
814 |
symbolPoint = (IMarkerSymbol) state.get(SYMBOLPOINT_FIELD); |
815 |
font = (Font) state.get(FONT_FIELD);
|
816 |
intervalX = (Double) state.get(INTERVALX_FIELD);
|
817 |
intervalY = (Double) state.get(INTERVALY_FIELD);
|
818 |
isLine = state.getBoolean(ISLINE_FIELD); |
819 |
sizeFont = state.getInt(FONTSYZE_FIELD); |
820 |
textColor = (Color) state.get(TEXTCOLOR_FIELD);
|
821 |
if (state.hasValue(USE_NUM_DIVISIONS_FIELD)) {
|
822 |
useNumDivisions = state.getInt(USE_NUM_DIVISIONS_FIELD); |
823 |
} |
824 |
if (state.hasValue(NUM_DIV_HORIZ_FIELD)) {
|
825 |
numDivHoriz = state.getInt(NUM_DIV_HORIZ_FIELD); |
826 |
} |
827 |
if (state.hasValue(NUM_DIV_VERT_FIELD)) {
|
828 |
numDivVert = state.getInt(NUM_DIV_VERT_FIELD); |
829 |
} |
830 |
if (state.hasValue(LABEL_FORMAT_FIELD)) {
|
831 |
labelFormat = (DecimalFormat) state.get(LABEL_FORMAT_FIELD);
|
832 |
} |
833 |
if (state.hasValue(VERT_LABEL_ROTATION_FIELD)) {
|
834 |
vertLabelRotation = state.getDouble(VERT_LABEL_ROTATION_FIELD); |
835 |
} |
836 |
if (state.hasValue(HORIZ_LABEL_ROTATION_FIELD)) {
|
837 |
horizLabelRotation = state.getDouble(HORIZ_LABEL_ROTATION_FIELD); |
838 |
} |
839 |
if (state.hasValue(LABEL_ANCHOR)) {
|
840 |
labelAnchor = state.getInt(LABEL_ANCHOR); |
841 |
} |
842 |
} |
843 |
|
844 |
@Override
|
845 |
public void saveToState(PersistentState state) throws PersistenceException { |
846 |
super.saveToState(state);
|
847 |
state.set(SYMBOLLINE_FIELD, symbolLine); |
848 |
state.set(SYMBOLPOINT_FIELD, symbolPoint); |
849 |
state.set(FONT_FIELD, font); |
850 |
state.set(INTERVALX_FIELD, intervalX); |
851 |
state.set(INTERVALY_FIELD, intervalY); |
852 |
state.set(ISLINE_FIELD, isLine); |
853 |
state.set(FONTSYZE_FIELD, sizeFont); |
854 |
state.set(TEXTCOLOR_FIELD, textColor); |
855 |
state.set(USE_NUM_DIVISIONS_FIELD, useNumDivisions); |
856 |
state.set(NUM_DIV_HORIZ_FIELD, numDivHoriz); |
857 |
state.set(NUM_DIV_VERT_FIELD, numDivVert); |
858 |
state.set(LABEL_FORMAT_FIELD, labelFormat); |
859 |
state.set(VERT_LABEL_ROTATION_FIELD, vertLabelRotation); |
860 |
state.set(HORIZ_LABEL_ROTATION_FIELD, horizLabelRotation); |
861 |
state.set(LABEL_ANCHOR, labelAnchor); |
862 |
} |
863 |
} |