コード例 #1
0
        static internal Point SegmentIntersection(Point first, Point second, Point from)
        {
            Directions dir       = PointComparer.GetPureDirection(first, second);
            Point      intersect = IsVertical(dir) ? new Point(first.X, from.Y) : new Point(from.X, first.Y);

            return(intersect);
        }
コード例 #2
0
 internal static bool FindBracketingVertices(VisibilityVertex sourceVertex, Point targetPoint, Directions dirToTarget
                                             , out VisibilityVertex bracketSource, out VisibilityVertex bracketTarget)
 {
     // Walk from the source to target until we bracket target or there is no nextVertex
     // in the desired direction.
     bracketSource = sourceVertex;
     for (; ;)
     {
         bracketTarget = StaticGraphUtility.FindNextVertex(bracketSource, dirToTarget);
         if (null == bracketTarget)
         {
             break;
         }
         if (PointComparer.Equal(bracketTarget.Point, targetPoint))
         {
             // Desired edge already exists.
             return(true);
         }
         if (dirToTarget != PointComparer.GetPureDirection(bracketTarget.Point, targetPoint))
         {
             // bracketTarget is past vertex in the traversal direction.
             break;
         }
         bracketSource = bracketTarget;
     }
     return(null != bracketTarget);
 }
コード例 #3
0
        private static VisibilityVertex GetSpliceTarget(ref VisibilityVertex spliceSource, Directions spliceTargetDir, Point nextExtendPoint)
        {
            // Look for the target.  There may be a dead-ended edge starting at the current spliceSource
            // edge that has a vertex closer to the extension line; in that case keep walking until we
            // have the closest vertex on the Source side of the extension line as spliceSource.
            Directions prevDir      = PointComparer.GetPureDirection(spliceSource.Point, nextExtendPoint);
            Directions nextDir      = prevDir;
            var        spliceTarget = spliceSource;

            while (nextDir == prevDir)
            {
                spliceSource = spliceTarget;
                spliceTarget = StaticGraphUtility.FindNextVertex(spliceSource, spliceTargetDir);
                if (null == spliceTarget)
                {
                    break;
                }
                if (PointComparer.Equal(spliceTarget.Point, nextExtendPoint))
                {
                    // If we encountered an existing vertex for the extension chain, update spliceTarget
                    // to be after it and we're done with this loop.
                    spliceTarget = StaticGraphUtility.FindNextVertex(spliceTarget, spliceTargetDir);
                    break;
                }
                nextDir = PointComparer.GetPureDirection(spliceTarget.Point, nextExtendPoint);
            }
            return(spliceTarget);
        }
コード例 #4
0
        void DevTrace_VerifyVertex(VisibilityVertex vertex)
        {
            if (transGraphVerify.IsLevel(1))
            {
                Directions dir = Directions.North;
                for (int idir = 0; idir < 4; ++idir, dir = CompassVector.RotateRight(dir))
                {
                    int count  = 0;
                    int cEdges = vertex.InEdges.Count;      // indexing is faster than foreach for Lists
                    for (int ii = 0; ii < cEdges; ++ii)
                    {
                        var edge = vertex.InEdges[ii];
                        if (PointComparer.GetPureDirection(vertex.Point, edge.SourcePoint) == dir)
                        {
                            ++count;
                        }
                    }

                    // Avoid GetEnumerator overhead.
                    var outEdgeNode = vertex.OutEdges.IsEmpty() ? null : vertex.OutEdges.TreeMinimum();
                    for (; outEdgeNode != null; outEdgeNode = vertex.OutEdges.Next(outEdgeNode))
                    {
                        var edge = outEdgeNode.Item;
                        if (PointComparer.GetPureDirection(vertex.Point, edge.TargetPoint) == dir)
                        {
                            ++count;
                        }
                    }
                    Debug.Assert(count < 2, "vertex has multiple edges in one direction");
                }
            }
        }
コード例 #5
0
        static internal VisibilityVertex FindNextVertex(VisibilityVertex vertex, Directions dir)
        {
            // This function finds the next vertex in the desired direction relative to the
            // current vertex, not necessarily the edge orientation, hence it does not use
            // EdgeDirection().  This is so the caller can operate on a desired movement
            // direction without having to track whether we're going forward or backward
            // through the In/OutEdge chain.
            int cEdges = vertex.InEdges.Count;      // indexing is faster than foreach for Lists

            for (int ii = 0; ii < cEdges; ++ii)
            {
                var edge = vertex.InEdges[ii];
                if (PointComparer.GetPureDirection(vertex.Point, edge.SourcePoint) == dir)
                {
                    return(edge.Source);
                }
            }

            // Avoid GetEnumerator overhead.
            var outEdgeNode = vertex.OutEdges.IsEmpty() ? null : vertex.OutEdges.TreeMinimum();

            for (; outEdgeNode != null; outEdgeNode = vertex.OutEdges.Next(outEdgeNode))
            {
                var edge = outEdgeNode.Item;
                if (PointComparer.GetPureDirection(vertex.Point, edge.TargetPoint) == dir)
                {
                    return(edge.Target);
                }
            }
            return(null);
        }
コード例 #6
0
        private void AddGroupIntersectionsToRestrictedRay(Obstacle obstacle, IList <IntersectionInfo> intersections)
        {
            // We'll let the lines punch through any intersections with groups, but track the location so we can enable/disable crossing.
            foreach (var intersectionInfo in intersections)
            {
                var intersect = SpliceUtility.RawIntersection(intersectionInfo, currentRestrictedRay.Start);

                // Skip intersections that are past the end of the restricted segment (though there may still be some
                // there if we shorten it later, but we'll skip them later).
                var distSquared = (intersect - currentRestrictedRay.Start).LengthSquared;
                if (distSquared > restrictedRayLengthSquared)
                {
                    continue;
                }

                var dirTowardIntersect = PointComparer.GetPureDirection(currentRestrictedRay.Start, currentRestrictedRay.End);
                var polyline           = (Polyline)intersectionInfo.Segment1; // this is the second arg to GetAllIntersections
                var dirsOfSide         = CompassVector.VectorDirection(polyline.Derivative(intersectionInfo.Par1));

                // The derivative is always clockwise, so if the side contains the rightward rotation of the
                // direction from the ray origin, then we're hitting it from the inside; otherwise from the outside.
                var dirToInsideOfGroup = dirTowardIntersect;
                if (0 != (dirsOfSide & CompassVector.RotateRight(dirTowardIntersect)))
                {
                    dirToInsideOfGroup = CompassVector.OppositeDir(dirToInsideOfGroup);
                }
                CurrentGroupBoundaryCrossingMap.AddIntersection(intersect, obstacle, dirToInsideOfGroup);
            }
        }
コード例 #7
0
        // ctor

        internal void Update(Point start, Point end)
        {
            Debug.Assert(PointComparer.Equal(start, end) ||
                         StaticGraphUtility.IsAscending(PointComparer.GetPureDirection(start, end))
                         , "non-ascending segment");
            startPoint = start;
            endPoint   = end;
        }
コード例 #8
0
        private void SpliceGroupBoundaryCrossings(PointAndCrossingsList crossingList, VisibilityVertex startVertex, LineSegment maxSegment)
        {
            if ((null == crossingList) || (0 == crossingList.Count))
            {
                return;
            }

            crossingList.Reset();
            var start = maxSegment.Start;
            var end   = maxSegment.End;
            var dir   = PointComparer.GetPureDirection(start, end);

            // Make sure we are going in the ascending direction.
            if (!StaticGraphUtility.IsAscending(dir))
            {
                start = maxSegment.End;
                end   = maxSegment.Start;
                dir   = CompassVector.OppositeDir(dir);
            }

            // We need to back up to handle group crossings that are between a VisibilityBorderIntersect on a sloped border and the
            // incoming startVertex (which is on the first ScanSegment in Perpendicular(dir) that is outside that padded border).
            startVertex = TraverseToFirstVertexAtOrAbove(startVertex, start, CompassVector.OppositeDir(dir));

            // Splice into the Vertices between and including the start/end points.
            for (var currentVertex = startVertex; null != currentVertex; currentVertex = StaticGraphUtility.FindNextVertex(currentVertex, dir))
            {
                bool isFinalVertex = (PointComparer.Compare(currentVertex.Point, end) >= 0);
                while (crossingList.CurrentIsBeforeOrAt(currentVertex.Point))
                {
                    PointAndCrossings pac = crossingList.Pop();

                    // If it's past the start and at or before the end, splice in the crossings in the descending direction.
                    if (PointComparer.Compare(pac.Location, startVertex.Point) > 0)
                    {
                        if (PointComparer.Compare(pac.Location, end) <= 0)
                        {
                            SpliceGroupBoundaryCrossing(currentVertex, pac, CompassVector.OppositeDir(dir));
                        }
                    }

                    // If it's at or past the start and before the end, splice in the crossings in the descending direction.
                    if (PointComparer.Compare(pac.Location, startVertex.Point) >= 0)
                    {
                        if (PointComparer.Compare(pac.Location, end) < 0)
                        {
                            SpliceGroupBoundaryCrossing(currentVertex, pac, dir);
                        }
                    }
                }

                if (isFinalVertex)
                {
                    break;
                }
            }
        }
コード例 #9
0
        private void GetRestrictedIntersectionTestSegment(Point startPoint, Point endPoint)
        {
            // Due to rounding issues use a larger line span for intersection calculations.
            Directions segDir = PointComparer.GetPureDirection(startPoint, endPoint);
            double     startX = (Directions.West == segDir) ? GraphBox.Right : ((Directions.East == segDir) ? GraphBox.Left : startPoint.X);
            double     endX   = (Directions.West == segDir) ? GraphBox.Left : ((Directions.East == segDir) ? GraphBox.Right : endPoint.X);
            double     startY = (Directions.South == segDir) ? GraphBox.Top * 2: ((Directions.North == segDir) ? GraphBox.Bottom : startPoint.Y);
            double     endY   = (Directions.South == segDir) ? GraphBox.Bottom : ((Directions.North == segDir) ? GraphBox.Top : startPoint.Y);

            restrictedIntersectionTestSegment = new LineSegment(new Point(startX, startY), new Point(endX, endY));
        }
コード例 #10
0
        private void ExtendEdgeChain(VisibilityVertex startVertex, Directions extendDir
                                     , LineSegment maxDesiredSegment, LineSegment maxVisibilitySegment
                                     , PointAndCrossingsList pacList, bool isOverlapped)
        {
            StaticGraphUtility.Assert(PointComparer.GetPureDirection(maxDesiredSegment.Start, maxDesiredSegment.End) == extendDir
                                      , "maxDesiredSegment is reversed", ObstacleTree, VisGraph);

            // Direction*s*, because it may return None, which is valid and means startVertex is on the
            // border of an obstacle and we don't want to go inside it.
            Directions segmentDir = PointComparer.GetDirections(startVertex.Point, maxDesiredSegment.End);

            if (segmentDir != extendDir)
            {
                // OppositeDir may happen on overlaps where the boundary has a gap in its ScanSegments due to other obstacles
                // overlapping it and each other.  This works because the port has an edge connected to startVertex,
                // which is on a ScanSegment outside the obstacle.
                StaticGraphUtility.Assert(isOverlapped || (segmentDir != CompassVector.OppositeDir(extendDir))
                                          , "obstacle encountered between prevPoint and startVertex", ObstacleTree, VisGraph);
                return;
            }

            // We'll find the segment to the left (or right if to the left doesn't exist),
            // then splice across in the opposite direction.
            Directions       spliceSourceDir = CompassVector.RotateLeft(extendDir);
            VisibilityVertex spliceSource    = StaticGraphUtility.FindNextVertex(startVertex, spliceSourceDir);

            if (null == spliceSource)
            {
                spliceSourceDir = CompassVector.OppositeDir(spliceSourceDir);
                spliceSource    = StaticGraphUtility.FindNextVertex(startVertex, spliceSourceDir);
                if (null == spliceSource)
                {
                    return;
                }
            }

            // Store this off before ExtendSpliceWorker, which overwrites it.
            Directions       spliceTargetDir = CompassVector.OppositeDir(spliceSourceDir);
            VisibilityVertex spliceTarget;

            if (ExtendSpliceWorker(spliceSource, extendDir, spliceTargetDir, maxDesiredSegment, maxVisibilitySegment, isOverlapped, out spliceTarget))
            {
                // We ended on the source side and may have dead-ends on the target side so reverse sides.
                ExtendSpliceWorker(spliceTarget, extendDir, spliceSourceDir, maxDesiredSegment, maxVisibilitySegment, isOverlapped, out spliceTarget);
            }

            SpliceGroupBoundaryCrossings(pacList, startVertex, maxDesiredSegment);
        }
コード例 #11
0
        internal VisibilityEdge FindOrAddEdge(VisibilityVertex sourceVertex, VisibilityVertex targetVertex, double weight)
        {
            // Since we're adding transient edges into the graph, we're not doing full intersection
            // evaluation; thus there may already be an edge from the source vertex in the direction
            // of the target vertex, but ending before or after the target vertex.
            Directions       dirToTarget = PointComparer.GetPureDirection(sourceVertex, targetVertex);
            VisibilityVertex bracketSource, bracketTarget;

            // Is there an edge in the chain from sourceVertex in the direction of targetVertex
            // that brackets targetvertex?
            //      <sourceVertex> -> ..1.. -> ..2.. <end>   3
            // Yes if targetVertex is at the x above 1 or 2, No if it is at 3.  If false, bracketSource
            // will be set to the vertex at <end> (if there are any edges in that direction at all).
            VisibilityVertex splitVertex = targetVertex;

            if (!FindBracketingVertices(sourceVertex, targetVertex.Point, dirToTarget
                                        , out bracketSource, out bracketTarget))
            {
                // No bracketing of targetVertex from sourceVertex but bracketSource has been updated.
                // Is there a bracket of bracketSource from the targetVertex direction?
                //                      3   <end> ..2.. <- ..1..   <targetVertex>
                // Yes if bracketSource is at the x above 1 or 2, No if it is at 3.  If false, bracketTarget
                // will be set to the vertex at <end> (if there are any edges in that direction at all).
                // If true, then bracketSource and splitVertex must be updated.
                VisibilityVertex tempSource;
                if (FindBracketingVertices(targetVertex, sourceVertex.Point, CompassVector.OppositeDir(dirToTarget)
                                           , out bracketTarget, out tempSource))
                {
                    Debug.Assert(bracketSource == sourceVertex, "Mismatched bracketing detection");
                    bracketSource = tempSource;
                    splitVertex   = sourceVertex;
                }
            }

            // If null != edge then targetVertex is between bracketSource and bracketTarget and SplitEdge returns the
            // first half-edge (and weight is ignored as the split uses the edge weight).
            var edge = VisGraph.FindEdge(bracketSource.Point, bracketTarget.Point);

            edge = (null != edge)
                    ? this.SplitEdge(edge, splitVertex)
                    : CreateEdge(bracketSource, bracketTarget, weight);
            DevTrace_VerifyEdge(edge);
            return(edge);
        }
コード例 #12
0
        internal void ExtendEdgeChain(VisibilityVertex startVertex, Rectangle limitRect, LineSegment maxVisibilitySegment,
                                      PointAndCrossingsList pacList, bool isOverlapped)
        {
            var dir = PointComparer.GetDirections(maxVisibilitySegment.Start, maxVisibilitySegment.End);

            if (dir == Directions.None)
            {
                return;
            }

            Debug.Assert(CompassVector.IsPureDirection(dir), "impure max visibility segment");

            // Shoot the edge chain out to the shorter of max visibility or intersection with the limitrect.
            StaticGraphUtility.Assert(PointComparer.Equal(maxVisibilitySegment.Start, startVertex.Point) ||
                                      (PointComparer.GetPureDirection(maxVisibilitySegment.Start, startVertex.Point) == dir)
                                      , "Inconsistent direction found", ObstacleTree, VisGraph);
            double oppositeFarBound      = StaticGraphUtility.GetRectangleBound(limitRect, dir);
            Point  maxDesiredSplicePoint = StaticGraphUtility.IsVertical(dir)
                                    ? ApproximateComparer.Round(new Point(startVertex.Point.X, oppositeFarBound))
                                    : ApproximateComparer.Round(new Point(oppositeFarBound, startVertex.Point.Y));

            if (PointComparer.Equal(maxDesiredSplicePoint, startVertex.Point))
            {
                // Nothing to do.
                return;
            }
            if (PointComparer.GetPureDirection(startVertex.Point, maxDesiredSplicePoint) != dir)
            {
                // It's in the opposite direction, so no need to do anything.
                return;
            }

            // If maxDesiredSplicePoint is shorter, create a new shorter segment.  We have to pass both segments
            // through to the worker function so it knows whether it can go past maxDesiredSegment (which may be limited
            // by limitRect).
            var maxDesiredSegment = maxVisibilitySegment;

            if (PointComparer.GetDirections(maxDesiredSplicePoint, maxDesiredSegment.End) == dir)
            {
                maxDesiredSegment = new LineSegment(maxDesiredSegment.Start, maxDesiredSplicePoint);
            }

            ExtendEdgeChain(startVertex, dir, maxDesiredSegment, maxVisibilitySegment, pacList, isOverlapped);
        }
コード例 #13
0
        static internal VisibilityEdge FindAdjacentEdge(VisibilityVertex a, Direction dir)
        {
            foreach (var edge in a.InEdges)
            {
                if (PointComparer.GetPureDirection(edge.SourcePoint, a.Point) == dir)
                {
                    return(edge);
                }
            }

            foreach (var edge in a.OutEdges)
            {
                if (PointComparer.GetPureDirection(a.Point, edge.TargetPoint) == dir)
                {
                    return(edge);
                }
            }
            return(null);
        }
コード例 #14
0
        internal void AddToAdjacentVertex(TransientGraphUtility transUtil, VisibilityVertex targetVertex
                                          , Rectangle limitRect, bool routeToCenter)
        {
            VisibilityVertex borderVertex = transUtil.VisGraph.FindVertex(this.VisibilityBorderIntersect);

            if (null != borderVertex)
            {
                ExtendFromBorderVertex(transUtil, borderVertex, limitRect, routeToCenter);
                return;
            }

            // There is no vertex at VisibilityBorderIntersect, so create it and link it to targetVertex.
            // Note: VisibilityBorderIntersect may == targetIntersect if that is on our border, *and*
            // targetIntersect may be on the border of a touching obstacle, in which case this will splice
            // into or across the adjacent obstacle, which is consistent with "touching is overlapped".
            // So we don't use UnpaddedBorderIntersect as prevPoint when calling ExtendEdgeChain.

            // VisibilityBorderIntersect may be rounded just one Curve.DistanceEpsilon beyond the ScanSegment's
            // perpendicular coordinate; e.g. our X may be targetIntersect.X + Curve.DistanceEpsilon, thereby
            // causing the direction from VisibilityBorderIntersect to targetIntersect to be W instead of E.
            // So use the targetIntersect if they are close enough; they will be equal for flat borders, and
            // otherwise the exact value we use only needs be "close enough" to the border.  (We can't use
            // CenterVertex as the prevPoint because that could be an impure direction).
            // Update: With the change to carry MaxVisibilitySegment within the PortEntrance, PortManager finds
            // targetVertex between VisibilityBorderIntersect and MaxVisibilitySegment.End, so this should no longer
            // be able to happen.
            // See RectilinearTests.PaddedBorderIntersectMeetsIncomingScanSegment for an example of what happens
            // when VisibilityBorderIntersect is on the incoming ScanSegment (it jumps out above with borderVertex found).
            if (OutwardDirection == PointComparer.GetPureDirection(targetVertex.Point, this.VisibilityBorderIntersect))
            {
                Debug.Assert(false, "Unexpected reversed direction between VisibilityBorderIntersect and targetVertex");
// ReSharper disable HeuristicUnreachableCode
                this.VisibilityBorderIntersect = targetVertex.Point;
                borderVertex = targetVertex;
// ReSharper restore HeuristicUnreachableCode
            }
            else
            {
                borderVertex = transUtil.FindOrAddVertex(this.VisibilityBorderIntersect);
                transUtil.FindOrAddEdge(borderVertex, targetVertex, InitialWeight);
            }
            ExtendEdgeChain(transUtil, borderVertex, targetVertex, limitRect, routeToCenter);
        }
コード例 #15
0
        internal VisibilityEdge FindOrAddEdge(VisibilityVertex sourceVertex, VisibilityVertex targetVertex, double weight)
        {
            // Since we're adding transient edges into the graph, we're not doing full intersection
            // evaluation; thus there may already be an edge from the source vertex in the direction
            // of the target vertex, but ending before or after the target vertex.
            Direction        dirToTarget = PointComparer.GetPureDirection(sourceVertex, targetVertex);
            VisibilityVertex bracketSource, bracketTarget, splitVertex;

            GetBrackets(sourceVertex, targetVertex, dirToTarget, out bracketSource, out bracketTarget, out splitVertex);

            // If null != edge then targetVertex is between bracketSource and bracketTarget and SplitEdge returns the
            // first half-edge (and weight is ignored as the split uses the edge weight).
            var edge = VisGraph.FindEdge(bracketSource.Point, bracketTarget.Point);

            edge = (edge != null)
                    ? this.SplitEdge(edge, splitVertex)
                    : CreateEdge(bracketSource, bracketTarget, weight);
            DevTrace_VerifyEdge(edge);
            return(edge);
        }
コード例 #16
0
ファイル: FreePoint.cs プロジェクト: suprcodr/EFDesigner
        internal void ExtendEdgeChain(TransientGraphUtility transUtil, VisibilityVertex targetVertex, Directions dirToExtend, Rectangle limitRect)
        {
            // Extend the edge chain to the opposite side of the limit rectangle.
            StaticGraphUtility.Assert(PointComparer.Equal(this.Point, targetVertex.Point) ||
                                      (PointComparer.GetPureDirection(this.Point, targetVertex.Point) == dirToExtend)
                                      , "input dir does not match with to-targetVertex direction", transUtil.ObstacleTree, transUtil.VisGraph);

            var extendOverlapped = IsOverlapped;

            if (extendOverlapped)
            {
                // The initial vertex we connected to may be on the border of the enclosing obstacle,
                // or of another also-overlapped obstacle.  If the former, we turn off overlap now.
                extendOverlapped = transUtil.ObstacleTree.PointIsInsideAnObstacle(targetVertex.Point, dirToExtend);
            }

            // If we're inside an obstacle's boundaries we'll never extend past the end of the obstacle
            // due to encountering the boundary from the inside.  So start the extension at targetVertex.
            SegmentAndCrossings segmentAndCrossings = GetSegmentAndCrossings(this.IsOverlapped ? targetVertex : this.Vertex, dirToExtend, transUtil);

            transUtil.ExtendEdgeChain(targetVertex, limitRect, segmentAndCrossings.Item1, segmentAndCrossings.Item2, extendOverlapped);
        }
コード例 #17
0
        static internal VisibilityVertex FindAdjacentVertex(VisibilityVertex a, Direction dir)
        {
            // This function finds the next vertex in the desired direction relative to the
            // current vertex, not necessarily the edge orientation, hence it does not use
            // EdgeDirection().  This is so the caller can operate on a desired movement
            // direction without having to track whether we're going forward or backward
            // through the In/OutEdge chain.
            foreach (var edge in a.InEdges)
            {
                if (PointComparer.GetPureDirection(a.Point, edge.SourcePoint) == dir)
                {
                    return(edge.Source);
                }
            }

            foreach (var edge in a.OutEdges)
            {
                if (PointComparer.GetPureDirection(a.Point, edge.TargetPoint) == dir)
                {
                    return(edge.Target);
                }
            }
            return(null);
        }
コード例 #18
0
        // The return value is whether we should try a second pass if this is called on the first pass,
        // using spliceTarget to wrap up dead-ends on the target side.
        bool ExtendSpliceWorker(VisibilityVertex spliceSource, Directions extendDir, Directions spliceTargetDir
                                , LineSegment maxDesiredSegment, LineSegment maxVisibilitySegment
                                , bool isOverlapped, out VisibilityVertex spliceTarget)
        {
            // This is called after having created at least one extension vertex (initially, the
            // first one added outside the obstacle), so we know extendVertex will be there. spliceSource
            // is the vertex to the OppositeDir(spliceTargetDir) of that extendVertex.
            VisibilityVertex extendVertex = StaticGraphUtility.FindNextVertex(spliceSource, spliceTargetDir);

            spliceTarget = StaticGraphUtility.FindNextVertex(extendVertex, spliceTargetDir);
            for (; ;)
            {
                if (!GetNextSpliceSource(ref spliceSource, spliceTargetDir, extendDir))
                {
                    break;
                }

                // spliceSource is now on the correct edge relative to the desired nextExtendPoint.
                // spliceTarget is in the opposite direction of the extension-line-to-spliceSource.
                Point nextExtendPoint = StaticGraphUtility.FindBendPointBetween(extendVertex.Point
                                                                                , spliceSource.Point, CompassVector.OppositeDir(spliceTargetDir));

                // We test below for being on or past maxDesiredSegment; here we may be skipping
                // over maxDesiredSegmentEnd which is valid since we want to be sure to go to or
                // past limitRect, but be sure to stay within maxVisibilitySegment.
                if (IsPointPastSegmentEnd(maxVisibilitySegment, nextExtendPoint))
                {
                    break;
                }

                spliceTarget = GetSpliceTarget(ref spliceSource, spliceTargetDir, nextExtendPoint);

                //StaticGraphUtility.Test_DumpVisibilityGraph(ObstacleTree, VisGraph);

                if (null == spliceTarget)
                {
                    // This may be because spliceSource was created just for Group boundaries.  If so,
                    // skip to the next nextExtendVertex location.
                    if (this.IsSkippableSpliceSourceWithNullSpliceTarget(spliceSource, extendDir))
                    {
                        continue;
                    }

                    // We're at a dead-end extending from the source side, or there is an intervening obstacle, or both.
                    // Don't splice across lateral group boundaries.
                    if (ObstacleTree.SegmentCrossesAnObstacle(spliceSource.Point, nextExtendPoint))
                    {
                        return(false);
                    }
                }

                // We might be walking through a point where a previous chain dead-ended.
                VisibilityVertex nextExtendVertex = VisGraph.FindVertex(nextExtendPoint);
                if (null != nextExtendVertex)
                {
                    if ((null == spliceTarget) || (null != this.VisGraph.FindEdge(extendVertex.Point, nextExtendPoint)))
                    {
                        // We are probably along a ScanSegment so visibility in this direction has already been determined.
                        // Stop and don't try to continue extension from the opposite side.  If we continue splicing here
                        // it might go across an obstacle.
                        if (null == spliceTarget)
                        {
                            Debug_VerifyNonOverlappedExtension(isOverlapped, extendVertex, nextExtendVertex, spliceSource: null, spliceTarget: null);
                            FindOrAddEdge(extendVertex, nextExtendVertex, isOverlapped ? ScanSegment.OverlappedWeight : ScanSegment.NormalWeight);
                        }
                        return(false);
                    }

                    // This should always have been found in the find-the-next-target loop above if there is
                    // a vertex (which would be nextExtendVertex, which we just found) between spliceSource
                    // and spliceTarget.  Even for a sparse graph, an edge should not skip over a vertex.
                    StaticGraphUtility.Assert(spliceTarget == StaticGraphUtility.FindNextVertex(nextExtendVertex, spliceTargetDir)
                                              , "no edge exists between an existing nextExtendVertex and spliceTarget"
                                              , ObstacleTree, VisGraph);
                }
                else
                {
                    StaticGraphUtility.Assert((null == spliceTarget) ||
                                              spliceTargetDir == PointComparer.GetPureDirection(nextExtendPoint, spliceTarget.Point)
                                              , "spliceTarget is not to spliceTargetDir of nextExtendVertex"
                                              , ObstacleTree, VisGraph);
                    nextExtendVertex = this.AddVertex(nextExtendPoint);
                }
                FindOrAddEdge(extendVertex, nextExtendVertex, isOverlapped ? ScanSegment.OverlappedWeight : ScanSegment.NormalWeight);

                Debug_VerifyNonOverlappedExtension(isOverlapped, extendVertex, nextExtendVertex, spliceSource, spliceTarget);

                // This will split the edge if targetVertex is non-null; otherwise we are at a dead-end
                // on the target side so must not create a vertex as it would be inside an obstacle.
                FindOrAddEdge(spliceSource, nextExtendVertex, isOverlapped ? ScanSegment.OverlappedWeight : ScanSegment.NormalWeight);
                if (isOverlapped)
                {
                    isOverlapped = this.SeeIfSpliceIsStillOverlapped(extendDir, nextExtendVertex);
                }
                extendVertex = nextExtendVertex;

                // Test GetDirections because it may return Directions. None.
                if (0 == (extendDir & PointComparer.GetDirections(nextExtendPoint, maxDesiredSegment.End)))
                {
                    // At or past the desired max extension point, so we're done.
                    spliceTarget = null;
                    break;
                }
            }
            return(null != spliceTarget);
        }
コード例 #19
0
 static internal bool PointIsOnSegment(Point first, Point second, Point test)
 {
     return(PointComparer.Equal(first, test) ||
            PointComparer.Equal(second, test) ||
            (PointComparer.GetPureDirection(first, test) == PointComparer.GetPureDirection(test, second)));
 }
コード例 #20
0
 static internal bool IsVertical(VisibilityEdge edge)
 {
     return(IsVertical(PointComparer.GetPureDirection(edge.SourcePoint, edge.TargetPoint)));
 }
コード例 #21
0
 static internal bool IsVertical(Point first, Point second)
 {
     return(IsVertical(PointComparer.GetPureDirection(first, second)));
 }
コード例 #22
0
 static internal Directions EdgeDirection(VisibilityVertex source, VisibilityVertex target)
 {
     return(PointComparer.GetPureDirection(source.Point, target.Point));
 }
コード例 #23
0
 static internal bool IsVertical(LineSegment seg)
 {
     return(IsVertical(PointComparer.GetPureDirection(seg.Start, seg.End)));
 }