// Called by LowReflectionEvent or HighReflectionEvent ctors, which are called out of
 // AddReflectionEvent, which in turn is called by LoadLookaheadIntersections.
 // In this case we know the eventObstacle and initialObstacle are the same obstacle (the
 // one that the reflected ray bounced off of, to generate the Left/HighReflectionEvent).
 internal BasicReflectionEvent(BasicReflectionEvent previousSite, Obstacle reflectingObstacle, Point site)
 {
     this.InitialObstacle    = previousSite.ReflectingObstacle;
     this.ReflectingObstacle = reflectingObstacle;
     this.site         = site;
     this.PreviousSite = previousSite;
 }
 protected override bool InsertParallelReflectionSegment(Point start, Point end, Obstacle eventObstacle,
         BasicObstacleSide lowNborSide, BasicObstacleSide highNborSide, BasicReflectionEvent action) {
     // See notes in InsertPerpendicularReflectionSegment for comments about an existing segment.
     // Here, we call AddSegment which adds the segment and continues the reflection staircase.
     if (null != ParallelScanSegments.Find(start, end)) {
         return false;
     }
     return AddSegment(start, end, eventObstacle, lowNborSide, highNborSide, action, ScanSegment.ReflectionWeight);
 }
        void AddReflectionEvent(BasicReflectionEvent previousSite, BasicObstacleSide side, Point site) {
            Debug.Assert(null != scanLine.Find(side), "AddReflectionEvent could not find 'side' in the scanline");

            // Add an event that will be drained when a side spanning the scanline-parallel is loaded
            // as the sweep moves "up".
            var lowSide = side as LowObstacleSide;
            if (lowSide != null) {
                eventQueue.Enqueue(new LowReflectionEvent(previousSite, lowSide, site));
            } else {
                eventQueue.Enqueue(new HighReflectionEvent(previousSite, (HighObstacleSide)side, site));
            }
        }
 protected abstract bool InsertParallelReflectionSegment(Point start, Point end, Obstacle eventObstacle,
         BasicObstacleSide lowNborSide, BasicObstacleSide highNborSide, BasicReflectionEvent action);
 private bool AddParallelReflectionSegment(Obstacle eventObstacle, BasicObstacleSide lowNborSide
                         , BasicObstacleSide highNborSide, BasicReflectionEvent action) {
     // If this is reflecting to a low neighbor, then that intersect is 'start' in the low-to-high
     // sequence, and the event site is the end; otherwise we start at the event site and end at
     // the high neighbor.
     Point intersect = ScanLineIntersectSide(action.Site, lowNborSide ?? highNborSide);
     Point start = (null != lowNborSide) ? intersect : action.Site;
     Point end = (null != lowNborSide) ? action.Site : intersect;
     
     // Now get the opposite neighbors so AddSegment can continue the reflection chain.
     if (null == lowNborSide) {
         lowNborSide = scanLine.NextLow(highNborSide).Item;
     }
     else {
         highNborSide = scanLine.NextHigh(lowNborSide).Item;
     }
     return InsertParallelReflectionSegment(start, end, eventObstacle, lowNborSide, highNborSide, action);
 }
        // Determine whether the event is valid and do some common processing.
        bool AddPerpendicularReflectionSegment(BasicReflectionEvent currentEvent, BasicObstacleSide eventSide, BasicObstacleSide nborSide) {
            // If eventSide is null it means we had the wrong side type as a scanline neighbor.
            // If another obstacle opened up, then that obstacle (or another intervening one) should have
            // drained this reflection event.
            Debug.Assert(null != eventSide, "eventSide should not be null");

            // Between the time currentEvent was queued and the time we're now processing it, another
            // obstacle may have opened between the previousSite and the eventSite, in which case it
            // removed currentEvent from the queue already.  So currentEvent may be stale.  The new
            // obstacle may have stored *another* lookahead site with the same scanline-parallel 
            // coordinate (but higher up perpendicularly).  So remove the exact site of currentEvent; 
            // otherwise the currentEvent could be a stale event with the lower scanline-parallel
            // coordinate, and would remove the site from the lookahead list before the "live" event
            // looks for it.  See RectilinearTests.ReflectionsRemoveInterceptedSite.
            if (lookaheadScan.RemoveExact(currentEvent.PreviousSite)) {
                Debug.Assert(currentEvent.InitialObstacle == currentEvent.PreviousSite.ReflectingObstacle
                            , "Inconsistency: currentEvent.InitialObstacle != currentEvent.PreviousSite.ReflectingObstacle");
// ReSharper disable HeuristicUnreachableCode
// ReSharper disable ConditionIsAlwaysTrueOrFalse
                if (null == eventSide) {
                    // We've removed the event so there's nothing else to do.
                    return false;
                }
// ReSharper restore ConditionIsAlwaysTrueOrFalse
// ReSharper restore HeuristicUnreachableCode

                // If the two sides intersect ahead of the scanline, we don't want the reflection.

                // If the reflecting side is flat, no reflection is done - that's handled by OpenVertexEvent.
                Debug.Assert(!IsFlat(eventSide), "Flat sides should not be encountered in reflections");
                if (currentEvent.PreviousSite.IsStaircaseStep(currentEvent.ReflectingObstacle)) {
                    // We need to draw the perpendicular lines here because we may be on the second
                    // sweep so there won't be a subsequent sweep to draw them.  And if we're on the
                    // second sweep, we may have already loaded this segment as part of a continuation
                    // of an overlapped segment. Either way, we only want this if we are not on an extreme
                    // edge of the target obstacle (reflectingObstacle for the perpendicular segment,
                    // nborSide.Obstacle for the parallel segment).  Extreme vertices will generate segments.
                    // See TestRectilinear.Reflection_Staircase_Stops_At_BoundingBox_Side*.
                    if (!StaticGraphUtility.PointIsInRectangleInterior(currentEvent.Site, currentEvent.ReflectingObstacle.VisibilityBoundingBox))
                    {
                        return false;
                    }
                    DevTraceInfoVgGen(1, "Perpendicular Reflection - Adding Segment [{0} -> {1}]", currentEvent.PreviousSite.Site, currentEvent.Site);
                    DevTraceInfoVgGen(2, "  -> side {0}", eventSide);   // same indent as AddSegment; eventSide is highNbor
                    if (!InsertPerpendicularReflectionSegment(currentEvent.PreviousSite.Site, currentEvent.Site)) {
                        return false;
                    }

                    // If the neighbor continues the staircase and the parallel segment would hit a non-extreme point
                    // on the neighbor, return true and the Low/HighReflectionEvent handler will add the parallel segment.
                    if ((null != nborSide) && currentEvent.IsStaircaseStep(nborSide.Obstacle)) {
                        return this.ScanLineCrossesObstacle(currentEvent.Site, nborSide.Obstacle);
                    }
                    DevTraceInfoVgGen(1, "Reflection Lookahead site {0} is not an outgoing staircase step; discontinuing", currentEvent.PreviousSite);
                }
                else {
                    DevTraceInfoVgGen(1, "Reflection Lookahead site {0} is not an incoming staircase step; discontinuing", currentEvent.PreviousSite);
                }
            }
            else {
                DevTraceInfoVgGen(1, "Reflection Lookahead site {0} is no longer in the lookahead table; skipping", currentEvent.PreviousSite);
            }
            return false;
        }
 internal HighReflectionEvent(BasicReflectionEvent previousSite, HighObstacleSide targetSide, Point site)
     : base (previousSite, targetSide.Obstacle, site) {
     this.Side = targetSide;
 }
Example #8
0
 internal LowReflectionEvent(BasicReflectionEvent previousSite, LowObstacleSide targetSide, Point site)
     : base(previousSite, targetSide.Obstacle, site)
 {
     this.Side = targetSide;
 }
Example #9
0
        protected override bool InsertParallelReflectionSegment(Point start, Point end, Obstacle eventObstacle,
                                                                BasicObstacleSide lowNborSide, BasicObstacleSide highNborSide, BasicReflectionEvent action)
        {
            Debug.Assert(false, "base.wantReflections is false in Sparse mode so this should never be called");
// ReSharper disable HeuristicUnreachableCode
            return(false);
// ReSharper restore HeuristicUnreachableCode
        }
Example #10
0
        protected override bool InsertParallelReflectionSegment(Point start, Point end, Obstacle eventObstacle,
                                                                BasicObstacleSide lowNborSide, BasicObstacleSide highNborSide, BasicReflectionEvent action)
        {
            // See notes in InsertPerpendicularReflectionSegment for comments about an existing segment.
            // Here, we call AddSegment which adds the segment and continues the reflection staircase.
            if (null != ParallelScanSegments.Find(start, end))
            {
                return(false);
            }

            return(AddSegment(start, end, eventObstacle, lowNborSide, highNborSide, action, ScanSegment.ReflectionWeight));
        }
 // Called by LowReflectionEvent or HighReflectionEvent ctors, which are called out of 
 // AddReflectionEvent, which in turn is called by LoadLookaheadIntersections.
 // In this case we know the eventObstacle and initialObstacle are the same obstacle (the
 // one that the reflected ray bounced off of, to generate the Left/HighReflectionEvent).
 internal BasicReflectionEvent(BasicReflectionEvent previousSite, Obstacle reflectingObstacle, Point site) {
     this.InitialObstacle = previousSite.ReflectingObstacle;
     this.ReflectingObstacle = reflectingObstacle;
     this.site = site;
     this.PreviousSite = previousSite;
 }