public void GenerateInterconnectPolygon(ArbiterInterconnect ai) { List<Coordinates> polyPoints = new List<Coordinates>(); try { // width double width = 3.0; if (ai.InitialGeneric is ArbiterWaypoint) { ArbiterWaypoint aw = (ArbiterWaypoint)ai.InitialGeneric; width = width < aw.Lane.Width ? aw.Lane.Width : width; } if (ai.FinalGeneric is ArbiterWaypoint) { ArbiterWaypoint aw = (ArbiterWaypoint)ai.FinalGeneric; width = width < aw.Lane.Width ? aw.Lane.Width : width; } if (ai.TurnDirection == ArbiterTurnDirection.UTurn || ai.TurnDirection == ArbiterTurnDirection.Straight || !(ai.InitialGeneric is ArbiterWaypoint) || !(ai.FinalGeneric is ArbiterWaypoint)) { LinePath lp = ai.InterconnectPath.ShiftLateral(width / 2.0); LinePath rp = ai.InterconnectPath.ShiftLateral(-width / 2.0); polyPoints.AddRange(lp); polyPoints.AddRange(rp); ai.TurnPolygon = Polygon.GrahamScan(polyPoints); if (ai.TurnDirection == ArbiterTurnDirection.UTurn) { List<Coordinates> updatedPts = new List<Coordinates>(); LinePath interTmp = ai.InterconnectPath.Clone(); Coordinates pathVec = ai.FinalGeneric.Position - ai.InitialGeneric.Position; interTmp[1] = interTmp[1] + pathVec.Normalize(width / 2.0); interTmp[0] = interTmp[0] - pathVec.Normalize(width / 2.0); lp = interTmp.ShiftLateral(TahoeParams.VL); rp = interTmp.ShiftLateral(-TahoeParams.VL); updatedPts.AddRange(lp); updatedPts.AddRange(rp); ai.TurnPolygon = Polygon.GrahamScan(updatedPts); } } else { // polygon points List<Coordinates> interPoints = new List<Coordinates>(); // waypoint ArbiterWaypoint awI = (ArbiterWaypoint)ai.InitialGeneric; ArbiterWaypoint awF = (ArbiterWaypoint)ai.FinalGeneric; // left and right path LinePath leftPath = new LinePath(); LinePath rightPath = new LinePath(); // some initial points LinePath initialPath = new LinePath(new Coordinates[] { awI.PreviousPartition.Initial.Position, awI.Position }); LinePath il = initialPath.ShiftLateral(width / 2.0); LinePath ir = initialPath.ShiftLateral(-width / 2.0); leftPath.Add(il[1]); rightPath.Add(ir[1]); // some final points LinePath finalPath = new LinePath(new Coordinates[] { awF.Position, awF.NextPartition.Final.Position }); LinePath fl = finalPath.ShiftLateral(width / 2.0); LinePath fr = finalPath.ShiftLateral(-width / 2.0); leftPath.Add(fl[0]); rightPath.Add(fr[0]); // initial and final paths Line iPath = new Line(awI.PreviousPartition.Initial.Position, awI.Position); Line fPath = new Line(awF.Position, awF.NextPartition.Final.Position); // get where the paths intersect and vector to normal path Coordinates c; iPath.Intersect(fPath, out c); Coordinates vector = ai.InterconnectPath.GetClosestPoint(c).Location - c; Coordinates center = c + vector.Normalize((vector.Length / 2.0)); // get width expansion Coordinates iVec = awI.PreviousPartition != null ? awI.PreviousPartition.Vector().Normalize(1.0) : awI.NextPartition.Vector().Normalize(1.0); double iRot = -iVec.ArcTan; Coordinates fVec = awF.NextPartition != null ? awF.NextPartition.Vector().Normalize(1.0) : awF.PreviousPartition.Vector().Normalize(1.0); fVec = fVec.Rotate(iRot); double fDeg = fVec.ToDegrees(); double arcTan = Math.Atan2(fVec.Y, fVec.X) * 180.0 / Math.PI; double centerWidth = width + width * 2.0 * Math.Abs(arcTan) / 90.0; // get inner point (small scale) Coordinates innerPoint = center + vector.Normalize(centerWidth / 4.0); // get outer Coordinates outerPoint = center - vector.Normalize(centerWidth / 2.0); if (ai.TurnDirection == ArbiterTurnDirection.Right) { rightPath.Insert(1, innerPoint); ai.InnerCoordinates = rightPath; leftPath.Reverse(); leftPath.Insert(1, outerPoint); Polygon p = new Polygon(leftPath.ToArray()); p.AddRange(rightPath.ToArray()); ai.TurnPolygon = p; } else { leftPath.Insert(1, innerPoint); ai.InnerCoordinates = leftPath; rightPath.Reverse(); rightPath.Insert(1, outerPoint); Polygon p = new Polygon(leftPath.ToArray()); p.AddRange(rightPath.ToArray()); ai.TurnPolygon = p; } } } catch (Exception e) { Console.WriteLine("error generating turn polygon: " + ai.ToString()); ai.TurnPolygon = ai.DefaultPoly(); } }
/// <summary> /// Check for all waypoints who have exit interconnects that overlaps input and no stop /// </summary> /// <param name="exits"></param> /// <param name="ai"></param> /// <returns></returns> private List<IntersectionInvolved> nonStopOverlaps(IEnumerable<ITraversableWaypoint> exits, ArbiterInterconnect ai) { // list of exits that have an interconnect which overlaps the interconnect input List<IntersectionInvolved> nonStopOverlapWaypoints = new List<IntersectionInvolved>(); // get line of the interconnect Line aiLine = new Line(ai.InitialGeneric.Position, ai.FinalGeneric.Position); // loop over all exits foreach (ITraversableWaypoint exit in exits) { // make sure not our exit and the exit is not a stop and if exit and other are both waypoints then ways not the same if (!exit.Equals(ai.InitialGeneric) && !exit.IsStop && ((!(ai.InitialGeneric is ArbiterWaypoint) || !(exit is ArbiterWaypoint)) || !((ArbiterWaypoint)ai.InitialGeneric).Lane.Way.Equals(((ArbiterWaypoint)exit).Lane.Way))) { // get all interconnects of the exit foreach (ArbiterInterconnect tmp in exit.Exits) { // check relative priority that these are equal or lesser priority if (ai.ComparePriority(tmp) != -1) { // simple check if the interconnect's final is same as input final if (tmp.FinalGeneric.Equals(ai.FinalGeneric)) { // check not already added if (!nonStopOverlapWaypoints.Contains(new IntersectionInvolved(((ITraversableWaypoint)tmp.FinalGeneric).VehicleArea))) { // add exit nonStopOverlapWaypoints.Add(new IntersectionInvolved(exit, exit.VehicleArea, tmp.TurnDirection)); } } // otherwise check overlap of interconnects else { // get line of tmp interconnect Line tmpLine = new Line(tmp.InitialGeneric.Position, tmp.FinalGeneric.Position); // position of cross Coordinates intersectionPoint; // check intersection bool intersects = aiLine.Intersect(tmpLine, out intersectionPoint) && ai.IsInside(intersectionPoint); if (intersects) { // check not already added if (!nonStopOverlapWaypoints.Contains(new IntersectionInvolved(((ITraversableWaypoint)tmp.FinalGeneric).VehicleArea))) { // add exit nonStopOverlapWaypoints.Add(new IntersectionInvolved(exit, exit.VehicleArea, tmp.TurnDirection)); } } } } } } } return nonStopOverlapWaypoints; }
protected void GetIntersectionPullPath(LinePath startingPath, LinePath endingPath, Polygon intersectionPolygon, bool addStartingPoint, bool addEndingPoint, LinePath targetPath, ref double pullWeight) { double angle = Math.Acos(startingPath.EndSegment.UnitVector.Dot(endingPath.GetSegment(0).UnitVector)); // get the centroid of the intersection Coordinates centroid; // check if the angle is great than an threshold if (angle > 10*Math.PI/180.0) { // intersect the two lines formed by the starting and ending lanes Line startingLaneLine = new Line(startingPath[startingPath.Count-2], startingPath[startingPath.Count-1]); Line endingLaneLine = new Line(endingPath[1], endingPath[0]); // intersect them stuff and see if the point of intersection is between the two lines Coordinates K; if (!startingLaneLine.Intersect(endingLaneLine, out centroid, out K) || K.X <= 0 || K.Y <= 0) return; } else { // if there is no intersection polygon, there isn't much we can do if (intersectionPolygon == null || intersectionPolygon.Count < 3) { return; } centroid = intersectionPolygon.GetCentroid(); } // calculate the pull weighting dependent on angle of intersection // angle 0 -> 0 weighting // angle 45 -> 0.00025 weighting // angle 90 -> 0.001 weighting pullWeight = Math.Pow(angle/(Math.PI/2), 2)*0.001; // get the relative transform from the behavior timestamp to the current timestamp RelativeTransform transform = Services.RelativePose.GetTransform(behaviorTimestamp, curTimestamp); centroid = transform.TransformPoint(centroid); if (addStartingPoint) { targetPath.Add(startingPath.EndPoint.Location); } // add the line from exit -> centroid (assuming that exit is already in the target path) targetPath.Add(centroid); if (addEndingPoint) { // add the line from centroid -> entrance targetPath.Add(endingPath[0]); } Services.UIService.PushLineList(targetPath, curTimestamp, "intersection path", true); Services.Dataset.ItemAs<double>("intersection weight").Add(pullWeight, curTimestamp); }