Jump to content
Ed!

Not all roads are connected?

Recommended Posts

I've created a script that finds the shortest route between points via roads. But I've found that not all roads are connected properly. Is there a workaround to know which roads are connected without using roadsConnectedTo?

 

I montirored the search by adding a marker to jump to the active node being searched and it stopped at the following spot (marked with red arrow): 

pOjIUOu.jpg?1

 

createMarker ["tst",[0,0]];
			"tst" setMarkerShape "ELLIPSE";
			"tst" setMarkerSize [50,50];			
			"tst" setMarkerColor "ColorGreen";

SelectFrontier = {
	node = Frontier select 0;
	Frontier deleteAt 0;
	node;
};

InsertFrontier = {
	_alreadyExplored = false;
	
	{
		if(_this select 0 == _x select 0) exitWith{//Both parent and current node must match, because it allows exploring different paths in junctions (paths with more than 2 paths attached to them)
			//Already explored or on line to be explored
hint "Already Explored";			
_alreadyExplored = true;	
		};
	
	}foreach Explored + Frontier;
	
	if(_alreadyExplored) exitWith{};
	hint "adding";
	_tmpFront = [];
	_tmpBack= [];
	_score = (_this select 2) + ((_this select 0) distance Destination);
	{		
		if(_score > ((Frontier select _forEachIndex) select 2) + (((Frontier select _forEachIndex) select 0) distance Destination)) then
		{
			_tmpFront = _tmpFront + [Frontier select _forEachIndex];
		} 
		else 
		{
			_tmpBack = _tmpBack + [Frontier select _forEachIndex];
		};
	}foreach Frontier;
	
	systemchat str Frontier;
	
	Frontier = _tmpFront + [_this] + _tmpBack;

	
	systemchat ("added to:" + str count(_tmpFront));
};

CreateNode = {
	_score = 0;
	if(!isNull ((_this select 1) select 0)) then
	{
		_score = ((_this select 0) distance (_this select 1 select 0)) + (_this select 1 select 2); //(distance between currentNode & parentNode) + parentNodeScore
	};
	[_this select 0, _this select 1, _score];
};


	Destination = (destinationlogic nearRoads 10) select 0;
	if(isNull Destination) exitWith{ hint "BAD ROAD!";};
	Start = (player nearRoads 10) select 0;
	Frontier = [[Start, [objNull, nil, 0]] call CreateNode];
	Explored = [];
	pathFound = false;
	[] spawn {
	
	while{count Frontier > 0 && !pathFound} do
	{		
		_currentNode = call SelectFrontier;
		"tst" setMarkerPos getPos (_currentNode select 0);
		Explored = Explored + [_currentNode];
		hint str (count(roadsConnectedTo (_currentNode select 0)));
		{
			if(_x == Destination) then {
				pathFound = true;
				player setPos getPos _x;
				goalNode = [_x, _currentNode] call CreateNode
			};
			if(str _x != str(_currentNode select 1)) then {
				([_x, _currentNode] call CreateNode) call InsertFrontier;
			};
		} foreach roadsConnectedTo (_currentNode select 0);
	};
	
	
	if(!isNil "goalNode") then
	{
		_curNode = goalNode;
		while{!isNull (_curNode select 0)} do 
		{
			_markerstr = createMarker [str random 1000000,_curNode select 0];
			_markerstr setMarkerShape "ELLIPSE";
			_markerstr setMarkerSize [10,10];
			_markerstr setMarkerPos getPos (_curNode select 0);
			_markerstr setMarkerColor "ColorGreen";
			_curNode = _curNode select 1;
		};
	};
	hint "done";
	}; 

Share this post


Link to post
Share on other sites

That means that road is not really connected (engine wise) to where visually seems to.

 

The only workaround I can tell you is to create a whitelist of roads which have this situation, so: if ((count roadsConnectedTo _road) == 1) then {if (_road in whiteListRoads) then....  

 

I'm curious to know if the path of your script is the same than AI uses to travel in SAFE or CARELESS mode, is it?

  • Like 1

Share this post


Link to post
Share on other sites

That means that road is not really connected (engine wise) to where visually seems to.

 

The only workaround I can tell you is to create a whitelist of roads which have this situation, so: if ((count roadsConnectedTo _road) == 1) then {if (_road in whiteListRoads) then....  

 

I'm curious to know if the path of your script is the same than AI uses to travel in SAFE or CARELESS mode, is it?

I haven't tested this, although I think the result might be very similar.

 

I also thought the (count roadsConnectedTo _road) == 1, but the problem was that it was 2. There is a junction in the road. The result should have been 3 roadsConnectedTo.

 

Finding the shortest route would have taken about 10 seconds instead of a minute if those roads were connected.

Share this post


Link to post
Share on other sites

Yep. Encountered same thing, when was doing something analogous. Here are some insights on this issue, where proposed workaround was using nearRoads and proper solution - a dev fixing the map or road network creation tool. :)

  • Like 1

Share this post


Link to post
Share on other sites

Not sure when that will get fixed but anyways here is somewhat of a work around.

 

Once you get to the point where roadsConnectedTo is not returning an expected value define last/current road segment object
represented by _last_marked_road_segment.

Then you can do something like.

_current_road_pos = getPos _last_marked_road_segment;
_roads = _current_road_pos nearRoads 20;
if (count _roads > 1) then {
    _roadsSorted = [_roads,[],{_current_road_pos distance _x},"ASCEND"] call BIS_fnc_sortBy;
    _roadsSorted = _roadsSorted - [_last_marked_road_segment];
    if (count _roadsSorted > 0) then {
        _nearestRoad = _roadsSorted select 0;
    };
};

Share this post


Link to post
Share on other sites

If I am understanding well your answers, he can't do it that way, as he would be searching for nearRoads in each segment, which is cpu murdering...

 

It's easier to have a whitelist, even if my example was bad, because the "bad" road may have more than one connection, it's easier to check if the road segment is in the array on each iteration than making a road search...

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×