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

History | View | Annotate | Download (7.01 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
    public EuclideanLine2DImpl(double m, double b) {
39
        
40
        this.m = m;
41
        this.b = b;
42
        
43
        this.coefA = m;
44
        this.coefB = -1.0;
45
        this.coefC = b;
46
        
47
        reduceCoefs();
48
        
49
    }
50
    
51
    public EuclideanLine2DImpl(double x0, double y0, double x1, double y1) {
52
        this(y1 - y0, -(x1 - x0), -(y1 - y0) * x0 + (x1 - x0) * y0);
53
    }
54

    
55
    public EuclideanLine2DImpl(Point2D p0, Point2D p1) {
56
        this(p0.getX(), p0.getY(), p1.getX(), p1.getY());
57
    }
58
    
59
    
60
    private void reduceCoefs() {
61
        if(coefA != 0 && Double.isFinite(coefA)){
62
            coefC = coefC/coefA;
63
            coefB = coefB/coefA;
64
            coefA = 1.0;
65
        } else if(coefB != 0 && Double.isFinite(coefB)){
66
            coefA = coefA/coefB; // for change the sign of coefA when coefA is infinite && coefB = -1;
67
            coefC = coefC/coefB;
68
            coefB = 1.0;
69
        }
70
    }
71

    
72
    @Override
73
    public double getA() {
74
        return coefA;
75
    }
76

    
77
    @Override
78
    public double getB() {
79
        return coefB;
80
    }
81

    
82
    @Override
83
    public double getC() {
84
        return coefC;
85
    }
86

    
87
    @Override
88
    public double getSlope() {
89
        return m;
90
    }
91

    
92
    @Override
93
    public double getYIntercept() {
94
        return b;
95
    }
96

    
97
    @Override
98
    public double getY(double x) {
99
        return (-coefA*x-coefC)/coefB;
100
    }
101

    
102
    @Override
103
    public double getX(double y) {
104
        return (-coefB*y-coefC)/coefA;
105
    }
106

    
107
    @Override
108
    public double getAngle(EuclideanLine2D line) {
109
        double m1 = line.getSlope();
110
        return Math.atan(Math.abs((m1-m)/(1+m1*m)));
111
    }
112

    
113
    @Override
114
    public double getAngle(EuclideanLine2D line, Point2D quadrant) {
115
        //FIXME: not implemented yet
116
        double m1 = line.getSlope();
117
        return Math.atan(Math.abs((m1-m)/(1+m1*m)));
118
    }
119

    
120
    @Override
121
    public double getDegreesAngle(EuclideanLine2D line) {
122
        return Math.toDegrees(getAngle(line));
123
    }
124

    
125
    @Override
126
    public double getDegreesAngle(EuclideanLine2D line, Point2D quadrant) {
127
        return Math.toDegrees(getAngle(line, quadrant));
128
    }
129

    
130
    @Override
131
    public double getDistance(double pointX, double pointY) {
132
        // d(P,r)=|A*px+B*py+C|/SQRT(A?+B?)
133

    
134
        double den = Math.abs(Math.sqrt(Math.pow(coefA, 2) + Math.pow(coefB, 2)));
135
        return Math.abs((coefA * pointX + coefB * pointY + coefC)) / den;
136
    }
137

    
138
    @Override
139
    public double getDistance(Point2D point) {
140
        return getDistance(point.getX(), point.getY());
141
    }
142

    
143
    @Override
144
    public double getDistance(EuclideanLine2D line) {
145

    
146
        if (isParallel(line)) { //Parallel lines
147
            if (Double.isInfinite(m)) { //Vertical lines
148
                return line.getC() - coefC;
149
            }
150
            Double den = Math.sqrt(Math.pow(coefA, 2) + Math.pow(coefB, 2));
151
            return Math.abs(line.getC() - coefC) / den;
152
        }
153
        return 0d;
154
    }
155

    
156
    @Override
157
    public boolean isParallel(EuclideanLine2D line) {
158
        
159
        double m1 = line.getSlope();
160
        return (m == m1 || (Double.isInfinite(m) && Double.isInfinite(m1)));
161
    }
162

    
163
    @Override
164
    public Point2D getIntersection(EuclideanLine2D line) {
165
        //Using Cramer's rule
166
        double a1 = coefA;
167
        double b1 = coefB;
168
        double c1 = coefC;
169

    
170
        Double a2 = line.getA();
171
        Double b2 = line.getB();
172
        Double c2 = line.getC();
173

    
174
        Double det = a1 * b2 - a2 * b1;
175
        Double detX = -c1 * b2 + c2 * b1;
176
        Double detY =  -a1 * c2 + a2 * c1;
177

    
178
        Double x = detX / det;
179
        Double y = detY / det;
180
        
181
        return new Point2D.Double(x, y);
182
        
183
        //Using Apache commons math library, need import the library
184
//        RealMatrix coefficients =
185
//        new Array2DRowRealMatrix(new double[][] { { coefA, coefB }, { line.getA(), line.getB() } }, false);
186
//        DecompositionSolver solver = new LUDecomposition(coefficients).getSolver();
187
//        RealVector constants = new ArrayRealVector(new double[] { -coefC, -line.getC() }, false);
188
//        RealVector solution = solver.solve(constants);
189
//        return new Point2D.Double(solution.getEntry(0), solution.getEntry(1));
190
        
191
    }
192

    
193
    @Override
194
    public EuclideanLine2D getPerpendicular(double pointX, double pointY) {
195
        // perpendicular slope (m)
196
        Double m1 = -1 / m;
197

    
198
        // perpendicular y-intercept (b)
199
        Double b1 = pointY - (m1 * pointX);
200

    
201
        return new EuclideanLine2DImpl(m1, b1);
202
    }
203

    
204
    @Override
205
    public EuclideanLine2D getPerpendicular(Point2D point) {
206
        return getPerpendicular(point.getX(), point.getY());
207
    }
208

    
209
    @Override
210
    public Point2D getNearestPoint(double pointX, double pointY) {
211
        double x;
212
        double y;
213

    
214
        if (Double.isInfinite(m)) {
215
            y = pointY;
216
            x = (-coefB * y - coefC) / coefA;
217
        } else if (m == 0) {
218
            x = pointX;
219
            y = b;
220
        } else {
221

    
222
            EuclideanLine2D perp = getPerpendicular(pointX, pointY);
223
            Double m1 = perp.getSlope();
224
            Double b1 = perp.getYIntercept();
225

    
226
            x = (b1 - b) / (m - m1);
227
            y = m * x + b;
228
        }
229

    
230
        return new Point2D.Double(x, y);
231
    }
232

    
233
    @Override
234
    public Point2D getNearestPoint(Point2D point) {
235
        return getNearestPoint(point.getX(), point.getY());
236
    }
237

    
238
    @Override
239
    public EuclideanLine2D[] getBisectors(EuclideanLine2D line) {
240
        /*
241
            r) A1x + B1y + C1 = 0
242
            s) A2x + B2y + C2 = 0
243

244
            |A1x+B1y+C1|/SQRT(A1?+B1?)= |A2x+B2y+C2|/SQRT(A2?+B2?)
245
        */
246

    
247
        Double a1 = coefA;
248
        Double b1 = coefB;
249
        Double c1 = coefC;
250

    
251
        Double a2 = line.getA();
252
        Double b2 = line.getB();
253
        Double c2 = line.getC();
254

    
255
        Double den1 = Math.sqrt(Math.pow(a1,2) + Math.pow(b1,2));
256
        Double den2 = Math.sqrt(Math.pow(a1,2) + Math.pow(b1,2));
257

    
258
        EuclideanLine2D[] result = new EuclideanLine2DImpl[2];
259
        result[0] = new EuclideanLine2DImpl(
260
                den2 * a1 - den1 * a2,
261
                den2 * b1 - den1 * b2,
262
                den2 * c1 - den1 * c2
263
        );
264
        result[1] = new EuclideanLine2DImpl(
265
                den2 * a1 + den1 * a2,
266
                den2 * b1 + den1 * b2,
267
                den2 * c1 + den1 * c2
268
        );
269
        
270
        return result;
271
        
272
    }
273

    
274
}