void ProcessEvent(CloseVertexEvent closeVertEvent) {
            // This event closes the obstacle.  It removes the ActiveLowSide and ActiveHighSide from the scanline and does
            // not add new sides.  As above, see comments in OpenVertexEvent and its callees for more detailed explanations.
            CreateCloseEventSegmentsAndFindNeighbors(closeVertEvent);
            
            // For reflection, in addition to the delayed lookahead we do in the other *VertexEvents, we need to
            // detect pending reflections up to an already loaded obstacle side.  This may be transitive; using
            // H directions as an example:
            //  (A). Obstacles A and B lean rightward such that a vertical line can be drawn from the lower side
            //    of ObstacleA downward to the right of ObstacleB (missing it) and hitting Obstacle C.
            //  (B). ObstacleC's start point is above the start points of Obstacles A and B.
            //  (C). ObjectC reflects a Lookahead scan up along the line cited in (A).
            // To handle this, whenever we close an object, see if either nbor side spans lookahead scan points.
            // If so, then add the events.  Otherwise, we know that a new side for those nbor objects, or for
            // subsequent higher objects, will be created at some point (unless we run out of obstacles).
            // Since we do reflections only in staircase situations, these lookahead events will be discarded
            // (because the existing edge would have to have already been processed as an immediate neighbor,
            // in order to satisfy the definition of a staircase).  See RectilinearTests.ReflectionsDetectedByAlreadyLoadedSide.

            // Check the neighbors in both directions for reflection events.
            // When querying for lookahead sites for a nborSide, always test the full nborSide range if
            // the opposite nborSide reflects upward, because we will have generated a lookahead site for the
            // current eventObstacle on that upward-reflecting nborSide.  For example, restricting the 
            // lowNborSide lookahead-site query to the currentEventObstacle.ActiveLowSide would pick up
            // any lookahead sites stored on eventObstacle.ActiveLowSide, but would not pick up a lookahead
            // site that the current CloseVertexEvent just stored on the highNborSide).
            // Fix: Updated this to remove restricted-range as it skips the range that includes the far side of the 
            // current obstacle when called for neighbors that extend across the top vertex.
            var lowNborSide = (HighObstacleSide)LowNeighborSides.LowNeighbor.Item;
            var highNborSide = (LowObstacleSide)HighNeighborSides.HighNeighbor.Item;
            var obstacle = closeVertEvent.Obstacle;
            LoadReflectionEvents(lowNborSide);
            LoadReflectionEvents(highNborSide);

            // This prepares the object for the second (perpendicular) sweep.
            obstacle.Close();
        } // end ProcessEvent(CloseVertexEvent)
        } // end ProcessEvent(HighBendVertexEvent)

        void CreateCloseEventSegmentsAndFindNeighbors(CloseVertexEvent closeVertEvent) {
            var obstacle = closeVertEvent.Obstacle;
            DevTraceIfFlatSide(false /*isObstacleOpen*/, obstacle.ActiveLowSide.End, obstacle.ActiveHighSide.End);
            RBNode<BasicObstacleSide> lowSideNode = scanLine.Find(obstacle.ActiveLowSide);
            RBNode<BasicObstacleSide> highSideNode = scanLine.Find(obstacle.ActiveHighSide);

            // Two sides coming together at a top point will be reverse-ordered in the scanline,
            // because their projections ahead of the intersection are slope-based.  This must
            // be the case in order to maintain scanline consistency.  Therefore we need to
            // check the comparison and reverse the local variables if necessary.  Fortunately
            // we only concern ourselves with the actual Low-vs-High side type for neighbors,
            // not the sides of the obstacle.
            if (1 == scanLine.Compare(obstacle.ActiveLowSide, obstacle.ActiveHighSide)) {
                var temp = lowSideNode;
                lowSideNode = highSideNode;
                highSideNode = temp;
            }

            // As with OpenVertexEvent, the idea here is to find the neighbors and draw the line between them 
            // that includes the event vertex (and any flat top obstacle side), with consideration for overlaps.
            this.FindNeighborsAndProcessVertexEvent(lowSideNode, highSideNode, closeVertEvent);

            // Inner overlaps: any overlapped sides coming out of the obstacle must have reflection events
            // drained for any that were generated from sides of the closing obstacle if they extend
            // outside the closing obstacle.
            if (this.wantReflections && obstacle.IsOverlapped) {
                for (RBNode<BasicObstacleSide> nextNode = scanLine.NextHigh(lowSideNode);
                        nextNode.Item != highSideNode.Item; nextNode = scanLine.NextHigh(nextNode)) {
                    LoadReflectionEvents(nextNode.Item);
                }
            }

            // Remove the obstacle from the Scanline.  This comes after the foregoing which is why it's a
            // separate function; the RBTree modifies RBNodes, so doing the .Remove at the end of a separate 
            // function ensures we won't access RBNodes that may no longer contain what we expect.
            scanLine.Remove(obstacle.ActiveLowSide, closeVertEvent.Site);
            scanLine.Remove(obstacle.ActiveHighSide, closeVertEvent.Site);
        }