/************************************************************ * CONSTRUCTORS/DESTRUCTORS AND FIELD MANIPULATORS * ************************************************************/ public ClosestPair() { InitializeComponent(); X_MAX = Panel1.Width + 10; Y_MAX = Panel1.Height + 10; DELAY = 100; North = new PointSet(); South = new PointSet(); East = new PointSet(); West = new PointSet(); rand = new Random(); isSplit = new System.Drawing.Point(); }
public double ClosestPairDQ(PointSet S, ref PointSet current) { if (S.points.Count <= 1) { S.dmin = inf; } else { // calculate co-ordinates of median point int median = (int)Math.Ceiling((decimal)S.points.Count / 2); Point M = S.pointAt(median - 1); // calculate two subproblems (median in first subset) PointSet S1 = subSet(S, 0, median - 1); PointSet S2 = subSet(S, median, S.points.Count - 1); // highlight the whole set if (DELAY > 50) { drawField(S, Color.Cyan); drawVertical(M, Color.Blue); pause(DELAY); eraseVertical(M); eraseField(S); } // recursively calculate solutions to sub-problems S.dmin = Math.Min(ClosestPairDQ(S1, ref current), ClosestPairDQ(S2, ref current)); // highlight the whole set, and solutions for each subset if (DELAY > 50) { drawField(S, Color.Cyan); drawVertical(M, Color.Blue); pause(DELAY); } // merge two sub-solutions S = merge(S, S1, S2, ref current); // highlight set in gray b/c solution has been computed if (DELAY > 50) { eraseVertical(M); eraseField(S); drawField(S, Color.LightGray); pause(DELAY); } } return S.dmin; }
public ClosestPair(int delay) { InitializeComponent(); X_MAX = Panel1.Width; Y_MAX = Panel1.Height; DELAY = delay; North = new PointSet(); South = new PointSet(); East = new PointSet(); West = new PointSet(); rand = new Random(); distance.Left = 0; distance.Top = 0; isSplit = new System.Drawing.Point(); }
// Test a point Q in P's bounding box PointSet testBoundingBoxPoint(PointSet S, Point P, Point Q) { double d = dist(P, Q); if (d < S.dmin) { // update minimal distance S.dmin = d; if (S.closestPair.Count == 0) { S.closestPair.Add(P); S.closestPair.Add(Q); } else { S.closestPair[0] = P; S.closestPair[1] = Q; } // flash the segment to show that a new minimal distance was found if (DELAY > 50) { for (int i = 0; i < 3; i++) { eraseSegment(P, Q, Color.Yellow); pause((int)(DELAY / 2)); drawSegment(P, Q); pause((int)(DELAY / 2)); } } } return S; }
/*********************************************************************** * DIVIDE-AND-CONQUER ALGORITHM + FUNCTIONS * ***********************************************************************/ public double ClosestPairDQ(PointSet S) { return ClosestPairDQ(S, ref S); }
private bool SameColor(PointSet ps) { if (ps.closestPair.Count > 1) { if (ps.closestPair[0].color == ps.closestPair[1].color) return true; } return false; }
private void Panel1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { Point p; if (isSplit.X != 0) { if (radioButton1.Checked) { p = new Point(e.X, e.Y, 0); } else if (radioButton2.Checked) { p = new Point(e.X, e.Y, 1); } else { p = new Point(e.X, e.Y, rand.Next(0, 2)); } if (e.X > 0 && e.X < isSplit.X) { //west if (e.Y > 0 && e.Y < isSplit.Y) { North.add(p); } else { West.add(p); } } else { //east if (e.Y > 0 && e.Y < isSplit.Y) { East.add(p); } else { South.add(p); } } } else { if (radioButton1.Checked) { p = new Point(e.X, e.Y, 0); } else if (radioButton2.Checked) { p = new Point(e.X, e.Y, 1); } else { p = new Point(e.X, e.Y, rand.Next(0, 2)); } North.add(p); } drawPoint(p); } else if (e.Button == MouseButtons.Right) { if (isSplit.X == 0) { isSplit.X = e.X; isSplit.Y = e.Y; Graphics g = Panel1.CreateGraphics(); Pen p = new Pen(Color.Black); g.DrawLine(p, 0, e.Y, e.X, e.Y); g.DrawLine(p, e.X, 0, e.X, e.Y); g.DrawLine(p, e.X, e.Y, e.X, Panel1.Height); g.DrawLine(p, e.X, e.Y, Panel1.Width, e.Y); PointSet temp = new PointSet(); temp.points.AddRange(North.points); North.points.Clear(); foreach (Point point in temp.points) { if (point.x > 0 && point.x < isSplit.X) { //west if (point.y > 0 && point.y < isSplit.Y) { North.add(point); } else { West.add(point); } } else { //east if (point.y > 0 && point.y < isSplit.Y) { East.add(point); } else { South.add(point); } } } } } }
PointSet merge(PointSet S, PointSet S1, PointSet S2, ref PointSet WorkSet) { Point M = S1.pointAt(S1.points.Count - 1); // draw the strip about the median if (DELAY > 50) { drawDQStrip(S, M); pause(DELAY); } for (int i = 0; i < S.points.Count; i++) { Point P = S.pointAt(i); if (Math.Abs(P.x - M.x) <= S.dmin) { // P is in S1, only look in S2 if (S1.contains(P)) { S = testStripPoint(S, P, S2, M, true); } // P is in S2, only look in S1 if (S2.contains(P)) { S = testStripPoint(S, P, S1, M, false); } // update miniMUM distance if (S.dmin < WorkSet.dmin) { WorkSet.dmin = S.dmin; if (WorkSet.closestPair.Count == 0) { WorkSet.closestPair.Add(S.closestPair[0]); WorkSet.closestPair.Add(S.closestPair[1]); } else { WorkSet.closestPair[0] = S.closestPair[0]; WorkSet.closestPair[1] = S.closestPair[1]; } } } } return S; }
/************************************************************ * GRAPHICS FUNCTIONS FOR THE DIVIDE AND CONQUER ALGORITHM * ************************************************************/ public void drawDQStrip(PointSet S, Point M) { Graphics g = Panel1.CreateGraphics(); int x, w; // set x if ((M.x - S.dmin) < S.first().x) { x = S.first().x; } else { x = M.x - ((int)S.dmin); } // set w if ((M.x + S.dmin) > S.last().x) { w = S.last().x - x; } else { w = M.x + ((int)S.dmin) - x; } SolidBrush brush = new SolidBrush(Color.Pink); g.FillRectangle(brush, x, 0, w, Y_MAX); drawVertical(M, Color.Blue); drawPoints(S, Color.Black); }
private void findMidPoint(int x, int y) { if (x <= Panel1.Width || y <= Panel1.Height) { if (pairs() >= 4) { PointSet tempNorth = new PointSet(); PointSet tempSouth = new PointSet(); PointSet tempEast = new PointSet(); PointSet tempWest = new PointSet(); System.Drawing.Point temp = new System.Drawing.Point(x, y); PointSet tempSet = new PointSet(); tempSet.points.AddRange(North.points); //North.points.Clear(); foreach (Point point in tempSet.points) { if (point.x > 0 && point.x < temp.X) { //west if (point.y > 0 && point.y < temp.Y) { tempNorth.add(point); } else { tempWest.add(point); } } else { //east if (point.y > 0 && point.y < temp.Y) { tempEast.add(point); } else { tempSouth.add(point); } } } double distancePointsNorth = ClosestPairDQ(tempNorth); double distancePointsSouth = ClosestPairDQ(tempSouth); double distancePointsEast = ClosestPairDQ(tempEast); double distancePointsWest = ClosestPairDQ(tempWest); if (SameColor(tempNorth) && SameColor(tempEast) && SameColor(tempSouth) && SameColor(tempWest)) { if (!Double.IsInfinity(distancePointsEast) && !Double.IsInfinity(distancePointsNorth) && !Double.IsInfinity(distancePointsSouth) && !Double.IsInfinity(distancePointsWest)) { isSplit = temp; Graphics g = Panel1.CreateGraphics(); Pen p = new Pen(Color.Black); g.DrawLine(p, 0, isSplit.Y, isSplit.X, isSplit.Y); g.DrawLine(p, isSplit.X, 0, isSplit.X, isSplit.Y); g.DrawLine(p, isSplit.X, isSplit.Y, isSplit.X, Panel1.Height); g.DrawLine(p, isSplit.X, isSplit.Y, Panel1.Width, isSplit.Y); tempSet.points.Clear(); tempSet.points.AddRange(North.points); North.points.Clear(); foreach (Point point in tempSet.points) { if (point.x > 0 && point.x < isSplit.X) { //west if (point.y > 0 && point.y < isSplit.Y) { North.add(point); } else { West.add(point); } } else { //east if (point.y > 0 && point.y < isSplit.Y) { East.add(point); } else { South.add(point); } } } } else { System.Drawing.Point point; if (tempEast.points.Count > tempNorth.points.Count) { if (tempEast.points.Count > tempSouth.points.Count) { if (tempEast.points.Count > tempWest.points.Count) point = findAverage(tempEast, temp); else point = findAverage(tempWest, temp); } else if (tempSouth.points.Count > tempWest.points.Count) point = findAverage(tempSouth, temp); else point = findAverage(tempWest, temp); } else if (tempNorth.points.Count > tempSouth.points.Count) { if (tempNorth.points.Count > tempWest.points.Count) point = findAverage(tempNorth, temp); else point = findAverage(tempWest, temp); } else if (tempSouth.points.Count > tempWest.points.Count) { point = findAverage(tempSouth, temp); } else { point = findAverage(tempWest, temp); } findMidPoint(point.X, point.Y); } } else { //niet dezelfde kleur } } else { //niet genoeg paren } } else { //niet gevonden } }
private System.Drawing.Point findAverage(PointSet ps, System.Drawing.Point point) { int tempx = 0; int tempy = 0; foreach (Point p in ps.points) { tempx += p.x; tempy += p.y; } tempx = tempx / ps.points.Count; tempy = tempy / ps.points.Count; if (lastPoint.X == tempx && lastPoint.Y == tempy) { lastPoint = point; homePoint.X = rand.Next(0, Panel1.Width); homePoint.Y = rand.Next(0, Panel1.Height); return homePoint; } else { lastPoint = point; return new System.Drawing.Point(tempx, tempy); } }
// returns a subset of containing the elements of S from fromIndex to // toIndex inclusive public PointSet subSet(PointSet S, int fromIndex, int toIndex) { PointSet T = new PointSet(); for (int i = fromIndex; i <= toIndex; i++) { T.add(S.pointAt(i)); } return T; }
public void reset() { North = new PointSet(); South = new PointSet(); West = new PointSet(); East = new PointSet(); Graphics g = Panel1.CreateGraphics(); SolidBrush brush = new SolidBrush(Color.White); g.FillRectangle(brush, 0, 0, X_MAX, Y_MAX); distance.Text = ""; }
public void eraseField(PointSet S) { Graphics g = Panel1.CreateGraphics(); int w, x; x = S.first().x; w = S.last().x - x; SolidBrush brush = new SolidBrush(Color.White); g.FillRectangle(brush, x, 0, w, Y_MAX); drawPoints(S, Color.Black); }
public void drawPoints(PointSet S, Color c) { for (int i = 0; i < S.points.Count; i++) { Point P = S.pointAt(i); drawPoint(P); } }
// Test for closest pairs to P in set sS (P is a point in the strip) PointSet testStripPoint(PointSet S, Point P, PointSet sS, Point M, Boolean lookDIR) { Point Q; // Draw P's bounding box if (DELAY > 50) { drawDQBoundingBox(S, P, M, lookDIR); pause(DELAY); } for (int j = 0; j < sS.points.Count; j++) { Q = sS.pointAt(j); // if Q is in P's bounding box //if ((Math.Abs(P.x - Q.x) <= S.dmin) && //(Math.Abs(P.y - Q.y) <= S.dmin)) //{ // draw a red segment to show that it is being compared if (DELAY > 50) { drawSegment(P, Q); pause(DELAY); } numComparisons++; S = testBoundingBoxPoint(S, P, Q); // erase the red segment after the comparison if (DELAY > 50) { eraseSegment(P, Q, Color.Yellow); pause(DELAY); } //} } // Erase P's bounding box if (DELAY > 50) { drawDQStrip(S, M); } return S; }
public void drawDQBoundingBox(PointSet S, Point P, Point M, Boolean lookR) { Graphics g = Panel1.CreateGraphics(); int x, y, w, h; // set x if (lookR == true) { x = P.x; } else { if ((P.x - S.dmin) < S.first().x) { x = S.first().x; } else { x = P.x - ((int)S.dmin); } } // set y if ((P.y - S.dmin) < 0) { y = 0; } else { y = P.y - ((int)S.dmin); } // set w if (lookR == true) { if ((x + S.dmin) > S.last().x) { w = S.last().x - x; } else { w = ((int)S.dmin); } } else { w = P.x - x; } // set h if ((P.y + S.dmin) > Y_MAX) { h = Y_MAX - y; } else { h = P.y + ((int)S.dmin) - y; } SolidBrush brush = new SolidBrush(Color.Yellow); g.FillRectangle(brush, x, y, w, h); drawVertical(M, Color.Blue); drawPoints(S, Color.Black); }