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