-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dead end connection #1613
Dead end connection #1613
Changes from all commits
c62e1d8
e43fdda
60919b3
e41dd64
4f961a0
c533aae
58fa219
e03aaef
1680031
c36c4b0
b3bee3e
bd1ab6a
2792e1a
d8c4e6e
b418f7b
a92d189
78816d9
9559eb6
23beaee
eb48b16
78fefac
c207794
34b4ee7
f6e8709
a9c4e95
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -249,6 +249,7 @@ internal bool RemoveLaneConnection(uint sourceLaneId, uint targetLaneId, bool so | |
ushort targetSegmentId = targetLaneId.ToLane().m_segment; | ||
ushort nodeId = sourceSegmentId.ToSegment().GetNodeId(sourceStartNode); | ||
var result = connectionDataBase_.Disconnect(sourceLaneId, targetLaneId, nodeId); | ||
AssertLane(sourceLaneId, sourceStartNode); | ||
|
||
if (verbose_) { | ||
Log._Debug($"LaneConnectionSubManager({Group}).RemoveLaneConnection({sourceLaneId}, {targetLaneId}, " + | ||
|
@@ -298,6 +299,10 @@ internal void RemoveLaneConnectionsFromNode(ushort nodeId) { | |
} | ||
} | ||
|
||
if (Supports(LaneEndTransitionGroup.Road)) { | ||
LaneArrowManager.Instance.ResetNodeLaneArrows(nodeId); | ||
} | ||
|
||
for (int i = 0; i < 8; ++i) { | ||
ushort segmentId = node.GetSegment(i); | ||
RoutingManager.Instance.RequestRecalculation(segmentId); | ||
|
@@ -341,9 +346,6 @@ internal void RemoveLaneConnections(uint laneId, | |
/// <param name="sourceStartNode">The affected node</param> | ||
/// <returns>true if any connection was added</returns> | ||
internal bool AddLaneConnection(uint sourceLaneId, uint targetLaneId, bool sourceStartNode) { | ||
if (sourceLaneId == targetLaneId) { | ||
return false; | ||
} | ||
|
||
bool valid = ValidateLane(sourceLaneId) & ValidateLane(targetLaneId); | ||
if (!valid) { | ||
|
@@ -376,14 +378,17 @@ static bool IsDirectionValid(ref NetLane lane, NetInfo.Lane laneInfo, ushort nod | |
return dir.IsFlagSet(NetInfo.Direction.Backward); | ||
} | ||
} | ||
canConnect = | ||
IsDirectionValid(ref sourceNetLane, sourceLaneInfo, nodeId, true) && | ||
IsDirectionValid(ref targetNetLane, targetLaneInfo, nodeId, false); | ||
canConnect = IsDirectionValid(ref sourceNetLane, sourceLaneInfo, nodeId, true); | ||
bool deadEnd = sourceLaneId == targetLaneId; | ||
if (!deadEnd) { | ||
canConnect &= IsDirectionValid(ref targetNetLane, targetLaneInfo, nodeId, false); | ||
} | ||
|
||
if (!canConnect) { | ||
return false; | ||
} | ||
|
||
if (Group == LaneEndTransitionGroup.Track) { | ||
if (!deadEnd && Group == LaneEndTransitionGroup.Track) { | ||
bool targetStartnode = targetSegmentId.ToSegment().IsStartNode(nodeId); | ||
canConnect = LaneConnectionManager.CheckSegmentsTurningAngle( | ||
sourceSegmentId, sourceStartNode, targetSegmentId, targetStartnode); | ||
|
@@ -392,8 +397,36 @@ static bool IsDirectionValid(ref NetLane lane, NetInfo.Lane laneInfo, ushort nod | |
} | ||
} | ||
|
||
var connections = GetLaneConnections(sourceLaneId, sourceStartNode); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this could be its own method right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what can be its own method? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. basically the whole block that was added. or something like that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it would be two one line functions (unless if you count in the verbose log). Not sure this is a good idea. |
||
if (verbose_) { | ||
Log._Debug($"AddLaneConnection: {sourceLaneId}->{targetLaneId} at {nodeId} connections={connections.ToSTR()}"); | ||
} | ||
if (connections != null) { | ||
foreach (uint laneId in connections) { | ||
LaneEnd key = new(laneId, nodeId); | ||
if (deadEnd) { | ||
if (laneId != sourceLaneId) { | ||
// dead end lane connection cannot have other lane connections. | ||
if (verbose_) { | ||
Log._Debug($"making a dead end connection disconnecting {sourceLaneId}->{laneId} at {nodeId}"); | ||
} | ||
connectionDataBase_.Disconnect(sourceLaneId, laneId, nodeId); | ||
} | ||
} else { | ||
if (laneId == sourceLaneId) { | ||
// if adding a new connection then remove the dead end connection. | ||
if (verbose_) { | ||
Log._Debug($"removing dead end connection for lane:{sourceLaneId} at node:{nodeId}"); | ||
} | ||
connectionDataBase_.Disconnect(sourceLaneId, sourceLaneId, nodeId); | ||
} | ||
} | ||
} | ||
} | ||
|
||
connectionDataBase_.ConnectTo(sourceLaneId, targetLaneId, nodeId); | ||
Assert(AreLanesConnected(sourceLaneId, targetLaneId, sourceStartNode), $"AreLanesConnected({sourceLaneId}, {targetLaneId}, {sourceStartNode})"); | ||
AssertLane(sourceLaneId, sourceStartNode); | ||
DaEgi01 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (verbose_) { | ||
Log._Debug($"LaneConnectionSubManager({Group}).AddLaneConnection({sourceLaneId}, " + | ||
|
@@ -423,6 +456,16 @@ static bool IsDirectionValid(ref NetLane lane, NetInfo.Lane laneInfo, ushort nod | |
return true; | ||
} | ||
|
||
private void AssertLane(uint laneId, bool startNode) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this function ends with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its only called when adding/removing lane connections so its not performance critical. therefore I decided to include it in release build. you never know .... it might help with debugging user errors. Should I make it conditional? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean the assert function is marked debug only. i believe it is. So in release this code does nothing, just calculates values and returns. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assert is not marked as debug. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably AssertDeadEndConnection would be a better method name. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think i should also add |
||
Assert(laneId.ToLane().IsValidWithSegment(), $"IsValidWithSegment() faild for laneId:{laneId}"); | ||
var connections = GetLaneConnections(laneId, startNode); | ||
if (connections != null && connections.Contains(laneId)) { | ||
// dead end should only have one connection to itself. | ||
ushort nodeId = laneId.ToLane().GetNodeId(startNode); | ||
Assert(connections.Length == 1, $"connections for lane:{laneId} at node:{nodeId} = " + connections.ToSTR()); | ||
} | ||
} | ||
|
||
private void ReleasingSegment(ushort segmentId, ref NetSegment segment) { | ||
if (verbose_) { | ||
Log._Debug($"LaneConnectionSubManager({Group}).ReleasingSegment({segmentId}, isValid={segment.IsValid()}): " + | ||
|
@@ -462,15 +505,6 @@ private void RecalculateLaneArrows(uint laneId, ushort nodeId, bool startNode) { | |
return; | ||
} | ||
|
||
if (!HasOutgoingConnections(laneId, startNode)) { | ||
if (verbose_) { | ||
Log._Debug($"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"lane {laneId} does not have outgoing connections"); | ||
} | ||
|
||
return; | ||
} | ||
|
||
if (nodeId == 0) { | ||
if (verbose_) { | ||
Log._Debug($"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
|
@@ -480,7 +514,6 @@ private void RecalculateLaneArrows(uint laneId, ushort nodeId, bool startNode) { | |
return; | ||
} | ||
|
||
var arrows = LaneArrows.None; | ||
ushort segmentId = laneId.ToLane().m_segment; | ||
|
||
if (segmentId == 0) { | ||
|
@@ -508,153 +541,43 @@ private void RecalculateLaneArrows(uint laneId, ushort nodeId, bool startNode) { | |
return; | ||
} | ||
|
||
IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; | ||
ExtSegmentEnd segEnd = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)]; | ||
|
||
for (int i = 0; i < 8; ++i) { | ||
ushort otherSegmentId = netNode.GetSegment(i); | ||
if (otherSegmentId != 0) { | ||
//TODO move the following into a function | ||
ArrowDirection dir = segEndMan.GetDirection(ref segEnd, otherSegmentId); | ||
|
||
if (verbose_) { | ||
Log._Debug( | ||
$"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"processing connected segment {otherSegmentId}. dir={dir}"); | ||
} | ||
|
||
// check if arrow has already been set for this direction | ||
switch (dir) { | ||
case ArrowDirection.Turn: { | ||
if (LHT) { | ||
if ((arrows & LaneArrows.Right) != LaneArrows.None) { | ||
continue; | ||
} | ||
} else { | ||
if ((arrows & LaneArrows.Left) != LaneArrows.None) { | ||
continue; | ||
} | ||
} | ||
|
||
break; | ||
} | ||
|
||
case ArrowDirection.Forward: { | ||
if ((arrows & LaneArrows.Forward) != LaneArrows.None) { | ||
continue; | ||
} | ||
|
||
break; | ||
} | ||
|
||
case ArrowDirection.Left: { | ||
if ((arrows & LaneArrows.Left) != LaneArrows.None) { | ||
continue; | ||
} | ||
|
||
break; | ||
} | ||
|
||
case ArrowDirection.Right: { | ||
if ((arrows & LaneArrows.Right) != LaneArrows.None) { | ||
continue; | ||
} | ||
|
||
break; | ||
} | ||
|
||
default: { | ||
continue; | ||
} | ||
} | ||
|
||
if (verbose_) { | ||
Log._Debug( | ||
$"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"processing connected segment {otherSegmentId}: need to determine arrows"); | ||
} | ||
|
||
bool addArrow = false; | ||
uint curLaneId = otherSegmentId.ToSegment().m_lanes; | ||
|
||
while (curLaneId != 0) { | ||
if (verbose_) { | ||
Log._Debug( | ||
$"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"processing connected segment {otherSegmentId}: checking lane {curLaneId}"); | ||
} | ||
|
||
if (AreLanesConnected(laneId, curLaneId, startNode)) { | ||
if (verbose_) { | ||
Log._Debug( | ||
$"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"processing connected segment {otherSegmentId}: checking lane " + | ||
$"{curLaneId}: lanes are connected"); | ||
} | ||
|
||
addArrow = true; | ||
break; | ||
} | ||
|
||
curLaneId = curLaneId.ToLane().m_nextLane; | ||
} | ||
|
||
if (verbose_) { | ||
Log._Debug( | ||
$"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"processing connected segment {otherSegmentId}: finished processing " + | ||
$"lanes. addArrow={addArrow} arrows (before)={arrows}"); | ||
} | ||
|
||
if (!addArrow) { | ||
continue; | ||
} | ||
|
||
switch (dir) { | ||
case ArrowDirection.Turn: { | ||
if (LHT) { | ||
arrows |= LaneArrows.Right; | ||
} else { | ||
arrows |= LaneArrows.Left; | ||
} | ||
|
||
break; | ||
} | ||
|
||
case ArrowDirection.Forward: { | ||
arrows |= LaneArrows.Forward; | ||
break; | ||
} | ||
|
||
case ArrowDirection.Left: { | ||
arrows |= LaneArrows.Left; | ||
break; | ||
} | ||
var targetLaneIds = this.GetLaneConnections(laneId, startNode); | ||
if (targetLaneIds.IsNullOrEmpty()) { | ||
LaneArrowManager.Instance.ResetLaneArrows(laneId); | ||
return; | ||
} | ||
|
||
case ArrowDirection.Right: { | ||
arrows |= LaneArrows.Right; | ||
break; | ||
} | ||
ref ExtSegmentEnd segEnd = ref ExtSegmentEndManager.Instance.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)]; | ||
|
||
default: { | ||
continue; | ||
} | ||
} | ||
|
||
if (verbose_) { | ||
Log._Debug( | ||
$"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"processing connected segment {otherSegmentId}: arrows={arrows}"); | ||
} | ||
var arrows = LaneArrows.None; | ||
foreach (uint targetLaneId in targetLaneIds) { | ||
if (targetLaneId != laneId) { | ||
ArrowDirection dir = segEndMan.GetDirection(ref segEnd, targetLaneId.ToLane().m_segment); | ||
arrows |= ToLaneArrows(dir); | ||
} | ||
} | ||
|
||
if (verbose_) { | ||
Log._Debug($"LaneConnectionSubManager({Group}).RecalculateLaneArrows({laneId}, {nodeId}): " + | ||
$"setting lane arrows to {arrows}"); | ||
$"setting lane arrows to {arrows}"); | ||
} | ||
|
||
LaneArrowManager.Instance.SetLaneArrows(laneId, arrows, true); | ||
|
||
static LaneArrows ToLaneArrows(ArrowDirection dir) { | ||
switch (dir) { | ||
case ArrowDirection.Forward: | ||
return LaneArrows.Forward; | ||
case ArrowDirection.Left: | ||
return LaneArrows.Left; | ||
case ArrowDirection.Right: | ||
return LaneArrows.Right; | ||
case ArrowDirection.Turn: | ||
return LaneArrows_Far; | ||
default: | ||
return LaneArrows.None; | ||
} | ||
} | ||
} | ||
|
||
internal void ResetLaneConnections() { | ||
|
@@ -682,10 +605,6 @@ public bool LoadData(List<Configuration.LaneConnection> data) { | |
continue; | ||
} | ||
|
||
if (conn.sourceLaneId == conn.targetLaneId) { | ||
continue; | ||
} | ||
|
||
ushort nodeId = sourceLane.GetNodeId(conn.sourceStartNode); | ||
#if DEBUGLOAD | ||
Log._Debug($"Loading lane connection: lane {conn.sourceLaneId} -> {conn.targetLaneId} @ node: {nodeId}"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ternary expression for the win
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
notice the
&=
operator. won't fit well with ternary.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true! I didn't see that at first.
wouldn't it be better to encapsulate the logic in the isdirectionvalid method itself?
since the method with the change now only does a "90% job".