using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Markup; namespace ComPDFKit.Tool { /// /// Help class for calculating the alignment position of the rectangle /// public class AlignmentsHelp { /// /// Set the source rectangle to be left-aligned in the target rectangle /// /// /// Origin rectangle /// /// /// Target rectangle /// /// /// X Y direction distance required for alignment of the source rectangle /// public static Point SetAlignLeft(Rect src, Rect dst) { Point movePoint = new Point(dst.Left - src.Left, 0); return movePoint; } /// /// Set the source rectangle to be horizontally centered in the target rectangle /// /// /// Origin rectangle /// /// /// Target rectangle /// /// /// X Y direction distance required for alignment of the source rectangle /// public static Point SetAlignHorizonCenter(Rect src, Rect dst) { Point movePoint = new Point((dst.Left + dst.Right - src.Left - src.Right) / 2, 0); return movePoint; } /// /// Right-align the source rectangle in the target rectangle /// /// /// Origin rectangle /// /// /// Target rectangle /// /// /// X Y direction distance required for alignment of the source rectangle /// public static Point SetAlignRight(Rect src, Rect dst) { Point movePoint = new Point(dst.Right - src.Width - src.Left, 0); return movePoint; } /// /// Set the source rectangle to be top-aligned in the target rectangle /// /// /// Origin rectangle /// /// /// Target rectangle /// /// /// X Y direction distance required for alignment of the source rectangle /// public static Point SetAlignTop(Rect src, Rect dst) { Point movePoint = new Point(0, dst.Top - src.Top); return movePoint; } /// /// Set the source rectangle to be vertically centered in the target rectangle /// /// /// Origin rectangle /// /// /// Target rectangle /// /// /// X Y direction distance required for alignment of the source rectangle /// public static Point SetAlignVerticalCenter(Rect src, Rect dst) { Point movePoint = new Point(0, (dst.Bottom + dst.Top - src.Top - src.Bottom) / 2); return movePoint; } /// /// Set the source rectangle to be horizontally and vertically centered in the target rectangle /// /// /// Origin rectangle /// /// /// Target rectangle /// /// /// X Y direction distance required for alignment of the source rectangle /// public static Point SetAlignHorizonVerticalCenter(Rect src, Rect dst) { Point movePoint = new Point((dst.Left + dst.Right - src.Left - src.Right) / 2, (dst.Bottom + dst.Top - src.Top - src.Bottom) / 2); return movePoint; } /// /// Set the source rectangle to be bottom-aligned in the target rectangle /// /// /// Origin rectangle /// /// /// Target rectangle /// /// /// X Y direction distance required for alignment of the source rectangle /// public static Point SetAlignBottom(Rect src, Rect dst) { Point movePoint = new Point(0, dst.Bottom - src.Height - src.Top); return movePoint; } /// /// Set the source rectangle to be horizontally distributed and aligned in the target rectangle /// /// /// Array of source rectangles needed /// /// /// Target rectangle /// /// /// Dictionary of XY direction distance required for alignment of each source rectangle /// public static Dictionary SetDistributeHorizontal(List src, Rect dst) { Dictionary dictionary = new Dictionary(); List Leftlist = new List(); // Sort the data according to the leftmost position of each rectangle, not the array order foreach (Rect srcRect in src) { Leftlist.Add(srcRect.Left + srcRect.Width / 2); } double[] datalist = Leftlist.ToArray(); Sort(datalist, 0, Leftlist.Count - 1); double startX = dst.Left; double endX = dst.Right; double interval = (endX - startX) / Leftlist.Count; for (int i = 0; i < datalist.Count(); i++) { int index = Leftlist.IndexOf(datalist[i]); Point movePoint = new Point(startX + i * interval - src[index].Left - src[index].Width / 2, 0); dictionary.Add(src[index], movePoint); } return dictionary; } /// /// Vertically distribute the source rectangles within the target rectangle (sorting based on the leftmost position of each rectangle, not the array order) /// /// /// Array of source rectangles needed /// /// /// Target rectangle /// /// /// Dictionary of XY direction distance required for alignment of each source rectangle /// public static Dictionary SetDistributeVertical(List src, Rect dst) { Dictionary dictionary = new Dictionary(); List Leftlist = new List(); // Sort the data according to the leftmost position of each rectangle, not the array order foreach (Rect srcRect in src) { Leftlist.Add(srcRect.Left + srcRect.Width / 2); } double[] datalist = Leftlist.ToArray(); Sort(datalist, 0, Leftlist.Count - 1); double startY = dst.Top; double endY = dst.Bottom; double interval = (endY - startY) / Leftlist.Count; for (int i = 0; i < datalist.Count(); i++) { int index = Leftlist.IndexOf(datalist[i]); Point movePoint = new Point(0, startY + i * interval - src[index].Top - src[index].Height / 2); dictionary.Add(src[index], movePoint); } return dictionary; } /// /// Set the source rectangle to a horizontal distribution and align it within the target rectangle to maintain consistent gaps /// /// /// Array of source rectangles needed /// /// /// Target rectangle /// /// /// Dictionary of XY direction distance required for alignment of each source rectangle /// public static Dictionary SetGapDistributeHorizontal(List src, Rect dst) { Dictionary dictionary = new Dictionary(); List Leftlist = new List(); // Sort the data according to the leftmost position of each rectangle, not the array order double weight = 0; foreach (Rect srcRect in src) { double left = srcRect.Left; if (Leftlist.Contains(left)) { left += src.IndexOf(srcRect) * 0.01; } Leftlist.Add(left); weight += srcRect.Width; } double[] datalist = Leftlist.ToArray(); Sort(datalist, 0, Leftlist.Count - 1); double startX = dst.Left; double endX = dst.Right; double interval = ((endX - startX) - weight) / (Leftlist.Count - 1); for (int i = 0; i < datalist.Count(); i++) { int index = Leftlist.IndexOf(datalist[i]); Point movePoint = new Point(); if (i == 0 || i == datalist.Count() - 1) { movePoint = new Point(0, 0); } else { double width = 0; for (int f = 0; f < i; f++) { int index2 = 0; if (f != 0) { index2 = Leftlist.IndexOf(datalist[i - 1]); width += src[index2].Width; } int index0 = Leftlist.IndexOf(datalist[0]); if (f == 0) { width += src[index0].Right; } width += interval; } movePoint = new Point(width - src[index].X , 0); } dictionary.Add(src[index], movePoint); } return dictionary; } /// /// Vertically distribute source rectangles within the target rectangle to maintain consistent gaps (sorted by the leftmost position of each rectangle, rather than array order) /// /// /// Array of source rectangles needed /// /// /// Target rectangle /// /// /// Dictionary of XY direction distance required for alignment of each source rectangle /// public static Dictionary SetGapDistributeVertical(List src, Rect dst) { Dictionary dictionary = new Dictionary(); List Leftlist = new List(); // Sort the data according to the leftmost position of each rectangle, not the array order double tall = 0; foreach (Rect srcRect in src) { double top = srcRect.Top; if (Leftlist.Contains(top)) { top += src.IndexOf(srcRect)*0.01; } Leftlist.Add(top); tall += srcRect.Height; } double[] datalist = Leftlist.ToArray(); Sort(datalist, 0, Leftlist.Count - 1); double startY = dst.Top; double endY = dst.Bottom; double interval = ((endY - startY) - tall) / (Leftlist.Count - 1); for (int i = 0; i < datalist.Count(); i++) { int index = Leftlist.IndexOf(datalist[i]); Point movePoint = new Point(); if (i == 0 || i == datalist.Count() - 1) { movePoint = new Point(0, 0); } else { double height = 0; for (int f = 0; f < i; f++) { int index2 = 0; if (f != 0) { index2 = Leftlist.IndexOf(datalist[i - 1]); height += src[index2].Height; } int index0 = Leftlist.IndexOf(datalist[0]); if (f == 0) { height += src[index0].Bottom; } height +=interval; } movePoint = new Point(0, height - src[index].Y); } dictionary.Add(src[index], movePoint); } return dictionary; } #region Quick sort private static int SortUnit(double[] array, int low, int high) { double key = array[low]; while (low < high) { // Search backward for values smaller than the key while (array[high] >= key && high > low) --high; // Put the value smaller than key on the left array[low] = array[high]; // Search forward for values larger than the key while (array[low] <= key && high > low) ++low; // Put the value larger than key on the right array[high] = array[low]; } // Left is smaller than key, right is larger than key. // Put the key in the current position of the cursor // At this point, 'low' equals 'high array[low] = key; return high; } private static void Sort(double[] array, int low, int high) { if (low >= high) return; // Finish a single unit sort int index = SortUnit(array, low, high); // Sort the left unit Sort(array, low, index - 1); // Sort the right unit Sort(array, index + 1, high); } #endregion } }