/// <summary> /// This method will add a given event to the list of events. Any previous /// clustering information will be removed. /// </summary> /// <param name="evt">The event to be added</param> public void Add(Event evt) { // Remove any previous clustering data evt.Coordinate.ClearClusterData(); // Add the event to the EventCollection Events.Add(evt); }
/// <summary> /// This method will return all coordinates within C's eps-neighbourhood. /// </summary> /// <param name="c">The centroid coordinate</param> /// <returns>A list of neighbouring coordinates</returns> private EventCollection GetRegion(Event evt) { // Collection of neighbouring coordinates EventCollection neighbours = new EventCollection(); // Square the Epsilon (radius) to get the diameter of the neighbourhood double eps = Epsilon * Epsilon; // Loop over all coordinates foreach (Event neighbour in Calls) { // Calculate the distance of the two coordinates double distance = Distance.haversine(evt.Coordinate, neighbour.Coordinate); // Class as a neighbour if it falls in the 'catchment area' if (eps >= distance) { neighbours.Add(neighbour); } } return neighbours; }
/// <summary> /// This function will expand each of the given coordinate neighbours, and /// all of their neighbours. This will decide which coordinates are within /// the given coordinate's EPS, and therefore whether or not the neighbours /// belong to the new cluster. /// </summary> /// <param name="c">The coordinate to expand</param> /// <param name="clusterId">The current cluster ID</param> /// <returns>whether or not a new cluster has been defined or not</returns> private bool ExpandCluster(Event evt, int clusterId) { // Get the all of evt's neighbours. EventCollection neighbours = GetRegion(evt); neighbours.Centroid.Radius = Epsilon; // Remove itself from the neighbours neighbours.Remove(evt); // Decrement the MinPoints by one so that we take int minimumPoints = MinPoints - 1; // Check to see if there is a core point (based on the minimum number of points per cluster) if (neighbours.Count < minimumPoints) { evt.Coordinate.Classified = true; evt.Coordinate.Noise = true; return false; } // Assume that all points are reachable from C neighbours.UpdateAllClusterID(clusterId); // Explore all the neighbours while (neighbours.Count > 0) { // Get C's neighbour Event currentNeighbour = neighbours[0]; // Get all the neighbours of the original neighbour EventCollection neighbouringNeighbours = GetRegion(currentNeighbour); if (neighbouringNeighbours.Count >= minimumPoints) { // Check to see if foreach (Event resultP in neighbouringNeighbours) { if (!resultP.Coordinate.Classified || resultP.Coordinate.Noise) { if (!resultP.Coordinate.Classified) { resultP.Coordinate.Classified = true; resultP.Coordinate.Noise = false; neighbours.Add(resultP); } resultP.Coordinate.ClusterId = clusterId; } } } // Remove C's direct neighbour as it has been explored. neighbours.Remove(currentNeighbour); } return true; }
/// <summary> /// This method will find a given event's closest cluster. The distance between /// the coordinate and the cluster's centroid is calculated using the haversine /// formula. /// </summary> /// <see cref="Distance.haversine"/> /// <param name="clusters">a list of clusters</param> /// <param name="evt">the pivot event</param> /// <returns>index location of the cluster</returns> private int FindNearestCluster(List<EventCollection> clusters, Event evt) { // The minimum distance to a coordinate double minimumDistance = Double.MaxValue; // The index of the nearest cluster int clusterIndex = -1; // Find the nearest cluster for (int k = 0; k < clusters.Count; k++) { // Calculate the distance double distance = Distance.haversine(evt.Coordinate, clusters[k].Centroid); // Compare the two distance values if (minimumDistance > distance) { // A smaller distance has been found minimumDistance = distance; clusterIndex = k; } } return clusterIndex; }