public bool TwoSegmentsIntersectionTest(Line L1, Line L2) { Enums.TurnType first_orientation = HelperMethods.CheckTurn(L1, L2.Start); Enums.TurnType second_orientation = HelperMethods.CheckTurn(L1, L2.End); Enums.TurnType third_orientation = HelperMethods.CheckTurn(L2, L1.Start); Enums.TurnType fourth_orientation = HelperMethods.CheckTurn(L2, L1.End); if (first_orientation != second_orientation && third_orientation != fourth_orientation) { return(true); } if (first_orientation == Enums.TurnType.Colinear && HelperMethods.PointOnSegment(L2.Start, L1.Start, L1.End)) { return(true); } if (second_orientation == Enums.TurnType.Colinear && HelperMethods.PointOnSegment(L2.End, L1.Start, L1.End)) { return(true); } if (third_orientation == Enums.TurnType.Colinear && HelperMethods.PointOnSegment(L1.Start, L2.Start, L2.End)) { return(true); } if (fourth_orientation == Enums.TurnType.Colinear && HelperMethods.PointOnSegment(L1.End, L2.Start, L2.End)) { return(true); } return(false); }
public bool polygonInCCW(List <Point> polygon) { // 1. Get Point with Min X double extMin = 1e9; int minPointIndex = -1; for (int i = 0; i < polygon.Count; ++i) { if ((polygon[i].X < extMin) || (polygon[i].X == extMin && polygon[i].Y < polygon[minPointIndex].Y)) { extMin = polygon[i].X; minPointIndex = i; } } int prev, next; prev = HelperMethods.getPrevIndex(minPointIndex, polygon.Count); next = HelperMethods.getNextIndex(minPointIndex, polygon.Count); Line line = new Line(polygon[prev], polygon[next]); Enums.TurnType type = HelperMethods.CheckTurn(line, polygon[minPointIndex]); if (type == Enums.TurnType.Left) { return(false); } else { return(true); } }
public bool polygonCCW(List <Point> myPolygon) { double mini = 1e9; int minPointIndex = -1; for (int i = 0; i < myPolygon.Count; i++) { if (myPolygon[i].X < mini || myPolygon[i].X == mini && myPolygon[i].Y < myPolygon[minPointIndex].Y) { mini = myPolygon[i].X; minPointIndex = i; } } int prev, next; prev = HelperMethods.getPrevIndex(minPointIndex, myPolygon.Count); next = HelperMethods.getNextIndex(minPointIndex, myPolygon.Count); Line line = new Line(myPolygon[prev], myPolygon[next]); Enums.TurnType type = HelperMethods.CheckTurn(line, myPolygon[minPointIndex]); if (type == Enums.TurnType.Left) { return(false); } else { return(true); } }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { if (points.Count == 0 || polygons.Count == 0) { return; } int idx = 0; Enums.TurnType prevSide = Enums.TurnType.Left;//dummy value bool inside = true; foreach (Point p in points) { idx = 0; inside = true; foreach (Line l in polygons[0].lines) { var curSide = HelperMethods.CheckTurn(l, p); if (idx != 0) { if (curSide != prevSide) { inside = false; } } prevSide = curSide; idx++; } if (inside) { outPoints.Add(p); } } }
public override void Run( List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygon) { bool x = false, y = false; Enums.TurnType e1 = HelperMethods.CheckTurn(lines[0], lines[1].Start); Enums.TurnType e2 = HelperMethods.CheckTurn(lines[0], lines[1].End); if ((e1 == Enums.TurnType.Left && e2 == Enums.TurnType.Left) || (e1 == Enums.TurnType.Right && e2 == Enums.TurnType.Right)) { x = true; } e1 = HelperMethods.CheckTurn(lines[1], lines[0].Start); e2 = HelperMethods.CheckTurn(lines[1], lines[0].End); if ((e1 == Enums.TurnType.Left && e2 == Enums.TurnType.Left) || (e1 == Enums.TurnType.Right && e2 == Enums.TurnType.Right)) { y = true; } if (!x && !y) { outLines.Add(lines[0]); } }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { /* * [on purpose] * don't handle repeated points * neither colinear points */ if (polygons[0].lines.Count != 3) {// not a triangle return; } Line l1 = polygons[0].lines[0]; Line l2 = polygons[0].lines[1]; Line l3 = polygons[0].lines[2]; Point p = points[0]; Enums.TurnType t1 = HelperMethods.CheckTurn(l1, p); Enums.TurnType t2 = HelperMethods.CheckTurn(l2, p); Enums.TurnType t3 = HelperMethods.CheckTurn(l3, p); // have to be inside the triangle not colinear with one of the edges // not repeated points if (t1 == t2 && t2 == t3) { outPoints.Add(p); } return; }
public Participant AddParticipant(Guid gameId, Guid categoryId, Enums.TurnType turnType, string userId) { try { var duplicateParticipants = _context.Participants.Where(x => x.GameId == gameId && x.UserId == userId && x.Deleted == null); if (duplicateParticipants.Any()) { throw new DataException("User is already participating in this game."); } var participant = new Participant() { UserId = userId, GameId = gameId, TurnType = turnType }; var addedparticipant = _context.Add(participant).Entity; var gameCategory = new GameCategory() { CategoryId = categoryId, GameId = gameId, ParticipantId = addedparticipant.Id }; _context.Add(gameCategory); _context.SaveChanges(); return(addedparticipant); } catch (Exception e) { throw new DataException("Could not add new participant", e); } }
public override void Run( List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygon) { int left = 0, right = 0; for (int i = 0; i < polygons[0].lines.Count; i++) { Enums.TurnType e = HelperMethods.CheckTurn(polygons[0].lines[i], points[0]); if (e == Enums.TurnType.Left) { left++; } else if (e == Enums.TurnType.Right) { right++; } } if (left == 3 || right == 3) { outLines.Add(polygons[0].lines[0]); outLines.Add(polygons[0].lines[1]); outLines.Add(polygons[0].lines[2]); } else { outPoints.Add(points[0]); } }
public void OnPress(object sender, EventArgs e) { var pressedButton = sender as Button; Enums.TurnType turnType = default; currentPlayer = currentPlayer == 1 ? 2 : 1; switch (currentPlayer) { case 1: turnType = Enums.TurnType.Cross; pressedButton.BackgroundImage = crossImage; pressedButton.Enabled = false; break; case 2: turnType = Enums.TurnType.Zero; pressedButton.BackgroundImage = zeroImage; pressedButton.Enabled = false; break; } if (_buttonsMap.TryGetValue(pressedButton.Name, out var turnPoint)) { _gameController.MakeTurn(turnPoint, turnType); } if (_gameController.CheckState()) { MessageBox.Show("Game ended. New game started a few moment later!"); RenderTableWithButtons(); } }
public bool LinesIntersect(Line l1, Line l2) { bool x = false, y = false; Enums.TurnType e1 = HelperMethods.CheckTurn(l1, l2.Start); Enums.TurnType e2 = HelperMethods.CheckTurn(l1, l2.End); if ((e1 == Enums.TurnType.Left && e2 == Enums.TurnType.Left) || (e1 == Enums.TurnType.Right && e2 == Enums.TurnType.Right)) { x = true; } e1 = HelperMethods.CheckTurn(l2, l1.Start); e2 = HelperMethods.CheckTurn(l2, l1.End); if ((e1 == Enums.TurnType.Left && e2 == Enums.TurnType.Left) || (e1 == Enums.TurnType.Right && e2 == Enums.TurnType.Right)) { y = true; } if (x || y) { return(false); } else { return(true); } }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { if (points.Count <= 3) { outPoints = points; return; } //get extreames(minX, maxX) Point minXP = new Point(0, 0), maxXP = new Point(0, 0); double minx = 100000000; double maxx = -100000000; for (int i = 0; i < points.Count; i++) { if (points[i].X < minx) { minx = points[i].X; minXP = points[i]; } if (points[i].X > maxx) { maxx = points[i].X; maxXP = points[i]; } } //add two points to quickhull CH.Add(minXP); CH.Add(maxXP); //make a line btw them Line lineL = new Line(minXP, maxXP); Line lineR = new Line(maxXP, minXP); //split data List <Point> left = new List <Point>(); List <Point> right = new List <Point>(); for (int i = 0; i < points.Count; i++) { Enums.TurnType turnType = HelperMethods.CheckTurn(lineL, points[i]); if (turnType == Enums.TurnType.Left) { left.Add(points[i]); } else if (turnType == Enums.TurnType.Right) { right.Add(points[i]); } } Quickhull(left, lineL); Quickhull(right, lineR); outPoints = CH; }
public void Quickhull(List <Point> points, Line line) { //for each point get h //then get max h //cross(a,b) = 1/4 b*h //get h if (points.Count <= 0) { return; } double maxh = 0; Point maxP = new Point(0, 0); for (int i = 0; i < points.Count; i++) { double h = getH(line, points[i]); if (Math.Abs(h) > maxh) { maxh = h; maxP = points[i]; } } //add the point to convex hull CH.Add(maxP); List <Point> leftPoints = new List <Point>(); List <Point> rightPoints = new List <Point>(); Line leftLine = new Line(line.Start, maxP); Line rightLine = new Line(maxP, line.End); for (int i = 0; i < points.Count; i++) { Enums.TurnType turnType = HelperMethods.CheckTurn(leftLine, points[i]); Enums.PointInPolygon pointInPolygon = HelperMethods.PointInTriangle(points[i], maxP, line.Start, line.End); if (turnType == Enums.TurnType.Left) { leftPoints.Add(points[i]); } else if (pointInPolygon == Enums.PointInPolygon.Outside) { rightPoints.Add(points[i]); } // turnType = HelperMethods.CheckTurn(rightLine, points[i]); // if (turnType == Enums.TurnType.Right) rightPoints.Add(points[i]); } Quickhull(leftPoints, leftLine); Quickhull(rightPoints, rightLine); }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { /* * how to handle buggy cases with H and V lines !?? */ Line l1 = lines[0]; Line l2 = lines[1]; if (parallel_line(l1, l2)) { return; } double s1 = (l1.Start.Y - l1.End.Y) / (l1.Start.X - l1.End.X); double s2 = (l2.Start.Y - l2.End.Y) / (l2.Start.X - l2.End.X); double b1 = l1.Start.Y - s1 * l1.Start.X; double b2 = l2.Start.Y - s2 * l2.Start.X; // point of intersection (treating segments as lines) double y = (s2 * b1 - s1 * b2) / (s2 - s1); double x = 0; if (s1 != 0) { x = (y - b1) / s1; // BUG it divides by zero and the test cases have Horizontal line and this give x =nan as inter point which } // can't be drawn on the canves else { x = (y - b2) / s2; } // check if the point is inside th segments /* * // naive logic * if(x >= Math.Min(l1.Start.X , l1.End.X) && x <= Math.Max(l1.Start.X, l1.End.X)) * if (y >= Math.Min(l1.Start.Y, l1.End.Y) && y <= Math.Max(l1.Start.Y, l1.End.Y)) * if (x >= Math.Min(l2.Start.X, l2.End.X) && x <= Math.Max(l2.Start.X, l2.End.X)) * if (y >= Math.Min(l2.Start.Y, l2.End.Y) && y <= Math.Max(l2.Start.Y, l2.End.Y)) * outPoints.Add(new Point(x, y)); */ // using orientation test Enums.TurnType t1 = HelperMethods.CheckTurn(l1, l2.Start); Enums.TurnType t2 = HelperMethods.CheckTurn(l1, l2.End); Enums.TurnType t3 = HelperMethods.CheckTurn(l2, l1.Start); Enums.TurnType t4 = HelperMethods.CheckTurn(l2, l1.End); if (t1 != t2 && t3 != t4) { outPoints.Add(new Point(x, y)); } }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { HashSet <PointComparer> hashP = new HashSet <PointComparer>(); for (int i = 0; i < points.Count; ++i) { hashP.Add(new PointComparer(points[i])); } PointComparer[] res = hashP.ToArray(); points.Clear(); for (int i = 0; i < res.Length; ++i) { points.Add(res[i].p); } if (points.Count < 4) { outPoints = new List <Point>(points); return; } HashSet <Point> setPoints = new HashSet <Point>(); for (int i = 0; i < points.Count; ++i) { for (int j = i + 1; j < points.Count; ++j) { Enums.TurnType turn = HelperMethods.CheckTurn(new Line(points[i], points[j]), points[0]); bool ok = true; for (int k = 0; k < points.Count; ++k) { if (valid(i, j, k)) { Enums.TurnType curTurn = HelperMethods.CheckTurn(new Line(points[i], points[j]), points[k]); turn = (turn == Enums.TurnType.Colinear) ? curTurn : turn; if (curTurn != Enums.TurnType.Colinear && turn != curTurn) { ok = false; break; } else if (curTurn == Enums.TurnType.Colinear && !HelperMethods.PointOnLine(points[k], points[i], points[j])) { ok = false; break; } } } if (ok) { setPoints.Add(points[i]); setPoints.Add(points[j]); } } } outPoints = new List <Point>(setPoints); }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { if (polygons[0].lines.Count < 3 || points.Count == 0) { // not valid case to be solved return; } // line to right of given point Point a = points[0]; Point b = new Point(a.X + 10000, a.Y); Line vir_line = new Line(a, b); List <Line> poly_segments = polygons[0].lines; // this may be bad practice segment_segment_intersection seg_inter = new segment_segment_intersection(); // do segment - segment intersection for vir_line with all the segments of the concave polygon for (int i = 0; i < poly_segments.Count; i++) { Line poly_seg = poly_segments[i]; // check segment - segment intersection List <Line> tmp_lines = new List <Line>(); tmp_lines.Add(vir_line); tmp_lines.Add(poly_seg); /* * this will add points of intersections to outpoints list * so we have to delete them later */ seg_inter.Run(points, tmp_lines, polygons, ref outPoints, ref outLines, ref outPolygons); // check for colinearity (point is on a polygon segment) Enums.TurnType t = HelperMethods.CheckTurn(poly_seg, a); if (t == Enums.TurnType.Colinear && check_point_inside_segment(poly_seg, a)) { outPoints.Clear(); // clear points of intersections outPoints.Add(a); return; } } // intersect odd number of segments = inside the polygon if (outPoints.Count % 2 != 0) { outPoints.Clear(); // clear points of intersections outPoints.Add(a); } else { outPoints.Clear(); } return; }
public vertexType getVertexType(int index) //index of vertex { Enums.TurnType turn = new Enums.TurnType(); //double angle = 0; Point Prev, Vertex, Next; Vertex = P.lines[index].Start; Next = P.lines[index % P.lines.Count].End; if (index == 0) { Prev = P.lines[P.lines.Count - 1].Start; } else { Prev = P.lines[index - 1].Start; } turn = HelperMethods.CheckTurn(new Line(Prev, Vertex), Next); /* * Point CB = new Point(Vertex.X - Prev.X, Vertex.Y - Prev.Y); * Point BA = new Point(Next.X - Vertex.X , Next.Y - Vertex.Y); * double dot = (CB.X * BA.Y) - (CB.Y * BA.X); * double CBnorm = Math.Sqrt((CB.X * CB.X) + (CB.Y * CB.Y)); * double BAnorm = Math.Sqrt((BA.X * BA.X) + (BA.Y * BA.Y)); * * angle = Math.Abs(Math.Asin(dot / (CBnorm * BAnorm)));*/ //Left <180, Right >180 if (turn == Enums.TurnType.Left && Prev.Y < Vertex.Y && Next.Y < Vertex.Y) { return(vertexType.Start); } else if (turn == Enums.TurnType.Right && Prev.Y < Vertex.Y && Next.Y < Vertex.Y) { return(vertexType.Split); } else if (turn == Enums.TurnType.Left && Prev.Y > Vertex.Y && Next.Y > Vertex.Y) { return(vertexType.End); } else if (turn == Enums.TurnType.Right && Prev.Y > Vertex.Y && Next.Y > Vertex.Y) { return(vertexType.Merge); } else { return(vertexType.Regular); } }
public override void Run( List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygon) { Enums.TurnType e = HelperMethods.CheckTurn(lines[0], points[0]); if (e == Enums.TurnType.Left) { outPoints.Add(points[0]); } else { outLines.Add(lines[0]); } }
public bool isConvex(int pointIndex, List <Point> myPolygon) { int prev, next; prev = HelperMethods.getPrevIndex(pointIndex, myPolygon.Count); next = HelperMethods.getNextIndex(pointIndex, myPolygon.Count); Line line = new Line(myPolygon[prev], myPolygon[pointIndex]); Enums.TurnType type = HelperMethods.CheckTurn(line, myPolygon[next]); if (type == Enums.TurnType.Left) { return(true); } return(false); }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { /* * this function assume that the line is at index 0 * and the segment is at index 1 */ Line l = lines[0]; Line seg = lines[1]; if (parallel_line(l, seg)) { return; } // get point of intersection as if they are lines double s1 = (l.Start.Y - l.End.Y) / (l.Start.X - l.End.X); double s2 = (seg.Start.Y - seg.End.Y) / (seg.Start.X - seg.End.X); double b1 = l.Start.Y - s1 * l.Start.X; double b2 = seg.Start.Y - s2 * seg.Start.X; // point of intersection (treating segments as lines) double y = (s2 * b1 - s1 * b2) / (s2 - s1); double x = (y - b1) / s1; // check the intersection Enums.TurnType t1 = HelperMethods.CheckTurn(l, seg.Start); Enums.TurnType t2 = HelperMethods.CheckTurn(l, seg.End); if (t1 != t2) { Enums.TurnType t3 = HelperMethods.CheckTurn(seg, l.Start); Enums.TurnType t4 = HelperMethods.CheckTurn(seg, l.End); if (t1 == Enums.TurnType.Left && t3 == Enums.TurnType.Right) { outPoints.Add(new Point(x, y)); } else if (t1 == Enums.TurnType.Right && t3 == Enums.TurnType.Left) { outPoints.Add(new Point(x, y)); } // coolinear end points case else if (t3 == Enums.TurnType.Colinear || t4 == Enums.TurnType.Colinear) { outPoints.Add(new Point(x, y)); } } }
private void lastCase(List <Point> p) { Point p1 = p[0], p2 = p[1], np = p.Last(); Enums.TurnType turn = HelperMethods.CheckTurn(new Line(p2, p1), np); if (turn == Enums.TurnType.Right) { p.RemoveAt(0); } else if (turn == Enums.TurnType.Colinear) { if (HelperMethods.distance(p2, p1) < HelperMethods.distance(p2, np)) { p.RemoveAt(0); } } }
public int Compare(Point b, Point c) { /* * function return : * 0 if b == c * 1 if b > c * -1 if b < c * in angular manner * * logic : * check turn * if from a to b to c is turn right so c have less angler value than b return c less then b * else if right left turn si b<c * else if colinear check for furthest one , return any threr will be no problem */ Line seg = new Line(a, b); Enums.TurnType t = HelperMethods.CheckTurn(seg, c); if (t == Enums.TurnType.Right) { return(1); } else if (t == Enums.TurnType.Left) { return(-1); } else {// colinear double bdis = get_dis2(a, b); double cdis = get_dis2(a, c); if (bdis >= cdis) { return(1); } else { return(-1); } } }
public static bool IsSupportLine(Line l, List <Point> points) { int idx = 0; Enums.TurnType prevSide = Enums.TurnType.Left;//dummy value bool inside = true; foreach (Point p in points) { if (p.Equals(l.Start) || p.Equals(l.End)) { continue; } var curSide = HelperMethods.CheckTurn(l, p); if (curSide == Enums.TurnType.Colinear) { var dst1 = Point.GetSqrDistance(l.Start, l.End); var dst2 = Point.GetSqrDistance(l.Start, p); if (dst1 < dst2) { inside = false; break; } } if (idx != 0) { if (curSide != prevSide) { inside = false; break; } } prevSide = curSide; idx++; } return(inside); }
public bool isConvex(LinkedListNode <Point> pointIndex, LinkedList <Point> _polygon) { LinkedListNode <Point> prev = pointIndex.Previous; LinkedListNode <Point> next = pointIndex.Next; if (prev == null) { prev = _polygon.Last; } if (next == null) { next = _polygon.First; } Line line = new Line(prev.Value, pointIndex.Value); Enums.TurnType type = HelperMethods.CheckTurn(line, next.Value); if (type == Enums.TurnType.Left) { return(true); } return(false); }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { if (lines.Count == 0 || polygons.Count == 0) { return; } int idx = 0; Enums.TurnType prevSide = Enums.TurnType.Left;//dummy value bool check; foreach (Line l in lines) { check = true; foreach (Line pl in polygons[0].lines) { var t1 = HelperMethods.CheckTurn(l, pl.Start); var t2 = HelperMethods.CheckTurn(l, pl.End); if (t1 != t2) { check = false; } if (idx != 0) { if (prevSide != t1) { check = false; } } prevSide = t1; idx++; } if (check) { outLines.Add(l); } } }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { /* * this function require lines to have start and end poitns * in a s pecific order CCW or CW * line order it self don't mater */ // as point inside concave polygon is a general algo for // any kind of polygon we can just call the other function here List <Line> l = polygons[0].lines; Point p = points[0]; int left = 0, right = 0; for (int i = 0; i < l.Count; i++) { Line tmp_l = l[i]; // check turn Enums.TurnType t = HelperMethods.CheckTurn(tmp_l, p); if (t == Enums.TurnType.Left) { left += 1; } else if (t == Enums.TurnType.Right) { right += 1; } // else colinear , no problem } if (left == 0 || right == 0) { outPoints.Add(p); } return; }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { // handle non logical cases if (points.Count == 0) { return; } /* * input : set of points * return : segments , points in CCW manner * check how the algo will behave for many colinear points !!!!!! */ int minp_index = get_min_point_index(points); Point minp = points[minp_index]; my_sort_algo anguler_sort = new my_sort_algo(minp); /* * sort the points in angular manner respect to min point * sort using turn left and turn right */ List <Point> sorted_points = points; sorted_points.Sort(anguler_sort); // apply graham scan algo List <Point> hull = new List <Point>(); // *********************** /* * this introduce a bug , why !??? * if(minp!=sorted_points[0]) * { * return; * }*/ // *********************** hull.Add(minp); if (points.Count == 1) { outPoints.Add(minp); return; } hull.Add(sorted_points[1]); for (int i = 2; i < sorted_points.Count; i++) { int index = hull.Count - 1; Point a = hull[index - 1]; Point b = hull[index]; Point c = sorted_points[i]; // check turn Line seg = new Line(a, b); Enums.TurnType t = HelperMethods.CheckTurn(seg, c); if (t == Enums.TurnType.Left) { hull.Add(c); } else if (t == Enums.TurnType.Right) { // c enclose some points that are on the boundary of the hull hull.RemoveAt(hull.Count - 1); // O(1) i -= 1; // don't go further untill we are making left turn // as hull could have more points that are enclosed by c } else // colinear , pick farthest { // only 2 points could be colinear with c // I don't think that we need to get the dis // c is farther than b double bdis = get_dis2(a, b); double cdis = get_dis2(a, c); if (cdis > bdis) { hull.RemoveAt(hull.Count - 1); // O(1) no further elements to shift left hull.Add(c); } } } /* * handle similar points */ if (hull.Count == 2) { if (Math.Abs(hull[0].X - hull[1].X) <= Constants.Epsilon && Math.Abs(hull[0].Y - hull[1].Y) <= Constants.Epsilon) { hull.RemoveAt(hull.Count - 1); } } // return for (int i = 0; i < hull.Count; i++) { if (i > 0) { outLines.Add(new Line(hull[i - 1], hull[i])); } outPoints.Add(hull[i]); } if (hull.Count > 2) // closing segment { outLines.Add(new Line(hull[hull.Count - 1], hull[0])); } return; }
void merger(List<Point> conv1, List<Point> conv2, out int[] L, out int[] R) { int conv1Idx = 0, conv2Idx = 0; for (int i = 0; i < conv1.Count; ++i) if (conv1[i].X > conv1[conv1Idx].X) conv1Idx = i; for (int i = 0; i < conv2.Count; ++i) if (conv2[i].X < conv2[conv2Idx].X) conv2Idx = i; L = new int[2]; R = new int[2]; L[0] = L[1] = conv1Idx; R[0] = R[1] = conv2Idx; int[] op = new int[2] { 1, -1 }; Enums.TurnType[] type = new Enums.TurnType[2] { Enums.TurnType.Right, Enums.TurnType.Left }; for (int state = 0; state < 2; ++state) { bool doneR = true, doneL = true; do { doneR = true; doneL = true; while (true) { int rNxt = (R[1 - state] + op[state] + conv2.Count) % conv2.Count; Enums.TurnType turn = HelperMethods.CheckTurn(new Line(conv2[rNxt], conv2[R[1 - state]]), conv1[L[1 - state]]); if (turn == type[1 - state] || turn == Enums.TurnType.Colinear) { R[1 - state] = rNxt; doneR = false; } else break; } while (true) { int lPrev = (L[1 - state] + op[1 - state] + conv1.Count) % conv1.Count; Enums.TurnType turn = HelperMethods.CheckTurn(new Line(conv1[lPrev], conv1[L[1 - state]]), conv2[R[1 - state]]); if (turn == type[state] || turn == Enums.TurnType.Colinear) { L[1 - state] = lPrev; doneL = false; } else break; } } while (!doneR || !doneL) ; } }
public override void Run(System.Collections.Generic.List <CGUtilities.Point> points, System.Collections.Generic.List <CGUtilities.Line> lines, System.Collections.Generic.List <CGUtilities.Polygon> polygons, ref System.Collections.Generic.List <CGUtilities.Point> outPoints, ref System.Collections.Generic.List <CGUtilities.Line> outLines, ref System.Collections.Generic.List <CGUtilities.Polygon> outPolygons) { // Step [ 1 ] :: first at all we must check that polygon points is Sorted CCW // Step [ 1 ] :: first at all we must check that polygon points is Sorted CCW List <Point> input = new List <Point>(); // // get minimum_X to use it in checking that the polygon points are sorted CCW OR Not for (int i = 0; i < polygons[0].lines.Count(); i++) { Point p = polygons[0].lines[i].Start; if (p.X <= mini_x.X) { if (p.X < mini_x.X) { mini_x = p; index_of_mini_x = i; } else if (p.Y < mini_x.Y) { mini_x = p; index_of_mini_x = i; } } input.Add(p); } bool Points_sorted_CCW = HelperMethods.IS_points_Sorted_CCW(mini_x, index_of_mini_x, input); // if points were sorted CC then Resort them to be CCW if (Points_sorted_CCW == false) { /* for (int i = 0; i < polygons[0].lines.Count; i++) * { * Point temp = polygons[0].lines[i].Start; * * polygons[0].lines[i].Start = polygons[0].lines[i].End; * polygons[0].lines[i].End = temp; * * }*/ polygons[0].lines.Reverse(); input.Reverse(); } // Now we have ploygon sorted CCW // Step [ 2 ] :: Check that the polygon is Monotone // Step [ 2 ] :: Check that the polygon is Monotone bool is_Montone = Check_Poly_IS_Monotone(input); if (is_Montone) { List <Smart_point_Y_monotone> Sorted_Points = Sort_Polygon(input); Stack <Smart_point_Y_monotone> My_Stack = new Stack <Smart_point_Y_monotone>(); My_Stack.Push(Sorted_Points[0]); My_Stack.Push(Sorted_Points[1]); int ind = 2; while (ind != Sorted_Points.Count()) { Smart_point_Y_monotone V = Sorted_Points[ind]; Smart_point_Y_monotone First_Top = My_Stack.Peek(); if (V.chain.Equals(First_Top.chain)) // Same Chain { My_Stack.Pop(); Smart_point_Y_monotone Sceond_Top = My_Stack.Peek(); if (First_Top.chain == "left") { Line line = new Line(Sceond_Top.current_point, First_Top.current_point); Enums.TurnType chain_Type = HelperMethods.CheckTurn(line, V.current_point); if (chain_Type == Enums.TurnType.Left) { outLines.Add(new Line(V.current_point, Sceond_Top.current_point)); if (My_Stack.Count == 1) { My_Stack.Push(V); ind++; } } else { My_Stack.Push(First_Top); My_Stack.Push(V); ind++; } } // end of condition Same Chain && chain is Left else if (First_Top.chain == "right") { Line line = new Line(Sceond_Top.current_point, First_Top.current_point); Enums.TurnType type = HelperMethods.CheckTurn(line, V.current_point); if (type == Enums.TurnType.Right) { outLines.Add(new Line(V.current_point, Sceond_Top.current_point)); if (My_Stack.Count == 1) { My_Stack.Push(V); ind++; } } else { My_Stack.Push(First_Top); My_Stack.Push(V); ind++; } } //end of condtion Same Cahin && chain is Right } //end of Same Chain else // oppsite Chain { while (My_Stack.Count != 1) { Smart_point_Y_monotone sceond_Top = My_Stack.Pop(); outLines.Add(new Line(V.current_point, sceond_Top.current_point)); } My_Stack.Pop(); My_Stack.Push(First_Top); My_Stack.Push(V); ind++; } //end of Oppsite Chain } //end of big while loop } //end of condition poly is monotone outLines.Remove(outLines[outLines.Count - 1]); } //end of Run
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { if (points.Count == 1) { outPoints.Add(points[0]); } else { double minY = 100000; double minX = -1000; int index = -1; //bageeb el min y with max x for (int i = 0; i < points.Count; i++) { if ((points[i].Y < minY) || (points[i].Y == minY && points[i].X >= minX)) { index = i; minY = points[i].Y; minX = points[i].X; } } Point minPoint = points[index]; double x = minPoint.X + 100000000; double y = minPoint.Y; Point virtualPoint = new Point(x, y); points.RemoveAt(index); List <KeyValuePair <double, Point> > sortedAngles = new List <KeyValuePair <double, Point> >(); for (int i = 0; i < points.Count; i++) { double angle = CalcAngle(minPoint, virtualPoint, points[i]); sortedAngles.Add(new KeyValuePair <double, Point>(angle, points[i])); } sortedAngles.Sort((s, ss) => s.Key.CompareTo(ss.Key)); Stack <Point> myStack = new Stack <Point>(); myStack.Push(minPoint); myStack.Push(sortedAngles[0].Value); for (int i = 1; i < points.Count; i++) { Point p1 = myStack.Pop(); Point p2 = myStack.Pop(); myStack.Push(p2); myStack.Push(p1); Line l = new Line(p1, p2); Enums.TurnType t = HelperMethods.CheckTurn(l, sortedAngles[i].Value); while (myStack.Count > 2 && t != Enums.TurnType.Left) { myStack.Pop(); p1 = myStack.Pop(); p2 = myStack.Pop(); myStack.Push(p2); myStack.Push(p1); l = new Line(p1, p2); t = HelperMethods.CheckTurn(l, sortedAngles[i].Value); } myStack.Push(sortedAngles[i].Value); } while (myStack.Count != 0) { outPoints.Add(myStack.Pop()); } } // special cases ///////////////////////////// List <Point> temp = new List <Point>(); temp.Clear(); for (int i = 0; i < outPoints.Count; ++i) { temp.Add(outPoints[i]); } outPoints.Clear(); for (int i = 0; i < temp.Count; ++i) { List <Point> diagonal = new List <Point>(); diagonal.Add(temp[i]); for (int j = 0; j < temp.Count; ++j) { if ((i != j) && (temp[i].X - temp[j].X == temp[i].Y - temp[j].Y)) { diagonal.Add(temp[j]); } } // keda ma3aya kol el no2at el 3ala nfs el 5at // 3amalna sort bel x wel y diagonal = diagonal.OrderBy(x => x.X).ThenBy(x => x.Y).ToList(); // 3ashan lw el point mtkarara maslan 3ala kaza diagonal if (!outPoints.Contains(diagonal[0])) { outPoints.Add(diagonal[0]); } // lazem nt2aked size el diagonal akbar men 1 3ashan mn3melsh access le 7aga out of range if (diagonal.Count > 1 && !outPoints.Contains(diagonal[diagonal.Count - 1])) { outPoints.Add(diagonal[diagonal.Count - 1]); } } /////////////////////////////// temp.Clear(); for (int i = 0; i < outPoints.Count; ++i) { temp.Add(outPoints[i]); } outPoints.Clear(); for (int i = 0; i < temp.Count; ++i) { List <Point> verticalLine = new List <Point>(); verticalLine.Add(temp[i]); for (int j = 0; j < temp.Count; ++j) { if (i != j && temp[i].X == temp[j].X) { verticalLine.Add(temp[j]); } } verticalLine = verticalLine.OrderBy(x => x.Y).ToList(); if (!outPoints.Contains(verticalLine[0])) { outPoints.Add(verticalLine[0]); } if (verticalLine.Count > 1 && !outPoints.Contains(verticalLine[verticalLine.Count - 1])) { outPoints.Add(verticalLine[verticalLine.Count - 1]); } } //////////////////////////////////////////////////////////// temp.Clear(); for (int i = 0; i < outPoints.Count; ++i) { temp.Add(outPoints[i]); } outPoints.Clear(); for (int i = 0; i < temp.Count; ++i) { List <Point> horizontalLine = new List <Point>(); horizontalLine.Add(temp[i]); for (int j = 0; j < temp.Count; ++j) { if (i != j && temp[i].Y == temp[j].Y) { horizontalLine.Add(temp[j]); } } horizontalLine = horizontalLine.OrderBy(x => x.X).ToList(); if (!outPoints.Contains(horizontalLine[0])) { outPoints.Add(horizontalLine[0]); } if (horizontalLine.Count > 1 && !outPoints.Contains(horizontalLine[horizontalLine.Count - 1])) { outPoints.Add(horizontalLine[horizontalLine.Count - 1]); } } }
public override void Run(List <Point> points, List <Line> lines, List <Polygon> polygons, ref List <Point> outPoints, ref List <Line> outLines, ref List <Polygon> outPolygons) { /* * this function will take set of points * return only the points on the boundary of the polygon * it don't deal with colinear points * we could make the algo faster by excluding the non extreme points from building the triangle also * proof that this will not affect the non extreme detection !!! ****** */ /* * this will affect outpoints and I will deal with it to make things alright */ // preprocessing List <Point> tmp = new List <Point>(); for (int i = 0; i < points.Count; i++) { bool dup = false; for (int j = 0; j < i; j++) { if (Math.Abs(points[i].X - points[j].X) <= Constants.Epsilon && Math.Abs(points[i].Y - points[j].Y) <= Constants.Epsilon) { dup = true; break; } } if (dup) { continue; } tmp.Add(points[i]); } points.Clear(); points = tmp; Point_in_convex_polygon check_p_in_t = new Point_in_convex_polygon(); bool[] is_extreme = new bool[points.Count]; for (int i = 0; i < points.Count; i++) { is_extreme[i] = true; } for (int i = 0; i < points.Count; i++) { // don't use non extreme points in checking // as if we have the same point more than 1 time they will exclude each other if (is_extreme[i] == false) { continue; } for (int j = 0; j < points.Count; j++) { if (is_extreme[j] == false) { continue; } if (i == j) { continue; } for (int k = 0; k < points.Count; k++) { if (is_extreme[k] == false) { continue; } if (k == i || k == j) { continue; } Point a = points[i], b = points[j], c = points[k]; // check if points are colinear Enums.TurnType t = HelperMethods.CheckTurn(new Line(a, b), c); if (t == Enums.TurnType.Colinear) { continue; } // loop throw the points for (int index = 0; index < points.Count; index++) { if (is_extreme[index] == false || index == i || index == j || index == k) { continue; } // check if the point is inside the polygon triangle List <Line> tmp_ll = new List <Line>(); List <Polygon> tmp_pl = new List <Polygon>(); Polygon tmp_poly = new Polygon(); Point p = points[index]; // does the order matters !??? tmp_ll.Add(new Line(a, b)); tmp_ll.Add(new Line(b, c)); tmp_ll.Add(new Line(c, a)); tmp_poly.lines = tmp_ll; tmp_pl.Add(tmp_poly); // tmp out lists // does C# have garbage collector !?? List <Point> tmp_outpoints = new List <Point>(); List <Line> tmp_outlines = new List <Line>(); List <Polygon> tmp_outpolygons = new List <Polygon>(); List <Point> in_points = new List <Point>(); in_points.Add(p); check_p_in_t.Run(in_points, new List <Line>(), tmp_pl, ref tmp_outpoints, ref tmp_outlines, ref tmp_outpolygons); if (tmp_outpoints.Count != 0) { is_extreme[index] = false; } } } } } // return extreme points for (int i = 0; i < points.Count; i++) { if (is_extreme[i] == true) { outPoints.Add(points[i]); } } return; }
void merger(List <Point> conv1, List <Point> conv2, out int[] L, out int[] R) { int conv1Idx = 0, conv2Idx = 0; for (int i = 0; i < conv1.Count; ++i) { if (conv1[i].X > conv1[conv1Idx].X) { conv1Idx = i; } } for (int i = 0; i < conv2.Count; ++i) { if (conv2[i].X < conv2[conv2Idx].X) { conv2Idx = i; } } L = new int[2]; R = new int[2]; L[0] = L[1] = conv1Idx; R[0] = R[1] = conv2Idx; int[] op = new int[2] { 1, -1 }; Enums.TurnType[] type = new Enums.TurnType[2] { Enums.TurnType.Right, Enums.TurnType.Left }; for (int state = 0; state < 2; ++state) { bool doneR = true, doneL = true; do { doneR = true; doneL = true; while (true) { int rNxt = (R[1 - state] + op[state] + conv2.Count) % conv2.Count; Enums.TurnType turn = HelperMethods.CheckTurn(new Line(conv2[rNxt], conv2[R[1 - state]]), conv1[L[1 - state]]); if (turn == type[1 - state] || turn == Enums.TurnType.Colinear) { R[1 - state] = rNxt; doneR = false; } else { break; } } while (true) { int lPrev = (L[1 - state] + op[1 - state] + conv1.Count) % conv1.Count; Enums.TurnType turn = HelperMethods.CheckTurn(new Line(conv1[lPrev], conv1[L[1 - state]]), conv2[R[1 - state]]); if (turn == type[state] || turn == Enums.TurnType.Colinear) { L[1 - state] = lPrev; doneL = false; } else { break; } } } while (!doneR || !doneL); } }