Statistics
| Revision:

gvsig-lrs / org.gvsig.lrs / trunk / org.gvsig.lrs / org.gvsig.lrs.app / org.gvsig.lrs.app.mainplugin / src / main / java / org / gvsig / lrs / app / showmeasures / ShowMeasuresExtension.java @ 800

History | View | Annotate | Download (20 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2015 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.lrs.app.showmeasures;
24

    
25
import java.awt.Color;
26
import java.awt.event.ActionEvent;
27
import java.awt.event.ActionListener;
28
import java.awt.event.ComponentEvent;
29
import java.awt.event.ComponentListener;
30
import java.text.DecimalFormat;
31
import java.util.ArrayList;
32
import java.util.Iterator;
33
import java.util.List;
34

    
35
import javax.swing.JOptionPane;
36

    
37
import org.apache.commons.lang3.StringUtils;
38
import org.cresques.cts.ICoordTrans;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

    
42
import org.gvsig.andami.IconThemeHelper;
43
import org.gvsig.andami.plugins.Extension;
44
import org.gvsig.app.ApplicationLocator;
45
import org.gvsig.app.ApplicationManager;
46
import org.gvsig.app.project.documents.view.ViewDocument;
47
import org.gvsig.app.project.documents.view.gui.IView;
48
import org.gvsig.fmap.dal.DataSet;
49
import org.gvsig.fmap.dal.exception.DataException;
50
import org.gvsig.fmap.dal.feature.Feature;
51
import org.gvsig.fmap.dal.feature.FeatureSelection;
52
import org.gvsig.fmap.dal.feature.FeatureStore;
53
import org.gvsig.fmap.geom.Geometry;
54
import org.gvsig.fmap.geom.GeometryLocator;
55
import org.gvsig.fmap.geom.GeometryManager;
56
import org.gvsig.fmap.geom.aggregate.MultiLine;
57
import org.gvsig.fmap.geom.exception.CreateGeometryException;
58
import org.gvsig.fmap.geom.primitive.Line;
59
import org.gvsig.fmap.geom.primitive.Point;
60
import org.gvsig.fmap.mapcontext.MapContext;
61
import org.gvsig.fmap.mapcontext.MapContextLocator;
62
import org.gvsig.fmap.mapcontext.layers.FLayer;
63
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
64
import org.gvsig.fmap.mapcontext.layers.vectorial.GraphicLayer;
65
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
66
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
67
import org.gvsig.gui.beans.ProgressDialog;
68
import org.gvsig.lrs.lib.api.LrsAlgorithm;
69
import org.gvsig.lrs.lib.api.LrsAlgorithmsLocator;
70
import org.gvsig.lrs.lib.api.LrsAlgorithmsManager;
71
import org.gvsig.lrs.lib.api.LrsShowMeasuresAlgorithmParams;
72
import static org.gvsig.lrs.lib.api.LrsShowMeasuresAlgorithmParams.LRS_SHOWMEASURES_KILOMETER;
73
import static org.gvsig.lrs.lib.api.LrsShowMeasuresAlgorithmParams.LRS_SHOWMEASURES_METER;
74
import org.gvsig.lrs.lib.api.exceptions.LrsGettingParametersException;
75
import org.gvsig.lrs.lib.api.exceptions.LrsNeededParameterException;
76
import org.gvsig.lrs.swing.api.JLrsAlgorithmParams;
77
import org.gvsig.lrs.swing.api.JLrsProgressDialog;
78
import org.gvsig.lrs.swing.api.LrsAlgorithmsSwingLocator;
79
import org.gvsig.lrs.swing.api.LrsAlgorithmsSwingManager;
80
import org.gvsig.lrs.swing.impl.JLrsShowMeasuresParamsController;
81
import org.gvsig.lrs.swing.impl.JLrsUtils;
82
import org.gvsig.symbology.SymbologyLocator;
83
import org.gvsig.symbology.SymbologyManager;
84
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.ISimpleTextSymbol;
85
import org.gvsig.tools.ToolsLocator;
86
import org.gvsig.tools.dispose.DisposableIterator;
87
import org.gvsig.tools.i18n.I18nManager;
88
import org.gvsig.tools.locator.LocatorException;
89
import org.gvsig.tools.swing.api.ToolsSwingLocator;
90
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
91
import org.gvsig.tools.task.SimpleTaskStatus;
92

    
93
/**
94
 * @author dmartinez
95
 *
96
 */
97
public class ShowMeasuresExtension extends Extension implements ComponentListener {
98

    
99
    private static final Logger logger = LoggerFactory.getLogger(ShowMeasuresExtension.class);
100

    
101
    public static final String SHOW_MEASURES_GRAPHICS_ID = "ShowMeasures";
102

    
103
    private JLrsShowMeasuresParamsController panel;
104

    
105

    
106
    /*
107
     * (non-Javadoc)
108
     *
109
     * @see org.gvsig.andami.plugins.IExtension#execute(java.lang.String)
110
     */
111
    public void execute(String actionCommand) {
112
        if (StringUtils.equalsIgnoreCase(actionCommand, "show-measures")) {
113
            IView view = getActiveView();
114
            final MapContext mapContext = view.getMapControl().getMapContext();
115
            final GraphicLayer graphics = mapContext.getGraphicsLayer();
116

    
117
            final FLyrVect activeLayer = getActiveLayer(view);
118

    
119
            final WindowManager winManager = ToolsSwingLocator.getWindowManager();
120

    
121
            final LrsAlgorithmsSwingManager manager = LrsAlgorithmsSwingLocator.getLrsAlgorithmsSwingManager();
122

    
123
            final I18nManager i18nManager = ToolsLocator.getI18nManager();
124

    
125
            try {
126
                panel =
127
                    (JLrsShowMeasuresParamsController) manager.createJLrsShowMeasuresAlgorithmParameters(activeLayer,
128
                        null);
129
                panel.addComponentListener(this);
130
            } catch (LrsNeededParameterException e2) {
131
                logger.error("Error creating panel", e2);
132
                JOptionPane.showMessageDialog(
133
                    null,
134
                    new StringBuilder().append(i18nManager.getTranslation("error_creating_panel")).append(":")
135
                        .append(e2.getLocalizedMessage()), i18nManager.getTranslation("error"),
136
                    JOptionPane.ERROR_MESSAGE);
137
                return;
138
            }
139
            panel.setVisibleAceptCancel(true);
140
            panel.addActionListener(new ActionListener() {
141

    
142
                public void actionPerformed(ActionEvent e) {
143
                    JLrsAlgorithmParams panel = (JLrsAlgorithmParams) e.getSource();
144
                    if (panel.isCanceled()) {
145
                        return;
146
                    }
147
                    LrsShowMeasuresAlgorithmParams params = null;
148
                    try {
149
                        params = (LrsShowMeasuresAlgorithmParams) panel.getParams();
150
                    } catch (LrsGettingParametersException e1) {
151
                        logger.error("Error getting parameters", e1);
152
                        JOptionPane.showMessageDialog(
153
                            null,
154
                            new StringBuilder().append(i18nManager.getTranslation("error_getting_parameters"))
155
                                .append(":").append(e1.getLocalizedMessage()), i18nManager.getTranslation("error"),
156
                            JOptionPane.ERROR_MESSAGE);
157
                        return;
158
                    } catch (LrsNeededParameterException e1) {
159
                        logger.warn("Error getting parameters", e1);
160
                        JOptionPane.showMessageDialog(null, i18nManager.getTranslation(e1.getMessage()),
161
                            i18nManager.getTranslation("warning"), JOptionPane.WARNING_MESSAGE);
162
                        return;
163
                    }
164
                    final SimpleTaskStatus taskStatus =
165
                        ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
166
                            i18nManager.getTranslation("progress"));
167

    
168
                    final JLrsProgressDialog progressDialog = manager.createJLrsProgressDialog(taskStatus);
169

    
170
                    winManager.showWindow(progressDialog.asJComponent(), i18nManager.getTranslation("show_measures"),
171
                        WindowManager.MODE.WINDOW);
172

    
173
                    final double distance = params.getDistance();
174
                    final int units = params.getUnits();
175

    
176
                    Thread task = new Thread(new Runnable() {
177

    
178
                        public void run() {
179
                            try {
180
                                showMeasures(graphics, activeLayer, distance, units, taskStatus);
181
                                mapContext.invalidate();
182
                                if(!taskStatus.isRunning() && progressDialog.asJComponent().isVisible()){
183
                                    progressDialog.asJComponent().setVisible(false);
184
                                }
185
                            } catch (Exception e) {
186
                                logger.error("Error showing measures", e);
187
                                String message = e.getMessage();
188
                                if (e.getCause() != null) {
189
                                    message = e.getCause().getMessage();
190
                                }
191
                                JOptionPane.showMessageDialog(progressDialog.asJComponent(), message,
192
                                    i18nManager.getTranslation("show_measures"), JOptionPane.ERROR_MESSAGE);
193
                            }
194
                        }
195
                    });
196
                    task.start();
197

    
198
                }
199
            });
200
            winManager.showWindow(panel.asJComponent(), i18nManager.getTranslation("show_measures"),
201
                WindowManager.MODE.WINDOW);
202
        }
203
    }
204

    
205
    /*
206
     * (non-Javadoc)
207
     *
208
     * @see org.gvsig.andami.plugins.IExtension#initialize()
209
     */
210
    public void initialize() {
211
        registerIcons();
212
    }
213

    
214
    /*
215
     * (non-Javadoc)
216
     *
217
     * @see org.gvsig.andami.plugins.IExtension#isEnabled()
218
     */
219
    public boolean isEnabled() {
220
        IView view = getActiveView();
221
        FLyrVect activeLayer = getActiveLayer(view);
222
        if (panel == null && activeLayer != null) {
223
            return JLrsUtils.hasMLayersWithSelectedFeatures(activeLayer);
224
        }
225
        return false;
226
    }
227

    
228
    /*
229
     * (non-Javadoc)
230
     *
231
     * @see org.gvsig.andami.plugins.IExtension#isVisible()
232
     */
233
    public boolean isVisible() {
234
        ApplicationManager application = ApplicationLocator.getManager();
235

    
236
        return application.getActiveComponent(ViewDocument.class) != null;
237
    }
238

    
239
    private void registerIcons() {
240
        IconThemeHelper.registerIcon("lrs", "pk_green", this);
241
    }
242

    
243
    /*
244
     * Shows measurements along the selected features in a layer with a fixed spacing
245
     *
246
     */
247
    private void showMeasures(GraphicLayer graphics, FLyrVect layer, double distance, int units, SimpleTaskStatus taskStatus)
248
        throws DataException, CreateGeometryException, LocatorException {
249
        FeatureStore featureStore = layer.getFeatureStore();
250
        FeatureSelection selection = featureStore.getFeatureSelection();
251
        if (selection != null && !selection.isEmpty()) {
252
            long range = getRange(selection);
253
            taskStatus.setRangeOfValues(0, range);
254
            long curValue = 0;
255
            taskStatus.setCurValue(curValue);
256
            DisposableIterator it = selection.fastIterator();
257
            ICoordTrans ct = layer.getCoordTrans();
258
            while (it.hasNext()) {
259
                Feature feature = (Feature) it.next();
260
                Geometry geometry = feature.getDefaultGeometry();
261
                if (geometry instanceof Line) {
262
                    curValue = showLineMeasures(graphics, curValue, (Line) geometry, distance, units, ct);
263
                    taskStatus.setCurValue(curValue);
264
                } else if (geometry instanceof MultiLine) {
265
                    MultiLine multiLine = (MultiLine) geometry;
266
                    int primitives = multiLine.getPrimitivesNumber();
267
                    for (int i = 0; i < primitives; i++) {
268
                        curValue = showLineMeasures(graphics, curValue, (Line) multiLine.getPrimitiveAt(i), distance, units, ct);
269
                        taskStatus.setCurValue(curValue);
270
                    }
271
                }
272
            }
273
            it.dispose();
274
        }
275
        taskStatus.terminate();
276
    }
277

    
278
    /**
279
     * Shows measurements along a line with a fixed spacing
280
     *
281
     * @param curValue
282
     * @param ct2
283
     * @param taskStatus
284
     * @param geometry
285
     * @return
286
     * @throws LocatorException
287
     * @throws CreateGeometryException
288
     */
289
    private long showLineMeasures(GraphicLayer graphics, long curValue, Line line, Double distance, int units, ICoordTrans ct) throws CreateGeometryException, LocatorException {
290
        long value = curValue;
291
        for (int i = 0; i < line.getNumVertices() - 1; i++) {
292
            value++;
293
            Point vertex = (Point) line.getVertex(i);
294
            double m0 = vertex.getCoordinateAt(vertex.getDimension() - 1);
295

    
296
            double div = m0 / distance;
297
            if (isMultiple(m0, distance)) {
298
                showMeasure(graphics, vertex, m0, units, ct);
299
            }
300
            Point nextVertex = line.getVertex(i + 1);
301
            double m1 = nextVertex.getCoordinateAt(vertex.getDimension() - 1);
302
            List<Double> multiples = calculateMultiplesBetweenTwoValues(distance, m0, m1);
303
            for (Iterator iterator = multiples.iterator(); iterator.hasNext();) {
304
                Double m = (Double) iterator.next();
305
                Point point = getPointWithMBetweenTwoVertex(m, vertex, nextVertex);
306
                showMeasure(graphics, point, m, units, ct);
307
            }
308
        }
309
        value++;
310
        return value;
311
    }
312

    
313
    /**
314
     * Show the m in the point p on the graphicLayer
315
     *
316
     * @param m
317
     * @param ct
318
     */
319
    private void showMeasure(GraphicLayer graphics, Point p, double m, int units, ICoordTrans ct) {
320

    
321
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
322
        SymbolManager symbolManager = MapContextLocator.getSymbolManager();
323

    
324
        ISymbol markerSymbol = symbolManager.createSymbol(Geometry.TYPES.POINT, Color.RED);
325
        ISimpleTextSymbol textSymbol = getTextSymbol();
326
        DecimalFormat formato = new DecimalFormat("0.000");
327
        double theMeasure = m;
328
        if(units == LRS_SHOWMEASURES_METER){
329
            theMeasure = m/1000;
330
        }
331
        
332
        String text = formato.format(theMeasure);
333
        if(units == LRS_SHOWMEASURES_METER || units == LRS_SHOWMEASURES_KILOMETER){
334
            text = text.replace(",", " + ");
335
        }
336

    
337
        textSymbol.setText(text);
338
        int idMarkerSymbol = graphics.addSymbol(markerSymbol);
339
        int idTextSymbol = graphics.addSymbol(textSymbol);
340
        Point clonedPoint = (Point) p.cloneGeometry();
341
        clonedPoint.reProject(ct);
342
        graphics.addGraphic(SHOW_MEASURES_GRAPHICS_ID, clonedPoint, idTextSymbol);
343
        graphics.addGraphic(SHOW_MEASURES_GRAPHICS_ID, clonedPoint, idMarkerSymbol);
344
    }
345

    
346
    /*
347
     * Creates a text symbol to be used in showMeasure
348
     */
349
    private ISimpleTextSymbol getTextSymbol(){
350
        SymbologyManager symbologyManager = SymbologyLocator.getSymbologyManager();
351
        ISimpleTextSymbol textSymbol = symbologyManager.createSimpleTextSymbol();
352
        textSymbol.setFontSize(10);
353
        return textSymbol;
354
    }
355

    
356
    /**
357
     * Dados dos puntos con coordenada M, calcula el punto correspondiente a la m dada.
358
     *
359
     * @param m
360
     * @param vertex
361
     * @param nextVertex
362
     * @return
363
     * @throws LocatorException
364
     * @throws CreateGeometryException
365
     */
366
    private Point getPointWithMBetweenTwoVertex(Double m, Point vertex, Point nextVertex) throws CreateGeometryException, LocatorException {
367
        Point point = (Point)GeometryLocator.getGeometryManager().create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2D);
368
        point.setX(
369
            getCoordinateBetweenTwoValues(
370
                m,
371
                vertex.getCoordinateAt(vertex.getDimension()-1),
372
                nextVertex.getCoordinateAt(vertex.getDimension()-1),
373
                vertex.getX(),
374
                nextVertex.getX()));
375
        point.setY(
376
            getCoordinateBetweenTwoValues(
377
                m,
378
                vertex.getCoordinateAt(vertex.getDimension()-1),
379
                nextVertex.getCoordinateAt(vertex.getDimension()-1),
380
                vertex.getY(),
381
                nextVertex.getY()));
382

    
383
        return point;
384
    }
385

    
386
    /**
387
     * Dados los valores en una dimensi?n de dos puntos y sus "m" correspondientes,
388
     * calcula el valor en esa dimensi?n correspondiente a la "m" dada.
389
     *
390
     * @param m
391
     * @param m1
392
     * @param m2
393
     * @param v1
394
     * @param v2
395
     * @return
396
     */
397
    private double getCoordinateBetweenTwoValues(double m, double m1, double m2, double v1, double v2) {
398
        if (v1==v2){
399
            return Double.POSITIVE_INFINITY;
400
        }
401
         return ((v2-v1)*(m-m1)/(m2-m1))+v1;
402
    }
403

    
404
    /**
405
     * Calcula los m?ltiplos de "distance" que existen entre los valores "value0" y "value1"
406
     *
407
     * @param distance
408
     * @param value0
409
     * @param value1
410
     * @return
411
     */
412
    private List<Double> calculateMultiplesBetweenTwoValues(Double distance, double value0, double value1) {
413
        List<Double> result = new ArrayList<Double>();
414

    
415
        double v0;
416
        double v1;
417
        if(value0<=value1){
418
            v0 = value0;
419
            v1 = value1;
420
        } else {
421
            v0 = value1;
422
            v1 = value0;
423
        }
424

    
425
        int factor1 = (int) Math.ceil(v0/distance);
426
        int factor2 = (int) Math.floor(v1/distance);
427
            for (int factor = factor1; factor <= factor2; factor++) {
428
                double m = factor * distance;
429
                if(m>=v0 && m<=v1){
430
                    result.add(m);
431
                }
432
            }
433
        return result;
434
    }
435

    
436

    
437
    /**
438
     * Calcula si el valor del par?metro n es m?ltiplo del valor del par?metro d
439
     * @param n
440
     * @param d
441
     */
442
    private boolean isMultiple(double n, double d) {
443
        double div = n / d;
444
        return ((div - (int) div) < 0.000001);
445
    }
446

    
447
    /**
448
     * @param selection
449
     * @throws DataException
450
     */
451
    private long getRange(FeatureSelection selection) throws DataException {
452
        long range = 0;
453
        DisposableIterator it = selection.fastIterator();
454
        while (it.hasNext()) {
455
            Feature feature = (Feature) it.next();
456
            Geometry geometry = feature.getDefaultGeometry();
457
            if (geometry instanceof Line) {
458
                range += ((Line) geometry).getNumVertices();
459
            } else if (geometry instanceof MultiLine) {
460
                MultiLine multiLine = (MultiLine) geometry;
461
                int primitives = multiLine.getPrimitivesNumber();
462
                for (int i = 0; i < primitives; i++) {
463
                    range += ((Line) multiLine.getPrimitiveAt(i)).getNumVertices();
464
                }
465
            }
466
        }
467
        it.dispose();
468
        return range;
469
    }
470

    
471
    private IView getActiveView() {
472
        ApplicationManager application = ApplicationLocator.getManager();
473
        IView view = (IView) application.getActiveComponent(ViewDocument.class);
474
        return view;
475
    }
476

    
477
    private FLyrVect getActiveLayer(IView vista) {
478
        if (vista != null) {
479
            ViewDocument viewDocument = vista.getViewDocument();
480
            FLayer[] actives = viewDocument.getMapContext().getLayers().getActives();
481

    
482
            if ((actives.length == 1) && (actives[0] instanceof FLyrVect)) {
483
                return (FLyrVect) actives[0];
484
            }
485
        }
486
        return null;
487
    }
488

    
489
    /*
490
     * (non-Javadoc)
491
     *
492
     * @see java.awt.event.ComponentListener#componentResized(java.awt.event.
493
     * ComponentEvent)
494
     */
495
    public void componentResized(ComponentEvent e) {
496
        // TODO Auto-generated method stub
497

    
498
    }
499

    
500
    /*
501
     * (non-Javadoc)
502
     *
503
     * @see
504
     * java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent
505
     * )
506
     */
507
    public void componentMoved(ComponentEvent e) {
508
        // TODO Auto-generated method stub
509

    
510
    }
511

    
512
    /*
513
     * (non-Javadoc)
514
     *
515
     * @see
516
     * java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent
517
     * )
518
     */
519
    public void componentShown(ComponentEvent e) {
520
        // TODO Auto-generated method stub
521

    
522
    }
523

    
524
    /*
525
     * (non-Javadoc)
526
     *
527
     * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.
528
     * ComponentEvent)
529
     */
530
    public void componentHidden(ComponentEvent e) {
531
        panel = null;
532
    }
533
}