public static double CalculateLocation(List <Dot> dots, AggregatedDot center) { var centerX = center.Dot.Position.X; var centerY = center.Dot.Position.Y; double sumEucledeans = 0; foreach (Dot d in dots) { var euclidean = Math.Sqrt(Math.Pow(centerX - d.Position.X, 2) + Math.Pow(centerY - d.Position.Y, 2)); sumEucledeans += euclidean; } var average = sumEucledeans / dots.Count; return(average); }
// To enable resolve overlap, uncomment line 63. // It is not enabled, because it takes O(n^2) time, which is slow. // We use a greedy implementation. // 1. Try to add as much points as possible in the first time. i.e ignore all overlap dots. // 2. Try to add the overlap dots without effecting others. // When resolving the overlap, we ignore the minimum radius requirement, which is set to 4. // The minimum raduis will be 1 if overlap occurs. // Note that there will be no full overlap (same center), becasue we use the center of the minimum cover circle as the position of the dot. // hence, they are all unique and raduis = 1 would be the value which will not cause any overlap with others. private void ResolvePossibleOverLap() { float distanceBetweenCenter = 0; List <AggregatedDot> tempAggregatedDots = new List <AggregatedDot>(_aggregatedDots); _aggregatedDots.Clear(); List <AggregatedDot> overlapDots = new List <AggregatedDot>(); for (int i = 0; i < tempAggregatedDots.Count; i++) { var tempDot = tempAggregatedDots[i]; bool containsOverlap = false; foreach (AggregatedDot dot in _aggregatedDots) { double xdiffer = tempDot.Dot.Position.X * _ratio * _width - dot.Dot.Position.X * _ratio * _width; double ydiffer = tempDot.Dot.Position.Y * _ratio * _height - dot.Dot.Position.Y * _ratio * _height; distanceBetweenCenter = (float)Math.Sqrt(Math.Pow(xdiffer, 2) + Math.Pow(ydiffer, 2)); if (distanceBetweenCenter < (tempDot.Raduis + dot.Raduis) / 2) { containsOverlap = true; overlapDots.Add(tempDot); break; } } if (!containsOverlap) { _aggregatedDots.Add(tempDot); } } foreach (AggregatedDot overlapDot in overlapDots) { List <AggregatedDot> allDotsOverlapWithThisDot = new List <AggregatedDot>(); List <float> distances = new List <float>(); foreach (AggregatedDot d in _aggregatedDots) { double xdiffer = overlapDot.Dot.Position.X * _ratio * _width - d.Dot.Position.X * _ratio * _width; double ydiffer = overlapDot.Dot.Position.Y * _ratio * _height - d.Dot.Position.Y * _ratio * _height; distanceBetweenCenter = (float)Math.Sqrt(Math.Pow(xdiffer, 2) + Math.Pow(ydiffer, 2)); if (distanceBetweenCenter < (overlapDot.Raduis + d.Raduis) / 2) { distances.Add(distanceBetweenCenter); allDotsOverlapWithThisDot.Add(d); } } // When resolving the overlap, we ignore the minimum radius requirement, which is set to 4 in Setting.cs for (int i = 0; i < distances.Count; i++) { AggregatedDot criticalDot = allDotsOverlapWithThisDot[i]; double xdiffer = overlapDot.Dot.Position.X * _ratio * _width - criticalDot.Dot.Position.X * _ratio * _width; double ydiffer = overlapDot.Dot.Position.Y * _ratio * _height - criticalDot.Dot.Position.Y * _ratio * _height; distanceBetweenCenter = (float)Math.Sqrt(Math.Pow(xdiffer, 2) + Math.Pow(ydiffer, 2)); if (distanceBetweenCenter < (overlapDot.Raduis + criticalDot.Raduis) / 2) { overlapDot.Raduis = Math.Max(1, Convert.ToInt32((Convert.ToDouble(overlapDot.Raduis) / (overlapDot.Raduis + criticalDot.Raduis)) * distanceBetweenCenter / 1.1)); // 1.1 for some distance between 2 dots. criticalDot.Raduis = Math.Max(1, Convert.ToInt32((Convert.ToDouble(criticalDot.Raduis) / (overlapDot.Raduis + criticalDot.Raduis)) * distanceBetweenCenter / 1.1)); } } _aggregatedDots.Add(overlapDot); } }