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