Javascript 查找最近的三维点
假设我有一个播放器位于:Javascript 查找最近的三维点,javascript,node.js,math,nearest-neighbor,Javascript,Node.js,Math,Nearest Neighbor,假设我有一个播放器位于:X:100,Y:100,Z:100,我想找到以下哪一点最接近并获得它的ID: ID: 1, X: 200; Y: 200; Z: 100, ID: 2, X: 150; Y: 300; Z: 300, ID: 3, X: 300; Y: 200; Z: 100, ID: 4, X: 50; Y: 100; Z: 200 我怎么做呢?它背后的数学原理是什么?如果有帮助,我已经有以下代码: var returnVehicles = []; mp.vehicl
X:100,Y:100,Z:100
,我想找到以下哪一点最接近并获得它的ID:
ID: 1, X: 200; Y: 200; Z: 100,
ID: 2, X: 150; Y: 300; Z: 300,
ID: 3, X: 300; Y: 200; Z: 100,
ID: 4, X: 50; Y: 100; Z: 200
我怎么做呢?它背后的数学原理是什么?如果有帮助,我已经有以下代码:
var returnVehicles = [];
mp.vehicles.forEachInRange(player.position, 100, (vehicle) => {
if(vehicle.ownerID == player.id) {
returnVehicles.push(vehicle.position, vehicle.id);
}
}
);
它在100的范围内循环通过车辆,并将属于玩家的车辆的ID和位置添加到一个数组中。然而,我不知道该怎么办
有人向我推荐.sort()方法,但这似乎不起作用,因为它只获取最小的坐标,而不是最近的坐标
@编辑:我的完整代码
function distance3D(posA, posB) {
const dX = posA.X - posB.X;
const dY = posA.Y - posB.Y;
const dZ = posA.Z - posB.Z;
return Math.sqrt(dX * dX + dY * dY + dZ * dZ);
}
const vehiclesAndDistances = [];
function lockPlayerVehicle (player) {
let vehicle = player.vehicle;
if (vehicle) {
//IRRELEVANT
}
else {
mp.vehicles.forEachInRange(player.position, 40, (vehicle) => {
if(vehicle.ownerID == player.id) {
vehiclesAndDistances.push({vehicle, distance: distance3D(player, vehicle),});
}
}
);
vehiclesAndDistances.sort((a, b) => a.distance - b.distance);
player.outputChatBox("Lista Pequena: " + String(vehiclesAndDistances[0]));
console.log(vehiclesAndDistances[0], vehiclesAndDistances[0].vehicle.model)
};
}
mp.events.add("keypress:DOWNARROW", lockPlayerVehicle);
对于少量车辆,只需使用查找车辆与玩家之间的距离就足够了。(对于少数情况(或者如果需要经常循环),您可能需要研究空间分区算法,如四叉树,以使查找更有效。) 编辑:如评论中所述,如果您只需要最近的点,可以将其重新表述为
let closestDistance = undefined;
let closestVehicle = undefined;
mp.vehicles.forEachInRange(player.position, 100, (vehicle) => {
if (vehicle.ownerID === player.id) {
const distance = distance3D(player, vehicle);
if (closestDistance === undefined || distance < closestDistance) {
closestVehicle = vehicle;
closestDistance = distance;
}
}
});
let closestDistance=未定义;
let closestVehicle=未定义;
mp.vehicles.ForEachRange(玩家位置,100,(车辆)=>{
如果(vehicle.ownerID==玩家id){
常量距离=距离3D(玩家、车辆);
if(最近距离===未定义的| |距离<最近距离){
关闭车辆=车辆;
最近距离=距离;
}
}
});
对于少量车辆,只需使用查找车辆与播放器之间的距离就足够了。(对于少数情况(或者如果需要经常循环),您可能需要研究空间分区算法,如四叉树,以使查找更有效。)
编辑:如评论中所述,如果您只需要最近的点,可以将其重新表述为
let closestDistance = undefined;
let closestVehicle = undefined;
mp.vehicles.forEachInRange(player.position, 100, (vehicle) => {
if (vehicle.ownerID === player.id) {
const distance = distance3D(player, vehicle);
if (closestDistance === undefined || distance < closestDistance) {
closestVehicle = vehicle;
closestDistance = distance;
}
}
});
let closestDistance=未定义;
let closestVehicle=未定义;
mp.vehicles.ForEachRange(玩家位置,100,(车辆)=>{
如果(vehicle.ownerID==玩家id){
常量距离=距离3D(玩家、车辆);
if(最近距离===未定义的| |距离<最近距离){
关闭车辆=车辆;
最近距离=距离;
}
}
});
您可以使用。将其应用于每个点并选择最小值。时间复杂度是线性的,但您可能在每帧的循环中运行它,因此总体复杂度是二次的。有可用的优化。看
const dist=(a,b)=>Math.sqrt(
(b.X-a.X)**2+
(b.Y-a.Y)**2+
(b.Z-a.Z)**2
);
常数最近=(目标点,eps=0.00001)=>{
常量距离=点.map(e=>dist(target,e));
常数最近=数学最小值(…距离);
返回点。查找((e,i)=>距离[i]-最近的您可以使用。将其应用于每个点并选择最小值。时间复杂度是线性的,但您可能在每帧的循环中运行它,因此总体复杂度是二次的。有可用的优化。看
不改变时间复杂度的可能微观优化包括避免平方根操作、一次保存最小值等
const dist=(a,b)=>Math.sqrt(
(b.X-a.X)**2+
(b.Y-a.Y)**2+
(b.Z-a.Z)**2
);
常数最近=(目标点,eps=0.00001)=>{
常量距离=点.map(e=>dist(target,e));
常数最近=数学最小值(…距离);
返回点。查找((e,i)=>距离[i]-最近的 日志(最近的(玩家,点数))代码>您可以使用欧几里德距离计算公式。将所有坐标放在一个数组中,并使用map创建一个新的距离数组,该距离数组是通过实现欧几里德公式导出的。可以按升序或降序对数组中的元素进行排序,并找到距离
let currData=[{
ID:1,
X:200,
Y:200,
Z:100
},
{
ID:2,
X:150,
Y:300,
Z:300
},
{
ID:3,
X:300,
Y:200,
Z:100
},
{
ID:4,
X:50,
Y:100,
Z:200
}
]
常数vehlPos={
X:250,
Y:400,
Z:600
};
让getDist=currData.map((项)=>{
const xdiff=Math.pow((vehlPos.X-item.X),2);
const ydiff=数学功率((vehlPos.Y-item.Y),2);
常数zdiff=数学功率((vehlPos.Z-项目Z),2);
返回Math.sqrt(xdiff+ydiff+zdiff)
});
console.log(getDist)
您可以使用欧几里德距离计算公式。将所有坐标放在一个数组中,并使用map创建一个新的距离数组,该距离数组是通过实现欧几里德公式导出的。可以按升序或降序对数组中的元素进行排序,并找到距离
let currData=[{
ID:1,
X:200,
Y:200,
Z:100
},
{
ID:2,
X:150,
Y:300,
Z:300
},
{
ID:3,
X:300,
Y:200,
Z:100
},
{
ID:4,
X:50,
Y:100,
Z:200
}
]
常数vehlPos={
X:250,
Y:400,
Z:600
};
让getDist=currData.map((项)=>{
const xdiff=Math.pow((vehlPos.X-item.X),2);
const ydiff=数学功率((vehlPos.Y-item.Y),2);
常数zdiff=数学功率((vehlPos.Z-项目Z),2);
返回Math.sqrt(xdiff+ydiff+zdiff)
});
log(getDist)
您可以将对象转换为点并使用向量函数
下面是一个3D向量类的示例