internal void HandleCircleEvent(VEvent circleEvent, List <VHalfEdge> halfEdges, ref Dictionary <VEvent, VEventInfo> events, ref List <Vector2> vertices, ref PriorityQueue priorityQueue) { //Add vertex to corresponding edge record VEventInfo evnt = events[circleEvent]; VEdge vEdgeOne = edges[beachTree[evnt.VEdgeOneIndex].EdgeIndex]; //(VEdge)beachTree[evnt.VEdgeOneIndex]; VEdge vEdgeTwo = edges[beachTree[evnt.VEdgeTwoIndex].EdgeIndex]; //(VEdge)beachTree[evnt.VEdgeTwoIndex]; Vector2 vertex = new Vector2(circleEvent.EventLocation.X, circleEvent.EventLocation.Y + evnt.Radius); vertices.Add(vertex); //The two halfEdges that are colliding VHalfEdge halfEdgeOne = vEdgeOne.HalfEdge; halfEdgeOne.End = vertex; VHalfEdge halfEdgeTwo = vEdgeTwo.HalfEdge; halfEdgeTwo.End = vertex; //Deleting disappearing arc //Create new edge record //replace edgeOne with the new edge //replace edgeTwo with the opposite branch //VEdge newEdge = new VEdge(vEdgeOne.LeftArcIndex, vEdgeTwo.RightArcIndex); //beachTree[evnt.VEdgeOneIndex].EdgeIndex = edges.Count; //edges.Add(newEdge); //copyTree(evnt.VEdgeTwoIndex, getSibling(evnt.VEdgeTwoIndex)); VEdge newEdge; VHalfEdge newHalfEdge = new VHalfEdge(); VHalfEdge newHalfEdgeTwin = new VHalfEdge() { End = vertex, Twin = newHalfEdge }; newHalfEdge.Twin = newHalfEdgeTwin; halfEdges.Add(newHalfEdge); halfEdges.Add(newHalfEdgeTwin); if (halfEdgeOne.Tile == halfEdgeTwo.Twin.Tile) { halfEdgeOne.Next = halfEdgeTwo.Twin; halfEdgeTwo.Twin.Prev = halfEdgeOne; halfEdgeTwo.Next = newHalfEdge; newHalfEdge.Prev = halfEdgeTwo; newHalfEdge.Tile = halfEdgeTwo.Tile; newHalfEdgeTwin.Next = halfEdgeOne.Twin; halfEdgeOne.Twin.Prev = newHalfEdgeTwin; newHalfEdgeTwin.Tile = halfEdgeOne.Twin.Tile; newHalfEdge.Tile.Edges.AddLast(newHalfEdge); newHalfEdgeTwin.Tile.Edges.AddLast(newHalfEdgeTwin); } else { halfEdgeOne.Next = newHalfEdge; newHalfEdge.Prev = halfEdgeOne; newHalfEdgeTwin.Next = halfEdgeTwo.Twin; halfEdgeTwo.Twin.Prev = newHalfEdgeTwin; halfEdgeTwo.Next = halfEdgeOne.Twin; halfEdgeOne.Twin.Prev = halfEdgeTwo; newHalfEdge.Tile = halfEdgeOne.Tile; newHalfEdgeTwin.Tile = halfEdgeTwo.Twin.Tile; newHalfEdge.Tile.Edges.AddLast(newHalfEdge); newHalfEdgeTwin.Tile.Edges.AddLast(newHalfEdgeTwin); } if (arcs[vEdgeOne.LeftArcIndex].Focus == arcs[vEdgeTwo.LeftArcIndex].Focus || arcs[vEdgeOne.LeftArcIndex].Focus == arcs[vEdgeTwo.RightArcIndex].Focus) { if (arcs[vEdgeOne.LeftArcIndex].Focus == arcs[vEdgeTwo.LeftArcIndex].Focus) { newEdge = new VEdge(vEdgeTwo.RightArcIndex, vEdgeOne.RightArcIndex, newHalfEdge); //newEdge = new VEdge(vEdgeTwo.RightArcIndex, vEdgeOne.RightArcIndex); beachTree[evnt.VEdgeOneIndex].EdgeIndex = edges.Count; beachTree[evnt.VEdgeOneIndex].IsEdge = true; edges.Add(newEdge); //want to delete left arc of edge2 beachTree[getLeftChildIndex(evnt.VEdgeTwoIndex)] = null; copyTree(evnt.VEdgeTwoIndex, getSibling(getLeftChildIndex(evnt.VEdgeTwoIndex)), ref events); } else { newEdge = new VEdge(vEdgeTwo.LeftArcIndex, vEdgeOne.RightArcIndex, newHalfEdge); beachTree[evnt.VEdgeOneIndex].EdgeIndex = edges.Count; beachTree[evnt.VEdgeOneIndex].IsEdge = true; edges.Add(newEdge); //want to delete the right arc of edge2 beachTree[getRightChildIndex(evnt.VEdgeTwoIndex)] = null; copyTree(evnt.VEdgeTwoIndex, getSibling(getRightChildIndex(evnt.VEdgeTwoIndex)), ref events); } } else { //vEdgeOne.RightArcIndex; if (arcs[vEdgeOne.RightArcIndex].Focus == arcs[vEdgeTwo.RightArcIndex].Focus) { newEdge = new VEdge(vEdgeOne.LeftArcIndex, vEdgeTwo.LeftArcIndex, newHalfEdge); beachTree[evnt.VEdgeOneIndex].EdgeIndex = edges.Count; beachTree[evnt.VEdgeOneIndex].IsEdge = true; edges.Add(newEdge); //want to delete right arc of arc2 copyTree(evnt.VEdgeTwoIndex, getSibling(getRightChildIndex(evnt.VEdgeTwoIndex)), ref events); } else { newEdge = new VEdge(vEdgeOne.LeftArcIndex, vEdgeTwo.RightArcIndex, newHalfEdge); beachTree[evnt.VEdgeOneIndex].EdgeIndex = edges.Count; beachTree[evnt.VEdgeOneIndex].IsEdge = true; edges.Add(newEdge); //want to delete left arc of arc2 copyTree(evnt.VEdgeTwoIndex, getSibling(getLeftChildIndex(evnt.VEdgeTwoIndex)), ref events); //copyTree(evnt.VEdgeTwoIndex, getSibling(getRightChildIndex(evnt.VEdgeTwoIndex)), ref events); } } //need to look left and right, events[circleEvent].Deleted = true;//look here... 10-26 //evnt.VEdgeOneIndex int newEdgeIndex = evnt.VEdgeOneIndex; //int parentEdgeOfNewEdgeIndex = getParentIndex(newEdgeIndex); int parentEdgeOfNewEdgeIndex = getClosestLeftAncestor(newEdgeIndex); int closestLeftEdgeIndex = getClosestLeftEdgeIndex(newEdgeIndex); int closestRightEdgeIndex = getClosestRightEdgeIndex(newEdgeIndex); //Check the new triplets for potential circle events if (parentEdgeOfNewEdgeIndex != newEdgeIndex) { newEdge = edges[beachTree[newEdgeIndex].EdgeIndex];//probably not a need line? Vector2 intercept = getRayIntercept(newEdge, edges[beachTree[parentEdgeOfNewEdgeIndex].EdgeIndex], circleEvent.EventLocation); if (intercept.Y != float.NegativeInfinity && intercept != vertex) { VEdge parentEdgeOfNewEdge = edges[beachTree[parentEdgeOfNewEdgeIndex].EdgeIndex]; float radius = Vector2.Distance(arcs[parentEdgeOfNewEdge.LeftArcIndex].Focus, intercept); intercept.Y -= radius; VEvent newCircleEvent = new VEvent(intercept, EventType.CircleEvent); priorityQueue.Enqueue(newCircleEvent); events.Add(newCircleEvent, new VEventInfo() { Radius = radius, VEdgeOneIndex = parentEdgeOfNewEdgeIndex, //pk pl VEdgeTwoIndex = newEdgeIndex, //pl pm }); //add to leafs VArc arc = arcs[parentEdgeOfNewEdge.LeftArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[parentEdgeOfNewEdge.LeftArcIndex] = arc; arc = arcs[parentEdgeOfNewEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[parentEdgeOfNewEdge.LeftArcIndex] = arc; newEdge = edges[beachTree[newEdgeIndex].EdgeIndex]; arc = arcs[newEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[newEdge.RightArcIndex] = arc; } } if (closestLeftEdgeIndex != newEdgeIndex)//here { newEdge = edges[beachTree[newEdgeIndex].EdgeIndex]; Vector2 intercept = getRayIntercept(newEdge, edges[beachTree[closestLeftEdgeIndex].EdgeIndex], circleEvent.EventLocation); if (intercept.Y != float.NegativeInfinity && intercept != vertex) { VEdge closestLeftEdgeOfNewEdge = edges[beachTree[closestLeftEdgeIndex].EdgeIndex]; float radius = Vector2.Distance(arcs[closestLeftEdgeOfNewEdge.LeftArcIndex].Focus, intercept); intercept.Y -= radius; VEvent newCircleEvent = new VEvent(intercept, EventType.CircleEvent); priorityQueue.Enqueue(newCircleEvent); events.Add(newCircleEvent, new VEventInfo() { Radius = radius, VEdgeOneIndex = newEdgeIndex, VEdgeTwoIndex = closestLeftEdgeIndex, }); //add to leafs VArc arc = arcs[closestLeftEdgeOfNewEdge.LeftArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); arc = arcs[closestLeftEdgeOfNewEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); newEdge = edges[beachTree[newEdgeIndex].EdgeIndex]; arc = arcs[newEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); } } if (closestRightEdgeIndex != newEdgeIndex) { newEdge = edges[beachTree[newEdgeIndex].EdgeIndex]; Vector2 intercept = getRayIntercept(newEdge, edges[beachTree[closestRightEdgeIndex].EdgeIndex], circleEvent.EventLocation); if (intercept.Y != float.NegativeInfinity && intercept != vertex) { VEdge closestRightEdgeOfNewEdge = edges[beachTree[closestRightEdgeIndex].EdgeIndex]; float radius = Vector2.Distance(arcs[closestRightEdgeOfNewEdge.LeftArcIndex].Focus, intercept); intercept.Y -= radius; VEvent newCircleEvent = new VEvent(intercept, EventType.CircleEvent); priorityQueue.Enqueue(newCircleEvent); events.Add(newCircleEvent, new VEventInfo() { Radius = radius, VEdgeOneIndex = newEdgeIndex, VEdgeTwoIndex = closestRightEdgeIndex, }); //add to leafs VArc arc = arcs[closestRightEdgeOfNewEdge.LeftArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); arc = arcs[closestRightEdgeOfNewEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); newEdge = edges[beachTree[newEdgeIndex].EdgeIndex]; arc = arcs[newEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); } } }
internal void HandleVertexEvent(Vector2 eventLocation, List <VHalfEdge> halfEdges, ref Dictionary <VEvent, VEventInfo> events, ref VTile[] tiles, int curTileIndex, ref PriorityQueue priorityQueue) { //locate the existing arc (if any) that is above the new site int arcIndex = getExistingArc(beachTree, eventLocation); //break the arc by replacing the leaf node with a sub tree representing //the new arc and its break points tiles[curTileIndex] = new VTile(eventLocation); if (arcIndex == -1) { //beachTree[0] = new VArc(eventLocation); beachTree[0] = new BeachLineItem() { IsEdge = false, ArcIndex = arcs.Count, }; arcs.Add(new VArc(eventLocation, tiles[curTileIndex])); } else { //Corresponding leaf replaced by a new sub-tree removeRelatedCircleEvent(arcIndex, eventLocation, ref events); VArc newArc = new VArc(eventLocation, tiles[curTileIndex]); VArc arc = arcs[beachTree[arcIndex].ArcIndex]; //Add two half-edge records in the doubly linked list VHalfEdge halfEdge = new VHalfEdge()//pm pl { Tile = newArc.Tile, }; halfEdges.Add(halfEdge); VHalfEdge twinHalfEdge = new VHalfEdge()//pl pm { Tile = arc.Tile, }; //edges[edges.Count - 1].HalfEdge = halfEdge; //edges[edges.Count - 2].HalfEdge = twinHalfEdge; halfEdges.Add(twinHalfEdge); halfEdge.Twin = twinHalfEdge; twinHalfEdge.Twin = halfEdge; newArc.Tile.Neighbors.AddLast(arc.Tile); arc.Tile.Neighbors.AddLast(newArc.Tile); newArc.Tile.Edges.AddLast(halfEdge); //halfedge belongs to the newArc created arc.Tile.Edges.AddLast(twinHalfEdge); //created twinedge belongs to the split collided arc int leftChildIndex = getLeftChildIndex(arcIndex); beachTree[leftChildIndex] = new BeachLineItem() { IsEdge = false, ArcIndex = beachTree[arcIndex].ArcIndex, }; //arc; int rChild = getRightChildIndex(arcIndex); ensureExtraCapacity(getLeftChildIndex(rChild)); beachTree[getLeftChildIndex(rChild)] = new BeachLineItem() { IsEdge = false, ArcIndex = arcs.Count, }; //newArc; arcs.Add(newArc); ensureExtraCapacity(getRightChildIndex(rChild)); beachTree[getRightChildIndex(rChild)] = new BeachLineItem() { IsEdge = false, ArcIndex = arcs.Count, }; //arc; arcs.Add(new VArc(arc.Focus, arc.Tile)); beachTree[rChild] = new BeachLineItem() { IsEdge = true, EdgeIndex = edges.Count, }; edges.Add(new VEdge(beachTree[getLeftChildIndex(rChild)].ArcIndex, beachTree[getRightChildIndex(rChild)].ArcIndex, twinHalfEdge)); //edges[edges.Count - 1].HalfEdge = halfEdges.Count; beachTree[arcIndex] = new BeachLineItem() { IsEdge = true, EdgeIndex = edges.Count, }; edges.Add(new VEdge(beachTree[leftChildIndex].ArcIndex, beachTree[getLeftChildIndex(rChild)].ArcIndex, halfEdge)); //edges[edges.Count - 1].HalfEdge = halfEdges.Count + 1; //Check for potential circle events, add them to event queue if they exist if (!hasParent(arcIndex)) { //there is no possible circle event, return; } //int parentIndex = getParentIndex(arcIndex);//<-- get first right parent index //int rightParentIndex = getRightParentIndex(arcIndex); VEdge leftCreatedHalfEdge = edges[beachTree[arcIndex].EdgeIndex]; int leftParentIndex = getFirstLeftParentIndex(arcIndex); //if(leftParentIndex == -1) -> then there is no need to check for edges on the left if (leftParentIndex >= 0) { VEdge leftParentEdge = edges[beachTree[leftParentIndex].EdgeIndex]; Vector2 intercept = getRayIntercept(leftCreatedHalfEdge, leftParentEdge, eventLocation); if (intercept.Y != float.NegativeInfinity)//probably don't need this check? { //we want circle event location to be droped lower by radius to x val //we want to calculate radius and store it with the event //we add starting point to the halfedge that belongs to the newArc //halfEdge.Start = intercept; float radius = Vector2.Distance((arcs[leftCreatedHalfEdge.LeftArcIndex]).Focus, intercept); intercept.Y -= radius; VEvent newCircleEvent = new VEvent(intercept, EventType.CircleEvent); priorityQueue.Enqueue(newCircleEvent); events.Add(newCircleEvent, new VEventInfo() { Radius = radius, VEdgeOneIndex = leftParentIndex, //pk pl VEdgeTwoIndex = arcIndex, //pl pm //rChild? }); //add to leafs arc = arcs[leftCreatedHalfEdge.LeftArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[edgeOne.LeftArcIndex] = arc; arc = arcs[leftCreatedHalfEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[edgeOne.LeftArcIndex] = arc; arc = arcs[leftParentEdge.LeftArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[edgeTwo.RightArcIndex] = arc; } } VEdge rightCreatedHalfEdge = edges[beachTree[rChild].EdgeIndex]; int rightParentIndex = getFirstRightParentIndex(arcIndex); //if(rightParentIndex == -1) -> then there is no need to check for edges on the right if (rightParentIndex >= 0) { VEdge rightParentEdge = edges[beachTree[rightParentIndex].EdgeIndex];//(VEdge)beachTree[parentIndex]; Vector2 intercept = getRayIntercept(rightCreatedHalfEdge, rightParentEdge, eventLocation); if (intercept.Y != float.NegativeInfinity) { //we want circle event location to be droped lower by radius to x val //we want to calculate radius and store it with the event //we add starting point to the halfedge that belongs to the newArc //twinHalfEdge.Start = intercept; float radius = Vector2.Distance((arcs[rightCreatedHalfEdge.LeftArcIndex]).Focus, intercept); intercept.Y -= radius; VEvent newCircleEvent = new VEvent(intercept, EventType.CircleEvent); priorityQueue.Enqueue(newCircleEvent); events.Add(newCircleEvent, new VEventInfo() { Radius = radius, VEdgeOneIndex = rightParentIndex, //pk pl VEdgeTwoIndex = rChild, //pl pm }); //add to leafs arc = arcs[rightCreatedHalfEdge.LeftArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[edgeOne.LeftArcIndex] = arc; arc = arcs[rightCreatedHalfEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[edgeOne.LeftArcIndex] = arc; arc = arcs[rightParentEdge.RightArcIndex]; arc.CircleEventLocations.Add(newCircleEvent); //beachTree[edgeTwo.RightArcIndex] = arc; } } } }