/// <summary> /// Gibt eine Liste mit allen Schnittpunkten von nc mit anderen existierenden NodeConnections /// </summary> /// <param name="nc">zu untersuchende NodeConnection</param> /// <param name="tolerance">Toleranz (maximale Kantenlänge der Boundingboxen)</param> /// <returns>Eine Liste mit Intersection Objekten die leer ist, falls keine Schnittpunkte existieren</returns> private List<Intersection> CalculateIntersections(NodeConnection nc, double tolerance) { List<Intersection> toReturn = new List<Intersection>(); foreach (NodeConnection nc2 in connections) { if (nc != nc2) { if ( (nc.startNode.networkLayer == nc.endNode.networkLayer && (nc2.startNode.networkLayer == nc.startNode.networkLayer || nc2.endNode.networkLayer == nc.endNode.networkLayer)) || (nc.startNode.networkLayer != nc.endNode.networkLayer && ( nc2.startNode.networkLayer == nc.startNode.networkLayer || nc2.startNode.networkLayer == nc.endNode.networkLayer || nc2.endNode.networkLayer == nc.startNode.networkLayer || nc2.endNode.networkLayer == nc.endNode.networkLayer))) { // Zeitparameterpaare ermitteln List<Pair<double>> intersectionTimes = CalculateIntersections(nc.lineSegment, nc2.lineSegment, 0d, 1d, 0d, 1d, tolerance, nc.lineSegment, nc2.lineSegment); if (intersectionTimes != null) { // Intersections erstellen foreach (Pair<double> p in intersectionTimes) { toReturn.Add(new Intersection(nc, nc2, p.Left, p.Right)); } } } } } return toReturn; }
/// <summary> /// Standardkonstruktor /// Erstellt ein neues Intersection Objekt /// Die Parameter sollten so gewählt sein, dass _aConnection.lineSegment.AtTime(_aTime) ~ _bConnection.lineSegment.AtTime(_bTime) /// </summary> /// <param name="_aConnection">NodeConnection A</param> /// <param name="_bConnection">NodeConnection B</param> /// <param name="_aTime">Zeitpunkt des Schnittpunktes an NodeConnection A</param> /// <param name="_bTime">Zeitpunkt des Schnittpunktes an NodeConnection B</param> public Intersection(NodeConnection _aConnection, NodeConnection _bConnection, double _aTime, double _bTime) { this._aConnection = _aConnection; this._bConnection = _bConnection; this._aTime = _aTime; this._bTime = _bTime; const double stepSize = 8; double distance = 0; double aPos = aArcPosition - distance; double bPos = bArcPosition - distance; while ( Vector2.GetDistance(_aConnection.lineSegment.AtPosition(aPos), _bConnection.lineSegment.AtPosition(bPos)) < 22 && aPos > 0 && bPos > 0) { aPos -= stepSize; bPos -= stepSize; distance += stepSize; } _frontWaitingDistance = distance; distance = 0; aPos = aArcPosition + distance; bPos = bArcPosition + distance; while (Vector2.GetDistance(_aConnection.lineSegment.AtPosition(aPos), _bConnection.lineSegment.AtPosition(bPos)) < 22 && aPos < _aConnection.lineSegment.length && bPos < _bConnection.lineSegment.length) { aPos += stepSize; bPos += stepSize; distance += stepSize; } _rearWaitingDistance = distance; }
/// <summary> /// Aktualisiert die NodeConnection ncToUpdate /// (Bezierkurve neu berechnen, etc.) /// </summary> /// <param name="ncToUpdate">zu aktualisierende NodeConnection</param> public void UpdateNodeConnection(NodeConnection ncToUpdate) { ncToUpdate.lineSegment = null; ncToUpdate.lineSegment = new LineSegment(0, ncToUpdate.startNode.position, ncToUpdate.startNode.outSlopeAbs, ncToUpdate.endNode.inSlopeAbs, ncToUpdate.endNode.position); FindIntersections(ncToUpdate); if (ncToUpdate.enableIncomingLineChange) { // TODO: diese Lösung ist viel zu unperformant! Da muss was anderes her. /* RemoveLineChangePoints(ncToUpdate, false, true); foreach (NodeConnection nc in m_connections) { if (nc.enableOutgoingLineChange) { FindLineChangePoints(nc, Constants.maxDistanceToLineChangePoint, Constants.maxDistanceToParallelConnection); } }*/ } else { // TODO: überlegen, ob hier wirklich nichts gemacht werden muss } if (ncToUpdate.enableOutgoingLineChange && (ncToUpdate.carsAllowed || ncToUpdate.busAllowed)) { RemoveLineChangePoints(ncToUpdate,true, false); FindLineChangePoints(ncToUpdate, Constants.maxDistanceToLineChangePoint, Constants.maxDistanceToParallelConnection); } else { // TODO: überlegen, ob hier wirklich nichts gemacht werden muss } InvalidateNodeBounds(); }
/// <summary> /// erstellt eine SpecificPosition mittels NodeConnection und Zeitparameter /// </summary> /// <param name="nc">NodeConnection</param> /// <param name="time">Zeitparameter auf der NodeConnection</param> public SpecificPosition(NodeConnection nc, double time) { this.nc = nc; this.time = time; this.arcPosition = nc.lineSegment.TimeToArcPosition(time); }
/// <summary> /// entfernt alle LineChangePoints und LineChangeIntervals zur NodeConnection nc /// </summary> /// <param name="nc">Ziel-NodeConnection der zu löschenden LineChangePoints</param> public void RemoveAllLineChangePointsTo(NodeConnection nc) { for (int i = 0; i < _lineChangePoints.Count; i++) { if ((_lineChangePoints[i].otherStart.nc == nc) || (_lineChangePoints[i].target.nc == nc)) { _lineChangePoints.RemoveAt(i); i--; } } _lineChangeIntervals.Remove(nc.endNode.hashcode); _viaLineChangeReachableNodes.Remove(nc.endNode); }
/// <summary> /// Berechnet alle Schnittpunkte von nc mit anderen existierenden NodeConnections und meldet sie an /// </summary> /// <param name="nc">zu untersuchende NodeConnection</param> public void FindIntersections(NodeConnection nc) { // erstmal bestehende Intersections dieser NodeConnections zerstören for (int i = 0; i < intersections.Count; i++) { if ((intersections[i]._aConnection == nc) || (intersections[i]._bConnection == nc)) { intersections[i].Dispose(); intersections.RemoveAt(i); i--; } } // jetzt können wir nach neuen Intersections suchen und diese anmelden List<Intersection> foundIntersections = CalculateIntersections(nc, 0.25d); foreach (Intersection i in foundIntersections) { i._aConnection.AddIntersection(i); i._bConnection.AddIntersection(i); intersections.Add(i); } }
/// <summary> /// Entfernt alle LineChangePoints, die von nc ausgehen und evtl. eingehen /// </summary> /// <param name="nc">NodeConnection dessen ausgehende LineChangePoints gelöscht werden</param> /// <param name="removeOutgoingLineChangePoints">ausgehende LineChangePoints löschen</param> /// <param name="removeIncomingLineChangePoints">eingehende LineChangePoints löschen</param> public void RemoveLineChangePoints(NodeConnection nc, bool removeOutgoingLineChangePoints, bool removeIncomingLineChangePoints) { if (removeOutgoingLineChangePoints) { nc.ClearLineChangePoints(); } if (removeIncomingLineChangePoints) { foreach (NodeConnection otherNc in _connections) { otherNc.RemoveAllLineChangePointsTo(nc); } } }
/// <summary> /// Gibt den Zeitpunkt des Schnittpunktes an der NodeConnection nc an /// </summary> /// <param name="nc">NodeConnection dessen Schnittpunkt-Zeitparameter zurückgegeben werden soll</param> /// <returns>_aTime/_bTime falls nc=_aConnection/nc=_bConnection, sonst Exception</returns> public double GetMyTime(NodeConnection nc) { if (_aConnection == nc) return _aTime; else if (_bConnection == nc) return _bTime; else throw new Exception(); }
/// <summary> /// Gibt die andere an der Intersection teilhabende NodeConnection zurück /// </summary> /// <param name="nc">NodeConnection die nicht zurückgegeben werden soll</param> /// <returns>Die NodeConnection, die sich in dieser Intersection mit nc schneidet oder null, wenn nc nicht an der Intersection teilnimmt</returns> public NodeConnection GetOtherNodeConnection(NodeConnection nc) { if (_aConnection == nc) { return _bConnection; } else if (_bConnection == nc) { return _aConnection; } else { return null; } }
/// <summary> /// Gibt Bogenlängenposition des Schnittpunktes an der NodeConnection nc an /// </summary> /// <param name="nc">NodeConnection dessen Bogenlängenposition zurückgegeben werden soll</param> /// <returns>aArcPosition/bArcPosition falls nc=_aConnection/nc=_bConnection, sonst Exception</returns> public double GetMyArcPosition(NodeConnection nc) { if (_aConnection == nc) return aArcPosition; else if (_bConnection == nc) return bArcPosition; else throw new Exception(); }
/// <summary> /// Gibt den ListNode des Schnittpunktes an der NodeConnection nc an /// </summary> /// <param name="nc">NodeConnection dessen ListNode zurückgegeben werden soll</param> /// <returns>_aListNode/_bListNode falls nc=_aConnection/nc=_bConnection, sonst Exception</returns> public LinkedListNode<Intersection> GetMyListNode(NodeConnection nc) { if (_aConnection == nc) return _aListNode; else if (_bConnection == nc) return _bListNode; else throw new Exception(); }
/// <summary> /// Returns the CrossingVehicleTimes data of the given vehicle. /// </summary> /// <param name="v">Vehicle to search for (must already be registered!).</param> /// <param name="nc">NodeConnection the vehicle is going to use (must participate on this Intersection!).</param> /// <returns>The CrossingVehicleTimes data of the given vehicle.</returns> public CrossingVehicleTimes GetCrossingVehicleTimes(IVehicle v, NodeConnection nc) { Debug.Assert(nc == _aConnection || nc == _bConnection); if (nc == _aConnection) { Debug.Assert(aCrossingVehicles.ContainsKey(v)); return aCrossingVehicles[v]; } else { Debug.Assert(bCrossingVehicles.ContainsKey(v)); return bCrossingVehicles[v]; } }
/// <summary> /// prüft ob die NodeConnection nc an der Intersection teilnimmt /// </summary> /// <param name="nc">zu prüfende NodeConnection</param> /// <returns>(nc == _aConnection) || (nc == _bConnection)</returns> public bool ContainsNodeConnection(NodeConnection nc) { return (nc == _aConnection) || (nc == _bConnection); }
/// <summary> /// Calculates all interfering vehicles from registered vehicles. /// </summary> public List<CrossingVehicleTimes> CalculateInterferingVehicles(IVehicle v, NodeConnection nc) { Debug.Assert(nc == _aConnection || nc == _bConnection); // hopefully these are references... ;) List<CrossingVehicleTimes> toReturn = new List<CrossingVehicleTimes>(); Dictionary<IVehicle, CrossingVehicleTimes> myCrossingVehicles = (nc == _aConnection ? aCrossingVehicles : bCrossingVehicles); Dictionary<IVehicle, CrossingVehicleTimes> otherCrossingVehicles = (nc == _aConnection ? bCrossingVehicles : aCrossingVehicles); CrossingVehicleTimes myCvt = myCrossingVehicles[v]; if (_aConnection.startNode != _bConnection.startNode || (_frontWaitingDistance < aArcPosition && _frontWaitingDistance < bArcPosition)) { // check each vehicle in aCrossingVehicles with each in bCrossingVehicles for interference foreach (KeyValuePair<IVehicle, CrossingVehicleTimes> ocv in otherCrossingVehicles) { if ( (!ocv.Value.willWaitInFrontOfIntersection || ocv.Value.remainingDistance < 0) && myCvt.blockingTime.IntersectsTrue(ocv.Value.blockingTime)) { toReturn.Add(ocv.Value); } } } return toReturn; }
/// <summary> /// setzt nextNodes und prevNodes bei den an nc teilnehmenden LineNodes /// </summary> /// <param name="nc">NodeConnections die angemeldet werden soll</param> private void TellNodesTheirConnection(NodeConnection nc) { nc.startNode.nextConnections.Add(nc); nc.endNode.prevConnections.Add(nc); }
/// <summary> /// Registers that the given vehicle is going to cross this intersection via the given NodeConnection. /// </summary> /// <param name="v">Vehicle to cross intersection (must not be registered yet!).</param> /// <param name="nc">NodeConnection the vehicle is going to use (must participate on this Intersection!).</param> /// <param name="distance">Current distance of the vehicle to the Intersection</param> /// <param name="currentTime">current world time.</param> public void RegisterVehicle(IVehicle v, NodeConnection nc, double distance, double currentTime) { Debug.Assert(nc == _aConnection || nc == _bConnection); // TODO: add some safety space before and behind double blockingStartTime = currentTime + CalculateArrivingTime(v, distance - (_frontWaitingDistance / 2)) - v.SafetyTime/8; double blockingEndTime = currentTime + CalculateArrivingTime(v, distance + v.length) + v.SafetyTime/8; double originalArrivingTime = currentTime + v.GetTimeToCoverDistance(distance, false); if (nc == _aConnection) { //if (aCrossingVehicles.ContainsKey(v)) //{ aCrossingVehicles.Add(v, new CrossingVehicleTimes(originalArrivingTime, distance, new Interval<double>(blockingStartTime, blockingEndTime), false)); // } } else { // if (bCrossingVehicles.ContainsKey(v)) // { bCrossingVehicles.Add(v, new CrossingVehicleTimes(originalArrivingTime, distance, new Interval<double>(blockingStartTime, blockingEndTime), false)); /* } */ } }
/// <summary> /// stellt eine NodeConnection von from nach to her /// </summary> /// <param name="from">LineNode von dem die NodeConnection ausgehen soll</param> /// <param name="to">LineNode zu der die NodeConnection hingehen soll</param> /// <param name="priority">Priorität der Linie</param> /// <param name="targetVelocity">Target velocity on the NodeConnection</param> /// <param name="carsAllowed">Flag, ob Autos auf dieser NodeConnection erlaubt sind</param> /// <param name="busAllowed">Flag, ob Busse auf dieser NodeConnection erlaubt sind</param> /// <param name="tramAllowed">Flag, ob Straßenbahnen auf dieser NodeConnection erlaubt sind</param> /// <param name="enableIncomingLineChange">Flag, ob eingehende Spurwechsel erlaubt sind</param> /// <param name="enableOutgoingLineChange">Flag, ob ausgehende Spurchwechsel erlaubt sind</param> public void Connect(LineNode from, LineNode to, int priority, double targetVelocity, bool carsAllowed, bool busAllowed, bool tramAllowed, bool enableIncomingLineChange, bool enableOutgoingLineChange) { NodeConnection nc = new NodeConnection(from, to, null, priority, targetVelocity, carsAllowed, busAllowed, tramAllowed, enableIncomingLineChange, enableOutgoingLineChange); TellNodesTheirConnection(nc); UpdateNodeConnection(nc); ResetAverageVelocities(nc); connections.Add(nc); }
/// <summary> /// Unregisters the given vehicle from this intersection. /// </summary> /// <param name="v">Vehicle to unregister (must already be registered!).</param> /// <param name="nc">NodeConnection the vehicle is going to use (must participate on this Intersection!).</param> public void UnregisterVehicle(IVehicle v, NodeConnection nc) { Debug.Assert(nc == _aConnection || nc == _bConnection); if (nc == _aConnection) { Debug.Assert(aCrossingVehicles.ContainsKey(v)); aCrossingVehicles.Remove(v); } else { Debug.Assert(bCrossingVehicles.ContainsKey(v)); bCrossingVehicles.Remove(v); } }
/// <summary> /// Berechnet alle Spurwechselstellen der NodeConnection nc mit anderen NodeConnections /// </summary> /// <param name="nc">zu untersuchende NodeConnection</param> /// <param name="distanceBetweenChangePoints">Distanz zwischen einzelnen LineChangePoints (quasi Genauigkeit)</param> /// <param name="maxDistanceToOtherNodeConnection">maximale Entfernung zwischen zwei NodeConnections zwischen denen ein Spurwechsel stattfinden darf</param> public void FindLineChangePoints(NodeConnection nc, double distanceBetweenChangePoints, double maxDistanceToOtherNodeConnection) { nc.ClearLineChangePoints(); double currentArcPosition = distanceBetweenChangePoints/2; double delta = distanceBetweenChangePoints / 4; /* * TODO: Spurwechsel funktioniert soweit so gut. Einziges Manko ist der Spurwechsel über LineNodes hinweg: * * Zum einen, können so rote Ampeln überfahren werden und zum anderen, kommt es z.T. zu sehr komischen Situationen, wo * das spurwechselnde Auto irgendwie denkt es sei viel weiter vorne und so mittendrin wartet und erst weiterfährt, wenn * das Auto 20m weiter weg ist. * * Als workaround werden jetzt doch erstmal Spurwechsel kurz vor LineNodes verboten, auch wenn das eigentlich ja gerade * auch ein Ziel der hübschen Spurwechsel war. * */ // nur so lange suchen, wie die NodeConnection lang ist while (currentArcPosition < nc.lineSegment.length - distanceBetweenChangePoints/2) { Vector2 startl = nc.lineSegment.AtPosition(currentArcPosition - delta); Vector2 startr = nc.lineSegment.AtPosition(currentArcPosition + delta); Vector2 leftVector = nc.lineSegment.DerivateAtTime(nc.lineSegment.PosToTime(currentArcPosition - delta)).RotatedClockwise.Normalized; Vector2 rightVector = nc.lineSegment.DerivateAtTime(nc.lineSegment.PosToTime(currentArcPosition + delta)).RotatedCounterClockwise.Normalized; // Faule Implementierung: statt Schnittpunkt Gerade/Bezierkurve zu berechnen nutzen wir vorhandenen // Code und Berechnen den Schnittpunkt zwischen zwei Bezierkurven. // TODO: Sollte das hier zu langsam sein, muss eben neuer optimierter Code her für die Berechnung // von Schnittpunkten Gerade/Bezierkurve LineSegment leftLS = new LineSegment(0, startl, startl + 0.25 * maxDistanceToOtherNodeConnection * leftVector, startl + 0.75 * maxDistanceToOtherNodeConnection * leftVector, startl + maxDistanceToOtherNodeConnection * leftVector); LineSegment rightLS = new LineSegment(0, startr, startr + 0.25 * maxDistanceToOtherNodeConnection * rightVector, startr + 0.75 * maxDistanceToOtherNodeConnection * rightVector, startr + maxDistanceToOtherNodeConnection * rightVector); foreach (NodeConnection nc2 in _connections) { if (nc2.enableIncomingLineChange && (nc2.carsAllowed || nc2.busAllowed) && nc != nc2 && nc.startNode.networkLayer == nc2.startNode.networkLayer && nc.endNode.networkLayer == nc2.endNode.networkLayer) { // LINKS: Zeitparameterpaare ermitteln List<Pair<double>> intersectionTimes = CalculateIntersections(leftLS, nc2.lineSegment, 0d, 1d, 0d, 1d, 8, leftLS, nc2.lineSegment); if (intersectionTimes != null) { // Startposition NodeConnection.SpecificPosition start = new NodeConnection.SpecificPosition(currentArcPosition - delta, nc); // LineChangePoints erstellen foreach (Pair<double> p in intersectionTimes) { // Winkel überprüfen if (Vector2.AngleBetween(nc.lineSegment.DerivateAtTime(nc.lineSegment.PosToTime(currentArcPosition - delta)), nc2.lineSegment.DerivateAtTime(p.Right)) < Constants.maximumAngleBetweenConnectionsForLineChangePoint) { NodeConnection.SpecificPosition otherStart = new NodeConnection.SpecificPosition(nc2, p.Right); // Einfädelpunkt des Fahrzeugs bestimmen und evtl. auf nächste NodeConnection weiterverfolgen: double distance = (nc.lineSegment.AtPosition(currentArcPosition - delta) - nc2.lineSegment.AtTime(p.Right)).Abs; // Einfädelpunkt: double arcPositionTarget = nc2.lineSegment.TimeToArcPosition(p.Right) + 3 * distance; if (arcPositionTarget <= nc2.lineSegment.length) { NodeConnection.SpecificPosition target = new NodeConnection.SpecificPosition(arcPositionTarget, nc2); nc.AddLineChangePoint(new NodeConnection.LineChangePoint(start, target, otherStart)); } else { double diff = arcPositionTarget - nc2.lineSegment.length; foreach (NodeConnection nextNc in nc2.endNode.nextConnections) { if ( (diff <= nextNc.lineSegment.length) && (nextNc.enableIncomingLineChange && (nextNc.carsAllowed || nextNc.busAllowed)) && (nc != nextNc)) { NodeConnection.SpecificPosition target = new NodeConnection.SpecificPosition(diff, nextNc); nc.AddLineChangePoint(new NodeConnection.LineChangePoint(start, target, otherStart)); } } } break; } } } // RECHTS: Zeitparameterpaare ermitteln intersectionTimes = CalculateIntersections(rightLS, nc2.lineSegment, 0d, 1d, 0d, 1d, 8, leftLS, nc2.lineSegment); if (intersectionTimes != null) { // Startposition NodeConnection.SpecificPosition start = new NodeConnection.SpecificPosition(currentArcPosition + delta, nc); // LineChangePoints erstellen foreach (Pair<double> p in intersectionTimes) { // Winkel überprüfen if (Vector2.AngleBetween(nc.lineSegment.DerivateAtTime(nc.lineSegment.PosToTime(currentArcPosition + delta)), nc2.lineSegment.DerivateAtTime(p.Right)) < Constants.maximumAngleBetweenConnectionsForLineChangePoint) { NodeConnection.SpecificPosition otherStart = new NodeConnection.SpecificPosition(nc2, p.Right); // Einfädelpunkt des Fahrzeugs bestimmen und evtl. auf nächste NodeConnection weiterverfolgen: double distance = (nc.lineSegment.AtPosition(currentArcPosition + delta) - nc2.lineSegment.AtTime(p.Right)).Abs; // Einfädelpunkt: double arcPositionTarget = nc2.lineSegment.TimeToArcPosition(p.Right) + 3 * distance; if (arcPositionTarget <= nc2.lineSegment.length) { NodeConnection.SpecificPosition target = new NodeConnection.SpecificPosition(arcPositionTarget, nc2); nc.AddLineChangePoint(new NodeConnection.LineChangePoint(start, target, otherStart)); } else { double diff = arcPositionTarget - nc2.lineSegment.length; foreach (NodeConnection nextNc in nc2.endNode.nextConnections) { if ((diff <= nextNc.lineSegment.length) && (nextNc.enableIncomingLineChange && (nextNc.carsAllowed || nextNc.busAllowed)) && (nc != nextNc)) { NodeConnection.SpecificPosition target = new NodeConnection.SpecificPosition(diff, nextNc); nc.AddLineChangePoint(new NodeConnection.LineChangePoint(start, target, otherStart)); } } } break; } } } } } currentArcPosition += distanceBetweenChangePoints; } }
/// <summary> /// Updates the already registered vehicle v crossing on nc. /// </summary> /// <param name="v">Vehicle to update (must already be registered!).</param> /// <param name="nc">NodeConnection the vehicle is going to use (must participate on this Intersection!).</param> /// <param name="distance">Current distance of the vehicle to the Intersection</param> /// <param name="currentTime">current world time.</param> public void UpdateVehicle(IVehicle v, NodeConnection nc, double distance, double currentTime) { Debug.Assert(nc == _aConnection || nc == _bConnection); // TODO: add some safety space before and behind double blockingStartTime = currentTime + CalculateArrivingTime(v, distance - (_frontWaitingDistance / 2)) - v.SafetyTime / 8; double blockingEndTime = currentTime + CalculateArrivingTime(v, distance + v.length) + v.SafetyTime / 8; if (nc == _aConnection) { Debug.Assert(aCrossingVehicles.ContainsKey(v)); CrossingVehicleTimes cvt = aCrossingVehicles[v]; // CrossingVehicleTimes is a Value-Type! cvt.remainingDistance = distance; cvt.blockingTime.left = blockingStartTime; cvt.blockingTime.right = blockingEndTime; aCrossingVehicles[v] = cvt; } else { Debug.Assert(bCrossingVehicles.ContainsKey(v)); CrossingVehicleTimes cvt = bCrossingVehicles[v]; // CrossingVehicleTimes is a Value-Type! cvt.remainingDistance = distance; cvt.blockingTime.left = blockingStartTime; cvt.blockingTime.right = blockingEndTime; bCrossingVehicles[v] = cvt; } }
/// <summary> /// Resets the average velocities array of the given NodeConnection. /// </summary> /// <param name="nc">The NodeConection to reset</param> public void ResetAverageVelocities(NodeConnection nc) { int numBuckets = (int)(GlobalTime.Instance.cycleTime * GlobalTime.Instance.ticksPerSecond); nc.ResetStatistics(numBuckets); }
/// <summary> /// Updates the already registered vehicle v crossing on nc. /// </summary> /// <param name="v">Vehicle to update (must already be registered!).</param> /// <param name="nc">NodeConnection the vehicle is going to use (must participate on this Intersection!).</param> /// <param name="willWaitInFrontOfIntersection">Set true if vehicle will wait before intersection (and thus not cross it in the meantime).</param> public void UpdateVehicle(IVehicle v, NodeConnection nc, bool willWaitInFrontOfIntersection) { Debug.Assert(nc == _aConnection || nc == _bConnection); if (nc == _aConnection) { Debug.Assert(aCrossingVehicles.ContainsKey(v)); CrossingVehicleTimes cvt = aCrossingVehicles[v]; // CrossingVehicleTimes is a Value-Type! cvt.willWaitInFrontOfIntersection = willWaitInFrontOfIntersection; aCrossingVehicles[v] = cvt; } else { Debug.Assert(bCrossingVehicles.ContainsKey(v)); CrossingVehicleTimes cvt = bCrossingVehicles[v]; // CrossingVehicleTimes is a Value-Type! cvt.willWaitInFrontOfIntersection = willWaitInFrontOfIntersection; bCrossingVehicles[v] = cvt; } }
/// <summary> /// erstellt eine SpecificPosition mittels NodeConnection und Bogenlängenposition /// </summary> /// <param name="arcPosition">Bogenlängenposition</param> /// <param name="nc">NodeConnection</param> public SpecificPosition(double arcPosition, NodeConnection nc) { this.nc = nc; this.arcPosition = arcPosition; this.time = nc.lineSegment.PosToTime(arcPosition); }
/// <summary> /// Teilt die NodeConnection nc in zwei einzelne NodeConnections auf. /// Dabei wird in der Mitte natürlich auch ein neuer LineNode erstellt /// </summary> /// <param name="nc">aufzuteilende NodeConnection</param> public void SplitNodeConnection(NodeConnection nc) { LineNode startNode = nc.startNode; LineNode endNode = nc.endNode; // Mittelknoten erstellen LineNode middleNode = new LineNode(nc.lineSegment.subdividedFirst.p3, nc.startNode.networkLayer, false); middleNode.inSlopeAbs = nc.lineSegment.subdividedFirst.p2; middleNode.outSlopeAbs = nc.lineSegment.subdividedSecond.p1; nodes.Add(middleNode); // Anfangs- und Endknoten bearbeiten startNode.outSlopeAbs = nc.lineSegment.subdividedFirst.p1; endNode.inSlopeAbs = nc.lineSegment.subdividedSecond.p2; // Alte Connections lösen Disconnect(startNode, endNode); // Neue Connections bauen Connect(startNode, middleNode, nc.priority, nc.targetVelocity, nc.carsAllowed, nc.busAllowed, nc.tramAllowed, nc.enableIncomingLineChange, nc.enableOutgoingLineChange); Connect(middleNode, endNode, nc.priority, nc.targetVelocity, nc.carsAllowed, nc.busAllowed, nc.tramAllowed, nc.enableIncomingLineChange, nc.enableOutgoingLineChange); }
/// <summary> /// Prüfe, ob ich auf der NodeConnection nc fahren darf /// </summary> /// <param name="nc">zu prüfende NodeConnection</param> /// <returns>nc.carsAllowed</returns> public override bool CheckNodeConnectionForSuitability(NodeConnection nc) { return nc.carsAllowed; }
/// <summary> /// Standardkonstruktor /// </summary> /// <param name="nc">NodeConnection</param> /// <param name="i">Intersection, die an nc liegt</param> public SpecificIntersection(NodeConnection nc, Intersection i) { nodeConnection = nc; intersection = i; }