Ejemplo n.º 1
0
        public static VisibilityPolygon[] ComputeWaypointVisibilityPolygons(this PolyNode landNode)
        {
            if (landNode.visibilityGraphNodeData.AggregateContourWaypointVisibilityPolygons != null)
            {
                return(landNode.visibilityGraphNodeData.AggregateContourWaypointVisibilityPolygons);
            }

            var waypoints          = FindAggregateContourCrossoverWaypoints(landNode);
            var barriers           = FindContourAndChildHoleBarriers(landNode);
            var visibilityPolygons = waypoints.Map(waypoint => {
                var visibilityPolygon = VisibilityPolygon.Create(waypoint.ToDoubleVector2(), barriers);
//            for (var edgeDescriptionIndex = 0; edgeDescriptionIndex < landNode.visibilityGraphNodeData.SectorSnapshot.SourceSegmentEdgeDescriptions.Count; edgeDescriptionIndex++) {
//               var erodedCrossoverSegmentBox = landNode.visibilityGraphNodeData.SectorSnapshotGeometryContext.ErodedBoundaryCrossoverSegments[edgeDescriptionIndex];
//               if (!erodedCrossoverSegmentBox.HasValue) {
//                  continue;
//               }
//               if (waypoint == erodedCrossoverSegmentBox.Value.First || waypoint == erodedCrossoverSegmentBox.Value.Second) {
//                  continue;
//               }
//               visibilityPolygon.ClearBeyond(landNode.visibilityGraphNodeData.SectorSnapshot.SourceSegmentEdgeDescriptions[edgeDescriptionIndex].SourceSegment);
//            }
                return(visibilityPolygon);
            });

            return(landNode.visibilityGraphNodeData.AggregateContourWaypointVisibilityPolygons = visibilityPolygons);
        }
Ejemplo n.º 2
0
        public static void DrawCrossSectorVisibilityPolygon(
            this IDebugCanvas canvas,
            TerrainOverlayNetworkNode terrainNode,
            IntVector2 visibilityPolygonOrigin,
            FillStyle fillStyle = null
            )
        {
            fillStyle = fillStyle ?? kDefaultFillStyle;

            canvas.Transform = terrainNode.SectorNodeDescription.WorldTransform;

//         canvas.DrawPoint(visibilityPolygonOrigin, StrokeStyle.RedThick25Solid);
            var visibilityPolygon = VisibilityPolygon.Create(visibilityPolygonOrigin.ToDoubleVector2(), terrainNode.LandPolyNode.FindContourAndChildHoleBarriers());
            var visibleCrossoverSegmentsByNeighbor = FindVisibleCrossoverSegmentsByNeighborAndClearLocalAt(canvas, terrainNode, visibilityPolygon, visibilityPolygonOrigin);

            canvas.DrawVisibilityPolygon(visibilityPolygon, fillStyle: fillStyle ?? kDefaultFillStyle, angleBoundaryStrokeStyle: StrokeStyle.None, visibleWallStrokeStyle: StrokeStyle.None);

            var visibilityPolygonOriginWorld = Vector3.Transform(new Vector3(visibilityPolygonOrigin.ToDotNetVector(), 0), terrainNode.SectorNodeDescription.WorldTransform);

            foreach (var(neighbor, inboundCrossoverSegments) in visibleCrossoverSegmentsByNeighbor)
            {
                var neighborPolygonOrigin = Vector3.Transform(visibilityPolygonOriginWorld, neighbor.SectorNodeDescription.WorldTransformInv);
                Z(canvas, new IntVector2((int)neighborPolygonOrigin.X, (int)neighborPolygonOrigin.Y), neighbor, inboundCrossoverSegments, new HashSet <TerrainOverlayNetworkNode> {
                    terrainNode
                }, fillStyle);
            }
        }
Ejemplo n.º 3
0
        public static VisibilityPolygon GetIntersectionArea(Polygon firstPolygon, Polygon secondPolygon)
        {
            // Prepare the second (main) polygon to be merged
            List <CyclicalList <IntPoint> > subj = new List <CyclicalList <IntPoint> >();

            if (secondPolygon.GetVerticesCount() > 0)
            {
                subj.Add(new CyclicalList <IntPoint>());
                for (int i = 0; i < secondPolygon.GetVerticesCount(); i++)
                {
                    subj[subj.Count - 1].Add(new IntPoint(secondPolygon.GetPoint(i).x, secondPolygon.GetPoint(i).y));
                }
            }


            // The current seen area so it will be merged with the previous area
            List <CyclicalList <IntPoint> > clip = new List <CyclicalList <IntPoint> >();

            if (firstPolygon.GetVerticesCount() > 0)
            {
                clip.Add(new CyclicalList <IntPoint>());
                for (int i = 0; i < firstPolygon.GetVerticesCount(); i++)
                {
                    clip[clip.Count - 1].Add(new IntPoint(firstPolygon.GetPoint(i).x, firstPolygon.GetPoint(i).y));
                }
            }


            // Merge the two polygons
            List <CyclicalList <IntPoint> > solution = new List <CyclicalList <IntPoint> >();

            Clipper c = new Clipper();

            c.AddPaths(clip, PolyType.ptClip, true);
            c.AddPaths(subj, PolyType.ptSubject, true);
            c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);


            // Result merged polygon
            VisibilityPolygon mergedPolygon = new VisibilityPolygon();

            // Fill the result
            if (solution.Count > 0)
            {
                foreach (CyclicalList <IntPoint> polygon in solution)
                {
                    for (int i = 0; i < polygon.Count; i++)
                    {
                        mergedPolygon.AddPoint(new Vector2(polygon[i].X, polygon[i].Y));
                    }
                }
            }

            return(mergedPolygon);
        }
Ejemplo n.º 4
0
        private static void Z(this IDebugCanvas canvas, IntVector2 visibilityPolygonOrigin, TerrainOverlayNetworkNode terrainNode, IReadOnlyCollection <IntLineSegment2> inboundCrossoverSegments, HashSet <TerrainOverlayNetworkNode> visited, FillStyle fillStyle)
        {
            canvas.Transform = terrainNode.SectorNodeDescription.WorldTransform;

//         canvas.DrawPoint(visibilityPolygonOrigin, StrokeStyle.RedThick25Solid);
            var visibilityPolygon = new VisibilityPolygon(
                visibilityPolygonOrigin.ToDoubleVector2(),
                new[] {
                new VisibilityPolygon.IntervalRange {
                    Id         = VisibilityPolygon.RANGE_ID_INFINITESIMALLY_NEAR,
                    ThetaStart = 0,
                    ThetaEnd   = VisibilityPolygon.TwoPi
                },
            });

            foreach (var inboundCrossoverSegment in inboundCrossoverSegments)
            {
                visibilityPolygon.ClearBefore(inboundCrossoverSegment);
            }

//         Console.WriteLine("====");

            foreach (var seg in terrainNode.LandPolyNode.FindContourAndChildHoleBarriers())
            {
                if (GeometryOperations.Clockness(visibilityPolygon.Origin, seg.First.ToDoubleVector2(), seg.Second.ToDoubleVector2()) == Clockness.CounterClockwise)
                {
                    continue;
                }
                visibilityPolygon.Insert(seg);
//            Console.WriteLine(seg);
            }
//         Console.WriteLine("====");

            var visibleCrossoverSegmentsByNeighbor = FindVisibleCrossoverSegmentsByNeighborAndClearLocalAt(canvas, terrainNode, visibilityPolygon, visibilityPolygonOrigin, visited);

            canvas.DrawVisibilityPolygon(visibilityPolygon, fillStyle: fillStyle ?? kDefaultFillStyle, angleBoundaryStrokeStyle: StrokeStyle.None, visibleWallStrokeStyle: StrokeStyle.None);


            var visibilityPolygonOriginWorld = Vector3.Transform(new Vector3(visibilityPolygonOrigin.ToDotNetVector(), 0), terrainNode.SectorNodeDescription.WorldTransform);

            foreach (var(neighbor, nextInboundCrossoverSegments) in visibleCrossoverSegmentsByNeighbor)
            {
                var neighborPolygonOrigin = Vector3.Transform(visibilityPolygonOriginWorld, neighbor.SectorNodeDescription.WorldTransformInv);
                //visibilityPolygonOrigin
                Z(canvas, new IntVector2((int)neighborPolygonOrigin.X, (int)neighborPolygonOrigin.Y), neighbor, nextInboundCrossoverSegments,
                  visited.Concat(new[] { terrainNode }).ToHashSet(), fillStyle);
            }
        }
Ejemplo n.º 5
0
        private static void Benchmark()
        {
            var inputs = Util.Generate(5, RandomInput);

            while (true)
            {
                var sw = new Stopwatch();
                sw.Start();
                const int niters = 1000;
                for (var i = 0; i < niters; i++)
                {
                    var(p, segments) = inputs[i % inputs.Length];
                    VisibilityPolygon.Create(p, segments);
                }
                Console.WriteLine(sw.Elapsed.TotalMilliseconds / niters);
            }
        }
Ejemplo n.º 6
0
        private static void RenderVisualizationFrame(DoubleVector2 p, IntLineSegment2[] segments, int eventLimit = -1)
        {
            var canvas = host.CreateAndAddCanvas(frameCounter++);
            var vp     = VisibilityPolygon.Create(p, segments, eventLimit);

            vp = new VisibilityPolygon(p);
            foreach (var seg in segments)
            {
                vp.Insert(seg);
            }
//         vp.Insert(new IntLineSegment2(p.LossyToIntVector2() + new IntVector2(50, -20), p.LossyToIntVector2() + new IntVector2(50, 20)));

            canvas.BatchDraw(() => {
                canvas.DrawVisibilityPolygon(vp, 0, new FillStyle(Color.FromArgb(120, Color.Cyan)));
                foreach (var s in segments)
                {
                    canvas.DrawLine(s.First, s.Second, StrokeStyle.BlackHairLineSolid);
                }
                canvas.DrawPoint(p, StrokeStyle.RedThick5Solid);
            });
        }
Ejemplo n.º 7
0
        public static void DrawVisibilityPolygon(this IDebugCanvas debugCanvas, VisibilityPolygon avss, double z = 0.0, FillStyle fillStyle = null, StrokeStyle angleBoundaryStrokeStyle = null, StrokeStyle visibleWallStrokeStyle = null)
        {
            fillStyle = fillStyle ?? DefaultFillStyle;
            var oxy = avss.Origin;

            foreach (var range in avss.Get().Where(range => range.Id != VisibilityPolygon.RANGE_ID_INFINITELY_FAR && range.Id != VisibilityPolygon.RANGE_ID_INFINITESIMALLY_NEAR))
            {
                var rstart = DoubleVector2.FromRadiusAngle(100, range.ThetaStart);
                var rend   = DoubleVector2.FromRadiusAngle(100, range.ThetaEnd);

                var           s = range.Segment;
                var           s1 = s.First.ToDoubleVector2();
                var           s2 = s.Second.ToDoubleVector2();
                DoubleVector2 visibleStart, visibleEnd;
                if (!GeometryOperations.TryFindLineLineIntersection(oxy, oxy + rstart, s1, s2, out visibleStart) ||
                    !GeometryOperations.TryFindLineLineIntersection(oxy, oxy + rend, s1, s2, out visibleEnd))
                {
                    continue;
                }

                debugCanvas.FillTriangle(oxy, visibleStart, visibleEnd, fillStyle);

                debugCanvas.DrawLine(
                    new DoubleVector3(oxy.X, oxy.Y, z),
                    new DoubleVector3(visibleStart.X, visibleStart.Y, z),
                    angleBoundaryStrokeStyle ?? DefaultAngleBoundaryStrokeStyle);

                debugCanvas.DrawLine(
                    new DoubleVector3(oxy.X, oxy.Y, z),
                    new DoubleVector3(visibleEnd.X, visibleEnd.Y, z),
                    angleBoundaryStrokeStyle ?? DefaultAngleBoundaryStrokeStyle);

                debugCanvas.DrawLine(
                    new DoubleVector3(visibleStart.X, visibleStart.Y, z),
                    new DoubleVector3(visibleEnd.X, visibleEnd.Y, z),
                    visibleWallStrokeStyle ?? DefaultVisibleWallStrokeStyle);
            }
        }
Ejemplo n.º 8
0
        private static MultiValueDictionary <TerrainOverlayNetworkNode, IntLineSegment2> FindVisibleCrossoverSegmentsByNeighborAndClearLocalAt(
            IDebugCanvas canvas,
            TerrainOverlayNetworkNode terrainNode,
            VisibilityPolygon visibilityPolygon,
            IntVector2 visibilityPolygonOrigin,
            HashSet <TerrainOverlayNetworkNode> visited = null)
        {
            var visibleCrossoverSegmentsByNeighbor = MultiValueDictionary <TerrainOverlayNetworkNode, IntLineSegment2> .Create(() => new HashSet <IntLineSegment2>());

            foreach (var outboundEdgeGroup in terrainNode.OutboundEdgeGroups)
            {
                var otherTerrainNode = outboundEdgeGroup.Key;
                if (visited?.Contains(otherTerrainNode) ?? false)
                {
                    continue;
                }

                foreach (var outboundEdge in outboundEdgeGroup.Value)
                {
                    var ranges = visibilityPolygon.Get();

                    (IntLineSegment2, bool) FlipMaybeSorta(IntLineSegment2 x) =>
                    GeometryOperations.Clockness(visibilityPolygonOrigin, x.First, x.Second) == Clockness.CounterClockwise
                     ? (new IntLineSegment2(x.Second, x.First), true)
                     : (x, false);

                    var(localCrossoverSegment, lcsFlipped)  = FlipMaybeSorta(outboundEdge.EdgeJob.EdgeDescription.SourceSegment);
                    var(remoteCrossoverSegment, rcsFlipped) = FlipMaybeSorta(outboundEdge.EdgeJob.EdgeDescription.DestinationSegment);

                    // todo: clamp visibleStartT, visibleEndT to account for agent radius eroding crossover segmetmentnt
                    var rangeIndexIntervals    = visibilityPolygon.RangeStab(localCrossoverSegment);
                    var locallyClearedSegments = new List <IntLineSegment2>();
                    foreach (var(startIndexInclusive, endIndexInclusive) in rangeIndexIntervals)
                    {
                        for (var i = startIndexInclusive; i <= endIndexInclusive; i++)
                        {
                            if (ranges[i].Id == VisibilityPolygon.RANGE_ID_INFINITELY_FAR || ranges[i].Id == VisibilityPolygon.RANGE_ID_INFINITESIMALLY_NEAR)
                            {
                                continue;
                            }

                            var seg = ranges[i].Segment;

                            var rstart = DoubleVector2.FromRadiusAngle(100, ranges[i].ThetaStart) * 100;
                            var rend   = DoubleVector2.FromRadiusAngle(100, ranges[i].ThetaEnd) * 100;

                            double visibleStartT, visibleEndT;
                            if (!GeometryOperations.TryFindNonoverlappingLineLineIntersectionT(localCrossoverSegment.First.ToDoubleVector2(), localCrossoverSegment.Second.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2() + rstart, out visibleStartT) ||
                                !GeometryOperations.TryFindNonoverlappingLineLineIntersectionT(localCrossoverSegment.First.ToDoubleVector2(), localCrossoverSegment.Second.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2(), visibilityPolygonOrigin.ToDoubleVector2() + rend, out visibleEndT))
                            {
                                // wtf?
                                Console.WriteLine("???");
                                continue;
                            }

                            // Todo: I don't actually understand why visibleEndT > 1 is a thing?
                            // t values are for parameterization of crossover line segment, so must be within [0, 1]
                            if ((visibleStartT < 0 && visibleEndT < 0) || (visibleStartT > 1 && visibleEndT > 1))
                            {
                                continue;
                            }
                            visibleStartT = Math.Min(1.0, Math.Max(0.0, visibleStartT));
                            visibleEndT   = Math.Min(1.0, Math.Max(0.0, visibleEndT));

                            if (visibilityPolygon.SegmentComparer.Compare(localCrossoverSegment, seg) < 0)
                            {
                                var localVisibleStart = localCrossoverSegment.PointAt(visibleStartT).LossyToIntVector2();
                                var localVisibleEnd   = localCrossoverSegment.PointAt(visibleEndT).LossyToIntVector2();

                                var remoteVisibleStart = remoteCrossoverSegment.PointAt(lcsFlipped == rcsFlipped ? visibleStartT : 1.0 - visibleStartT).LossyToIntVector2();
                                var remoteVisibleEnd   = remoteCrossoverSegment.PointAt(lcsFlipped == rcsFlipped ? visibleEndT : 1.0 - visibleEndT).LossyToIntVector2();

                                if (localVisibleStart == localVisibleEnd)
                                {
                                    continue;
                                }
                                if (remoteVisibleStart == remoteVisibleEnd)
                                {
                                    continue;
                                }

                                var locallyClearedSegment = new IntLineSegment2(localVisibleStart, localVisibleEnd);
                                locallyClearedSegments.Add(locallyClearedSegment);

                                visibleCrossoverSegmentsByNeighbor.Add(otherTerrainNode, new IntLineSegment2(remoteVisibleStart, remoteVisibleEnd));
                            }
                        }
                    }
                    foreach (var locallyClearedSegment in locallyClearedSegments)
                    {
                        visibilityPolygon.ClearBefore(locallyClearedSegment);
                    }
                }
            }
            return(visibleCrossoverSegmentsByNeighbor);
        }