public void TestBarelyFittingRectangle() { CygonRectanglePacker packer = new CygonRectanglePacker(128, 128); Point placement = packer.Pack(128, 128); Assert.AreEqual(new Point(0, 0), placement); }
/// <summary> /// This method adds the collection of views to the existing ViewSheet and packs them /// </summary> /// <param name="views"></param> private void InternalAddViewsToSheetView(IEnumerable <Autodesk.Revit.DB.View> views) { var sheet = InternalViewSheet; TransactionManager.Instance.EnsureInTransaction(Document); // (sic) from Dynamo Legacy var width = sheet.Outline.Max.U - sheet.Outline.Min.U; var height = sheet.Outline.Max.V - sheet.Outline.Min.V; var packer = new CygonRectanglePacker(width, height); int count = 0; foreach (var view in views) { var viewWidth = view.Outline.Max.U - view.Outline.Min.U; var viewHeight = view.Outline.Max.V - view.Outline.Min.V; Autodesk.Revit.DB.UV placement = null; if (packer.TryPack(viewWidth, viewHeight, out placement)) { var dbViews = sheet.GetAllPlacedViews().Select(x => Document.GetElement(x)). OfType <Autodesk.Revit.DB.View>(); if (dbViews.Contains(view)) { //move the view //find the corresponding viewport var enumerable = DocumentManager.Instance.ElementsOfType <Autodesk.Revit.DB.Viewport>() .Where(x => x.SheetId == sheet.Id && x.ViewId == view.Id).ToArray(); if (!enumerable.Any()) { continue; } var viewport = enumerable.First(); viewport.SetBoxCenter(new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } else { //place the view on the sheet if (Autodesk.Revit.DB.Viewport.CanAddViewToSheet(Document, sheet.Id, view.Id)) { var viewport = Autodesk.Revit.DB.Viewport.Create(Document, sheet.Id, view.Id, new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } } } else { throw new Exception(String.Format("View {0} could not be packed on the Sheet. The sheet is {1} x {2} and the view to be added is {3} x {4}", count, width, height, viewWidth, viewHeight)); } count++; } TransactionManager.Instance.TransactionTaskDone(); }
public void TestTooLargeRectangle() { CygonRectanglePacker packer = new CygonRectanglePacker(128, 128); Point placement; bool result = packer.TryPack(129, 10, out placement); Assert.IsFalse(result); result = packer.TryPack(10, 129, out placement); Assert.IsFalse(result); }
protected override Size ArrangeOverride(Size finalSize) { if (Children.Count != 0) { double top = 0; double left = 0; double width = _tileWidth; double height = _tileHeight; Size spacing = _tileSpacing; bool first = true; var crp = new CygonRectanglePacker(finalSize.Width, finalSize.Height); var sizedElements = Children.OrderBy(child => child.DesiredSize.Area()).Reverse(); foreach (UIElement element in sizedElements) { if (element.Visibility != Visibility.Collapsed) { Point placement; crp.TryPack(element.DesiredSize.Width, element.DesiredSize.Height, out placement); Rect finalRect = new Rect(placement, element.DesiredSize); element.Arrange(finalRect); //element.SetValue(BoundsProperty, finalRect); //if(first == false) //{ // left += spacing.Width; //} //ArrangeElement(element, new Rect(left, top, width, height)); //left = left + width; //if((left + spacing.Width + width) > finalSize.Width) //{ // left = 0; // top += height + spacing.Height; // first = true; //} //else //{ // first = false; //} } element.RenderTransform = new CompositeTransform() { Rotation = _rnd.Next(-5, 5), CenterX = element.DesiredSize.Width / 2, CenterY = element.DesiredSize.Height / 2, //TranslateX = _rnd.Next((int)-(element.DesiredSize.Width / 10), (int)(element.DesiredSize.Width / 10)), //TranslateY = _rnd.Next((int)-(element.DesiredSize.Height / 10), (int)(element.DesiredSize.Height / 10)) }; } } return(finalSize); }
protected override Size ArrangeOverride(Size finalSize) { if(Children.Count != 0) { double top = 0; double left = 0; double width = _tileWidth; double height = _tileHeight; Size spacing = _tileSpacing; bool first = true; var crp = new CygonRectanglePacker(finalSize.Width, finalSize.Height); var sizedElements = Children.OrderBy(child => child.DesiredSize.Area()).Reverse(); foreach(UIElement element in sizedElements) { if(element.Visibility != Visibility.Collapsed) { Point placement; crp.TryPack(element.DesiredSize.Width, element.DesiredSize.Height, out placement); Rect finalRect = new Rect(placement, element.DesiredSize); element.Arrange(finalRect); //element.SetValue(BoundsProperty, finalRect); //if(first == false) //{ // left += spacing.Width; //} //ArrangeElement(element, new Rect(left, top, width, height)); //left = left + width; //if((left + spacing.Width + width) > finalSize.Width) //{ // left = 0; // top += height + spacing.Height; // first = true; //} //else //{ // first = false; //} } element.RenderTransform = new CompositeTransform() { Rotation = _rnd.Next(-5, 5), CenterX = element.DesiredSize.Width / 2, CenterY = element.DesiredSize.Height / 2, //TranslateX = _rnd.Next((int)-(element.DesiredSize.Width / 10), (int)(element.DesiredSize.Width / 10)), //TranslateY = _rnd.Next((int)-(element.DesiredSize.Height / 10), (int)(element.DesiredSize.Height / 10)) }; } } return finalSize; }
/* * Constructor for Engine class * @param side, an int of the lenght of a side. Only one as it works with a square * @param images, a collection of ImageInfo objects * Takes a collection of images and trys to fit them to a square, * increasing the size of square if they don't fit */ public Engine(int side, IEnumerable <ImageInfo> images) { /// Collection of images not fitting List <ImageInfo> dontFit = new List <ImageInfo>(); /// A check of whether all images are mapped bool check = true; while (check) { /// Initalise a packer object packer = new CygonRectanglePacker(side, side); /// Creating a Point object, for positioning images Point placement; /// Iterates through images, and trys to place it on the square foreach (ImageInfo image in images) { /// Checking to see if it fits, else it is added to dontFit if (packer.TryPack(image.Width, image.Height, out placement)) { image.Position = placement; }//end if else { dontFit.Add(image); } //end else } // end foreach /// If images didn't fit, the loop will go again, otherwise it will finsih if (dontFit.Count == 0) { check = false; }// end if else { side = side * 2; dontFit.Clear(); }// end else } /// Initalising size with final square side lenght size = side; }
public static List <Point> ByCoordinateSystems(IEnumerable <BoundingBox> boundingBoxes, double width, double height, double gap) { var locs = new List <Point>(); var packer = new CygonRectanglePacker(width, height); foreach (var bbox in boundingBoxes) { var packLocation = UV.ByCoordinates(); var w = bbox.MaxPoint.X - bbox.MinPoint.X + gap; var h = bbox.MaxPoint.Y - bbox.MinPoint.Y + gap; if (packer.TryPack(w, h, out packLocation)) { locs.Add(Point.ByCoordinates(packLocation.U, packLocation.V, 0)); } } return(locs); }
private bool TryPacking(IEnumerable <Window> windows, double scale) { var packer = new CygonRectanglePacker(Width, Height); foreach (var window in windows) { try { var rect = window.Rectangle; var ts = (rect.Width * rect.Height < 10000) ? 1.0 : scale; // show tiny windows at full size window.TargetRectangle = new Rectangle( packer.Pack((int)(rect.Width * ts), (int)(rect.Height * ts)), new Size((int)(rect.Width * ts), (int)(rect.Height * ts))); } catch { return(false); } } return(true); }
/// <summary> /// Collect information about the images and bin pack them using the chosen algorithm /// </summary> /// <param name="imagesInfo"></param> /// <param name="spriteSize"></param> public void GetImagesInfo(out List<SpriteImageItem> imagesInfo, out Size spriteSize, int padding) { imagesInfo = new List<SpriteImageItem>(); // calculate initial sprite size to optimize process speed // -> make sure that the widest and the tallest images fit // -> make sure the resulting area is the same as the sum of all images area int maxW = 0; int maxH = 0; //int totalArea = 0; foreach (var file in GetFiles()) { var image = Image.FromFile(file.FullName); imagesInfo.Add(new SpriteImageItem() { Image = image, Name = file.Name }); if (image.Width > maxW) maxW = image.Width; if (image.Height > maxH) maxH = image.Height; //totalArea = image.Width * image.Height; } int finalW = 0; int finalH = 0; //int totalW = (int)Math.Ceiling((decimal)totalArea / 2); //int totalH = totalW; finalW = maxW;// maxW > totalW ? maxW : totalW; finalH = maxH; // maxH > totalH ? maxH : totalH; List<SpriteImageItem> unfitImagesInfo = new List<SpriteImageItem>(); bool finished = false; while (!finished) { // start packing process RectanglePacker packer = null; switch (this.Options.BinPackingLevel) { case 1: // faster and less compless algorithm packer = new SimpleRectanglePacker(finalW, finalH); break; case 2: // still fast and much better packing algorithm packer = new CygonRectanglePacker(finalW, finalH); break; case 3: // the best packing algorithm. Addicional processing time might not be noticeable packer = new ArevaloRectanglePacker(finalW, finalH); break; default: // default packer = new CygonRectanglePacker(finalW, finalH); break; } //var usedArea = 0; foreach (var iInfo in imagesInfo) { // Find a place for a rectangle of size 30x20 in the packing area Point placement; if (packer.TryPack(iInfo.Image.Width + padding, iInfo.Image.Height + padding, out placement)) { iInfo.Position = placement; //usedArea += iInfo.Image.Width * iInfo.Image.Height; } else { unfitImagesInfo.Add(iInfo); } } if (unfitImagesInfo.Count == 0) { finished = true; } else { // add the diff between the used area and the remaining images area //var extraW = 0; //var extraH = 0; //foreach (var unfit in unfitImagesInfo) //{ // extraW += unfit.Image.Width; // extraH += unfit.Image.Height; //} // after some tests the speed and result are quite the same as adding a few more pixels to the // sprite final size and run the whole process again finalW += 10; finalH += 10; unfitImagesInfo.Clear(); } } spriteSize = new Size(finalW, finalH); }
public override Value Evaluate(FSharpList <Value> args) { var name = ((Value.String)args[0]).Item; var number = ((Value.String)args[1]).Item; var tb = (FamilySymbol)((Value.Container)args[2]).Item; if (!args[3].IsList) { throw new Exception("The views input must be a list of views."); } var views = ((Value.List)args[3]).Item; Autodesk.Revit.DB.ViewSheet sheet = null; if (this.Elements.Any()) { if (dynUtils.TryGetElement(this.Elements[0], out sheet)) { if (sheet.Name != null && sheet.Name != name) { sheet.Name = name; } if (number != null && sheet.SheetNumber != number) { sheet.SheetNumber = number; } } else { //create a new view sheet sheet = Autodesk.Revit.DB.ViewSheet.Create(dynRevitSettings.Doc.Document, tb.Id); sheet.Name = name; sheet.SheetNumber = number; Elements[0] = sheet.Id; } } else { sheet = Autodesk.Revit.DB.ViewSheet.Create(dynRevitSettings.Doc.Document, tb.Id); sheet.Name = name; sheet.SheetNumber = number; Elements.Add(sheet.Id); } //rearrange views on sheets //first clear the collection of views on the sheet //sheet.Views.Clear(); var width = sheet.Outline.Max.U - sheet.Outline.Min.U; var height = sheet.Outline.Max.V - sheet.Outline.Min.V; var packer = new CygonRectanglePacker(width, height); foreach (var val in views) { var view = (View)((Value.Container)val).Item; var viewWidth = view.Outline.Max.U - view.Outline.Min.U; var viewHeight = view.Outline.Max.V - view.Outline.Min.V; UV placement = null; if (packer.TryPack(viewWidth, viewHeight, out placement)) { if (sheet.Views.Contains(view)) { //move the view //find the corresponding viewport var collector = new FilteredElementCollector(dynRevitSettings.Doc.Document); collector.OfClass(typeof(Viewport)); var found = collector.ToElements() .Cast <Viewport>() .Where(x => x.SheetId == sheet.Id && x.ViewId == view.Id); var enumerable = found as Viewport[] ?? found.ToArray(); if (!enumerable.Any()) { continue; } var viewport = enumerable.First(); viewport.SetBoxCenter(new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } else { //place the view on the sheet if (Viewport.CanAddViewToSheet(dynRevitSettings.Doc.Document, sheet.Id, view.Id)) { var viewport = Viewport.Create(dynRevitSettings.Doc.Document, sheet.Id, view.Id, new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } } } else { throw new Exception("View could not be packed on sheet."); } } return(Value.NewContainer(sheet)); }
public override Value Evaluate(FSharpList<Value> args) { var name = ((Value.String)args[0]).Item; var number = ((Value.String)args[1]).Item; var tb = (FamilySymbol)((Value.Container)args[2]).Item; if (!args[3].IsList) throw new Exception("The views input must be a list of views."); var views = ((Value.List)args[3]).Item; Autodesk.Revit.DB.ViewSheet sheet = null; if (this.Elements.Any()) { if (dynUtils.TryGetElement(this.Elements[0], out sheet)) { if(sheet.Name != null && sheet.Name != name) sheet.Name = name; if(number != null && sheet.SheetNumber != number) sheet.SheetNumber = number; } else { //create a new view sheet sheet = Autodesk.Revit.DB.ViewSheet.Create(dynRevitSettings.Doc.Document, tb.Id); sheet.Name = name; sheet.SheetNumber = number; Elements[0] = sheet.Id; } } else { sheet = Autodesk.Revit.DB.ViewSheet.Create(dynRevitSettings.Doc.Document, tb.Id); sheet.Name = name; sheet.SheetNumber = number; Elements.Add(sheet.Id); } //rearrange views on sheets //first clear the collection of views on the sheet //sheet.Views.Clear(); var width = sheet.Outline.Max.U - sheet.Outline.Min.U; var height = sheet.Outline.Max.V - sheet.Outline.Min.V; var packer = new CygonRectanglePacker(width, height); foreach (var val in views) { var view = (View)((Value.Container) val).Item; var viewWidth = view.Outline.Max.U - view.Outline.Min.U; var viewHeight = view.Outline.Max.V - view.Outline.Min.V; UV placement = null; if (packer.TryPack(viewWidth, viewHeight, out placement)) { if (sheet.Views.Contains(view)) { //move the view //find the corresponding viewport var collector = new FilteredElementCollector(dynRevitSettings.Doc.Document); collector.OfClass(typeof (Viewport)); var found = collector.ToElements() .Cast<Viewport>() .Where(x => x.SheetId == sheet.Id && x.ViewId == view.Id); var enumerable = found as Viewport[] ?? found.ToArray(); if (!enumerable.Any()) continue; var viewport = enumerable.First(); viewport.SetBoxCenter(new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } else { //place the view on the sheet if (Viewport.CanAddViewToSheet(dynRevitSettings.Doc.Document, sheet.Id, view.Id)) { var viewport = Viewport.Create(dynRevitSettings.Doc.Document, sheet.Id, view.Id, new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } } } else { throw new Exception("View(s) do not fit on sheet."); } } return Value.NewContainer(sheet); }
protected override Size MeasureOverride(Size availableSize) { if (Children.Count == 0) { return(new Size(0, 0)); } var crp = new CygonRectanglePacker(availableSize.Width, availableSize.Height); foreach (UIElement element in Children) { element.Measure(Infinite); Point placement; crp.TryPack(element.DesiredSize.Width, element.DesiredSize.Height, out placement); } //var sizedElements = Children.OrderBy(child => child.DesiredSize.Area()).Reverse.ToList(); _tileWidth = Children .Where(child => child.Visibility != Visibility.Collapsed) .Max(child => child.DesiredSize.Width); _tileHeight = Children .Where(child => child.Visibility != Visibility.Collapsed) .Max(child => child.DesiredSize.Height); double top = 0; double left = 0; bool first = true; foreach (UIElement element in Children) { if (element.Visibility != Visibility.Collapsed) { if (first == false) { left += _tileSpacing.Width; } left += _tileWidth; if ((left + _tileSpacing.Width + _tileWidth) > availableSize.Width) { left = 0; top += _tileHeight + _tileSpacing.Height; first = true; } else { first = false; } } } if (left == 0) { return(new Size(availableSize.Width, top)); } //return new Size(double.IsPositiveInfinity(availableSize.Width) ? _tileWidth*4 : availableSize.Width, top + _tileHeight); return(new Size( double.IsPositiveInfinity(availableSize.Width) ? _tileWidth * 3.5 : availableSize.Width, double.IsPositiveInfinity(availableSize.Height) ? _tileHeight * 2 : availableSize.Height)); }
/// <summary> /// This method adds the collection of views to the existing ViewSheet and packs them /// </summary> /// <param name="views"></param> private void InternalAddViewsToSheetView(IEnumerable<Autodesk.Revit.DB.View> views) { var sheet = InternalViewSheet; TransactionManager.Instance.EnsureInTransaction(Document); // (sic) from Dynamo Legacy var width = sheet.Outline.Max.U - sheet.Outline.Min.U; var height = sheet.Outline.Max.V - sheet.Outline.Min.V; var packer = new CygonRectanglePacker(width, height); int count = 0; foreach (var view in views) { var viewWidth = view.Outline.Max.U - view.Outline.Min.U; var viewHeight = view.Outline.Max.V - view.Outline.Min.V; Autodesk.Revit.DB.UV placement = null; if (packer.TryPack(viewWidth, viewHeight, out placement)) { if (sheet.Views.Contains(view)) { //move the view //find the corresponding viewport var enumerable = DocumentManager.Instance.ElementsOfType<Autodesk.Revit.DB.Viewport>() .Where(x => x.SheetId == sheet.Id && x.ViewId == view.Id).ToArray(); if (!enumerable.Any()) continue; var viewport = enumerable.First(); viewport.SetBoxCenter(new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } else { //place the view on the sheet if (Viewport.CanAddViewToSheet(Document, sheet.Id, view.Id)) { var viewport = Viewport.Create(Document, sheet.Id, view.Id, new XYZ(placement.U + viewWidth / 2, placement.V + viewHeight / 2, 0)); } } } else { throw new Exception( String.Format("View {0} could not be packed on the Sheet. The sheet is {1} x {2} and the view to be added is {3} x {4}", count, width, height, viewWidth, viewHeight)); } count++; } TransactionManager.Instance.TransactionTaskDone(); }
public void TestThrowOnTooLargeRectangle() { CygonRectanglePacker packer = new CygonRectanglePacker(128, 128); Assert.Throws<OutOfSpaceException>( delegate() { packer.Pack(129, 129); } ); }
protected override Size MeasureOverride(Size availableSize) { if(Children.Count == 0) { return new Size(0, 0); } var crp = new CygonRectanglePacker(availableSize.Width, availableSize.Height); foreach(UIElement element in Children) { element.Measure(Infinite); Point placement; crp.TryPack(element.DesiredSize.Width, element.DesiredSize.Height, out placement); } //var sizedElements = Children.OrderBy(child => child.DesiredSize.Area()).Reverse.ToList(); _tileWidth = Children .Where(child => child.Visibility != Visibility.Collapsed) .Max(child => child.DesiredSize.Width); _tileHeight = Children .Where(child => child.Visibility != Visibility.Collapsed) .Max(child => child.DesiredSize.Height); double top = 0; double left = 0; bool first = true; foreach(UIElement element in Children) { if(element.Visibility != Visibility.Collapsed) { if(first == false) { left += _tileSpacing.Width; } left += _tileWidth; if((left + _tileSpacing.Width + _tileWidth) > availableSize.Width) { left = 0; top += _tileHeight + _tileSpacing.Height; first = true; } else { first = false; } } } if(left == 0) { return new Size(availableSize.Width, top); } //return new Size(double.IsPositiveInfinity(availableSize.Width) ? _tileWidth*4 : availableSize.Width, top + _tileHeight); return new Size( double.IsPositiveInfinity(availableSize.Width) ? _tileWidth*3.5 : availableSize.Width, double.IsPositiveInfinity(availableSize.Height) ? _tileHeight * 2 : availableSize.Height); }
private bool TryPacking(IEnumerable<Window> windows, double scale) { var packer = new CygonRectanglePacker(Width, Height); foreach (var window in windows) { try { var rect = window.Rectangle; var ts = (rect.Width * rect.Height < 10000) ? 1.0 : scale; // show tiny windows at full size window.TargetRectangle = new Rectangle( packer.Pack((int)(rect.Width * ts), (int)(rect.Height * ts)), new Size((int)(rect.Width * ts), (int)(rect.Height * ts))); } catch { return false; } } return true; }