Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / symbol / style / Line2DOffset.java @ 34294

History | View | Annotate | Download (20.7 KB)

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

    
43
import java.awt.Shape;
44
import java.awt.geom.Line2D;
45
import java.awt.geom.PathIterator;
46
import java.awt.geom.Point2D;
47
import java.util.ArrayList;
48
import java.util.HashMap;
49
import java.util.List;
50
import java.util.Map;
51

    
52
import org.gvsig.fmap.geom.Geometry;
53
import org.gvsig.fmap.geom.primitive.GeneralPathX;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56

    
57
import com.vividsolutions.jts.geom.Coordinate;
58
import com.vividsolutions.jts.geom.LineSegment;
59
/**
60
 *
61
 * Line2DOffset.java
62
 *
63
 *
64
 * @author jaume dominguez faus - jaume.dominguez@iver.es Jan 3, 2008
65
 *
66
 */
67

    
68
public class Line2DOffset {
69
        final static private Logger logger = LoggerFactory.getLogger(Line2DOffset.class);
70

    
71
        public static GeneralPathX offsetLine(Shape p, double offset) {
72

    
73
                if (Math.abs(offset) < 1) {
74
                        return new GeneralPathX(p.getPathIterator(null));
75
                }
76
                PathIterator pi = p.getPathIterator(null);
77
                double[] dataCoords = new double[6];
78
                Coordinate from = null, first = null;
79
                List<LineSegment> segments = new ArrayList<LineSegment>();
80
                GeneralPathX offsetSegments = new GeneralPathX();
81
                LineSegment line;
82
                try {
83
                        while (!pi.isDone()) {
84
                                // while not done
85
                                int type = pi.currentSegment(dataCoords);
86

    
87
                                switch (type) {
88
                                case PathIterator.SEG_MOVETO:
89
                                        if(from == null){
90
                                                from = new Coordinate(dataCoords[0], dataCoords[1]);
91
                                                first = from;
92
                                                break;
93
                                        } else {
94
                                                /* Puede significar un agujero en un pol?gono o un salto en una linea.
95
                                                 * Entonces, consumimos los segmentos que llevamos
96
                                                 * y empezamos un nuevo pol?gono o una nueva linea.
97
                                                 */
98
                                                try {
99
                                                        if(((Geometry)p).getType() == Geometry.TYPES.SURFACE){
100
                                                                offsetSegments.append(offsetAndConsumeClosedSegments(offset, segments).getPathIterator(null),
101
                                                                                false);
102
                                                        } else {
103
                                                                offsetSegments.append(offsetAndConsumeSegments(offset, segments).getPathIterator(null),
104
                                                                                false);
105
                                                        }
106
                                                } catch (NotEnoughSegmentsToClosePathException e) {
107
                                                        logger.error(
108
                                                                        e.getMessage(), e);
109
                                                }
110
                                                segments.clear();
111
                                                from = new Coordinate(dataCoords[0], dataCoords[1]);
112
                                                first = from;
113
                                                break;
114
                                        }
115

    
116
                                case PathIterator.SEG_LINETO:
117

    
118
                                        // System.out.println("SEG_LINETO");
119
                                        Coordinate to = new Coordinate(dataCoords[0], dataCoords[1]);
120
                                        if(from.compareTo(to)!=0){
121
                                                line = new LineSegment(from, to);
122
                                                segments.add(line);
123
                                                from = to;
124
                                        }
125
                                        break;
126
                                case PathIterator.SEG_CLOSE:
127
                                        line = new LineSegment(from, first);
128
                                        segments.add(line);
129
                                        //                                        from = first;
130
                                        try {
131
                                                offsetSegments.append(offsetAndConsumeClosedSegments(
132
                                                                offset, segments).getPathIterator(null), false);
133
                                        } catch (NotEnoughSegmentsToClosePathException e) {
134
                                                logger.error(
135
                                                                e.getMessage(), e);
136
                                        }
137
                                        segments.clear();
138
                                        first =null;
139
                                        from = null;
140

    
141
                                        break;
142

    
143
                                } // end switch
144

    
145
                                pi.next();
146
                        }
147
                        offsetSegments.append(offsetAndConsumeSegments(offset, segments)
148
                                        .getPathIterator(null), false);
149

    
150
                        return offsetSegments;
151
                } catch (ParallelLinesCannotBeResolvedException e) {
152
                        logger.error(e.getMessage(), e);
153
                        return new GeneralPathX(p.getPathIterator(null));
154
                }
155
        }
156

    
157
        private static GeneralPathX offsetAndConsumeSegments(double offset,
158
                        List<LineSegment> segments)
159
        throws ParallelLinesCannotBeResolvedException {
160
                Map<LineSegment, LineEquation> offsetLines =
161
                        new HashMap<LineSegment, LineEquation>();
162
                int segmentCount = segments.size();
163
                // first calculate offset lines with the starting point
164
                for (int i = 0; i < segmentCount; i++) {
165
                        LineSegment segment = (LineSegment)segments.get(i);
166
                        double theta = segment.angle();
167
                        //FIXME: ?Esto para qu? es?
168
                        //                        if (Math.abs(theta) % (Math.PI*0.5) < 0.00001){
169
                        //                                theta=theta+0.00000000000001;
170
                        //                        }
171

    
172
                        double xOffset = offset * Math.sin(theta);
173
                        double yOffset = offset * Math.cos(theta);
174

    
175
                        Coordinate p0 = segment.p0;
176
                        double x0 = p0.x + xOffset;
177
                        double y0 = p0.y - yOffset;
178

    
179
                        Coordinate p1 = segment.p1;
180
                        double x1 = p1.x + xOffset;
181
                        double y1 = p1.y - yOffset;
182

    
183
                        LineEquation offsetLine = new LineEquation(theta, x0, y0, x1, y1);
184
                        offsetLines.put(segment, offsetLine);
185
                }
186

    
187
                /*
188
                 * let's now calculate the end point of each segment with the point
189
                 * where each line crosses the next one. this point will be the end
190
                 * point of the first line, and the start point of its next one.
191
                 */
192
                Point2D pIni = null;
193
                Point2D pEnd = null;
194
                GeneralPathX gpx = new GeneralPathX();
195
                for (int i = 0; i < segmentCount; i++) {
196
                        LineSegment segment = (LineSegment)segments.get(0);
197
                        LineEquation eq = (LineEquation)offsetLines.get(segment);
198
                        if (i == 0) {
199
                                pIni = new Point2D.Double(eq.x, eq.y);
200
                        } else {
201
                                pIni = pEnd;
202
                        }
203

    
204
                        if (i < segmentCount - 1) {
205
                                LineEquation eq1 = (LineEquation) offsetLines.get(segments.get(1));
206
                                try{
207
                                        pEnd = eq.resolve(eq1);
208
                                } catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma.
209
                                        pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
210
                                        gpx.append(new Line2D.Double(pIni, pEnd)
211
                                        .getPathIterator(null), true); // a?adimos una linea
212
                                        // hasta el final
213
                                        // del primer
214
                                        // segmento
215
                                        //                                         y asignamos como punto final el principio del siguiente segmento
216
                                        //                                         para que en la siguiente iteraci?n lo tome como punto inicial.
217
                                        pIni = pEnd;
218
                                        pEnd = new Point2D.Double(eq1.x, eq1.y);
219
                                        segments.remove(0);
220
                                        continue;
221
                                }
222
                        } else {
223
                                pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
224
                        }
225

    
226
                        gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true);
227
                        segments.remove(0);
228
                }
229
                return gpx;
230
        }
231

    
232
        private static GeneralPathX offsetAndConsumeClosedSegments(double offset,
233
                        List<LineSegment> segments)
234
        throws ParallelLinesCannotBeResolvedException, NotEnoughSegmentsToClosePathException {
235
                int segmentCount = segments.size();
236
                if (segmentCount > 1) {
237
                        Map<LineSegment, LineEquation> offsetLines = new HashMap<LineSegment, LineEquation>();
238
                        // first calculate offset lines with the starting point
239
                        for (int i = 0; i < segmentCount; i++) {
240
                                LineSegment segment = (LineSegment)segments.get(i);
241
                                double theta = segment.angle();
242
                                //FIXME: ?Esto para qu? es?
243
                                //                        if (Math.abs(theta) % (Math.PI*0.5) < 0.00001){
244
                                //                                theta=theta+0.00000000000001;
245
                                //                        }
246

    
247
                                double xOffset = offset * Math.sin(theta);
248
                                double yOffset = offset * Math.cos(theta);
249

    
250
                                Coordinate p0 = segment.p0;
251
                                double x0 = p0.x + xOffset;
252
                                double y0 = p0.y - yOffset;
253

    
254
                                Coordinate p1 = segment.p1;
255
                                double x1 = p1.x + xOffset;
256
                                double y1 = p1.y - yOffset;
257

    
258
                                LineEquation offsetLine = new LineEquation(theta, x0, y0, x1, y1);
259
                                offsetLines.put(segment, offsetLine);
260
                        }
261

    
262
                        /*
263
                         * let's now calculate the end point of each segment with the point
264
                         * where each line crosses the next one. this point will be the end
265
                         * point of the first line, and the start point of its next one.
266
                         */
267
                        Point2D pIni = null;
268
                        Point2D pEnd = null;
269
                        Point2D firstP = null;
270
                        GeneralPathX gpx = new GeneralPathX();
271
                        for (int i = 0; i < segmentCount; i++) {
272
                                LineSegment segment = (LineSegment)segments.get(0);
273
                                LineEquation eq = offsetLines.get(segment);
274
                                if (i == 0) { //Calculo de la intersecci?n entre el primer segmento y el ?ltimo
275
                                        LineEquation eq0 = offsetLines.get((LineSegment)segments.get(segmentCount-1));
276
                                        try{
277
                                                pIni = eq0.resolve(eq);
278
                                        } catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma.
279
                                                //                                                pIni = new Point2D.Double(eq0.xEnd, eq0.yEnd);
280
                                                pIni = new Point2D.Double(eq.x, eq.y);
281
                                        }
282
                                        firstP = pIni;
283
                                } else {
284
                                        pIni = pEnd;
285
                                }
286

    
287
                                if (i < segmentCount - 1) {
288
                                        LineEquation eq1 = offsetLines.get((LineSegment)segments.get(1));
289
                                        try{
290
                                                pEnd = eq.resolve(eq1);
291
                                        } catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma.
292
                                                pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
293
                                                gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true); // a?adimos una linea hasta el final del primer segmento
294
                                                //                                         y asignamos como punto final el principio del siguiente segmento
295
                                                //                                         para que en la siguiente iteraci?n lo tome como punto inicial.
296
                                                pIni = pEnd;
297
                                                pEnd = new Point2D.Double(eq1.x, eq1.y);
298
                                                segments.remove(0);
299
                                                continue;
300
                                        }
301
                                } else {
302
                                        //                                        pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
303
                                        pEnd = new Point2D.Double(firstP.getX(), firstP.getY());
304
                                }
305

    
306
                                gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true);
307
                                segments.remove(0);
308
                        }
309
                        return gpx;
310
                }
311
                throw new NotEnoughSegmentsToClosePathException(segments);
312

    
313
        }
314

    
315
        //        private static GeneralPathX offsetAndConsumeClosedSegments(double offset,
316
        //                        List<LineSegment> segments)
317
        //        throws ParallelLinesCannotBeResolvedException,
318
        //        NotEnoughSegmentsToClosePathException {
319
        //                int segmentCount = segments.size();
320
        //                if (segmentCount > 1) {
321
        //                        GeneralPathX openPath = offsetAndConsumeSegments(offset, segments);
322
        //                        openPath.closePath();
323
        //                        return openPath;
324
        //                }
325
        //                throw new NotEnoughSegmentsToClosePathException(segments);
326
        //        }
327
}
328

    
329
class LineEquation {
330
        double theta, m, x, y;
331

    
332
        double xEnd, yEnd; // just for simplicity of code
333

    
334
        public LineEquation(double theta, double x, double y, double xEnd,
335
                        double yEnd) {
336
                //                this.theta = Math.tan(theta); //Esto es un error, no podemos confundir el angulo de la recta con su pendiente
337
                this.theta = theta;
338
                this.m = Math.tan(theta);
339
                this.x = x;
340
                this.y = y;
341
                this.xEnd = xEnd;
342
                this.yEnd = yEnd;
343
        }
344

    
345
        public Point2D resolve(LineEquation otherLine)
346
        throws ParallelLinesCannotBeResolvedException {
347
                /*
348
                 * line1 (this): y - y0 = m*(x - x0)
349
                 * line2 (otherLine): y' - y'0 = m'*(x' - x'0)
350
                 */
351

    
352
                double X;
353
                double Y;
354
                if(Math.abs(this.x - this.xEnd)<0.00001) { //Esta linea es vertical
355
                        //                        System.out.println("1 VERTICAL");
356
                        X = this.xEnd;
357
                        if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical
358
                                //                                System.out.println("    2 PERPENDICULAR");
359
                                if(Math.abs(this.x - otherLine.x)<0.00001){ //Son la misma linea, devolvemos el primer punto de la otra linea.
360
                                        //                                        System.out.println("        MISMA LINEA");
361
                                        Y = otherLine.y;
362
                                } else { //No son la misma linea, entonces son paralelas, excepcion.
363
                                        //                                        System.out.println("        CASCO POR 1");
364
                                        throw new ParallelLinesCannotBeResolvedException(this, otherLine);
365
                                }
366
                        } else if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal
367
                                //                                System.out.println("    2 HORIZONTAL");
368
                                Y = otherLine.y;
369
                        } else { //Si no
370
                                //                                System.out.println("    2 CUALQUIERA");
371
                                Y = otherLine.m*(X - otherLine.x)+otherLine.y;
372
                        }
373

    
374
                } else if (Math.abs(this.y - this.yEnd)<0.00001) { //Esta linea es horizontal
375
                        //                        System.out.println("1 HORIZONTAL");
376
                        Y = this.yEnd;
377
                        if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal
378
                                //                                System.out.println("    2 HORIZONTAL");
379
                                if(Math.abs(this.y - otherLine.y)<0.00001){ //Son la misma linea, devolvemos el primer punto de la otra linea.
380
                                        //                                        System.out.println("        MISMA LINEA");
381
                                        X = otherLine.x;
382
                                } else { //No son la misma linea, entonces son paralelas, excepcion.
383
                                        //                                        System.out.println("        CASCO POR 2");
384
                                        throw new ParallelLinesCannotBeResolvedException(this, otherLine);
385
                                }
386
                        } else if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical
387
                                //                                System.out.println("    2 VERTICAL");
388
                                X = otherLine.x;
389
                        } else { //Si no
390
                                //                                System.out.println("    2 CUALQUIERA");
391
                                X = (Y - otherLine.y)/otherLine.m +otherLine.x;
392
                        }
393
                } else { //Esta linea no es ni vertical ni horizontal
394
                        //                        System.out.println("1 CUALQUIERA");
395
                        if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal
396
                                //                                System.out.println("    2 HORIZONTAL");
397
                                Y = otherLine.y;
398
                                X = (Y - this.y)/this.m +this.x;
399
                        } else if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical
400
                                //                                System.out.println("    2 VERTICAL");
401
                                X = otherLine.x;
402
                                Y = this.m*(X - this.x)+this.y;
403
                        } else if ((Math.abs(otherLine.m - this.m)<0.00001)) { //Tienen la misma pendiente
404
                                //                                System.out.println("    MISMA PENDIENTE");
405
                                Y = otherLine.m*(this.x - otherLine.x)+otherLine.y;
406
                                if (Math.abs(this.y - Y)<0.00001){ //Las lineas son la misma
407
                                        //                                        System.out.println("        MISMA LINEA");
408
                                        X = otherLine.x;
409
                                        Y = otherLine.y;
410
                                } else {
411
                                        //                                        System.out.println("        CASCO POR 3");
412
                                        throw new ParallelLinesCannotBeResolvedException(this, otherLine);
413
                                }
414
                        } else {
415
                                //                                System.out.println("    AMBAS CUALESQUIERA");
416
                                double mTimesX = this.m * this.x;
417
                                X = (mTimesX - this.y - otherLine.m * otherLine.x + otherLine.y) / (this.m - otherLine.m);
418
                                Y = this.m * X - mTimesX + this.y;
419
                        }
420
                }
421

    
422
                //                System.out.println("DEVOLVEMOS X = "+X+" Y = "+Y);
423
                return new Point2D.Double(X, Y);
424

    
425
        }
426

    
427
        public String toString() {
428
                return "Y - " + y + " = " + m + "*(X - " + x + ")";
429
        }
430
}
431

    
432
class NotEnoughSegmentsToClosePathException extends Exception {
433
        private static final long serialVersionUID = 95503944546535L;
434

    
435
        public NotEnoughSegmentsToClosePathException(List<LineSegment> segments) {
436
                super("Need at least 2 segments to close a path. I've got "
437
                                + segments.size() + ".");
438
        }
439
}
440

    
441
class ParallelLinesCannotBeResolvedException extends Exception {
442
        private static final long serialVersionUID = 8322556508820067641L;
443

    
444
        public ParallelLinesCannotBeResolvedException(LineEquation eq1,
445
                        LineEquation eq2) {
446
                super("Lines '" + eq1 + "' and '" + eq2
447
                                + "' are parallel and don't share any point!");
448
        }
449
}
450
//public class Line2DOffset {
451

    
452
//private static final double TOL = 1E-8;
453
//private static final double ANGLE_TOL = 0.01/180*Math.PI;
454

    
455
//public static GeneralPathX offsetLine(Shape p, double offset) {
456

    
457
//PathIterator pi = p.getPathIterator(null);
458
//double[] dataCoords = new double[6];
459
//Coordinate from = null, first = null;
460
//ArrayList<LineSegment> segments = new ArrayList<LineSegment>();
461
//GeneralPathX offsetSegments = new GeneralPathX();
462
//try {
463
//while (!pi.isDone()) {
464
//// while not done
465
//int type = pi.currentSegment(dataCoords);
466

    
467
//switch (type) {
468
//case PathIterator.SEG_MOVETO:
469
//from = new Coordinate(dataCoords[0], dataCoords[1]);
470
//first = from;
471
//break;
472

    
473
//case PathIterator.SEG_LINETO:
474

    
475
//// System.out.println("SEG_LINETO");
476
//Coordinate to = new Coordinate(dataCoords[0], dataCoords[1]);
477
//LineSegment line = new LineSegment(from, to);
478
//int size = segments.size();
479
//if (size>0) {
480
//LineSegment prev = segments.get(size-1);
481
//if (line.angle() == prev.angle()) {
482
//if (Math.abs(line.p0.x - prev.p1.x) < TOL &&
483
//Math.abs(line.p0.y - prev.p1.y) < TOL) {
484
//prev.p1 = line.p1;
485
//break;
486
//}
487
//}
488
//}
489
//from = to;
490
//segments.add(line);
491

    
492
//break;
493
//case PathIterator.SEG_CLOSE:
494
//line = new LineSegment(from, first);
495
//segments.add(line);
496
//from = first;
497
//try {
498
//offsetSegments.append(offsetAndConsumeClosedSegments(offset, segments), false);
499
//} catch (NotEnoughSegmentsToClosePathException e) {
500
//Logger.getLogger(Line2DOffset.class).error(e.getMessage(), e);
501
//}
502
//break;
503

    
504
//} // end switch
505

    
506
//pi.next();
507
//}
508
//offsetSegments.append(offsetAndConsumeSegments(offset, segments), true);
509

    
510
//return offsetSegments;
511
//} catch (ParallelLinesCannotBeResolvedException e) {
512
//Logger.getLogger(Line2DOffset.class).error(e.getMessage(), e);
513
//return new GeneralPathX(p);
514
//}
515
//}
516

    
517
//private static GeneralPathX offsetAndConsumeSegments(double offset, ArrayList<LineSegment> segments)  {
518
//Hashtable<LineSegment, LineEquation> offsetLines = new Hashtable<LineSegment, LineEquation>();
519
//int segmentCount = segments.size();
520
//// first calculate offset lines with the starting point
521
//for (int i = 0; i < segmentCount; i++) {
522
//LineSegment segment = segments.get(i);
523
//double theta = segment.angle();
524

    
525
//double xOffset = offset*Math.sin(theta);
526
//double yOffset = offset*Math.cos(theta);
527

    
528
//Coordinate p0 = segment.p0;
529
//double x0 = p0.x + xOffset;
530
//double y0 = p0.y - yOffset;
531

    
532
//Coordinate p1 = segment.p1;
533
//double x1 = p1.x + xOffset;
534
//double y1 = p1.y - yOffset;
535

    
536
//LineEquation offsetLine = new LineEquation(theta, x0, y0, x1, y1, offset);
537
//offsetLines.put(segment, offsetLine);
538
//}
539

    
540
///*
541
//* let's now calculate the end point of each segment with
542
//* the point where each line crosses the next one.
543
//* this point will be the end point of the first line, and
544
//* the start point of its next one.
545
//*/
546
//Point2D pIni = null;
547
//Point2D pEnd = null;
548
//GeneralPathX gpx = new GeneralPathX();
549
//for (int i = 0; i < segmentCount; i++) {
550
//LineSegment segment = segments.get(0);
551
//LineEquation eq = offsetLines.get(segment);
552
//Point2D pAux = null;
553
//if (i < segmentCount -1) {
554
//try {
555
//pAux = eq.resolve(offsetLines.get(segments.get(1)));
556
//if (i == 0) {
557
//pIni = new Point2D.Double(eq.x, eq.y);
558
//} else {
559
//pIni = pEnd;
560
//}
561
//} catch (ParallelLinesCannotBeResolvedException e) {
562
//segments.remove(0);
563
//continue;
564
//}
565
//}
566

    
567

    
568
//if (pAux != null) {
569
//pEnd = pAux;
570
//} else {
571
//pEnd = new Point2D.Double(eq.xEnd, eq.yEnd);
572
//}
573

    
574
//gpx.append(new Line2D.Double(pIni, pEnd), true);
575
//segments.remove(0);
576
//}
577
//return gpx;
578
//}
579

    
580
//private static GeneralPathX offsetAndConsumeClosedSegments(double offset, ArrayList<LineSegment> segments) throws ParallelLinesCannotBeResolvedException, NotEnoughSegmentsToClosePathException {
581
//int segmentCount = segments.size();
582
//if (segmentCount > 1) {
583
//GeneralPathX openPath = offsetAndConsumeSegments(offset, segments);
584
//openPath.closePath();
585
//return openPath;
586
//}
587
//throw new NotEnoughSegmentsToClosePathException(segments);
588
//}
589
//}
590

    
591
//class LineEquation {
592
//double theta, x, y;
593
//double xEnd, yEnd; // just for simplicity of code
594
//double offset;
595

    
596
//public LineEquation(double theta, double x, double y, double xEnd, double yEnd, double offset) {
597
//this.theta = theta;
598
//this.x = x;
599
//this.y = y;
600
//this.xEnd = xEnd;
601
//this.yEnd = yEnd;
602
//this.offset = offset;
603
//}
604

    
605
//public Point2D resolve(LineEquation otherLine) throws ParallelLinesCannotBeResolvedException {
606
//double X;
607
//double Y;
608

    
609

    
610
///*
611
//* line1 (this):      y  -  y0 =  m*(x  - x0)
612
//* line2 (otherLine): y' - y'0 = m'*(x' - x'0)
613
//*/
614
//if (otherLine.theta == this.theta)
615
//throw new ParallelLinesCannotBeResolvedException(this, otherLine);
616

    
617
//if (Math.cos(theta) == 0) {
618

    
619
//X = otherLine.x + offset*Math.cos(otherLine.theta);
620
//Y = otherLine.y + offset*Math.sin(otherLine.theta);
621
//} else if (Math.cos(otherLine.theta) == 0) {
622
//X = x + offset*Math.cos(theta);
623
//Y = y + offset*Math.sin(theta);
624
//} else {
625
///*
626
//* m*(X - x0) + y0 = m'*(X - x'0) + y0'
627
//* X = (m*x0 - y0 - m'*x0' + y'0) / (m - m')
628
//*/
629
//double tanTheta = Math.tan(theta);
630
//double otherTanTheta = Math.tan(otherLine.theta);
631
//double thetaTimesX = tanTheta*this.x;
632
//X = (thetaTimesX - this.y - otherTanTheta*otherLine.x + otherLine.y) / (tanTheta - otherTanTheta);
633

    
634
///*
635
//* Y - y0 = m*(X - x0)
636
//* Y = m*X - m*x0 + y0
637
//*/
638
//Y = tanTheta*X - thetaTimesX + this.y;
639
//}
640
//return new Point2D.Double(X, Y);
641
//}
642

    
643
//@Override
644
//public String toString() {
645
//return "Y - "+y+" = "+theta+"*(X - "+x+")";
646
//}
647
//}
648

    
649
//class NotEnoughSegmentsToClosePathException extends Exception {
650
//private static final long serialVersionUID = 95503944546535L;
651
//public NotEnoughSegmentsToClosePathException(ArrayList<LineSegment> segments) {
652
//super("Need at least 2 segments to close a path. I've got "+segments.size()+".");
653
//}
654
//}
655

    
656
//class ParallelLinesCannotBeResolvedException extends Exception {
657
//private static final long serialVersionUID = 8322556508820067641L;
658

    
659
//public ParallelLinesCannotBeResolvedException(LineEquation eq1, LineEquation eq2) {
660
//super("Lines '"+eq1+"' and '"+eq2+"' are parallel and don't share any point!");
661
//}
662
//}