class Shape : ICloneable { public abstract Boolean same_size(Shape other); private double my_niche_count; // niche_count is the denominator in the RFS shared fitness calc. // Measures the total amount overlap between this square and all // others in the population. public double x // Accessor methods for this square's coordinates. { get { return location.x; } set { location.x = value; } } public double y { get { return location.y; } set { location.y = value; } } public double niche_count // Accessor methods for this shape's niche_count. { get { return my_niche_count; } set { my_niche_count = value; } } public double fitness // Accessor methods for this shape's RFS shared fitness. { get { return 1.0 / niche_count; } } public void move(double newX, double newY) // Changes the location of this shape { x = newX; y = newY; } public abstract double area_of(); public void randomize() // Move ourselves to random location within 800 by 600 area. { x = rFountain.NextDouble() * 800; char randomChar = (char)rFountain.Next(0, 2); y = rFountain.NextDouble() * 600; } // EXPENSIVE, but MOST GENERAL calculation of overlap // Needs "getBoundingRect()", "inside(int inX, int inY)" and // "getRectOfOverlap(Rectangle rect1, Rectangle rect2)" below. public virtual double area_of_overlap(Shape other) { double estimate = 0.0; Rectangle overlap_rect = getRectOfOverlap(getBoundingRect(), other.getBoundingRect()); for (int column = overlap_rect.X; column <= overlap_rect.X + overlap_rect.Width; column++) for (int row = overlap_rect.Y; row <= overlap_rect.Y + overlap_rect.Height; row++) if (inside(column, row) && other.inside(column, row)) estimate++; return estimate; } public abstract Rectangle getBoundingRect(); public abstract Boolean inside(int inX, int inY); public Rectangle getRectOfOverlap(Rectangle rect1, Rectangle rect2) { Rectangle upper, lower; if (rect1.Y <= rect2.Y) { upper = rect1; lower = rect2; } else { upper = rect2; lower = rect1; } if (lower.X <= upper.X) // If lower rect to the left of upper... if (lower.X + lower.Width <= upper.X // then if rects do NOT overlap then || upper.Y + upper.Height <= lower.Y) return new Rectangle(upper.X, lower.Y, 0, 0); // return a rect with no area else return new Rectangle(upper.X, // else return a rect with overlap... lower.Y, Math.Min(upper.Width, lower.X + lower.Width - upper.X), Math.Min(lower.Height, upper.Y + upper.Height - lower.Y)); else // lower is to right of upper... so ... if (upper.X + upper.Width <= lower.X // first check, if no overlap || upper.Y + upper.Height <= lower.Y) // then return return new Rectangle(upper.X, upper.Y, 0, 0); // a rect with no area else return new Rectangle(lower.X, lower.Y, Math.Min(lower.Width, upper.X + upper.Width - lower.X), Math.Min(lower.Height, upper.Y + upper.Height - lower.Y)); } }