Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.util / org.gvsig.tools.util.impl / src / main / java / org / gvsig / euclidean / EuclideanLine2DImpl.java @ 2313

History | View | Annotate | Download (8.21 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.euclidean;
7

    
8
import java.awt.geom.Point2D;
9

    
10
/**
11
 *
12
 * @author fdiaz
13
 */
14
public class EuclideanLine2DImpl implements EuclideanLine2D {
15
    
16
    double coefA;
17
    double coefB;
18
    double coefC;
19
    double m;
20
    double b;
21

    
22
    public EuclideanLine2DImpl(double coefA, double coefB, double coefC) {
23
        
24
        this.coefA = coefA;
25
        this.coefB = coefB;
26
        this.coefC = coefC;
27
        
28
        reduceCoefs();
29
        
30
        this.m = -coefA/coefB;
31
        if(this.m == -0.0){
32
            this.m = 0.0;
33
        }
34
        this.b = -coefC / coefB;
35

    
36
    }
37

    
38
    /**
39
     * If m parameter m is infinite, preferably use the constructor EuclideanLine2DImpl(double coefA, double coefB, double coefC)
40
     * 
41
     * @param m
42
     * @param b 
43
     */
44
    
45
    public EuclideanLine2DImpl(double m, double b) {
46
        
47
        this.m = m;
48
        this.b = b;
49
        
50
        this.coefA = m;
51
        this.coefB = -1.0;
52
        this.coefC = b;
53
        
54
        reduceCoefs();
55
        
56
    }
57
    
58
    public EuclideanLine2DImpl(double x0, double y0, double x1, double y1) {
59
        this(y1 - y0, -(x1 - x0), -(y1 - y0) * x0 + (x1 - x0) * y0);
60
    }
61

    
62
    public EuclideanLine2DImpl(Point2D p0, Point2D p1) {
63
        this(p0.getX(), p0.getY(), p1.getX(), p1.getY());
64
    }
65
    
66
    
67
    private void reduceCoefs() {
68
        if(coefA != 0 && Double.isFinite(coefA)){
69
            coefC = coefC/coefA;
70
            coefB = coefB/coefA;
71
            coefA = 1.0;
72
        } else if(coefB != 0 && Double.isFinite(coefB)){
73
            coefA = coefA/coefB; // for change the sign of coefA when coefA is infinite && coefB = -1;
74
            coefC = coefC/coefB;
75
            coefB = 1.0;
76
        }
77
    }
78

    
79
    @Override
80
    public double getA() {
81
        return coefA;
82
    }
83

    
84
    @Override
85
    public double getB() {
86
        return coefB;
87
    }
88

    
89
    @Override
90
    public double getC() {
91
        return coefC;
92
    }
93

    
94
    @Override
95
    public double getSlope() {
96
        return m;
97
    }
98

    
99
    @Override
100
    public double getYIntercept() {
101
        return b;
102
    }
103

    
104
    @Override
105
    public double getY(double x) {
106
        return (-coefA*x-coefC)/coefB;
107
    }
108

    
109
    @Override
110
    public double getX(double y) {
111
        return (-coefB*y-coefC)/coefA;
112
    }
113

    
114
    @Override
115
    public double getAngle() {
116
        return Math.atan(m);
117
    }
118

    
119
    @Override
120
    public double getDegreesAngle() {
121
        return Math.toDegrees(getAngle());
122
    }
123
            
124
    @Override
125
    public double getAngle(EuclideanLine2D line) {
126
        double m1 = line.getSlope();
127
        return Math.atan(Math.abs((m1-m)/(1+m1*m)));
128
    }
129

    
130
    @Override
131
    public double getAngle(EuclideanLine2D line, Point2D quadrant) {
132
        //FIXME: not implemented yet
133
        double m1 = line.getSlope();
134
        return Math.atan(Math.abs((m1-m)/(1+m1*m)));
135
    }
136

    
137
    @Override
138
    public double getDegreesAngle(EuclideanLine2D line) {
139
        return Math.toDegrees(getAngle(line));
140
    }
141

    
142
    @Override
143
    public double getDegreesAngle(EuclideanLine2D line, Point2D quadrant) {
144
        return Math.toDegrees(getAngle(line, quadrant));
145
    }
146

    
147
    @Override
148
    public double getDistance(double pointX, double pointY) {
149
        // d(P,r)=|A*px+B*py+C|/SQRT(A?+B?)
150

    
151
        double den = Math.abs(Math.sqrt(Math.pow(coefA, 2) + Math.pow(coefB, 2)));
152
        return Math.abs((coefA * pointX + coefB * pointY + coefC)) / den;
153
    }
154

    
155
    @Override
156
    public double getDistance(Point2D point) {
157
        return getDistance(point.getX(), point.getY());
158
    }
159

    
160
    @Override
161
    public double getDistance(EuclideanLine2D line) {
162

    
163
        if (isParallel(line)) { //Parallel lines
164
            Double num = Math.abs(line.getC() - coefC);
165
            if (Double.isInfinite(m)) { //Vertical lines
166
                return num;
167
            }
168
            Double den = Math.sqrt(Math.pow(coefA, 2) + Math.pow(coefB, 2));
169
            return num / den;
170
        }
171
        return 0d;
172
    }
173

    
174
    @Override
175
    public boolean isParallel(EuclideanLine2D line) {
176
        
177
        double m1 = line.getSlope();
178
        return (m == m1 || (Double.isInfinite(m) && Double.isInfinite(m1)));
179
    }
180

    
181
    @Override
182
    public Point2D getIntersection(EuclideanLine2D line) {
183
        //Using Cramer's rule
184
        double a1 = coefA;
185
        double b1 = coefB;
186
        double c1 = coefC;
187

    
188
        Double a2 = line.getA();
189
        Double b2 = line.getB();
190
        Double c2 = line.getC();
191

    
192
        Double det = a1 * b2 - a2 * b1;
193
        Double detX = -c1 * b2 + c2 * b1;
194
        Double detY =  -a1 * c2 + a2 * c1;
195

    
196
        Double x = detX / det;
197
        Double y = detY / det;
198
        
199
        return new Point2D.Double(x, y);
200
        
201
        //Using Apache commons math library, need import the library
202
//        RealMatrix coefficients =
203
//        new Array2DRowRealMatrix(new double[][] { { coefA, coefB }, { line.getA(), line.getB() } }, false);
204
//        DecompositionSolver solver = new LUDecomposition(coefficients).getSolver();
205
//        RealVector constants = new ArrayRealVector(new double[] { -coefC, -line.getC() }, false);
206
//        RealVector solution = solver.solve(constants);
207
//        return new Point2D.Double(solution.getEntry(0), solution.getEntry(1));
208
        
209
    }
210

    
211
    @Override
212
    public EuclideanLine2D getPerpendicular(double pointX, double pointY) {
213
        if(Math.abs(m)==0.0){
214
            return new EuclideanLine2DImpl(1, 0, -pointX);
215
        }
216
        if(Double.isInfinite(m)){
217
            return new EuclideanLine2DImpl(0, 1, -pointY);
218
        }
219
        // perpendicular slope (m)
220
        Double m1 = -1 / m;
221

    
222
        // perpendicular y-intercept (b)
223
        Double b1 = pointY - (m1 * pointX);
224

    
225
        return new EuclideanLine2DImpl(m1, b1);
226
    }
227

    
228
    @Override
229
    public EuclideanLine2D getPerpendicular(Point2D point) {
230
        return getPerpendicular(point.getX(), point.getY());
231
    }
232

    
233
        @Override
234
    public EuclideanLine2D getParallel(double pointX, double pointY) {
235
        if(Math.abs(m)==0.0){
236
            return new EuclideanLine2DImpl(0, 1, -pointY);
237
        }
238
        if(Double.isInfinite(m)){
239
            return new EuclideanLine2DImpl(1, 0, -pointX);
240
        }
241
        // parallel slope (m)
242
        Double m1 = m;
243

    
244
        // parallel y-intercept (b)
245
        Double b1 = pointY - (m1 * pointX);
246

    
247
        return new EuclideanLine2DImpl(m1, b1);
248
    }
249

    
250
    @Override
251
    public EuclideanLine2D getParallel(Point2D point) {
252
        return getParallel(point.getX(), point.getY());
253
    }
254

    
255
    
256
    @Override
257
    public Point2D getNearestPoint(double pointX, double pointY) {
258
        double x;
259
        double y;
260

    
261
        if (Double.isInfinite(m)) {
262
            y = pointY;
263
            x = (-coefB * y - coefC) / coefA;
264
        } else if (Math.abs(m) == 0) {
265
            x = pointX;
266
            y = b;
267
        } else {
268

    
269
            EuclideanLine2D perp = getPerpendicular(pointX, pointY);
270
            Double m1 = perp.getSlope();
271
            Double b1 = perp.getYIntercept();
272

    
273
            x = (b1 - b) / (m - m1);
274
            y = m * x + b;
275
        }
276

    
277
        return new Point2D.Double(x, y);
278
    }
279

    
280
    @Override
281
    public Point2D getNearestPoint(Point2D point) {
282
        return getNearestPoint(point.getX(), point.getY());
283
    }
284

    
285
    @Override
286
    public EuclideanLine2D[] getBisectors(EuclideanLine2D line) {
287
        /*
288
            r) A1x + B1y + C1 = 0
289
            s) A2x + B2y + C2 = 0
290

291
            |A1x+B1y+C1|/SQRT(A1?+B1?)= |A2x+B2y+C2|/SQRT(A2?+B2?)
292
        */
293

    
294
        Double a1 = coefA;
295
        Double b1 = coefB;
296
        Double c1 = coefC;
297

    
298
        Double a2 = line.getA();
299
        Double b2 = line.getB();
300
        Double c2 = line.getC();
301

    
302
        Double den1 = Math.sqrt(Math.pow(a1,2) + Math.pow(b1,2));
303
        Double den2 = Math.sqrt(Math.pow(a2,2) + Math.pow(b2,2));
304

    
305
        EuclideanLine2D[] result = new EuclideanLine2DImpl[2];
306
        result[0] = new EuclideanLine2DImpl(
307
                den2 * a1 - den1 * a2,
308
                den2 * b1 - den1 * b2,
309
                den2 * c1 - den1 * c2
310
        );
311
        result[1] = new EuclideanLine2DImpl(
312
                den2 * a1 + den1 * a2,
313
                den2 * b1 + den1 * b2,
314
                den2 * c1 + den1 * c2
315
        );
316
        
317
        return result;
318
        
319
    }
320

    
321
}