public static void ConvexHull() { int[] testSizes = new int[] { 12345, 100, 316, 1000, 3160, 10000, 31600, 100000, 316000, 1000000, 3160000, 10000000 }; for (int iter = 0; iter < testSizes.Length; iter++) { Random r = new Random(); List <PointD> points = new List <PointD>(testSizes[iter]); for (int i = 0; i < points.Capacity; i++) { double size = r.NextDouble(); double ang = r.NextDouble() * (Math.PI * 2); points.Add(new PointD(size * Math.Cos(ang), size * Math.Sin(ang))); } // Plus: test sorting time to learn how much of the time is spent sorting var points2 = new List <PointD>(points); EzStopwatch timer = new EzStopwatch(true); points2.Sort((a, b) => a.X == b.X ? a.Y.CompareTo(b.Y) : (a.X < b.X ? -1 : 1)); Stopwatch timer2 = new Stopwatch(); timer2.Start(); int sortTime = timer.Restart(); IListSource <Point <double> > output = PointMath.ComputeConvexHull(points, true); int hullTime = timer.Millisec; Console.WriteLine("{0:c} (ticks:{1,10} freq:{2})", timer2.Elapsed, timer2.ElapsedTicks, Stopwatch.Frequency); if (iter == 0) { continue; // first iteration primes the JIT/caches } Console.WriteLine("Convex hull of {0,8} points took {1} ms ({2} ms for sorting step). Output has {3} points.", testSizes[iter], hullTime, sortTime, output.Count); } }
public void ComputeVertices() { ////use convex hull to find vertices planeVertices.Clear(); List <Point <double> > points2 = new List <Point <double> >(); foreach (MyVector3 p in planePoints) { Point <double> pt = new Point <double>(p.x, p.y); points2.Add(pt); } List <Point <double> > convex_hull = PointMath.ComputeConvexHull(points2, false).ToList(); foreach (Point <double> point in convex_hull) { MyVector3 u = new MyVector3(point.X, point.Y, ComputeZ(point.X, point.Y)); planeVertices.Add(u); } ProjectVerticesTo2d(); //ComputePlaneArea(); }
// To recognize a scribble we require the simplified line to reverse // direction at least three times. There are separate criteria for // erasing a shape currently being drawn and for erasing existing // shapes. // // The key difference between an "erase scribble" and a "cancel // scribble" is that an erase scribble starts out as such, while // a cancel scribble indicates that the user changed his mind, so // the line will not appear to be a scribble at the beginning. // The difference is detected by timestamps. For example, the // following diagram represents an "erase" operation and a "cancel" // operation. Assume the input points are evenly spaced in time, // and that the dots represent points where the input reversed // direction. // // Input points .......................... // Reversals (erase) . . . . . . // Reversals (cancel) . . . . // // So, a scribble is considered an erasure if it satisfies t0 < t1, // where t0 is the time between mouse-down and the first reversal, // and t1 is the time between the first and third reversals. A cancel // operation satisfies t0 > t1 instead. // // Both kinds of scribble need to satisfy the formula LL*c > CHA, // where c is a constant factor in pixels, LL is the drawn line // length and CHA is the area of the Convex Hull that outlines the // drawn figure. This formula basically detects that the user // is convering the same ground repeatedly; if the pen reverses // direction repeatedly but goes to new places each time, it's not // considered an erasure scribble. For a cancel scribble, LL is // computed starting from the first reversal. IEnumerable <Shape> RecognizeScribbleForEraseOrCancel(DragState state, out bool cancel, out List <PointT> simplifiedSS) { cancel = false; simplifiedSS = null; var tolerance = state._inputTransform.Transform(new VectorT(0, 10)).Length(); var simplifiedMP = LineMath.SimplifyPolyline( state.UnfilteredMousePoints.Select(p => p.Point), tolerance); List <int> reversals = FindReversals(simplifiedMP, 3); if (reversals.Count >= 3) { simplifiedSS = simplifiedMP.Select(p => state._inputTransform.Transform(p)).ToList(); // 3 reversals confirmed. Now decide: erase or cancel? int[] timeStampsMs = FindTimeStamps(state.UnfilteredMousePoints, simplifiedMP); int t0 = timeStampsMs[reversals[0]], t1 = timeStampsMs[reversals[2]] - t0; cancel = t0 > t1 + 500; // Now test the formula LL*c > CHA as explained above IListSource <PointT> simplifiedMP_ = cancel ? simplifiedMP.Slice(reversals[0]) : simplifiedMP.AsListSource(); float LL = simplifiedMP_.AdjacentPairs().Sum(pair => pair.A.Sub(pair.B).Length()); var hull = PointMath.ComputeConvexHull(simplifiedMP); float CHA = PolygonMath.PolygonArea(hull); if (LL * EraseNubWidth > CHA) { // Erasure confirmed. if (cancel) { return(EmptyList <Shape> .Value); } // Figure out which shapes to erase. To do this, we compute for // each shape the amount of the scribble that overlaps that shape. var simplifiedSS_ = simplifiedSS; return(_doc.Shapes.Where(s => ShouldErase(s, simplifiedSS_)).ToList()); } } return(null); }
public JsonResult ConvexHull(int Id, int Forecast) { if (Forecast > 0) { using (MeteoDataEntities me = new MeteoDataEntities()) { var asciiResult = me.IndexMaps.Where(x => x.Id == Id).Select(x => x.IndexMapZipAscii).First(); Byte[] ascii = ex.Uncompress(asciiResult); //System.IO.File.WriteAllBytes(@"C:\Static\test.asc", ascii); #region Read ascii List <AsciiValues> listasp = new List <AsciiValues>(); int counter = 0; string line; int ncols = 0; int nrows = 0; int xllcorner = 0; int yllcorner = 0; int cellsize = 0; int NODATA_value = 0; using (MemoryStream memoryStream = new MemoryStream(ascii)) { using (StreamReader st = new StreamReader(memoryStream)) { while ((line = st.ReadLine()) != null) { //System.Console.WriteLine(line); if (!string.IsNullOrWhiteSpace(line)) { counter++; #region ASC Details if (counter < 7) { string[] result = line.Split(' '); if (result[0].Contains("ncols")) { for (int i = 1; i < result.Length; i++) { if (!String.IsNullOrWhiteSpace(result[i])) { int number; if (int.TryParse(result[i], out number)) { ncols = number; } } } } if (result[0].Contains("nrows")) { for (int i = 1; i < result.Length; i++) { if (!String.IsNullOrWhiteSpace(result[i])) { int number; if (int.TryParse(result[i], out number)) { nrows = number; } } } } if (result[0].Contains("xllcorner")) { for (int i = 1; i < result.Length; i++) { if (!String.IsNullOrWhiteSpace(result[i])) { int number; if (int.TryParse(result[i], out number)) { xllcorner = number; } } } } if (result[0].Contains("yllcorner")) { for (int i = 1; i < result.Length; i++) { if (!String.IsNullOrWhiteSpace(result[i])) { int number; if (int.TryParse(result[i], out number)) { yllcorner = number; } } } } if (result[0].Contains("cellsize")) { for (int i = 1; i < result.Length; i++) { if (!String.IsNullOrWhiteSpace(result[i])) { int number; if (int.TryParse(result[i], out number)) { cellsize = number; } } } } if (result[0].Contains("NODATA_value")) { for (int i = 1; i < result.Length; i++) { if (!String.IsNullOrWhiteSpace(result[i])) { int number; if (int.TryParse(result[i], out number)) { NODATA_value = number; } } } } } #endregion ASC Details else { string[] result = line.Split(' '); for (int i = 0; i < result.Length; i++) { int number; if (int.TryParse(result[i], out number)) { AsciiValues aspul = new AsciiValues() { X = xllcorner + (i * cellsize), Y = (yllcorner + (nrows * cellsize)) - (cellsize * (counter - 7)), Value = number }; AsciiValues aspur = new AsciiValues() { X = xllcorner + (i * cellsize) + cellsize, Y = (yllcorner + (nrows * cellsize)) - (cellsize * (counter - 7)), Value = number }; AsciiValues aspdl = new AsciiValues() { X = xllcorner + (i * cellsize), Y = (yllcorner + (nrows * cellsize)) - (cellsize * (counter - 7)) - cellsize, Value = number }; AsciiValues aspdr = new AsciiValues() { X = xllcorner + (i * cellsize) + cellsize, Y = (yllcorner + (nrows * cellsize)) - (cellsize * (counter - 7)) - cellsize, Value = number }; listasp.Add(aspul); listasp.Add(aspur); listasp.Add(aspdl); listasp.Add(aspdr); } } } } } counter.ToString(); } } #endregion Read ascii var points = listasp.Where(x => x.Value <= Forecast && x.Value > 0); var finalpoints = points.Select(x => new Point <double>() { X = x.X, Y = x.Y }).ToList(); var ConvexHullresult = PointMath.ComputeConvexHull(finalpoints, true); return(this.Json(ConvexHullresult, JsonRequestBehavior.AllowGet)); } } else { return(this.Json(null, JsonRequestBehavior.AllowGet)); } }