예제 #1
0
        FindOptimalLinksToCrossovers(
            IntVector2 p,
            int[] candidateWaypoints = null,
            IReadOnlyDictionary <DoubleLineSegment2, IntLineSegment2[]> candidateBarriersByDestinationSegment = null
            )
        {
            Interlocked.Increment(ref FindOptimalLinksToCrossoversInvocationCount);
            //var links = new List<PathLink>(128);
            //links.Resize(crossoverPoints.Count);
            //return (new PathLink[0], 0, new PathLink[waypoints.Length], links);

            int visibleWaypointLinksLength;

            PathLink[] optimalLinkToWaypoints;
            var        visibleWaypointLinks = FindVisibleWaypointLinks(p, candidateWaypoints, out visibleWaypointLinksLength, out optimalLinkToWaypoints);

            // Cost from p to other crossoverPoints...
            var optimalLinkToCrossovers = new ExposedArrayList <PathLink>(Math.Max(128, crossoverPoints.Count));

            optimalLinkToCrossovers.size = crossoverPoints.Count;

            void ProcessCpi(int cpi, IntLineSegment2[] candidateBarriers)
            {
                // for bench
                optimalLinkToCrossovers[cpi] = new PathLink {
                    PriorIndex = PathLink.ErrorInvalidIndex,
                    TotalCost  = float.PositiveInfinity
                };
                return;

                Interlocked.Increment(ref ProcessCpiInvocationCount);
                bool isDirectPath;

                if (p == crossoverPoints[cpi])
                {
                    isDirectPath = true; // degenerate segment
                }
                else if (candidateBarriers == null)
                {
                    //               Console.WriteLine($"Try intersect {cpi}: {p} to {crossoverPoints[cpi]}");
                    var isDirectPath1 = !landPolyNode.FindContourAndChildHoleBarriersBvh().Intersects(new IntLineSegment2(p, crossoverPoints[cpi]));
                    //               var isDirectPath2 = landPolyNode.SegmentInLandPolygonNonrecursive(p, crossoverPoints[cpi]);
                    //               Console.WriteLine($" => res {isDirectPath1} vs {isDirectPath2}");
                    isDirectPath = isDirectPath1;
                }
                else
                {
                    // below is equivalent to (and shaved off 22% execution time relative to):
                    // isDirectPath = candidateBarriers.None(new ILS2(p, crossoverPoints[cpi]).Intersects)
                    isDirectPath = true;
                    //var seg = new IntLineSegment2(p, crossoverPoints[cpi]);
                    for (var bi = 0; bi < candidateBarriers.Length && isDirectPath; bi++)
                    {
                        Interlocked.Increment(ref ProcessCpiInvocation_CandidateBarrierIntersectCount);

                        if (IntLineSegment2.Intersects(
                                p.X, p.Y, crossoverPoints[cpi].X, crossoverPoints[cpi].Y,
                                candidateBarriers[bi].X1, candidateBarriers[bi].Y1, candidateBarriers[bi].X2, candidateBarriers[bi].Y2))
                        {
                            isDirectPath = false;
                        }
                        //if (seg.Intersects(ref candidateBarriers[bi])) isDirectPath = false;
                    }
                }

                if (isDirectPath)
                {
                    Interlocked.Increment(ref ProcessCpiInvocation_DirectCount);
                    var totalCost = p.To(crossoverPoints[cpi]).Norm2F();
                    Trace.Assert(!float.IsNaN(totalCost));
                    optimalLinkToCrossovers[cpi] = new PathLink {
                        PriorIndex = PathLink.DirectPathIndex,
                        TotalCost  = totalCost
                    };
                }
                else
                {
                    Interlocked.Increment(ref ProcessCpiInvocation_IndirectCount);
                    var otherOptimalLinkByWaypointIndex = optimalLinkToWaypointsByCrossoverPointIndex[cpi];

                    //--
                    // Below is equivalent to (and shaved off 14% execution time relative to):
                    // visibleWaypointLinks.MinBy(cpwl => cpwl.TotalCost + otherOptimalLinkByWaypointIndex[cpwl.PriorIndex].TotalCost);
                    var optimalLinkToOtherCrossoverPointIndex = -1;
                    var optimalLinkToOtherCrossoverPointCost  = float.PositiveInfinity;
                    for (var vwli = 0; vwli < visibleWaypointLinksLength; vwli++)
                    {
                        ref var vwl  = ref visibleWaypointLinks[vwli];
                        var     cost = vwl.TotalCost + otherOptimalLinkByWaypointIndex[vwl.PriorIndex].TotalCost;
                        if (cost < optimalLinkToOtherCrossoverPointCost)
                        {
                            optimalLinkToOtherCrossoverPointIndex = vwli;
                            optimalLinkToOtherCrossoverPointCost  = cost;
                        }
                    }

                    if (optimalLinkToOtherCrossoverPointIndex == -1)
                    {
                        // Todo: This shouldn't happen!
                        optimalLinkToCrossovers[cpi] = new PathLink {
                            PriorIndex = PathLink.ErrorInvalidIndex,
                            TotalCost  = float.PositiveInfinity
                        };
                    }
                    else
                    {
                        ref var optimalLinkToOtherCrossoverPoint = ref visibleWaypointLinks[optimalLinkToOtherCrossoverPointIndex];

                        //--
                        var optimalLinkFromOtherCrossoverPoint = otherOptimalLinkByWaypointIndex[optimalLinkToOtherCrossoverPoint.PriorIndex];
                        var totalCost = optimalLinkToOtherCrossoverPoint.TotalCost + optimalLinkFromOtherCrossoverPoint.TotalCost;
                        Trace.Assert(!float.IsNaN(totalCost));
                        optimalLinkToCrossovers[cpi] = new PathLink {
                            PriorIndex = optimalLinkToOtherCrossoverPoint.PriorIndex,
                            TotalCost  = totalCost
                        };
                    }
                }