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