Exemple #1
0
        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();
        }
Exemple #2
0
        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);
                //	}
            }
        }