public bool Encloses(List <Point> points) { List <Line> helpers = new List <Line>(); foreach (Point point in points) { helpers.Add(new Line(point, new Point(DRAWING_SCREEN_WIDTH, point.Y))); } foreach (Line helper in helpers) { //foreach (Side side1 in Sides) //{ // side1.Checked = false; //} List <Side> VisualSides = GetVisualSides(); int intersectCount = 0; bool isPointPartOfTheEdge = VisualSides.Any(s => s.IsPartOfMe(helper.Start)); if (!isPointPartOfTheEdge) { foreach (Side side in VisualSides) { if (side.Checked == false) { Orientation first = GetOrientation(helper.Start, helper.End, side.Start); Orientation second = GetOrientation(helper.Start, helper.End, side.End); Orientation third = GetOrientation(side.Start, side.End, helper.Start); Orientation fourth = GetOrientation(side.Start, side.End, helper.End); List <Orientation> orientations = new List <Orientation>() { first, second, third, fourth }; if (orientations.Count(o => o == Orientation.Colinear) == 0 && first != second && third != fourth) { // ténylegesen metszik egymást intersectCount++; } else if (orientations.Count(o => o == Orientation.Colinear) == 1) { if (first == Orientation.Colinear || second == Orientation.Colinear) { // o o // \ | // \ | // o----o--o-o--o---------o helper // | \ // | \ // o o if (third != fourth) { //this condition should be always true //az éppen vizsgált él azon csúcsa, ami rajta van a helperen Point vertex = Vertices.Single(v => v.Y == helper.Start.Y && side.IsPartOfMe(v)); // a vizsgált élhez az előbb megkapott csúcsban csatlakozó másik él //Side sideTwo = Sides.Single(s => (s.Start.Equals(vertex) || s.End.Equals(vertex)) && s.Id != side.Id); Side sideTwo = VisualSides.Single(s => (s.Start.Equals(vertex) || s.End.Equals(vertex)) && s.Id != side.Id); List <Point> pts = new List <Point>() { side.Start, side.End, sideTwo.Start, sideTwo.End }; List <Point> pts2 = pts.Where(p => !p.Equals(vertex)).ToList(); if (pts2.ElementAt(0).Y > helper.Start.Y && pts2.ElementAt(1).Y > helper.Start.Y) { // o o // \ / // \ / // o-------o-------------- helper // // // intersectCount += 2; side.Checked = true; foreach (Side s in VisualSides) { if (s.Equals(sideTwo)) { s.Checked = true; } } } else if (pts2.ElementAt(0).Y < helper.Start.Y && pts2.ElementAt(1).Y < helper.Start.Y) { // // // // o--------o------------- helper // / \ // / \ // o o intersectCount += 2; side.Checked = true; foreach (Side s in VisualSides) { if (s.Equals(sideTwo)) { s.Checked = true; } } } else if (pts2.Any(v => v.Y == helper.Start.Y)) { // itt a v-e1 él a vizsgált él, ha a e0-v lenne, akkor mind a négy colinear lenne // // (e0) v // o---o-----o------------- helper // \ // \ // o (e1) //akkor hagyjuk az egészet és majd ez az oldal ott kerül feldolgozásra // ahol a vizzszintes oldalt vizsgáljuk és a két hozzá kapcsolódó élt } else { //ez az általános eset // o // \ // \ // o-------o-------------- helper // / // / // o intersectCount++; side.Checked = true; foreach (Side s in VisualSides) { if (s.Equals(sideTwo)) { s.Checked = true; } } } } } } else if (orientations.Count(o => o == Orientation.Colinear) == 4) { if (helper.Start.X < side.Start.X) { // o (connectedOne) // \ // \ (side) // o-------o------o-------- helper // | // | // o (connectedTwo) //Side connectedSideOne = Sides.Single(s => s.End.Equals(side.Start)); //Side connectedSideTwo = Sides.Single(s => s.Start.Equals(side.End)); Side connectedSideOne = VisualSides.Single(s => s.End.Equals(side.Start)); Side connectedSideTwo = VisualSides.Single(s => s.Start.Equals(side.End)); List <Point> pts = new List <Point>() { connectedSideOne.Start, connectedSideOne.End, connectedSideTwo.Start, connectedSideTwo.End }; List <Point> pts2 = pts.Where(p => !p.Equals(side.Start) && !p.Equals(side.End)).ToList(); if ((side.Start.Y < pts2.ElementAt(0).Y&& side.Start.Y < pts2.ElementAt(1).Y) || (pts2.ElementAt(0).Y < side.Start.Y && pts2.ElementAt(1).Y < side.Start.Y)) { // o o // \ / // \ / // o-------o------o---- helper // // // // // // o--------o------o-------- helper // / \ // / \ // o o intersectCount += 2; } else if (false) { // ezek még nincsenek lekezelve // // o---o~~~~o~~~~~~o~~~~o---- helper // // // // o // \ // \ // o-------o~~~~~~o~~~~o---- helper // // // // // // o---o~~~~o~~~~~~o-------- helper // \ // \ // o } else { // o // \ // \ // o-------o-------o---- helper // \ // \ // o // o // / // / // o-------o-------o---- helper // / // / // o intersectCount += 3; } side.Checked = true; foreach (Side s in VisualSides) { if (s.Equals(connectedSideOne) || s.Equals(connectedSideTwo)) { s.Checked = true; } } } } } } } else { intersectCount = 1; } if (intersectCount % 2 == 0) { return(false); } } return(true); }
public bool Equals(Side side) { return((Start.Equals(side.Start) && End.Equals(side.End)) || (Start.Equals(side.End) && End.Equals(side.Start))); }
private static Side OtherSide(Side side) { return(side == Side.Left ? Side.Right : Side.Left); }
private NodeMeta SwapWithAdjacent(NodeMeta meta, Side side) { Side otherSide = OtherSide(side); NodeMeta adjacentMeta = Adjacent(side, meta); Node adjacent = adjacentMeta.Node; Node toBeReplaced = meta.Node; Node adjacentParent = adjacentMeta.ParentMeta.Node; // Swap the nodes. // Cache the children of item to be replaced. Node child = adjacent[side]; bool parentChildSwap = toBeReplaced[side] == adjacent; // Adjacent takes place of node to be removed. meta.ReplaceNode(adjacent); if (meta.ParentMeta == null) { root = adjacent; } else { meta.ParentMeta.Node[meta.SideFromParent] = adjacent; } if (!parentChildSwap) { adjacent[side] = toBeReplaced[side]; } adjacent[otherSide] = toBeReplaced[otherSide]; // Put node to be replaced in adjacent spot if (parentChildSwap) { adjacent[otherSide] = toBeReplaced; } else { adjacentParent[otherSide] = toBeReplaced; } toBeReplaced[side] = child; toBeReplaced[otherSide] = null; // This is null, that is how we know it is the leaf adjacentMeta.ReplaceNode(toBeReplaced); // Swap the color Color temp = toBeReplaced.Color; toBeReplaced.Color = adjacent.Color; adjacent.Color = temp; if (meta.ParentMeta == null) { adjacent.Color = Color.Black; } if (child == null) { // We have found the node to remove. Replace it with a sentinal return(adjacentMeta); } else { return(SwapWithAdjacent(adjacentMeta, side)); } }
private void BalanceTree(NodeMeta meta) { if (meta == null) { return; } /* Five steps of any balance operation * 1) Extract relatives from meta data * 2) Decide on operation to perform * 3) Rotate as appropriate * 4) Change colors as appropriate * 5) Pass along metadata for next balance operation * */ var current = meta.Node; var parentMeta = meta.ParentMeta; NodeMeta nextMeta = parentMeta; if (current.Color == Color.DoubleBlack) { Side otherSide = OtherSide(meta.SideFromParent); Node distalNephew = meta.Sibling[otherSide]; Node proximalNephew = meta.Sibling[meta.SideFromParent]; if (meta.Sibling.Color == Color.Black) { if (distalNephew != null && distalNephew.Color == Color.Red) { nextMeta = RotateToChild(meta.SideFromParent, meta.ParentMeta); RemoveDoubleBlack(meta); meta.Sibling.Color = Color.Red; distalNephew.Color = Color.Black; } else if (proximalNephew != null && proximalNephew.Color == Color.Red) { var siblingMeta = new NodeMeta(meta.ParentMeta, meta.Sibling, otherSide, current); nextMeta = RotateToChild(otherSide, siblingMeta); proximalNephew.Color = Color.Black; meta.Sibling.Color = Color.Red; // Re-run this algorithm to process the distalNephew case. nextMeta = meta; } else { RemoveDoubleBlack(meta); meta.Sibling.Color = Color.Red; var color = meta.ParentMeta.Node.Color == Color.Red ? Color.Black : Color.DoubleBlack; meta.ParentMeta.Node.Color = color; nextMeta = color == Color.DoubleBlack ? meta.ParentMeta : null; } } else { meta.Sibling.Color = Color.Black; meta.ParentMeta.Node.Color = Color.Red; nextMeta = RotateToChild(meta.SideFromParent, meta.ParentMeta); var gpmeta = nextMeta ?? new NodeMeta(root); var pmeta = new NodeMeta(gpmeta, meta.ParentMeta.Node, meta.SideFromParent, gpmeta.Node[otherSide]); nextMeta = new NodeMeta(pmeta, meta.Node, meta.SideFromParent, meta.ParentMeta.Node[otherSide]); } } else if (current.Color == Color.Red) { if (parentMeta.Node.Color == Color.Red) { if (parentMeta.Sibling != null && parentMeta.Sibling.Color == Color.Red) { // Papa and Uncle are Red, but Grandpa is black. Swap colors for everyone. parentMeta.Sibling.Color = Color.Black; parentMeta.Node.Color = Color.Black; SetRed(parentMeta.ParentMeta.Node); // Skip a generation. nextMeta = parentMeta.ParentMeta; } else if (meta.SideFromParent == parentMeta.SideFromParent) { // Handle Left-Left or Right-Right //http://www.geeksforgeeks.org/red-black-tree-set-2-insert/ nextMeta = RotateToChild(OtherSide(meta.SideFromParent), parentMeta.ParentMeta); var newSibling = parentMeta.ParentMeta.Node; SetRed(newSibling); meta.ParentMeta.Node.Color = Color.Black; } else { // Handle Left-Right or Right-Left //http://www.geeksforgeeks.org/red-black-tree-set-2-insert/ // We know that our sibling is null // We know that we have a grandparent. nextMeta = RotateUpTwo(meta); if (nextMeta == null) { SetRoot(meta.Node); } meta.Node.Color = Color.Black; SetRed(meta.ParentMeta.ParentMeta.Node); } } /* Node is red, and parent is black. * If sibling is red, we can push the red up a node. * This is not necessary, so I comment it out. */ //else if (meta.Sibling != null && meta.Sibling.Color == Color.Red) { // meta.Node.Color = Color.Black; // meta.Sibling.Color = Color.Black; // SetRed(meta.ParentMeta.Node); //} } BalanceTree(nextMeta); }
public virtual Node this[Side side] { get { return(children[(int)side]); } set { children[(int)side] = value; } }