1
|
/*******************************************************************************
|
2
|
* Copyright (c) 2010 IBM Corporation and others.
|
3
|
* All rights reserved. This program and the accompanying materials
|
4
|
* are made available under the terms of the Eclipse Public License v1.0
|
5
|
* which accompanies this distribution, and is available at
|
6
|
* http://www.eclipse.org/legal/epl-v10.html
|
7
|
*
|
8
|
* Contributors:
|
9
|
* Research Group Software Construction,
|
10
|
* RWTH Aachen University, Germany - initial API and implementation
|
11
|
*
|
12
|
*******************************************************************************/
|
13
|
package org.eclipse.draw2d.geometry;
|
14
|
|
15
|
/**
|
16
|
* Represents a straight line within 2-dimensional Euclidean space.
|
17
|
*
|
18
|
* @author Alexander Nyssen
|
19
|
* @since 3.6
|
20
|
*/
|
21
|
public class Straight {
|
22
|
|
23
|
/** position vector of this straight */
|
24
|
public Vector position;
|
25
|
|
26
|
/** direction vector of this straight */
|
27
|
public Vector direction;
|
28
|
|
29
|
/**
|
30
|
* Constructs a new Straight with the given position and direction.
|
31
|
*
|
32
|
* @param position
|
33
|
* @param direction
|
34
|
*/
|
35
|
public Straight(Vector position, Vector direction) {
|
36
|
if (direction.isNull()) {
|
37
|
throw new IllegalArgumentException(
|
38
|
"direction has to be unequal to (0,0)"); //$NON-NLS-1$
|
39
|
}
|
40
|
this.position = position;
|
41
|
this.direction = direction;
|
42
|
}
|
43
|
|
44
|
/**
|
45
|
* Constructs a new Straight between the two given Points.
|
46
|
*
|
47
|
* @param point1
|
48
|
* a first waypoint of the Straight to be constructed
|
49
|
* @param point2
|
50
|
* a second waypoint of the Straight to be constructed
|
51
|
*/
|
52
|
public Straight(PrecisionPoint point1, PrecisionPoint point2) {
|
53
|
this(new Vector(point1), new Vector(point1, point2));
|
54
|
}
|
55
|
|
56
|
/**
|
57
|
* Checks whether this Straight and the provided one have an intersection
|
58
|
* point.
|
59
|
*
|
60
|
* @param other
|
61
|
* The Straight to use for the calculation.
|
62
|
* @return true if the two Straights intersect, false otherwise.
|
63
|
*/
|
64
|
public boolean intersects(Straight other) {
|
65
|
return direction.getDotProduct(other.direction
|
66
|
.getOrthogonalComplement()) != 0;
|
67
|
}
|
68
|
|
69
|
/**
|
70
|
* Checks whether this Straight and the provided one have an intersection
|
71
|
* point, which is inside the specified segment between segmentStart and
|
72
|
* segmentEnd.
|
73
|
*
|
74
|
* segmentStart a Vector indicating the start point of the segment. Has to
|
75
|
* be a point on the straight.
|
76
|
*
|
77
|
* @param segmentEnd
|
78
|
* a Vector indicating the end point of the segment. Has to be a
|
79
|
* point on the straight.
|
80
|
* @param other
|
81
|
* the Straight to test
|
82
|
* @return true if the true straights intersect and the intersection point
|
83
|
* is contained within the specified segment, false otherwise.
|
84
|
* @since 3.2
|
85
|
*/
|
86
|
public boolean intersectsWithinSegment(Vector segmentStart,
|
87
|
Vector segmentEnd, Straight other) {
|
88
|
// precondition: segment start and end have to be points on this
|
89
|
// straight.
|
90
|
if (!contains(segmentStart) || !contains(segmentEnd)) {
|
91
|
throw new IllegalArgumentException(
|
92
|
"segment points have to be contained"); //$NON-NLS-1$
|
93
|
}
|
94
|
|
95
|
// check if segmentStart->segmentEnd is a legal segment or a single
|
96
|
// point
|
97
|
Vector segmentDirection = segmentEnd.getSubtracted(segmentStart);
|
98
|
if (segmentDirection.isNull()) {
|
99
|
return other.contains(segmentStart);
|
100
|
}
|
101
|
|
102
|
// legal segment, check if there is an intersection within the segment
|
103
|
if (intersects(other)) {
|
104
|
Vector intersection = getIntersection(other);
|
105
|
return containsWithinSegment(segmentStart, segmentEnd, intersection);
|
106
|
}
|
107
|
return false;
|
108
|
}
|
109
|
|
110
|
/**
|
111
|
* Computes the intersection point of this Straight and the provided one, if
|
112
|
* it exists.
|
113
|
*
|
114
|
* @param other
|
115
|
* The Straight to use for calculations.
|
116
|
* @return A Vector pointing to the intersection point, if it exists, null
|
117
|
* if no intersection point exists (or the Straights are equal).
|
118
|
*/
|
119
|
public Vector getIntersection(Straight other) {
|
120
|
// first check if there is a single intersection point
|
121
|
if (!intersects(other)) {
|
122
|
return null;
|
123
|
}
|
124
|
// calculate intersection point
|
125
|
Vector s1 = direction.getMultiplied(other.position
|
126
|
.getDotProduct(other.direction.getOrthogonalComplement()));
|
127
|
Vector s2 = other.direction.getMultiplied(position
|
128
|
.getDotProduct(direction.getOrthogonalComplement()));
|
129
|
return s1.getSubtracted(s2).getDivided(
|
130
|
direction.getDotProduct(other.direction
|
131
|
.getOrthogonalComplement()));
|
132
|
}
|
133
|
|
134
|
/**
|
135
|
* Returns the (smallest) angle between this Straight and the provided one.
|
136
|
*
|
137
|
* @param other
|
138
|
* The Straight to be used for the calculation.
|
139
|
* @return The angle spanned between the two Straights.
|
140
|
*/
|
141
|
public double getAngle(Straight other) {
|
142
|
return direction.getAngle(other.direction);
|
143
|
}
|
144
|
|
145
|
/**
|
146
|
* Returns the projection of the given Vector onto this Straight, which is
|
147
|
* the point on this Straight with the minimal distance to the point,
|
148
|
* denoted by the provided Vector.
|
149
|
*
|
150
|
* @param vector
|
151
|
* The Vector whose projection should be determined.
|
152
|
* @return A new Vector representing the projection of the provided Vector
|
153
|
* onto this Straight.
|
154
|
*/
|
155
|
public Vector getProjection(Vector vector) {
|
156
|
return getIntersection(new Straight(vector,
|
157
|
direction.getOrthogonalComplement()));
|
158
|
}
|
159
|
|
160
|
/**
|
161
|
* Returns the distance of the provided Vector to this Straight, which is
|
162
|
* the distance between the provided Vector and its projection onto this
|
163
|
* Straight.
|
164
|
*
|
165
|
* @param vector
|
166
|
* The Vector whose distance is to be calculated.
|
167
|
* @return the distance between this Straight and the provided Vector.
|
168
|
*/
|
169
|
public double getDistance(Vector vector) {
|
170
|
return getProjection(vector).getSubtracted(vector).getLength();
|
171
|
}
|
172
|
|
173
|
/**
|
174
|
* Calculates whether the point indicated by the provided Vector is a point
|
175
|
* on this Straight.
|
176
|
*
|
177
|
* @param vector
|
178
|
* the Vector who has to be checked.
|
179
|
* @return true if the point indicated by the given Vector is a point of
|
180
|
* this Straight, false otherwise.
|
181
|
*/
|
182
|
public boolean contains(Vector vector) {
|
183
|
return getDistance(vector) == 0;
|
184
|
}
|
185
|
|
186
|
/**
|
187
|
* Calculates whether the point indicated by the provided Vector is a point
|
188
|
* on the straight segment between the given start and end points.
|
189
|
*
|
190
|
* @param segmentStart
|
191
|
* a Vector indicating the start point of the segment. Has to be
|
192
|
* a point on the straight.
|
193
|
* @param segmentEnd
|
194
|
* a Vector indicating the end point of the segment. Has to be a
|
195
|
* point on the straight.
|
196
|
* @param vector
|
197
|
* the Vector who has to be checked.
|
198
|
* @return true if point indicated by the given Vector is a point on this
|
199
|
* straight, within the specified segment, false otherwise.
|
200
|
*/
|
201
|
public boolean containsWithinSegment(Vector segmentStart,
|
202
|
Vector segmentEnd, Vector vector) {
|
203
|
// precondition: segment start and end have to be points on this
|
204
|
// straight.
|
205
|
if (!contains(segmentStart) || !contains(segmentEnd)) {
|
206
|
throw new IllegalArgumentException(
|
207
|
"segment points have to be contained"); //$NON-NLS-1$
|
208
|
}
|
209
|
|
210
|
// check if segmentStart->segmentEnd is a legal segment or a single
|
211
|
// point
|
212
|
Vector segmentDirection = segmentEnd.getSubtracted(segmentStart);
|
213
|
if (segmentDirection.isNull()) {
|
214
|
return segmentStart.equals(vector);
|
215
|
}
|
216
|
|
217
|
// legal segment
|
218
|
if (new Straight(segmentStart, segmentDirection).contains(vector)) {
|
219
|
// compute parameter s, so that vector = segmentStart + s *
|
220
|
// (segmentEnd - segmentStart).
|
221
|
double s = segmentDirection.isVertical() ? (vector.y - segmentDirection.y)
|
222
|
/ segmentDirection.y
|
223
|
: (vector.x - segmentStart.x) / segmentDirection.x;
|
224
|
// if s is between 0 and 1, intersection point lies within
|
225
|
// segment
|
226
|
if (0 <= s && s <= 1) {
|
227
|
return true;
|
228
|
}
|
229
|
}
|
230
|
return false;
|
231
|
}
|
232
|
|
233
|
/**
|
234
|
* Checks whether this Straight and the provided one are parallel to each
|
235
|
* other.
|
236
|
*
|
237
|
* @param other
|
238
|
* The Straight to test for parallelism.
|
239
|
* @return true if the direction vectors of this Straight and the provided
|
240
|
* one are parallel, false otherwise.
|
241
|
*/
|
242
|
public boolean isParallelTo(Straight other) {
|
243
|
return direction.isParallelTo(other.direction);
|
244
|
}
|
245
|
|
246
|
/**
|
247
|
* Checks whether this Straight is equal to the provided Straight. Two
|
248
|
* Straights s1 and s2 are equal, if the position vector of s2 is a point on
|
249
|
* s1 and the direction vectors of s1 and s2 are parallel.
|
250
|
*
|
251
|
* @see java.lang.Object#equals(java.lang.Object)
|
252
|
*/
|
253
|
public boolean equals(Object other) {
|
254
|
if (!(other instanceof Straight)) {
|
255
|
return false;
|
256
|
} else {
|
257
|
Straight otherStraight = (Straight) other;
|
258
|
return contains(otherStraight.position)
|
259
|
&& isParallelTo(otherStraight);
|
260
|
}
|
261
|
}
|
262
|
|
263
|
/**
|
264
|
* @see java.lang.Object#hashCode()
|
265
|
*/
|
266
|
public int hashCode() {
|
267
|
return position.hashCode() + direction.hashCode();
|
268
|
}
|
269
|
|
270
|
/**
|
271
|
* @see java.lang.Object#toString()
|
272
|
*/
|
273
|
public String toString() {
|
274
|
return position.toString() + " + s * " + direction.toString(); //$NON-NLS-1$
|
275
|
}
|
276
|
|
277
|
}
|