private void copyTree(int target, int treeStart, ref Dictionary <VEvent, VEventInfo> events) { if (beachTree[treeStart] == null) { return; } beachTree[target] = beachTree[treeStart]; if (beachTree[treeStart].IsEdge) { //update related circle events to edge VEdge edge = edges[beachTree[treeStart].EdgeIndex]; VArc arc = arcs[edge.LeftArcIndex]; foreach (VEvent circleEventLocation in arc.CircleEventLocations) { if (events[circleEventLocation].VEdgeTwoIndex == treeStart) { events[circleEventLocation].VEdgeTwoIndex = target; } else if (events[circleEventLocation].VEdgeOneIndex == treeStart) { events[circleEventLocation].VEdgeOneIndex = target; } } } beachTree[treeStart] = null; copyTree(getLeftChildIndex(target), getLeftChildIndex(treeStart), ref events); copyTree(getRightChildIndex(target), getRightChildIndex(treeStart), ref events); }
//locate the existing arc (if any) that is above the new site //eventIntersection is the location of intersection between the event in question with the most relavant arc on the beachline private int getExistingArc(BeachLineItem[] beachTree, Vector2 eventLocation) { if (beachTree[0] == null) { return(-1); } if (!beachTree[0].IsEdge) { return(0); } int nodeIndex = 0; bool arcNotFound = true; while (arcNotFound) { ensureExtraCapacity(nodeIndex); if (!isLeafNode(nodeIndex)) { VEdge edgeNode = edges[beachTree[nodeIndex].EdgeIndex]; float rightXIntercept = getPorabolaRightIntercept(arcs[edgeNode.LeftArcIndex], arcs[edgeNode.RightArcIndex], eventLocation); ensureExtraCapacity(getLeftChildIndex(nodeIndex)); if (rightXIntercept < eventLocation.X && !float.IsNaN(rightXIntercept)) { nodeIndex = getRightChildIndex(nodeIndex); } else if (!isLeafNode(getLeftChildIndex(nodeIndex))) { int leftChildIndex = getLeftChildIndex(nodeIndex); VEdge leftEdgeNode = edges[beachTree[leftChildIndex].EdgeIndex]; float leftIntercept = getPorabolaRightIntercept(arcs[leftEdgeNode.LeftArcIndex], arcs[leftEdgeNode.RightArcIndex], eventLocation); if (leftIntercept < eventLocation.X) { //needs to return an index on the beachtree //not an arc index //looking for the beachline index that points to the same arc index as 'targetArcIndex' nodeIndex = getRightChildIndex(leftChildIndex); //return leftEdgeNode.RightArcIndex; } else { nodeIndex = leftChildIndex; } } else { //arcNotFound = false; //float rightYIntercept = solveForY(arcs[edgeNode.LeftArcIndex], rightXIntercept, eventLocation); //eventIntersection.Y = solveForY(arcs[beachTree[nodeIndex].ArcIndex], eventIntersection.X, eventLocation); return(getLeftChildIndex(nodeIndex)); } } else { //arcNotFound = false; return(nodeIndex); } } return(-1); }
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; } } } }
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); } } }
private Vector2 getRayIntercept(VEdge edgeOne, VEdge edgeTwo, Vector2 eventLocation) { //VectorEquation vecEQ = midPointOne + vectorSlopeOne * t where t >= 0 VArc LeftArc = arcs[edgeOne.LeftArcIndex]; VArc RightArc = arcs[edgeOne.RightArcIndex]; float x1 = LeftArc.Focus.X; float y1 = LeftArc.Focus.Y; float x2 = RightArc.Focus.X; float y2 = RightArc.Focus.Y; Vector2 vectorSlopeOne = new Vector2(y2 - y1, x1 - x2); // instead of midpoint, it should be at the relavant intersection of the two arcs. //Vector2 midPointOne = new Vector2((x1 + x2) / 2, (y1 + y2) / 2); float startingPointOneX = getPorabolaRightIntercept(LeftArc, RightArc, eventLocation); float startingPointOneY = solveForY(LeftArc, startingPointOneX, eventLocation); if (float.IsNaN(startingPointOneY) || float.IsInfinity(startingPointOneY)) { startingPointOneY = solveForY(RightArc, startingPointOneX, eventLocation); } Vector2 startPointOne = new Vector2(startingPointOneX, startingPointOneY); LeftArc = arcs[edgeTwo.LeftArcIndex]; RightArc = arcs[edgeTwo.RightArcIndex]; x1 = LeftArc.Focus.X; y1 = LeftArc.Focus.Y; x2 = RightArc.Focus.X; y2 = RightArc.Focus.Y; Vector2 vectorSlopeTwo = new Vector2(y2 - y1, x1 - x2); // instead of midpoint, it should be at the relavant intersection of the two arcs. //Vector2 midPointTwo = new Vector2((x1 + x2) / 2, (y1 + y2) / 2); float startingPointTwoX = getPorabolaRightIntercept(LeftArc, RightArc, eventLocation); float startingPointTwoY = solveForY(LeftArc, startingPointTwoX, eventLocation); if (float.IsNaN(startingPointTwoY) || float.IsInfinity(startingPointTwoY)) { startingPointTwoY = solveForY(RightArc, startingPointOneX, eventLocation); } Vector2 startPointTwo = new Vector2(startingPointTwoX, startingPointTwoY); float[,] GMatrix = { { vectorSlopeOne.X, -vectorSlopeTwo.X, (startPointTwo.X - startPointOne.X) }, { vectorSlopeOne.Y, -vectorSlopeTwo.Y, (startPointTwo.Y - startPointOne.Y) } }; GaussianElim.SolutionResult result = GaussianElim.Solve(GMatrix, GMatrix.GetLength(0)); if (result == GaussianElim.SolutionResult.OneSolution) { float parameterResultOne = GMatrix[0, 2] / GMatrix[0, 0]; float parameterResultTwo = GMatrix[1, 2] / GMatrix[1, 1]; if (parameterResultOne >= 0 && parameterResultTwo >= 0) { Vector2 foo = new Vector2(startPointOne.X + vectorSlopeOne.X * parameterResultOne, startPointOne.Y + vectorSlopeOne.Y * parameterResultOne); Vector2 bar = new Vector2(startPointTwo.X + vectorSlopeTwo.X * parameterResultTwo, startPointTwo.Y + vectorSlopeTwo.Y * parameterResultTwo); return(bar); //return new Vector3(midPointOne.x + vectorSlopeOne.x * parameterResultOne, midPointOne.y + vectorSlopeOne.y * parameterResultOne); } else { return(new Vector2(float.NegativeInfinity, float.NegativeInfinity)); } } else { return(new Vector2(float.NegativeInfinity, float.NegativeInfinity)); } }