public DNA(Stream stream, int shapes, int vertices) { Shapes = new Shape[shapes]; for (int i = 0; i < Shapes.Length; i++) { Shapes[i] = new Shape(stream, vertices); } }
public DNA(DNA other) { Shapes = new Shape[other.Shapes.Length]; for (int i = 0; i < Shapes.Length; i++) { Shapes[i] = new Shape(other.Shapes[i]); } Divergence = other.Divergence; }
public DNA(NBTag tag) { Divergence = tag["Divergence"].GetDouble(); var shapesTag = (NBTList)tag["Shapes"]; Shapes = new Shape[shapesTag.Tags.Length]; for (int i = 0; i < Shapes.Length; i++) { Shapes[i] = new Shape(shapesTag[i]); } }
public DNA Initialize( Random rand, TaskState task ) { DNA dna = new DNA { Shapes = new Shape[task.Shapes] }; int shapesPerSegment = task.Shapes / 9; int shapeCounter = 0; for( int i = 0; i < task.Shapes - shapesPerSegment * 9; i++ ) { Shape shape = new Shape { Color = Color.FromArgb( StartingAlpha, Color.R, Color.G, Color.B ), Points = new PointF[task.Vertices] }; for( int j = 0; j < shape.Points.Length; j++ ) { shape.Points[j] = new PointF( rand.NextFloat( -MaxOverlap, task.ImageWidth + MaxOverlap ), rand.NextFloat( -MaxOverlap, task.ImageHeight + MaxOverlap ) ); } dna.Shapes[i] = shape; shapeCounter++; } for( int x = 0; x < 3; x++ ) { for( int y = 0; y < 3; y++ ) { for( int i = 0; i < shapesPerSegment; i++ ) { Shape shape = new Shape { Color = Color.FromArgb( StartingAlpha, Color.R, Color.G, Color.B ), Points = new PointF[task.Vertices] }; for( int j = 0; j < shape.Points.Length; j++ ) { shape.Points[j] = new PointF( rand.NextFloat( task.ImageWidth / 3f * x - MaxOverlap, task.ImageWidth / 3f * ( x + 1 ) + MaxOverlap ), rand.NextFloat( task.ImageHeight / 3f * y - MaxOverlap, task.ImageHeight / 3f * ( y + 1 ) + MaxOverlap ) ); } dna.Shapes[shapeCounter] = shape; shapeCounter++; } } } return dna; }
static void MutateShape( Random rand, DNA dna, Shape shape, TaskState task ) { int maxOverlap = task.ProjectOptions.MaxOverlap; shape.PreviousState = shape.Clone() as Shape; switch( rand.Next( 9 ) ) { case 0: shape.Color = Color.FromArgb( (byte)rand.Next( task.ProjectOptions.MinAlpha, 256 ), shape.Color.R, shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.ReplaceColor; break; case 1: shape.Color = Color.FromArgb( shape.Color.A, (byte)rand.Next( 256 ), shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.ReplaceColor; break; case 2: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, (byte)rand.Next( 256 ), shape.Color.B ); dna.LastMutation = MutationType.ReplaceColor; break; case 3: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, shape.Color.G, (byte)rand.Next( 256 ) ); dna.LastMutation = MutationType.ReplaceColor; break; case 4: case 5: shape.Points[rand.Next( shape.Points.Length )].X = rand.NextFloat( -maxOverlap, task.ImageWidth + maxOverlap ); dna.LastMutation = MutationType.ReplacePoint; break; case 6: case 7: shape.Points[rand.Next( shape.Points.Length )].Y = rand.NextFloat( -maxOverlap, task.ImageHeight + maxOverlap ); dna.LastMutation = MutationType.ReplacePoint; break; case 8: shape.Points[rand.Next( shape.Points.Length )].X = rand.NextFloat( -maxOverlap, task.ImageWidth + maxOverlap ); shape.Points[rand.Next( shape.Points.Length )].Y = rand.NextFloat( -maxOverlap, task.ImageHeight + maxOverlap ); dna.LastMutation = MutationType.ReplacePoints; break; } }
// Randomly redistribute extra vertices by dividing edges of a given polygon static void Subdivide(Random rand, Shape shape, int extraVertices) { int points = shape.Points.Length; int assignedPoints = points - extraVertices; while (assignedPoints < points) { int p1 = rand.Next(0, assignedPoints); if (p1 == assignedPoints - 1) { shape.Points[assignedPoints] = Lerp(shape.Points[p1], shape.Points[0], 0.5f); } else { Array.Copy(shape.Points, p1 + 1, shape.Points, p1 + 2, assignedPoints - p1 - 1); shape.Points[p1 + 1] = Lerp(shape.Points[p1], shape.Points[p1 + 2], 0.5f); } assignedPoints++; } }
DNA IInitializer.Initialize( Random rand, TaskState task ) { DNA dna = new DNA { Shapes = new Shape[task.Shapes] }; for( int i = 0; i < dna.Shapes.Length; i++ ) { Shape shape = new Shape { Color = Color.FromArgb( StartingAlpha, Color.R, Color.G, Color.B ), Points = new PointF[task.Vertices] }; for( int j = 0; j < shape.Points.Length; j++ ) { shape.Points[j] = new PointF( rand.NextFloat( -MaxOverlap, task.ImageWidth + MaxOverlap ), rand.NextFloat( -MaxOverlap, task.ImageHeight + MaxOverlap ) ); } dna.Shapes[i] = shape; } return dna; }
void MutateMultiplePoints( Shape shape, Random rand, DNA dna, TaskState task ) { int index = rand.Next( shape.Points.Length ); shape.Points[index] = MutatePoint( rand, dna, shape.Points[index], task ); if( rand.Next( 2 ) == 0 ) { index = ( index + 1 ) % shape.Points.Length; shape.Points[index] = MutatePoint( rand, dna, shape.Points[index], task ); if( rand.Next( 2 ) == 0 ) { index = ( index + 1 ) % shape.Points.Length; shape.Points[index] = MutatePoint( rand, dna, shape.Points[index], task ); } dna.LastMutation = MutationType.ReplacePoints; } else { dna.LastMutation = MutationType.ReplacePoint; } }
void ScaleShape( Random rand, Shape shape, TaskState task ) { RectangleF rect = shape.GetBoundaries(); int maxOverlap = task.ProjectOptions.MaxOverlap; int maxWidth = (int)( Math.Min( rect.X, task.ImageWidth - rect.Right ) + rect.Width ) + maxOverlap * 2; int maxHeight = (int)( Math.Min( rect.Y, task.ImageHeight - rect.Bottom ) + rect.Height ) + maxOverlap * 2; double newWidthRatio = rand.Next( 3, maxWidth + 1 ) / rect.Width; double newHeightRatio = rand.Next( 3, maxHeight + 1 ) / rect.Height; if( PreserveAspectRatio ) { newWidthRatio = Math.Min( newWidthRatio, newHeightRatio ); newHeightRatio = newWidthRatio; } PointF rectCenter = new PointF { X = rect.X + rect.Width / 2f, Y = rect.Y + rect.Height / 2f }; for( int i = 0; i < shape.Points.Length; i++ ) { shape.Points[i].X = (float)( rectCenter.X + ( shape.Points[i].X - rectCenter.X ) * newWidthRatio ); shape.Points[i].Y = (float)( rectCenter.Y + ( shape.Points[i].Y - rectCenter.Y ) * newHeightRatio ); } }
static void RotateShape( Random rand, Shape shape ) { RectangleF rect = shape.GetBoundaries(); PointF rectCenter = new PointF { X = rect.X + rect.Width / 2, Y = rect.Y + rect.Height / 2 }; double rotation = rand.NextDouble() * Math.PI * 2; for( int i = 0; i < shape.Points.Length; i++ ) { float alignedX = shape.Points[i].X - rectCenter.X; float alignedY = shape.Points[i].Y - rectCenter.Y; shape.Points[i].X = (float)( rectCenter.X + alignedX * Math.Cos( rotation ) - alignedY * Math.Sin( rotation ) ); shape.Points[i].Y = (float)( rectCenter.Y + alignedX * Math.Sin( rotation ) + alignedY * Math.Cos( rotation ) ); } }
static void MoveShape( Random rand, Shape shape, TaskState task ) { RectangleF rect = shape.GetBoundaries(); int maxOverlap = task.ProjectOptions.MaxOverlap; PointF delta = new PointF { X = rand.NextFloat( -rect.X - maxOverlap, task.ImageWidth - rect.Right + maxOverlap ), Y = rand.NextFloat( -rect.Y - maxOverlap, task.ImageHeight - rect.Bottom + maxOverlap ) }; for( int i = 0; i < shape.Points.Length; i++ ) { shape.Points[i].X += delta.X; shape.Points[i].Y += delta.Y; } }
static void ChangeColor( Random rand, Shape shape, TaskState task ) { shape.PreviousState = shape.Clone() as Shape; switch( rand.Next( 4 ) ) { case 0: shape.Color = Color.FromArgb( rand.NextByte( task.ProjectOptions.MinAlpha, 256 ), shape.Color.R, shape.Color.G, shape.Color.B ); break; case 1: shape.Color = Color.FromArgb( shape.Color.A, rand.NextByte(), shape.Color.G, shape.Color.B ); break; case 2: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, rand.NextByte(), shape.Color.B ); break; case 3: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, shape.Color.G, rand.NextByte() ); break; } }
void ChangeColor( Random rand, Shape shape, TaskState task ) { shape.PreviousState = shape.Clone() as Shape; int delta = rand.NextByte( 1, (int)( MaxColorDelta + 1 ) ) * ( rand.Next( 2 ) == 0 ? 1 : -1 ); switch( rand.Next( 4 ) ) { case 0: shape.Color = Color.FromArgb( Math.Max( task.ProjectOptions.MinAlpha, Math.Min( 255, shape.Color.A + delta ) ), shape.Color.R, shape.Color.G, shape.Color.B ); break; case 1: shape.Color = Color.FromArgb( shape.Color.A, Math.Max( 0, Math.Min( 255, shape.Color.R + delta ) ), shape.Color.G, shape.Color.B ); break; case 2: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, Math.Max( 0, Math.Min( 255, shape.Color.G + delta ) ), shape.Color.B ); break; case 3: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, shape.Color.G, Math.Max( 0, Math.Min( 255, shape.Color.B + delta ) ) ); break; } }
void bImportDNA_Click(object sender, EventArgs e) { DNAImportWindow win = new DNAImportWindow(); if (win.ShowDialog() == DialogResult.OK) { Reset(); try { string[] parts = win.DNA.Split(' '); Stop(); State.Vertices = Int32.Parse(parts[0]); State.Shapes = Int32.Parse(parts[1]); nVertices.Value = State.Vertices; nPolygons.Value = State.Shapes; DNA importedDNA = new DNA { Shapes = new Shape[State.Shapes] }; int offset = 2; for (int s = 0; s < State.Shapes; s++) { Shape shape = new Shape { Points = new PointF[State.Vertices] }; int r = Int32.Parse(parts[offset]); int g = Int32.Parse(parts[offset + 1]); int b = Int32.Parse(parts[offset + 2]); int a = (int)(float.Parse(parts[offset + 3])*255); shape.Color = Color.FromArgb(a, r, g, b); offset += 4; for (int v = 0; v < State.Vertices; v++) { float X = float.Parse(parts[offset]); float Y = float.Parse(parts[offset + 1]); shape.Points[v] = new PointF(X, Y); offset += 2; } importedDNA.Shapes[s] = shape; } State.CurrentMatch = importedDNA; State.BestMatch = importedDNA; State.SetEvaluator(State.Evaluator); UpdateTick(); picBestMatch.Invalidate(); picDiff.Invalidate(); } catch (FormatException ex) { MessageBox.Show("Could not import DNA!" + Environment.NewLine + ex); } } }
public DNA Initialize(Random rand, TaskState task) { var dna = new DNA { Shapes = new Shape[task.Shapes] }; for (int s = 0; s < task.Shapes; s++) { var shape = new Shape { Color = Color.FromArgb(StartingAlpha, Color.R, Color.G, Color.B), Points = new PointF[task.Vertices] }; int maxRadius = (int)Math.Round(Math.Min(task.ImageWidth, task.ImageHeight)*MaxRadiusRatio); int radius = rand.Next(MinRadius, maxRadius); var center = new Point(rand.Next(radius - MaxOverlap, task.ImageWidth - radius + MaxOverlap), rand.Next(radius - MaxOverlap, task.ImageHeight - radius + MaxOverlap)); for (int v = 0; v < task.Vertices; v++) { double t = v*Math.PI*2*Revolutions/task.Vertices + Angle*Math.PI*2 + Math.PI/task.Vertices; shape.Points[v].X = (float)(center.X + Math.Cos(t)*radius); shape.Points[v].Y = (float)(center.Y + Math.Sin(t)*radius); } if (shape.GetBoundaries().Width < 1 || shape.GetBoundaries().Height < 1) { continue; } dna.Shapes[s] = shape; } return dna; }
// Take a polygon and divide it into two, using the slot of a sacrificial polygon for second half public void DivideShape(Random rand, int shapeToDivide, int shapeToSacrifice) { Shape original = Shapes[shapeToDivide]; int points = original.Points.Length; // Figure out which dividing vertex produces the shortest dividing edge. PointF divisionVertex1 = default(PointF); PointF divisionVertex2 = default(PointF); double shortestDividingEdgeLength = Double.MaxValue; Shape shifted = original; for (int shiftAmount = 0; shiftAmount < points; shiftAmount++) { Shape shiftedGuess = ShiftPoints(original, shiftAmount); // Find the two dividing vertices PointF vertexGuess1; if (points%2 == 1) { // odd number of points vertexGuess1 = shiftedGuess.Points[points/2]; } else { // even number of points vertexGuess1 = Lerp(shiftedGuess.Points[points/2 - 1], shiftedGuess.Points[points/2], 0.5f); } PointF vertexGuess2 = Lerp(shiftedGuess.Points[0], shiftedGuess.Points[points - 1], 0.5f); double dividingEdgeLength = Math.Sqrt((vertexGuess1.X - vertexGuess2.X)*(vertexGuess1.X - vertexGuess2.X) + (vertexGuess1.Y - vertexGuess2.Y)*(vertexGuess1.Y - vertexGuess2.Y)); if (dividingEdgeLength < shortestDividingEdgeLength) { shortestDividingEdgeLength = dividingEdgeLength; shifted = shiftedGuess; divisionVertex1 = vertexGuess1; divisionVertex2 = vertexGuess2; } } var half1 = new Shape(shifted); var half2 = new Shape(shifted); // Construct half-shape #1 half1.Points[0] = divisionVertex1; half1.Points[1] = divisionVertex2; for (int i = 0; i < points/2; i++) { half1.Points[i + 2] = shifted.Points[i]; } // Construct half-shape #2 half2.Points[0] = divisionVertex2; half2.Points[1] = divisionVertex1; for (int i = 0; i < points/2; i++) { half2.Points[i + 2] = shifted.Points[points/2 + i + 1]; } // Randomly redistribute extra vertices for each half (if there are any) int extraVertices = (points - 3)/2; Subdivide(rand, half1, extraVertices); Subdivide(rand, half2, extraVertices); // Write back the changes Shapes[shapeToDivide] = half1; Shapes[shapeToSacrifice] = half2; half1.OutlineColor = Color.Green; half2.OutlineColor = Color.Red; ShiftShapeIndex(shapeToSacrifice, shapeToDivide); }
static void RandomizeShape( Random rand, Shape shape, TaskState task ) { int maxOverlap = task.ProjectOptions.MaxOverlap; shape.PreviousState = shape.Clone() as Shape; shape.Color = Color.FromArgb( rand.Next( task.ProjectOptions.MinAlpha, 256 ), rand.Next( 256 ), rand.Next( 256 ), rand.Next( 256 ) ); for( int i = 0; i < shape.Points.Length; i++ ) { shape.Points[i] = new PointF( rand.NextFloat( -maxOverlap, task.ImageWidth + maxOverlap ), rand.NextFloat( -maxOverlap, task.ImageHeight + maxOverlap ) ); } }
void MutateShape( Random rand, DNA dna, Shape shape, TaskState task ) { shape.PreviousState = shape.Clone() as Shape; int colorDelta = (byte)rand.Next( 1, MaxColorDelta + 1 ) * ( rand.Next( 2 ) == 0 ? 1 : -1 ); switch( rand.Next( 10 ) ) { case 0: shape.Color = Color.FromArgb( Math.Max( task.ProjectOptions.MinAlpha, Math.Min( 255, shape.Color.A + colorDelta ) ), shape.Color.R, shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.AdjustColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; case 1: shape.Color = Color.FromArgb( shape.Color.A, Math.Max( 0, Math.Min( 255, shape.Color.R + colorDelta ) ), shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.AdjustColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; case 2: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, Math.Max( 0, Math.Min( 255, shape.Color.G + colorDelta ) ), shape.Color.B ); dna.LastMutation = MutationType.AdjustColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; case 3: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, shape.Color.G, Math.Max( 0, Math.Min( 255, shape.Color.B + colorDelta ) ) ); dna.LastMutation = MutationType.AdjustColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; default: MutateMultiplePoints( shape, rand, dna, task ); break; } }
void MutateShape( Random rand, DNA dna, Shape shape, TaskState task ) { shape.PreviousState = shape.Clone() as Shape; switch( rand.Next( 10 ) ) { case 0: shape.Color = Color.FromArgb( (byte)rand.Next( task.ProjectOptions.MinAlpha, 256 ), shape.Color.R, shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.ReplaceColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; case 1: shape.Color = Color.FromArgb( shape.Color.A, rand.NextByte(), shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.ReplaceColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; case 2: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, rand.NextByte(), shape.Color.B ); dna.LastMutation = MutationType.ReplaceColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; case 3: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, shape.Color.G, rand.NextByte() ); dna.LastMutation = MutationType.ReplaceColor; if( rand.Next( 10 ) == 0 ) { MutateMultiplePoints( shape, rand, dna, task ); dna.LastMutation = MutationType.ReplaceShape; } break; default: MutateMultiplePoints( shape, rand, dna, task ); break; } }
static Shape ShiftPoints(Shape shape, int shift) { var copy = new Shape(shape); int offset = shift%shape.Points.Length; Array.Copy(shape.Points, offset, copy.Points, 0, shape.Points.Length - offset); Array.Copy(shape.Points, 0, copy.Points, shape.Points.Length - offset, offset); return copy; }
void MutateShape( Random rand, DNA dna, Shape shape, TaskState task ) { int maxOverlap = task.ProjectOptions.MaxOverlap; shape.PreviousState = shape.Clone() as Shape; int colorDelta = (byte)rand.Next( 1, MaxColorDelta + 1 ) * ( rand.Next( 2 ) == 0 ? 1 : -1 ); float posDelta = (float)rand.NextDouble() * MaxPosDelta * ( rand.Next( 2 ) == 0 ? 1 : -1 ); switch( rand.Next( 9 ) ) { case 0: shape.Color = Color.FromArgb( Math.Max( task.ProjectOptions.MinAlpha, Math.Min( 255, shape.Color.A + colorDelta ) ), shape.Color.R, shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.AdjustColor; break; case 1: shape.Color = Color.FromArgb( shape.Color.A, Math.Max( 0, Math.Min( 255, shape.Color.R + colorDelta ) ), shape.Color.G, shape.Color.B ); dna.LastMutation = MutationType.AdjustColor; break; case 2: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, Math.Max( 0, Math.Min( 255, shape.Color.G + colorDelta ) ), shape.Color.B ); dna.LastMutation = MutationType.AdjustColor; break; case 3: shape.Color = Color.FromArgb( shape.Color.A, shape.Color.R, shape.Color.G, Math.Max( 0, Math.Min( 255, shape.Color.B + colorDelta ) ) ); dna.LastMutation = MutationType.AdjustColor; break; case 4: case 5: int pt1 = rand.Next( shape.Points.Length ); shape.Points[pt1].X = Math.Max( -maxOverlap, Math.Min( task.ImageWidth - 1 + maxOverlap, shape.Points[pt1].X + posDelta ) ); dna.LastMutation = MutationType.AdjustPoint; break; case 6: case 7: int pt2 = rand.Next( shape.Points.Length ); shape.Points[pt2].Y = Math.Max( -maxOverlap, Math.Min( task.ImageHeight - 1 + maxOverlap, shape.Points[pt2].Y + posDelta ) ); dna.LastMutation = MutationType.AdjustPoint; break; case 8: int pt3 = rand.Next( shape.Points.Length ); shape.Points[pt3].X = Math.Max( -maxOverlap, Math.Min( task.ImageWidth - 1 + maxOverlap, shape.Points[pt3].X + posDelta ) ); shape.Points[pt3].Y = Math.Max( -maxOverlap, Math.Min( task.ImageHeight - 1 + maxOverlap, shape.Points[pt3].Y + posDelta ) ); dna.LastMutation = MutationType.AdjustPoints; break; } }
public Shape( Shape other ) { Color = other.Color; Points = (PointF[])other.Points.Clone(); OutlineColor = other.OutlineColor; }