I'm simulating the operation of a railroad.
I have a table with train departure time, departure location, and arrival location data. Locations are given using longitude and latitude coordinates.
I created my rail yards on the GIS map using their coordinates.
I can make the trains depart following the schedules in the table and the correct departure location.
But I can't get them to go to the right destination.
When trying to use the moveTo block you can only indicate a single destination. In my simulator, each train will go to a different yard.
How can I perform this movement using a data table and geographic coordinates?
Some pertinent remarks:
I'm not using the rail library. I'm working in the GIS space with routes determined by Anylogic itself. I didn't design or import railroads.
For this reason, I'm using the "source" and "moveTo" blocks from the process modeling library.
In the "moveTo" block I didn't find options that allow me to use the longitude and latitude data of the destination and which are stored in the data table (as I do in the "source" block).
Whenever I try to insert some code that does this, Anylogic returns saying the error:
"Exception during discrete event execution:
root:
Non-unique value in the database!"
It is better to rather use an agent-based approach for this kind of movement instead of doing it using move to blocks. It is hard to explain here but do some more tutorial examples and you will understand. You want the agents to move at a specific time and in a process flow modelling approach unless you use delay or hold blocks agents will flow from one block to the next as soon as there is space.
Here is an example of how to do it using the agent-based approach using your setup.
I have an agent called Trem with a dynamic event to move it to a specific location.
Now we populate the dynamic events with data from the database at the start of the model using the code below.
List<Tuple> rows = selectFrom(db_table)
.list();
for (Tuple row : rows) {
//What is the start time of the movement
double timeToTripBegin = dateToTime(row.get( db_table.trip_begin_time ));
//Lets create a new movement event to trigger the movement in the future
create_MoveToLocation(timeToTripBegin,
row.get( db_table.latitude_chegada ),
row.get( db_table.longitude_chegada ));
}
These events will then trigger the required movement for us when the event executes.
In our application, we draw rooms by reading information from an IFC file and then generate custom objects which are added to the model builder. For each vertex, we substract the globalOffset, so that the rooms align nicely with the model. This works perfectly for most models we have. However, for one model, the globalOffset is huge and thus, the custom objects will be drawn far away from the model.
The vertices we read from the IFC file are located in a reasonable space around {0, 0, 0}.
My question now is: How is the globalOffset calculated? What properties of the IFC file are taken into account?
As already stated, the other models work fine when we subtract the globalOffset from each vertex. Here is an example:
Thanks in advance for any form of help!
EDIT:
For everyone interested in the origin of the global offset in the IFC file: search for "ifcsite", there should be a reference to a local placement and this may contain a rather big translation (at least in my case).
The global offset is the mid-point of the model bounding box by default like the below:
var bboxMeta = model.getData().metadata["world bounding box"];
var min = new THREE.Vector3(bbox.minXYZ[0], bbox.minXYZ[1], bbox.minXYZ[2]);
var max = new THREE.Vector3(bbox.maxXYZ[0], bbox.maxXYZ[1], bbox.maxXYZ[2]);
var bbox = new THREE.Box3(min, max);
var globalOffset = bbox.center();
It's used to avoid floating point precision issues for models that are far away from the viewer's origin. By default, Forge Viewer will use this offset to move the whole model to the viewer's origin.
To get the global offset you can also use the following line of code with the same output:
let globalOffset = viewer.model.getData().globalOffset;
The measurement tool of the viewer has calibration tool. It requires that user selects two points in the viewer and define the distance with proper units.
My plan is that I will have the points defined in my model at a fixed distance. I will not need user input for this. How do I add the distance, unit, and size so as to programmatically set the calibration?
Edit: The workaround.
I need that the default units be meters and it should correctly show 1 meter on the model to 1 meter as measured by measurement tool.
For the time being, what I did is -
I manually calibrate the model using calibrate tool to meters by picking two known points in the model.
Then I used this to get the scale factor -
var measureExtension =NOP_VIEWER.getExtension('Autodesk.Measure')
var factor = measureExtension.getCalibrationFactor()
(I used the above code lines in the developer console of the browser while interacting with the viewer simultaneously.)
which gave me this value factor = 0.039369.
I am adding this scale factor in my code once the model is loaded again.
measureExtension.calibrateByScale('m', 0.039369)
This seems to solve the issue for the models that I have with me.
I know this will break once I have some different model with different default units. Please let me know if someone has a better solution.
I'm taking a quick guess by looking at the viewer3D.js source:
var measureExt = viewer.getExtension('Autodesk.Measure')
// pick from available values:
// 'decimal-ft'
// 'ft-and-fractional-in'
// 'ft-and-decimal-in'
// 'decimal-in'
// 'fractional-in'
// 'm'
// 'cm'
// 'mm'
// 'm-and-cm'
measureExt.calibrate('decimal-in', 10)
I explain my issue in below image (I'm sorry I speak English not well).
I'm using Google Maps Directions API to calculate directions between start point and destination and there is a place between them (you see in the map). How can I know that place is on route?
The only way I can think of (and I have used this method) is thus:
When you make a directions request, you receive a DirectionsResult object.
If you drill down into that result you can get latitudes and longitudes.
If you are using the JavaScript API, for example:
// Every step is about 22 LatLngs per mile; we'll try one LatLng per 3
// miles or so:
var specRoute = directionResult.routes[0].legs[0].steps[i];
for (var j = 0; j < specRoute.path.length; j = j + 171) {
var lattotal = latarr.push(specRoute.path[j].lat());
var lngtotal = lngarr.push(specRoute.path[j].lng());
}
In this example I am formatting arrays of lats and lngs to be compared to a lot of other lats and lngs in a php file elsewhere. It sounds like you only need to check one latlng so it should be simpler.
What I did thereafter (and what you could do) is to determine how close to the path your point is required to be, and write some logic to check. You could do that with straight latitude and longitude numbers, or convert to another distance measurement (miles, meters, etc).
There is a negative aspect in that you will have to deal with converging longitude lines the farther north you go (in the Northern hemisphere).
I used a regression fit workaround but there is probably a better way.
There may also be a better method for doing this, but this is the only way I could think of on past projects.
I'm using AS3, but general programming wisdom unspecific to AS3 is great too!
I am creating my first game, a top-down dungeon crawler with tile-based navigation, and I am deciding how to store my maps. I need to be able to access a specific tile at any point in time. My only thought so far is to use nested Vectors or Arrays with the first level being the row and the second being the column, something like this:
private var map:Array = new Array(Array(0,1,0,0,1,1,0),Array(0,1,0,1,0,1,0));
private var row2col3:uint = map[1][2];
/*map would display as such:*/
#|##||#
#|#|#|#
Ultimately, the idea is to build a Map class that will be easily extensible and, again, allow free access to any specific tile. I am looking for help in determining an effective/efficient design architecture for that Map class.
Thanks!
As stated in the comments I would upload and give my source code for a 12 hour challenge project to create a tile based level editor. The source code can be found at: GitHub BKYeates
This level editor focuses on textures being a power of 2, and uses blitting for drawing on all the textures. It can read, write, and store partial tiles. There is also some functionality to erase and draw on collision boxes.
Now in regards to how the storage should be setup, it is really up to you. If you are going to be storing lots of information I recommend using Vectors. Vectors perform faster than most other container types except for ByteArray (if used correctly). In my level editor I used a Vector with a particular setup.
The Vector I used named _map in a class called tilemodel. tilemodel is responsible for updating all the storage information when a change is made. The _map variable is setup like so:
_map = new Vector.<Vector.<Vector.<Object>>>();
This is a pretty heavily nested Vector and in the end stores, can you believe it, an Object! Which admittedly really chunks out the performance gains you get from using Vector when you are indexing the furthest nested elements.
But ignore that because the indexing gain from this setup is really key. The reason it is setup this way is because I can reference a layer, a row, and a column to grab a specific tile object. For example, I have a tile on layer 2 in row 12 column 13 that I want to access:
var tileObject:Object = _map[2][12][13];
That works perfectly for pretty much any scenario I could use in my tile based game, and the speed is comparatively better than that of a Object or Dictionary when this is being accessed multiple times (i.e. - in a loop which happens often).
The level editor is designed to use all blitting and leave onus to my management classes for storage. The speed gain from doing this is very high, and the way it is currently setup the tilemodel can store partial bitmaps making it slightly more flexible than your standard rigidness of a power of 2 texture reader.
Feel free to look through the source code. But here is a summary of what some of the classes do:
tilecontroller - Issues state changes and updates to tilemanager and tilemodel
tilemanager - Responsible for texture drawing and removal.
tilemodel - Stores and updates the current map on state changes.
r_loader - Loads all assets from assetList.txt (paths set to images
there).
hudcontroller - Currently this was the last thing I was working on, lets you draw on collision boxes that are stored in a separate file alongside the map.
g_global & g_keys - Global constants and static methods use
ubiquitously
LevelEditor - Main class, also designed as "View" class ( see MVC pattern: MVC Pattern )
Also as I've mentioned it can read back all the storage. The class used for that I did not upload to GitHub, but figured I would show the important method here:
//#param assets needs to be the list of loaded bitmap images
public function generateMap( assets:* ):void {
var bmd:BitmapData = new BitmapData( g_global.stageWidth, g_global.stageHeight, true, 0 );
_canvas = new Bitmap( bmd, "auto", true );
_mapLayer.addChild( _canvas );
_canvas.bitmapData.unlock();
g_global.echo( "generating map" );
var i:int, j:int, m:int;
for ( m = 0; m < _tiles.length; m++ ) {
for ( i = 0; i < _tiles[m].length; i++ ) {
for ( j = 0; j < _tiles[m][i].length; j++ ) {
//wondering why im type casting in this evaluation? _tiles[i][j].tile == int( _tiles[i][j].tile )
//the level editor stores tiles that are larger than the grid size at indices containing values that are a percent of the tile size
var tile:Object = _tiles[m][i][j];
if ( tile != null && int( tile.tile ) == tile.tile ) {
addTile( g_global.GRIDSIZE * tile.column, g_global.GRIDSIZE * tile.row, { index:tile.tile, bitmap:assets[ tile.tile ] }, tile.rotation );
}
}
}
}
_canvas.bitmapData.lock();
}
Anyway I hope this information finds you well. Good luck!
I asked a similar question a while back: https://gamedev.stackexchange.com/questions/60433/is-it-more-efficient-to-store-my-tile-grid-as-a-dictionary-or-an-array. I'm not sure that it would really matter whether it's an Array or a Vector (the differences in efficiency seem to differ between FP versions, etc.).
But, yeah, you probably want to use one or the other (not a Dictionary or anything), and you probably want to index it like [y * width + x], not [x][y]. Reasons: Efficiency and not having overly complicated data structures.
Also if you need to be able to regularly access the Array or Vector outside of that class, just make the variable internal or public or whatever; making it private and wrapping over it with functions, while being more prim-and-proper class design, would still be overkill.
One method I am using right now for my own thing is that I'm storing my tiles in a black and white pixel bitmap (and wrote a wrapper around that). I'm not sure how efficient this is overall as I've never benchmarked it and just wrote it quickly to create a map for testing purposes, but I am finding that it does offer an advantage in that I can draw my maps in an image editor and view them easily while still allowing random pixel/tile access.
Looking at your sample code, I'm guessing you have only two types of tiles right now, so you could just use black and white pixels as well if you want to try it.
I've done the 2d array method as well (using it still actually for other parts) which works fine too, but perhaps can be harder to visualise at larger sizes. Looking forward to Bennett's answer.