private void AssertLineWithCircle(double frX, double frY, double toX, double toY, double cX, double cY, double cR, double expL1, double expL2) { EdgeD lin = new EdgeD(frX, frY, toX, toY); CircleD cir = new CircleD(cX, cY, cR); double l1, l2; Intersect.LineWithCircle(ref lin, ref cir, out l1, out l2); Assert.AreEqual(MinTO(expL1, expL2), MinTO(l1, l2), 0.001); Assert.AreEqual(MaxTO(expL1, expL2), MaxTO(l1, l2), 0.001); }
private void AssertRayWithCircle(double frX, double frY, double toX, double toY, double cX, double cY, double cR, double expL1, double expL2) { EdgeD ray = new EdgeD(frX, frY, toX, toY); CircleD cir = new CircleD(cX, cY, cR); double l1, l2; Intersect.RayWithCircle(ref ray, ref cir, out l1, out l2); Assert.AreEqual(expL1, l1, 0.001); Assert.AreEqual(expL2, l2, 0.001); }
public void Run() { var eu = new EdgeU(100, 50); var ed = new EdgeD(22, 11); var ew = new EdgeW(12, 34, 5.67); var dew = new DirectedEdge(12, 34, 5.67); Console.WriteLine(eu); Console.WriteLine(ed); Console.WriteLine(ew); Console.WriteLine(dew); Console.ReadLine(); }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); Console.ReadLine(); }
/// <summary> /// Finds the point of intersection of two lines. The result is in terms of lambda along each of the lines. Point /// of intersection is defined as "line.Start + lambda * line", for each line. If the lines don't intersect, the /// lambdas are set to NaN.</summary> public static void LineWithLine(ref EdgeD line1, ref EdgeD line2, out double line1Lambda, out double line2Lambda) { // line1 direction vector double l1dx = line1.End.X - line1.Start.X; double l1dy = line1.End.Y - line1.Start.Y; // line2 direction vector double l2dx = line2.End.X - line2.Start.X; double l2dy = line2.End.Y - line2.Start.Y; double denom = l1dx * l2dy - l1dy * l2dx; if (denom == 0) { line1Lambda = double.NaN; line2Lambda = double.NaN; } else { line1Lambda = (l2dx * (line1.Start.Y - line2.Start.Y) - l2dy * (line1.Start.X - line2.Start.X)) / denom; line2Lambda = (l1dx * (line1.Start.Y - line2.Start.Y) - l1dy * (line1.Start.X - line2.Start.X)) / denom; } }
/// <summary> /// Returns a random simple DAG containing <tt>V</tt> vertices and <tt>E</tt> edges. /// Note: it is not uniformly selected at random among all such DAGs. /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="e">E the number of vertices</param> /// <returns>a random simple DAG on <tt>V</tt> vertices, containing a total of <tt>E</tt> edges</returns> /// <exception cref="ArgumentException">if no such simple DAG exists</exception> public static Digraph Dag(int v, int e) { if (e > (long)v * (v - 1) / 2) throw new ArgumentException("Too many edges"); if (e < 0) throw new ArgumentException("Too few edges"); var g = new Digraph(v); var set = new SET<EdgeD>(); var vertices = new int[v]; for (var i = 0; i < v; i++) vertices[i] = i; StdRandom.Shuffle(vertices); while (g.E < e) { var ve = StdRandom.Uniform(v); var we = StdRandom.Uniform(v); var edge = new EdgeD(ve, we); if ((ve < we) && !set.Contains(edge)) { set.Add(edge); g.AddEdge(vertices[ve], vertices[we]); } } return g; }
/// <summary> /// Returns a random simple digraph on <tt>V</tt> vertices, <tt>E</tt> /// edges and (at least) <tt>c</tt> strong components. The vertices are randomly /// assigned integer labels between <tt>0</tt> and <tt>c-1</tt> (corresponding to /// strong components). Then, a strong component is creates among the vertices /// with the same label. Next, random edges (either between two vertices with /// the same labels or from a vetex with a smaller label to a vertex with a /// larger label). The number of components will be equal to the number of /// distinct labels that are assigned to vertices. /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="e">E the number of edges</param> /// <param name="c">c the (maximum) number of strong components</param> /// <returns>a random simple digraph on <tt>V</tt> vertices and <tt>E</tt> edges, with (at most) <tt>c</tt> strong components</returns> /// <exception cref="ArgumentException">if <tt>c</tt> is larger than <tt>V</tt></exception> public static Digraph Strong(int v, int e, int c) { if (c >= v || c <= 0) throw new ArgumentException("Number of components must be between 1 and V"); if (e <= 2 * (v - c)) throw new ArgumentException("Number of edges must be at least 2(V-c)"); if (e > (long)v * (v - 1) / 2) throw new ArgumentException("Too many edges"); // the digraph var g = new Digraph(v); // edges added to G (to avoid duplicate edges) var set = new SET<EdgeD>(); var label = new int[v]; for (var i = 0; i < v; i++) label[i] = StdRandom.Uniform(c); // make all vertices with label c a strong component by // combining a rooted in-tree and a rooted out-tree for (var i = 0; i < c; i++) { // how many vertices in component c var count = 0; for (var ii = 0; ii < g.V; ii++) { if (label[ii] == i) count++; } // if (count == 0) System.err.println("less than desired number of strong components"); var vertices = new int[count]; var j = 0; for (var jj = 0; jj < v; jj++) { if (label[jj] == i) vertices[j++] = jj; } StdRandom.Shuffle(vertices); // rooted-in tree with root = vertices[count-1] for (var ve = 0; ve < count - 1; ve++) { var we = StdRandom.Uniform(ve + 1, count); var edge = new EdgeD(we, ve); set.Add(edge); g.AddEdge(vertices[we], vertices[ve]); } // rooted-out tree with root = vertices[count-1] for (var ve = 0; ve < count - 1; ve++) { var we = StdRandom.Uniform(ve + 1, count); var edge = new EdgeD(ve, we); set.Add(edge); g.AddEdge(vertices[ve], vertices[we]); } } while (g.E < e) { var ve = StdRandom.Uniform(v); var we = StdRandom.Uniform(v); var edge = new EdgeD(ve, we); if (!set.Contains(edge) && ve != we && label[ve] <= label[we]) { set.Add(edge); g.AddEdge(ve, we); } } return g; }
/// <summary> /// Returns a random simple digraph containing <tt>V</tt> vertices and <tt>E</tt> edges. /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="e">E the number of vertices</param> /// <returns>a random simple digraph on <tt>V</tt> vertices, containing a total of <tt>E</tt> edges</returns> /// <exception cref="ArgumentException">if no such simple digraph exists</exception> public static Digraph Simple(int v, int e) { if (e > (long)v * (v - 1)) throw new ArgumentException("Too many edges"); if (e < 0) throw new ArgumentException("Too few edges"); var g = new Digraph(v); var set = new SET<EdgeD>(); while (g.E < e) { var ve = StdRandom.Uniform(v); var we = StdRandom.Uniform(v); var edge = new EdgeD(ve, we); if ((ve != we) && !set.Contains(edge)) { set.Add(edge); g.AddEdge(ve, we); } } return g; }
/// <summary> /// Returns a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges. /// A rooted out-tree is a DAG in which every vertex is reachable from a /// single vertex. /// The DAG returned is not chosen uniformly at random among all such DAGs. /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="e">E the number of edges</param> /// <returns>a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges</returns> public static Digraph RootedOutDag(int v, int e) { if (e > (long)v * (v - 1) / 2) throw new ArgumentException("Too many edges"); if (e < v - 1) throw new ArgumentException("Too few edges"); var g = new Digraph(v); var set = new SET<EdgeD>(); // fix a topological order var vertices = new int[v]; for (var i = 0; i < v; i++) vertices[i] = i; StdRandom.Shuffle(vertices); // one edge pointing from each vertex, other than the root = vertices[V-1] for (var ve = 0; ve < v - 1; ve++) { var we = StdRandom.Uniform(ve + 1, v); var edge = new EdgeD(we, ve); set.Add(edge); g.AddEdge(vertices[we], vertices[ve]); } while (g.E < e) { var ve = StdRandom.Uniform(v); var we = StdRandom.Uniform(v); var edge = new EdgeD(we, ve); if ((ve < we) && !set.Contains(edge)) { set.Add(edge); g.AddEdge(vertices[we], vertices[ve]); } } return g; }
/// <summary> /// Calculates the intersection of a ray with a segment. Returns the result as the lambdas of the intersection /// point along the ray and the segment. If there is no intersection returns double.NaN in both lambdas.</summary> public static void RayWithSegment(ref EdgeD ray, ref EdgeD segment, out double rayL, out double segmentL) { Intersect.LineWithLine(ref ray, ref segment, out rayL, out segmentL); if (!double.IsNaN(rayL) && ((rayL < 0) || (segmentL < 0) || (segmentL > 1))) rayL = segmentL = double.NaN; }
/// <summary> /// Finds the points of intersection between a ray and an arc. The resulting lambdas along the ray are sorted in /// ascending order, so the "first" intersection is always in lambda1 (if any). Lambda may be NaN if there is no /// intersection (or no "second" intersection).</summary> public static void RayWithArc(ref EdgeD ray, ref ArcD arc, out double lambda1, out double lambda2) { RayWithCircle(ref ray, ref arc.Circle, out lambda1, out lambda2); var sweepdir = Math.Sign(arc.AngleSweep); if (!double.IsNaN(lambda1)) { var dir = ((ray.Start + lambda1 * (ray.End - ray.Start)) - arc.Circle.Center).Theta(); if (!(GeomUt.AngleDifference(arc.AngleStart, dir) * sweepdir > 0 && GeomUt.AngleDifference(arc.AngleStart + arc.AngleSweep, dir) * sweepdir < 0)) lambda1 = double.NaN; } if (!double.IsNaN(lambda2)) { var dir = ((ray.Start + lambda2 * (ray.End - ray.Start)) - arc.Circle.Center).Theta(); if (!(GeomUt.AngleDifference(arc.AngleStart, dir) * sweepdir > 0 && GeomUt.AngleDifference(arc.AngleStart + arc.AngleSweep, dir) * sweepdir < 0)) lambda2 = double.NaN; } if (double.IsNaN(lambda1) && !double.IsNaN(lambda2)) { lambda1 = lambda2; lambda2 = double.NaN; } }
/// <summary> /// Draws a straight line using the specified pen. /// </summary> public void DrawLine(Pen pen, EdgeD segment) { Graphics.DrawLine(pen, SX(segment.Start.X), SY(segment.Start.Y), SX(segment.End.X), SY(segment.End.Y)); }
/// <summary> /// Finds the points of intersection between a line and a circle. The results are two lambdas along the line, one /// for each point, or NaN if there is no intersection.</summary> public static void LineWithCircle(ref EdgeD line, ref CircleD circle, out double lambda1, out double lambda2) { // The following expressions come up a lot in the solution, so simplify using them. double dx = line.End.X - line.Start.X; double dy = line.End.Y - line.Start.Y; double ax = -line.Start.X + circle.Center.X; double ay = -line.Start.Y + circle.Center.Y; // Solve simultaneously for l: // Eq of a line: x = sx + l * dx // y = sy + l * dy // Eq of a circle: (x - cx)^2 + (y - cy)^2 = r^2 // // Eventually we get a standard quadratic equation in l with the // following coefficients: double a = dx * dx + dy * dy; double b = -2 * (ax * dx + ay * dy); double c = ax * ax + ay * ay - circle.Radius * circle.Radius; // Now just solve the quadratic eqn... double D = b * b - 4 * a * c; if (D < 0) { lambda1 = lambda2 = double.NaN; } else { double sqrtD = Math.Sqrt(D); lambda1 = (-b + sqrtD) / (2 * a); lambda2 = (-b - sqrtD) / (2 * a); } }
/// <summary> /// Finds the point of intersection of two lines. If the lines don't intersect, the resulting point coordinates /// are NaN.</summary> public static PointD LineWithLine(EdgeD line1, EdgeD line2) { double line1Lambda, line2Lambda; LineWithLine(ref line1, ref line2, out line1Lambda, out line2Lambda); return line1.Start + line1Lambda * (line1.End - line1.Start); }
/// <summary> /// Checks for intersections between a ray and a bounding box. Returns true if there is at least one intersection.</summary> public static bool RayWithBoundingBox(ref EdgeD ray, ref BoundingBoxD box) { double dx = ray.End.X - ray.Start.X; double dy = ray.End.Y - ray.Start.Y; double k, c; // temporaries // Check intersection with horizontal bounds if (dy != 0) { // Upper line k = (box.Ymax - ray.Start.Y) / dy; if (k >= 0) { c = ray.Start.X + k * dx; if (c >= box.Xmin && c <= box.Xmax) return true; } // Lower line k = (box.Ymin - ray.Start.Y) / dy; if (k >= 0) { c = ray.Start.X + k * dx; if (c >= box.Xmin && c <= box.Xmax) return true; } } // Check intersection with vertical bounds if (dx != 0) { // Rightmost line k = (box.Xmax - ray.Start.X) / dx; if (k >= 0) { c = ray.Start.Y + k * dy; if (c >= box.Ymin && c <= box.Ymax) return true; } // Leftmost line k = (box.Xmin - ray.Start.X) / dx; if (k >= 0) { c = ray.Start.Y + k * dy; if (c >= box.Ymin && c <= box.Ymax) return true; } } return false; }
/// <summary> /// Finds intersections between a ray and a rectangle. Returns the lambdas of intersections, if any, or NaN /// otherwise. Guarantees that lambda1 < lambda2, and if only one of them is NaN then it's lambda2. Lambda is /// such that ray.Start + lambda * (ray.End - ray.Start) gives the point of intersection.</summary> public static void RayWithRectangle(ref EdgeD ray, ref RectangleD rect, out double lambda1, out double lambda2) { double lambda, dummy; bool done1 = false; lambda1 = lambda2 = double.NaN; for (int i = 0; i < 4; i++) { EdgeD segment; switch (i) { case 0: segment = new EdgeD(rect.Left, rect.Top, rect.Right, rect.Top); break; case 1: segment = new EdgeD(rect.Right, rect.Top, rect.Right, rect.Bottom); break; case 2: segment = new EdgeD(rect.Right, rect.Bottom, rect.Left, rect.Bottom); break; case 3: segment = new EdgeD(rect.Left, rect.Bottom, rect.Left, rect.Top); break; default: throw new InternalErrorException("fsvxhfhj"); // shut up compiler about uninitialized "segment" variable } Intersect.RayWithSegment(ref ray, ref segment, out lambda, out dummy); if (!double.IsNaN(lambda)) { if (!done1) { lambda1 = lambda; done1 = true; } else if (lambda != lambda1) { if (lambda > lambda1) lambda2 = lambda; else { lambda2 = lambda1; lambda1 = lambda; } return; } } } }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); var tc = new TransitiveClosure(digraph); // print header Console.Write(" "); for (var i = 0; i < digraph.V; i++) Console.Write($"{i,3}"); Console.WriteLine(); Console.WriteLine("--------------------------------------------"); // print transitive closure for (var i = 0; i < digraph.V; i++) { Console.Write($"{i,3}: "); for (var w = 0; w < digraph.V; w++) { Console.Write(tc.Reachable(i, w) ? " T" : " "); } Console.WriteLine(); } Console.ReadLine(); }
/// <summary>Returns a new BoundingBox bounding the specified edge.</summary> public static BoundingBoxD FromEdge(EdgeD edge) { return FromPoint(ref edge.Start, ref edge.End); }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("2 - mediumDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "2": fileName = "mediumDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); var scc = new TarjanSCC(digraph); // number of connected components var m = scc.Count(); Console.WriteLine($"{m} components"); // compute list of vertices in each strong component var components = new Core.Collections.Queue<Integer>[m]; for (var i = 0; i < m; i++) { components[i] = new Core.Collections.Queue<Integer>(); } for (var i = 0; i < digraph.V; i++) { components[scc.Id(i)].Enqueue(i); } // print results for (var i = 0; i < m; i++) { foreach (int j in components[i]) { Console.Write($"{j} "); } Console.WriteLine(); } Console.ReadLine(); }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); Console.WriteLine("------------------------------------------------------"); var bag1 = new Core.Collections.Bag<Integer> { new Integer(1) }; var bag2 = new Core.Collections.Bag<Integer> { new Integer(2) }; var bag3 = new Core.Collections.Bag<Integer> { new Integer(6) }; var listSources = new List<Core.Collections.Bag<Integer>> { bag1, bag2, bag3 }; foreach (var sources in listSources) { foreach (var source in sources) { // multiple-source reachability var dfs = new NonrecursiveDirectedDFS(digraph, source.Value); // print out vertices reachable from sources for (var i = 0; i < digraph.V; i++) { if (dfs.Marked(i)) Console.Write($"{i} "); } Console.WriteLine(); } Console.WriteLine(); Console.WriteLine("---------------------------------------------------------"); } Console.ReadLine(); }
/// <summary>Returns true if this bounding box intersects with the specified ray.</summary> public bool IntersectsWithRay(EdgeD ray) { return Intersect.RayWithBoundingBox(ref ray, ref this); }
/// <summary> /// Finds the points of intersection between a ray and a circle. The resulting lambdas along the ray are sorted in /// ascending order, so the "first" intersection is always in lambda1 (if any). Lambda may be NaN if there is no /// intersection (or no "second" intersection).</summary> public static void RayWithCircle(ref EdgeD ray, ref CircleD circle, out double lambda1, out double lambda2) { LineWithCircle(ref ray, ref circle, out lambda1, out lambda2); // Sort the two values in ascending order, with NaN last, // while resetting negative values to NaNs if (lambda1 < 0) lambda1 = double.NaN; if (lambda2 < 0) lambda2 = double.NaN; if (lambda1 > lambda2 || double.IsNaN(lambda1)) { double temp = lambda1; lambda1 = lambda2; lambda2 = temp; } }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDAG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDAG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); var dfs = new DepthFirstOrder(digraph); Console.WriteLine(" v pre post"); Console.WriteLine("--------------"); for (var vi = 0; vi < digraph.V; vi++) { Console.Write($"{vi} {dfs.Pre(vi)} {dfs.Post(vi)}{Environment.NewLine}"); } Console.Write("Preorder: "); foreach (int vi in dfs.Pre()) { Console.Write($"{vi} "); } Console.WriteLine(); Console.Write("Postorder: "); foreach (int vi in dfs.Post()) { Console.Write($"{vi} "); } Console.WriteLine(); Console.Write("Reverse postorder: "); foreach (int vi in dfs.ReversePost()) { Console.Write($"{vi} "); } Console.ReadLine(); }
/// <summary>Returns an array containing all the edges of this polygon.</summary> public EdgeD[] ToEdges() { var edges = new EdgeD[_vertices.Count]; int i; for (i = 0; i < _vertices.Count - 1; i++) edges[i] = new EdgeD(_vertices[i], _vertices[i + 1]); edges[i] = new EdgeD(_vertices[i], _vertices[0]); return edges; }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("2 - mediumDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "2": fileName = "mediumDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); Console.WriteLine("------------------------------------------------------"); const int s = 3; var bfs = new BreadthFirstDirectedPaths(digraph, s); for (var i = 0; i < digraph.V; i++) { if (bfs.HasPathTo(i)) { Console.Write($"{s} to {i} ({bfs.DistTo(i)}): "); foreach (int x in bfs.PathTo(i)) { if (x == s) Console.Write(x); else Console.Write("->" + x); } Console.WriteLine(); } else { Console.Write($"{s} to {i} (-): not connected{Environment.NewLine}"); } } Console.ReadLine(); }
/// <summary> /// Finds the points of intersection between a line and a circle. The results are two lambdas along the line, one /// for each point, or NaN if there is no intersection.</summary> public static void LineWithCircle(EdgeD line, CircleD circle, out double lambda1, out double lambda2) { LineWithCircle(ref line, ref circle, out lambda1, out lambda2); }