View Javadoc
1   package org.opentrafficsim.draw.network;
2   
3   import java.rmi.RemoteException;
4   import java.util.HashSet;
5   import java.util.Set;
6   
7   import javax.naming.Binding;
8   import javax.naming.NamingEnumeration;
9   import javax.naming.NamingException;
10  import javax.naming.event.EventContext;
11  
12  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
13  import org.opentrafficsim.core.network.Link;
14  import org.opentrafficsim.core.network.NetworkException;
15  import org.opentrafficsim.core.network.Node;
16  import org.opentrafficsim.core.network.OTSLink;
17  import org.opentrafficsim.core.network.OTSNetwork;
18  import org.opentrafficsim.core.network.OTSNetworkUtils;
19  import org.opentrafficsim.core.network.OTSNode;
20  import org.opentrafficsim.draw.core.ClonableRenderable2DInterface;
21  
22  import nl.tudelft.simulation.dsol.animation.Locatable;
23  import nl.tudelft.simulation.dsol.animation.D2.Renderable2DInterface;
24  import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
25  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
26  import nl.tudelft.simulation.naming.context.ContextUtil;
27  
28  /**
29   * OTSNetworkAnimationUtils can make a deep clone of a network, including animation, and can destroy the animation. <br>
30   * <br>
31   * Copyright (c) 2003-2019 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
32   * for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>. The
33   * source code and binary code of this software is proprietary information of Delft University of Technology.
34   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
35   */
36  public final class OTSNetworkAnimationUtils
37  {
38      /** */
39      private OTSNetworkAnimationUtils()
40      {
41          // utility class
42      }
43  
44      /**
45       * Clone the OTSNetwork, including animation.
46       * @param network OTSNetwork; the network to clone
47       * @param newId String; the new id of the network
48       * @param oldSimulator SimulatorInterface.TimeDoubleUnit; the old simulator for this network
49       * @param newSimulator OTSSimulatorInterface; the new simulator for this network
50       * @return a clone of this network
51       * @throws NetworkException in case the cloning fails
52       */
53      @SuppressWarnings("checkstyle:designforextension")
54      public static OTSNetwork clone(final OTSNetwork network, final String newId,
55              final SimulatorInterface.TimeDoubleUnit oldSimulator, final OTSSimulatorInterface newSimulator)
56              throws NetworkException
57      {
58          OTSNetwork newNetwork = OTSNetworkUtils.clone(network, newId, oldSimulator, newSimulator);
59  
60          // clone the link animation
61          for (Link oldLink : network.getLinkMap().values())
62          {
63              OTSLink newLink = (OTSLink) newNetwork.getLink(oldLink.getId());
64              cloneAnimation(oldLink, newLink, oldSimulator, newSimulator);
65          }
66  
67          // clone the node animation
68          for (Node oldNode : network.getNodeMap().values())
69          {
70              OTSNode newNode = (OTSNode) newNetwork.getNode(oldNode.getId());
71              cloneAnimation(oldNode, newNode, oldSimulator, newSimulator);
72          }
73  
74          // TODO clone the animation of the visible objects
75  
76          return newNetwork;
77      }
78  
79      /**
80       * Clone all animation objects for the given class. The given class is the <b>source</b> of the animation objects, as it is
81       * not known on beforehand which objects need to be cloned. It is important for cloning that the animation objects implement
82       * the CloneableRenderable2DInterface, so they can be cloned with their properties. If not, they will not be taken into
83       * account for cloning by this method.
84       * @param oldSource Locatable; the old source object that might have one or more animation objects attached to it
85       * @param newSource T; the new source object to attach the cloned animation objects to
86       * @param oldSimulator SimulatorInterface.TimeDoubleUnit; the old simulator when the old objects can be found
87       * @param newSimulator SimulatorInterface.TimeDoubleUnit; the new simulator where the new simulation objects need to be
88       *            registered
89       * @param <T> locatable type
90       */
91      @SuppressWarnings("checkstyle:designforextension")
92      public static <T extends Locatable> void cloneAnimation(final Locatable oldSource, final T newSource,
93              final SimulatorInterface.TimeDoubleUnit oldSimulator, final SimulatorInterface.TimeDoubleUnit newSimulator)
94      {
95          if (!(oldSimulator instanceof AnimatorInterface) || !(newSimulator instanceof AnimatorInterface))
96          {
97              return;
98          }
99  
100         try
101         {
102             EventContext context =
103                     (EventContext) ContextUtil.lookup(oldSimulator.getReplication().getContext(), "/animation/2D");
104             NamingEnumeration<Binding> list = context.listBindings("");
105             while (list.hasMore())
106             {
107                 Binding binding = list.next();
108                 @SuppressWarnings("unchecked")
109                 Renderable2DInterface<T> animationObject = (Renderable2DInterface<T>) binding.getObject();
110                 T locatable = animationObject.getSource();
111                 if (oldSource.equals(locatable) && animationObject instanceof ClonableRenderable2DInterface)
112                 {
113                     ((ClonableRenderable2DInterface<T>) animationObject).clone(newSource, newSimulator);
114                 }
115             }
116         }
117         catch (NamingException | RemoteException exception)
118         {
119             System.err.println("Error when cloning animation objects for object " + oldSource);
120         }
121     }
122 
123     /**
124      * Remove all objects and animation in the network.
125      * @param network OTSNetwork; the network to destroy
126      * @param simulator SimulatorInterface.TimeDoubleUnit; the simulator of the old network
127      */
128     @SuppressWarnings("checkstyle:designforextension")
129     public static void destroy(final OTSNetwork network, final SimulatorInterface.TimeDoubleUnit simulator)
130     {
131         Set<Renderable2DInterface<?>> animationObjects = new HashSet<>();
132         try
133         {
134             EventContext context = (EventContext) ContextUtil.lookup(simulator.getReplication().getContext(), "/animation/2D");
135             NamingEnumeration<Binding> list = context.listBindings("");
136             while (list.hasMore())
137             {
138                 Binding binding = list.next();
139                 Renderable2DInterface<?> animationObject = (Renderable2DInterface<?>) binding.getObject();
140                 animationObjects.add(animationObject);
141             }
142 
143             for (Renderable2DInterface<?> ao : animationObjects)
144             {
145                 try
146                 {
147                     ao.destroy();
148                 }
149                 catch (Exception e)
150                 {
151                     //
152                 }
153             }
154         }
155         catch (NamingException exception)
156         {
157             System.err.println("Error when destroying animation objects");
158         }
159 
160         // destroy the network, GTUs, Routes, etc.
161         OTSNetworkUtils.destroy(network, simulator);
162     }
163 
164     /**
165      * Remove all animation objects of the given class.
166      * @param clazz Class&lt;?&gt;; the class to remove the animation objects for
167      * @param oldSimulator SimulatorInterface.TimeDoubleUnit; the old simulator
168      */
169     @SuppressWarnings("checkstyle:designforextension")
170     public static void removeAnimation(final Class<?> clazz, final SimulatorInterface.TimeDoubleUnit oldSimulator)
171     {
172         if (!(oldSimulator instanceof AnimatorInterface))
173         {
174             return;
175         }
176 
177         try
178         {
179             EventContext context =
180                     (EventContext) ContextUtil.lookup(oldSimulator.getReplication().getContext(), "/animation/2D");
181             NamingEnumeration<Binding> list = context.listBindings("");
182             while (list.hasMore())
183             {
184                 Binding binding = list.next();
185                 Renderable2DInterface<?> animationObject = (Renderable2DInterface<?>) binding.getObject();
186                 Locatable locatable = animationObject.getSource();
187                 if (clazz.isAssignableFrom(locatable.getClass()))
188                 {
189                     animationObject.destroy();
190                 }
191             }
192         }
193         catch (NamingException | RemoteException exception)
194         {
195             System.err.println("Error when destroying animation objects for class " + clazz.getSimpleName());
196         }
197     }
198 
199 }