Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extEditing / src / org / gvsig / editing / gui / cad / tools / PolylineCADTool.java @ 40418

History | View | Annotate | Download (23.6 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.editing.gui.cad.tools;
23

    
24
import java.awt.event.InputEvent;
25
import java.awt.event.MouseEvent;
26
import java.awt.geom.Point2D;
27
import java.util.ArrayList;
28
import java.util.List;
29

    
30
import javax.swing.JOptionPane;
31

    
32
import org.gvsig.andami.PluginServices;
33
import org.gvsig.app.ApplicationLocator;
34
import org.gvsig.editing.gui.cad.exception.CommandException;
35
import org.gvsig.editing.gui.cad.tools.smc.PolylineCADToolContext;
36
import org.gvsig.editing.gui.cad.tools.smc.PolylineCADToolContext.PolylineCADToolState;
37
import org.gvsig.fmap.dal.exception.ReadException;
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.GeometryManager;
41
import org.gvsig.fmap.geom.exception.CreateGeometryException;
42
import org.gvsig.fmap.geom.handler.Handler;
43
import org.gvsig.fmap.geom.primitive.Curve;
44
import org.gvsig.fmap.geom.primitive.GeneralPathX;
45
import org.gvsig.fmap.geom.primitive.Point;
46
import org.gvsig.fmap.geom.primitive.Surface;
47
import org.gvsig.fmap.geom.util.UtilFunctions;
48
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
49
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
50
import org.gvsig.i18n.Messages;
51
import org.slf4j.Logger;
52
import org.slf4j.LoggerFactory;
53

    
54
/**
55
 * DOCUMENT ME!
56
 * 
57
 * @author Vicente Caballero Navarro
58
 */
59
public class PolylineCADTool extends AbstractCurveSurfaceCADTool {
60

    
61
    private static final Logger LOG = LoggerFactory.getLogger(PolylineCADTool.class);
62

    
63
    protected PolylineCADToolContext _fsm;
64
    protected Point2D firstPoint;
65
    protected Point2D antPoint;
66
    protected Point2D antantPoint;
67
    protected Point2D antCenter;
68
    protected Point2D antInter;
69
    protected List<Curve> list = new ArrayList<Curve>();
70
    protected boolean close = false;
71
    protected GeometryManager geomManager = GeometryLocator.getGeometryManager();
72

    
73
    /**
74
     * M?todo de incio, para poner el c?digo de todo lo que se requiera de una
75
     * carga previa a la utilizaci?n de la herramienta.
76
     */
77
    public void init() {
78
        _fsm = new PolylineCADToolContext(this);
79
    }
80

    
81
    public Geometry getGeometry() {
82
        Geometry newGeom = null;
83
        newGeom = concatenateCurves(list, false);
84
        return newGeom;
85
    }
86

    
87

    
88

    
89
    public int getLinesCount() {
90
        return list.size();
91
    }
92

    
93
    public boolean isPolygonLayer() {
94
        try {
95
            return (((FLyrVect) getVLE().getLayer()).getShapeType() == Geometry.TYPES.SURFACE);
96
        } catch (ReadException e) {
97
            return false;
98
        }
99
    }
100

    
101
    public void endGeometry() {
102
        
103
        /*
104
        if (gpx == null) {
105
            gpx = new GeneralPathX();
106
            Geometry[] geoms = (Geometry[]) list.toArray(new Geometry[0]);
107
            MultiPrimitive fgc = createMultiPrimitive(geoms);
108
            // No queremos guardar FGeometryCollections:
109
            gpx.append(fgc.getPathIterator(null, geomManager.getFlatness()),
110
                true);
111
        }
112
        
113
        try {
114
            if (((FLyrVect) getVLE().getLayer()).getShapeType() == Geometry.TYPES.SURFACE
115
                && !close) {
116
                closeGeometry();
117
            }
118
        } catch (ReadException e) {
119
            NotificationManager.addError(e.getMessage(), e);
120
        }
121
        */
122
        
123

    
124
        Geometry newGeom = null;
125
        int type = getCadToolAdapter().getActiveLayerType();
126
        
127
        if ((type == Geometry.TYPES.SURFACE)
128
            || (type == Geometry.TYPES.MULTISURFACE)) {
129
            
130
            newGeom = concatenateCurves(list, true);
131
            closeSurfaceIfNecessary((Surface) newGeom);
132
            // newGeom = createSurface(gpx);
133
        } else {
134
            newGeom = concatenateCurves(list, false);
135
            // newGeom = createCurve(gpx);
136
        }
137
        insertAndSelectGeometry(newGeom);
138
        _fsm = new PolylineCADToolContext(this);
139
        list.clear();
140
        clearTemporalCache();
141
        close = false;
142
        antantPoint = antCenter = antInter = antPoint = firstPoint = null;
143
    }
144

    
145
    /**
146
     * @param newGeom
147
     */
148
    private void closeSurfaceIfNecessary(Surface geo) {
149
        
150
        if (!close && geo != null && geo.getNumVertices() > 1) {
151
            Point firstp = geo.getVertex(0);
152
            firstp = (Point) firstp.cloneGeometry();
153
            geo.addVertex(firstp);
154
        }
155
        // TODO Auto-generated method stub
156
        
157
    }
158

    
159
    public void closeGeometry() {
160
        
161
        int ng = list.size();
162
        if (ng > 0) {
163
            Curve firstcurve = list.get(0);
164
            Curve lastcurve = list.get(ng - 1);
165
            Point firstp = firstcurve.getVertex(0);
166
            firstp = (Point) firstp.cloneGeometry();
167
            lastcurve.addVertex(firstp);
168
        }
169
        close = true;
170
    }
171

    
172
    public void transition(double x, double y, InputEvent event) {
173
        _fsm.addPoint(x, y, event);
174
    }
175

    
176
    public void transition(double d) {
177
        _fsm.addValue(d);
178
    }
179

    
180
    public void transition(String s) throws CommandException {
181
        if (!super.changeCommand(s)) {
182
            _fsm.addOption(s);
183
        }
184
    }
185

    
186
    /**
187
     * Equivale al transition del prototipo pero sin pasarle como par?metro el
188
     * editableFeatureSource que ya estar? creado.
189
     * 
190
     * @param sel
191
     *            Bitset con las geometr?as que est?n seleccionadas.
192
     * @param x
193
     *            par?metro x del punto que se pase en esta transici?n.
194
     * @param y
195
     *            par?metro y del punto que se pase en esta transici?n.
196
     */
197
    public void addPoint(double x, double y, InputEvent event) {
198
        PolylineCADToolState actualState =
199
            (PolylineCADToolState) _fsm.getPreviousState();
200
        String status = actualState.getName();
201
        if (status.equals("Polyline.NextPointOrArcOrClose")
202
            || status.equals("Polyline.FirstPoint")) {
203

    
204
            if (firstPoint == null) {
205
                firstPoint = new Point2D.Double(x, y);
206
            }
207
            Point2D point = new Point2D.Double(x, y);
208

    
209
            if (antPoint != null
210
                && (antPoint.getX() != point.getX() || antPoint.getY() != point
211
                    .getY())) {
212
                GeneralPathX elShape =
213
                    new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, 2);
214
                elShape.moveTo(antPoint.getX(), antPoint.getY());
215
                elShape.lineTo(point.getX(), point.getY());
216
                Curve geom = createCurve(elShape);
217
                if (geom != null) {
218
                    list.add(geom);
219
                    addTemporalCache(geom);
220
                }
221
            }
222
            if (antPoint == null)
223
                antPoint = (Point2D) firstPoint.clone();
224

    
225
            if (antPoint != null) {
226
                antantPoint = antPoint;
227
            }
228

    
229
            antPoint = point;
230
        } else
231
            if (status.equals("Polyline.NextPointOrLineOrClose")) {
232
                Point2D point = new Point2D.Double(x, y);
233
                Point2D lastp = antPoint; // (Point2D)points.get(i-1);
234

    
235
                if (antantPoint == null) {
236
                    antantPoint =
237
                        new Point2D.Double(lastp.getX() + (point.getX() / 2),
238
                            lastp.getY() + (point.getY() / 2));
239
                }
240

    
241
                if (((point.getY() == lastp.getY()) && (point.getX() < lastp
242
                    .getX()))
243
                    || ((point.getX() == lastp.getX()) && (point.getY() < lastp
244
                        .getY()))) {
245
                } else {
246
                    if (point.getX() == lastp.getX()) {
247
                        point =
248
                            new Point2D.Double(point.getX() + 0.00000001,
249
                                point.getY());
250
                    } else
251
                        if (point.getY() == lastp.getY()) {
252
                            point =
253
                                new Point2D.Double(point.getX(),
254
                                    point.getY() + 0.00000001);
255
                        }
256

    
257
                    if (point.getX() == antantPoint.getX()) {
258
                        point =
259
                            new Point2D.Double(point.getX() + 0.00000001,
260
                                point.getY());
261
                    } else
262
                        if (point.getY() == antantPoint.getY()) {
263
                            point =
264
                                new Point2D.Double(point.getX(),
265
                                    point.getY() + 0.00000001);
266
                        }
267

    
268
                    if (!(list.size() > 0)
269
                        || (((Geometry) list.get(list.size() - 1)).getType() == Geometry.TYPES.CURVE)) {
270
                        Point2D[] ps1 =
271
                            UtilFunctions.getPerpendicular(antantPoint, lastp,
272
                                lastp);
273
                        Point2D mediop =
274
                            new Point2D.Double(
275
                                (point.getX() + lastp.getX()) / 2,
276
                                (point.getY() + lastp.getY()) / 2);
277
                        Point2D[] ps2 =
278
                            UtilFunctions
279
                                .getPerpendicular(lastp, point, mediop);
280
                        Point2D interp =
281
                            UtilFunctions.getIntersection(ps1[0], ps1[1],
282
                                ps2[0], ps2[1]);
283
                        antInter = interp;
284

    
285
                        double radio = interp.distance(lastp);
286

    
287
                        if (UtilFunctions.isLowAngle(antantPoint, lastp,
288
                            interp, point)) {
289
                            radio = -radio;
290
                        }
291

    
292
                        Point2D centerp =
293
                            UtilFunctions.getPoint(interp, mediop, radio);
294
                        antCenter = centerp;
295

    
296
                        Curve ig = createArc(lastp, centerp, point);
297

    
298
                        if (ig != null) {
299
                            list.add(ig);
300
                            addTemporalCache(ig);
301
                        } else {
302
                            
303
                            ApplicationLocator.getManager().message(
304
                                Messages.getText("_Unable_to_create_arc"),
305
                                JOptionPane.ERROR_MESSAGE);
306

    
307
                        }
308
                    } else {
309
                        Point2D[] ps1 =
310
                            UtilFunctions.getPerpendicular(lastp, antInter,
311
                                lastp);
312
                        double a1 = UtilFunctions.getAngle(ps1[0], ps1[1]);
313
                        double a2 = UtilFunctions.getAngle(ps1[1], ps1[0]);
314
                        double angle = UtilFunctions.getAngle(antCenter, lastp);
315
                        Point2D ini1 = null;
316
                        Point2D ini2 = null;
317

    
318
                        if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions
319
                            .absoluteAngleDistance(angle, a2)) {
320
                            ini1 = ps1[0];
321
                            ini2 = ps1[1];
322
                        } else {
323
                            ini1 = ps1[1];
324
                            ini2 = ps1[0];
325
                        }
326

    
327
                        Point2D unit = UtilFunctions.getUnitVector(ini1, ini2);
328
                        Point2D correct =
329
                            new Point2D.Double(lastp.getX() + unit.getX(),
330
                                lastp.getY() + unit.getY());
331
                        Point2D[] ps =
332
                            UtilFunctions.getPerpendicular(lastp, correct,
333
                                lastp);
334
                        Point2D mediop =
335
                            new Point2D.Double(
336
                                (point.getX() + lastp.getX()) / 2,
337
                                (point.getY() + lastp.getY()) / 2);
338
                        Point2D[] ps2 =
339
                            UtilFunctions
340
                                .getPerpendicular(lastp, point, mediop);
341
                        Point2D interp =
342
                            UtilFunctions.getIntersection(ps[0], ps[1], ps2[0],
343
                                ps2[1]);
344
                        antInter = interp;
345

    
346
                        double radio = interp.distance(lastp);
347

    
348
                        if (UtilFunctions.isLowAngle(correct, lastp, interp,
349
                            point)) {
350
                            radio = -radio;
351
                        }
352

    
353
                        Point2D centerp =
354
                            UtilFunctions.getPoint(interp, mediop, radio);
355
                        antCenter = centerp;
356
                        Curve geom = createArc(lastp, centerp, point);
357
                        
358
                        if (geom != null) {
359
                            list.add(geom);
360
                            addTemporalCache(geom);
361
                        }
362
                    }
363

    
364
                    antantPoint = antPoint;
365
                    antPoint = point;
366
                }
367
            }
368
    }
369

    
370
    /**
371
     * M?todo para dibujar la lo necesario para el estado en el que nos
372
     * encontremos.
373
     * 
374
     * @param g
375
     *            Graphics sobre el que dibujar.
376
     * @param selectedGeometries
377
     *            BitSet con las geometr?as seleccionadas.
378
     * @param x
379
     *            par?metro x del punto que se pase para dibujar.
380
     * @param y
381
     *            par?metro x del punto que se pase para dibujar.
382
     */
383
    public void drawOperation(MapControlDrawer renderer, double x, double y) {
384
        PolylineCADToolState actualState = _fsm.getState();
385
        String status = actualState.getName();
386

    
387
        if (status.equals("Polyline.NextPointOrArcOrClose")
388
            || status.equals("Polyline.FirstPoint")) {
389
            for (int i = 0; i < list.size(); i++) {
390
                renderer.draw((Geometry) list.get(i),
391
                    mapControlManager.getGeometrySelectionSymbol());
392
            }
393
            if (antPoint != null)
394
                renderer.drawLine(antPoint, new Point2D.Double(x, y),
395
                    mapControlManager.getGeometrySelectionSymbol());
396

    
397
        } else
398
            if ((status.equals("Polyline.NextPointOrLineOrClose"))) {
399
                for (int i = 0; i < list.size(); i++) {
400
                    renderer.draw((Geometry) list.get(i),
401
                        mapControlManager.getGeometrySelectionSymbol());
402
                }
403

    
404
                Point2D point = new Point2D.Double(x, y);
405
                Point2D lastp = antPoint;
406

    
407
                if (!(list.size() > 0)
408
                    || (((Geometry) list.get(list.size() - 1)).getType() == Geometry.TYPES.CURVE)) {
409
                    if (antantPoint == null) {
410
                        drawArc(point, lastp, new Point2D.Double(lastp.getX()
411
                            + (point.getX() / 2), lastp.getY()
412
                            + (point.getY() / 2)), renderer);
413
                    } else {
414
                        drawArc(point, lastp, antantPoint, renderer);
415
                    }
416
                } else {
417
                    if (antInter != null) {
418
                        Point2D[] ps1 =
419
                            UtilFunctions.getPerpendicular(lastp, antInter,
420
                                lastp);
421
                        double a1 = UtilFunctions.getAngle(ps1[0], ps1[1]);
422
                        double a2 = UtilFunctions.getAngle(ps1[1], ps1[0]);
423
                        double angle = UtilFunctions.getAngle(antCenter, lastp);
424
                        Point2D ini1 = null;
425
                        Point2D ini2 = null;
426

    
427
                        if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions
428
                            .absoluteAngleDistance(angle, a2)) {
429
                            ini1 = ps1[0];
430
                            ini2 = ps1[1];
431
                        } else {
432
                            ini1 = ps1[1];
433
                            ini2 = ps1[0];
434
                        }
435

    
436
                        Point2D unit = UtilFunctions.getUnitVector(ini1, ini2);
437
                        Point2D correct =
438
                            new Point2D.Double(lastp.getX() + unit.getX(),
439
                                lastp.getY() + unit.getY());
440
                        drawArc(point, lastp, correct, renderer);
441
                    }
442
                }
443
            }
444
        try {
445
            if (((FLyrVect) getVLE().getLayer()).getShapeType() == Geometry.TYPES.SURFACE
446
                && !list.isEmpty()) {
447
                Handler handler1 =
448
                    ((Geometry) list.get(0))
449
                        .getHandlers(Geometry.SELECTHANDLER)[0];
450
                GeneralPathX gpx = new GeneralPathX();
451
                gpx.moveTo(x, y);
452
                Point2D p1 = handler1.getPoint();
453
                gpx.lineTo(p1.getX(), p1.getY());
454
                Curve curve = createCurve(gpx);
455
                renderer.draw(curve,
456
                    mapControlManager.getGeometrySelectionSymbol());
457
            }
458
        } catch (ReadException e) {
459
            e.printStackTrace();
460
        }
461
    }
462

    
463
    /**
464
     * Dibuja el arco sobre el graphics.
465
     * 
466
     * @param point
467
     *            Puntero del rat?n.
468
     * @param lastp
469
     *            ?ltimo punto de la polilinea.
470
     * @param antp
471
     *            Punto antepenultimo.
472
     * @param g
473
     *            Graphics sobre el que se dibuja.
474
     */
475
    private void drawArc(Point2D point, Point2D lastp, Point2D antp,
476
        MapControlDrawer renderer) {
477
        if (((point.getY() == lastp.getY()) && (point.getX() < lastp.getX()))
478
            || ((point.getX() == lastp.getX()) && (point.getY() < lastp.getY()))) {
479
        } else {
480
            if (point.getX() == lastp.getX()) {
481
                point =
482
                    new Point2D.Double(point.getX() + 0.00000001, point.getY());
483
            } else
484
                if (point.getY() == lastp.getY()) {
485
                    point =
486
                        new Point2D.Double(point.getX(),
487
                            point.getY() + 0.00000001);
488
                }
489

    
490
            if (point.getX() == antp.getX()) {
491
                point =
492
                    new Point2D.Double(point.getX() + 0.00000001, point.getY());
493
            } else
494
                if (point.getY() == antp.getY()) {
495
                    point =
496
                        new Point2D.Double(point.getX(),
497
                            point.getY() + 0.00000001);
498
                }
499

    
500
            Point2D[] ps1 = UtilFunctions.getPerpendicular(lastp, antp, lastp);
501
            Point2D mediop =
502
                new Point2D.Double((point.getX() + lastp.getX()) / 2,
503
                    (point.getY() + lastp.getY()) / 2);
504
            Point2D[] ps2 =
505
                UtilFunctions.getPerpendicular(lastp, point, mediop);
506
            Point2D interp =
507
                UtilFunctions.getIntersection(ps1[0], ps1[1], ps2[0], ps2[1]);
508

    
509
            double radio = interp.distance(lastp);
510

    
511
            if (UtilFunctions.isLowAngle(antp, lastp, interp, point)) {
512
                radio = -radio;
513
            }
514

    
515
            Point2D centerp = UtilFunctions.getPoint(interp, mediop, radio);
516
            renderer.drawLine(lastp, point,
517
                mapControlManager.getGeometrySelectionSymbol());
518

    
519
            Geometry ig = createArc(lastp, centerp, point);
520

    
521
            if (ig != null) {
522
                renderer.draw(ig,
523
                    mapControlManager.getGeometrySelectionSymbol());
524
            }
525
        }
526
    }
527

    
528
    /**
529
     * Add a diferent option.
530
     * 
531
     * @param sel
532
     *            DOCUMENT ME!
533
     * @param s
534
     *            Diferent option.
535
     */
536
    public void addOption(String s) {
537
        // Nothing to do
538
    }
539

    
540
    public void addValue(double d) {
541
        // Nothing to do
542
    }
543

    
544
    public void cancel() {
545
        list.clear();
546
        clearTemporalCache();
547
        antantPoint = antCenter = antInter = antPoint = firstPoint = null;
548
    }
549

    
550
    public void end() {
551
        // Nothing to do
552
    }
553

    
554
    public String getName() {
555
        return PluginServices.getText(this, "polyline_");
556
    }
557

    
558
    public String toString() {
559
        return "_polyline";
560
    }
561

    
562
    public void endTransition(double x, double y, MouseEvent event) {
563
        _fsm.endPoint(x, y, event);
564
    }
565
    
566
    private Point create3DPoint(Point p) {
567
            try {
568
                        return geomManager.createPoint(p.getX(), p.getY(), Geometry.SUBTYPES.GEOM3D);
569
                } catch (CreateGeometryException e) {
570
                        return p;
571
                }
572
    }
573
    
574
    /**
575
     * @param geoms
576
     * @return
577
     * @throws CreateGeometryException 
578
     */
579
    private Geometry concatenateCurves(List<Curve> cus, boolean surf) {
580
        
581
        Curve _curv = null;
582
        Surface _surf = null;
583
        int subtype = cus.size() > 0 && cus.get(0) != null ? cus.get(0).getGeometryType().getSubType() : Geometry.SUBTYPES.GEOM2D;
584
                boolean is3D = subtype == 1 || subtype == 3;
585
        
586
        try {
587
            if (surf) {
588
                _surf = (Surface) geomManager.create(Geometry.TYPES.SURFACE, subtype);
589
            } else {
590
                _curv = (Curve) geomManager.create(Geometry.TYPES.CURVE, subtype);
591
            }
592
        } catch (CreateGeometryException e) {
593
            LOG.info("Unable to create geometry: " + e.getMessage());
594
            ApplicationLocator.getManager().message(
595
                Messages.getText("_Unable_to_create_geometry"),
596
                JOptionPane.ERROR_MESSAGE);
597
            return null;
598
        }
599
        
600
        
601
        if (cus == null || cus.size() == 0) {
602
            if (surf) {
603
                return _surf;
604
            } else {
605
                return _curv;
606
            }
607
        }
608
        
609
        Curve item_cu = cus.get(0);
610
        int len = item_cu.getNumVertices();
611
        Point po = null;
612
        /*
613
         * All from first curve
614
         */
615
        for (int i = 0; i < len; i++) {
616
                po = item_cu.getVertex(i);
617
                if(is3D) {
618
                        po = create3DPoint(po);
619
                } 
620
                if (surf) {
621
                        _surf.addVertex(po);
622
                } else {
623
                        _curv.addVertex(po);
624
                }
625

    
626
        }
627
        
628
        for (int n = 1; n < cus.size(); n++) {
629
            
630
            item_cu = cus.get(n);
631
            len = item_cu.getNumVertices();
632
            for (int i = 0; i < len; i++) {
633
                po = item_cu.getVertex(i);
634
                if(is3D) {
635
                            po = create3DPoint(po);
636
                    } 
637
                
638
                /*
639
                 * Add only if not same coords
640
                 */
641
                if (surf) {
642
                    if (differentCoordinates(po,
643
                        _surf.getVertex(
644
                        _surf.getNumVertices()-1))) {
645
                        _surf.addVertex(po);
646
                    }
647
                } else {
648
                    if (differentCoordinates(po,
649
                        _curv.getVertex(
650
                        _curv.getNumVertices()-1))) {
651
                        _curv.addVertex(po);
652
                    }
653
                }
654
            }
655
        }
656
        
657
        if (surf) {
658
            return _surf;
659
        } else {
660
            return _curv;
661
        }
662
        
663
    }
664

    
665
    /**
666
     * @param po
667
     * @param vertex
668
     * @return
669
     */
670
    private boolean differentCoordinates(Point p1, Point p2) {
671
        return !p1.equals(p2);
672
    }
673

    
674
}