public Voronoi(List <Point> pointList, double xSize, double ySize, double precision) { XSize = xSize; YSize = ySize; Precision = precision; // 优先队列,制定排序规则:Y 小先出队,Y 相等X 小先出队(从上到下进行扫描) priorityQueue = new PriorityQueue <IEvent>( (e1, e2) => { if (e1.QueryPoint().Y < e2.QueryPoint().Y) { return(-1); } if (e1.QueryPoint().Y > e2.QueryPoint().Y) { return(1); } if (e1.QueryPoint().X < e2.QueryPoint().X) { return(-1); } if (e1.QueryPoint().X > e2.QueryPoint().X) { return(1); } return(0); } ); foreach (var point in pointList) { // 根据初始点集创建相应的站点事件加入优先队列 IEvent e = new SiteEvent(point.X, point.Y); priorityQueue.Push(e); Sites.Add(e.QueryPoint()); // 创建维诺图结构体 faces[e.QueryPoint()] = new Face(e.QueryPoint()); } // 开始构建维诺图 Build(); }
private void ProcSiteEvent(SiteEvent e) { if (tree.Empty()) { // 树为空时,直接添加成第一个结点 IData data = new ArcData(e.QueryPoint(), null, false); tree.AddFirstArc(data); } else { // 先找出站点正上方的弧 ArcData oldArc = tree.GetAboveArc(e.QueryPoint()); // 正上方的弧将被拆成两段,所以肯定会破坏其的圆事件 if (oldArc.CircleEvent != null) { oldArc.CircleEvent.Deleted = true; oldArc.CircleEvent = null; } //if (oldArc.A.Y == e.QueryPoint().Y) { // // 可以选择不要这个分支,直接统一走下面那个 // // 这样的话,计算交点的方法需要做特殊处理 // // 如果正上方弧的 y 坐标和新站点的 y 坐标一致 // // 则是一条弧分裂成两条弧,将原先的弧删掉,新增一个内部结点和两个叶子结点 // var intersection = new IntersectionData(oldArc.A, e.QueryPoint(), oldArc.Fa, oldArc.IsLeft(), tree); // var arc01 = new ArcData(oldArc.A, intersection, true); // var arc02 = new ArcData(e.QueryPoint(), intersection, false); // // 维护双向链表 // arc01.Prev = oldArc.Prev; // arc02.Prev = arc01; // if (oldArc.Next != null) { // oldArc.Next.Prev = arc02; // } // if (oldArc.Prev != null) { // oldArc.Prev.Next = arc01; // } // arc01.Next = arc02; // arc02.Next = oldArc.Next; // arc01.S0 = oldArc.S0; // // 交点目前坐标,用于创建维诺图边 // var p = intersection.CalcIntersection(e.QueryPoint().Y); // // 交点计算 // var seg = new Segment(p, QueryFace(e.QueryPoint()), QueryFace(oldArc.A)); // arc01.S1 = seg; // arc02.S0 = seg; // FixCircleEvent(arc01); //} else { // 正常情况下,正上方的弧会被新增弧分割成两段 // 将原先的弧删掉,新增两个内部结点和三个叶子结点 var intersection01 = new IntersectionData(oldArc.A, e.QueryPoint(), oldArc.Fa, oldArc.IsLeft(), tree); var intersection02 = new IntersectionData(e.QueryPoint(), oldArc.A, intersection01, false, tree); var arc01 = new ArcData(oldArc.A, intersection01, true); var arc02 = new ArcData(e.QueryPoint(), intersection02, true); var arc03 = new ArcData(oldArc.A, intersection02, false); // 维护双向链表 arc01.Prev = oldArc.Prev; arc02.Prev = arc01; arc03.Prev = arc02; if (oldArc.Next != null) { oldArc.Next.Prev = arc03; } if (oldArc.Prev != null) { oldArc.Prev.Next = arc01; } arc01.Next = arc02; arc02.Next = arc03; arc03.Next = oldArc.Next; // 原弧分裂出来的两段弧分别继承S0、S1 arc01.S0 = oldArc.S0; arc03.S1 = oldArc.S1; // 交点目前坐标,用于创建维诺图边 // 目前两个交点应该是重叠的,由这两个点勾勒出同一条维诺图边 var p = intersection01.CalcIntersection(e.QueryPoint().Y); var seg = new Segment(p, QueryFace(e.QueryPoint()), QueryFace(oldArc.A)); arc01.S1 = seg; arc02.S0 = seg; seg = new Segment(p, QueryFace(e.QueryPoint()), QueryFace(oldArc.A)); arc02.S1 = seg; arc03.S0 = seg; FixCircleEvent(arc01); FixCircleEvent(arc03); // } } }