public bool Intersect(RectangleNormal rect) { return !((this.left - rect.right >= -0.001f) || (rect.left - this.right >= -0.001f) || (this.top - rect.bottom >= -0.001f) || (rect.top - this.bottom >= -0.001f)); /*return !(this.left >= rect.right || rect.left >= this.right || this.top >= rect.bottom || rect.top >= this.bottom);*/ }
public bool Contains(RectangleNormal rect) { return ((rect.left - this.left >= -0.001f) && (this.right - rect.right >= -0.001f) && (rect.top - this.top >= -0.001f) && (this.bottom - rect.bottom >= -0.001f)); /*return (rect.left >= this.left && rect.right <= this.right && rect.top >= this.top && rect.bottom <= this.bottom);*/ }
public bool Contains(RectangleNormal rect) { return((rect.left - this.left >= -0.001f) && (this.right - rect.right >= -0.001f) && (rect.top - this.top >= -0.001f) && (this.bottom - rect.bottom >= -0.001f)); /*return (rect.left >= this.left * && rect.right <= this.right * && rect.top >= this.top * && rect.bottom <= this.bottom);*/ }
public bool Intersect(RectangleNormal rect) { return(!((this.left - rect.right >= -0.001f) || (rect.left - this.right >= -0.001f) || (this.top - rect.bottom >= -0.001f) || (rect.top - this.bottom >= -0.001f))); /*return !(this.left >= rect.right || rect.left >= this.right || this.top >= rect.bottom || rect.top >= this.bottom);*/ }
public override bool AddChild(Balloon generatedBalloon, bool isFromStatic, bool staticDockedBottomFlag) { RectangleNormal newRect = new RectangleNormal(); if(isFromStatic) { // add it to the list this.AddChildToList(generatedBalloon); } else { if(!this.GetNewRect(generatedBalloon, ref newRect)) { return false; } else { generatedBalloon.WidthInPixels = newRect.right - newRect.left; generatedBalloon.HeightInPixels = newRect.bottom - newRect.top; generatedBalloon.positionRect.top = newRect.top; generatedBalloon.positionRect.left = newRect.left; generatedBalloon.containerRect = newRect; this.AddChildToList(generatedBalloon); } // 1. ask for free space and get new rect for it // 2. in case there is no space // check for conditions to grow // try to grow this balloon (also parents). Return which one failed growing if anyone failed and return FALSE // if balloon grew goto 1. // if cannot grow return false // 3. in case there is enough space. // move new balloon to the rect position and set position and sizes to structure // add balloon to rect List and return true. } return true; }
public bool GetNewRectRightBottom(Balloon generatedBalloon, ref RectangleNormal outRect) { RectangleNormal resRect = new RectangleNormal(); RectangleNormal containRect = new RectangleNormal(); //RectangleNormal firstFound = null; //IEnumerator<RectangleNormal> tempEnum = null; //RectangleNormal tempRect; ////RectangleNormal intersectFound = null; //RectangleNormal maxXRect = null; //RectangleNormal minXRect = null; //RectangleNormal minYRect = null; //bool tmpB = false; // make rect to be at 0,0 position. 0,0 is top, left coordinate in this situation if(outRect == null) { return false; } resRect.left = 0; resRect.top = 0; resRect.right = generatedBalloon.WidthInPixels; resRect.bottom = generatedBalloon.HeightInPixels; containRect.left = 0; containRect.top = 0; containRect.right = this.WidthInPixels; containRect.bottom = this.HeightInPixels; //System.IO.TextWriter writer; // make grid from rectMatrix GeneratorGridCell[,] grid; int rowCount = 0; int colCount = 0; List<float> horizLines = new List<float>(); List<float> vertLines = new List<float>(); vertLines.Add(0.0f); vertLines.Add(containRect.right); horizLines.Add(0.0f); horizLines.Add(containRect.bottom); // Make rect lines foreach(RectangleNormal rect in this.rectMatrix) { // add to horiz lines if (!horizLines.Contains(rect.top)) { horizLines.Add(rect.top); } if (!horizLines.Contains(rect.bottom)) { horizLines.Add(rect.bottom); } // add vertical lines if (!vertLines.Contains(rect.left)) { vertLines.Add(rect.left); } if (!vertLines.Contains(rect.right)) { vertLines.Add(rect.right); } } colCount = vertLines.Count - 1; rowCount = horizLines.Count - 1; vertLines.Sort(); horizLines.Sort(); if (rowCount <= 0 || colCount <= 0) { resRect.MoveTo(0, 0); outRect.left = resRect.left; outRect.right = resRect.right; outRect.bottom = resRect.bottom; outRect.top = resRect.top; return true; } grid = new GeneratorGridCell[rowCount, colCount]; // fill grid foreach (RectangleNormal rect in this.rectMatrix) { int xind1 = vertLines.IndexOf(rect.left); int xind2 = vertLines.IndexOf(rect.right); int yind1 = horizLines.IndexOf(rect.top); int yind2 = horizLines.IndexOf(rect.bottom); for(int i = xind1; i < xind2; i++) { for(int j = yind1; j < yind2; j++) { grid[j, i].allocated = true; } } } // make coordinates for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { grid[i, j].sx = vertLines[j]; grid[i, j].sy = horizLines[i]; } } // if all rects all allocated then outRect should be set to bottom line bool allAlocated = true; for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { if (!grid[i, j].allocated) { allAlocated = false; break; } } } if (allAlocated) { // move this to bottom line in case all blocks are allocated resRect.left = 0; resRect.top = containRect.bottom; resRect.right = generatedBalloon.WidthInPixels; resRect.bottom = generatedBalloon.HeightInPixels; } else { // find first empty place for new rect for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { if (!grid[i, j].allocated) { // check if rect can be fitted here resRect.MoveTo(grid[i, j].sx, grid[i, j].sy); // check for any intersection with any rect bool anyIntersection = false; foreach (RectangleNormal tmpRect in this.rectMatrix) { if (tmpRect.Intersect(resRect)) { anyIntersection = true; break; } } if (!anyIntersection && containRect.Contains(resRect)) { outRect.left = resRect.left; outRect.right = resRect.right; outRect.bottom = resRect.bottom; outRect.top = resRect.top; return true; } } } } } if (Math.Abs(resRect.bottom - containRect.bottom) < Epsilon || resRect.bottom < containRect.bottom) { outRect.left = resRect.left; outRect.top = containRect.bottom; outRect.right = resRect.right; outRect.bottom = containRect.bottom + generatedBalloon.heightInPixels; } else { // make output as we are interested in last free position outRect.left = resRect.left; outRect.right = resRect.right; outRect.bottom = resRect.bottom; outRect.top = resRect.top; } return false; }
public bool GetNewRect(Balloon generatedBalloon, ref RectangleNormal outRect) { return this.GetNewRectRightBottom(generatedBalloon, ref outRect); }
public bool GrowBalloon(Balloon generatedBalloon, float growDelta) { RectangleNormal rect1 = new RectangleNormal(); RectangleNormal rect2 = new RectangleNormal(); Debug.Assert(growDelta >= -Epsilon , "Grow Delta Should never be negative"); // check what generate algorithm is used and do logic from that //if (generatedBalloon->generatingAlgorithm == GENERATING_ALGORITHM_RIGHT_BOTTOM) { // this means we can grow only on bottom. growDelta contains info how much we need to grow // 1. Grow Parent if can grow if(this.Parent != null) { // check if parent needs to grow at all // rect of parent rect1.top = 0; rect1.left = 0; rect1.right = this.Parent.WidthInPixels; rect1.bottom = this.Parent.HeightInPixels; //desired rect after growth. Growth to allow generatedBalloon to fall in rect2.left = this.positionRect.left; rect2.top = this.positionRect.top; rect2.bottom = (rect2.top + this.HeightInPixels + growDelta); rect2.right = (rect2.left + this.WidthInPixels); if(rect1.Contains(rect2)) { // check if we intersect some rectangle in rectMatrix and in case we do return false foreach(RectangleNormal rect in this.Parent.rectMatrix) { // if rect.top != rect2.top && rect.left != rect2.left - or if this is not the same rect which already has taken place // and if it does insterest something return false if (!(System.Math.Abs(rect.top - rect2.top) < Epsilon && System.Math.Abs(rect.left - rect2.left) < Epsilon) && rect.Intersect(rect2)) { return false; } } // we don't need to grow parent just increase size of self this.HeightInPixels += growDelta; this.containerRect.bottom += growDelta; } else { // can parent grow at all if(this.CanGrow) { // grow parent if(this.Parent is Balloon) { Balloon parentBallon = (Balloon)this.Parent; if(parentBallon.CanGrow && parentBallon.GrowBalloon(generatedBalloon, growDelta)) { this.HeightInPixels += growDelta; this.containerRect.bottom += growDelta; } else { return false; } } else { return false; } } else { // cannot increase size return FALSE return false; } } } else { // no parent ... grow in height by required size. this.HeightInPixels += growDelta; this.containerRect.bottom += growDelta; } this.positionRect.bottom = rect2.bottom; } //if (generatedBalloon->generatingAlgorithm == GENERATING_ALGORITHM_BOTTOM_RIGHT) //{ // // this means we can grow only on left // // TODO: Not implemented yet //} return true; }
/// <summary> /// Adds new child to this balloon and performs resize if necessary. /// /// </summary> /// <param name="generatedBalloon">newly created balloon that needs to fit into this one</param> /// <param name="staticBalloonFlag">this flag is true if generated balloon should be threated as static. if true /// then it is put exactly where it should be. If this is true staticDockedBottomFlag is ignored</param> /// <param name="staticDockedBottomFlag">Flag that tells if this should be threated as static bottom docked ballooon. </param> /// <returns></returns> public override bool AddChild(Balloon generatedBalloon, bool staticBalloonFlag, bool staticDockedBottomFlag) { RectangleNormal newRect = new RectangleNormal(); if(staticBalloonFlag) { // add it to the list this.AddChildToList(generatedBalloon); } else { // if there is no room for another child here if (this.FillCapacity > 0 && (this.DynamicChildBalloons + 1 > this.FillCapacity) && !staticDockedBottomFlag) { return false; } if(!this.GetNewRect(generatedBalloon, ref newRect)) { if(this.CanGrow) { // we established that balloon need to grow to put this new one inside and determined ammount of grow // we need to check if grow is allowed on parents side (maybe it is already taken on parents size and allocated in // rect matrix. this is checked before grow if(this.GrowBalloon(generatedBalloon, generatedBalloon.HeightInPixels - (this.HeightInPixels - newRect.top))) { return this.AddChild(generatedBalloon, staticBalloonFlag, staticDockedBottomFlag); } else { return false; } } else { return false; } } else { if (staticDockedBottomFlag && !this.FitToContent) { // in case this one is static docked bottom and we wont to put him on the bottom of this balloon newRect.top = this.containerRect.bottom - (newRect.bottom - newRect.top); newRect.bottom = this.containerRect.bottom; generatedBalloon.WidthInPixels = newRect.right - newRect.left; generatedBalloon.HeightInPixels = newRect.bottom - newRect.top; generatedBalloon.positionRect.top = newRect.top; generatedBalloon.positionRect.left = newRect.left; generatedBalloon.containerRect = newRect; } else { generatedBalloon.WidthInPixels = newRect.right - newRect.left; generatedBalloon.HeightInPixels = newRect.bottom - newRect.top; generatedBalloon.positionRect.top = newRect.top; generatedBalloon.positionRect.left = newRect.left; generatedBalloon.containerRect = newRect; } this.AddChildToList(generatedBalloon); } // 1. ask for free space and get new rect for it // 2. in case there is no space // check for conditions to grow // try to grow this balloon (also parents). Return which one failed growing if anyone failed and return FALSE // if balloon grew goto 1. // if cannot grow return false // 3. in case there is enough space. // move new balloon to the rect position and set position and sizes to structure // add balloon to rect List and return true. } return true; }