private void CenterAroundRois(RectRelativeToViewport overrideRectRelativeToViewport)
 {
     if (m_ViewModel.SelectedRois.Count > 0)
     {
         CenterAroundRect(GetCentralRoisBoundingRect(), overrideRectRelativeToViewport);
     }
 }
        private RectRelativeToViewport GetOverrideRectRelativeToViewport()
        {
            if (m_ViewModel.SelectedRois.Count == 0)
            {
                return(null);
            }
            RectRelativeToViewport r = new RectRelativeToViewport();

            Rect rect = GetCentralRoisBoundingRect();

            if (m_ViewModel.PersistentViewState.VisualWidth - rect.Right < rect.Left)
            {
                r.HorizontalState = RectRelativeToViewport.HorizontalRelativeToViewPort.Right;
            }
            else
            {
                r.HorizontalState = RectRelativeToViewport.HorizontalRelativeToViewPort.Left;
            }

            if (m_ViewModel.PersistentViewState.VisualHeight - rect.Bottom < rect.Top)
            {
                r.VerticalState = RectRelativeToViewport.VerticalRelativeToViewPort.Bottom;
            }
            else
            {
                r.VerticalState = RectRelativeToViewport.VerticalRelativeToViewPort.Top;
            }

            return(r);
        }
        private RectRelativeToViewport GetRectRelativeToViewport(double roiExtendedBoundLeft, double roiExtendedBoundTop, double roiExtendedBoundRight, double roiExtendedBoundBottom)
        {
            RectRelativeToViewport rectRelativeToViewport = new RectRelativeToViewport();

            //first, trim the ROI rectangle in case viewport is smaller ("clip to bounds" of viewport)
            //  aribitrarily decided (can change this) that the top left of the rect is the most important.
            if (roiExtendedBoundRight - roiExtendedBoundLeft > this.scrollViewer.ViewportWidth)
            {
                roiExtendedBoundRight = roiExtendedBoundLeft + this.scrollViewer.ViewportWidth - 1;
            }
            if (roiExtendedBoundBottom - roiExtendedBoundTop > this.scrollViewer.ViewportHeight)
            {
                roiExtendedBoundBottom = roiExtendedBoundTop + this.scrollViewer.ViewportHeight - 1;
            }

            //horizontal
            if (this.scrollViewer.HorizontalOffset <= roiExtendedBoundLeft &&
                this.scrollViewer.ViewportWidth + this.scrollViewer.HorizontalOffset >= roiExtendedBoundRight)
            {
                rectRelativeToViewport.HorizontalState = RectRelativeToViewport.HorizontalRelativeToViewPort.Contained;
            }
            else if (this.scrollViewer.HorizontalOffset > roiExtendedBoundLeft)
            {
                rectRelativeToViewport.HorizontalState = RectRelativeToViewport.HorizontalRelativeToViewPort.Left;
            }
            else
            {
                rectRelativeToViewport.HorizontalState = RectRelativeToViewport.HorizontalRelativeToViewPort.Right;
            }

            //vertical
            if (this.scrollViewer.VerticalOffset <= roiExtendedBoundTop &&
                this.scrollViewer.ViewportHeight + this.scrollViewer.VerticalOffset >= roiExtendedBoundBottom)
            {
                rectRelativeToViewport.VerticalState = RectRelativeToViewport.VerticalRelativeToViewPort.Contained;
            }
            else if (this.scrollViewer.VerticalOffset > roiExtendedBoundTop)
            {
                rectRelativeToViewport.VerticalState = RectRelativeToViewport.VerticalRelativeToViewPort.Top;
            }
            else
            {
                rectRelativeToViewport.VerticalState = RectRelativeToViewport.VerticalRelativeToViewPort.Bottom;
            }

            return(rectRelativeToViewport);
        }
 private void CenterAroundRect(Rect rect, RectRelativeToViewport overrideRectRelativeToViewport)
 {
     //TODO: change 20 to ViewMode.PaddingThickness
     CenterAroundRect(rect, PaddingThickness, PaddingThickness, overrideRectRelativeToViewport);
 }
        /// <summary>
        /// TODO: Yoav 2013.05.01: Fix in cases where viewport is smaller that CenteredRois bounding rect, and then in some cases the scrolling is behaving strangely (don't know exactly which cases yet).
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="surroundBorderWidth"></param>
        /// <param name="surroundBorderHeight"></param>
        private void CenterAroundRect(Rect rect, double surroundBorderWidth = PaddingThickness, double surroundBorderHeight = PaddingThickness, RectRelativeToViewport overrideRectRelativeToViewport = null)
        {
            if (this.scrollViewer.ExtentWidth == 0)
            {
                return;
            }
            //actual width of displayed area inside the scrollViewer
            //this.scrollViewer.ExtentWidth
            //this.scrollViewer.ExtentHeight
            //position after ScrollToVerticalOffset should equal  this.scrollViewer.VerticalOffset
            //position after ScrollToHorizontalOffset should equal  this.scrollViewer.HorizontalOffset

            //When trying to scroll to H/V offset:
            //center of scrollable area is determined ExtentHight / 2,  ExtentWidth / 2
            //after this normalize the 0,0 of image after scale to determine the actual location of the rectangle on the scrollViewer
            //then, when trying to resize, the ScrollableHeight, ScrollableWidth may be smaller than the value you want to pass ScrollToVerticalOffset, ScrollToHorizontalOffset,
            //and in this case it will take the ScrollableHeight, ScrollableWidth value instead.

            double deltaX = (this.scrollViewer.ExtentWidth / 2) - (m_ViewModel.PersistentViewState.VisualWidth * m_ViewModel.VolatileViewState.ScaleTransform.ScaleX / 2);
            double deltaY = (this.scrollViewer.ExtentHeight / 2) - (m_ViewModel.PersistentViewState.VisualHeight * m_ViewModel.VolatileViewState.ScaleTransform.ScaleY / 2);

            //normalize to current viewport coordinates + scale
            double roiExtendedBoundLeft   = rect.X * m_ViewModel.VolatileViewState.ScaleTransform.ScaleX + deltaX - surroundBorderWidth;
            double roiExtendedBoundTop    = rect.Y * m_ViewModel.VolatileViewState.ScaleTransform.ScaleY + deltaY - surroundBorderHeight;
            double roiExtendedBoundRight  = roiExtendedBoundLeft + rect.Width * m_ViewModel.VolatileViewState.ScaleTransform.ScaleX + 2 * surroundBorderWidth;
            double roiExtendedBoundBottom = roiExtendedBoundTop + rect.Height * m_ViewModel.VolatileViewState.ScaleTransform.ScaleY + 2 * surroundBorderHeight;

            //in case the deltas are negative (ROI outside visible area, can this actually happen?)
            roiExtendedBoundLeft = Math.Max(roiExtendedBoundLeft, 0);
            roiExtendedBoundLeft = Math.Max(roiExtendedBoundLeft, deltaX);  //in ROI is outside the margin (actually happens when the surroundBorderWidth (=20) makes the ROI extended borders go outside the image
            roiExtendedBoundTop  = Math.Max(roiExtendedBoundTop, 0);
            roiExtendedBoundTop  = Math.Max(roiExtendedBoundTop, deltaY);   //in ROI is outside the margin (actually happens when the surroundBorderWidth (=20) makes the ROI extended borders go outside the image
            //roiExtendedBoundRight = Math.Min(roiExtendedBoundRight, this.scrollViewer.ExtentWidth - deltaX);
            //roiExtendedBoundBottom = Math.Min(roiExtendedBoundBottom, this.scrollViewer.ExtentHeight - deltaY);

            RectRelativeToViewport rp;

            if (overrideRectRelativeToViewport != null)
            {
                rp = overrideRectRelativeToViewport;
            }
            else
            {
                rp = GetRectRelativeToViewport(roiExtendedBoundLeft, roiExtendedBoundTop, roiExtendedBoundRight, roiExtendedBoundBottom);
            }

            //horizontal aspect
            double visibleRightMargin   = GetVisibleRightMargin();
            double visibleLeftMargin    = GetVisibleLeftMargin();
            double eliminateRightMargin = this.scrollViewer.HorizontalOffset - visibleRightMargin;
            double eliminateLeftMargin  = this.scrollViewer.HorizontalOffset + visibleLeftMargin;

            if (rp.HorizontalState == RectRelativeToViewport.HorizontalRelativeToViewPort.Left)
            {
                this.scrollViewer.ScrollToHorizontalOffset(Math.Min(/*deltaX +*/ roiExtendedBoundLeft, eliminateRightMargin));
            }
            else if (rp.HorizontalState == RectRelativeToViewport.HorizontalRelativeToViewPort.Right)
            {
                this.scrollViewer.ScrollToHorizontalOffset(Math.Max(roiExtendedBoundRight - this.scrollViewer.ViewportWidth, eliminateLeftMargin));
            }
            else
            {
                if (visibleLeftMargin > 0)
                {
                    this.scrollViewer.ScrollToHorizontalOffset(eliminateLeftMargin);
                }
                else if (visibleRightMargin > 0)
                {
                    this.scrollViewer.ScrollToHorizontalOffset(eliminateRightMargin);
                }
            }


            //vertical aspect
            double visibleBottomMargin   = GetVisibleBottomMargin();
            double visibleTopMargin      = GetVisibleTopMargin();
            double eliminateBottomMargin = this.scrollViewer.VerticalOffset - visibleBottomMargin;
            double eliminateTopMargin    = this.scrollViewer.VerticalOffset + visibleTopMargin;

            if (rp.VerticalState == RectRelativeToViewport.VerticalRelativeToViewPort.Top)
            {
                this.scrollViewer.ScrollToVerticalOffset(Math.Min(/*deltaY +*/ roiExtendedBoundTop, eliminateBottomMargin));
            }
            else if (rp.VerticalState == RectRelativeToViewport.VerticalRelativeToViewPort.Bottom)
            {
                this.scrollViewer.ScrollToVerticalOffset(Math.Max(roiExtendedBoundBottom - this.scrollViewer.ViewportHeight, eliminateTopMargin));
            }
            else
            {
                if (visibleTopMargin > 0)
                {
                    this.scrollViewer.ScrollToVerticalOffset(eliminateTopMargin);
                }
                else if (visibleBottomMargin > 0)
                {
                    this.scrollViewer.ScrollToVerticalOffset(eliminateBottomMargin);
                }
            }
        }