feat: allow local annotations geometry to be editable in the UI via exact co-ordinate input from keyboard
- Dominant language
- TypeScript
- Stars
- 1.5k
- Forks
- 389
- Avg merge
- 3d 21h
- Merged PRs (30d)
- 3
Description
See #809 for idea from @stuarteberg. Opened issue here just to keep track. I think something like the below is probably in the right direction
https://github.com/user-attachments/assets/b48bc89d-6c0e-4dc8-9ac5-99f762a892d6
For example, changing the `visitTransformedAnnotationGeometry` call in `src/ui/annotations.ts` to something like this would allow changing point annotations in the UI
```typescript
visitTransformedAnnotationGeometry(
annotation,
chunkTransform as ChunkTransformParameters,
(layerPosition, isVector) => {
const copyButton = makeCopyButton({
title: "Copy position",
onClick: () => {
setClipboard(layerPosition.map((x) => Math.floor(x)).join(", "));
},
});
copyButton.style.gridColumn = "copy";
positionGrid.appendChild(copyButton);
for (let layerDim = 0; layerDim < layerRank; ++layerDim) {
const coordElement = document.createElement("input");
coordElement.classList.add(
"neuroglancer-selected-annotation-details-position-coord",
);
coordElement.style.gridColumn = `coord ${layerDim + 1}`;
coordElement.value = Math.floor(layerPosition[layerDim]).toString();
coordElement.addEventListener("change", (event) => {
const input = event.target as HTMLInputElement;
const value = parseFloat(input.value);
if (isNaN(value)) return;
const newLayerPosition = new Float32Array(layerPosition.length);
for (let i = 0; i < layerPosition.length; ++i) {
newLayerPosition[i] = layerPosition[i];
}
newLayerPosition[layerDim] = value;
const newAnnotation = reference.value;
if (!newAnnotation) return;
if (newAnnotation.type === AnnotationType.POINT) {
// TODO consider to refactor the visitTransformedAnnotationGeometry
// This is basically the same operation but using the inverse transform
// Also to handle other annotation types
// Annotations that are not points are more complex
// because they need to know which piece of geometry
// is being updated
const toChunkTransform = (chunkTransform as ChunkTransformParameters)
.layerToChunkTransform;
const { layerRank } = chunkTransform as ChunkTransformParameters;
const paddedChunkPosition = new Float32Array(layerRank);
paddedChunkPosition.set(newLayerPosition, 0);
const layerSourcePosition = new Float32Array(layerRank);
(isVector ? matrix.transformVector : matrix.transformPoint)(
layerSourcePosition,
toChunkTransform,
layerRank + 1,
paddedChunkPosition,
layerRank,
);
newAnnotation.point = layerSourcePosition;
}
annotationLayer.source.update(reference, newAnnotation);
annotationLayer.source.commit(reference);
});
positionGrid.appendChild(coordElement);
}
if (!isVector) {
const moveButton = makeMoveToButton({
title: "Move to position",
onClick: () => {
setLayerPosition(this, chunkTransform, layerPosition);
},
});
moveButton.style.gridColumn = "move";
positionGrid.appendChild(moveButton);
}
},
);
```
Contributor guide
Assessment
This issue has not been assessed yet.