/// <summary> /// Retrieves a sequence of adjacent horizontal same-color segments /// </summary> /// <param name="field">from this field</param> /// <param name="y"></param> /// <returns></returns> static SpanList GetSpansFromLine(Field field, int y) { SpanList result = new SpanList(); Color currentElement = field[0, y]; Span current = new Span() { StartX = 0, Y = y, Color = currentElement }; for (int x = 1; x < field.Size.Width; x++) { if (field[x, y] != currentElement) { currentElement = field[x, y]; current.EndX = x - 1; result.Add(current); current = new Span() { StartX = x, Y = y, Color = currentElement }; } } current.EndX = field.Size.Width - 1; result.Add(current); return(result); }
public void ShiftGenerations(ConnectedComponentSet complete) { // add first generation to the second Spans.UnionWith(FrontalSpans); // if the Generation 0 hasn't been filled, // it means the component is complete and won't grow anymore if (NewFrontalSpans.Count == 0) { // add it to the list of complete components complete.Add(this); } else { // Generation 0 grows older and becomes Generation 1 FrontalSpans = NewFrontalSpans; // And a new Generation 0 is born NewFrontalSpans = new SpanList(); } }
/// <summary> /// Calculates and returns a set of 4-connected components in a field /// </summary> /// <param name="field">The two-dimensional matrix with colors</param> /// <returns></returns> public static ConnectedComponentSet FindConnectedComponents(Field field) { ConnectedComponentSet result = new ConnectedComponentSet(); ConnectedComponentSet current = new ConnectedComponentSet(); // we scan the entire matrix line by line for (int y = 0; y < field.Size.Height; y++) { SpanList spansOnCurrentLine = GetSpansFromLine(field, y); foreach (var span in spansOnCurrentLine) { PlaceSpan(span, current); } // check which components didn't change since the previous iteration ConnectedComponentSet complete = new ConnectedComponentSet(); foreach (var component in current) { component.ShiftGenerations(complete); } foreach (var component in complete) { component.FrontalSpans.Clear(); current.Remove(component); result.Add(component); } } // We reached the bottom // For all the remaining components, add them to the result foreach (var component in current) { component.Spans.UnionWith(component.FrontalSpans); component.Spans.UnionWith(component.NewFrontalSpans); result.Add(component); } return(result); }
public ConnectedComponent() { Spans = new SpanList(); FrontalSpans = new SpanList(); NewFrontalSpans = new SpanList(); }
public void UnionWith(SpanList otherSpans) { this.AddRange(otherSpans); }