1
2
3
4
5
6
7
8
9
10
11 package nl.tudelft.simulation.traffic.vehicle;
12
13 import java.rmi.RemoteException;
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
17 import javax.media.j3d.Bounds;
18 import javax.media.j3d.Transform3D;
19 import javax.vecmath.Point3d;
20 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
21 import nl.tudelft.simulation.dsol.simulators.DEVDESSSimulatorInterface;
22 import nl.tudelft.simulation.dsol.statistics.charts.XYChart;
23 import nl.tudelft.simulation.event.EventInterface;
24 import nl.tudelft.simulation.event.EventProducer;
25 import nl.tudelft.simulation.event.EventProducerInterface;
26 import nl.tudelft.simulation.event.EventType;
27 import nl.tudelft.simulation.event.TimedEvent;
28 import nl.tudelft.simulation.language.d3.BoundingBox;
29 import nl.tudelft.simulation.language.d3.DirectedPoint;
30 import nl.tudelft.simulation.logger.Logger;
31 import nl.tudelft.simulation.traffic.animation.VehicleAnimation;
32 import nl.tudelft.simulation.traffic.controlpoint.ControlPointInterface;
33 import nl.tudelft.simulation.traffic.controlpoint.real.Changeable;
34 import nl.tudelft.simulation.traffic.controlpoint.real.SpeedLimitInterface;
35 import nl.tudelft.simulation.traffic.controlpoint.real.StopSignInterface;
36 import nl.tudelft.simulation.traffic.controlpoint.util.ControlPointsList;
37 import nl.tudelft.simulation.traffic.track.Track;
38 import nl.tudelft.simulation.traffic.track.TrackInterface;
39 import nl.tudelft.simulation.traffic.track.TrackLinkInterface;
40 import nl.tudelft.simulation.traffic.track.util.TrackProgression;
41
42 /***
43 * <br>
44 * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
45 * University of Technology </a>, the Netherlands. <br>
46 * See for project information <a href="http://www.simulation.tudelft.nl">
47 * www.simulation.tudelft.nl </a> <br>
48 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
49 * License (GPL) </a>, no warranty <br>
50 *
51 * @version Jul 4, 2004 <br>
52 * @author <a
53 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
54 * Verbraeck </a>
55 */
56 public class VehiclePhysical extends EventProducer
57 implements
58 VehiclePhysicalInterface
59 {
60 /*** the simulator to schedule on */
61 private DEVDESSSimulatorInterface simulator;
62
63 /*** the vehicle type with all relevant information */
64 private VehicleType vehicleType;
65
66 /*** vehicle control of this vehicle */
67 private VehicleControlInterface vehicleControl;
68
69 /*** current track to travel on */
70 private List currentTracks = new ArrayList();
71
72 /*** current progression on the current track */
73 private double progression;
74
75 /*** current speed */
76 private double currentSpeed = 0.0;
77
78 /*** total distance traveled since creation */
79 private double distanceTraveled;
80
81 /*** are we allowed to drive? */
82 private boolean driving = false;
83
84 /*** the differential equations to make the vehicle move */
85 private VehiclePositioner vehiclePositioner;
86
87 /*** current maximum speed */
88 private double currentMaximumSpeed;
89
90 /*** acceleration profile */
91 private AccelerationProfile accelerationProfile;
92
93 /*** deceleration profile */
94 private DecelerationProfile decelerationProfile;
95
96 /*** the progression horizon to look for control points */
97 private double horizon;
98
99 /*** the control points between the current position and the horizon */
100 private List speedControlPoints = new ArrayList();
101
102 /*** the array of control points on the current track */
103 private List trackControlPointsList = new ArrayList();
104
105 /*** the unique name */
106 private String name;
107
108 /*** the chart to display the speed vs time graph */
109 private XYChart tvChart;
110
111 /*** the chart to display the speed vs progression graph */
112 private XYChart xvChart;
113
114 /*** the t-v event type to use for the xyChart */
115 public EventType TIME_SPEED_1SECOND_EVENT = new EventType("tv");
116
117 /*** the x-v event type to use for the xyChart */
118 public EventType DISTANCE_SPEED_1SECOND_EVENT = new EventType("xv");
119
120 /*** last second in the chart */
121 private double sampleSecond = -10.0;
122
123 /*** helper string */
124 private String lastString;
125
126 /*** the maximum braking distance */
127 private double maxBrakeDistance;
128
129 /***
130 * Create a physical vehicle
131 *
132 * @param vehicleType
133 * @param vehicleControl
134 * @param track
135 * @param progression
136 * @param maxSpeedStart
137 * @param simulator
138 */
139 public VehiclePhysical(final VehicleType vehicleType,
140 final VehicleControlInterface vehicleControl,
141 final TrackInterface track, final double progression,
142 final double maxSpeedStart,
143 final DEVDESSSimulatorInterface simulator)
144 {
145 try
146 {
147 this.simulator = simulator;
148 this.distanceTraveled = 0;
149 this.name = vehicleType.generateUniqueName();
150 this.vehicleType = vehicleType;
151 this.accelerationProfile = vehicleType.getAccelerationProfile();
152 this.decelerationProfile = vehicleType.getDecelerationProfile();
153 this.maxBrakeDistance = this.decelerationProfile.getBrakeDistance(
154 vehicleType.getVehicleMaximumSpeed(), 0.0);
155 this.horizon = this.maxBrakeDistance * 1.5;
156 System.out.println("Horizon for vehicle " + this.name + " is "
157 + this.horizon);
158 this.vehicleControl = vehicleControl;
159 moveToFirstTrack(track, progression);
160 this.currentMaximumSpeed = maxSpeedStart;
161 if (simulator instanceof AnimatorInterface)
162 {
163 ArrayList segments = this.vehicleType.getSegments();
164 if (segments.isEmpty())
165 {
166 new VehicleAnimation(this, simulator, this.vehicleType
167 .getColor());
168 } else
169 {
170 for (int i = 0; i < segments.size(); i++)
171 {
172 VehicleType.Segment segment = (VehicleType.Segment) segments
173 .get(i);
174 new VehicleSegment(this, simulator, vehicleType
175 .getColor(), segment.getFront(), segment
176 .getAxle1(), segment.getAxle2(), segment
177 .getLength());
178 }
179 }
180
181 this.tvChart = new XYChart(simulator, "t-v vehicle "
182 + this.name);
183 this.tvChart.getChart().getXYPlot().getDomainAxis()
184 .setAutoRange(true);
185 this.tvChart.getChart().getXYPlot().getDomainAxis().setLabel(
186 "time (s)");
187 this.tvChart.getChart().getXYPlot().getRangeAxis()
188 .setAutoRange(false);
189 this.tvChart.getChart().getXYPlot().getRangeAxis()
190 .setLowerBound(0.0);
191 this.tvChart.getChart().getXYPlot().getRangeAxis()
192 .setUpperBound(
193 this.vehicleType.getVehicleMaximumSpeed());
194 this.tvChart.getChart().getXYPlot().getRangeAxis().setLabel(
195 "speed (m/s)");
196 this.TIME_SPEED_1SECOND_EVENT = new EventType("t-v vehicle "
197 + this.name);
198 this.tvChart.add("t-v vehicle " + this.name, this,
199 this.TIME_SPEED_1SECOND_EVENT);
200
201 this.xvChart = new XYChart(simulator, "x-v vehicle "
202 + this.name);
203 this.xvChart.getChart().getXYPlot().getDomainAxis()
204 .setAutoRange(true);
205 this.xvChart.getChart().getXYPlot().getDomainAxis().setLabel(
206 "progression (m)");
207 this.xvChart.getChart().getXYPlot().getRangeAxis()
208 .setAutoRange(false);
209 this.xvChart.getChart().getXYPlot().getRangeAxis()
210 .setLowerBound(0.0);
211 this.xvChart.getChart().getXYPlot().getRangeAxis()
212 .setUpperBound(
213 this.vehicleType.getVehicleMaximumSpeed());
214 this.xvChart.getChart().getXYPlot().getRangeAxis().setLabel(
215 "speed (m/s)");
216 this.DISTANCE_SPEED_1SECOND_EVENT = new EventType(
217 "x-v vehicle " + this.name);
218 this.xvChart.add("x-v vehicle " + this.name, this,
219 this.DISTANCE_SPEED_1SECOND_EVENT);
220 }
221 this.vehiclePositioner = new VehiclePositioner(this, simulator);
222 this.vehiclePositioner.setValue(0.0, progression);
223 } catch (Exception exception)
224 {
225 exception.printStackTrace();
226 }
227 }
228
229 /***
230 * @see nl.tudelft.simulation.event.EventProducerInterface#getEventTypes()
231 */
232 public synchronized EventType[] getEventTypes()
233 {
234 return new EventType[]{};
235 }
236
237 /***
238 * rebuilds the list of control points between the current location and the
239 * horizon. Always take at least two tracks, where the second track should
240 * be longer than the max brake distance.
241 */
242 private void readControlPointsWithinHorizon()
243 {
244 Logger.fine(this, "readControlPointsWithinHorizon", this.name
245 + ": Making new horizon list for track "
246 + this.getCurrentTrack());
247 this.speedControlPoints.clear();
248
249 TrackInterface track = this.getCurrentTrack();
250 double progression = 0.0;
251 while (progression < this.horizon + this.getCurrentTrack().getLength())
252 {
253 if (track == null)
254 return;
255
256 ControlPointsList cpList = track.getControlPoints();
257 Iterator it = cpList.iterator();
258 while (it.hasNext())
259 {
260 ControlPointInterface cp = (ControlPointInterface) it.next();
261
262 if (cp instanceof Changeable)
263 {
264 try
265 {
266 ((EventProducerInterface) cp).addListener(this,
267 Changeable.CHANGE_STATUS_EVENT);
268 } catch (Exception e)
269 {
270 Logger
271 .severe(this, "readControlPointsWithinHorizon",
272 e);
273 }
274 }
275
276
277
278 if ((cp instanceof Changeable)
279 || (cp instanceof SpeedLimitInterface)
280 || (cp instanceof StopSignInterface))
281 {
282 ControlPointProgression cpp = new ControlPointProgression(
283 cp, progression + cp.getProgression());
284 this.speedControlPoints.add(cpp);
285 Logger.fine(this, "readControlPointsWithinHorizon",
286 " ..." + cp + ", distance = " + progression
287 + cp.getProgression());
288 }
289 }
290 progression += track.getLength();
291 TrackLinkInterface link = track.getEndLink();
292 track = link.getActiveSuccessor(getCurrentTrack());
293 }
294 }
295
296 /***
297 * indicate that the vehicle can start driving. As long as this variable is
298 * false, the acceleration remains zero.
299 *
300 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#startDriving()
301 */
302 public void startDriving()
303 {
304 this.driving = true;
305 }
306
307 /***
308 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#getCurrentAcceleration(double,
309 * double)
310 */
311 public double getCurrentAcceleration(final double speed,
312 final double progression)
313 {
314 try
315 {
316 double time = this.simulator.getSimulatorTime();
317
318 if (time - this.sampleSecond > 1.0)
319 {
320 this.fireEvent(new TimedEvent(this.TIME_SPEED_1SECOND_EVENT,
321 this, new Double(speed), time));
322 this.fireEvent(new TimedEvent(
323 this.DISTANCE_SPEED_1SECOND_EVENT, this, new Double(
324 speed), this.distanceTraveled));
325 this.sampleSecond = time;
326 }
327 } catch (RemoteException e)
328 {
329 e.printStackTrace();
330 }
331
332
333
334 if (!this.driving)
335 {
336 return 0.0;
337 }
338
339 double accdec = 0.0;
340 if (speed < this.currentMaximumSpeed)
341 {
342 accdec = this.accelerationProfile.getAcceleration(speed);
343 }
344
345
346
347
348
349
350 double brakeDistance0 = this.decelerationProfile.getBrakeDistance(
351 speed, 0) + 1.01;
352
353 double predecessorDistance = calculatePredecessorDistance(progression,
354 brakeDistance0);
355 if (predecessorDistance < brakeDistance0)
356 {
357 if (speed > 0)
358 return this.decelerationProfile.getDeceleration(speed);
359 else
360 return 0.0;
361 }
362
363 Iterator it = this.speedControlPoints.iterator();
364 boolean finished = false;
365 while (it.hasNext() && !finished)
366 {
367 ControlPointProgression cpp = (ControlPointProgression) it.next();
368 ControlPointInterface cp = cpp.getControlPoint();
369 double cpDistance = cpp.getDistance() - progression;
370 if (cpDistance > brakeDistance0)
371 finished = true;
372
373
374
375 if (cpDistance > 0.0)
376 {
377
378 if (cp instanceof SpeedLimitInterface)
379 {
380 if (cpDistance <= this.decelerationProfile
381 .getBrakeDistance(speed, ((SpeedLimitInterface) cp)
382 .getSpeedLimit()))
383 {
384 if (!cp.toString().equals(this.lastString))
385 {
386 this.lastString = cp.toString();
387 Logger
388 .fine(
389 this,
390 "getCurrentAcceleration",
391 this.name
392 + " braking for speedlimit cp "
393 + this.lastString
394 + ", cpDistance="
395 + cpDistance
396 + "\n brakeDistance="
397 + this.decelerationProfile
398 .getBrakeDistance(
399 speed,
400 ((SpeedLimitInterface) cp)
401 .getSpeedLimit())
402 + ", progression="
403 + this.progression
404 + "\n track="
405 + this.getCurrentTrack()
406 + ", length="
407 + this.getCurrentTrack()
408 .getLength());
409 }
410 accdec = this.decelerationProfile
411 .getDeceleration(speed);
412 finished = true;
413 }
414 }
415
416 else if (cp instanceof StopSignInterface)
417 {
418 if (((StopSignInterface) cp).getStatus().equals(
419 StopSignInterface.STOP)
420 && (cpDistance <= brakeDistance0))
421 {
422 if (!cp.toString().equals(this.lastString))
423 {
424 this.lastString = cp.toString();
425 Logger.fine(this, "getCurrentAcceleration",
426 this.name
427 + " braking for trafficlight cp "
428 + this.lastString
429 + ", cpDistance="
430 + cpDistance
431 + "\n brakeDistance="
432 + brakeDistance0
433 + ", progression="
434 + this.progression
435 + "\n track="
436 + this.getCurrentTrack()
437 + ", length="
438 + this.getCurrentTrack()
439 .getLength());
440 }
441 accdec = this.decelerationProfile
442 .getDeceleration(speed);
443 finished = true;
444 }
445
446
447 if (((StopSignInterface) cp).getStatus().equals(
448 StopSignInterface.STOP)
449 && (cpDistance <= 1.01))
450 {
451 if (speed > 0)
452 accdec = this.decelerationProfile
453 .getDeceleration(speed);
454 else
455 accdec = 0.0;
456 }
457 }
458 }
459 }
460 return accdec;
461 }
462
463 /***
464 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#setSpeedAndProgression(double,
465 * double)
466 */
467 public double[] setSpeedAndProgression(final double speed,
468 final double progression)
469 {
470 this.currentSpeed = speed;
471
472
473 this.distanceTraveled += progression - this.progression;
474 TrackInterface track = this.getCurrentTrack();
475
476
477
478 if (progression < track.getLength())
479 {
480 driveOverControlPoints(this.progression, progression);
481 this.progression = progression;
482 } else
483 {
484
485
486 driveOverControlPoints(this.progression, track.getLength());
487 double restProgression = Math.max(0.0, track.getLength()
488 - this.progression);
489 moveToNextTrack();
490 track = this.getCurrentTrack();
491 driveOverControlPoints(0.0, restProgression);
492 this.vehiclePositioner.setValue(this.currentSpeed, restProgression);
493 this.progression = restProgression;
494 }
495 return new double[]{this.currentSpeed, this.progression};
496 }
497
498 /***
499 * The front of the vehicle passes the track limit. Add a new track to the
500 * current track list. The progression on the new track will be 0. The
501 * 'update' method is responsible for deleting trailing tracks that are no
502 * longer needed.
503 *
504 * Note: the vehicle is only registered on the track of the front of the
505 * vehicle.
506 */
507 protected void moveToNextTrack()
508 {
509 getCurrentTrack().removeVehicle(this);
510 TrackLinkInterface link = getCurrentTrack().getEndLink();
511 TrackInterface newCurrentTrack = link
512 .getActiveSuccessor(getCurrentTrack());
513 this.progression = 0;
514 this.currentTracks.add(newCurrentTrack);
515 Logger.fine(this, "moveToNextTrack", this.name
516 + " moved to next track " + this.getCurrentTrack());
517 readControlPointsWithinHorizon();
518 makeControlPointsArray(newCurrentTrack);
519 newCurrentTrack.addVehicle(this);
520 }
521
522 /***
523 * @param track
524 * @param progression
525 */
526 protected void moveToFirstTrack(final TrackInterface track,
527 final double progression)
528 {
529 this.currentTracks.add(track);
530 this.progression = progression;
531 this.currentTracks.add(track);
532 readControlPointsWithinHorizon();
533 makeControlPointsArray(track);
534 track.addVehicle(this);
535 }
536
537 /***
538 * @param progression
539 * @param maxDistance
540 * @return
541 */
542 private double calculatePredecessorDistance(final double progression,
543 final double maxDistance)
544 {
545 double rest = maxDistance;
546 TrackInterface track = getCurrentTrack();
547 double length = track.getLength() - progression;
548 while (rest > 0)
549 {
550 List vehicleList = track.getVehiclesOnTrack();
551 for (int i = 0; i < vehicleList.size(); i++)
552 {
553 VehiclePhysicalInterface vehicle = (VehiclePhysicalInterface) vehicleList
554 .get(i);
555 if (vehicle != this)
556 {
557 double distance = Track.calculateDistanceFrontBack(this,
558 vehicle);
559 if (distance > 0)
560 return distance;
561 }
562 }
563 rest -= length;
564 track = track.getEndLink().getActiveSuccessor(track);
565 if (track == null)
566 return (maxDistance + 1.0);
567 length = track.getLength();
568 }
569 return (maxDistance + 1.0);
570 }
571
572 /***
573 * @param track
574 */
575 private void makeControlPointsArray(final TrackInterface track)
576 {
577 this.trackControlPointsList.clear();
578 ControlPointsList cpl = track.getControlPoints();
579 Iterator it = cpl.iterator();
580 while (it.hasNext())
581 {
582 ControlPointInterface cp = (ControlPointInterface) it.next();
583 this.trackControlPointsList.add(cp);
584 }
585 }
586
587 /***
588 * @param from
589 * @param to
590 */
591 protected void driveOverControlPoints(final double from, final double to)
592 {
593 boolean finished = false;
594 while (!finished)
595 {
596 if (this.trackControlPointsList.size() == 0)
597 finished = true;
598 else
599 {
600 ControlPointInterface cp = (ControlPointInterface) this.trackControlPointsList
601 .get(0);
602 if (cp.getProgression() >= from - 0.001
603 && cp.getProgression() <= to + 0.001)
604 {
605 System.out.println(this.name + " drove over cp " + cp);
606 this.trackControlPointsList.remove(0);
607
608 Iterator it = this.speedControlPoints.iterator();
609 while (it.hasNext())
610 {
611 ControlPointProgression cpp = (ControlPointProgression) it
612 .next();
613 if (cpp.getControlPoint().equals(cp))
614 {
615 System.out
616 .println("also removed from speedControlPoints: "
617 + cp);
618 it.remove();
619 }
620 }
621 cp.pass(this);
622 } else
623 {
624 finished = true;
625 }
626 }
627 }
628 }
629
630 /***
631 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#getCurrentSpeed()
632 */
633 public double getCurrentSpeed()
634 {
635 return this.currentSpeed;
636 }
637
638 /***
639 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#setMaximumSpeed(double)
640 */
641 public void setMaximumSpeed(final double maxSpeed)
642 {
643 this.currentMaximumSpeed = maxSpeed;
644 }
645
646 /***
647 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#getProgression()
648 */
649 public double getProgression()
650 {
651 return this.progression;
652 }
653
654 /***
655 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#getCurrentTrack()
656 */
657 public TrackInterface getCurrentTrack()
658 {
659 return (TrackInterface) this.currentTracks.get(this.currentTracks
660 .size() - 1);
661 }
662
663 /***
664 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#getVehicleType()
665 */
666 public VehicleType getVehicleType()
667 {
668 return this.vehicleType;
669 }
670
671 /***
672 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#getVehicleControl()
673 */
674 public VehicleControlInterface getVehicleControl()
675 {
676 return this.vehicleControl;
677 }
678
679 /***
680 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#setVehicleControl(nl.tudelft.simulation.traffic.vehicle.VehicleControlInterface)
681 */
682 public void setVehicleControl(VehicleControlInterface vehicleControl)
683 {
684 this.vehicleControl = vehicleControl;
685 }
686
687 /***
688 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#getDistanceTraveled()
689 */
690 public double getDistanceTraveled()
691 {
692 return this.distanceTraveled;
693 }
694
695 /***
696 * @see nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface#removeVehicle()
697 */
698 public void removeVehicle() throws RemoteException
699 {
700
701 getCurrentTrack().removeVehicle(this);
702 this.vehicleControl.removeVehicle();
703 this.fireEvent(VehiclePhysicalInterface.REMOVE_EVENT, true);
704 removeAllListeners();
705 this.vehiclePositioner.stopIntegration();
706 this.driving = false;
707 }
708
709 /***
710 * @see nl.tudelft.simulation.event.EventListenerInterface#notify(nl.tudelft.simulation.event.EventInterface)
711 */
712 public void notify(EventInterface event) throws RemoteException
713 {
714 if (event.getType().equals(Changeable.CHANGE_STATUS_EVENT))
715 {
716 if (!this.driving)
717 {
718 ((EventProducerInterface) event.getSource()).removeListener(
719 this, Changeable.CHANGE_STATUS_EVENT);
720 }
721 this.readControlPointsWithinHorizon();
722 } else
723 System.err.println("Vehicle " + this.name + ": unknown event: "
724 + event);
725 }
726
727 /***
728 * @return the total length of the current track list
729 */
730 protected double getCurrentTracksLength()
731 {
732 double totalLength = 0.0;
733 for (int i = 0; i < this.currentTracks.size(); i++)
734 {
735 totalLength += ((TrackInterface) this.currentTracks.get(i))
736 .getLength();
737 }
738 return totalLength;
739 }
740
741 /***
742 * @see nl.tudelft.simulation.dsol.animation.LocatableInterface#getLocation()
743 */
744 public DirectedPoint getLocation()
745 {
746
747
748 DirectedPoint front = getCurrentTrack().getLocationOfProgression(
749 this.progression);
750 TrackProgression tp = getCurrentTrack()
751 .calculateTrackProgressionListActive(
752 this.progression - this.vehicleType.getLength());
753 if (tp == null)
754 {
755 tp = getCurrentTrack().calculateTrackProgressionListActive(
756 this.progression - 0.1);
757 }
758 if (tp == null)
759 return new DirectedPoint(front.x, front.y, 0.1, 0, 0, 0);
760 DirectedPoint back = tp.getTrack().getLocationOfProgression(
761 tp.getProgression());
762 double theta = Math.atan2(back.y - front.y, back.x - front.x);
763 return new DirectedPoint(front.x, front.y, front.z + 0.05, 0, 0, theta);
764 }
765
766 /***
767 * get a location along the track to the back
768 *
769 * @param distance
770 * @return the location
771 */
772 public Point3d getBackwardLocation(final double distance)
773 {
774 TrackProgression tp = getCurrentTrack()
775 .calculateTrackProgressionListActive(
776 this.progression - distance);
777 if (tp == null)
778 {
779 System.err.println("ERROR " + this.name
780 + ": cannot calculate backwardLocation from "
781 + getCurrentTrack() + ", progression=" + this.progression
782 + ", back distance=" + distance);
783 tp = getCurrentTrack().calculateTrackProgressionListActive(
784 this.progression);
785 if (tp == null)
786 return new DirectedPoint(0, 0, 0);
787 }
788 DirectedPoint back = tp.getTrack().getLocationOfProgression(
789 tp.getProgression());
790 return new Point3d(back.x, back.y, back.z);
791 }
792
793 /***
794 * @see nl.tudelft.simulation.dsol.animation.LocatableInterface#getBounds()
795 */
796 public Bounds getBounds()
797 {
798 DirectedPoint location = getLocation();
799 double width = this.vehicleType.getWidth();
800 Bounds box = new BoundingBox(new Point3d(0.0, -width / 2.0, 0.0),
801 new Point3d(this.vehicleType.getLength(), width / 2.0,
802 0.0));
803 Transform3D rot = new Transform3D();
804 rot.rotZ(location.getRotZ());
805 box.transform(rot);
806 return box;
807 }
808
809 /***
810 * @see java.lang.Object#toString()
811 */
812 public String toString()
813 {
814 return this.name;
815 }
816
817 /***
818 *
819 * <br>
820 * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
821 * University of Technology </a>, the Netherlands. <br>
822 * See for project information <a href="http://www.simulation.tudelft.nl">
823 * www.simulation.tudelft.nl </a> <br>
824 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General
825 * Public License (GPL) </a>, no warranty <br>
826 *
827 * @version Jul 7, 2004 <br>
828 * @author <a
829 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
830 * Verbraeck </a>
831 */
832 private class ControlPointProgression
833 {
834 /*** the control point */
835 private ControlPointInterface controlPoint;
836
837 /*** the overall progression from the start of the first track */
838 private double distance;
839
840 /***
841 * @param controlPoint
842 * @param distance
843 */
844 public ControlPointProgression(
845 final ControlPointInterface controlPoint, final double distance)
846 {
847 this.controlPoint = controlPoint;
848 this.distance = distance;
849 }
850
851 /***
852 * @return Returns the controlPoint.
853 */
854 public ControlPointInterface getControlPoint()
855 {
856 return this.controlPoint;
857 }
858
859 /***
860 * @return Returns the distance.
861 */
862 public double getDistance()
863 {
864 return this.distance;
865 }
866
867 /***
868 * @see java.lang.Object#toString()
869 */
870 public String toString()
871 {
872 return "CPP:" + this.controlPoint + ", distance:" + this.distance;
873 }
874 }
875 }