/// <summary> /// Check and return polygon intersections /// </summary> /// <param name="polygon1"></param> /// <param name="polygon2"></param> /// <param name="intersections"></param> /// <returns></returns> private static bool VerticesIntersect(Vertices polygon1, Vertices polygon2, out List <EdgeIntersectInfo> intersections) { intersections = new List <EdgeIntersectInfo>(); // Iterate through polygon1's edges for (int i = 0; i < polygon1.Count; i++) { // Get edge vertices Vector2 p1 = polygon1[i]; Vector2 p2 = polygon1[polygon1.NextIndex(i)]; // Get intersections between this edge and polygon2 for (int j = 0; j < polygon2.Count; j++) { Vector2 point; Vector2 p3 = polygon2[j]; Vector2 p4 = polygon2[polygon2.NextIndex(j)]; // Check if the edges intersect if (LineTools.LineIntersect(p1, p2, p3, p4, true, true, out point)) { // Here, we round the returned intersection point to its nearest whole number. // This prevents floating point anomolies where 99.9999-> is returned instead of 100. point = new Vector2((float)Math.Round(point.X, 0), (float)Math.Round(point.Y, 0)); // Record the intersection intersections.Add(new EdgeIntersectInfo(new Edge(p1, p2), new Edge(p3, p4), point)); } } } // true if any intersections were found. return(intersections.Count > 0); }
private bool SearchForOutstandingVertex(Vertices hullArea, out Vector2 outstanding) { Vector2 outstandingResult = Vector2.Zero; bool found = false; if (hullArea.Count > 2) { int hullAreaLastPoint = hullArea.Count - 1; Vector2 tempVector1; Vector2 tempVector2 = hullArea[0]; Vector2 tempVector3 = hullArea[hullAreaLastPoint]; // Search between the first and last hull point. for (int i = 1; i < hullAreaLastPoint; i++) { tempVector1 = hullArea[i]; // Check if the distance is over the one that's tolerable. if (LineTools.DistanceBetweenPointAndLineSegment(ref tempVector1, ref tempVector2, ref tempVector3) >= _hullTolerance) { outstandingResult = hullArea[i]; found = true; break; } } } outstanding = outstandingResult; return(found); }
private static bool CanSee(int i, int j, Vertices vertices) { if (Reflex(i, vertices)) { if (LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices)) && RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices))) { return(false); } } else { if (RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices)) || LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices))) { return(false); } } if (Reflex(j, vertices)) { if (LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices)) && RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices))) { return(false); } } else { if (RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices)) || LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices))) { return(false); } } for (int k = 0; k < vertices.Count; ++k) { if ((k + 1) % vertices.Count == i || k == i || (k + 1) % vertices.Count == j || k == j) { continue; // ignore incident edges } Vector2 intersectionPoint; if (LineTools.LineIntersect(At(i, vertices), At(j, vertices), At(k, vertices), At(k + 1, vertices), out intersectionPoint)) { return(false); } } return(true); }
public static Option Registration() { ConsoleWriter.ClearScreen(); var lines = File.ReadAllLines(@"UI/maps/4a.Registration.txt"); var drawables = TextEditor.Add.DrawablesAt(lines, 0); TextEditor.Center.AllUnitsInXDir(drawables, Console.WindowWidth); TextEditor.Center.InYDir(drawables, Console.WindowHeight); ConsoleWriter.TryAppend(drawables); ConsoleWriter.Update(); Func <IDrawable, (int X, int Y)> getCoord = drawable => (drawable.CoordinateX + 2, drawable.CoordinateY); var colons = drawables.FindAll(x => x.Chars == ":"); var nameCoord = getCoord(colons[0]); var pass1Coord = getCoord(colons[1]); var pass2Coord = getCoord(colons[2]); Console.ForegroundColor = ConsoleColor.Green; LineTools.SetCursor(nameCoord); var nameLine = new InputLine(nameCoord.X, nameCoord.Y, 30, ConsoleColor.Green); var pass1Line = new InputLine(pass1Coord.X, pass1Coord.Y, 30, ConsoleColor.Green); var pass2Line = new InputLine(pass2Coord.X, pass2Coord.Y, 30, ConsoleColor.Green); var accountName = ""; var password1 = ""; var password2 = ""; do { accountName = nameLine.GetInputString(false); password1 = pass1Line.GetInputString(true); password2 = pass2Line.GetInputString(true); LineTools.ClearAt(nameCoord, accountName); LineTools.ClearAt(pass1Coord, password1); LineTools.ClearAt(pass2Coord, password2); } while (password1 != password2 || accountName.Length <= 5 || password1.Length <= 5); _namepass = (accountName, password1); if (DatabaseManagement.AccountManagement.Exists(accountName, true)) { ConsoleWriter.ClearScreen(); LineTools.SetCursor(nameCoord); Console.Write("Account name is already taken!"); Console.ReadLine(); return(Option.Start); } return(Option.RegisterShip); }
public PointF GetIntersectionTest( PointF lineFirstStar, PointF lineFirstEnd, PointF lineSecondStar, PointF lineSecondEnd ) { PointF result = LineTools.GetIntersection (lineFirstStar, lineFirstEnd, lineSecondStar, lineSecondEnd); return(result); // TODO: 将断言添加到 方法 LineToolsTest.GetIntersectionTest(PointF, PointF, PointF, PointF) }
bool DistanceToHullAcceptable(Vertices polygon, Vector2 point, bool higherDetail) { if (polygon == null) { throw new ArgumentNullException(nameof(polygon), "'polygon' can't be null."); } if (polygon.Count < 3) { throw new ArgumentException("'polygon.Count' can't be less then 3."); } Vector2 edgeVertex2 = polygon[polygon.Count - 1]; Vector2 edgeVertex1; if (higherDetail) { for (int i = 0; i < polygon.Count; i++) { edgeVertex1 = polygon[i]; if (LineTools.DistanceBetweenPointAndLineSegment(ref point, ref edgeVertex1, ref edgeVertex2) <= _hullTolerance || Vector2.Distance(point, edgeVertex1) <= _hullTolerance) { return(false); } edgeVertex2 = polygon[i]; } return(true); } else { for (int i = 0; i < polygon.Count; i++) { edgeVertex1 = polygon[i]; if (LineTools.DistanceBetweenPointAndLineSegment(ref point, ref edgeVertex1, ref edgeVertex2) <= _hullTolerance) { return(false); } edgeVertex2 = polygon[i]; } return(true); } }
private static bool CanSee(int i, int j, Vertices vertices) { if (Reflex(i, vertices)) { if (LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices)) && RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices))) { return(false); } } else { if (RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices)) || LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices))) { return(false); } } if (Reflex(j, vertices)) { if (LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices)) && RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices))) { return(false); } } else { if (RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices)) || LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices))) { return(false); } } for (int k = 0; k < vertices.Count; ++k) { if ((k + 1) % vertices.Count == i || k == i || (k + 1) % vertices.Count == j || k == j) { continue; // ignore incident edges } //if(QLineF(at(i), at(j)).intersect(QLineF(at(k), at(k + 1)), NULL) == QLineF::BoundedIntersection) { if (LineTools.LineIntersect(At(i, vertices), At(j, vertices), At(k, vertices), At(k + 1, vertices)) != Vector2.Zero) { return(false); } } return(true); }
private static void SimplifySection(Vertices vertices, int i, int j, bool[] usePoint, float distanceTolerance) { if ((i + 1) == j) { return; } Vector2 a = vertices[i]; Vector2 b = vertices[j]; double maxDistance = -1.0; int maxIndex = i; for (int k = i + 1; k < j; k++) { Vector2 point = vertices[k]; double distance = LineTools.DistanceBetweenPointAndLineSegment(ref point, ref a, ref b); if (distance > maxDistance) { maxDistance = distance; maxIndex = k; } } if (maxDistance <= distanceTolerance) { for (int k = i + 1; k < j; k++) { usePoint[k] = false; } } else { SimplifySection(vertices, i, maxIndex, usePoint, distanceTolerance); SimplifySection(vertices, maxIndex, j, usePoint, distanceTolerance); } }
public static Option Account() { ConsoleWriter.ClearScreen(); var lines = File.ReadAllLines(@"UI/maps/6.Account.txt"); var drawables = TextEditor.Add.DrawablesAt(lines, 0); TextEditor.Center.ToScreen(drawables, Console.WindowWidth, Console.WindowHeight); var parameterCoords = drawables.FindAll(x => x.Chars == "¤").ToList() .Select(x => (x.CoordinateX, x.CoordinateY)).ToList(); var nameCoord = parameterCoords[0]; var shipCoord = parameterCoords[1]; var selectionList = new SelectionList <Option>(ForegroundColor, '$'); selectionList.GetCharPositions(drawables); selectionList.AddSelections(new[] { Option.Parking, Option.Receipts, Option.ReRegisterShip, Option.Homeplanet, Option.Logout, Option.Exit }); ConsoleWriter.TryAppend(drawables); ConsoleWriter.Update(); Console.ForegroundColor = ConsoleColor.Green; LineTools.SetCursor(nameCoord); Console.Write(_account.User.Name); LineTools.SetCursor(shipCoord); Console.Write(_account.SpaceShip.Model); return(selectionList.GetSelection()); }
/// <summary> /// Calculates all intersections between two polygons. /// </summary> /// <param name="polygon1">The first polygon.</param> /// <param name="polygon2">The second polygon.</param> /// <param name="slicedPoly1">Returns the first polygon with added intersection points.</param> /// <param name="slicedPoly2">Returns the second polygon with added intersection points.</param> private static void CalculateIntersections(Vertices polygon1, Vertices polygon2, out Vertices slicedPoly1, out Vertices slicedPoly2) { slicedPoly1 = new Vertices(polygon1); slicedPoly2 = new Vertices(polygon2); // Iterate through polygon1's edges for (int i = 0; i < polygon1.Count; i++) { // Get edge vertices Vector2 a = polygon1[i]; Vector2 b = polygon1[polygon1.NextIndex(i)]; // Get intersections between this edge and polygon2 for (int j = 0; j < polygon2.Count; j++) { Vector2 c = polygon2[j]; Vector2 d = polygon2[polygon2.NextIndex(j)]; Vector2 intersectionPoint; // Check if the edges intersect if (LineTools.LineIntersect(a, b, c, d, out intersectionPoint)) { // calculate alpha values for sorting multiple intersections points on a edge float alpha; // Insert intersection point into first polygon alpha = GetAlpha(a, b, intersectionPoint); if (alpha > 0f && alpha < 1f) { int index = slicedPoly1.IndexOf(a) + 1; while (index < slicedPoly1.Count && GetAlpha(a, b, slicedPoly1[index]) <= alpha) { ++index; } slicedPoly1.Insert(index, intersectionPoint); } // Insert intersection point into second polygon alpha = GetAlpha(c, d, intersectionPoint); if (alpha > 0f && alpha < 1f) { int index = slicedPoly2.IndexOf(c) + 1; while (index < slicedPoly2.Count && GetAlpha(c, d, slicedPoly2[index]) <= alpha) { ++index; } slicedPoly2.Insert(index, intersectionPoint); } } } } // Check for very small edges for (int i = 0; i < slicedPoly1.Count; ++i) { int iNext = slicedPoly1.NextIndex(i); //If they are closer than the distance remove vertex if ((slicedPoly1[iNext] - slicedPoly1[i]).sqrMagnitude <= ClipperEpsilonSquared) { slicedPoly1.RemoveAt(i); --i; } } for (int i = 0; i < slicedPoly2.Count; ++i) { int iNext = slicedPoly2.NextIndex(i); //If they are closer than the distance remove vertex if ((slicedPoly2[iNext] - slicedPoly2[i]).sqrMagnitude <= ClipperEpsilonSquared) { slicedPoly2.RemoveAt(i); --i; } } }
private static List <Vertices> TriangulatePolygon(Vertices vertices) { List <Vertices> list = new List <Vertices>(); Vector2 lowerInt = new Vector2(); Vector2 upperInt = new Vector2(); // intersection points int lowerIndex = 0, upperIndex = 0; Vertices lowerPoly, upperPoly; for (int i = 0; i < vertices.Count; ++i) { if (Reflex(i, vertices)) { float upperDist; float lowerDist = upperDist = float.MaxValue; for (int j = 0; j < vertices.Count; ++j) { // if line intersects with an edge float d; Vector2 p; if (Left(At(i - 1, vertices), At(i, vertices), At(j, vertices)) && RightOn(At(i - 1, vertices), At(i, vertices), At(j - 1, vertices))) { // find the point of intersection p = LineTools.LineIntersect(At(i - 1, vertices), At(i, vertices), At(j, vertices), At(j - 1, vertices)); if (Right(At(i + 1, vertices), At(i, vertices), p)) { // make sure it's inside the poly d = SquareDist(At(i, vertices), p); if (d < lowerDist) { // keep only the closest intersection lowerDist = d; lowerInt = p; lowerIndex = j; } } } if (Left(At(i + 1, vertices), At(i, vertices), At(j + 1, vertices)) && RightOn(At(i + 1, vertices), At(i, vertices), At(j, vertices))) { p = LineTools.LineIntersect(At(i + 1, vertices), At(i, vertices), At(j, vertices), At(j + 1, vertices)); if (Left(At(i - 1, vertices), At(i, vertices), p)) { d = SquareDist(At(i, vertices), p); if (d < upperDist) { upperDist = d; upperIndex = j; upperInt = p; } } } } // if there are no vertices to connect to, choose a point in the middle if (lowerIndex == (upperIndex + 1) % vertices.Count) { Vector2 p = ((lowerInt + upperInt) / 2); lowerPoly = Copy(i, upperIndex, vertices); lowerPoly.Add(p); upperPoly = Copy(lowerIndex, i, vertices); upperPoly.Add(p); } else { double highestScore = 0, bestIndex = lowerIndex; while (upperIndex < lowerIndex) { upperIndex += vertices.Count; } for (int j = lowerIndex; j <= upperIndex; ++j) { if (CanSee(i, j, vertices)) { double score = 1 / (SquareDist(At(i, vertices), At(j, vertices)) + 1); if (Reflex(j, vertices)) { if (RightOn(At(j - 1, vertices), At(j, vertices), At(i, vertices)) && LeftOn(At(j + 1, vertices), At(j, vertices), At(i, vertices))) { score += 3; } else { score += 2; } } else { score += 1; } if (score > highestScore) { bestIndex = j; highestScore = score; } } } lowerPoly = Copy(i, (int)bestIndex, vertices); upperPoly = Copy((int)bestIndex, i, vertices); } list.AddRange(TriangulatePolygon(lowerPoly)); list.AddRange(TriangulatePolygon(upperPoly)); return(list); } } // polygon is already convex if (vertices.Count > Settings.MaxPolygonVertices) { lowerPoly = Copy(0, vertices.Count / 2, vertices); upperPoly = Copy(vertices.Count / 2, 0, vertices); list.AddRange(TriangulatePolygon(lowerPoly)); list.AddRange(TriangulatePolygon(upperPoly)); } else { list.Add(vertices); } return(list); }
public static Option Identification() { ConsoleWriter.ClearScreen(); var lines = File.ReadAllLines(@"UI/maps/3a.Identification.txt"); var drawables = TextEditor.Add.DrawablesAt(lines, 0); TextEditor.Center.ToScreen(drawables, Console.WindowWidth, Console.WindowHeight); ConsoleWriter.TryAppend(drawables); ConsoleWriter.Update(); Console.CursorVisible = true; Console.ForegroundColor = ConsoleColor.Green; Func <string, (int X, int Y)> GetCoord = chr => { var drawable = drawables.Find(x => x.Chars == chr); return(drawable.CoordinateX, drawable.CoordinateY); }; Action <string> Clear = clear => { Console.CursorVisible = false; foreach (var c in clear) { Console.Write(" "); } Console.CursorVisible = true; }; var fCoord = GetCoord("F"); var nameEndCoord = GetCoord(":"); LineTools.SetCursor((nameEndCoord.X + 2, nameEndCoord.Y)); var username = Console.ReadLine(); LineTools.ClearAt(fCoord, "First name: " + username); Console.Write("Security question loading..."); Func <string, string> getSecurityAnswer = securityQuestion => { LineTools.ClearAt(fCoord, "Security question loading..."); Console.Write(securityQuestion + " "); return(Console.ReadLine()); }; var user = DatabaseManagement.AccountManagement.IdentifyWithQuestion(username, getSecurityAnswer); LineTools.ClearAt(fCoord, "Security question loading... plus the long answer that i cleared now!"); if (user == null) { ConsoleWriter.ClearScreen(); LineTools.SetCursor(fCoord); Console.Write("Incorrect answer or incorrect name input"); Console.ReadKey(true); return(Option.Start); } var registrationExists = DatabaseManagement.AccountManagement.Exists(username, true); var userExists = DatabaseManagement.AccountManagement.Exists(user.Name, false); if (registrationExists == false && userExists == false) { _account.User = user; return(Option.Registration); } LineTools.SetCursor(fCoord); Console.WriteLine("User is already registered"); Thread.Sleep(1000); return(Option.Start); }
/// <summary> /// Precondition: Counter Clockwise polygon /// Decompose the polygon into several smaller non-concave polygon. /// If the polygon is already convex, it will return the original polygon, unless it is over Settings.MaxPolygonVertices. /// </summary> /// <param name="vertices"></param> /// <returns></returns> public static List <Vertices> ConvexPartition(Vertices vertices) { List <Vertices> list = new List <Vertices>(); float d, dist1, dist2; Vector2 ip; Vector2 ip1 = new Vector2(); Vector2 ip2 = new Vector2(); // intersection points int ind1 = 0, ind2 = 0; Vertices poly1, poly2; for (int i = 0; i < vertices.Count; ++i) { if (Reflex(i, vertices)) { dist1 = dist2 = float.MaxValue; // std::numeric_limits<qreal>::max(); for (int j = 0; j < vertices.Count; ++j) { if (Left(At(i - 1, vertices), At(i, vertices), At(j, vertices)) && RightOn(At(i - 1, vertices), At(i, vertices), At(j - 1, vertices))) { // if ray (i-1)->(i) intersects with edge (j, j-1) //QLineF(at(i - 1), at(i)).intersect(QLineF(at(j), at(j - 1)), ip); ip = LineTools.LineIntersect(At(i - 1, vertices), At(i, vertices), At(j, vertices), At(j - 1, vertices)); if (Right(At(i + 1, vertices), At(i, vertices), ip)) { // intersection point isn't caused by backwards ray d = SquareDist(At(i, vertices), ip); if (d < dist1) { // take the closest intersection so we know it isn't blocked by another edge dist1 = d; ind1 = j; ip1 = ip; } } } if (Left(At(i + 1, vertices), At(i, vertices), At(j + 1, vertices)) && RightOn(At(i + 1, vertices), At(i, vertices), At(j, vertices))) { // if ray (i+1)->(i) intersects with edge (j+1, j) //QLineF(at(i + 1), at(i)).intersect(QLineF(at(j), at(j + 1)), ip); ip = LineTools.LineIntersect(At(i + 1, vertices), At(i, vertices), At(j, vertices), At(j + 1, vertices)); if (Left(At(i - 1, vertices), At(i, vertices), ip)) { d = SquareDist(At(i, vertices), ip); if (d < dist2) { dist2 = d; ind2 = j; ip2 = ip; } } } } if (ind1 == (ind2 + 1) % vertices.Count) { // no vertices in range Vector2 sp = ((ip1 + ip2) / 2); poly1 = Copy(i, ind2, vertices); poly1.Add(sp); poly2 = Copy(ind1, i, vertices); poly2.Add(sp); } else { double highestScore = 0, bestIndex = ind1; while (ind2 < ind1) { ind2 += vertices.Count; } for (int j = ind1; j <= ind2; ++j) { if (CanSee(i, j, vertices)) { double score = 1 / (SquareDist(At(i, vertices), At(j, vertices)) + 1); if (Reflex(j, vertices)) { if (RightOn(At(j - 1, vertices), At(j, vertices), At(i, vertices)) && LeftOn(At(j + 1, vertices), At(j, vertices), At(i, vertices))) { score += 3; } else { score += 2; } } else { score += 1; } if (score > highestScore) { bestIndex = j; highestScore = score; } } } poly1 = Copy(i, (int)bestIndex, vertices); poly2 = Copy((int)bestIndex, i, vertices); } list.AddRange(ConvexPartition(poly1)); list.AddRange(ConvexPartition(poly2)); return(list); } } // polygon is already convex if (vertices.Count > Settings.MaxPolygonVertices) { poly1 = Copy(0, vertices.Count / 2, vertices); poly2 = Copy(vertices.Count / 2, 0, vertices); list.AddRange(ConvexPartition(poly1)); list.AddRange(ConvexPartition(poly2)); } else { list.Add(vertices); } //The polygons are not guaranteed to be without collinear points. We remove //them to be sure. for (int i = 0; i < list.Count; i++) { list[i] = SimplifyTools.CollinearSimplify(list[i], 0); } return(list); }
//TODO: Reenable the rounding if it is necessary for the boolean tools to work. /// <summary> /// Rounds vertices X and Y values to whole numbers. /// </summary> /// <param name="polygon">The polygon whose vertices should be rounded.</param> /// <returns>A new polygon with rounded vertices.</returns> //public static Vertices Round(Vertices polygon) //{ // Vertices returnPoly = new Vertices(); // for (int i = 0; i < polygon.Count; i++) // returnPoly.Add(new Vector2((float)Math.Round(polygon[i].X, 0), (float)Math.Round(polygon[i].Y, 0))); // return returnPoly; //} /// <summary> /// Determines if three vertices are collinear (ie. on a straight line) /// </summary> /// <param name="p1">Vertex 1</param> /// <param name="p2">Vertex 2</param> /// <param name="p3">Vertex 3</param> /// <returns></returns> public static bool VerticesAreCollinear(ref Vector2 p1, ref Vector2 p2, ref Vector2 p3) { float collinearity = (p3.X - p1.X) * (p2.Y - p1.Y) + (p3.Y - p1.Y) * (p1.X - p2.X); return(LineTools.FloatEquals(collinearity, 0, 0.00001f)); }
private bool SplitPolygonEdge(Vertices polygon, Vector2 coordInsideThePolygon, out int vertex1Index, out int vertex2Index) { Vector2 slope; int nearestEdgeVertex1Index = 0; int nearestEdgeVertex2Index = 0; bool edgeFound = false; float shortestDistance = float.MaxValue; bool edgeCoordFound = false; Vector2 foundEdgeCoord = Vector2.Zero; List <float> xCoords = SearchCrossingEdges(polygon, (int)coordInsideThePolygon.Y); vertex1Index = 0; vertex2Index = 0; foundEdgeCoord.Y = coordInsideThePolygon.Y; if (xCoords != null && xCoords.Count > 1 && xCoords.Count % 2 == 0) { float distance; for (int i = 0; i < xCoords.Count; i++) { if (xCoords[i] < coordInsideThePolygon.X) { distance = coordInsideThePolygon.X - xCoords[i]; if (distance < shortestDistance) { shortestDistance = distance; foundEdgeCoord.X = xCoords[i]; edgeCoordFound = true; } } } if (edgeCoordFound) { shortestDistance = float.MaxValue; int edgeVertex2Index = polygon.Count - 1; int edgeVertex1Index; for (edgeVertex1Index = 0; edgeVertex1Index < polygon.Count; edgeVertex1Index++) { Vector2 tempVector1 = polygon[edgeVertex1Index]; Vector2 tempVector2 = polygon[edgeVertex2Index]; distance = LineTools.DistanceBetweenPointAndLineSegment(ref foundEdgeCoord, ref tempVector1, ref tempVector2); if (distance < shortestDistance) { shortestDistance = distance; nearestEdgeVertex1Index = edgeVertex1Index; nearestEdgeVertex2Index = edgeVertex2Index; edgeFound = true; } edgeVertex2Index = edgeVertex1Index; } if (edgeFound) { slope = polygon[nearestEdgeVertex2Index] - polygon[nearestEdgeVertex1Index]; slope.Normalize(); Vector2 tempVector = polygon[nearestEdgeVertex1Index]; distance = Vector2.Distance(tempVector, foundEdgeCoord); vertex1Index = nearestEdgeVertex1Index; vertex2Index = nearestEdgeVertex1Index + 1; polygon.Insert(nearestEdgeVertex1Index, distance * slope + polygon[vertex1Index]); polygon.Insert(nearestEdgeVertex1Index, distance * slope + polygon[vertex2Index]); return(true); } } } return(false); }
/// <summary> /// Decompose the polygon into several smaller non-concave polygon. /// If the polygon is already convex, it will return the original polygon, unless it is over Settings.MaxPolygonVertices. /// Precondition: Counter Clockwise polygon /// </summary> /// <param name="vertices"></param> /// <returns></returns> public static List <Vertices> ConvexPartition(Vertices vertices) { //We force it to CCW as it is a precondition in this algorithm. vertices.ForceCounterClockWise(); List <Vertices> list = new List <Vertices>(); float d, lowerDist, upperDist; Vector2 p; Vector2 lowerInt = new Vector2(); Vector2 upperInt = new Vector2(); // intersection points int lowerIndex = 0, upperIndex = 0; Vertices lowerPoly, upperPoly; for (int i = 0; i < vertices.Count; ++i) { if (Reflex(i, vertices)) { lowerDist = upperDist = float.MaxValue; // std::numeric_limits<qreal>::max(); for (int j = 0; j < vertices.Count; ++j) { // if line intersects with an edge if (Left(At(i - 1, vertices), At(i, vertices), At(j, vertices)) && RightOn(At(i - 1, vertices), At(i, vertices), At(j - 1, vertices))) { // find the point of intersection p = LineTools.LineIntersect(At(i - 1, vertices), At(i, vertices), At(j, vertices), At(j - 1, vertices)); if (Right(At(i + 1, vertices), At(i, vertices), p)) { // make sure it's inside the poly d = SquareDist(At(i, vertices), p); if (d < lowerDist) { // keep only the closest intersection lowerDist = d; lowerInt = p; lowerIndex = j; } } } if (Left(At(i + 1, vertices), At(i, vertices), At(j + 1, vertices)) && RightOn(At(i + 1, vertices), At(i, vertices), At(j, vertices))) { p = LineTools.LineIntersect(At(i + 1, vertices), At(i, vertices), At(j, vertices), At(j + 1, vertices)); if (Left(At(i - 1, vertices), At(i, vertices), p)) { d = SquareDist(At(i, vertices), p); if (d < upperDist) { upperDist = d; upperIndex = j; upperInt = p; } } } } // if there are no vertices to connect to, choose a point in the middle if (lowerIndex == (upperIndex + 1) % vertices.Count) { Vector2 sp = ((lowerInt + upperInt) / 2); lowerPoly = Copy(i, upperIndex, vertices); lowerPoly.Add(sp); upperPoly = Copy(lowerIndex, i, vertices); upperPoly.Add(sp); } else { double highestScore = 0, bestIndex = lowerIndex; while (upperIndex < lowerIndex) { upperIndex += vertices.Count; } for (int j = lowerIndex; j <= upperIndex; ++j) { if (CanSee(i, j, vertices)) { double score = 1 / (SquareDist(At(i, vertices), At(j, vertices)) + 1); if (Reflex(j, vertices)) { if (RightOn(At(j - 1, vertices), At(j, vertices), At(i, vertices)) && LeftOn(At(j + 1, vertices), At(j, vertices), At(i, vertices))) { score += 3; } else { score += 2; } } else { score += 1; } if (score > highestScore) { bestIndex = j; highestScore = score; } } } lowerPoly = Copy(i, (int)bestIndex, vertices); upperPoly = Copy((int)bestIndex, i, vertices); } list.AddRange(ConvexPartition(lowerPoly)); list.AddRange(ConvexPartition(upperPoly)); return(list); } } // polygon is already convex if (vertices.Count > Settings.MaxPolygonVertices) { lowerPoly = Copy(0, vertices.Count / 2, vertices); upperPoly = Copy(vertices.Count / 2, 0, vertices); list.AddRange(ConvexPartition(lowerPoly)); list.AddRange(ConvexPartition(upperPoly)); } else { list.Add(vertices); } //The polygons are not guaranteed to be without collinear points. We remove //them to be sure. for (int i = 0; i < list.Count; i++) { list[i] = SimplifyTools.CollinearSimplify(list[i], 0); } //Remove empty vertice collections for (int i = list.Count - 1; i >= 0; i--) { if (list[i].Count == 0) { list.RemoveAt(i); } } return(list); }
public static Option Parking() { ConsoleWriter.ClearScreen(); var lines = File.ReadAllLines(@"UI/maps/7.Parking.txt"); var drawables = TextEditor.Add.DrawablesAt(lines, 0); TextEditor.Center.ToScreen(drawables, Console.WindowWidth, Console.WindowHeight); var selectionList = new SelectionList <Option>(ConsoleColor.Green, '$'); selectionList.GetCharPositions(drawables); selectionList.AddSelections(new[] { Option.PurchaseTicket, Option.ReEnterhours, Option.Account }); var drawProps = drawables.FindAll(x => x.Chars == "¤"); var props = drawProps.Select(x => (x.CoordinateX, x.CoordinateY)).ToList(); var parkFromXY = props[0]; var pricePerHourXY = props[1]; var shipLengthXY = props[2]; var calculatedPriceXY = props[3]; var enterHoursXY = props[4]; var receiptXY = props[5]; var openNext = DatabaseManagement.ParkingManagement.CheckParkingStatus(); Console.ForegroundColor = ConsoleColor.Green; LineTools.SetCursor(parkFromXY); if (openNext.isOpen) { Console.Write("Now"); } else { Console.Write(openNext.nextAvailable); } LineTools.SetCursor(pricePerHourXY); Console.Write(DatabaseManagement.ParkingManagement.CalculatePrice(_account.SpaceShip, 1) * 60); LineTools.SetCursor(shipLengthXY); Console.Write(_account.SpaceShip.ShipLength); ConsoleWriter.TryAppend(drawables.Except(drawProps).ToList()); ConsoleWriter.Update(); Option menuSel; double hours; var timeGetter = new TimeGetter(enterHoursXY, calculatedPriceXY, 10000, DatabaseManagement.ParkingManagement.CalculatePrice); if (openNext.isOpen == false) { Console.ReadKey(true); return(Option.Account); } do { hours = timeGetter.GetMinutes(_account.SpaceShip); menuSel = selectionList.GetSelection(); if (menuSel == Option.PurchaseTicket && hours == 0) { menuSel = Option.ReEnterhours; } } while (menuSel == Option.ReEnterhours); if (Option.PurchaseTicket == menuSel) { ConsoleWriter.ClearScreen(); var receipt = DatabaseManagement.ParkingManagement.SendInvoice(_account, hours); var boxData = new BoxData((Console.WindowWidth / 2 - 10, parkFromXY.CoordinateY)); boxData.Update(new[] { "Loading receipt..." }); string[] receiptString = { "Purchase successful!", "", "Ticket Holder: " + receipt.Account.AccountName, "Start time: " + receipt.StartTime, "End time: " + receipt.EndTime, "Price: " + receipt.Price }; boxData.Update(receiptString); Console.ReadKey(true); } return(Option.Account); }