Пример #1
0
 private void ensureExtraCapacity(int index)
 {
     //2 * parentIndex + 2
     if (2 * index + 2 >= capacity)
     {
         BeachLineItem[] newArray = new BeachLineItem[2 * index + 3];
         Array.Copy(beachTree, newArray, beachTree.Length);
         beachTree = newArray;
         capacity  = beachTree.Length;
     }
 }
Пример #2
0
        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;
                    }
                }
            }
        }