Statistics
| Revision:

root / branches / v10 / extensions / extAnnotations / src / com / iver / cit / gvsig / fmap / operation / strategies / Annotation_Strategy.java @ 12529

History | View | Annotate | Download (24.3 KB)

1

    
2
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
3
 *
4
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
19
 *
20
 * For more information, contact:
21
 *
22
 *  Generalitat Valenciana
23
 *   Conselleria d'Infraestructures i Transport
24
 *   Av. Blasco Ib??ez, 50
25
 *   46010 VALENCIA
26
 *   SPAIN
27
 *
28
 *      +34 963862235
29
 *   gvsig@gva.es
30
 *      www.gvsig.gva.es
31
 *
32
 *    or
33
 *
34
 *   IVER T.I. S.A
35
 *   Salamanca 50
36
 *   46005 Valencia
37
 *   Spain
38
 *
39
 *   +34 963163400
40
 *   dac@iver.es
41
 */
42

    
43
package com.iver.cit.gvsig.fmap.operation.strategies;
44

    
45
import java.awt.Color;
46
import java.awt.Font;
47
import java.awt.Graphics2D;
48
import java.awt.geom.AffineTransform;
49
import java.awt.geom.NoninvertibleTransformException;
50
import java.awt.geom.Point2D;
51
import java.awt.geom.Rectangle2D;
52
import java.awt.image.BufferedImage;
53
import java.util.List;
54

    
55
import javax.print.attribute.PrintRequestAttributeSet;
56
import javax.print.attribute.standard.PrintQuality;
57

    
58
import org.cresques.cts.ICoordTrans;
59

    
60
import com.hardcode.driverManager.DriverLoadException;
61
import com.hardcode.gdbms.engine.values.NullValue;
62
import com.hardcode.gdbms.engine.values.NumericValue;
63
import com.hardcode.gdbms.engine.values.StringValue;
64
import com.hardcode.gdbms.engine.values.Value;
65
import com.iver.andami.messages.NotificationManager;
66
import com.iver.cit.gvsig.fmap.DriverException;
67
import com.iver.cit.gvsig.fmap.ViewPort;
68
import com.iver.cit.gvsig.fmap.core.FPoint2D;
69
import com.iver.cit.gvsig.fmap.core.FShape;
70
import com.iver.cit.gvsig.fmap.core.IGeometry;
71
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
72
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
73
import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
74
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
75
import com.iver.cit.gvsig.fmap.layers.Annotation_Layer;
76
import com.iver.cit.gvsig.fmap.layers.Annotation_Mapping;
77
import com.iver.cit.gvsig.fmap.layers.FBitSet;
78
import com.iver.cit.gvsig.fmap.layers.FLayer;
79
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
80
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
81
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
82
import com.iver.cit.gvsig.fmap.operations.strategies.DefaultStrategy;
83
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException;
84
import com.iver.cit.gvsig.fmap.rendering.Annotation_Legend;
85
import com.iver.utiles.swing.threads.Cancellable;
86
import com.vividsolutions.jts.geom.Geometry;
87
import com.vividsolutions.jts.geom.IntersectionMatrix;
88

    
89

    
90
/**
91
 * Esta clase se encargar? de dibujar de la forma m?s eficiente los temas de
92
 * anotaciones.
93
 *
94
 * @author Vicente Caballero Navarro
95
 */
96
public class Annotation_Strategy extends DefaultStrategy {
97
    private FSymbol symbolPoint = new FSymbol(FShape.POINT, Color.black);
98
    private Annotation_Layer capa;
99
    private static AffineTransform ati=new AffineTransform();
100
    /**
101
     * Crea un nuevo AnotationStrategy.
102
     *
103
     * @param layer
104
     */
105
    public Annotation_Strategy(FLayer layer) {
106
        super(layer);
107
        capa = (Annotation_Layer) getCapa();
108
        symbolPoint.setSize(5);
109
    }
110

    
111
      public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
112
        Cancellable cancel) {
113
              drawAnnotations(image,g,viewPort,cancel,null);
114
    }
115
      private void drawAnnotations(BufferedImage image, Graphics2D g, ViewPort viewPort,
116
                    Cancellable cancel,PrintRequestAttributeSet properties) {
117
                    BufferedImage bi=new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_ARGB);
118
                    Graphics2D gBi=(Graphics2D)bi.getGraphics();
119
                    Point2D offset=viewPort.getOffset();
120
                    gBi.translate(-offset.getX(),-offset.getY());
121
                    Annotation_Legend l = (Annotation_Legend) capa.getLegend();
122
                    FSymbol sym = (FSymbol) l.getDefaultSymbol();
123

    
124
                    try {
125
                        ReadableVectorial source = capa.getSource();
126
                       // limit the labeling to the visible extent
127
                        FBitSet bs = capa.queryByRect(viewPort.getAdjustedExtent());
128

    
129
                        SelectableDataSource recordSet = source.getRecordset();
130
                        recordSet.start();
131
                        FBitSet bitSet = recordSet.getSelection();
132
                        Annotation_Mapping mapping = ((Annotation_Layer) capa).getAnnotatonMapping();
133
                        int idHeightField = mapping.getColumnHeight();
134
                        int idFontName = mapping.getColumnTypeFont();
135
                        int idFontStyle = mapping.getColumnStyleFont();
136
                        int idRotationField = mapping.getColumnRotate();
137
                        int idFontColor = mapping.getColumnColor();
138
                        int idTextField = mapping.getColumnText();
139

    
140
                        double rotation = 0D;
141
                        float size = sym.getFont().getSize()* (float)FConstant.FONT_HEIGHT_SCALE_FACTOR;
142

    
143
                        String fontName = "Dialog";
144
                        int fontStyle = sym.getFont().getStyle();
145
                        int fontColor = sym.getFontColor().getRGB();
146
                        long t1 = System.currentTimeMillis();
147

    
148
                        for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
149
                            if (cancel.isCanceled()) {
150
                                break;
151
                            }
152

    
153
                            Value[] vv = recordSet.getRow(i);
154

    
155
                            if (idHeightField != -1) {
156
                                // text size is defined in the table
157
                                try {
158
                                    size = (float)(((NumericValue) vv[idHeightField]).doubleValue() * FConstant.FONT_HEIGHT_SCALE_FACTOR);
159
                                } catch (ClassCastException ccEx) {
160
                                    if (!NullValue.class.equals(
161
                                                vv[idHeightField].getClass())) {
162
                                    }
163
                                    continue;
164
                                }
165
                            }
166

    
167
                            if (idFontName != -1) {
168
                                fontName = ((StringValue) vv[idFontName]).toString();
169
                            }
170

    
171
                            if (idFontStyle != -1) {
172
                                fontStyle = ((NumericValue) vv[idFontStyle]).intValue();
173
                            }
174

    
175
                            if (idRotationField != -1) {
176
                                // text rotation is defined in the table
177
                                rotation = ((NumericValue) vv[idRotationField]).doubleValue();
178
                                sym.setRotation((int)rotation);
179
                            }
180

    
181
                            if (idFontColor != -1) {
182
                                // text rotation is defined in the table
183
                                fontColor = ((NumericValue) vv[idFontColor]).intValue();
184
                                sym.setFontColor(new Color(fontColor));
185
                            }
186

    
187
                            if (bitSet.get(i)) {
188
                                sym = (FSymbol) sym.getSymbolForSelection();
189
                            }
190

    
191
                            sym.setFont(new Font(fontName, fontStyle, (int) size));
192
                            source.start();
193
                            IGeometry geom = source.getShape(i);
194
                            source.stop();
195
                            geom.transform(viewPort.getAffineTransform());
196
                            FPoint2D fpPixels=(FPoint2D)geom.getInternalShape();//new FPoint2D(rPixels.getX(),rPixels.getY());
197
                            //Si el tama?o de la fuente est? en unidades de mapa.
198
                            if (!sym.isFontSizeInPixels()){
199
                                    boolean draw=false;
200
                                    Rectangle2D r=capa.getTextWrappingGeometryInPixels(size,vv[idTextField].toString(),rotation,fontName, fontStyle,i,viewPort,geom).getBounds2D();
201
                                    Rectangle2D rPixels=new Rectangle2D.Double(r.getX(),r.getY()+r.getHeight(),r.getWidth(),r.getHeight());
202

    
203
                                    Point2D p=new Point2D.Double(fpPixels.getX(),fpPixels.getY());
204

    
205
                                    if (!capa.isEditing() && l.isAvoidOverLapping()){
206
                                            p=getPoint(bi,rPixels,l.isDelOverLapping());
207
                                            if (p!=null)
208
                                                    draw=true;
209
                                    }else{
210
                                            if (!capa.isEditing() && l.isDelOverLapping()){
211
                                                    if (isOverlapping(bi,rPixels)){
212
                                                            draw=true;
213
                                                    }
214
                                            }else{
215
                                                    draw=true;
216
                                            }
217
                                    }
218
                                    if (draw){
219
                                        if (sym.isShapeVisible()) {
220
                                            symbolPoint.draw(gBi,
221
                                                   ati,
222
                                                   fpPixels);
223
                                        }
224
//                                        g.drawRect((int)rPixels.getX(),(int)rPixels.getY(),(int)rPixels.getWidth(),(int)rPixels.getHeight());
225
//                                        FGraphicUtilities.DrawAnnotation(gBi,
226
//                                                ati, sym, aux[0], metrics, false);
227
                                               DrawAnnotation(gBi,sym, p, vv[idTextField].toString(),viewPort,properties);
228
                                    }
229
                            }else{
230

    
231
                                    // Si el tama?o de la fuente est? en pixels.
232
                                    boolean draw=false;
233
                                    Rectangle2D r=capa.getTextWrappingGeometryInPixels(size,vv[idTextField].toString(),rotation,fontName,fontStyle,i,viewPort,geom).getBounds2D();
234
//                                    g.draw(capa.getTextWrappingGeometryInPixels(size,vv[idTextField].toString(),rotation,fontName,fontStyle,i,viewPort,geom));
235
                                    Rectangle2D rPixels= new Rectangle2D.Double(r.getX(),r.getY()+r.getHeight(),r.getWidth(),r.getHeight());
236

    
237
                                    Point2D pSearch = new Point2D.Double(fpPixels.getX(),fpPixels.getY());
238

    
239
                                    if (!capa.isEditing() && l.isAvoidOverLapping()){
240
                                            pSearch =getPoint(bi,rPixels,l.isDelOverLapping());
241
                                            if (pSearch !=null){
242
                                                    draw=true;
243
                                            }
244
                                    }else{
245
                                            if (!capa.isEditing() && l.isDelOverLapping()){
246
                                                    if (isOverlapping(bi,rPixels)){
247
                                                            draw=true;
248
                                                    }
249
                                            }else{
250
                                                    draw=true;
251
                                            }
252
                                    }
253
                                    if (draw){
254
                                        if (sym.isShapeVisible()) {
255
                                            symbolPoint.draw(gBi,
256
                                                   ati,
257
                                                   fpPixels);
258
                                        }
259
//                                        g.drawRect((int)pSearch.getX(),(int)(pSearch.getY()-rPixels.getHeight()),(int)rPixels.getWidth(),(int)rPixels.getHeight());
260
//                                        FGraphicUtilities.DrawAnnotation(gBi,
261
//                                                ati, sym, aux[0], metrics, false);
262
                                               DrawAnnotation(gBi,sym, pSearch , vv[idTextField].toString(),viewPort,properties);
263
                                    }
264
                            }
265
                            //Al dibujar esta imagen sobre el graphics la trasparencia no puede existir.
266
                            if (i%1000==0){
267
                                     g.drawImage(bi,0,0,null);
268
                            }
269
                        }
270
                        gBi.translate(offset.getX(),offset.getY());
271
                        g.drawImage(bi,(int)offset.getX(),(int)offset.getY(),null);
272
                        System.err.println(System.currentTimeMillis()-t1+"millis");
273
                        recordSet.stop();
274
                    } catch (Exception e) {
275
                        NotificationManager.addError(e);
276
                    }
277
                }
278
    private Point2D getPoint(BufferedImage bi, Rectangle2D rec, boolean b) {
279
                Rectangle2D r=new Rectangle2D.Double(rec.getX(),rec.getY()-rec.getHeight(),rec.getWidth(),rec.getHeight());
280
                if (isOverlapping(bi,r))
281
                        return new Point2D.Double(r.getX(),r.getY()+rec.getHeight());
282

    
283
                r.setFrame(rec.getX(),rec.getY(),rec.getWidth(),rec.getHeight());
284
                if (isOverlapping(bi,r))
285
                        return new Point2D.Double(r.getX(),r.getY()+rec.getHeight());
286

    
287
                r.setFrame(rec.getX()-rec.getWidth(),rec.getY()-rec.getHeight(),rec.getWidth(),rec.getHeight());
288
                if (isOverlapping(bi,r))
289
                        return new Point2D.Double(r.getX(),r.getY()+rec.getHeight());
290

    
291
                r.setFrame(rec.getX()-rec.getWidth(),rec.getY(),rec.getWidth(),rec.getHeight());
292
                if (isOverlapping(bi,r))
293
                        return new Point2D.Double(r.getX(),r.getY()+rec.getHeight());
294

    
295
                r.setFrame(rec.getX()-rec.getWidth()/2,rec.getY(),rec.getWidth(),rec.getHeight());
296
                if (isOverlapping(bi,r))
297
                        return new Point2D.Double(r.getX(),r.getY()+rec.getHeight());
298

    
299
                r.setFrame(rec.getX()-rec.getWidth()/2,rec.getY()-rec.getHeight(),rec.getWidth(),rec.getHeight());
300
                if (isOverlapping(bi,r))
301
                        return new Point2D.Double(r.getX(),r.getY()+rec.getHeight());
302

    
303
                r.setFrame(rec.getX(),rec.getY()+rec.getHeight()/2,rec.getWidth(),rec.getHeight());
304
                if (isOverlapping(bi,r))
305
                        return new Point2D.Double(r.getX(),r.getY()+rec.getHeight());
306

    
307
                if (!b)
308
                        return new Point2D.Double(rec.getX(),rec.getY());
309
                else
310
                        return null;
311
        }
312

    
313
        private boolean isOverlapping(BufferedImage bi, Rectangle2D rPixels) {
314
        for (int i=(int)rPixels.getX();i<rPixels.getMaxX();i++){
315
            for (int j=(int)rPixels.getY();j<rPixels.getMaxY();j++){
316
                if (i<0 || j<0 || bi.getWidth()<i+1 || bi.getHeight()<j+1)
317
                    continue;
318
                if (bi.getRGB(i,j)!=0){
319
                    return false;
320
                }
321
            }
322
        }
323
        return true;
324
    }
325

    
326
    /*
327
     * (non-Javadoc)
328
     *
329
     * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByShape(com.iver.cit.gvsig.fmap.core.IGeometry,
330
     *      int)
331
     */
332
    public FBitSet queryByShape(IGeometry g, int relationship)
333
        throws DriverException, VisitException {
334
        // Si hay un ?ndice espacial, lo usamos para hacer el query.
335
        FLyrVect lyr = (FLyrVect) capa;
336

    
337
        // if (lyr.getSpatialIndex() == null)
338
        if (lyr.getISpatialIndex() == null) {
339
            return super.queryByShape(g, relationship);
340
        }
341

    
342
        long t1 = System.currentTimeMillis();
343
        ReadableVectorial va = lyr.getSource();
344
        ICoordTrans ct = lyr.getCoordTrans();
345
        Rectangle2D bounds = g.getBounds2D();
346

    
347
        // Coordinate c1 = new Coordinate(bounds.getMinX(), bounds.getMinY());
348
        // Coordinate c2 = new Coordinate(bounds.getMaxX(), bounds.getMaxY());
349
        // Envelope env = new Envelope(c1, c2);
350
        // List lstRecs = lyr.getSpatialIndex().query(env);
351
        List lstRecs = lyr.getISpatialIndex().query(bounds);
352
        Integer idRec;
353
        FBitSet bitset = new FBitSet();
354
        Geometry jtsShape = g.toJTSGeometry();
355
        IntersectionMatrix m;
356
        int index;
357

    
358
        try {
359
            va.start();
360

    
361
            // Annotation_Legend aLegend=(Annotation_Legend)capa.getLegend();
362
            for (int i = 0; i < lstRecs.size(); i++) {
363
                idRec = (Integer) lstRecs.get(i);
364
                index = idRec.intValue();
365

    
366
                IGeometry geom = va.getShape(index);
367

    
368
                // FSymbol symbol=(FSymbol)aLegend.getSymbol(index);
369
                // IGeometry geom=aLegend.getTextWrappingGeometry(symbol,index);
370
                // IGeometry
371
                // geom=getGeometry(((Annotation_Layer)capa).getLabel(index).getBoundBox());
372
                if (ct != null) {
373
                    geom.reProject(ct);
374
                }
375

    
376
                Geometry jtsGeom = geom.toJTSGeometry();
377

    
378
                switch (relationship) {
379
                case CONTAINS:
380
                    m = jtsShape.relate(jtsGeom);
381

    
382
                    if (m.isContains()) {
383
                        bitset.set(index, true);
384
                    }
385

    
386
                    break;
387

    
388
                case CROSSES:
389
                    m = jtsShape.relate(jtsGeom);
390

    
391
                    if (m.isCrosses(jtsGeom.getDimension(),
392
                                jtsShape.getDimension())) {
393
                        bitset.set(index, true);
394
                    }
395

    
396
                    break;
397

    
398
                case DISJOINT:
399

    
400
                    // TODO: CREO QUE EL DISJOINT NO SE PUEDE METER AQUI
401
                    m = jtsShape.relate(jtsGeom);
402

    
403
                    if (m.isDisjoint()) {
404
                        bitset.set(index, true);
405
                    }
406

    
407
                    break;
408

    
409
                case EQUALS:
410
                    m = jtsShape.relate(jtsGeom);
411

    
412
                    if (m.isEquals(jtsGeom.getDimension(),
413
                                jtsShape.getDimension())) {
414
                        bitset.set(index, true);
415
                    }
416

    
417
                    break;
418

    
419
                case INTERSECTS:
420
                    m = jtsShape.relate(jtsGeom);
421

    
422
                    if (m.isIntersects()) {
423
                        bitset.set(index, true);
424
                    }
425

    
426
                    break;
427

    
428
                case OVERLAPS:
429
                    m = jtsShape.relate(jtsGeom);
430

    
431
                    if (m.isOverlaps(jtsGeom.getDimension(),
432
                                jtsShape.getDimension())) {
433
                        bitset.set(index, true);
434
                    }
435

    
436
                    break;
437

    
438
                case TOUCHES:
439
                    m = jtsShape.relate(jtsGeom);
440

    
441
                    if (m.isTouches(jtsGeom.getDimension(),
442
                                jtsShape.getDimension())) {
443
                        bitset.set(index, true);
444
                    }
445

    
446
                    break;
447

    
448
                case WITHIN:
449
                    m = jtsShape.relate(jtsGeom);
450

    
451
                    if (m.isWithin()) {
452
                        bitset.set(index, true);
453
                    }
454

    
455
                    break;
456
                }
457
            }
458

    
459
            va.stop();
460
        } catch (DriverIOException e) {
461
                throw new DriverException(e);
462
        }
463

    
464
        long t2 = System.currentTimeMillis();
465

    
466
        // logger.debug("queryByShape optimizado sobre la capa " + lyr.getName()
467
        // + ". " + (t2-t1) + " mseg.");
468
        return bitset;
469
    }
470

    
471
    /**
472
     * DOCUMENT ME!
473
     *
474
     * @param rect DOCUMENT ME!
475
     *
476
     * @return DOCUMENT ME!
477
     *
478
     * @throws DriverException DOCUMENT ME!
479
     */
480
    public FBitSet queryByRect(Rectangle2D rect) throws DriverException {
481
        // Si hay un ?ndice espacial, lo usamos para hacer el query.
482
        Annotation_Layer lyr = (Annotation_Layer) capa;
483
        ReadableVectorial va = lyr.getSource();
484
        ICoordTrans ct = lyr.getCoordTrans();
485
        Rectangle2D bounds = rect;
486
        // if (lyr.getSpatialIndex() == null)
487
        if (lyr.getISpatialIndex() == null) {
488
            return super.queryByRect(rect);
489
        }
490
        // Coordinate c1 = new Coordinate(bounds.getMinX(), bounds.getMinY());
491
        // Coordinate c2 = new Coordinate(bounds.getMaxX(), bounds.getMaxY());
492
        // Envelope env = new Envelope(c1, c2);
493
        //
494
        // List lstRecs = lyr.getSpatialIndex().query(env);
495
        // azabala
496
        List lstRecs = lyr.getISpatialIndex().query(bounds);
497
        Integer idRec;
498
        FBitSet bitset = new FBitSet();
499
        int index;
500

    
501
        try {
502
            va.start();
503

    
504
            DriverAttributes attr = va.getDriverAttributes();
505
            boolean bMustClone = false;
506

    
507
            if (attr != null) {
508
                if (attr.isLoadedInMemory()) {
509
                    bMustClone = attr.isLoadedInMemory();
510
                }
511
            }
512
            ViewPort vp=getCapa().getMapContext().getViewPort();
513
            SelectableDataSource sds=va.getRecordset();
514
            // Annotation_Legend aLegend=(Annotation_Legend)capa.getLegend();
515
            for (int i = 0; i < lstRecs.size(); i++) {
516
                idRec = (Integer) lstRecs.get(i);
517
                index = idRec.intValue();
518

    
519
                Annotation_Mapping mapping = ((Annotation_Layer) capa).getAnnotatonMapping();
520
                NumericValue vRotation = (NumericValue) sds.getFieldValue(index,
521
                        mapping.getColumnRotate());
522
                NumericValue vHeight = (NumericValue) sds.getFieldValue(index,
523
                        mapping.getColumnHeight());
524
                NumericValue vStyle = (NumericValue) sds.getFieldValue(index,mapping.getColumnStyleFont());
525
                StringValue vType = (StringValue) sds.getFieldValue(index,mapping.getColumnTypeFont());
526
                Value vText = sds.getFieldValue(index,
527
                        mapping.getColumnText());
528
                va.start();
529
                IGeometry geom = va.getShape(i);
530
                va.stop();
531
                geom.transform(vp.getAffineTransform());
532
                IGeometry geom1 = ((Annotation_Layer) capa).getTextWrappingGeometryInPixels(vHeight.floatValue(),
533
                        vText.toString(), vRotation.doubleValue(),vType.getValue(),vStyle.intValue(), index, vp,geom);
534
                geom1.transform(vp.getAffineTransform().createInverse());
535
                if (ct != null) {
536
                    if (bMustClone) {
537
                        geom1 = geom1.cloneGeometry();
538
                    }
539

    
540
                    geom1.reProject(ct);
541
                }
542

    
543
                if (geom1.intersects(rect)) {
544
                    bitset.set(index, true);
545
                }
546
            }
547

    
548
            va.stop();
549
        } catch (DriverIOException e) {
550
            throw new DriverException(e);
551
        } catch (DriverLoadException e) {
552
                throw new DriverException(e);
553
        } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
554
                throw new DriverException(e);
555
        } catch (NoninvertibleTransformException e) {
556
                throw new DriverException(e);
557
                }
558

    
559
        return bitset;
560
    }
561

    
562
    /*
563
     * (non-Javadoc)
564
     *
565
     * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByPoint(java.awt.geom.Point2D,
566
     *      double)
567
     */
568
    public FBitSet queryByPoint(Point2D p, double tolerance)
569
        throws DriverException {
570
        // TODO: OJO!!!!. Est? implementado como un rectangulo.
571
        // Lo correcto deber?a ser calculando las distancias reales
572
        // es decir, con un c?rculo.
573
        Rectangle2D recPoint = new Rectangle2D.Double(p.getX() -
574
                (tolerance / 2), p.getY() - (tolerance / 2), tolerance,
575
                tolerance);
576

    
577
        return queryByRect(recPoint);
578
    }
579

    
580
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
581
        PrintRequestAttributeSet properties) throws DriverException {
582
        capa.beforePrinting(properties);
583
        drawAnnotations(null,g, viewPort, cancel, properties);
584
        capa.afterPrinting();
585
    }
586
    private static void DrawAnnotation(Graphics2D g2,
587
                    FSymbol theSymbol,Point2D pAux, String text,ViewPort viewPort,PrintRequestAttributeSet properties) {
588
                    float x;
589
                    float y;
590
                    // Las etiquetas que pongamos a nulo ser? porque no la queremos dibujar.
591
                    // ?til para cuando queramos eliminar duplicados.
592
                    if (text == null) {
593
                            return;
594
                    }
595
                    int size=theSymbol.getFont().getSize();
596
                    double resolutionPrinting=0;
597
                    if (!theSymbol.isFontSizeInPixels()){
598
                            size=viewPort.fromMapDistance(size);
599
                    }
600
                    if (properties!=null){
601
                            PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
602
                            if (resolution.equals(PrintQuality.NORMAL)){
603
                                    resolutionPrinting=300/72;
604
                            }else if (resolution.equals(PrintQuality.HIGH)){
605
                                    resolutionPrinting=600/72;
606
                            }else if (resolution.equals(PrintQuality.DRAFT)){
607
                                    resolutionPrinting=72/72;
608
                            }
609
                            size=(int)(size*resolutionPrinting);
610
                    }
611
                    Font font=new Font(theSymbol.getFont().getName(),theSymbol.getFont().getStyle(),size);
612
                           g2.setFont(font);
613
                    g2.setColor(theSymbol.getFontColor());
614
                    AffineTransform ant = g2.getTransform();
615

    
616
                    x = (float) pAux.getX();
617
                    y = (float) pAux.getY();
618

    
619
                    AffineTransform Tx = (AffineTransform) ant.clone();
620
                    Tx.translate(x, y); // S3: final translation
621
                    Tx.rotate(Math.toRadians(-theSymbol.getRotation())); // S2: rotate around anchor
622
                    g2.setTransform(Tx);
623
                        g2.drawString(text, 0, 0);
624
                    g2.setTransform(ant);
625
            }
626

    
627
}