/// <summary> /// The Graham Scan algorithm determines the points belonging to the convex hull in O(n lg n). /// </summary> /// <param name="points">set of points</param> /// <returns>points in the convex hull</returns> /// <seealso href="http://en.wikipedia.org/wiki/Graham_scan">Graham scan, Wikipedia</seealso> public static List <Point> GrahamScan(List <Point> points) { if (points.Count <= 3) { return(new List <Point>(points)); } var ps = new List <Point>(points); ps.Sort(new CompareYThenX()); ps.Sort(new PolarComparator(ps[0])); Deque <Point> hull = new ArrayDeque <Point>(); hull.Push(ps[0]); hull.Push(ps[1]); hull.Push(ps[2]); for (int i = 3; i < points.Count; i++) { var top = hull.Pop(); while (hull.Any() && !IsLeftTurn(hull.Peek(), top, ps[i])) { top = hull.Pop(); } hull.Push(top); hull.Push(ps[i]); } return(new List <Point>(hull)); }
/// <summary> /// Visits the given file, returning the {@code Event} corresponding to that /// visit. /// /// The {@code ignoreSecurityException} parameter determines whether /// any SecurityException should be ignored or not. If a SecurityException /// is thrown, and is ignored, then this method returns {@code null} to /// mean that there is no event corresponding to a visit to the file. /// /// The {@code canUseCached} parameter determines whether cached attributes /// for the file can be used or not. /// </summary> private Event Visit(Path entry, bool ignoreSecurityException, bool canUseCached) { // need the file attributes BasicFileAttributes attrs; try { attrs = GetAttributes(entry, canUseCached); } catch (IOException ioe) { return(new Event(EventType.ENTRY, entry, ioe)); } catch (SecurityException se) { if (ignoreSecurityException) { return(null); } throw se; } // at maximum depth or file is not a directory int depth = Stack.Size(); if (depth >= MaxDepth || !attrs.Directory) { return(new Event(EventType.ENTRY, entry, attrs)); } // check for cycles when following links if (FollowLinks && WouldLoop(entry, attrs.FileKey())) { return(new Event(EventType.ENTRY, entry, new FileSystemLoopException(entry.ToString()))); } // file is a directory, attempt to open it DirectoryStream <Path> stream = null; try { stream = Files.NewDirectoryStream(entry); } catch (IOException ioe) { return(new Event(EventType.ENTRY, entry, ioe)); } catch (SecurityException se) { if (ignoreSecurityException) { return(null); } throw se; } // push a directory node to the stack and return an event Stack.Push(new DirectoryNode(entry, attrs.FileKey(), stream)); return(new Event(EventType.START_DIRECTORY, entry, attrs)); }