public override void RegenerateShapes() { Point endpoint = getPoint(ThetaMax, nGroup * (DominoLength + NormalDistance) / a); double end_radius = Math.Sqrt(endpoint.X * endpoint.X + endpoint.Y * endpoint.Y); List <PathDomino> dominolist = new List <PathDomino>(); double pi2 = 1 / (2d * Math.PI); // spart ein paar Gleitkommadivisionen for (int i = 0; i < nGroup; i++) { double shift = i * (DominoLength + NormalDistance) / a; shift = shift - shiftfactor * nGroup * (DominoLength + NormalDistance) / a; double theta = ThetaMin; int ycounter = 0; double current_radius = 0; while (closeEnds ? current_radius < end_radius : theta < ThetaMax) { Point current_point = getPoint(theta, i * (DominoLength + NormalDistance) / a); current_radius = Math.Sqrt(current_point.X * current_point.X + current_point.Y * current_point.Y); for (int k = 0; k < nArms; k++) { PathDomino d = CreateDomino(theta, shift, 2.0 * Math.PI / nArms * k); //d.position = new ProtocolDefinition(); //d.position.y = (int)Math.Floor((theta - theta_min) * pi2); //d.position.x = ycounter; dominolist.Add(d); } double start_value = theta; double theta_new; do { start_value += 0.01d; theta_new = approximate_archimedean(theta, start_value, TangentialDistance + DominoWidth, shift); }while (theta_new < theta); ycounter++; if ((int)Math.Floor((theta - ThetaMin) * pi2) != (int)Math.Floor((theta_new - ThetaMin) * pi2)) { ycounter = 0; } theta = theta_new; } } IDominoShape[] dominoes = dominolist.ToArray(); DominoRectangle[] containers = dominoes.AsParallel().Select(x => x.GetContainer()).ToArray(); double x_min = containers.Min(x => x.x); double y_min = containers.Min(x => x.y); double x_max = containers.Max(x => x.width + x.x); double y_max = containers.Max(x => x.height + x.y); Parallel.For(0, dominoes.Length, (i) => { dominoes[i] = dominoes[i].TransformDomino(-x_min, -y_min, 0, 0, 0, 0); }); last = new DominoTransfer(dominoes, colors); shapesValid = true; }
public override void RegenerateShapes() { PathDomino[][] dominos = new PathDomino[Circles][]; Parallel.For(0, Circles, new ParallelOptions() { MaxDegreeOfParallelism = -1 }, (circlecount) => { int diameter = StartDiameter + circlecount * (2 * DominoWidth + 2 * NormalDistance); double domino_angle = Math.Asin((double)DominoLength / diameter) * 2; double distance_angle = Math.Asin((double)TangentialDistance / diameter) * 2; int current_domino_count = (int)Math.Floor(2 * Math.PI / ((double)domino_angle + distance_angle)); current_domino_count = (int)Math.Floor((double)current_domino_count / _force_divisibilty) * _force_divisibilty; // equally space the distance between all dominoes distance_angle = (2 * Math.PI - (domino_angle * current_domino_count)) / current_domino_count; // calculate dominoes double angle = (double)AngleShiftFactor * circlecount; dominos[circlecount] = new PathDomino[current_domino_count]; for (int i = 0; i < current_domino_count; i++) { PathDomino d = GenerateDomino(diameter, angle); angle += domino_angle + distance_angle; d.position = new ProtocolDefinition() { x = i, y = circlecount }; dominos[circlecount][i] = d; } }); IDominoShape[] dominoes = dominos.SelectMany(x => x).ToArray(); DominoRectangle[] containers = dominoes.AsParallel().Select(x => x.GetContainer()).ToArray(); double x_min = containers.Min(x => x.x); double y_min = containers.Min(x => x.y); double x_max = containers.Max(x => x.width + x.x); double y_max = containers.Max(x => x.height + x.y); Parallel.For(0, dominoes.Length, (i) => { dominoes[i] = dominoes[i].TransformDomino(-x_min, -y_min, 0, 0, 0, 0); }); last = new DominoTransfer(dominoes, colors); shapesValid = true; }
public override void RegenerateShapes() { Last = new DominoTransfer(getNewShapes(Length, Height), colors); shapesValid = true; }
public override void Calculate(DominoTransfer shapes, int charLength, CancellationToken ct) { LastValid = true; }
public abstract void Calculate(DominoTransfer shapes, int charLength, CancellationToken ct);
/// <summary> /// Weist jedem Shape die ideale Farbe zu, basierend auf den festgelegten Eigenschaften. /// </summary> /// <returns>ein Int-Array mit den Farbindizes</returns> internal override void CalculateColors() { var colors = this.colors.RepresentionForCalculation; //if (!shapesValid) throw new InvalidOperationException("Current shapes are invalid!"); IterationInformation.weights = Enumerable.Repeat(1.0, colors.Length).ToArray(); RTree <IDominoShape> tree = new RTree <IDominoShape>(9, new GuttmannQuadraticSplit <IDominoShape>()); // wird nur beim Dithering benötigt und nur dann ausgeführt; sortiert alle Shapes nach deren Mittelpunktskoordinate // erst nach x, bei gleichem x nach y var list = shapes.dominoes.OrderByDescending(x => { var container = x.GetContainer(); return(container.y + container.height / 2); }).ThenBy(x => { var container = x.GetContainer(); return(container.x + container.width / 2); }).ToList(); if (ditherMode.weights.GetLength(0) + ditherMode.weights.GetLength(1) > 2) { for (int i = 0; i < shapes.dominoes.Length; i++) { tree.Insert(shapes.dominoes[i]); } } for (int iter = 0; iter < IterationInformation.maxNumberOfIterations; iter++) { if (ditherMode.weights.GetLength(0) + ditherMode.weights.GetLength(1) > 2) { double extent_r = (ditherMode.matrix_width - ditherMode.start_first_row) * charLength; double extent_l = (ditherMode.start_first_row - 1) * charLength; double extent_u = (ditherMode.matrix_height - 1) * charLength; // ditherColors im Baum ersetzen for (int i = 0; i < list.Count; i++) { list[i].ditherColor = list[i].originalColor; } for (int i = 0; i < list.Count; i++) { var originalColor = list[i].ditherColor; list[i].CalculateColor(colors, colorMode, TransparencySetting, IterationInformation.weights); // Abweichung der beiden Farben bestimmen int fehler_r = (int)(originalColor.Red - colors[list[i].color].mediaColor.R); int fehler_g = (int)(originalColor.Green - colors[list[i].color].mediaColor.G); int fehler_b = (int)(originalColor.Blue - colors[list[i].color].mediaColor.B); // bestimme Abmessungen des Suchbereichs DominoRectangle orig = list[i].getBoundingRectangle(); double orig_x = orig.x + orig.width / 2; double orig_y = orig.y + orig.height / 2; DominoRectangle viewport = new DominoRectangle() { x = orig_x - extent_l, y = orig_y - extent_u, width = extent_r + extent_l, height = extent_u }; var result = tree.Search(viewport); var weights = new double[result.Count]; // Rohgewichte aller gefundenen Shapes finden for (int j = 0; j < result.Count; j++) { var bounding = result[j].getBoundingRectangle(); // alle rausschmeißen, die nicht komplett im Viewport liegen double center_x = bounding.x + bounding.width / 2; double center_y = bounding.y + bounding.height / 2; // überprüfen, ob das Shape schon abgearbeitet wurde if (center_y == orig_y && center_x <= orig_x) { continue; } if (center_y > orig_y) { continue; } weights[j] = ditherMode.Weight((center_x - orig_x) / charLength, (orig_y - center_y) / charLength); } var divisor = weights.Sum(); if (divisor == 0) { } for (int j = 0; j < result.Count; j++) { if (weights[j] == 0) { continue; } ditherMode.AddToPixel(result[j], (int)(fehler_r * weights[j] / divisor), (int)(fehler_g * weights[j] / divisor), (int)(fehler_b * weights[j] / divisor)); } } } else { ResetDitherColors(shapes.dominoes); IterationInformation.numberofiterations = iter; Console.WriteLine($"Iteration {iter}"); CancellationTokenSource cts = new CancellationTokenSource(); Parallel.For(0, shapes.dominoes.Length, new ParallelOptions() { MaxDegreeOfParallelism = -1, CancellationToken = cts.Token }, (i) => { try { shapes.dominoes[i].CalculateColor(colors, colorMode, TransparencySetting, IterationInformation.weights); } catch (Exception) { cts.Cancel(); } }); } // Farben zählen IterationInformation.EvaluateSolution(colors.ToArray(), shapes.dominoes); if (IterationInformation.colorRestrictionsFulfilled != false) { break; } } last = new DominoTransfer(shapes.dominoes, this.colors); }