internal ObstaclePortEntrance(ObstaclePort oport, Point unpaddedBorderIntersect, Directions outDir, ObstacleTree obstacleTree) {
            ObstaclePort = oport;
            UnpaddedBorderIntersect = unpaddedBorderIntersect;
            OutwardDirection = outDir;

            // Get the padded intersection.
            var lineSeg = new LineSegment(UnpaddedBorderIntersect, StaticGraphUtility.RectangleBorderIntersect(
                                            oport.Obstacle.VisibilityBoundingBox, UnpaddedBorderIntersect, outDir));
            IList<IntersectionInfo> xxs = Curve.GetAllIntersections(lineSeg, oport.Obstacle.VisibilityPolyline, true /*liftIntersections*/);
            Debug.Assert(1 == xxs.Count, "Expected one intersection");
            this.VisibilityBorderIntersect = ApproximateComparer.Round(SpliceUtility.RawIntersection(xxs[0], UnpaddedBorderIntersect));

            this.MaxVisibilitySegment = obstacleTree.CreateMaxVisibilitySegment(this.VisibilityBorderIntersect,
                    this.OutwardDirection, out this.pointAndCrossingsList);

            // Groups are never in a clump (overlapped) but they may still have their port entrance overlapped.
            if (this.Obstacle.IsOverlapped || (this.Obstacle.IsGroup && !this.Obstacle.IsInConvexHull)) {
                this.IsOverlapped = obstacleTree.IntersectionIsInsideAnotherObstacle(/*sideObstacle:*/ null, this.Obstacle
                        , this.VisibilityBorderIntersect, ScanDirection.GetInstance(OutwardDirection));
                if (!this.Obstacle.IsGroup || this.IsOverlapped || this.InteriorEdgeCrossesObstacle(obstacleTree)) {
                    unpaddedToPaddedBorderWeight = ScanSegment.OverlappedWeight;
                }
            }
            if (this.Obstacle.IsInConvexHull && (unpaddedToPaddedBorderWeight == ScanSegment.NormalWeight)) {
                SetUnpaddedToPaddedBorderWeightFromHullSiblingOverlaps(obstacleTree);
            }
        }
示例#2
0
        static internal void Test_DumpScanSegments(ObstacleTree obstacleTree, ScanSegmentTree hSegs, ScanSegmentTree vSegs)
        {
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);

            debugCurves.AddRange(Test_GetScanSegmentCurves(hSegs));
            debugCurves.AddRange(Test_GetScanSegmentCurves(vSegs));
            DebugCurveCollection.WriteToFile(debugCurves, GetDumpFileName("ScanSegments"));
        }
        static internal void Test_DumpPathsAfterNudging(ObstacleTree obstacleTree, IEnumerable <Path> edgePaths)
        {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetPostNudgedPathDebugCurves(edgePaths));
            DebugCurveCollection.WriteToFile(debugCurves, GetDumpFileName("PostNudgedPaths"));
#endif // TEST
        }
示例#4
0
        static internal void Test_DumpVisibilityGraph(ObstacleTree obstacleTree, VisibilityGraph vg)
        {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetVisibilityGraphDebugCurves(vg));
            DebugCurveCollection.WriteToFile(debugCurves, GetDumpFileName("VisibilityGraph"));
#endif // TEST
        }
        static internal void Test_ShowPathsAfterNudging(ObstacleTree obstacleTree, IEnumerable <Path> edgePaths)
        {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetPostNudgedPathDebugCurves(edgePaths));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(debugCurves);
#endif // TEST
        }
// ReSharper disable InconsistentNaming
        static internal void Test_ShowVisibilityGraph(ObstacleTree obstacleTree, VisibilityGraph vg)
        {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetVisibilityGraphDebugCurves(vg));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(debugCurves);
#endif // TEST
        }
 private bool InteriorEdgeCrossesObstacle(ObstacleTree obstacleTree) {
     // File Test: Nudger_Overlap4
     // Use the VisibilityBoundingBox for groups because those are what the tree consists of.
     var rect = new Rectangle(this.UnpaddedBorderIntersect, this.VisibilityBorderIntersect);
     return InteriorEdgeCrossesObstacle(rect, obs => obs.VisibilityPolyline,
             obstacleTree.Root.GetLeafRectangleNodesIntersectingRectangle(rect)
                 .Where(node => !node.UserData.IsGroup && (node.UserData != this.Obstacle)).Select(node => node.UserData));
 }
 static internal void Assert(bool condition, string message, ObstacleTree obstacleTree, VisibilityGraph vg)
 {
     if (!condition)
     {
         Test_DumpVisibilityGraph(obstacleTree, vg);
         Debug.Assert(condition, message);
     }
 }
        static internal void Test_ShowScanSegments(ObstacleTree obstacleTree, ScanSegmentTree hSegs, ScanSegmentTree vSegs)
        {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetScanSegmentCurves(hSegs));
            debugCurves.AddRange(Test_GetScanSegmentCurves(vSegs));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(debugCurves);
#endif // TEST
        }
示例#10
0
        private bool InteriorEdgeCrossesObstacle(ObstacleTree obstacleTree)
        {
            // File Test: Nudger_Overlap4
            // Use the VisibilityBoundingBox for groups because those are what the tree consists of.
            var rect = new Rectangle(this.UnpaddedBorderIntersect, this.VisibilityBorderIntersect);

            return(InteriorEdgeCrossesObstacle(rect, obs => obs.VisibilityPolyline,
                                               obstacleTree.Root.GetLeafRectangleNodesIntersectingRectangle(rect)
                                               .Where(node => !node.UserData.IsGroup && (node.UserData != this.Obstacle)).Select(node => node.UserData)));
        }
        internal void CreatePortEntrance(Point unpaddedBorderIntersect, Directions outDir, ObstacleTree obstacleTree) {
            var entrance = new ObstaclePortEntrance(this, unpaddedBorderIntersect, outDir, obstacleTree);
            PortEntrances.Add(entrance);
            this.VisibilityRectangle.Add(entrance.MaxVisibilitySegment.End);
#if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=370
            this.HasCollinearEntrances = this.HasCollinearEntrances | entrance.IsCollinearWithPort;
#else
            this.HasCollinearEntrances |= entrance.IsCollinearWithPort;
#endif
        }
 // obstacleToIgnore is the event obstacle if we're looking at intersections along its boundary.
 private bool IntersectionAtSideIsInsideAnotherObstacle(BasicObstacleSide side, Obstacle eventObstacle, Point intersect)
 {
     // See if the intersection with an obstacle side is inside another obstacle (that encloses
     // at least the part of side.Obstacle containing the intersection).  This will only happen
     // if side.Obstacle is overlapped and in the same clump (if it's not the same clump, we must
     // be hitting it from the outside).
     if (!side.Obstacle.IsOverlapped)
     {
         return(false);
     }
     if (!side.Obstacle.IsGroup && !eventObstacle.IsGroup && (side.Obstacle.Clump != eventObstacle.Clump))
     {
         return(false);
     }
     return(ObstacleTree.IntersectionIsInsideAnotherObstacle(side.Obstacle, eventObstacle, intersect, ScanDirection));
 }
 static internal List<DebugCurve> Test_GetObstacleDebugCurves(ObstacleTree obstacleTree, bool noPadPoly, bool noVisPoly) {
     return Test_GetObstacleDebugCurves(obstacleTree.GetAllObstacles(), noPadPoly, noVisPoly);
 }
 static internal List<DebugCurve> Test_GetObstacleDebugCurves(ObstacleTree obstacleTree) {
     return Test_GetObstacleDebugCurves(obstacleTree, false, false);
 }
        static internal void Test_DumpScanSegments(ObstacleTree obstacleTree, ScanSegmentTree hSegs, ScanSegmentTree vSegs) {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetScanSegmentCurves(hSegs));
            debugCurves.AddRange(Test_GetScanSegmentCurves(vSegs));
            DebugCurveCollection.WriteToFile(debugCurves, GetDumpFileName("ScanSegments"));
#endif // TEST
        }
        static internal void Test_ShowScanSegments(ObstacleTree obstacleTree, ScanSegmentTree hSegs, ScanSegmentTree vSegs) {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetScanSegmentCurves(hSegs));
            debugCurves.AddRange(Test_GetScanSegmentCurves(vSegs));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(debugCurves);
#endif // TEST
        }
        static internal void Test_DumpPathsAfterNudging(ObstacleTree obstacleTree, IEnumerable<Path> edgePaths) {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetPostNudgedPathDebugCurves(edgePaths));
            DebugCurveCollection.WriteToFile(debugCurves, GetDumpFileName("PostNudgedPaths"));
#endif // TEST
        }
        static internal void Test_ShowPathsAfterNudging(ObstacleTree obstacleTree, IEnumerable<Path> edgePaths) {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetPostNudgedPathDebugCurves(edgePaths));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(debugCurves);
#endif // TEST
        }
示例#19
0
 static internal List <DebugCurve> Test_GetObstacleDebugCurves(ObstacleTree obstacleTree, bool noPadPoly, bool noVisPoly)
 {
     return(Test_GetObstacleDebugCurves(obstacleTree.GetAllObstacles(), noPadPoly, noVisPoly));
 }
示例#20
0
        internal void CreatePortEntrance(Point unpaddedBorderIntersect, Directions outDir, ObstacleTree obstacleTree)
        {
            var entrance = new ObstaclePortEntrance(this, unpaddedBorderIntersect, outDir, obstacleTree);

            PortEntrances.Add(entrance);
            this.VisibilityRectangle.Add(entrance.MaxVisibilitySegment.End);
#if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=370
            this.HasCollinearEntrances = this.HasCollinearEntrances | entrance.IsCollinearWithPort;
#else
            this.HasCollinearEntrances |= entrance.IsCollinearWithPort;
#endif
        }
示例#21
0
        internal ObstaclePortEntrance(ObstaclePort oport, Point unpaddedBorderIntersect, Direction outDir, ObstacleTree obstacleTree)
        {
            ObstaclePort            = oport;
            UnpaddedBorderIntersect = unpaddedBorderIntersect;
            OutwardDirection        = outDir;

            // Get the padded intersection.
            var lineSeg = new LineSegment(UnpaddedBorderIntersect, StaticGraphUtility.RectangleBorderIntersect(
                                              oport.Obstacle.VisibilityBoundingBox, UnpaddedBorderIntersect, outDir));
            IList <IntersectionInfo> xxs = Curve.GetAllIntersections(lineSeg, oport.Obstacle.VisibilityPolyline, true /*liftIntersections*/);

            Debug.Assert(1 == xxs.Count, "Expected one intersection");
            this.VisibilityBorderIntersect = ApproximateComparer.Round(SpliceUtility.RawIntersection(xxs[0], UnpaddedBorderIntersect));

            this.MaxVisibilitySegment = obstacleTree.CreateMaxVisibilitySegment(this.VisibilityBorderIntersect,
                                                                                this.OutwardDirection, out this.pointAndCrossingsList);

            // Groups are never in a clump (overlapped) but they may still have their port entrance overlapped.
            if (this.Obstacle.IsOverlapped || (this.Obstacle.IsGroup && !this.Obstacle.IsInConvexHull))
            {
                this.IsOverlapped = obstacleTree.IntersectionIsInsideAnotherObstacle(/*sideObstacle:*/ null, this.Obstacle
                                                                                     , this.VisibilityBorderIntersect, ScanDirection.GetInstance(OutwardDirection));
                if (!this.Obstacle.IsGroup || this.IsOverlapped || this.InteriorEdgeCrossesObstacle(obstacleTree))
                {
                    unpaddedToPaddedBorderWeight = ScanSegment.OverlappedWeight;
                }
            }
            if (this.Obstacle.IsInConvexHull && (unpaddedToPaddedBorderWeight == ScanSegment.NormalWeight))
            {
                SetUnpaddedToPaddedBorderWeightFromHullSiblingOverlaps(obstacleTree);
            }
        }
 private void SetUnpaddedToPaddedBorderWeightFromHullSiblingOverlaps(ObstacleTree obstacleTree) {
     if (this.Obstacle.IsGroup ? this.InteriorEdgeCrossesObstacle(obstacleTree) : this.InteriorEdgeCrossesConvexHullSiblings()) {
         this.unpaddedToPaddedBorderWeight = ScanSegment.OverlappedWeight;
     }
 }
        // 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);
        }
 static internal void Assert(bool condition, string message, ObstacleTree obstacleTree, VisibilityGraph vg) {
     if (!condition) {
         Test_DumpVisibilityGraph(obstacleTree, vg);
         Debug.Assert(condition, message);
     }
 }
示例#25
0
 static internal List <DebugCurve> Test_GetObstacleDebugCurves(ObstacleTree obstacleTree)
 {
     return(Test_GetObstacleDebugCurves(obstacleTree, false, false));
 }
// ReSharper disable InconsistentNaming
        static internal void Test_ShowVisibilityGraph(ObstacleTree obstacleTree, VisibilityGraph vg) {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetVisibilityGraphDebugCurves(vg));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(debugCurves);
#endif // TEST
        }
        // ReSharper disable InconsistentNaming
        protected static void Debug_AssertGraphIsRectilinear(VisibilityGraph graph, ObstacleTree obstacleTree)
        // ReSharper restore InconsistentNaming
        {
#if DEBUG
            if (graph.Edges.Any(edge => !PointComparer.IsPureDirection(PointComparer.GetDirections(edge.SourcePoint, edge.TargetPoint))))
            {
                StaticGraphUtility.Assert(false, "Generated VisibilityGraph contains non-rectilinear lines", obstacleTree, graph);
                return;
            }
#endif
        }
        static internal void Test_DumpVisibilityGraph(ObstacleTree obstacleTree, VisibilityGraph vg) {
#if TEST_MSAGL
            var debugCurves = Test_GetObstacleDebugCurves(obstacleTree);
            debugCurves.AddRange(Test_GetVisibilityGraphDebugCurves(vg));
            DebugCurveCollection.WriteToFile(debugCurves, GetDumpFileName("VisibilityGraph"));
#endif // TEST
        }