public static void GrahamScanSortingTest(List <Vector3> points, List <Vector3> ccwPolygonPoints) { if (points.Count < 3) { return; } if (points.Count == 3) { for (int i = 0; i < points.Count; i++) { ccwPolygonPoints.Add(points[i]); } return; } //find the point having the lowest y coordinate (use x for euqual cases if any) //put it at the end of the list and remove it (this will be point P) Vector3 tmp = Vector3.zero; for (int i = points.Count - 1; i >= 0; i--) { if (points[points.Count - 1].z > points[i].z) { //swap tmp = points[points.Count - 1]; points[points.Count - 1] = points[i]; points[i] = tmp; } else if (points[points.Count - 1].z == points[i].z) { if (points[points.Count - 1].x < points[i].x) { tmp = points[points.Count - 1]; points[points.Count - 1] = points[i]; points[i] = tmp; } } } //sort the remaining point according the angle they form with the point P Vector3 P = points[points.Count - 1]; points.RemoveAt(points.Count - 1); SortAlgorithms.HeapSortGrahamScan(points, ref P); points.Add(P); //just a test }
/// <summary> /// Performs the computation of the convex hull of the passed points /// through Graham scan http://en.wikipedia.org/wiki/Graham_scan /// the returned points are the vertices of the polygon sorted /// counter clockwise /// </summary> /// <param name="points"> The points of which to find the convex hull that contains them /// A <see cref="List<Vector3>"/> /// </param> /// <returns> /// A <see cref="List<Vector3>"/> The list of counter clockwise sorted vertices of the convex hull polygon /// </returns> public static List <Vector3> GrahamScan(List <Vector3> points) { List <Vector3> ccwPolygonPoints = new List <Vector3> (); /* * if(points.Count < 3) * { * return ; * } * if(points.Count == 3) * { * for(int i=0; i < points.Count; i++) * { * ccwPolygonPoints.Add(points[i]); * } * return ; * } */ if (points.Count > 3) { //find the point having the lowest y coordinate (use x for euqual cases if any) //put it at the end of the list and remove it (this will be point P) Vector3 tmp = Vector3.zero; for (int i = points.Count - 1; i >= 0; i--) { if (points[points.Count - 1].z > points[i].z) { //swap tmp = points[points.Count - 1]; points[points.Count - 1] = points[i]; points[i] = tmp; } else if (points[points.Count - 1].z == points[i].z) { if (points[points.Count - 1].x < points[i].x) { tmp = points[points.Count - 1]; points[points.Count - 1] = points[i]; points[i] = tmp; } } } //sort the remaining point according the angle they form with the point P Vector3 P = points[points.Count - 1]; points.RemoveAt(points.Count - 1); SortAlgorithms.HeapSortGrahamScan(points, ref P); ccwPolygonPoints.Add(P); ccwPolygonPoints.Add(points[0]); //points.Add(P); int k = 1; while (k < points.Count) { //Debug.Log("while graham scan"); if (Vector3.Cross(ccwPolygonPoints[ccwPolygonPoints.Count - 1] - ccwPolygonPoints[ccwPolygonPoints.Count - 2], points[k] - ccwPolygonPoints[ccwPolygonPoints.Count - 2]).y < -SCAN_EPSILON) //Left turn, it should be > 0 but I am using 3D coordinate using z as y axis reported in the algorithm { ccwPolygonPoints.Add(points[k]); k++; } else { ccwPolygonPoints.RemoveAt(ccwPolygonPoints.Count - 1); if (ccwPolygonPoints.Count == 1) //in order to make the algorithm more robust { ccwPolygonPoints.Add(points[k]); k++; } } } } else if (points.Count == 3) { for (int i = 0; i < points.Count; i++) { ccwPolygonPoints.Add(points[i]); } } return(ccwPolygonPoints); }