找到最近的3d点 输出

问题描述

比方说,我有一个玩家位于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()方法,但这似乎不起作用,因为它只能获得最小的坐标,而不是最近的坐标。

@EDIT:我的完整代码

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);

解决方法

对于少量车辆,只需使用Pythagorean algorithm查找车辆与玩家之间的距离就足够了。 (对于不止几个(或者如果您需要经常循环),您可能需要研究空间分割算法(例如四叉树),以使查找更有效。)


// Assumes posA and posB are both objects with X,Y,Z members.
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);
}

// Stores objects of shape `{vehicle: ...,distance: number}`
const vehiclesAndDistances = [];

mp.vehicles.forEachInRange(player.position,100,(vehicle) => {
  if (vehicle.ownerID == player.id) {
    vehiclesAndDistances.push({
      vehicle,distance: distance3D(player,vehicle),});
  }
});
// Sort the array by the distance
vehiclesAndDistances.sort((a,b) => a.distance - b.distance);

编辑:如评论中所述,如果只需要最近点,则可以将其重新表示为

let closestDistance = undefined;
let closestVehicle = undefined;

mp.vehicles.forEachInRange(player.position,(vehicle) => {
  if (vehicle.ownerID === player.id) {
    const distance = distance3D(player,vehicle);
    if (closestDistance === undefined || distance < closestDistance) {
      closestVehicle = vehicle;
      closestDistance = distance;
    }
  }
});
,

您可以使用distance formula。将其应用于每个点并选择最小值。时间复杂度是线性的,但是您可能每帧循环运行一次,因此总体复杂度是二次的。有可用的优化。见

不改变时间复杂度的可能的微优化包括避免平方根运算,一分钟保存最小值等。

const dist = (a,b) => Math.sqrt(
  (b.X - a.X) ** 2 +
  (b.Y - a.Y) ** 2 +
  (b.Z - a.Z) ** 2
);

const closest = (target,points,eps=0.00001) => {
  const distances = points.map(e => dist(target,e));
  const closest = Math.min(...distances);
  return points.find((e,i) => distances[i] - closest < eps);
};

const player = {X: 100,Y: 100,Z: 100};
const points = [
  {ID: 1,X: 200,Y: 200,Z: 100},{ID: 2,X: 150,Y: 300,Z: 300},{ID: 3,X: 300,{ID: 4,X: 50,Z: 200}
];

console.log(closest(player,points));

您可以将dist推广到以下任意维度:

const dist = (a,b) => Math.sqrt(
  Object.keys(a).map(k => (b[k] - a[k]) ** 2)
    .reduce((a,e) => a + e)  
);
,

您可以使用欧式距离计算公式。将所有坐标放在一个数组中,并使用地图创建一个新的距离数组,该距离是通过实现欧几里得公式得出的。您可以按升序或降序对数组元素进行排序并找到距离

let currData = [{
    ID: 1,Z: 100
  },{
    ID: 2,Z: 300
  },{
    ID: 3,{
    ID: 4,Z: 200
  }
]

const vehlPos = {
  X: 250,Y: 400,Z: 600
};

let getDist = currData.map((item) => {
  const xdiff = Math.pow((vehlPos.X - item.X),2);
  const ydiff = Math.pow((vehlPos.Y - item.Y),2);
  const zdiff = Math.pow((vehlPos.Z - item.Z),2);
  return Math.sqrt(xdiff + ydiff + zdiff)
});

console.log(getDist)

,

您可以将对象转换为点并使用矢量函数。

这是3D矢量类别的somewhat-complete example

const main = () => {
  const player = { X: 100,Z: 100 };
  const points = [
    { ID: 1,Z: 100 },{ ID: 2,Z: 300 },{ ID: 3,{ ID: 4,X:  50,Z: 200 }
  ];

  console.log(findClosestPoint(player,points));
};

const findClosestPoint = (player,points) => {
  let { X,Z } = player;
  const pos = new Vector3D(X,Z),minDist = points.reduce((res,point,index) => {
      let { X,Z } = point;
      const value = pos.distanceTo(new Vector3D(X,Z));
      return value < res.value ? { index,value } : res;
    },{ index: -1,value: Number.MAX_VALUE });
  console.log('Min distance:',minDist.value);
  return points[minDist.index];
};

class Vector3D {
  constructor (x,y,z) {
    this.x = x;
    this.y = y;
    this.z = z;
  }
  distanceTo (other) {
    return Math.sqrt(
      Math.pow(this.x - other.x,2) +
      Math.pow(this.y - other.y,2) +
      Math.pow(this.z - other.z,2)
    );
  }
}

main();
.as-console-wrapper { top: 0; max-height: 100% !important; }

输出

Min distance: 111.80339887498948
{
  "ID": 4,"X": 50,"Y": 100,"Z": 200
}