Ejemplo n.º 1
0
        /// <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);
                    }
                }
        }
Ejemplo n.º 2
0
        /// <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;
                }
        }