1 package org.newdawn.slick.geom;
2
3 import javax.annotation.Nonnull;
4 import javax.annotation.Nullable;
5
6
7
8
9
10
11
12
13 public class Line extends Shape {
14
15
16
17 private static final long serialVersionUID = 1L;
18
19 private Vector2f start;
20
21 private Vector2f end;
22
23 private Vector2f vec;
24
25 @Nonnull
26 private final Vector2f loc = new Vector2f(0, 0);
27
28 @Nonnull
29 private final Vector2f closest = new Vector2f(0, 0);
30
31
32
33
34
35
36
37
38
39
40
41
42 private Line(float x, float y, boolean inner, boolean outer) {
43 this(0, 0, x, y);
44 }
45
46
47
48
49
50
51
52
53
54 public Line(float x, float y) {
55 this(x, y, true, true);
56 }
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public Line(float x1, float y1, float x2, float y2) {
71 this(new Vector2f(x1, y1), new Vector2f(x2, y2));
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public Line(float x1, float y1, float dx, float dy, boolean dummy) {
89 this(new Vector2f(x1, y1), new Vector2f(x1 + dx, y1 + dy));
90 }
91
92
93
94
95
96
97
98
99
100 public Line(float[] start, float[] end) {
101 super();
102
103 set(start, end);
104 }
105
106
107
108
109
110
111
112
113
114 private Line(Vector2f start, Vector2f end) {
115 super();
116
117 set(start, end);
118 }
119
120
121
122
123
124
125
126
127
128 void set(float[] start, float[] end) {
129 set(start[0], start[1], end[0], end[1]);
130 }
131
132
133
134
135
136
137 public Vector2f getStart() {
138 return start;
139 }
140
141
142
143
144
145
146 public Vector2f getEnd() {
147 return end;
148 }
149
150
151
152
153
154
155 public float length() {
156 return vec.length();
157 }
158
159
160
161
162
163
164 public float lengthSquared() {
165 return vec.lengthSquared();
166 }
167
168
169
170
171
172
173
174
175
176 void set(Vector2f start, Vector2f end) {
177 super.pointsDirty = true;
178 if (this.start == null) {
179 this.start = new Vector2f();
180 }
181 this.start.set(start);
182
183 if (this.end == null) {
184 this.end = new Vector2f();
185 }
186 this.end.set(end);
187
188 vec = new Vector2f(end);
189 vec.sub(start);
190
191 vec.lengthSquared();
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206 public void set(float sx, float sy, float ex, float ey) {
207 super.pointsDirty = true;
208 start.set(sx, sy);
209 end.set(ex, ey);
210 float dx = (ex - sx);
211 float dy = (ey - sy);
212 vec.set(dx,dy);
213 }
214
215
216
217
218
219
220 public float getDX() {
221 return end.getX() - start.getX();
222 }
223
224
225
226
227
228
229 public float getDY() {
230 return end.getY() - start.getY();
231 }
232
233
234
235
236 public float getX() {
237 return getX1();
238 }
239
240
241
242
243 public float getY() {
244 return getY1();
245 }
246
247
248
249
250
251
252 float getX1() {
253 return start.getX();
254 }
255
256
257
258
259
260
261 float getY1() {
262 return start.getY();
263 }
264
265
266
267
268
269
270 float getX2() {
271 return end.getX();
272 }
273
274
275
276
277
278
279 float getY2() {
280 return end.getY();
281 }
282
283
284
285
286
287
288
289
290 public float distance(Vector2f point) {
291 return (float) Math.sqrt(distanceSquared(point));
292 }
293
294
295
296
297
298
299
300
301 public boolean on(@Nonnull Vector2f point) {
302 getClosestPoint(point, closest);
303
304 return point.equals(closest);
305 }
306
307
308
309
310
311
312
313
314 public float distanceSquared(Vector2f point) {
315 getClosestPoint(point, closest);
316 closest.sub(point);
317
318 float result = closest.lengthSquared();
319
320 return result;
321 }
322
323
324
325
326
327
328
329
330
331 void getClosestPoint(Vector2f point, @Nonnull Vector2f result) {
332 loc.set(point);
333 loc.sub(start);
334
335 float projDistance = vec.dot(loc);
336
337 projDistance /= vec.lengthSquared();
338
339 if (projDistance < 0) {
340 result.set(start);
341 return;
342 }
343 if (projDistance > 1) {
344 result.set(end);
345 return;
346 }
347
348 result.x = start.getX() + projDistance * vec.getX();
349 result.y = start.getY() + projDistance * vec.getY();
350 }
351
352
353
354
355 @Nonnull
356 public String toString() {
357 return "[Line " + start + "," + end + "]";
358 }
359
360
361
362
363
364
365
366
367 @Nullable
368 public Vector2f intersect(@Nonnull Line other) {
369 return intersect(other, false);
370 }
371
372
373
374
375
376
377
378
379
380
381 @Nullable
382 public Vector2f intersect(@Nonnull Line other, boolean limit) {
383 Vector2f temp = new Vector2f();
384
385 if (!intersect(other, limit, temp)) {
386 return null;
387 }
388
389 return temp;
390 }
391
392
393
394
395
396
397
398
399
400
401
402
403 boolean intersect(@Nonnull Line other, boolean limit, @Nonnull Vector2f result) {
404 float dx1 = end.getX() - start.getX();
405 float dx2 = other.end.getX() - other.start.getX();
406 float dy1 = end.getY() - start.getY();
407 float dy2 = other.end.getY() - other.start.getY();
408 float denom = (dy2 * dx1) - (dx2 * dy1);
409
410 if (denom == 0) {
411 return false;
412 }
413
414 float ua = (dx2 * (start.getY() - other.start.getY()))
415 - (dy2 * (start.getX() - other.start.getX()));
416 ua /= denom;
417 float ub = (dx1 * (start.getY() - other.start.getY()))
418 - (dy1 * (start.getX() - other.start.getX()));
419 ub /= denom;
420
421 if ((limit) && ((ua < 0) || (ua > 1) || (ub < 0) || (ub > 1))) {
422 return false;
423 }
424
425 float u = ua;
426
427 float ix = start.getX() + (u * (end.getX() - start.getX()));
428 float iy = start.getY() + (u * (end.getY() - start.getY()));
429
430 result.set(ix, iy);
431 return true;
432 }
433
434
435
436
437 protected void createPoints() {
438 points = new float[4];
439 points[0] = getX1();
440 points[1] = getY1();
441 points[2] = getX2();
442 points[3] = getY2();
443 }
444
445
446
447
448 @Nonnull
449 public Shape transform(@Nonnull Transform transform) {
450 float[] temp = new float[4];
451 createPoints();
452 transform.transform(points, 0, temp, 0, 2);
453
454 return new Line(temp[0], temp[1], temp[2], temp[3]);
455 }
456
457
458
459
460 public boolean closed() {
461 return false;
462 }
463
464
465
466
467 public boolean intersects(@Nonnull Shape shape)
468 {
469 if (shape instanceof Circle)
470 {
471 return shape.intersects(this);
472 }
473 return super.intersects(shape);
474 }
475 }