Dispatcher
From TrainzOnline
(Difference between revisions)
(Created page with "TBD: Update text TBD: Repost or update additional informations after reposting the registered objectsoup * CONTCRANE: Repost a goid list of reachable stacks. The contcrane i...") |
|||
Line 1: | Line 1: | ||
TBD: Update text | TBD: Update text | ||
− | TBD: Repost or update additional informations after reposting the registered objectsoup | + | '''TBD: Repost or update additional informations after reposting the registered objectsoup.''' |
+ | * CONTCRANE: Repost a goid list of reachable stacks. The contcrane itself informs the stacks about it's object data to update the maximum count of stackable containers. | ||
+ | * CONTSTACK: ??? | ||
+ | * CONTAINER: If a container has no stack place, randomly attach him to a free stack place and repost it. In case there is no one, repost an empty stack goid with place zero. '''''TBD: What happens if the stack it attached to does not exist? Possibly handled as a free container?''''' | ||
− | * CONTCRANE: Repost a goid list of reachable stacks. The contcrane itself informs the stacks about it's object data to update the maximum count of stackable containers. | + | ==Asset files pre version 0.1== |
− | * CONTSTACK: ??? | + | The files compile errorless and the messaging runs well. No more functionality implemented and tested in this pre version. |
− | * CONTAINER: If a container has no stack place, randomly attach him to a free stack place and repost it. In case there is no one, repost an empty stack goid with place zero. | + | |
+ | ===config.txt=== | ||
+ | <CODE> | ||
+ | kuid <kuid2:215489:110000:1> | ||
+ | username "aCTS DISPATCHER Library V1" | ||
+ | kind "Library" | ||
+ | category-class "YL" | ||
+ | trainz-build 4.6 | ||
+ | |||
+ | description "aCTS DISPATCHER Library V1" | ||
+ | |||
+ | script "acts_dispatcher.gs" | ||
+ | class "acts_dispatcher" | ||
+ | |||
+ | thumbnails | ||
+ | { | ||
+ | 0 | ||
+ | { | ||
+ | image "acts_dispatcher_thumb.jpg" | ||
+ | width 240 | ||
+ | height 180 | ||
+ | } | ||
+ | } | ||
+ | </CODE> | ||
+ | |||
+ | ===acts_dispatcher.gs=== | ||
+ | <CODE> | ||
+ | include "acts_global_values.gs" | ||
+ | include "acts_tools_script.gs" | ||
+ | |||
+ | //----------------------------------------------------------------------------- | ||
+ | // aCTS Dispatcher V0.1 Central Script - acts_dispatcher | ||
+ | //----------------------------------------------------------------------------- | ||
+ | // X acts_dispatcher <-- acts_dispatcher_script | ||
+ | // X acts_dispatcher_script <-- acts_dispatcher_globals | ||
+ | // X acts_dispatcher_globals <-- acts_global_values | ||
+ | // acts_global_values <-- MapObject | ||
+ | //----------------------------------------------------------------------------- | ||
+ | |||
+ | //----------------------------------------------------------------------------- | ||
+ | class acts_dispatcher_globals isclass acts_global_values | ||
+ | { | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Store from dispatcher received object registration values to the | ||
+ | // respective dispatchers sub soup. The sub soups register ids run as int | ||
+ | // from 0 ... The received id -1 tells, that the object isn't yet | ||
+ | // registered. | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Because the register id number list gets gaps while unregistering it will | ||
+ | // be nessecary to have some gap filling methods additionally. See | ||
+ | // AppendInsertUpdateObjectDataSoups and FindObjectSoupEntry methods. | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // AssetInstanceSoup { | ||
+ | // ObjectDataSoup { ... }, Only container, contstack, contcrane | ||
+ | // LocationSoup { ... }, Only container, contstack, contcrane | ||
+ | // OrientationSoup { ... }, Only container, contstack, contcrane | ||
+ | // SkinDataSoup { ... }, Only container | ||
+ | // ContentDataSoup { ... }, Only container | ||
+ | // X DispatcherDataSoup { ... } Only dispatcher | ||
+ | // X ContainerSoups { ... } Only dispatcher | ||
+ | // X ContstackSoups { ... } Only dispatcher | ||
+ | // X ContcraneSoups { ... } Only dispatcher | ||
+ | // } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | Soup ContainerSoups = Constructors.NewSoup(); | ||
+ | Soup ContstackSoups = Constructors.NewSoup(); | ||
+ | Soup ContcraneSoups = Constructors.NewSoup(); | ||
+ | //--------------------------------------------------------------------------- | ||
+ | Soup DispatcherDataSoup = Constructors.NewSoup(); | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // ObjectDataSoup received from and posted to objects. | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // ObjectDataSoup { goid GameObjectID, type string, dispID int, | ||
+ | // length int, height int, | ||
+ | // stack goid, place int, Only container | ||
+ | // active bool, action string }, | ||
+ | // activ: true means the object sended a register message while session run. | ||
+ | // All objects were set false while initialising dispatcher and if | ||
+ | // they stay false their entries will be deleted next initialising. | ||
+ | // actions: ["APPENDED", "INSERTED", "UPDATED"]; | ||
+ | //--------------------------------------------------------------------------- | ||
+ | GameObjectID dispgoid = me.GetGameObjectID(); | ||
+ | string objecttype; | ||
+ | GameObjectID objectgoid; | ||
+ | //--------------------------------------------------------------------------- | ||
+ | }; | ||
+ | |||
+ | class acts_dispatcher_script isclass acts_dispatcher_globals | ||
+ | { | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public void SetProperties(Soup soup) // Callback method after Init method | ||
+ | { | ||
+ | inherited(soup); | ||
+ | //------------------------------------------------------------------------- | ||
+ | DispatcherDataSoup.Copy(soup.GetNamedSoup("DispatcherData")); | ||
+ | ContainerSoups.Copy(soup.GetNamedSoup("ContainerSoups")); | ||
+ | ContstackSoups.Copy(soup.GetNamedSoup("ContstackSoups")); | ||
+ | ContcraneSoups.Copy(soup.GetNamedSoup("ContcraneSoups")); | ||
+ | //------------------------------------------------------------------------- | ||
+ | isSetPropertiesMethodFinnished = true; | ||
+ | PostMessage(me,"OBJECTINIT","SETPROPS_FINNISH",0); | ||
+ | return; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public Soup GetProperties(void) // Callback method before closing session | ||
+ | { | ||
+ | Soup soup = inherited(); | ||
+ | //------------------------------------------------------------------------- | ||
+ | DispatcherDataSoup.SetNamedTag("firstrun",false); | ||
+ | //------------------------------------------------------------------------- | ||
+ | soup.SetNamedSoup("DispatcherData",DispatcherDataSoup); | ||
+ | soup.SetNamedSoup("ContainerSoups",ContainerSoups); | ||
+ | soup.SetNamedSoup("ContstackSoups",ContstackSoups); | ||
+ | soup.SetNamedSoup("ContcraneSoups",ContcraneSoups); | ||
+ | //------------------------------------------------------------------------- | ||
+ | return soup; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public void WorldInitHandler(Message msg) | ||
+ | { | ||
+ | if (acts_debug) Interface.Log(Interface.GetTimeStamp() | ||
+ | + " [" + dispgoid.SerialiseToString() + "]" | ||
+ | + " DISPATCHER GOT WORLDINIT MESSAGE [" | ||
+ | + msg.major+"] ["+msg.minor+"]"); | ||
+ | //------------------------------------------------------------------------- | ||
+ | // If one of the two methods (Init or SetProperties) isn't finished yet, | ||
+ | // post "World","ModuleInit" message a little bit later again. | ||
+ | // So it is guaranteed that the Init and SetProperties methods are finished | ||
+ | // as well as the "World","ModuleInit" message tells to be save using the | ||
+ | // World.GetCurrentModule method. | ||
+ | //------------------------------------------------------------------------- | ||
+ | if (!(isSetPropertiesMethodFinnished and isInitMethodFinnished)) | ||
+ | { | ||
+ | //---------------------------------------------------------------------- | ||
+ | // While first run and before first session save for libraries the | ||
+ | // SetProperties methon will not run, whle no soup stored. If this case | ||
+ | // isn't handeled, the repost of "World","ModuleInit" runs infinitly. | ||
+ | //---------------------------------------------------------------------- | ||
+ | if (!DispatcherDataSoup.GetNamedTagAsBool("firstrun")) | ||
+ | PostMessage(me, "World", "ModuleInit", 0.1); | ||
+ | } | ||
+ | //------------------------------------------------------------------------- | ||
+ | isWorldInitFinnished = true; | ||
+ | PostMessage(me, "OBJECTINIT", "WORLD_INIT_FINNISHED", 0.0); | ||
+ | //------------------------------------------------------------------------- | ||
+ | return; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public void ObjectInitHandler(Message msg) | ||
+ | { | ||
+ | //------------------------------------------------------------------------- | ||
+ | // Until the Trainz core send the "World","ModuleInit" message it is not | ||
+ | // guarented to decide with the World.GetCurrentModule method to be in the | ||
+ | // returned module! | ||
+ | //------------------------------------------------------------------------- | ||
+ | if (acts_debug) Interface.Log(Interface.GetTimeStamp() | ||
+ | + " [" + dispgoid.SerialiseToString() + "]" | ||
+ | + " DISPATCHER GOT MESSAGE ["+msg.major+"] ["+msg.minor+"]"); | ||
+ | //-------------------------------------------------------------------------*/ | ||
+ | if (msg.dst==me and msg.major=="OBJECTINIT") | ||
+ | { | ||
+ | //----------------------------------------------------------------------- | ||
+ | if (msg.minor=="INIT_FINNISHED") | ||
+ | { | ||
+ | //--------------------------------------------------------------------- | ||
+ | // Not used yet | ||
+ | //--------------------------------------------------------------------- | ||
+ | } | ||
+ | //----------------------------------------------------------------------- | ||
+ | if (msg.minor=="SETPROPS_FINNISHED") | ||
+ | { | ||
+ | //--------------------------------------------------------------------- | ||
+ | // If DispatcherDataSoup is empty, this is the first call unsaved call | ||
+ | //--------------------------------------------------------------------- | ||
+ | if (DispatcherDataSoup.CountTags()==0) | ||
+ | DispatcherDataSoup.SetNamedTag("firstrun",true); | ||
+ | } | ||
+ | //----------------------------------------------------------------------- | ||
+ | if (msg.minor=="WORLD_INIT_FINNISHED") | ||
+ | { | ||
+ | //--------------------------------------------------------------------- | ||
+ | // Do no module only, driver module only or surveyor module only | ||
+ | // related initiations | ||
+ | //--------------------------------------------------------------------- | ||
+ | if (World.GetCurrentModule() == World.DRIVER_MODULE) | ||
+ | { | ||
+ | //------------------------------------------------------------------- | ||
+ | // Not used yet | ||
+ | //------------------------------------------------------------------- | ||
+ | } | ||
+ | //--------------------------------------------------------------------- | ||
+ | if (World.GetCurrentModule() == World.SURVEYOR_MODULE) | ||
+ | { | ||
+ | //------------------------------------------------------------------- | ||
+ | // Not used yet | ||
+ | //------------------------------------------------------------------- | ||
+ | } | ||
+ | //--------------------------------------------------------------------- | ||
+ | if (World.GetCurrentModule() == World.NO_MODULE) | ||
+ | { | ||
+ | //------------------------------------------------------------------- | ||
+ | // Not used yet | ||
+ | //------------------------------------------------------------------- | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Search the objects soup for next free entry gap. Parameter dsp is the | ||
+ | // object's type dispatcher sub soup (ContainerSoups, ContstackSoups or | ||
+ | // ContcraneSoups). Method returns a soup. | ||
+ | // soup { entry int, action string, active bool } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | Soup FindObjectSoupEntry(GameObjectID goid, Soup dsp) | ||
+ | { | ||
+ | int entry; | ||
+ | string action; | ||
+ | Soup rsp = Constructors.NewSoup(); | ||
+ | rsp.SetNamedTag("active",true); | ||
+ | int i; | ||
+ | for (i=0; i<dsp.CountTags(); i++) | ||
+ | { | ||
+ | entry = Str.ToInt(dsp.GetIndexedTagName(i)); | ||
+ | Soup sp = dsp.GetNamedSoup(entry); | ||
+ | if (sp.GetNamedTagAsGameObjectID("goid")==goid) // TBD: goid compar ison | ||
+ | { | ||
+ | rsp.SetNamedTag("entry",entry); | ||
+ | rsp.SetNamedTag("action","UPDATED"); | ||
+ | return rsp; | ||
+ | } | ||
+ | } | ||
+ | entry = actsTools.GetObjectSoupGap(dsp); | ||
+ | if (entry==dsp.CountTags()) rsp.SetNamedTag("action","APPENDED"); | ||
+ | else rsp.SetNamedTag("action","INSERTED"); | ||
+ | rsp.SetNamedTag("entry",entry); | ||
+ | return rsp; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Search the goid and update, insert or append the soup to register | ||
+ | // Parameter osp is the posted ObjectDataSoup. The other three are the | ||
+ | // dispatcher's object soups subsoups. | ||
+ | //--------------------------------------------------------------------------- | ||
+ | void AppendInsertUpdateObjectDataSoups(Soup osp, | ||
+ | Soup ContSps, Soup StackSps, Soup CraneSps) | ||
+ | { | ||
+ | //------------------------------------------------------------------------- | ||
+ | string type = osp.GetNamedTag("type"); | ||
+ | GameObjectID objgoid = osp.GetNamedTagAsGameObjectID("type"); | ||
+ | Soup objsps = Constructors.NewSoup(); | ||
+ | if (type == "CONTAINER") objsps = ContSps; | ||
+ | if (type == "CONTSTACK") objsps = StackSps; | ||
+ | if (type == "CONTCRANE") objsps = CraneSps; | ||
+ | Soup entry = FindObjectSoupEntry(objgoid, objsps); | ||
+ | // entry { entry int, active bool, action string } | ||
+ | // actions = ["APPENDED", "INSERTED", "UPDATED"]; | ||
+ | osp.SetNamedTag("active", true); | ||
+ | osp.SetNamedTag("action", entry.GetNamedTag("action")); | ||
+ | objsps.SetNamedSoup(entry.GetNamedTagAsInt("entry"), osp); | ||
+ | //------------------------------------------------------------------------- | ||
+ | // Post retour that register is updated | ||
+ | //------------------------------------------------------------------------- | ||
+ | GameObject obj = Router.GetGameObject(objgoid); | ||
+ | PostMessage(obj, "DISPATCHER", | ||
+ | "OBJECTSOUP_" + entry.GetNamedTag("action"), osp, 0.0); | ||
+ | //------------------------------------------------------------------------- | ||
+ | if (acts_debug) Interface.Log(Interface.GetTimeStamp() | ||
+ | + " [" + dispgoid.SerialiseToString() + "]" | ||
+ | + " DISPATCHER OBJECTSOUP " + entry.GetNamedTag("action") | ||
+ | + " " + type + " GOID [" + objgoid.SerialiseToString() + "]"); | ||
+ | if (acts_debug) Interface.Log(Interface.GetTimeStamp() | ||
+ | + " CONTENT OF " + entry.GetNamedTag("action") + " SOUP FROM GOID" | ||
+ | + " [" + objgoid.SerialiseToString() + "]"); | ||
+ | if (acts_debug) actsTools.ShowSoup(osp,"OSP=>"); | ||
+ | //-------------------------------------------------------------------------*/ | ||
+ | return; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public void RegisterHandler(Message msg) | ||
+ | { | ||
+ | if (msg.dst==me and msg.major=="REGISTER") | ||
+ | { | ||
+ | //----------------------------------------------------------------------- | ||
+ | if (acts_debug) Interface.Log(Interface.GetTimeStamp() | ||
+ | + " ["+dispgoid.SerialiseToString()+"]" | ||
+ | + " DISPATCHER GOT MESSAGE FROM OBJECT [" | ||
+ | + (cast<GameObject>msg.src).GetGameObjectID().SerialiseToString() | ||
+ | + "] [" + msg.major + "] [" + msg.minor + "]"); | ||
+ | //-----------------------------------------------------------------------*/ | ||
+ | if (msg.minor=="REGISTER_ME") | ||
+ | { | ||
+ | //--------------------------------------------------------------------- | ||
+ | // Update, insert or append the ObjectDataSoup | ||
+ | //--------------------------------------------------------------------- | ||
+ | Soup RegDataSoup = Constructors.NewSoup(); | ||
+ | RegDataSoup.Copy(cast<Soup>msg.paramSoup); | ||
+ | //--------------------------------------------------------------------- | ||
+ | if (acts_debug) Interface.Log(Interface.GetTimeStamp() | ||
+ | + " SOUP CONTENT OF 'DataSoup To Register' GOID" | ||
+ | + " [" + dispgoid.SerialiseToString() + "]"); | ||
+ | if (acts_debug) actsTools.ShowSoup(RegDataSoup,"=>"); | ||
+ | //--------------------------------------------------------------------- | ||
+ | AppendInsertUpdateObjectDataSoups(RegDataSoup, | ||
+ | ContainerSoups, ContstackSoups, ContcraneSoups); | ||
+ | //--------------------------------------------------------------------- | ||
+ | // TBD: Repost or update additional informations | ||
+ | // * CONTCRANE: Repost a goid list of reachable stacks. The contcrane | ||
+ | // itself informs the stacks about it's object data to update the | ||
+ | // maximum count of stackable containers. | ||
+ | // * CONTSTACK: ??? | ||
+ | // * CONTAINER: If a container has no stack place, randomly attach | ||
+ | // him to a free stack place and repost it. In case there is no | ||
+ | // one, repost an empty stack goid with place zero. | ||
+ | // TBD: What happens if the stack it attached to does not exist? | ||
+ | // Possibly handled as a free container? | ||
+ | //--------------------------------------------------------------------- | ||
+ | } | ||
+ | //----------------------------------------------------------------------- | ||
+ | } | ||
+ | return; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | class acts_dispatcher isclass acts_dispatcher_script | ||
+ | { | ||
+ | public void Init() | ||
+ | { | ||
+ | inherited(); | ||
+ | //------------------------------------------------------------------------- | ||
+ | // Make shure that the right module is set for World.GetCurrentModle() | ||
+ | // (see world.gs lines 939ff.) to start driver only or surveyor only | ||
+ | // related initiations and tell me, if my Init and SetProperties methods | ||
+ | // are finished | ||
+ | //------------------------------------------------------------------------- | ||
+ | AddHandler(me, "World", "ModuleInit", "WorldInitHandler"); | ||
+ | AddHandler(me, "OBJECTINIT", "", "ObjectInitHandler"); | ||
+ | AddHandler(me, "REGISTER", "", "RegisterHandler"); | ||
+ | //------------------------------------------------------------------------- | ||
+ | // Set asset special initial values | ||
+ | //------------------------------------------------------------------------- | ||
+ | objecttype = "DISPATCHER"; | ||
+ | //------------------------------------------------------------------------- | ||
+ | isInitMethodFinnished = true; | ||
+ | PostMessage(me,"OBJECTINIT","INIT_FINNISHED",0.0); // Init method finnished | ||
+ | return; | ||
+ | } | ||
+ | }; | ||
+ | </CODE> | ||
+ | |||
+ | ===acts_global_values.gs=== | ||
+ | <CODE> | ||
+ | include "mapobject.gs" | ||
+ | |||
+ | //----------------------------------------------------------------------------- | ||
+ | // Common aCTS values V0.1 - Dispatcher, Container, Stack, Crane Tools Script | ||
+ | //----------------------------------------------------------------------------- | ||
+ | |||
+ | class acts_global_values isclass MapObject | ||
+ | { | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Global variables | ||
+ | //--------------------------------------------------------------------------- | ||
+ | bool acts_debug = true; | ||
+ | //--------------------------------------------------------------------------- | ||
+ | float baseboardwidth = 720; | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Technical values from normatives | ||
+ | // -------------------------------------------------------------------------- | ||
+ | int container_length_10ft = 2991; // in [mm] | ||
+ | int container_length_20ft = 6058; // in [mm] | ||
+ | int container_length_40ft = 12192; // in [mm] | ||
+ | int container_length_45ft = 13716; // in [mm] | ||
+ | int container_length_53ft = 16154; // in [mm] | ||
+ | // -------------------------------------------------------------------------- | ||
+ | int container_width = 2438; // in [mm] | ||
+ | int container_height = 2591; // in [mm] | ||
+ | int container_deltahc = 305; // in [mm] | ||
+ | // -------------------------------------------------------------------------- | ||
+ | bool isWorldInitFinnished = false; | ||
+ | bool isInitMethodFinnished = false; | ||
+ | bool isSetPropertiesMethodFinnished = false; | ||
+ | //--------------------------------------------------------------------------- | ||
+ | }; | ||
+ | </CODE> | ||
+ | |||
+ | ===acts_tools_script.gs.gs=== | ||
+ | <CODE> | ||
+ | include "acts_global_values.gs" | ||
+ | |||
+ | //----------------------------------------------------------------------------- | ||
+ | // Common aCTS methods V0.1 - Dispatcher, Container, Stack, Crane Tools Script | ||
+ | //----------------------------------------------------------------------------- | ||
+ | |||
+ | final static class actsTools isclass acts_global_values | ||
+ | { | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Log soup content of a soup of soups only and without subsoups | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public void ShowSoup(Soup sp, string ind) | ||
+ | { | ||
+ | if (sp.CountTags()!=0) | ||
+ | { | ||
+ | int i; | ||
+ | for (i=0; i<sp.CountTags(); i++) | ||
+ | if (acts_debug) Interface.Log(ind + sp.GetIndexedTagName(i) | ||
+ | + " ["+sp.GetNamedTag(sp.GetIndexedTagName(i))+"]"); | ||
+ | } | ||
+ | return; | ||
+ | } | ||
+ | public void ShowSoups(Soup soup, string indent) | ||
+ | { | ||
+ | string ind = "="+indent; | ||
+ | int sc = soup.CountTags(); | ||
+ | int i; | ||
+ | for (i=0; i<sc; i++) | ||
+ | { | ||
+ | if (acts_debug) Interface.Log(indent + i + ".SubSoup"); | ||
+ | actsTools.ShowSoup(soup.GetNamedSoup(i),ind); | ||
+ | } | ||
+ | return; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Set all ObjectSoups active false and get the last insert gap | ||
+ | // TBD: Starting with a sorted soup | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public void ResetObjectSoups(Soup soup) | ||
+ | { | ||
+ | int i; | ||
+ | int gap = soup.CountTags();; | ||
+ | for (i=0; i<soup.CountTags(); i++) | ||
+ | { | ||
+ | int tn = Str.ToInt(soup.GetIndexedTagName(i)); | ||
+ | Soup sp = soup.GetNamedSoup(tn); | ||
+ | if (sp.GetNamedTagAsBool("active")) | ||
+ | { | ||
+ | sp.SetNamedTag("active",false); | ||
+ | soup.SetNamedSoup(tn,sp); | ||
+ | } else soup.RemoveNamedTag(tn); | ||
+ | } | ||
+ | return; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Return the first indexed gap in existing objectsoups tagnames | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public int GetObjectSoupGap(Soup soup) | ||
+ | { | ||
+ | int i; | ||
+ | for (i=0; i<soup.CountTags(); i++) | ||
+ | if (soup.GetIndexForNamedTag(i)==-1) return i; | ||
+ | return soup.CountTags(); | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Generate soup representation from WorldCoordinate | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public Soup WCoordToSoup(WorldCoordinate pos) | ||
+ | { | ||
+ | Soup sp = Constructors.NewSoup(); | ||
+ | sp.SetNamedTag("bbx",pos.baseboardX); | ||
+ | sp.SetNamedTag("bby",pos.baseboardY); | ||
+ | sp.SetNamedTag("px",pos.x); | ||
+ | sp.SetNamedTag("py",pos.y); | ||
+ | sp.SetNamedTag("pz",pos.z); | ||
+ | return sp; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Generate WorldCoordinate from its soup representation | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public WorldCoordinate WCoordFromSoup(Soup sp) | ||
+ | { | ||
+ | WorldCoordinate WC; | ||
+ | WC.baseboardX = sp.GetNamedTagAsInt("bbx"); | ||
+ | WC.baseboardY = sp.GetNamedTagAsInt("bby"); | ||
+ | WC.x = sp.GetNamedTagAsFloat("px"); | ||
+ | WC.y = sp.GetNamedTagAsFloat("py"); | ||
+ | WC.z = sp.GetNamedTagAsFloat("pz"); | ||
+ | return WC; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Normalize the WC to baseboard width | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public WorldCoordinate WCoordNormalize(WorldCoordinate WC) | ||
+ | { | ||
+ | WorldCoordinate nWC; | ||
+ | //------------------------------------------------------------------------- | ||
+ | int bx = WC.x * 1000.0 / baseboardwidth; // Basebord delta | ||
+ | if (WC.x < 0.0) bx--; | ||
+ | nWC.baseboardX = WC.baseboardX + bx; | ||
+ | nWC.x = WC.x - bx * baseboardwidth; | ||
+ | //------------------------------------------------------------------------- | ||
+ | int by = WC.y * 1000.0 / baseboardwidth; // Basebord delta | ||
+ | if (WC.y < 0.0) by--; | ||
+ | nWC.baseboardY = WC.baseboardX + by; | ||
+ | nWC.y = WC.y - by * baseboardwidth; | ||
+ | //------------------------------------------------------------------------- | ||
+ | nWC.z = WC.z; | ||
+ | return nWC; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Adjust baseboard from one WorlCoordinate to another | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public WorldCoordinate | ||
+ | WCoordAdjustBaseboard(WorldCoordinate frWC, WorldCoordinate toWC) | ||
+ | { | ||
+ | WorldCoordinate adjWC; | ||
+ | //------------------------------------------------------------------------- | ||
+ | adjWC.x = toWC.x + (frWC.baseboardX - toWC.baseboardX)*baseboardwidth; | ||
+ | adjWC.baseboardX = frWC.baseboardX; | ||
+ | adjWC.y = toWC.y + (frWC.baseboardY - toWC.baseboardY)*baseboardwidth; | ||
+ | adjWC.baseboardY = frWC.baseboardY; | ||
+ | adjWC.z = toWC.z; | ||
+ | //------------------------------------------------------------------------- | ||
+ | return adjWC; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Generate soup representation from Orientation | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public Soup OrientationToSoup(Orientation rot) | ||
+ | { | ||
+ | Soup sp = Constructors.NewSoup(); | ||
+ | sp.SetNamedTag("gx",rot.rx * 1800.0 / Math.PI); | ||
+ | sp.SetNamedTag("gy",rot.ry * 1800.0 / Math.PI); | ||
+ | sp.SetNamedTag("gz",rot.rz * 1800.0 / Math.PI); | ||
+ | sp.SetNamedTag("rx",rot.rx); | ||
+ | sp.SetNamedTag("ry",rot.ry); | ||
+ | sp.SetNamedTag("rz",rot.rz); | ||
+ | return sp; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Generate Orientation from its soup representation | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public Orientation OrientationFromSoup(Soup sp) | ||
+ | { | ||
+ | Orientation OR; | ||
+ | OR.rx = sp.GetNamedTagAsFloat("rx"); | ||
+ | OR.ry = sp.GetNamedTagAsFloat("ry"); | ||
+ | OR.rz = sp.GetNamedTagAsFloat("rz"); | ||
+ | return OR; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Adjust location and orientation to even mm and even 1/10° inplace | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public bool AutoAdjustTransformation(WorldCoordinate W, Orientation O) | ||
+ | { | ||
+ | float rd; | ||
+ | bool changed = false; | ||
+ | if (W.x<0) rd=-0.0005; else rd=0.0005; // rounding to full [mm] | ||
+ | int wcx = (W.x+rd) * 1000.0; | ||
+ | if (W.y<0) rd=-0.0005; else rd=0.0005; | ||
+ | int wcy = (W.y+rd) * 1000.0; | ||
+ | if (W.z<0) rd=-0.0005; else rd=0.0005; | ||
+ | int wcz = (W.z+rd) * 1000.0; | ||
+ | // rounding to full [1/10°] - here only z-axis, x,y-axis are set to zero | ||
+ | // to make shure the CTS is horizontal plane | ||
+ | if (O.rz<0) rd=-0.5; else rd=0.5; | ||
+ | int orz = O.rz * 1800.0 / Math.PI + rd; | ||
+ | if (W.x != wcx/1000.0) {W.x = wcx/1000.0; changed=true; } | ||
+ | if (W.y != wcy/1000.0) {W.y = wcy/1000.0; changed=true; } | ||
+ | if(W.z != 0.0) { W.z = 0.0; changed=true; } | ||
+ | if(O.rx != 0.0) { O.rx = 0.0; changed=true; } | ||
+ | if(O.ry != 0.0) { O.ry = 0.0; changed=true; } | ||
+ | if(O.rz != orz * Math.PI / 1800.0) | ||
+ | { O.rz = orz * Math.PI / 1800.0; changed=true; } | ||
+ | //------------------------------------------------------------------------- | ||
+ | return changed; | ||
+ | } | ||
+ | //--------------------------------------------------------------------------- | ||
+ | // Auto adjust WorldCoordinate and Orientation to [mm] and [1/10°] | ||
+ | // Adjusts the object and returns original and adjusted WC and OR as soup. | ||
+ | //--------------------------------------------------------------------------- | ||
+ | public Soup AutoAdjustMapObject(MapObject M) | ||
+ | { | ||
+ | //------------------------------------------------------------------------- | ||
+ | // M = cast<MapObject>(me); | ||
+ | //------------------------------------------------------------------------- | ||
+ | bool changed = false; | ||
+ | Soup sp = Constructors.NewSoup(); | ||
+ | WorldCoordinate W = M.GetMapObjectPosition(); | ||
+ | Orientation O = M.GetMapObjectOrientation(); | ||
+ | sp.SetNamedSoup("OriginalLocationSoup", WCoordToSoup(W)); | ||
+ | sp.SetNamedSoup("OriginalOrientationSoup", OrientationToSoup(O)); | ||
+ | changed = AutoAdjustTransformation(W,O); | ||
+ | M.SetMapObjectPosition(W); | ||
+ | M.SetMapObjectOrientation(O); | ||
+ | sp.SetNamedSoup("AdjustedLocationSoup", WCoordToSoup(W)); | ||
+ | sp.SetNamedSoup("AdjustedOrientationSoup", OrientationToSoup(O)); | ||
+ | sp.SetNamedTag("changed", changed); | ||
+ | //------------------------------------------------------------------------- | ||
+ | return sp; | ||
+ | } | ||
+ | }; | ||
+ | </CODE> | ||
[[Category:ACTS]] | [[Category:ACTS]] |
Revision as of 00:56, 25 April 2024
TBD: Update text
TBD: Repost or update additional informations after reposting the registered objectsoup. * CONTCRANE: Repost a goid list of reachable stacks. The contcrane itself informs the stacks about it's object data to update the maximum count of stackable containers. * CONTSTACK: ??? * CONTAINER: If a container has no stack place, randomly attach him to a free stack place and repost it. In case there is no one, repost an empty stack goid with place zero. TBD: What happens if the stack it attached to does not exist? Possibly handled as a free container?
Contents |
Asset files pre version 0.1
The files compile errorless and the messaging runs well. No more functionality implemented and tested in this pre version.
config.txt
kuid <kuid2:215489:110000:1> username "aCTS DISPATCHER Library V1" kind "Library" category-class "YL" trainz-build 4.6 description "aCTS DISPATCHER Library V1" script "acts_dispatcher.gs" class "acts_dispatcher" thumbnails { 0 { image "acts_dispatcher_thumb.jpg" width 240 height 180 } }
acts_dispatcher.gs
include "acts_global_values.gs" include "acts_tools_script.gs" //----------------------------------------------------------------------------- // aCTS Dispatcher V0.1 Central Script - acts_dispatcher //----------------------------------------------------------------------------- // X acts_dispatcher <-- acts_dispatcher_script // X acts_dispatcher_script <-- acts_dispatcher_globals // X acts_dispatcher_globals <-- acts_global_values // acts_global_values <-- MapObject //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- class acts_dispatcher_globals isclass acts_global_values { //--------------------------------------------------------------------------- // Store from dispatcher received object registration values to the // respective dispatchers sub soup. The sub soups register ids run as int // from 0 ... The received id -1 tells, that the object isn't yet // registered. //--------------------------------------------------------------------------- // Because the register id number list gets gaps while unregistering it will // be nessecary to have some gap filling methods additionally. See // AppendInsertUpdateObjectDataSoups and FindObjectSoupEntry methods. //--------------------------------------------------------------------------- // AssetInstanceSoup { // ObjectDataSoup { ... }, Only container, contstack, contcrane // LocationSoup { ... }, Only container, contstack, contcrane // OrientationSoup { ... }, Only container, contstack, contcrane // SkinDataSoup { ... }, Only container // ContentDataSoup { ... }, Only container // X DispatcherDataSoup { ... } Only dispatcher // X ContainerSoups { ... } Only dispatcher // X ContstackSoups { ... } Only dispatcher // X ContcraneSoups { ... } Only dispatcher // } //--------------------------------------------------------------------------- Soup ContainerSoups = Constructors.NewSoup(); Soup ContstackSoups = Constructors.NewSoup(); Soup ContcraneSoups = Constructors.NewSoup(); //--------------------------------------------------------------------------- Soup DispatcherDataSoup = Constructors.NewSoup(); //--------------------------------------------------------------------------- // ObjectDataSoup received from and posted to objects. //--------------------------------------------------------------------------- // ObjectDataSoup { goid GameObjectID, type string, dispID int, // length int, height int, // stack goid, place int, Only container // active bool, action string }, // activ: true means the object sended a register message while session run. // All objects were set false while initialising dispatcher and if // they stay false their entries will be deleted next initialising. // actions: ["APPENDED", "INSERTED", "UPDATED"]; //--------------------------------------------------------------------------- GameObjectID dispgoid = me.GetGameObjectID(); string objecttype; GameObjectID objectgoid; //--------------------------------------------------------------------------- }; class acts_dispatcher_script isclass acts_dispatcher_globals { //--------------------------------------------------------------------------- public void SetProperties(Soup soup) // Callback method after Init method { inherited(soup); //------------------------------------------------------------------------- DispatcherDataSoup.Copy(soup.GetNamedSoup("DispatcherData")); ContainerSoups.Copy(soup.GetNamedSoup("ContainerSoups")); ContstackSoups.Copy(soup.GetNamedSoup("ContstackSoups")); ContcraneSoups.Copy(soup.GetNamedSoup("ContcraneSoups")); //------------------------------------------------------------------------- isSetPropertiesMethodFinnished = true; PostMessage(me,"OBJECTINIT","SETPROPS_FINNISH",0); return; } //--------------------------------------------------------------------------- public Soup GetProperties(void) // Callback method before closing session { Soup soup = inherited(); //------------------------------------------------------------------------- DispatcherDataSoup.SetNamedTag("firstrun",false); //------------------------------------------------------------------------- soup.SetNamedSoup("DispatcherData",DispatcherDataSoup); soup.SetNamedSoup("ContainerSoups",ContainerSoups); soup.SetNamedSoup("ContstackSoups",ContstackSoups); soup.SetNamedSoup("ContcraneSoups",ContcraneSoups); //------------------------------------------------------------------------- return soup; } //--------------------------------------------------------------------------- public void WorldInitHandler(Message msg) { if (acts_debug) Interface.Log(Interface.GetTimeStamp() + " [" + dispgoid.SerialiseToString() + "]" + " DISPATCHER GOT WORLDINIT MESSAGE [" + msg.major+"] ["+msg.minor+"]"); //------------------------------------------------------------------------- // If one of the two methods (Init or SetProperties) isn't finished yet, // post "World","ModuleInit" message a little bit later again. // So it is guaranteed that the Init and SetProperties methods are finished // as well as the "World","ModuleInit" message tells to be save using the // World.GetCurrentModule method. //------------------------------------------------------------------------- if (!(isSetPropertiesMethodFinnished and isInitMethodFinnished)) { //---------------------------------------------------------------------- // While first run and before first session save for libraries the // SetProperties methon will not run, whle no soup stored. If this case // isn't handeled, the repost of "World","ModuleInit" runs infinitly. //---------------------------------------------------------------------- if (!DispatcherDataSoup.GetNamedTagAsBool("firstrun")) PostMessage(me, "World", "ModuleInit", 0.1); } //------------------------------------------------------------------------- isWorldInitFinnished = true; PostMessage(me, "OBJECTINIT", "WORLD_INIT_FINNISHED", 0.0); //------------------------------------------------------------------------- return; } //--------------------------------------------------------------------------- public void ObjectInitHandler(Message msg) { //------------------------------------------------------------------------- // Until the Trainz core send the "World","ModuleInit" message it is not // guarented to decide with the World.GetCurrentModule method to be in the // returned module! //------------------------------------------------------------------------- if (acts_debug) Interface.Log(Interface.GetTimeStamp() + " [" + dispgoid.SerialiseToString() + "]" + " DISPATCHER GOT MESSAGE ["+msg.major+"] ["+msg.minor+"]"); //-------------------------------------------------------------------------*/ if (msg.dst==me and msg.major=="OBJECTINIT") { //----------------------------------------------------------------------- if (msg.minor=="INIT_FINNISHED") { //--------------------------------------------------------------------- // Not used yet //--------------------------------------------------------------------- } //----------------------------------------------------------------------- if (msg.minor=="SETPROPS_FINNISHED") { //--------------------------------------------------------------------- // If DispatcherDataSoup is empty, this is the first call unsaved call //--------------------------------------------------------------------- if (DispatcherDataSoup.CountTags()==0) DispatcherDataSoup.SetNamedTag("firstrun",true); } //----------------------------------------------------------------------- if (msg.minor=="WORLD_INIT_FINNISHED") { //--------------------------------------------------------------------- // Do no module only, driver module only or surveyor module only // related initiations //--------------------------------------------------------------------- if (World.GetCurrentModule() == World.DRIVER_MODULE) { //------------------------------------------------------------------- // Not used yet //------------------------------------------------------------------- } //--------------------------------------------------------------------- if (World.GetCurrentModule() == World.SURVEYOR_MODULE) { //------------------------------------------------------------------- // Not used yet //------------------------------------------------------------------- } //--------------------------------------------------------------------- if (World.GetCurrentModule() == World.NO_MODULE) { //------------------------------------------------------------------- // Not used yet //------------------------------------------------------------------- } } } } //--------------------------------------------------------------------------- // Search the objects soup for next free entry gap. Parameter dsp is the // object's type dispatcher sub soup (ContainerSoups, ContstackSoups or // ContcraneSoups). Method returns a soup. // soup { entry int, action string, active bool } //--------------------------------------------------------------------------- Soup FindObjectSoupEntry(GameObjectID goid, Soup dsp) { int entry; string action; Soup rsp = Constructors.NewSoup(); rsp.SetNamedTag("active",true); int i; for (i=0; i<dsp.CountTags(); i++) { entry = Str.ToInt(dsp.GetIndexedTagName(i)); Soup sp = dsp.GetNamedSoup(entry); if (sp.GetNamedTagAsGameObjectID("goid")==goid) // TBD: goid compar ison { rsp.SetNamedTag("entry",entry); rsp.SetNamedTag("action","UPDATED"); return rsp; } } entry = actsTools.GetObjectSoupGap(dsp); if (entry==dsp.CountTags()) rsp.SetNamedTag("action","APPENDED"); else rsp.SetNamedTag("action","INSERTED"); rsp.SetNamedTag("entry",entry); return rsp; } //--------------------------------------------------------------------------- // Search the goid and update, insert or append the soup to register // Parameter osp is the posted ObjectDataSoup. The other three are the // dispatcher's object soups subsoups. //--------------------------------------------------------------------------- void AppendInsertUpdateObjectDataSoups(Soup osp, Soup ContSps, Soup StackSps, Soup CraneSps) { //------------------------------------------------------------------------- string type = osp.GetNamedTag("type"); GameObjectID objgoid = osp.GetNamedTagAsGameObjectID("type"); Soup objsps = Constructors.NewSoup(); if (type == "CONTAINER") objsps = ContSps; if (type == "CONTSTACK") objsps = StackSps; if (type == "CONTCRANE") objsps = CraneSps; Soup entry = FindObjectSoupEntry(objgoid, objsps); // entry { entry int, active bool, action string } // actions = ["APPENDED", "INSERTED", "UPDATED"]; osp.SetNamedTag("active", true); osp.SetNamedTag("action", entry.GetNamedTag("action")); objsps.SetNamedSoup(entry.GetNamedTagAsInt("entry"), osp); //------------------------------------------------------------------------- // Post retour that register is updated //------------------------------------------------------------------------- GameObject obj = Router.GetGameObject(objgoid); PostMessage(obj, "DISPATCHER", "OBJECTSOUP_" + entry.GetNamedTag("action"), osp, 0.0); //------------------------------------------------------------------------- if (acts_debug) Interface.Log(Interface.GetTimeStamp() + " [" + dispgoid.SerialiseToString() + "]" + " DISPATCHER OBJECTSOUP " + entry.GetNamedTag("action") + " " + type + " GOID [" + objgoid.SerialiseToString() + "]"); if (acts_debug) Interface.Log(Interface.GetTimeStamp() + " CONTENT OF " + entry.GetNamedTag("action") + " SOUP FROM GOID" + " [" + objgoid.SerialiseToString() + "]"); if (acts_debug) actsTools.ShowSoup(osp,"OSP=>"); //-------------------------------------------------------------------------*/ return; } //--------------------------------------------------------------------------- public void RegisterHandler(Message msg) { if (msg.dst==me and msg.major=="REGISTER") { //----------------------------------------------------------------------- if (acts_debug) Interface.Log(Interface.GetTimeStamp() + " ["+dispgoid.SerialiseToString()+"]" + " DISPATCHER GOT MESSAGE FROM OBJECT [" + (cast<GameObject>msg.src).GetGameObjectID().SerialiseToString() + "] [" + msg.major + "] [" + msg.minor + "]"); //-----------------------------------------------------------------------*/ if (msg.minor=="REGISTER_ME") { //--------------------------------------------------------------------- // Update, insert or append the ObjectDataSoup //--------------------------------------------------------------------- Soup RegDataSoup = Constructors.NewSoup(); RegDataSoup.Copy(cast<Soup>msg.paramSoup); //--------------------------------------------------------------------- if (acts_debug) Interface.Log(Interface.GetTimeStamp() + " SOUP CONTENT OF 'DataSoup To Register' GOID" + " [" + dispgoid.SerialiseToString() + "]"); if (acts_debug) actsTools.ShowSoup(RegDataSoup,"=>"); //--------------------------------------------------------------------- AppendInsertUpdateObjectDataSoups(RegDataSoup, ContainerSoups, ContstackSoups, ContcraneSoups); //--------------------------------------------------------------------- // TBD: Repost or update additional informations // * CONTCRANE: Repost a goid list of reachable stacks. The contcrane // itself informs the stacks about it's object data to update the // maximum count of stackable containers. // * CONTSTACK: ??? // * CONTAINER: If a container has no stack place, randomly attach // him to a free stack place and repost it. In case there is no // one, repost an empty stack goid with place zero. // TBD: What happens if the stack it attached to does not exist? // Possibly handled as a free container? //--------------------------------------------------------------------- } //----------------------------------------------------------------------- } return; } }; class acts_dispatcher isclass acts_dispatcher_script { public void Init() { inherited(); //------------------------------------------------------------------------- // Make shure that the right module is set for World.GetCurrentModle() // (see world.gs lines 939ff.) to start driver only or surveyor only // related initiations and tell me, if my Init and SetProperties methods // are finished //------------------------------------------------------------------------- AddHandler(me, "World", "ModuleInit", "WorldInitHandler"); AddHandler(me, "OBJECTINIT", "", "ObjectInitHandler"); AddHandler(me, "REGISTER", "", "RegisterHandler"); //------------------------------------------------------------------------- // Set asset special initial values //------------------------------------------------------------------------- objecttype = "DISPATCHER"; //------------------------------------------------------------------------- isInitMethodFinnished = true; PostMessage(me,"OBJECTINIT","INIT_FINNISHED",0.0); // Init method finnished return; } };
acts_global_values.gs
include "mapobject.gs" //----------------------------------------------------------------------------- // Common aCTS values V0.1 - Dispatcher, Container, Stack, Crane Tools Script //----------------------------------------------------------------------------- class acts_global_values isclass MapObject { //--------------------------------------------------------------------------- // Global variables //--------------------------------------------------------------------------- bool acts_debug = true; //--------------------------------------------------------------------------- float baseboardwidth = 720; //--------------------------------------------------------------------------- // Technical values from normatives // -------------------------------------------------------------------------- int container_length_10ft = 2991; // in [mm] int container_length_20ft = 6058; // in [mm] int container_length_40ft = 12192; // in [mm] int container_length_45ft = 13716; // in [mm] int container_length_53ft = 16154; // in [mm] // -------------------------------------------------------------------------- int container_width = 2438; // in [mm] int container_height = 2591; // in [mm] int container_deltahc = 305; // in [mm] // -------------------------------------------------------------------------- bool isWorldInitFinnished = false; bool isInitMethodFinnished = false; bool isSetPropertiesMethodFinnished = false; //--------------------------------------------------------------------------- };
acts_tools_script.gs.gs
include "acts_global_values.gs" //----------------------------------------------------------------------------- // Common aCTS methods V0.1 - Dispatcher, Container, Stack, Crane Tools Script //----------------------------------------------------------------------------- final static class actsTools isclass acts_global_values { //--------------------------------------------------------------------------- // Log soup content of a soup of soups only and without subsoups //--------------------------------------------------------------------------- public void ShowSoup(Soup sp, string ind) { if (sp.CountTags()!=0) { int i; for (i=0; i<sp.CountTags(); i++) if (acts_debug) Interface.Log(ind + sp.GetIndexedTagName(i) + " ["+sp.GetNamedTag(sp.GetIndexedTagName(i))+"]"); } return; } public void ShowSoups(Soup soup, string indent) { string ind = "="+indent; int sc = soup.CountTags(); int i; for (i=0; i<sc; i++) { if (acts_debug) Interface.Log(indent + i + ".SubSoup"); actsTools.ShowSoup(soup.GetNamedSoup(i),ind); } return; } //--------------------------------------------------------------------------- // Set all ObjectSoups active false and get the last insert gap // TBD: Starting with a sorted soup //--------------------------------------------------------------------------- public void ResetObjectSoups(Soup soup) { int i; int gap = soup.CountTags();; for (i=0; i<soup.CountTags(); i++) { int tn = Str.ToInt(soup.GetIndexedTagName(i)); Soup sp = soup.GetNamedSoup(tn); if (sp.GetNamedTagAsBool("active")) { sp.SetNamedTag("active",false); soup.SetNamedSoup(tn,sp); } else soup.RemoveNamedTag(tn); } return; } //--------------------------------------------------------------------------- // Return the first indexed gap in existing objectsoups tagnames //--------------------------------------------------------------------------- public int GetObjectSoupGap(Soup soup) { int i; for (i=0; i<soup.CountTags(); i++) if (soup.GetIndexForNamedTag(i)==-1) return i; return soup.CountTags(); } //--------------------------------------------------------------------------- // Generate soup representation from WorldCoordinate //--------------------------------------------------------------------------- public Soup WCoordToSoup(WorldCoordinate pos) { Soup sp = Constructors.NewSoup(); sp.SetNamedTag("bbx",pos.baseboardX); sp.SetNamedTag("bby",pos.baseboardY); sp.SetNamedTag("px",pos.x); sp.SetNamedTag("py",pos.y); sp.SetNamedTag("pz",pos.z); return sp; } //--------------------------------------------------------------------------- // Generate WorldCoordinate from its soup representation //--------------------------------------------------------------------------- public WorldCoordinate WCoordFromSoup(Soup sp) { WorldCoordinate WC; WC.baseboardX = sp.GetNamedTagAsInt("bbx"); WC.baseboardY = sp.GetNamedTagAsInt("bby"); WC.x = sp.GetNamedTagAsFloat("px"); WC.y = sp.GetNamedTagAsFloat("py"); WC.z = sp.GetNamedTagAsFloat("pz"); return WC; } //--------------------------------------------------------------------------- // Normalize the WC to baseboard width //--------------------------------------------------------------------------- public WorldCoordinate WCoordNormalize(WorldCoordinate WC) { WorldCoordinate nWC; //------------------------------------------------------------------------- int bx = WC.x * 1000.0 / baseboardwidth; // Basebord delta if (WC.x < 0.0) bx--; nWC.baseboardX = WC.baseboardX + bx; nWC.x = WC.x - bx * baseboardwidth; //------------------------------------------------------------------------- int by = WC.y * 1000.0 / baseboardwidth; // Basebord delta if (WC.y < 0.0) by--; nWC.baseboardY = WC.baseboardX + by; nWC.y = WC.y - by * baseboardwidth; //------------------------------------------------------------------------- nWC.z = WC.z; return nWC; } //--------------------------------------------------------------------------- // Adjust baseboard from one WorlCoordinate to another //--------------------------------------------------------------------------- public WorldCoordinate WCoordAdjustBaseboard(WorldCoordinate frWC, WorldCoordinate toWC) { WorldCoordinate adjWC; //------------------------------------------------------------------------- adjWC.x = toWC.x + (frWC.baseboardX - toWC.baseboardX)*baseboardwidth; adjWC.baseboardX = frWC.baseboardX; adjWC.y = toWC.y + (frWC.baseboardY - toWC.baseboardY)*baseboardwidth; adjWC.baseboardY = frWC.baseboardY; adjWC.z = toWC.z; //------------------------------------------------------------------------- return adjWC; } //--------------------------------------------------------------------------- // Generate soup representation from Orientation //--------------------------------------------------------------------------- public Soup OrientationToSoup(Orientation rot) { Soup sp = Constructors.NewSoup(); sp.SetNamedTag("gx",rot.rx * 1800.0 / Math.PI); sp.SetNamedTag("gy",rot.ry * 1800.0 / Math.PI); sp.SetNamedTag("gz",rot.rz * 1800.0 / Math.PI); sp.SetNamedTag("rx",rot.rx); sp.SetNamedTag("ry",rot.ry); sp.SetNamedTag("rz",rot.rz); return sp; } //--------------------------------------------------------------------------- // Generate Orientation from its soup representation //--------------------------------------------------------------------------- public Orientation OrientationFromSoup(Soup sp) { Orientation OR; OR.rx = sp.GetNamedTagAsFloat("rx"); OR.ry = sp.GetNamedTagAsFloat("ry"); OR.rz = sp.GetNamedTagAsFloat("rz"); return OR; } //--------------------------------------------------------------------------- // Adjust location and orientation to even mm and even 1/10° inplace //--------------------------------------------------------------------------- public bool AutoAdjustTransformation(WorldCoordinate W, Orientation O) { float rd; bool changed = false; if (W.x<0) rd=-0.0005; else rd=0.0005; // rounding to full [mm] int wcx = (W.x+rd) * 1000.0; if (W.y<0) rd=-0.0005; else rd=0.0005; int wcy = (W.y+rd) * 1000.0; if (W.z<0) rd=-0.0005; else rd=0.0005; int wcz = (W.z+rd) * 1000.0; // rounding to full [1/10°] - here only z-axis, x,y-axis are set to zero // to make shure the CTS is horizontal plane if (O.rz<0) rd=-0.5; else rd=0.5; int orz = O.rz * 1800.0 / Math.PI + rd; if (W.x != wcx/1000.0) {W.x = wcx/1000.0; changed=true; } if (W.y != wcy/1000.0) {W.y = wcy/1000.0; changed=true; } if(W.z != 0.0) { W.z = 0.0; changed=true; } if(O.rx != 0.0) { O.rx = 0.0; changed=true; } if(O.ry != 0.0) { O.ry = 0.0; changed=true; } if(O.rz != orz * Math.PI / 1800.0) { O.rz = orz * Math.PI / 1800.0; changed=true; } //------------------------------------------------------------------------- return changed; } //--------------------------------------------------------------------------- // Auto adjust WorldCoordinate and Orientation to [mm] and [1/10°] // Adjusts the object and returns original and adjusted WC and OR as soup. //--------------------------------------------------------------------------- public Soup AutoAdjustMapObject(MapObject M) { //------------------------------------------------------------------------- // M = cast<MapObject>(me); //------------------------------------------------------------------------- bool changed = false; Soup sp = Constructors.NewSoup(); WorldCoordinate W = M.GetMapObjectPosition(); Orientation O = M.GetMapObjectOrientation(); sp.SetNamedSoup("OriginalLocationSoup", WCoordToSoup(W)); sp.SetNamedSoup("OriginalOrientationSoup", OrientationToSoup(O)); changed = AutoAdjustTransformation(W,O); M.SetMapObjectPosition(W); M.SetMapObjectOrientation(O); sp.SetNamedSoup("AdjustedLocationSoup", WCoordToSoup(W)); sp.SetNamedSoup("AdjustedOrientationSoup", OrientationToSoup(O)); sp.SetNamedTag("changed", changed); //------------------------------------------------------------------------- return sp; } };