//==================================================================================================
// S i m u l a t i o n                                                                    Interface
// O b j e c t
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides basic classes to represent objects in a simulation. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "simulation/object.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guSimulationObject
#define guSimulationObject

// Headers //---------------------------------------------------------------------------------------
#include <set> /*INCLUDE*/
#include <bpp/standard.hpp> /*INCLUDE*/
#include <jirk/bpp/simulation/visualcomponent.hpp> /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef SIMULATION_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  simulationObject
#define private_area simulationObject_private

namespace public_area  { /*NAMESPACE*/ using namespace standard; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniSimulationObject
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace simulationSimulator { class clSimulator; }

namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 class clObject;
 class clPhysicalObject;
 class clStillObject;
 class clMobileObject;
 class clPath;
 //-----------------------------------------------------------------------------------Variable Types
 /*TYPE*/ /* Visual component representing a simulation object. */
 typedef jirk::bpp::simulation::jaVisualComponent clVisualComponent;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const clObject         ctObject;
 typedef const clPhysicalObject ctPhysicalObject;
 typedef const clStillObject    ctStillObject;
 typedef const clMobileObject   ctMobileObject;
 typedef const clPath           ctPath;
}

namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erInvalidPath; /* The path used to move the object is invalid. */
}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// O b j e c t  Interface //------------------------------------------------------------------------
namespace public_area {
 /*CLASS clObject */
 /* Represents an object in a simulation. Every class that instantiates objects to be managed
    within a simulation should inherit from this class. */
 class clObject {
  //-----------------------------------------------------------------------------------------Private
  private_property simulationSimulator::clSimulator & atSimulator;
  private_property clAbstractPool *                   atPool;

  private_property constructor clObject(ctObject &);
  private_property clObject & operator = (ctObject &);
  //------------------------------------------------------------------------------------------Public
  public_property simulationSimulator::clSimulator & simulator(void) const;
  public_property clAbstractPool *                   pool(void) const;

  public_property constructor        clObject(simulationSimulator::clSimulator &,clAbstractPool *);
  public_property virtual destructor clObject(void);
  //--------------------------------------------------------------------------------------Reflection
  class_indexer(clObject);
 };
}

// P h y s i c a l O b j e c t  Interface //--------------------------------------------------------
namespace public_area {
 /*CLASS clPhysicalObject */
 /* Represents a physical object, i.e. with a location and a visual representation. It is an
    abstract class. */
 class clPhysicalObject : public clObject {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clPhysicalObject */ /* Type of the list of still children of the object. */
  public_property typedef std_set(clStillObject *) clStillChildS;

  /*TYPE clPhysicalObject */ /* Type of the list of mobile children of the object. */
  public_property typedef std_set(clMobileObject *) clMobileChildS;

  /*TYPE clPhysicalObject */ /* Type of the pointer to the parent of the object. */
  public_property typedef clPhysicalObject * clParentPointer;
  //-----------------------------------------------------------------------------------------Private
  private_property tyBoolean atUpdateStillView;

  private_property void         clear(void);
  private_property void         updateChildrenView(tyPointer);
  private_property virtual void updateStatus(void);
  private_property virtual void updateView(tyPointer);

  private_property constructor clPhysicalObject(ctPhysicalObject &);
  private_property clPhysicalObject & operator = (ctPhysicalObject &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clPhysicalObject */ /* Name of the object. */
  read_write_attribute(clString,atName,name);

  /*ATTRIBUTE clPhysicalObject */
  /* Parent of the component, i.e. the physical object inside, or upon,
     which the component is located. */
  read_only_attribute(clParentPointer,atParent,parent);

  /*ATTRIBUTE clPhysicalObject */
  /* Indicates if the object is <I>deep</I>, i.e. if it has an inside representation. */
  read_only_attribute(tyBoolean,atDeep,deep);

  /*ATTRIBUTE clPhysicalObject */
  /* Still children of the component, i.e. still objects located on its layout. */
  read_only_attribute(clStillChildS,atStillChildS,stillChildren);

  /*ATTRIBUTE clPhysicalObject */
  /* Mobile children of the component, i.e. mobile objects temporarily located on its layout. */
  read_only_attribute(clMobileChildS,atMobileChildS,mobileChildren);

  /*ATTRIBUTE clPhysicalObject */ /* Visual representation of the object. */
  read_write_attribute(clVisualComponent,atView,view);

  /*ATTRIBUTE clPhysicalObject */ /* String describing the status of the object. */
  read_only_attribute(clString,atStatus,status);

  public_property constructor clPhysicalObject(simulationSimulator::clSimulator &,clAbstractPool *,
                                               tyBoolean=false,tcString="");

  public_property destructor clPhysicalObject(void);

  public_property tyReal absoluteX(void) const;
  public_property tyReal absoluteY(void) const;

  /*AMETHOD clPhysicalObject */
  /* Returns the X coordinate of the relative position of the object in the layout of its parent.
     Abstract method. */
  public_property virtual tyReal relativeX(void) const = 0;

  /*AMETHOD clPhysicalObject */
  /* Returns the Y coordinate of the relative position of the object in the layout of its parent.
     Abstract method. */
  public_property virtual tyReal relativeY(void) const = 0;

  public_property virtual void addChild(clStillObject *);
  public_property virtual void addChild(clMobileObject *);
  public_property virtual void removeChild(clStillObject *);
  public_property virtual void removeChild(clMobileObject *);

  public_property void updateView(void);
 };
}

// S t i l l O b j e c t  Interface //--------------------------------------------------------------
namespace public_area {
 /*CLASS clStillObject */ /* Represents a still physical object. */
 class clStillObject : public clPhysicalObject {
  //-----------------------------------------------------------------------------------------Private
  private_property tyReal atRelativeX;
  private_property tyReal atRelativeY;

  private_property constructor clStillObject(ctStillObject &);
  private_property clStillObject & operator = (ctStillObject &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clStillObject(simulationSimulator::clSimulator &,clAbstractPool *,
                                            tyBoolean=false,tyReal=0.0,tyReal=0.0,tcString="");

  public_property destructor clStillObject(void);

  public_property tyReal relativeX(void) const;
  public_property tyReal relativeY(void) const;
 };
}

// M o b i l e O b j e c t  Interface //------------------------------------------------------------
namespace public_area {
 /*CLASS clMobileObject */ /* Represents a mobile physical object. */
 class clMobileObject : public clPhysicalObject {
  //-----------------------------------------------------------------------------------------Private
  private_property void updateStatus(void);

  private_property constructor clMobileObject(ctMobileObject &);
  private_property clMobileObject & operator = (ctMobileObject &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clMobileObject */ /* Date the object arrived at its last location. */
  read_only_attribute(tyCardinal,atArrivalDate,arrivalDate);

  /*ATTRIBUTE clMobileObject */
  /* If the object is located on a path, time it needs to travel along the path. */
  read_only_attribute(tyCardinal,atTravelTime,travelTime);

  public_property constructor clMobileObject(simulationSimulator::clSimulator &,clAbstractPool *,
                                             tyBoolean=false,tcString="");

  public_property destructor clMobileObject(void);

  public_property tyBoolean moving(void) const;
  public_property tyReal    relativeX(void) const;
  public_property tyReal    relativeY(void) const;

  public_property virtual void arrive(clPhysicalObject *);
  public_property virtual void move(clPath *,tyCardinal);
  //--------------------------------------------------------------------------------------Reflection
  add_method_slot(arrive);
  add_method_slot(move);
 };
}

// P a t h  Interface //----------------------------------------------------------------------------
namespace public_area {
 /*CLASS clPath */ /* Represents a path between two still objects. */
 class clPath : public clStillObject {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clPath */ /* Type of a pointer to the extremities of the path. */
  public_property typedef clStillObject * tyExtremityPointer;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clPath(ctPath &);
  private_property clPath & operator = (ctPath &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clPath */ /* Still object that is the source of the path. */
  read_only_attribute(tyExtremityPointer,atSource,source);

  /*ATTRIBUTE clPath */ /* Still object that is the target of the path. */
  read_only_attribute(tyExtremityPointer,atTarget,target);

  public_property constructor clPath(simulationSimulator::clSimulator &,clAbstractPool *,
                                     clStillObject *,clStillObject *,tcString="");

  public_property destructor clPath(void);

  public_property tyReal relativeX(void) const;
  public_property tyReal relativeY(void) const;

  public_property virtual tyReal relativeX(ctMobileObject *) const;
  public_property virtual tyReal relativeY(ctMobileObject *) const;
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// O b j e c t  Inline //---------------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------Simulator
 /*METHOD clObject */ /* Returns the simulator that handles the object. */
 inline simulationSimulator::clSimulator & clObject::simulator(void) const
 { return (atSimulator); }
 //---------------------------------------------------------------------------------------------Pool
 /*METHOD clObject */
 /* Pointer to the pool used to allocate the object
    (<CODE>nil</CODE> means that no pool was used). */
 inline clAbstractPool * clObject::pool(void) const { return (atPool); }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clObject */
 /* Builds an object in a simulator. A pointer to the pool used to allocate the object must be
    provided. If no pool was used, <CODE>nil</CODE> must be provided. */
 inline clObject::clObject(simulationSimulator::clSimulator & agSimulator,clAbstractPool * agPool)
 : atSimulator(agSimulator),atPool(agPool) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clObject */ /* Destructs the object. */
 inline clObject::~clObject(void) {}
}

// P h y s i c a l O b j e c t  Inline //-----------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clPhysicalObject */
 /* Builds a physical object in a simulator. It is possible to create a deep object
    (default is not). A name can also be given to the object. */
 inline clPhysicalObject::clPhysicalObject(simulationSimulator::clSimulator & agSimulator,
                                           clAbstractPool * agPool,tyBoolean agDeep,
                                           tcString agName)
 : clObject(agSimulator,agPool),atUpdateStillView(false),atName(agName),atParent(nil),
   atDeep(agDeep),atStillChildS(),atMobileChildS(),atView(),atStatus("") {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clPhysicalObject */ /* Destructs the object. */
 inline clPhysicalObject::~clPhysicalObject(void) { clear(); }
}

// S t i l l O b j e c t  Inline //-----------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clStillObject */
 /* Builds a still physical object. The relative position of the object can be provided,
    default is <I>(0;0)</I>. */
 inline clStillObject::clStillObject(simulationSimulator::clSimulator & agSimulator,
                                     clAbstractPool * agPool,tyBoolean agDeep,tyReal agRelativeX,
                                     tyReal agRelativeY,tcString agName)
 : clPhysicalObject(agSimulator,agPool,agDeep,agName),
   atRelativeX(agRelativeX),atRelativeY(agRelativeY) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clStillObject */ /* Destructs the object. */
 inline clStillObject::~clStillObject(void) { if (atParent!=nil) atParent->removeChild(this); }
 //----------------------------------------------------------------------------------------RelativeX
 /*METHOD clStillObject */
 /* Returns the X coordinate of the relative position of the object in the layout of its parent. */
 inline tyReal clStillObject::relativeX(void) const { return (atRelativeX); }
 //----------------------------------------------------------------------------------------RelativeY
 /*METHOD clStillObject */
 /* Returns the Y coordinate of the relative position of the object in the layout of its parent. */
 inline tyReal clStillObject::relativeY(void) const { return (atRelativeY); }
}

// M o b i l e O b j e c t  Inline //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clMobileObject */ /* Builds a mobile physical object. */
 inline clMobileObject::clMobileObject(simulationSimulator::clSimulator & agSimulator,
                                       clAbstractPool * agPool,tyBoolean agDeep,tcString agName)
 : clPhysicalObject(agSimulator,agPool,agDeep,agName) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clMobileObject */ /* Destructs the object. */
 inline clMobileObject::~clMobileObject(void) { if (atParent!=nil) atParent->removeChild(this); }
 //-------------------------------------------------------------------------------------------Moving
 /*METHOD clMobileObject */ /* Indicates if the object is moving along a path. */
 inline tyBoolean clMobileObject::moving(void) const
 { return (dynamic_cast<clPath *>(atParent)!=nil); }
 //----------------------------------------------------------------------------------------RelativeX
 /*METHOD clMobileObject */
 /* Returns the X coordinate of the relative position of the object in the layout of its parent. */
 inline tyReal clMobileObject::relativeX(void) const {
  clPath * lcPath = dynamic_cast<clPath *>(atParent);

  return (lcPath!=nil ? lcPath->relativeX(this) : 0.0);
 }
 //----------------------------------------------------------------------------------------RelativeY
 /*METHOD clMobileObject */
 /* Returns the Y coordinate of the relative position of the object in the layout of its parent. */
 inline tyReal clMobileObject::relativeY(void) const {
  clPath * lcPath = dynamic_cast<clPath *>(atParent);

  return (lcPath!=nil ? lcPath->relativeY(this) : 0.0);
 }
}

// P a t h  Inline //-------------------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clPath */ /* Builds a path between two still objects. */
 inline clPath::clPath(simulationSimulator::clSimulator & agSimulator,clAbstractPool * agPool,
                       clStillObject * agSource,clStillObject * agTarget,tcString agName)
 : clStillObject(agSimulator,agPool,false,0.0,0.0,agName),atSource(agSource),atTarget(agTarget) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clPath */ /* Destructs the path. */
 inline clPath::~clPath(void) {}
 //----------------------------------------------------------------------------------------RelativeX
 /*METHOD clPath */
 /* Returns the X coordinate of the relative position of the object in the layout of its parent. */
 inline tyReal clPath::relativeX(void) const
 { return (standard::mini(atSource->relativeX(),atTarget->relativeX())); }
 //----------------------------------------------------------------------------------------RelativeY
 /*METHOD clPath */
 /* Returns the Y coordinate of the relative position of the object in the layout of its parent. */
 inline tyReal clPath::relativeY(void) const
 { return (standard::mini(atSource->relativeY(),atTarget->relativeY())); }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// S i m u l a t i o n                                                               Implementation
// O b j e c t
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU Library General Public License for more details (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "simulation/object.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define SIMULATION_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/simulation/object.hpp> /*INTERFACE*/
#include <bpp/simulation/simulator.hpp> /*NEED*/
#include <jirk/java/lang/string.hpp> /*NEED*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  simulationObject
#define private_area simulationObject_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Simulation/Object");

// Initialization //--------------------------------------------------------------------------------
#undef iniSimulationObject
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area { static_error erInvalidPath; }

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Static Members //--------------------------------------------------------------------------------
namespace public_area  { static_class_indexer(clObject); }
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// P h y s i c a l O b j e c t  Implementation //---------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------------Clear
 property void clPhysicalObject::clear(void) {
  tyCardinal                   lcCounter;
  std_vector(clMobileObject *) lcMobileObjectS;
  std_vector(clStillObject *)  lcStillObjectS;

  clMobileChildS::iterator lcCurrentMobile = atMobileChildS.begin();
  clStillChildS::iterator  lcCurrentStill  = atStillChildS.begin();
  clMobileChildS::iterator lcLastMobile    = atMobileChildS.end();
  clStillChildS::iterator  lcLastStill     = atStillChildS.end();

  // Mobile Children Destruction //
  while (lcCurrentMobile!=lcLastMobile) {
   lcMobileObjectS.push_back(*lcCurrentMobile);
   simulator().deleteObject(*lcCurrentMobile);
   ++lcCurrentMobile;
  }

  atMobileChildS.erase(atMobileChildS.begin(),atMobileChildS.end());
  lcCounter=lcMobileObjectS.size();

  while (lcCounter>0) {
   --lcCounter;
   removeChild(lcMobileObjectS[lcCounter]);
  }

  // Still Children Destruction //
  while (lcCurrentStill!=lcLastStill) {
   lcStillObjectS.push_back(*lcCurrentStill);
   simulator().deleteObject(*lcCurrentStill);
   ++lcCurrentStill;
  }

  atStillChildS.erase(atStillChildS.begin(),atStillChildS.end());
  lcCounter=lcStillObjectS.size();

  while (lcCounter>0) {
   --lcCounter;
   removeChild(lcStillObjectS[lcCounter]);
  }
 }
 //-------------------------------------------------------------------------------UpdateChildrenView
 property void clPhysicalObject::updateChildrenView(tyPointer agInspected) {
  typedef clMobileChildS::iterator clMobileIterator;
  typedef clStillChildS::iterator  clStillIterator;

  clMobileIterator lcCurrentMobile = atMobileChildS.begin();
  clStillIterator  lcCurrentStill  = atStillChildS.begin();
  clMobileIterator lcLastMobile    = atMobileChildS.end();
  clStillIterator  lcLastStill     = atStillChildS.end();

  // Mobile Children Update //
  while (lcCurrentMobile!=lcLastMobile) {
   (*lcCurrentMobile)->updateView(agInspected);
   ++lcCurrentMobile;
  }

  // Still View Update Requested //
  if (atUpdateStillView) {
   while (lcCurrentStill!=lcLastStill) {
    (*lcCurrentStill)->updateView(agInspected);
    ++lcCurrentStill;
   }

   atUpdateStillView=false;
  }

  // Still View Update Not Requested //
  else {
   while (lcCurrentStill!=lcLastStill) {
    if (agInspected==(*lcCurrentStill)) (*lcCurrentStill)->updateView(agInspected);
    else (*lcCurrentStill)->updateChildrenView(agInspected);

    ++lcCurrentStill;
   }
  }
 }
 //-------------------------------------------------------------------------------------UpdateStatus
 /*METHOD clPhysicalObject */ /* Updates the status of the object. Private method. */
 property void clPhysicalObject::updateStatus(void) {
  if (atParent==nil) atStatus="location = nil";
  else atStatus="location = "+atParent->name();

  atStatus+="\nchildren = "+string(tyCardinal(mobileChildren().size()));
 }
 //---------------------------------------------------------------------------------------UpdateView
 /*METHOD clPhysicalObject */
 /* Updates the visual representation of the object. A pointer to the object that is actually
    inspected by the graphical interface must be provided. Private method. */
 property void clPhysicalObject::updateView(tyPointer agInspected) {
  if (simulator().graphic() and view()!=java_nil) {
   clString lcPointer(string(this));

   view().j_setLocation(java::jyInteger(absoluteX()),java::jyInteger(absoluteY()));
   view().j_setName(jirk::java::lang::jaString::j_new(atName.data()));
   view().j_setNativePointer(jirk::java::lang::jaString::j_new(lcPointer.data()));
   updateStatus();
   view().j_setProperties(jirk::java::lang::jaString::j_new(status().data()));
   view().j_show();
   updateChildrenView(agInspected);
  }
 }
 //----------------------------------------------------------------------------------------AbsoluteX
 /*METHOD clPhysicalObject */
 /* Returns the X coordinate of the absolute position of the object in the layout. */
 property tyReal clPhysicalObject::absoluteX(void) const {
  if (parent()==nil) return (0.0);
  if (parent()->deep()) return (relativeX());
  return (parent()->absoluteX()+relativeX());
 }
 //----------------------------------------------------------------------------------------AbsoluteY
 /*METHOD clPhysicalObject */
 /* Returns the Y coordinate of the absolute position of the object in the layout. */
 property tyReal clPhysicalObject::absoluteY(void) const {
  if (parent()==nil) return (0.0);
  if (parent()->deep()) return (relativeY());
  return (parent()->absoluteY()+relativeY());
 }
 //-----------------------------------------------------------------------------------------AddChild
 /*METHOD clPhysicalObject */
 /* Adds a still child, i.e. a still object, on the layout of the object. */
 property void clPhysicalObject::addChild(clStillObject * agObject) {
  clPhysicalObject * lcObject;

  if (agObject!=nil) {
   atStillChildS.insert(agObject);
   agObject->atParent=this;
   atUpdateStillView=true;

   if (simulator().graphic() and agObject->view()!=java_nil) {
    lcObject=this;

    while (lcObject!=nil and not lcObject->deep()) lcObject=lcObject->parent();
    if (lcObject!=nil) lcObject->view().j_addInside(agObject->view());
   }
  }
 }
 //-----------------------------------------------------------------------------------------AddChild
 /*METHOD clPhysicalObject */
 /* Adds a mobile child, i.e. a mobile object, on the layout of the object. */
 property void clPhysicalObject::addChild(clMobileObject * agObject) {
  clPhysicalObject * lcObject;

  if (agObject!=nil) {
   atMobileChildS.insert(agObject);
   agObject->atParent=this;

   if (simulator().graphic() and agObject->view()!=java_nil) {
    lcObject=this;

    while (lcObject!=nil and not lcObject->deep()) lcObject=lcObject->parent();
    if (lcObject!=nil) lcObject->view().j_addInside(agObject->view());
   }
  }
 }
 //--------------------------------------------------------------------------------------RemoveChild
 /*METHOD clPhysicalObject */
 /* Removes a still child, i.e. a still object, from the layout of the object. */
 property void clPhysicalObject::removeChild(clStillObject * agObject) {
  clPhysicalObject * lcObject;

  if (agObject!=nil) {
   atStillChildS.erase(agObject);
   agObject->atParent=nil;
   atUpdateStillView=true;

   if (simulator().graphic() and agObject->view()!=java_nil) {
    lcObject=this;

    while (lcObject!=nil and not lcObject->deep()) lcObject=lcObject->parent();
    if (lcObject!=nil) lcObject->view().j_removeInside(agObject->view());
   }
  }
 }
 //--------------------------------------------------------------------------------------RemoveChild
 /*METHOD clPhysicalObject */
 /* Removes a mobile child, i.e. a mobile object, from the layout of the object. */
 property void clPhysicalObject::removeChild(clMobileObject * agObject) {
  clPhysicalObject * lcObject;

  if (agObject!=nil) {
   atMobileChildS.erase(agObject);
   agObject->atParent=nil;

   if (simulator().graphic() and agObject->view()!=java_nil) {
    lcObject=this;

    while (lcObject!=nil and not lcObject->deep()) lcObject=lcObject->parent();
    if (lcObject!=nil) lcObject->view().j_removeInside(agObject->view());
   }
  }
 }
 //---------------------------------------------------------------------------------------UpdateView
 /*METHOD clPhysicalObject */ /* Updates the visual representation of the object. */
 property void clPhysicalObject::updateView(void) { updateView(simulator().inspectedObject()); }
}

// M o b i l e O b j e c t  Implementation //-------------------------------------------------------
namespace simulationObject {
 //-------------------------------------------------------------------------------------UpdateStatus
 property void clMobileObject::updateStatus(void) {
  clPhysicalObject::updateStatus();

  if (moving()) {
   atStatus+="\nmoving = yes";
   atStatus+="\ndeparture = "+string(atArrivalDate);
   atStatus+="\ntravel = "+string(atTravelTime);
  }
  else {
   atStatus+="\nmoving = no";
   atStatus+="\narrival = "+string(atArrivalDate);
  }
 }
 //-------------------------------------------------------------------------------------------Arrive
 /*METHOD clMobileObject */
 /* Manages the arrival of the object in the layout of a physical object. */
 property void clMobileObject::arrive(clPhysicalObject * agObject) {
  if (atParent!=nil) atParent->removeChild(this);
  if (agObject!=nil) agObject->addChild(this);
  atArrivalDate=simulator().date();
  atTravelTime=0;
 }
 //---------------------------------------------------------------------------------------------Move
 /*METHOD clMobileObject */
 /* Manages the travel of the object along a given path, taking a given amount of time. */
 property void clMobileObject::move(clPath * agPath,tyCardinal agTravelTime) {
  if (agPath==nil or agPath->source()!=atParent)
   send_inline_error(erInvalidPath,"mobileObject::move");

  if (atParent!=nil) atParent->removeChild(this);
  agPath->addChild(this);
  atArrivalDate=simulator().date();
  atTravelTime=agTravelTime;

  simulator().schedule(simulator().date()+atTravelTime,this,method_id(clMobileObject,arrive),
                       agPath->target());
 }
}

// P a t h  Implementation //-----------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------RelativeX
 /*METHOD clPath */
 /* Returns the X coordinate of the position of a mobile object, using the path,
    relative to the position of the source object of the path. */
 property tyReal clPath::relativeX(ctMobileObject * agObject) const {
  tyReal lcDistance = (simulator().date()-agObject->arrivalDate())/tyReal(agObject->travelTime());
  tyReal lcX1       = atSource->relativeX();
  tyReal lcX2       = atTarget->relativeX();

  lcDistance=standard::mini(1.0,lcDistance);
  lcDistance=standard::maxi(0.0,lcDistance);
  return ((lcX2-lcX1)*lcDistance-mini(lcX1,lcX2)+lcX1);
 }
 //----------------------------------------------------------------------------------------RelativeY
 /*METHOD clPath */
 /* Returns the Y coordinate of the position of a mobile object, using the path,
    relative to the position of the source object of the path. */
 property tyReal clPath::relativeY(ctMobileObject * agObject) const {
  tyReal lcDistance = (simulator().date()-agObject->arrivalDate())/tyReal(agObject->travelTime());
  tyReal lcY1       = atSource->relativeY();
  tyReal lcY2       = atTarget->relativeY();

  lcDistance=standard::mini(1.0,lcDistance);
  lcDistance=standard::maxi(0.0,lcDistance);
  return ((lcY2-lcY1)*lcDistance-mini(lcY1,lcY2)+lcY1);
 }
}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erInvalidPath.create("Simulation - The path used to move the object is invalid.");
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) { environment::informTermination(goModuleName); }
}

// End //-------------------------------------------------------------------------------------------
}