private static void ReconfigureStationAccess() { var pathList = new List <BuildingInfo.PathInfo>(); var connectList = new List <Vector3[]>(); var singleGap = 16; var directionList = new List <string>(); //for (int i = 0; i < m_Info.m_paths.Length; i++) //{ // var thePath = m_Info.m_paths[i]; // if (thePath.m_netInfo == null || thePath.m_nodes == null || thePath.m_nodes.Count() < 2) // continue; // if (thePath.m_netInfo.IsUndergroundMetroStationTrack()) // { // var xDirection = (thePath.m_nodes.First().x - thePath.m_nodes.Last().x); // var zDirection = (thePath.m_nodes.First().z - thePath.m_nodes.Last().z); // var direction = $"{xDirection},{zDirection}"; // var antiDirection = $"{-xDirection},{-zDirection}"; // if (directionList.Contains(direction)) // { // continue; // } // if (directionList.Contains(antiDirection)) // { // thePath.m_nodes = thePath.m_nodes.Reverse().ToArray(); // } // else // { // directionList.Add(direction); // } // } //} for (int i = 0; i < m_Info.m_paths.Length; i++) { var thePath = m_Info.m_paths[i]; if (thePath.m_netInfo == null || thePath.m_nodes == null || thePath.m_nodes.Count() < 2) { continue; } if (thePath.m_netInfo.IsUndergroundSmallStationTrack() && !IsPathGenerated(thePath)) { var xCoeff = -(thePath.m_nodes.First().x - thePath.m_nodes.Last().x) / Vector3.Distance(thePath.m_nodes.First(), thePath.m_nodes.Last()); var zCoeff = (thePath.m_nodes.First().z - thePath.m_nodes.Last().z) / Vector3.Distance(thePath.m_nodes.First(), thePath.m_nodes.Last()); var multiplier = 1; var nearestTrackNode = m_Info.m_paths.Where(p => p.m_netInfo.IsUndergroundMetroStationTrack()).SelectMany(p => p.m_nodes).Where(n => n.y == thePath.m_nodes.First().y).OrderBy(n => Vector3.Distance(n, thePath.m_nodes.First())).FirstOrDefault(); if (Vector3.Distance(nearestTrackNode, thePath.m_nodes.First()) <= 2 * singleGap) { multiplier = -1; } var aNewPath = thePath.ShallowClone(); var nodeList = new List <Vector3>(); nodeList.Add(new Vector3() { x = thePath.m_nodes.First().x + multiplier * zCoeff * singleGap, y = thePath.m_nodes.First().y, z = thePath.m_nodes.First().z + multiplier * xCoeff * singleGap }); nodeList.Add(new Vector3() { x = thePath.m_nodes.Last().x + multiplier * zCoeff * singleGap, y = thePath.m_nodes.Last().y, z = thePath.m_nodes.Last().z + multiplier * xCoeff * singleGap }); aNewPath.m_nodes = nodeList.ToArray(); MarkPathGenerated(aNewPath); pathList.Add(aNewPath); } pathList.Add(thePath); } var aPath = pathList.FirstOrDefault(p => IsPedestrianPath(p)); if (aPath == null) { aPath = new BuildingInfo.PathInfo(); } for (int i = 0; i < pathList.Count; i++) { if (pathList[i].m_netInfo != null && pathList[i].m_netInfo.IsUndergroundMetroStationTrack()) { TrackPath = pathList[i]; var middleBend = GetMiddle(TrackPath, true); var middle = GetMiddle(TrackPath, false); BendVector = middleBend - middle; //var trackNodes = new List<Vector3>(); //for (var j = 0; j < trackPath.m_nodes.Count(); j++) //{ // trackNodes.Add(new Vector3() // { // x = trackPath.m_nodes[j].x - bendVector.x, // y = trackPath.m_nodes[j].y, // z = trackPath.m_nodes[j].z - bendVector.z // }); //} //trackPath.m_nodes = trackNodes.ToArray(); NewPath = aPath.ShallowClone(); NewPath.AssignNetInfo(SpecialNetInfo); MarkPathGenerated(NewPath); xCoeff = -(TrackPath.m_nodes[0].x - TrackPath.m_nodes.Last().x) / Vector3.Distance(TrackPath.m_nodes[0], TrackPath.m_nodes.Last()); zCoeff = (TrackPath.m_nodes[0].z - TrackPath.m_nodes.Last().z) / Vector3.Distance(TrackPath.m_nodes[0], TrackPath.m_nodes.Last()); var stationLength = Vector3.Distance(TrackPath.m_nodes[0], TrackPath.m_nodes.Last()); StairsLengthX = (((0.12f * m_BendStrength) + 1) * (stationLength * StairCoeff)) * -xCoeff; StairsLengthZ = (((0.12f * m_BendStrength) + 1) * (stationLength * StairCoeff)) * zCoeff; var interpolant = 0.6f; Crossing = Vector3.Lerp(TrackPath.m_nodes.First(), TrackPath.m_nodes.Last(), interpolant); if (TrackPath.m_netInfo.IsUndergroundIslandPlatformStationTrack()) { pathList.AddRange(SetStationPaths(0)); } //else if (TrackPath.m_netInfo.IsUndergroundSideIslandPlatformMetroStationTrack()) //{ // pathList.AddRange(SetStationPaths(-14, 0, 14)); //} else if (TrackPath.m_netInfo.IsUndergroundSmallStationTrack()) { pathList.AddRange(SetStationPaths(5)); } else if (TrackPath.m_netInfo.IsUndergroundPlatformLargeMetroStationTrack()) { pathList.AddRange(SetStationPaths(-11, 11)); } else if (TrackPath.m_netInfo.IsUndergroundDualIslandPlatformMetroStationTrack()) { pathList.AddRange(SetStationPaths(-8.8f, -5.5f, 5.5f, 8.8f)); } else if (TrackPath.m_netInfo.IsUndergroundSidePlatformMetroStationTrack()) { pathList.AddRange(SetStationPaths(-7, 7)); } if (!connectList.Contains(NewPath.m_nodes)) { connectList.Add(NewPath.m_nodes); } } } if (/*m_SuperInfo == null &&*/ m_Info.m_paths.Count() >= 2) { CheckPedestrianConnections(); } pathList = CleanPaths(pathList); var lowestHighPaths = m_Info.m_paths.Where(p => IsPedestrianPath(p) && p.m_nodes.Any(n => n.y > -4) && p.m_nodes.Any(nd => nd.y <= -4)).ToList(); if (lowestHighPaths.Count == 0) { lowestHighPaths.Add(m_Info.m_paths.Where(p => IsPedestrianPath(p)) .OrderByDescending(p => p.m_nodes[0].y) .FirstOrDefault()); } var connectPoints = new List <Vector3>(); if (lowestHighPaths != null && lowestHighPaths.Count > 0) { foreach (BuildingInfo.PathInfo p in lowestHighPaths) { if (p != null && p.m_nodes != null && p.m_nodes.Count() > 0) { connectPoints.Add(p.m_nodes.OrderByDescending(n => n.y).ThenBy(n => n.z).LastOrDefault()); } } } var currentVector = connectPoints.FirstOrDefault(); if (connectPoints != null && connectPoints.Count > 0) { var pool = new List <Vector3[]>(); var pivotPath = pathList.FirstOrDefault(p => p.m_nodes.Any(n => n == connectPoints.FirstOrDefault())); pool.AddRange(connectList); for (var i = 0; i < connectList.Count; i++) { var closestVector = pool.SelectMany(n => n).OrderBy(n => (currentVector.x - n.x) + (100 * (connectPoints.FirstOrDefault().y - n.y)) + (currentVector.z - n.z)).LastOrDefault(); var closestPath = pathList.FirstOrDefault(p => p.m_nodes.Any(n => n == closestVector)); BuildingInfo.PathInfo branch = null; if (currentVector == connectPoints.FirstOrDefault()) { branch = ChainPath(pivotPath, closestVector, Array.IndexOf(pivotPath.m_nodes, connectPoints.FirstOrDefault())); } else { branch = ChainPath(closestPath, currentVector, Array.IndexOf(closestPath.m_nodes, closestVector)); } branch.AssignNetInfo(SpecialNetInfo); branch.m_forbidLaneConnection = new[] { true, true }; pathList.Add(branch); var nodeArrayToLose = pool.FirstOrDefault(na => na.Any(n => n == closestVector)); if (nodeArrayToLose != null) { currentVector = nodeArrayToLose.OrderBy(n => Vector3.Distance(closestVector, n)).LastOrDefault(); pool.Remove(nodeArrayToLose); } } if (connectPoints.Count > 1) { for (var i = 1; i < connectPoints.Count(); i++) { Vector3 node = connectPoints[i]; Vector3 closestVector = connectList.SelectMany(n => n).OrderBy(n => (node.x - n.x) + (100 * (node.y - n.y)) + (node.z - n.z)).FirstOrDefault(); var closestPath = pathList.FirstOrDefault(p => p.m_nodes.Any(n => n == closestVector)); var branch = ChainPath(closestPath, node, Array.IndexOf(closestPath.m_nodes, closestVector)); branch.AssignNetInfo(SpecialNetInfo); branch.m_forbidLaneConnection = new[] { true, true }; pathList.Add(branch); } } } m_Info.m_paths = CleanPaths(pathList).ToArray(); }
private static List <BuildingInfo.PathInfo> SetStationPaths(params float[] connectorHalfWidths) { var retval = new List <BuildingInfo.PathInfo>(); if (connectorHalfWidths != null) { var newNodes = new List <Vector3>(); var connectorHalfWidthList = new List <float>(); connectorHalfWidthList.AddRange(connectorHalfWidths); connectorHalfWidthList.Sort(); var offset = connectorHalfWidthList[0]; var forbiddenList = new List <bool>(); for (int i = 0; i < connectorHalfWidthList.Count(); i++) { if (i == 0) { newNodes.Add(new Vector3() { x = Crossing.x + (connectorHalfWidthList[0] * zCoeff) - (3 * xCoeff), y = TrackPath.m_nodes.Last().y + 8, z = Crossing.z + (connectorHalfWidthList[0] * xCoeff) + (3 * zCoeff) }); newNodes[0] = new Vector3(newNodes[0].x - BendVector.x, newNodes[0].y, newNodes[0].z + BendVector.z); } else { offset -= connectorHalfWidthList[i]; newNodes.Add(new Vector3() { x = newNodes[i - 1].x + (Math.Abs(offset) * zCoeff), y = TrackPath.m_nodes.Last().y + 8, z = newNodes[i - 1].z + (Math.Abs(offset) * xCoeff) }); offset = connectorHalfWidthList[i]; } forbiddenList.Add(true); } var averagedNodeList = new List <Vector3>(); var stairNodes = new List <Vector3>(); if (newNodes.Count() == 1) { averagedNodeList.Add(newNodes.First()); stairNodes.Add(new Vector3() { x = newNodes[0].x + StairsLengthX, y = TrackPath.m_nodes.Last().y, z = newNodes[0].z + StairsLengthZ, }); } else { var mergeOnLast = false; for (int i = 0; i < newNodes.Count(); i++) { if (i > 0) { if (mergeOnLast) { mergeOnLast = false; } else if (Vector3.Distance(newNodes[i], newNodes[i - 1]) < 4) { averagedNodeList.Add(((newNodes[i] + newNodes[i - 1]) / 2)); mergeOnLast = true; } else { averagedNodeList.Add(newNodes[i - 1]); if (i == newNodes.Count() - 1) { averagedNodeList.Add(newNodes[i]); } } } stairNodes.Add(new Vector3() { x = newNodes[i].x + StairsLengthX, y = TrackPath.m_nodes.Last().y, z = newNodes[i].z + StairsLengthZ, }); } } NewPath.m_nodes = averagedNodeList.ToArray(); NewPath.m_forbidLaneConnection = forbiddenList.ToArray(); NewPath.AssignNetInfo(m_SpecialNetInfo); retval.Add(NewPath); for (var i = 0; i < stairNodes.Count(); i++) { var closestIndex = averagedNodeList.IndexOf(averagedNodeList.OrderBy(n => Vector3.Distance(n, stairNodes[i])).FirstOrDefault()); var branchPathStair = ChainPath(NewPath, stairNodes[i], closestIndex); branchPathStair.m_forbidLaneConnection = new[] { true, false }; branchPathStair.AssignNetInfo(m_SpecialNetInfo); retval.Add(branchPathStair); } } return(retval); }