1 package org.opentrafficsim.editor.extensions.map;
2
3 import org.djunits.value.vdouble.scalar.Direction;
4 import org.djutils.draw.bounds.Bounds2d;
5 import org.djutils.draw.line.Polygon2d;
6 import org.djutils.draw.point.DirectedPoint2d;
7 import org.djutils.draw.point.Point2d;
8 import org.djutils.event.Event;
9 import org.djutils.event.EventListener;
10 import org.djutils.event.reference.ReferenceType;
11 import org.opentrafficsim.base.geometry.OtsShape;
12 import org.opentrafficsim.draw.network.NodeAnimation.NodeData;
13 import org.opentrafficsim.editor.OtsEditor;
14 import org.opentrafficsim.editor.XsdTreeNode;
15 import org.opentrafficsim.editor.extensions.Adapters;
16
17
18
19
20
21
22
23
24
25 public class MapNodeData extends MapData implements NodeData, EventListener
26 {
27
28
29 private static final Bounds2d BOUNDS = new Bounds2d(2.0, 2.0);
30
31
32 private String id = "";
33
34
35 private Point2d coordinate = null;
36
37
38 private Direction direction = null;
39
40
41 private DirectedPoint2d location = new DirectedPoint2d(0.0, 0.0, 0.0);
42
43
44 private Polygon2d absoluteContour;
45
46
47 private Polygon2d relativeContour;
48
49
50
51
52
53
54
55 public MapNodeData(final EditorMap map, final XsdTreeNode nodeNode, final OtsEditor editor)
56 {
57 super(map, nodeNode, editor);
58 getNode().addListener(this, XsdTreeNode.ATTRIBUTE_CHANGED, ReferenceType.WEAK);
59
60 if (getNode().isActive())
61 {
62 notify(new Event(XsdTreeNode.ATTRIBUTE_CHANGED, new Object[] {getNode(), "Id", null}));
63 notify(new Event(XsdTreeNode.ATTRIBUTE_CHANGED, new Object[] {getNode(), "Coordinate", null}));
64 notify(new Event(XsdTreeNode.ATTRIBUTE_CHANGED, new Object[] {getNode(), "Direction", null}));
65 }
66 this.absoluteContour = OtsShape.boundsAsAbsoluteContour(this);
67 this.relativeContour =
68 new Polygon2d(OtsShape.toRelativeTransform(this.location).transform(this.absoluteContour.iterator()));
69 }
70
71 @Override
72 public Bounds2d getRelativeBounds()
73 {
74 return BOUNDS;
75 }
76
77 @Override
78 public Polygon2d getAbsoluteContour()
79 {
80 return this.absoluteContour;
81 }
82
83 @Override
84 public Polygon2d getRelativeContour()
85 {
86 return this.relativeContour;
87 }
88
89 @Override
90 public String getId()
91 {
92 return this.id;
93 }
94
95 @Override
96 public void destroy()
97 {
98 super.destroy();
99 getNode().removeListener(this, XsdTreeNode.ATTRIBUTE_CHANGED);
100 }
101
102 @Override
103 public DirectedPoint2d getLocation()
104 {
105 return this.location;
106 }
107
108 @Override
109 public void notify(final Event event)
110 {
111 String attribute = (String) ((Object[]) event.getContent())[1];
112 String value = getNode().getAttributeValue(attribute);
113 if ("Id".equals(attribute))
114 {
115 this.id = value == null ? "" : value;
116 return;
117 }
118 else if ("Coordinate".equals(attribute))
119 {
120 setValue((v) -> this.coordinate = v, Adapters.get(Point2d.class), getNode(), "Coordinate");
121 }
122 else if ("Direction".equals(attribute))
123 {
124 setValue((v) -> this.direction = v, Adapters.get(Direction.class), getNode(), "Direction");
125 }
126 else
127 {
128 return;
129 }
130 setLocation();
131 }
132
133 @Override
134 public void evalChanged()
135 {
136 this.id = getNode().getId() == null ? "" : getNode().getId();
137 setValue((v) -> this.coordinate = v, Adapters.get(Point2d.class), getNode(), "Coordinate");
138 setValue((v) -> this.direction = v, Adapters.get(Direction.class), getNode(), "Direction");
139 setLocation();
140 }
141
142
143
144
145 private void setLocation()
146 {
147 if (this.coordinate == null)
148 {
149 setInvalid();
150 return;
151 }
152 this.location = new DirectedPoint2d(this.coordinate, this.direction == null ? 0.0 : this.direction.si);
153 this.absoluteContour = OtsShape.boundsAsAbsoluteContour(this);
154 this.relativeContour =
155 new Polygon2d(OtsShape.toRelativeTransform(this.location).transform(this.absoluteContour.iterator()));
156 setValid();
157 }
158
159 @Override
160 public String toString()
161 {
162 return "Node " + this.id;
163 }
164
165 }