问题描述
如何在创建四叉树节点的点范围内找到中心并高效地进行?
class point {
constructor(x,y) {
this.x = x;
this.y = y;
}
}
//range = [] of points,(they get sorted into quarters in the tree node)
范围代表点的阵列,代表板。
以下是相关代码:
class quadtreeNode {
constructor(range,parent,depth) {
const centerPoint = findCenter(range);
this.center = centerPoint;
this.parent = parent;
if (range.length <= 1) {
this.leaf = true;
this.value = this.center;
} else {
this.TL = new quadtreeNode(
range.filter(x => x.x < this.center.x && x.y < this.center.y),this,depth + 1
);
this.TR = new quadtreeNode(
range.filter(x => x.x > this.center.x && x.y < this.center.y),depth + 1
);
this.BL = new quadtreeNode(
range.filter(x => x.x < this.center.x && x.y > this.center.y),depth+1
);
this.BR = new quadtreeNode(
range.filter(x => x.x > this.center.x && x.y > this.center.y),depth + 1
);
}
}
}
并且:
findCenter(array){
let centerPoint = null;
if (array.length <= 1) {
centerPoint = array[0];
} else {
let minX = array.sort((x,y) => x.x < y.x)[0];
let minY = array.sort((x,y) => x.y < y.y)[0];
let maxX = array.sort((x,y) => x.x > y.x)[0];
let maxY = array.sort((x,y) => x.y > y.y)[0];
const targetX = maxX-minX;
const targetY = maxY-minY;
const target = array.find(x => x.x == targetX && x.y == targetY);
if (!target) {
return array[(Math.floor(array.length / 2))];
} else {
centerPoint = target;
}
}
return centerPoint;
}
对于如何找到中心,我是否每次都需要找到确切的中心,或者是否有四叉树的估计,或者范围应为可被...整除的特定长度,我有些困惑。 4?
解决方法
这取决于您要优化的内容。大多数情况下,您需要最小化四叉树的深度。因此,理想情况下,您希望选择一个节点,以使其跟随的四个子范围中的每个子范围都具有大约四分之一的点,即相等的分布。如果您要在每个节点上实现该目标,那么当 n 是总数时,树的深度将接近log 4 n 的节点数。
但是,并非总是可以选择这样的中心节点。想象一下范围内的点分布:
*
*
*
*
*
*
*
*
无论选择哪个点,都将始终产生四个子范围,其中两个是空的,因此在4个子范围内均匀分布的“梦境”是不可行的。
您将要选择中心点,以使获得最大点数的象限最小。计算起来可能会很昂贵,但是以下是一种很好的启发式方法:
- 针对每个点,通过x坐标(sx)收集其排序顺序,并通过y坐标(sy)收集其排序顺序。通过执行两个排序操作,您可以轻松地实现这一点
- 考虑到最佳中心的(sx,sy)=(n / 2,n / 2),应选择(sx,sy)到(n / 2,n / 2)的点)最小化。
因此建议的代码为:
findCenter(array) {
const mid = array.length >> 1;
if (!mid) {
return array[0];
}
return array.sort((p,q) => p.x - q.x) // NB: sort callback should return signed number
.map((p,sx) => [p,sx]))
.sort(([p],[q]) => p.y - q.y)
.map(([p,sx],sy) => [(sx - mid) ** 2 + (sy - mid) ** 2,p])
.sort(([a],[b]) => a - b)[0][1];
}