Javascript 检测到的坐标与鼠标单击偏移

Javascript 检测到的坐标与鼠标单击偏移,javascript,canvas,three.js,mouse,raycasting,Javascript,Canvas,Three.js,Mouse,Raycasting,我需要一些建议: 当我们单击从右到左的第二个牙齿时,意外的结果是上面的牙齿是彩色的: 我将一步一步地写代码的作用 1) 我们得到用户点击画布的坐标: 相对于画布的坐标212.90908813476562 247.5454559326172 前面的值是有意义的,因为我们单击了右侧的一些位置 2) 我们在0和1之间标准化坐标: 标准化坐标x,y-0.03223141756924719-0.12520661787553267 上一个数字看起来有意义,因为它位于左侧中心的下方: 获取并打印相对坐标并

我需要一些建议:

当我们单击从右到左的第二个牙齿时,意外的结果是上面的牙齿是彩色的:

我将一步一步地写代码的作用

1) 我们得到用户点击画布的坐标:

相对于画布的坐标212.90908813476562 247.5454559326172

前面的值是有意义的,因为我们单击了右侧的一些位置

2) 我们在0和1之间标准化坐标:

标准化坐标x,y-0.03223141756924719-0.12520661787553267

上一个数字看起来有意义,因为它位于左侧中心的下方:

获取并打印相对坐标并最终将其规格化的代码为:

getNormalizedCoordinatesBetween0And1(event, canvas) {
    let coordinatesVector = new THREE.Vector2();

    console.log('coordinates relative to the canvas',
        event.clientX - canvas.getBoundingClientRect().left,
        event.clientY - canvas.getBoundingClientRect().top);

    coordinatesVector.x = ( (event.clientX - canvas.getBoundingClientRect().left) /
        canvas.width ) * 2 - 1;
    coordinatesVector.y = -( (event.clientY - canvas.getBoundingClientRect().top) /
        canvas.height ) * 2 + 1;
    return coordinatesVector;
}
3) 我们使用三个光线投射获得坐标,并从标准化坐标发出:-0.03223141756924719-0.12520661787553267

由三个坐标给出的坐标(坐标原点位于中心)为:

使用三个光线投射获得的坐标-3.1634989936945734-12.288972670909427

如果我们再次观察画布的尺寸和图像位置:

三个坐标在x轴上为负,在y轴上为负,这可能是有意义的,这告诉我们脉冲齿略低于中心的左侧

此步骤的代码为:

getCoordinatesUsingThreeRaycast(coordinatesVector, sceneManager) {
    let raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(coordinatesVector, sceneManager.camera);
    const three = raycaster.intersectObjects(sceneManager.scene.children);
    if (three[0]) {
        console.warn('Coordinates obtained using THREE Raycast',
            three[0].point.x, three[0].point.y);
        coordinatesVector.x = three[0].point.x;
        coordinatesVector.y = three[0].point.y;
        return coordinatesVector;
    }
}
4) 这里从3给出的坐标,我们将坐标原点移到左上角,成为IJ坐标系。数学是:

IJx=abs(coordinatesVector.x+(slice.canvas.width/2)=-3+(352/2)=-3+176=173

IJy=abs(坐标向量.y-(slice.canvas.height/2)=-12-(204/2)=-12-102=114

我们的程序给了我们:172.83 y 114.28

与此行为相关的代码是:

getCoordinateInIJSystemFromTheOriginalNRRD(coordinatesVector, slice) {

    // console.error('Coordenada::IJ from NRRD');

    let IJx = Math.abs(coordinatesVector.x + (slice.canvas.width / 2));
    console.log('Coordinate::IJx', IJx);
    console.log('Coordinate from THREE::', coordinatesVector.x);
    console.log('slice.canvas.width ', slice.canvas.width);

    let IJy = Math.abs(coordinatesVector.y - (slice.canvas.height / 2));
    console.log('Coordinate::IJy', IJy);
    console.log('Coordinate from THREE::', coordinatesVector.y);
    console.log('slice.canvas.height', slice.canvas.height);

    return {IJx, IJy}

}
5) 我们的第五步是缩放我们从可见NRRD 173114得到的点,使其尺寸与原始的大NRRD相匹配

这是因为可见图像是原始图像的一个小表示,我们的程序中有与大图像相关的数据:

如果我们手动获取坐标:

i=圆形(IJx*slice.canvasBuffer.width/slice.canvas.width)=172.83+1000/352=172.83*2.84=493.6772=494

j=round(IJy*slice.canvasBuffer.height/slice.canvas.height)=114.28^580/204=114.28*2.84=324

在我们的节目中,它给了我们:491325

将IJ转换为原始NRRD参考系491 325后的坐标

获取原始NRRD中的点的代码:

**
 * @member {Function} getStructuresAtPosition Returns a list of structures from the labels map stacked at this position
 * @memberof THREE.MultiVolumesSlice
 * @returns {{i: number, j: number}} the structures (can contain undefined)
 * @param IJx
 * @param IJy
 * @param slice
 */
getStructuresAtPosition: function (IJx, IJy, slice) {

    const i = Math.round(IJx * slice.canvasBuffer.width / slice.canvas.width);
    const j = Math.round(IJy * slice.canvasBuffer.height / slice.canvas.height);

    console.log('slice.canvasBuffer.width', slice.canvasBuffer.width);
    console.log('slice.canvasBuffer.height', slice.canvasBuffer.height);
    console.log('slice.canvas.width', slice.canvas.width);
    console.log('slice.canvas.height', slice.canvas.height);

    console.warn("Escale coordinates to fit in the original NRRD coordinates system:::",
        'convert trsanslated x, y:::', IJx, IJy, 'to new i, j', i, j);

    if (i >= slice.iLength || i < 0 || j >= slice.jLength || j < 0) {
        return undefined;
    }
    return {i, j};
},
**
*@member{Function}getStructuresAtPosition返回堆叠在此位置的标签映射中的结构列表
*@memberof THREE.multivolumeslice
*@返回{i:number,j:number}结构(可以包含未定义的)
*@param IJx
*@param IJy
*@param切片
*/
getStructuresAtPosition:函数(IJx、IJy、slice){
const i=Math.round(IJx*slice.canvasBuffer.width/slice.canvas.width);
const j=Math.round(IJy*slice.canvasBuffer.height/slice.canvas.height);
log('slice.canvasBuffer.width',slice.canvasBuffer.width);
log('slice.canvasBuffer.height',slice.canvasBuffer.height);
log('slice.canvas.width',slice.canvas.width);
log('slice.canvas.height',slice.canvas.height);
console.warn(“调整坐标以适应原始NRRD坐标系:”,
“将相关的x,y::”,IJx,IJy,'转换为新的i,j',i,j);
如果(i>=slice.i长度| | i<0 | | j>=slice.jLength | j<0){
返回未定义;
}
返回{i,j};
},
6) 最后,我们使用计算出的坐标:491325来获得点击段的索引,在本例中,我们的程序给出:15,这意味着点击区域的灰度为15

因此,我们可以看到,如果我们点击下颚从左到右的2颗牙齿,出于某种原因,程序认为我们点击的是上颚的牙齿:

你能帮我找出为什么被点击和着色的部分偏离你点击的点吗?谢谢你抽出时间

编辑:添加信息:

感谢您@manthrax提供的信息

我想我已经发现了问题,变焦,以及可见图像和实际图像之间的不同尺寸

例如,如果相机和nrrd之间的默认距离为300,则(i,j)=(863502) 距离为249时,坐标(i,j)为(906515) 最后,如果我们接近距离的163,坐标(i,j)是(932519)

我点击了可视图像左下角

关键是,当相机和图像之间的距离变小时,单击的点更接近真实点

真实的是:(1000580)

我们正在点击:


你能帮我吗?

这是一个常见的问题。光线投射代码使用鼠标的“标准化”坐标,该坐标通常通过鼠标x/y除以画布的宽度/高度来找到。。但是,如果您的代码错误地使用了不同于实际画布宽度/高度的维度来获取这些坐标,那么您就会遇到这些问题。例如,在左上角拾取效果很好,但在你走得更远的时候会逐渐“关闭”

不幸的是,你的问题没有一个有效的解决方案,我无法向你展示如何解决它。。但我把美元赌在甜甜圈上问题在于使用 getBoundingClientRect()来计算鼠标坐标,而不是使用常规的canvas.width、canvas.height

canvas.getBoundingClientRect()将返回一个不等于画布宽度和高度的矩形,但光线投射器希望坐标减去画布的canvas.clientLeft/canvas.clientTop,除以