Seeking guidance:
I need advice on an issue that arises when clicking on the second tooth from right to left, causing the upper teeth to be colored instead:
https://i.sstatic.net/czzmc.png
Below is a step-by-step explanation of what the code does:
1) The code retrieves the coordinates where the user clicked on the canvas:
Coordinates relative to the canvas 212.90908813476562 247.5454559326172
The obtained values indicate that the click was towards the lower right.
2) Normalizing the coordinates between 0 and 1:
Normalized Coordinates x,y -0.03223141756924719 -0.12520661787553267
These normalized numbers make sense as they are below the center on the left:
https://i.sstatic.net/qOjE4.png
The code snippet responsible for obtaining and normalizing the coordinates is:
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) Obtaining the coordinate using THREE Raycast, originating from the normalized coordinate: -0.03223141756924719 -0.12520661787553267
The resulting coordinate calculated by THREE with the origin at the center is:
Coordinates obtained using THREE Raycast -3.1634989936945734 -12.288972670909427
This makes sense as it indicates the clicked tooth is slightly below and to the left of the center.
The relevant code snippet is:
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) Shifting the coordinate's origin to the top-left corner, converting to an IJ coordinate system:
The program calculates IJx and IJy based on abs value of X and Y positions.
Result in our program: 172.83 y 114.28
The relevant code snippet for this operation is:
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) Scaling the point to fit the dimensions of the original big image:
In the program, the visible image acts as a representation of the original image, so scaling is necessary to match their dimensions:
If we manually calculate the coordinates:
i = round(IJx * slice.canvasBuffer.width / slice.canvas.width) = 494
j = round(IJy * slice.canvasBuffer.height / slice.canvas.height) = 325
Result in our program: 491, 325
Considering the scale difference between the visible and original images, the code snippet used for this operation is:
**
* @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.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};
},
6) Using the calculated coordinates: 491, 325 to identify the segment clicked, which in this case corresponds to gray level 15:
Despite clicking on the 2nd tooth from left to right on the lower jaw, the program mistakenly identifies it as part of the upper teeth:
https://i.sstatic.net/vxADj.png
Your assistance in identifying why the colored segment appears offset from the actual click point would be greatly appreciated. Thank you for your time.
EDIT: Additional Information:
Many thanks to @manthrax for providing information.
After further investigation, I believe the zoom level and dimensional disparities between the visible image and the original image may be causing the issue:
For instance, at a default camera-to-nrrd distance of 300, the coordinates (i,j) are (863,502). With a distance of 249, the coordinates become (906,515). And at a closer distance of 163, the coordinates change to (932,519).
These observations were made clicking at the bottom left corner of the visible image.
The problem seems to be related to the reduced distance between the camera and image, leading to discrepancies in the clicked point location.
The true coordinate should be: (1000,580)
https://i.sstatic.net/7ecJP.png
However, the click seems to register at:
https://i.sstatic.net/9oAqS.png
Your help in resolving this discrepancy is highly appreciated.