/// <summary> /// Update cropped area. /// </summary> /// <param name="dragPosition">The control point</param> /// <param name="diffPos">Position offset</param> private void UpdateCroppedRectWithAspectRatio(DragPosition dragPosition, Point diffPos) { if (diffPos == default(Point) || !CanvasRect.IsValid()) { return; } double radian = 0d, diffPointRadian = 0d, effectiveLength = 0d; if (KeepAspectRatio) { radian = Math.Atan(UsedAspectRatio); diffPointRadian = Math.Atan(diffPos.X / diffPos.Y); } var startPoint = new Point(_startX, _startY); var endPoint = new Point(_endX, _endY); var currentSelectedRect = new Rect(startPoint, endPoint); switch (dragPosition) { case DragPosition.Top: if (KeepAspectRatio) { var originSizeChange = new Point(-diffPos.Y * UsedAspectRatio, -diffPos.Y); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); startPoint.X += -safeChange.X / 2; endPoint.X -= -safeChange.X / 2; startPoint.Y += -safeChange.Y; } else { startPoint.Y += diffPos.Y; } break; case DragPosition.Bottom: if (KeepAspectRatio) { var originSizeChange = new Point(diffPos.Y * UsedAspectRatio, diffPos.Y); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); startPoint.X -= safeChange.X / 2; endPoint.X += safeChange.X / 2; endPoint.Y += safeChange.Y; } else { endPoint.Y += diffPos.Y; } break; case DragPosition.Left: if (KeepAspectRatio) { var originSizeChange = new Point(-diffPos.X, -diffPos.X / UsedAspectRatio); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); startPoint.Y += -safeChange.Y / 2; endPoint.Y -= -safeChange.Y / 2; startPoint.X += -safeChange.X; } else { startPoint.X += diffPos.X; } break; case DragPosition.Right: if (KeepAspectRatio) { var originSizeChange = new Point(diffPos.X, diffPos.X / UsedAspectRatio); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); startPoint.Y -= safeChange.Y / 2; endPoint.Y += safeChange.Y / 2; endPoint.X += safeChange.X; } else { endPoint.X += diffPos.X; } break; case DragPosition.UpperLeft: if (KeepAspectRatio) { effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); var originSizeChange = new Point(-effectiveLength * Math.Sin(radian), -effectiveLength * Math.Cos(radian)); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); diffPos.X = -safeChange.X; diffPos.Y = -safeChange.Y; } startPoint.X += diffPos.X; startPoint.Y += diffPos.Y; break; case DragPosition.UpperRight: if (KeepAspectRatio) { diffPointRadian = -diffPointRadian; effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); var originSizeChange = new Point(-effectiveLength * Math.Sin(radian), -effectiveLength * Math.Cos(radian)); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); diffPos.X = safeChange.X; diffPos.Y = -safeChange.Y; } endPoint.X += diffPos.X; startPoint.Y += diffPos.Y; break; case DragPosition.LowerLeft: if (KeepAspectRatio) { diffPointRadian = -diffPointRadian; effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); var originSizeChange = new Point(effectiveLength * Math.Sin(radian), effectiveLength * Math.Cos(radian)); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); diffPos.X = -safeChange.X; diffPos.Y = safeChange.Y; } startPoint.X += diffPos.X; endPoint.Y += diffPos.Y; break; case DragPosition.LowerRight: if (KeepAspectRatio) { effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); var originSizeChange = new Point(effectiveLength * Math.Sin(radian), effectiveLength * Math.Cos(radian)); var safeChange = _restrictedSelectRect.GetSafeSizeChangeWhenKeepAspectRatio(dragPosition, currentSelectedRect, originSizeChange, UsedAspectRatio); diffPos.X = safeChange.X; diffPos.Y = safeChange.Y; } endPoint.X += diffPos.X; endPoint.Y += diffPos.Y; break; } if (!RectExtensions.IsSafeRect(startPoint, endPoint, MinSelectSize)) { if (KeepAspectRatio) { if ((endPoint.Y - startPoint.Y) < (_endY - _startY) || (endPoint.X - startPoint.X) < (_endX - _startX)) { return; } } else { var safeRect = RectExtensions.GetSafeRect(startPoint, endPoint, MinSelectSize, dragPosition); safeRect.Intersect(_restrictedSelectRect); startPoint = new Point(safeRect.X, safeRect.Y); endPoint = new Point(safeRect.X + safeRect.Width, safeRect.Y + safeRect.Height); } } var isEffectiveRegion = _restrictedSelectRect.IsSafePoint(startPoint) && _restrictedSelectRect.IsSafePoint(endPoint); var selectedRect = new Rect(startPoint, endPoint); if (!isEffectiveRegion) { if (_restrictedSelectRect.GetContainsRect(ref selectedRect)) { startPoint = new Point(selectedRect.Left, selectedRect.Top); endPoint = new Point(selectedRect.Right, selectedRect.Bottom); } else { return; } } selectedRect.Union(CanvasRect); if (selectedRect != CanvasRect) { var croppedRect = _inverseImageTransform.TransformBounds( new Rect(startPoint, endPoint)); croppedRect.Intersect(_restrictedCropRect); _currentCroppedRect = croppedRect; var viewportRect = CanvasRect.GetUniformRect(selectedRect.Width / selectedRect.Height); var viewportImgRect = _inverseImageTransform.TransformBounds(selectedRect); UpdateImageLayoutWithViewport(viewportRect, viewportImgRect); } else { UpdateSelectedRect(startPoint, endPoint); } }
/// <summary> /// Update cropped area. /// </summary> /// <param name="dragPosition">The control point</param> /// <param name="diffPos">Position offset</param> private void UpdateCroppedRectWithAspectRatio(DragPosition dragPosition, Point diffPos) { double radian = 0d, diffPointRadian = 0d, effectiveLength = 0d; if (KeepAspectRatio) { radian = Math.Atan(UsedAspectRatio); diffPointRadian = Math.Atan(diffPos.X / diffPos.Y); } var startPoint = new Point(_startX, _startY); var endPoint = new Point(_endX, _endY); switch (dragPosition) { case DragPosition.Top: startPoint.Y += diffPos.Y; if (KeepAspectRatio) { var changeX = diffPos.Y * UsedAspectRatio; startPoint.X += changeX / 2; endPoint.X -= changeX / 2; } break; case DragPosition.Bottom: endPoint.Y += diffPos.Y; if (KeepAspectRatio) { var changeX = diffPos.Y * UsedAspectRatio; startPoint.X -= changeX / 2; endPoint.X += changeX / 2; } break; case DragPosition.Left: startPoint.X += diffPos.X; if (KeepAspectRatio) { var changeY = diffPos.X / UsedAspectRatio; startPoint.Y += changeY / 2; endPoint.Y -= changeY / 2; } break; case DragPosition.Right: endPoint.X += diffPos.X; if (KeepAspectRatio) { var changeY = diffPos.X / UsedAspectRatio; startPoint.Y -= changeY / 2; endPoint.Y += changeY / 2; } break; case DragPosition.UpperLeft: if (KeepAspectRatio) { effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); diffPos.X = effectiveLength * Math.Sin(radian); diffPos.Y = effectiveLength * Math.Cos(radian); } startPoint.X += diffPos.X; startPoint.Y += diffPos.Y; break; case DragPosition.UpperRight: if (KeepAspectRatio) { diffPointRadian = -diffPointRadian; effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); diffPos.X = -effectiveLength *Math.Sin(radian); diffPos.Y = effectiveLength * Math.Cos(radian); } endPoint.X += diffPos.X; startPoint.Y += diffPos.Y; break; case DragPosition.LowerLeft: if (KeepAspectRatio) { diffPointRadian = -diffPointRadian; effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); diffPos.X = -effectiveLength *Math.Sin(radian); diffPos.Y = effectiveLength * Math.Cos(radian); } startPoint.X += diffPos.X; endPoint.Y += diffPos.Y; break; case DragPosition.LowerRight: if (KeepAspectRatio) { effectiveLength = diffPos.Y / Math.Cos(diffPointRadian) * Math.Cos(diffPointRadian - radian); diffPos.X = effectiveLength * Math.Sin(radian); diffPos.Y = effectiveLength * Math.Cos(radian); } endPoint.X += diffPos.X; endPoint.Y += diffPos.Y; break; } if (!RectExtensions.IsSafeRect(startPoint, endPoint, MinSelectSize)) { if (KeepAspectRatio) { if ((endPoint.Y - startPoint.Y) < (_endY - _startY) || (endPoint.X - startPoint.X) < (_endX - _startX)) { return; } } else { var safeRect = RectExtensions.GetSafeRect(startPoint, endPoint, MinSelectSize, dragPosition); safeRect.Intersect(_restrictedSelectRect); startPoint = new Point(safeRect.X, safeRect.Y); endPoint = new Point(safeRect.X + safeRect.Width, safeRect.Y + safeRect.Height); } } var isEffectiveRegion = _restrictedSelectRect.IsSafePoint(startPoint) && _restrictedSelectRect.IsSafePoint(endPoint); if (!isEffectiveRegion) { return; } var selectedRect = new Rect(startPoint, endPoint); selectedRect.Union(CanvasRect); if (selectedRect != CanvasRect) { var inverseImageTransform = _imageTransform.Inverse; if (inverseImageTransform == null) { return; } var croppedRect = inverseImageTransform.TransformBounds( new Rect(startPoint, endPoint)); croppedRect.Intersect(_restrictedCropRect); _currentCroppedRect = croppedRect; var viewportRect = CanvasRect.GetUniformRect(selectedRect.Width / selectedRect.Height); var viewportImgRect = inverseImageTransform.TransformBounds(selectedRect); UpdateImageLayoutWithViewport(viewportRect, viewportImgRect); } else { UpdateSelectedRect(startPoint, endPoint); } }