Example #1
0
        // Filling queue with ImagePrintItems that we will try to place into page.
        protected int FillQueue(PrintPageEventArgs e)
        {
            ImagePrintItem printItem;
            Size           pageSize        = new Size(_pageWidth - 1, _pageHeight - 1);
            int            maxCachedSquare = _pageWidth * _pageHeight * CachedSquareCoefficient,
                           queuedSquare = 0;

            if (queuedSquare < maxCachedSquare)
            {
                while ((printItem = base.GetNextItem(e)) != null && queuedSquare < maxCachedSquare)
                {
                    printItem.FitSize(pageSize, _printOptions.PlaceholderAutoRotate);

                    ItemRectangle itemRect = new ItemRectangle(printItem, _verticalSpacing, _horizontalSpacing);
                    queuedSquare += itemRect.Square;
                    _queuedItems.Add(itemRect);
                }
            }

            // If print was canceled
            if (e.Cancel == true)
            {
                _queuedItems.Clear();
                return(0);
            }

            _queuedItems.Sort();
            return(_queuedItems.Count);
        }
Example #2
0
        // Intersects or not 2 rectangles? Contact != intersection
        public bool Intersects(ItemRectangle rectangle)
        {
            if (rectangle.X >= RightX ||
                rectangle.Y >= BottomY ||
                rectangle.RightX <= _rect.X ||
                rectangle.BottomY <= _rect.Y)
            {
                return(false);
            }

            return(true);
        }
Example #3
0
        protected bool IsInPageBorders(ItemRectangle itemRectangle)
        {
            if (itemRectangle.X < _pageLeft ||
                itemRectangle.Y < _pageTop ||
                itemRectangle.RightX > _pageRight + _horizontalSpacing ||
                itemRectangle.BottomY > _pageBottom + _verticalSpacing)
            {
                return(false);
            }

            return(true);
        }
Example #4
0
 protected ItemRectangle GetQueuedItemAt(ref int index)
 {
     for (; index < _queuedItems.Count; index++)
     {
         ItemRectangle item = (ItemRectangle)_queuedItems[index];
         if (!item.Locked)
         {
             item.Locked = true;
             return(item);
         }
     }
     return(null);
 }
Example #5
0
        public int CalculateCoverage(ItemRectangle rectangle, out bool haveTouch)
        {
            int coverage = 0;
            int left0    = this.X,
                right0   = this.RightX,
                top0     = this.Y,
                bottom0  = this.BottomY;
            int left1    = rectangle.X,
                right1   = rectangle.RightX,
                top1     = rectangle.Y,
                bottom1  = rectangle.BottomY;

            // ...If no touch - exit
            if (left1 > right0 ||
                right1 < left0 ||
                top1 > bottom0 ||
                bottom1 < top0)
            {
                haveTouch = false;
                return(0);
            }

            // Top/bottom touch
            int max, min;

            if ((top0 == bottom1 || bottom0 == top1) && left1 <= right0 && right1 >= left0)
            {
                max       = Math.Max(left0, left1);
                min       = Math.Min(right0, right1);
                coverage += min - max + 1;
            }

            // Left/right touch
            if ((left0 == right1 || right0 == left1) && top1 <= bottom0 && bottom1 >= top0)
            {
                max       = Math.Max(top0, top1);
                min       = Math.Min(bottom0, bottom1);
                coverage += min - max + 1;
            }

            haveTouch = true;
            return(coverage);
        }
Example #6
0
        protected static void PlaceRectangle(int dip, Position dstPosition, ItemRectangle itemRectangle, ArrayList placedRectangles)
        {
            itemRectangle.MoveToPosition(dstPosition);

            // ...Generate all possible positions
            Position[] hostedPoints = new Position[4];

            // Left-top corner
            Point pnt = itemRectangle.Location;

            hostedPoints[0] = new Position(pnt);

            // Left-bottom corner
            pnt.Y          += itemRectangle.Height - 1;
            hostedPoints[1] = new Position(pnt);

            // Right-bottom corner
            pnt.X          += itemRectangle.Width - 1;
            hostedPoints[2] = new Position(pnt);

            // Right-top corner
            pnt             = itemRectangle.Location;
            pnt.X          += itemRectangle.Width - 1;
            hostedPoints[3] = new Position(pnt);

            // ...Closing position that is closed by the pItemRectangle himself
            hostedPoints[0].Close(dip, true);

            for (int i = 0; i < 4; i++)
            {
                // Closing closed positions in pPositionsArray
                IEnumerator neighboursEnumerator = itemRectangle.Neighbours.GetEnumerator();
                bool        toContinue           = true;
                while (neighboursEnumerator.MoveNext() && toContinue)
                {
                    ItemRectangle neighbour = (ItemRectangle)neighboursEnumerator.Current;
                    for (int j = 0; j < neighbour.HostedPositions.Count; j++)
                    {
                        Position neighbourPosition = (Position)neighbour.HostedPositions[j];

                        if (hostedPoints[i].EqualCoordinates(neighbourPosition))
                        {
                            if (hostedPoints[i].Closed(dip) || neighbourPosition.Closed(dip))
                            {
                                hostedPoints[i].Close(dip, true);
                                neighbourPosition.Close(dip, true);

                                toContinue = false;
                                break;
                            }
                            else
                            {
                                hostedPoints[i] = neighbourPosition;
                            }
                        }
                    }
                }
            }

            // ...Adding new possible positions into pPositions array, adding new placed rect.
            foreach (Position pos in hostedPoints)
            {
                if (!pos.Closed(dip))
                {
                    itemRectangle.HostedPositions.Add(pos);
                }
            }
            placedRectangles.Add(itemRectangle);
        }
Example #7
0
        // Returns true if rectangle could be placed into position. (also calculates perimeter coverage in the position).
        protected bool ExaminePosition(ArrayList placedRectangles, Position position, ItemRectangle itemRectangle, out int coverage)
        {
            // ----- Trying to place exact at specified position -----
            itemRectangle.MoveToPosition(position);
            itemRectangle.Neighbours.Clear();
            coverage = 0;

            // ...intersects with page borders?
            if (!IsInPageBorders(itemRectangle))
            {
                return(false);
            }

            // ...intersects with other rectangles?
            foreach (ItemRectangle placedRect in placedRectangles)
            {
                if (itemRectangle.Intersects(placedRect))
                {
                    return(false);
                }

                bool haveTouch;
                coverage += itemRectangle.CalculateCoverage(placedRect, out haveTouch);
                if (haveTouch)
                {
                    itemRectangle.Neighbours.Add(placedRect);
                }
            }

            // ...additional coverage values - when contacts page borders
            if (itemRectangle.X == _pageLeft)
            {
                coverage += itemRectangle.Height;
            }
            if (itemRectangle.Y == _pageTop)
            {
                coverage += itemRectangle.Width;
            }
            if (itemRectangle.RightX == _pageRight)
            {
                coverage += itemRectangle.Height;
            }
            if (itemRectangle.BottomY == _pageBottom)
            {
                coverage += itemRectangle.Width;
            }

            return(true);
        }
Example #8
0
        // Trying to place the rectangle at specified position and also checks some alternatives based
        // on specified position. The best position will be chosen.
        protected bool TryToPlaceRectangle(int dip, ArrayList placedRectangles, Position initialPosition, ItemRectangle itemRectangle, out int coverage, out Position resultPosition)
        {
            Point initialCoords = initialPosition.Coordinates;
            bool  placed        = false;

            Position[] altPositions = new Position[3];
            int        altCount     = 0;

            coverage       = 0;
            resultPosition = null;

            // Filling array of possible variants for item placement.
            // ...original position
            if (!initialPosition.Closed(dip))
            {
                altPositions[altCount++] = initialPosition;
            }

            // ...trying to go left and top
            int minLeftDistance  = initialCoords.X + 1,
                minUpperDistance = initialCoords.Y + 1,
                left,
                upper;
            bool leftPointMatch  = true,
                 upperPointMatch = false;

            // ...check position relative to other rectangles
            foreach (ItemRectangle rect in placedRectangles)
            {
                if (rect.Y <= initialCoords.Y && rect.BottomY >= initialCoords.Y && rect.RightX <= initialCoords.X)
                {
                    left = initialCoords.X - rect.RightX;
                    if (left < minLeftDistance)
                    {
                        minLeftDistance = left;
                        if (initialCoords.Y == rect.Y || initialCoords.Y == rect.BottomY)
                        {
                            leftPointMatch = true;
                        }
                        else
                        {
                            leftPointMatch = false;
                        }
                    }
                }
                else if (rect.X <= initialCoords.X && rect.RightX >= initialCoords.X && rect.BottomY <= initialCoords.Y)
                {
                    upper = initialCoords.Y - rect.BottomY;
                    if (upper < minUpperDistance)
                    {
                        minUpperDistance = upper;
                        if (initialCoords.X == rect.X || initialCoords.X == rect.RightX)
                        {
                            upperPointMatch = true;
                        }
                        else
                        {
                            upperPointMatch = false;
                        }
                    }
                }
            }

            // ...storing existing additional positions
            if (minLeftDistance > 0 && !leftPointMatch)
            {
                altPositions[altCount++] = new Position(initialCoords.X - minLeftDistance, initialCoords.Y);
            }
            if (minUpperDistance > 0 && !upperPointMatch)
            {
                altPositions[altCount++] = new Position(initialCoords.X, initialCoords.Y - minUpperDistance);
            }

            // Choosing best position among alternatives
            int maxCoverage = 0;

            for (int i = 0; i < altCount; i++)
            {
                if (ExaminePosition(placedRectangles, altPositions[i], itemRectangle, out coverage) && coverage > maxCoverage)
                {
                    placed         = true;
                    maxCoverage    = coverage;
                    resultPosition = altPositions[i];
                }
            }

            coverage = maxCoverage;
            return(placed);
        }
Example #9
0
        public override void FillPage(PrintPageEventArgs e, System.Collections.ArrayList items, System.Collections.ArrayList coords)
        {
            // Getting page parameters, filling queue of elements for placement
            InitializePage(e);
            int i, itemCount = FillQueue(e);

            if (itemCount == 0)
            {
                return;
            }

            // Preparing stack
            SearchStackFrame[] stack = new SearchStackFrame[_queuedItems.Count + 1];
            for (i = 0; i < stack.Length; i++)
            {
                stack[i] = new SearchStackFrame();
            }

            // Adding fake rectangle with first position
            ItemRectangle fakeRect = new ItemRectangle();

            fakeRect.Location = new Point(-100000, -100000);
            fakeRect.HostedPositions.Add(new Position(_pageLeft, _pageTop));
            stack[0].PlacedRectangles.Add(fakeRect);

            // Go! - there we will emulate recursion in plain loop. Deep is restricted by s_intMaxBranchingDepth,
            // after this level - just going straight forward without recursive search.
            ItemPlacement[] bestPlacement = new ItemPlacement[_queuedItems.Count];       // best reached result
            ArrayList       positions     = new ArrayList(256);                          // search positions for current level

            int bestSquare      = -1,
                framePointer    = 0,
                placedItemCount = 0;

            while (true)
            {
                // if the dip is over
                if (framePointer < 0)
                {
                    break;
                }

                // extracting and cleaning current level of the stack
                SearchStackFrame stackFrame = stack[framePointer];
                if (stackFrame.Item != null)
                {
                    stackFrame.Item.Locked = false;
                    stackFrame.Item        = null;
                }
                stackFrame.ActualQueueIndex = stackFrame.InitialQueueIndex;

                // searching at this level
                if (stackFrame.ProcessState < 2)
                {
                    positions.Clear();
                    foreach (ItemRectangle tmp1 in stackFrame.PlacedRectangles)
                    {
                        foreach (Position tmp2 in tmp1.HostedPositions)
                        {
                            tmp2.Close(framePointer, false);
                            if (!tmp2.Closed(framePointer))
                            {
                                positions.Add(tmp2);
                            }
                        }
                    }

                    bool placed = false;
                    while (!placed)
                    {
                        int maxCoverage = -1;
                        int coverage;

                        Position resPosition;

                        stackFrame.Item = GetQueuedItemAt(ref stackFrame.ActualQueueIndex);
                        if (stackFrame.Item == null)
                        {
                            break;
                        }

                        // Original item orientation
                        stackFrame.Rotate = stackFrame.Item.Rotated = (stackFrame.ProcessState == 1);
                        for (i = 0; i < positions.Count; i++)
                        {
                            Position position = (Position)positions[i];
                            if (TryToPlaceRectangle(framePointer, stackFrame.PlacedRectangles, position, stackFrame.Item, out coverage, out resPosition) && coverage > maxCoverage)
                            {
                                stackFrame.ItemPosition = resPosition;
                                maxCoverage             = coverage;
                                placed = true;
                            }
                        }

                        // Rotated orientation (performed if we cannot use full-search on current level)
                        if (_printOptions.PlaceholderAutoRotate && framePointer > MaxBranchingDeep)
                        {
                            stackFrame.Item.Rotated = true;
                            for (i = 0; i < positions.Count; i++)
                            {
                                Position position = (Position)positions[i];
                                if (position.Closed(framePointer))
                                {
                                    continue;
                                }

                                if (TryToPlaceRectangle(framePointer, stackFrame.PlacedRectangles, position, stackFrame.Item, out coverage, out resPosition) && coverage > maxCoverage)
                                {
                                    stackFrame.ItemPosition = resPosition;
                                    maxCoverage             = coverage;
                                    stackFrame.Rotate       = true;
                                    placed = true;
                                }
                            }
                        }

                        if (placed)
                        {
                            // Goto next level
                            if (framePointer <= MaxBranchingDeep && _printOptions.PlaceholderAutoRotate)
                            {
                                stackFrame.ProcessState++;
                            }
                            else
                            {
                                stackFrame.ProcessState = 2;
                            }

                            int nextFrame = framePointer + 1;
                            stack[nextFrame].ProcessState      = 0;
                            stack[nextFrame].Item              = null;
                            stack[nextFrame].Coverage          = stackFrame.Coverage + maxCoverage;
                            stack[nextFrame].Square            = stackFrame.Square + stackFrame.Item.Square;
                            stack[nextFrame].InitialQueueIndex = stackFrame.ActualQueueIndex + 1;
                            stack[nextFrame].PlacedRectangles.AddRange(stackFrame.PlacedRectangles);

                            stackFrame.Item.Rotated = stackFrame.Rotate;
                            PlaceRectangle(framePointer, stackFrame.ItemPosition, stackFrame.Item, stack[nextFrame].PlacedRectangles);
                            stackFrame.Item.Neighbours.Clear();

                            framePointer++;
                        }
                        else
                        {
                            stackFrame.Item.Locked = false;
                            stackFrame.Item        = null;
                            stackFrame.ActualQueueIndex++;
                        }
                    }

                    if (!placed)
                    {
                        if (stackFrame.Square > bestSquare)
                        {
                            placedItemCount = framePointer;
                            bestSquare      = stackFrame.Square;

                            for (i = 0; i < framePointer; i++)
                            {
                                bestPlacement[i].QueueIndex   = stack[i].ActualQueueIndex;
                                bestPlacement[i].ItemPosition = stack[i].ItemPosition;
                                bestPlacement[i].Rotate       = stack[i].Rotate;
                                bestPlacement[i].Item         = stack[i].Item;
                            }
                        }

                        framePointer--;
                    }
                }
                else
                {
                    framePointer--;
                }
            }

            // Returning best result to caller
            if (bestSquare > 0)
            {
                for (i = 0; i < placedItemCount; i++)
                {
                    ItemPlacement element = bestPlacement[i];

                    GetQueuedItemAt(ref element.QueueIndex);
                    element.Item.Rotated = element.Rotate;

                    coords.Add(ItemRectangle.GetItemLeftTopCorner(element.ItemPosition));
                    items.Add(element.Item.Detach());
                }
            }

            FlushQueueNonPlaced();
            e.HasMorePages = HasMorePages();
        }