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 @ 43

History | View | Annotate | Download (19.3 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 org.gvsig.lrs.lib.api.exceptions.LrsGettingParametersException;
73
import org.gvsig.lrs.lib.api.exceptions.LrsNeededParameterException;
74
import org.gvsig.lrs.swing.api.JLrsAlgorithmParams;
75
import org.gvsig.lrs.swing.api.JLrsProgressDialog;
76
import org.gvsig.lrs.swing.api.LrsAlgorithmsSwingLocator;
77
import org.gvsig.lrs.swing.api.LrsAlgorithmsSwingManager;
78
import org.gvsig.lrs.swing.impl.JLrsShowMeasuresParamsController;
79
import org.gvsig.lrs.swing.impl.JLrsUtils;
80
import org.gvsig.symbology.SymbologyLocator;
81
import org.gvsig.symbology.SymbologyManager;
82
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.ISimpleTextSymbol;
83
import org.gvsig.tools.ToolsLocator;
84
import org.gvsig.tools.dispose.DisposableIterator;
85
import org.gvsig.tools.i18n.I18nManager;
86
import org.gvsig.tools.locator.LocatorException;
87
import org.gvsig.tools.swing.api.ToolsSwingLocator;
88
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
89
import org.gvsig.tools.task.SimpleTaskStatus;
90

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

    
97
    private static final Logger logger = LoggerFactory.getLogger(ShowMeasuresExtension.class);
98

    
99
    public static final String SHOW_MEASURES_GRAPHICS_ID = "ShowMeasures";
100

    
101
    private JLrsShowMeasuresParamsController panel;
102

    
103

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

    
115
            final FLyrVect activeLayer = getActiveLayer(view);
116

    
117
            final WindowManager winManager = ToolsSwingLocator.getWindowManager();
118

    
119
            final LrsAlgorithmsSwingManager manager = LrsAlgorithmsSwingLocator.getLrsAlgorithmsSwingManager();
120

    
121
            final I18nManager i18nManager = ToolsLocator.getI18nManager();
122

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

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

    
166
                    final JLrsProgressDialog progressDialog = manager.createJLrsProgressDialog(taskStatus);
167

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

    
171
                    final double distance = params.getDistance();
172

    
173
                    Thread task = new Thread(new Runnable() {
174

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

    
195
                }
196
            });
197
            winManager.showWindow(panel.asJComponent(), i18nManager.getTranslation("show_measures"),
198
                WindowManager.MODE.WINDOW);
199
        }
200
    }
201

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

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

    
225
    /*
226
     * (non-Javadoc)
227
     *
228
     * @see org.gvsig.andami.plugins.IExtension#isVisible()
229
     */
230
    public boolean isVisible() {
231
        return true;
232
    }
233

    
234
    private void registerIcons() {
235
        IconThemeHelper.registerIcon("lrs", "pk_green", this);
236
    }
237

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

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

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

    
308
    /**
309
     * Show the m in the point p on the graphicLayer
310
     *
311
     * @param m
312
     * @param ct
313
     */
314
    private void showMeasure(GraphicLayer graphics, Point p, double m, ICoordTrans ct) {
315

    
316
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
317
        SymbolManager symbolManager = MapContextLocator.getSymbolManager();
318

    
319
        ISymbol markerSymbol = symbolManager.createSymbol(Geometry.TYPES.POINT, Color.RED);
320
        ISimpleTextSymbol textSymbol = getTextSymbol();
321

    
322
        DecimalFormat formato = new DecimalFormat("0.000");
323
        textSymbol.setText(formato.format(m).replace(",", " + "));
324
        int idMarkerSymbol = graphics.addSymbol(markerSymbol);
325
        int idTextSymbol = graphics.addSymbol(textSymbol);
326
        Point clonedPoint = (Point) p.cloneGeometry();
327
        clonedPoint.reProject(ct);
328
        graphics.addGraphic(SHOW_MEASURES_GRAPHICS_ID, clonedPoint, idTextSymbol);
329
        graphics.addGraphic(SHOW_MEASURES_GRAPHICS_ID, clonedPoint, idMarkerSymbol);
330
    }
331

    
332
    /*
333
     * Creates a text symbol to be used in showMeasure
334
     */
335
    private ISimpleTextSymbol getTextSymbol(){
336
        SymbologyManager symbologyManager = SymbologyLocator.getSymbologyManager();
337
        ISimpleTextSymbol textSymbol = symbologyManager.createSimpleTextSymbol();
338
        textSymbol.setFontSize(10);
339
        return textSymbol;
340
    }
341

    
342
    /**
343
     * Dados dos puntos con coordenada M, calcula el punto correspondiente a la m dada.
344
     *
345
     * @param m
346
     * @param vertex
347
     * @param nextVertex
348
     * @return
349
     * @throws LocatorException
350
     * @throws CreateGeometryException
351
     */
352
    private Point getPointWithMBetweenTwoVertex(Double m, Point vertex, Point nextVertex) throws CreateGeometryException, LocatorException {
353
        Point point = (Point)GeometryLocator.getGeometryManager().create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2D);
354
        point.setX(
355
            getCoordinateBetweenTwoValues(
356
                m,
357
                vertex.getCoordinateAt(vertex.getDimension()-1),
358
                nextVertex.getCoordinateAt(vertex.getDimension()-1),
359
                vertex.getX(),
360
                nextVertex.getX()));
361
        point.setY(
362
            getCoordinateBetweenTwoValues(
363
                m,
364
                vertex.getCoordinateAt(vertex.getDimension()-1),
365
                nextVertex.getCoordinateAt(vertex.getDimension()-1),
366
                vertex.getY(),
367
                nextVertex.getY()));
368

    
369
        return point;
370
    }
371

    
372
    /**
373
     * Dados los valores en una dimensi?n de dos puntos y sus "m" correspondientes,
374
     * calcula el valor en esa dimensi?n correspondiente a la "m" dada.
375
     *
376
     * @param m
377
     * @param m1
378
     * @param m2
379
     * @param v1
380
     * @param v2
381
     * @return
382
     */
383
    private double getCoordinateBetweenTwoValues(double m, double m1, double m2, double v1, double v2) {
384
        if (v1==v2){
385
            return Double.POSITIVE_INFINITY;
386
        }
387
         return ((v2-v1)*(m-m1)/(m2-m1))+v1;
388
    }
389

    
390
    /**
391
     * Calcula los m?ltiplos de "distance" que existen entre los valores "value0" y "value1"
392
     *
393
     * @param distance
394
     * @param value0
395
     * @param value1
396
     * @return
397
     */
398
    private List<Double> calculateMultiplesBetweenTwoValues(Double distance, double value0, double value1) {
399
        List<Double> result = new ArrayList<Double>();
400

    
401
        double v0;
402
        double v1;
403
        if(value0<=value1){
404
            v0 = value0;
405
            v1 = value1;
406
        } else {
407
            v0 = value1;
408
            v1 = value0;
409
        }
410

    
411
        int factor1 = (int) Math.ceil(v0/distance);
412
        int factor2 = (int) Math.floor(v1/distance);
413
            for (int factor = factor1; factor <= factor2; factor++) {
414
                double m = factor * distance;
415
                if(m>=v0 && m<=v1){
416
                    result.add(m);
417
                }
418
            }
419
        return result;
420
    }
421

    
422

    
423
    /**
424
     * Calcula si el valor del par?metro n es m?ltiplo del valor del par?metro d
425
     * @param n
426
     * @param d
427
     */
428
    private boolean isMultiple(double n, double d) {
429
        double div = n / d;
430
        return ((div - (int) div) < 0.000001);
431
    }
432

    
433
    /**
434
     * @param selection
435
     * @throws DataException
436
     */
437
    private long getRange(FeatureSelection selection) throws DataException {
438
        long range = 0;
439
        DisposableIterator it = selection.fastIterator();
440
        while (it.hasNext()) {
441
            Feature feature = (Feature) it.next();
442
            Geometry geometry = feature.getDefaultGeometry();
443
            if (geometry instanceof Line) {
444
                range += ((Line) geometry).getNumVertices();
445
            } else if (geometry instanceof MultiLine) {
446
                MultiLine multiLine = (MultiLine) geometry;
447
                int primitives = multiLine.getPrimitivesNumber();
448
                for (int i = 0; i < primitives; i++) {
449
                    range += ((Line) multiLine.getPrimitiveAt(i)).getNumVertices();
450
                }
451
            }
452
        }
453
        it.dispose();
454
        return range;
455
    }
456

    
457
    private IView getActiveView() {
458
        ApplicationManager application = ApplicationLocator.getManager();
459
        IView view = (IView) application.getActiveComponent(ViewDocument.class);
460
        return view;
461
    }
462

    
463
    private FLyrVect getActiveLayer(IView vista) {
464
        if (vista != null) {
465
            ViewDocument viewDocument = vista.getViewDocument();
466
            FLayer[] actives = viewDocument.getMapContext().getLayers().getActives();
467

    
468
            if ((actives.length == 1) && (actives[0] instanceof FLyrVect)) {
469
                return (FLyrVect) actives[0];
470
            }
471
        }
472
        return null;
473
    }
474

    
475
    /*
476
     * (non-Javadoc)
477
     *
478
     * @see java.awt.event.ComponentListener#componentResized(java.awt.event.
479
     * ComponentEvent)
480
     */
481
    public void componentResized(ComponentEvent e) {
482
        // TODO Auto-generated method stub
483

    
484
    }
485

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

    
496
    }
497

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

    
508
    }
509

    
510
    /*
511
     * (non-Javadoc)
512
     *
513
     * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.
514
     * ComponentEvent)
515
     */
516
    public void componentHidden(ComponentEvent e) {
517
        panel = null;
518
    }
519
}