1 package org.opentrafficsim.trafficcontrol.trafcod;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.awt.Component;
6 import java.awt.Dimension;
7 import java.awt.Graphics2D;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.ActionListener;
10 import java.awt.image.BufferedImage;
11 import java.util.ArrayList;
12 import java.util.Comparator;
13 import java.util.LinkedHashMap;
14 import java.util.LinkedHashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
19 import javax.swing.BoxLayout;
20 import javax.swing.ImageIcon;
21 import javax.swing.JCheckBox;
22 import javax.swing.JFrame;
23 import javax.swing.JLabel;
24 import javax.swing.JPanel;
25 import javax.swing.JScrollPane;
26 import javax.swing.SwingUtilities;
27
28 import org.djutils.exceptions.Throw;
29 import org.opentrafficsim.trafficcontrol.TrafficControlException;
30 import org.opentrafficsim.trafficcontrol.TrafficController;
31
32
33
34
35
36
37
38
39
40
41
42
43 public class Diagram
44 {
45
46
47 static final int DIVIDER_1 = 0;
48
49
50 static final int CAR_ROUNDABOUT_LEFT = 1;
51
52
53 static final int PT_DIV_L = 3;
54
55
56 static final int DIVIDER_2 = 4;
57
58
59 static final int CAR_LEFT = 5;
60
61
62 static final int CAR_CENTER = 7;
63
64
65 static final int CAR_RIGHT = 9;
66
67
68 static final int DIVIDER_3 = 10;
69
70
71 static final int PT_RIGHT_BICYCLE = 11;
72
73
74 static final int DIVIDER_4 = 12;
75
76
77 static final int BICYCLE = 13;
78
79
80 static final int DIVIDER_5 = 14;
81
82
83 static final int PT_BICYCLE_SIDEWALK = 15;
84
85
86 static final int DIVIDER_6 = 16;
87
88
89 static final int SIDEWALK = 17;
90
91
92 static final int DIVIDER_7 = 18;
93
94
95 static final int PT_SIDEWALK_SHOULDER = 19;
96
97
98 static final int SHOULDER = 20;
99
100
101 static final int BOUNDARY = 21;
102
103
104 private final List<Short> streams;
105
106
107 private final Map<Short, XYPair[]> routes = new LinkedHashMap<>();
108
109
110
111
112
113
114 public Diagram(final Set<Short> streams) throws TrafficControlException
115 {
116 this.streams = new ArrayList<Short>(streams);
117 this.streams.sort(new Comparator<Short>()
118 {
119
120 @Override
121 public int compare(final Short o1, final Short o2)
122 {
123 return o1 - o2;
124 }
125 });
126
127
128
129
130
131
132
133
134
135 for (short stream = 1; stream <= 12; stream += 3)
136 {
137 int quadrant = (stream - 1) / 3;
138 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
139 new RouteStep(-BOUNDARY, CAR_RIGHT),
140 new RouteStep(-SHOULDER, CAR_RIGHT, Command.STOP_LINE_AND_ICON),
141 new RouteStep(-CAR_CENTER, CAR_RIGHT),
142 new RouteStep(-CAR_CENTER, BOUNDARY))));
143 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
144 new RouteStep(-BOUNDARY, CAR_CENTER),
145 new RouteStep(-SHOULDER, CAR_CENTER, Command.STOP_LINE_AND_ICON),
146 new RouteStep(Command.IF, stream + 1 + 60),
147 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_CENTER),
148 new RouteStep(Command.ELSE),
149 new RouteStep(BOUNDARY, CAR_CENTER),
150 new RouteStep(Command.END_IF))));
151 this.routes.put((short) (stream + 2), rotateRoute(quadrant, assembleRoute(
152 new RouteStep(-BOUNDARY, CAR_LEFT),
153 new RouteStep(-SHOULDER, CAR_LEFT, Command.STOP_LINE_AND_ICON),
154 new RouteStep(Command.IF, stream + 2 + 60),
155 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_LEFT),
156 new RouteStep(Command.ELSE_IF, (stream + 10) % 12 + 60),
157 new RouteStep(CAR_CENTER, CAR_LEFT),
158 new RouteStep(CAR_CENTER, CAR_ROUNDABOUT_LEFT),
159 new RouteStep(Command.ELSE),
160 new RouteStep(-CAR_LEFT, CAR_LEFT),
161 new RouteStep(-CAR_LEFT, PT_DIV_L),
162 new RouteStep(-CAR_ROUNDABOUT_LEFT, PT_DIV_L),
163 new RouteStep(-CAR_ROUNDABOUT_LEFT, -CAR_LEFT),
164 new RouteStep(PT_DIV_L, -CAR_LEFT),
165 new RouteStep(PT_DIV_L, -CAR_CENTER),
166 new RouteStep(CAR_CENTER, -CAR_CENTER),
167 new RouteStep(CAR_CENTER, -BOUNDARY),
168 new RouteStep(Command.END_IF))));
169 }
170
171 for (short stream = 21; stream <= 28; stream += 2)
172 {
173 int quadrant = (stream - 19) / 2 % 4;
174 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
175 new RouteStep(DIVIDER_1, BICYCLE, Command.ICON),
176 new RouteStep(SHOULDER, BICYCLE),
177 new RouteStep(BOUNDARY, BICYCLE, Command.ICON))));
178 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
179 new RouteStep(-BOUNDARY, BICYCLE),
180 new RouteStep(-DIVIDER_3, BICYCLE, Command.ICON),
181 new RouteStep(Command.IF, stream),
182 new RouteStep(-DIVIDER_1, BICYCLE, Command.ICON),
183 new RouteStep(Command.ELSE),
184 new RouteStep(SHOULDER, BICYCLE),
185 new RouteStep(BOUNDARY, BICYCLE, Command.ICON),
186 new RouteStep(Command.END_IF))));
187 }
188
189 for (short stream = 31; stream <= 38; stream += 2)
190 {
191 int quadrant = (stream - 29) / 2 % 4;
192 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
193 new RouteStep(DIVIDER_1, SIDEWALK),
194 new RouteStep(BOUNDARY, SIDEWALK))));
195 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
196 new RouteStep(-BOUNDARY, SIDEWALK),
197 new RouteStep(Command.IF, stream),
198 new RouteStep(-DIVIDER_1, SIDEWALK),
199 new RouteStep(Command.ELSE),
200 new RouteStep(BOUNDARY, SIDEWALK),
201 new RouteStep(Command.END_IF))));
202 }
203
204 for (short stream = 41; stream <= 52; stream += 3)
205 {
206 int quadrant = (stream - 41) / 3;
207 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
208 new RouteStep(-BOUNDARY, PT_DIV_L),
209 new RouteStep(-SHOULDER, PT_DIV_L, Command.STOP_LINE),
210 new RouteStep(-PT_SIDEWALK_SHOULDER, PT_DIV_L, Command.ICON),
211 new RouteStep(-CAR_RIGHT, PT_DIV_L),
212 new RouteStep(-CAR_RIGHT, CAR_LEFT),
213 new RouteStep(-PT_DIV_L, CAR_LEFT),
214 new RouteStep(-PT_DIV_L, SHOULDER),
215 new RouteStep(-PT_DIV_L, BOUNDARY, Command.ICON))));
216 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
217 new RouteStep(-BOUNDARY, PT_DIV_L),
218 new RouteStep(-SHOULDER, PT_DIV_L, Command.STOP_LINE),
219 new RouteStep(-PT_SIDEWALK_SHOULDER, PT_DIV_L, Command.ICON),
220 new RouteStep(SHOULDER, PT_DIV_L),
221 new RouteStep(BOUNDARY, PT_DIV_L))));
222 this.routes.put((short) (stream + 2), rotateRoute(quadrant, assembleRoute(
223 new RouteStep(-BOUNDARY, PT_DIV_L),
224 new RouteStep(-SHOULDER, PT_DIV_L, Command.STOP_LINE),
225 new RouteStep(-PT_SIDEWALK_SHOULDER, PT_DIV_L, Command.ICON),
226 new RouteStep(-CAR_RIGHT, PT_DIV_L),
227 new RouteStep(-CAR_RIGHT, CAR_ROUNDABOUT_LEFT),
228 new RouteStep(-PT_DIV_L, CAR_ROUNDABOUT_LEFT),
229 new RouteStep(Command.IF, (stream + 2 - 40) % 12 + 60),
230 new RouteStep(-PT_DIV_L, -PT_DIV_L),
231 new RouteStep(PT_DIV_L, -PT_DIV_L),
232 new RouteStep(Command.ELSE),
233 new RouteStep(-PT_DIV_L, -CAR_CENTER),
234 new RouteStep(CAR_ROUNDABOUT_LEFT, -CAR_CENTER),
235 new RouteStep(CAR_ROUNDABOUT_LEFT, -CAR_RIGHT),
236 new RouteStep(PT_DIV_L, -CAR_RIGHT),
237 new RouteStep(Command.END_IF),
238 new RouteStep(PT_DIV_L, -SHOULDER),
239 new RouteStep(PT_DIV_L, -BOUNDARY, Command.ICON))));
240 }
241
242 for (short stream = 62; stream <= 72; stream += 3)
243 {
244 int quadrant = (stream - 61) / 3;
245 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
246 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_CENTER),
247 new RouteStep(CAR_ROUNDABOUT_LEFT, CAR_CENTER, Command.STOP_LINE_AND_ICON),
248 new RouteStep(BOUNDARY, CAR_CENTER))));
249 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
250 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_LEFT),
251 new RouteStep(CAR_ROUNDABOUT_LEFT, CAR_LEFT, Command.STOP_LINE_AND_ICON),
252 new RouteStep(CAR_CENTER, CAR_LEFT),
253 new RouteStep(Command.IF, ((stream - 61) + 11) % 12 + 60),
254 new RouteStep(CAR_CENTER, CAR_ROUNDABOUT_LEFT),
255 new RouteStep(Command.ELSE),
256 new RouteStep(CAR_CENTER, -BOUNDARY),
257 new RouteStep(Command.END_IF))));
258 }
259
260 }
261
262
263
264
265
266
267 private boolean streamExists(final short stream)
268 {
269 return this.streams.contains(stream);
270 }
271
272
273
274
275
276
277 public static final boolean isGrass(final int i)
278 {
279 return i == DIVIDER_1 || i == DIVIDER_2 || i == DIVIDER_3 || i == DIVIDER_4 || i == DIVIDER_5 || i == DIVIDER_6
280 || i == DIVIDER_7 || i == SHOULDER;
281 }
282
283
284
285
286
287
288 final LaneType laneType(final int streamNumber)
289 {
290 if (streamNumber < 20 || streamNumber > 60 && streamNumber <= 80)
291 {
292 return LaneType.CAR_LANE;
293 }
294 if (streamNumber >= 20 && streamNumber < 30)
295 {
296 return LaneType.BICYCLE_LANE;
297 }
298 if (streamNumber >= 30 && streamNumber < 40)
299 {
300 return LaneType.PEDESTRIAN_LANE;
301 }
302 if (streamNumber > 40 && streamNumber <= 52 || streamNumber >= 81 && streamNumber <= 92)
303 {
304 return LaneType.PUBLIC_TRANSIT_LANE;
305 }
306 return null;
307 }
308
309
310
311
312 enum LaneType
313 {
314
315 CAR_LANE,
316
317 BICYCLE_LANE,
318
319 PUBLIC_TRANSIT_LANE,
320
321 PEDESTRIAN_LANE,
322 }
323
324
325
326
327
328
329
330 final int rotatedX(final XYPair xyPair, final int rotation)
331 {
332 switch (rotation % 4)
333 {
334 case 0:
335 return xyPair.getX();
336 case 1:
337 return -xyPair.getY();
338 case 2:
339 return -xyPair.getX();
340 case 3:
341 return xyPair.getY();
342 default:
343 break;
344 }
345 return 0;
346 }
347
348
349
350
351
352
353
354 final int rotatedY(final XYPair xyPair, final int rotation)
355 {
356 switch (rotation % 4)
357 {
358 case 0:
359 return xyPair.getY();
360 case 1:
361 return xyPair.getX();
362 case 2:
363 return -xyPair.getY();
364 case 3:
365 return -xyPair.getX();
366 default:
367 break;
368 }
369 return 0;
370 }
371
372
373
374
375 enum Command
376 {
377
378 NO_OP,
379
380 IF,
381
382 ELSE,
383
384 ELSE_IF,
385
386 END_IF,
387
388 STOP_LINE,
389
390 ICON,
391
392 STOP_LINE_AND_ICON,
393 }
394
395
396
397
398 class RouteStep
399 {
400
401 private final int x;
402
403
404 private final int y;
405
406
407 private final Command command;
408
409
410 private final int streamCondition;
411
412
413
414
415
416
417 RouteStep(final int x, final int y)
418 {
419 this.x = x;
420 this.y = y;
421 this.command = Command.NO_OP;
422 this.streamCondition = TrafficController.NO_STREAM;
423 }
424
425
426
427
428
429
430
431
432
433 RouteStep(final int x, final int y, final Command command) throws TrafficControlException
434 {
435 Throw.when(
436 Command.STOP_LINE != command && Command.NO_OP != command && Command.ICON != command
437 && Command.STOP_LINE_AND_ICON != command,
438 TrafficControlException.class,
439 "X and Y should only be provided with a NO_OP, STOP_LINE, ICON, or STOP_LINE_AND_ICON command; not with "
440 + command);
441 this.x = x;
442 this.y = y;
443 this.command = command;
444 this.streamCondition = TrafficController.NO_STREAM;
445 }
446
447
448
449
450
451
452
453
454 RouteStep(final Command command, final int streamCondition) throws TrafficControlException
455 {
456 Throw.when(Command.IF != command && Command.ELSE_IF != command, TrafficControlException.class,
457 "RouteStep constructor with stream condition must use command IF or ELSE_IF");
458 this.x = TrafficController.NO_STREAM;
459 this.y = TrafficController.NO_STREAM;
460 this.command = command;
461 Throw.when(streamCondition == TrafficController.NO_STREAM, TrafficControlException.class,
462 "IF or ELSE_IF need a valid traffic stream number");
463 this.streamCondition = streamCondition;
464 }
465
466
467
468
469
470
471 RouteStep(final Command command) throws TrafficControlException
472 {
473 Throw.when(Command.ELSE != command && Command.END_IF != command, TrafficControlException.class,
474 "RouteStep constructor with single command parameter requires ELSE or END_IF command");
475 this.x = TrafficController.NO_STREAM;
476 this.y = TrafficController.NO_STREAM;
477 this.command = command;
478 this.streamCondition = TrafficController.NO_STREAM;
479 }
480
481
482
483
484
485 public int getX()
486 {
487 return this.x;
488 }
489
490
491
492
493
494 public int getY()
495 {
496 return this.y;
497 }
498
499
500
501
502
503 public Command getCommand()
504 {
505 return this.command;
506 }
507
508
509
510
511
512 public int getStreamCondition()
513 {
514 return this.streamCondition;
515 }
516
517
518 @Override
519 public String toString()
520 {
521 return "RouteStep [x=" + this.x + ", y=" + this.y + ", command=" + this.command + ", streamCondition="
522 + this.streamCondition + "]";
523 }
524
525 }
526
527
528
529
530 class XYPair
531 {
532
533 private final int x;
534
535
536 private final int y;
537
538
539
540
541
542
543 XYPair(final int x, final int y)
544 {
545 this.x = x;
546 this.y = y;
547 }
548
549
550
551
552
553 XYPair(final RouteStep routeStep)
554 {
555 this.x = routeStep.getX();
556 this.y = routeStep.getY();
557 }
558
559
560
561
562
563
564 XYPair(final XYPair in, final int quadrant)
565 {
566 this.x = rotatedX(in, quadrant);
567 this.y = rotatedY(in, quadrant);
568 }
569
570
571
572
573
574 public int getX()
575 {
576 return this.x;
577 }
578
579
580
581
582
583 public int getY()
584 {
585 return this.y;
586 }
587
588
589 @Override
590 public String toString()
591 {
592 return "XYPair [x=" + this.x + ", y=" + this.y + "]";
593 }
594
595 }
596
597
598
599
600
601
602
603
604 private XYPair[] rotateRoute(final int quadrant, final RouteStep... steps) throws TrafficControlException
605 {
606 List<XYPair> route = new ArrayList<>();
607 boolean on = true;
608
609 for (RouteStep step : steps)
610 {
611 switch (step.getCommand())
612 {
613 case NO_OP:
614 case STOP_LINE:
615 case ICON:
616 case STOP_LINE_AND_ICON:
617 if (on)
618 {
619 route.add(new XYPair(new XYPair(step), quadrant));
620 }
621 break;
622
623 default:
624 throw new TrafficControlException("Bad command in rotateRoute: " + step.getCommand());
625
626 }
627 }
628 return route.toArray(new XYPair[route.size()]);
629 }
630
631
632
633
634
635
636
637 private RouteStep[] assembleRoute(final RouteStep... steps) throws TrafficControlException
638 {
639 List<RouteStep> result = new ArrayList<>();
640 RouteStep step;
641 for (int pointNo = 0; null != (step = routePoint(pointNo, steps)); pointNo++)
642 {
643 result.add(step);
644 }
645 return result.toArray(new RouteStep[result.size()]);
646 }
647
648
649
650
651
652
653
654
655 private RouteStep routePoint(final int pointNo, final RouteStep... steps) throws TrafficControlException
656 {
657 boolean active = true;
658 boolean beenActive = false;
659 int index = 0;
660
661 for (RouteStep routeStep : steps)
662 {
663 switch (routeStep.getCommand())
664 {
665 case NO_OP:
666 case STOP_LINE:
667 case ICON:
668 case STOP_LINE_AND_ICON:
669 if (active)
670 {
671 if (index++ == pointNo)
672 {
673 return routeStep;
674 }
675 }
676 break;
677
678 case IF:
679 active = streamExists((short) routeStep.getStreamCondition());
680 beenActive = active;
681 break;
682
683 case ELSE_IF:
684 if (active)
685 {
686 active = false;
687 }
688 else if (!beenActive)
689 {
690 active = this.streams.contains(routeStep.getStreamCondition());
691 }
692 if (active)
693 {
694 beenActive = true;
695 }
696 break;
697
698 case ELSE:
699 active = !beenActive;
700 break;
701
702 case END_IF:
703 active = true;
704 break;
705
706 default:
707 throw new TrafficControlException("Bad switch: " + routeStep);
708
709 }
710 }
711 return null;
712 }
713
714
715
716
717
718 public BufferedImage render()
719 {
720 int range = 2 * BOUNDARY + 1;
721 int cellSize = 10;
722 BufferedImage result = new BufferedImage(range * cellSize, range * cellSize, BufferedImage.TYPE_INT_RGB);
723 Graphics2D graphics = (Graphics2D) result.getGraphics();
724 graphics.setColor(Color.GREEN);
725 graphics.fillRect(0, 0, result.getWidth(), result.getHeight());
726 for (Short stream : this.streams)
727 {
728 switch (laneType(stream))
729 {
730 case BICYCLE_LANE:
731 graphics.setColor(Color.RED);
732 break;
733
734 case CAR_LANE:
735 graphics.setColor(Color.BLACK);
736 break;
737
738 case PEDESTRIAN_LANE:
739 graphics.setColor(Color.BLUE);
740 break;
741
742 case PUBLIC_TRANSIT_LANE:
743 graphics.setColor(Color.BLACK);
744 break;
745
746 default:
747 graphics.setColor(Color.WHITE);
748 break;
749
750 }
751 XYPair[] path = this.routes.get(stream);
752 if (null == path)
753 {
754 System.err.println("Cannot find path for stream " + stream);
755 continue;
756 }
757 XYPair prevPair = null;
758 for (XYPair xyPair : path)
759 {
760 if (null != prevPair)
761 {
762 int dx = (int) Math.signum(xyPair.getX() - prevPair.getX());
763 int dy = (int) Math.signum(xyPair.getY() - prevPair.getY());
764 int x = prevPair.getX() + dx;
765 int y = prevPair.getY() + dy;
766 while (x != xyPair.getX() || y != xyPair.getY())
767 {
768 fillXYPair(graphics, new XYPair(x, y));
769 if (x != xyPair.getX())
770 {
771 x += dx;
772 }
773 if (y != xyPair.getY())
774 {
775 y += dy;
776 }
777 }
778
779 }
780 fillXYPair(graphics, xyPair);
781 prevPair = xyPair;
782 }
783 }
784 return result;
785 }
786
787
788
789
790
791
792 private void fillXYPair(final Graphics2D graphics, final XYPair xyPair)
793 {
794 int cellSize = 10;
795 graphics.fillRect(cellSize * (BOUNDARY - xyPair.getX()), cellSize * (BOUNDARY - xyPair.getY()), cellSize, cellSize);
796 }
797
798
799
800
801
802 public static void main(final String[] args)
803 {
804 SwingUtilities.invokeLater(new Runnable()
805 {
806 @Override
807 public void run()
808 {
809 JFrame frame = new JFrame("Diagram test");
810 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
811 frame.setMinimumSize(new Dimension(1000, 1000));
812 JPanel mainPanel = new JPanel(new BorderLayout());
813 frame.add(mainPanel);
814 checkBoxPanel = new JPanel();
815 checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS));
816 JScrollPane scrollPane = new JScrollPane(checkBoxPanel);
817 scrollPane.setPreferredSize(new Dimension(150, 1000));
818 mainPanel.add(scrollPane, BorderLayout.LINE_START);
819 for (int stream = 1; stream <= 12; stream++)
820 {
821 checkBoxPanel.add(makeCheckBox(stream, stream % 3 == 2));
822 }
823 for (int stream = 21; stream <= 28; stream++)
824 {
825 checkBoxPanel.add(makeCheckBox(stream, false));
826 }
827 for (int stream = 31; stream <= 38; stream++)
828 {
829 checkBoxPanel.add(makeCheckBox(stream, false));
830 }
831 for (int stream = 41; stream <= 52; stream++)
832 {
833 checkBoxPanel.add(makeCheckBox(stream, false));
834 }
835 for (int stream = 61; stream <= 72; stream++)
836 {
837 if (stream % 3 == 1)
838 {
839 continue;
840 }
841 checkBoxPanel.add(makeCheckBox(stream, false));
842 }
843 testPanel = new JPanel();
844 rebuildTestPanel();
845 mainPanel.add(testPanel, BorderLayout.CENTER);
846 frame.setVisible(true);
847 }
848 });
849
850 }
851
852
853
854
855
856
857
858 public static JCheckBox makeCheckBox(final int stream, final boolean initialState)
859 {
860 JCheckBox result = new JCheckBox(String.format("Stream %02d", stream));
861 result.setSelected(initialState);
862 result.addActionListener(new ActionListener()
863 {
864
865 @Override
866 public void actionPerformed(final ActionEvent e)
867 {
868 rebuildTestPanel();
869 }
870 });
871 return result;
872 }
873
874
875 private static JPanel testPanel = null;
876
877
878 private static JPanel checkBoxPanel = null;
879
880
881
882
883 static void rebuildTestPanel()
884 {
885 testPanel.removeAll();
886 Set<Short> streamList = new LinkedHashSet<>();
887 for (Component c : checkBoxPanel.getComponents())
888 {
889 if (c instanceof JCheckBox)
890 {
891 JCheckBox checkBox = (JCheckBox) c;
892 if (checkBox.isSelected())
893 {
894 String caption = checkBox.getText();
895 String streamText = caption.substring(caption.length() - 2);
896 Short stream = Short.parseShort(streamText);
897 streamList.add(stream);
898 }
899 }
900 }
901 try
902 {
903 Diagram diagram = new Diagram(streamList);
904 testPanel.add(new JLabel(new ImageIcon(diagram.render())));
905 }
906 catch (TrafficControlException exception)
907 {
908 exception.printStackTrace();
909 }
910 testPanel.repaint();
911 testPanel.revalidate();
912 }
913
914 }