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