Project

General

Profile

Download (8.75 KB) Statistics
| Branch: | Tag: | Revision:
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
}
(12-12/17)