Skip to content

Commit c51627e

Browse files
committed
feat(segmentation_user_layer) implemented getObjectPosition for MeshLayer, finds the closest loaded associated mesh vertex to the global position
1 parent ddc325b commit c51627e

File tree

2 files changed

+95
-7
lines changed

2 files changed

+95
-7
lines changed

src/layer/segmentation/index.ts

+25-7
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import {
4141
MultiscaleMeshLayer,
4242
MultiscaleMeshSource,
4343
} from "#src/mesh/frontend.js";
44-
import type { RenderLayerTransform } from "#src/render_coordinate_transform.js";
4544
import {
4645
RenderScaleHistogram,
4746
trackableRenderScaleTarget,
@@ -108,6 +107,7 @@ import { DisplayOptionsTab } from "#src/ui/segmentation_display_options_tab.js";
108107
import { Uint64Map } from "#src/uint64_map.js";
109108
import { Uint64OrderedSet } from "#src/uint64_ordered_set.js";
110109
import { Uint64Set } from "#src/uint64_set.js";
110+
import { gatherUpdate } from "#src/util/array.js";
111111
import {
112112
packColor,
113113
parseRGBColorSpecification,
@@ -1229,13 +1229,31 @@ export class SegmentationUserLayer extends Base {
12291229

12301230
moveToSegment(id: Uint64) {
12311231
for (const layer of this.renderLayers) {
1232-
if (!(layer instanceof MultiscaleMeshLayer)) continue;
1233-
const layerPosition = layer.getObjectPosition(id);
1234-
if (layerPosition === undefined) continue;
1235-
this.setLayerPosition(
1236-
layer.displayState.transform.value as RenderLayerTransform,
1237-
layerPosition,
1232+
if (
1233+
!(layer instanceof MultiscaleMeshLayer || layer instanceof MeshLayer)
1234+
) {
1235+
continue;
1236+
}
1237+
const transform = layer.displayState.transform.value;
1238+
if (transform.error !== undefined) return undefined;
1239+
const { rank, globalToRenderLayerDimensions } = transform;
1240+
const { globalPosition } = this.manager.root;
1241+
const globalLayerPosition = new Float32Array(rank);
1242+
const renderToGlobalLayerDimensions = [];
1243+
for (let i = 0; i < rank; i++) {
1244+
renderToGlobalLayerDimensions[globalToRenderLayerDimensions[i]] = i;
1245+
}
1246+
gatherUpdate(
1247+
globalLayerPosition,
1248+
globalPosition.value,
1249+
renderToGlobalLayerDimensions,
12381250
);
1251+
const layerPosition =
1252+
layer instanceof MeshLayer
1253+
? layer.getObjectPosition(id, globalLayerPosition)
1254+
: layer.getObjectPosition(id);
1255+
if (layerPosition === undefined) continue;
1256+
this.setLayerPosition(transform, layerPosition);
12391257
return;
12401258
}
12411259
StatusMessage.showTemporaryMessage(

src/mesh/frontend.ts

+70
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,76 @@ export class MeshLayer extends PerspectiveViewRenderLayer<ThreeDimensionalRender
582582
);
583583
return ready;
584584
}
585+
586+
getObjectPosition(
587+
id: Uint64,
588+
nearestTo: Float32Array,
589+
): Float32Array | undefined {
590+
const transform = this.displayState.transform.value;
591+
if (transform.error !== undefined) return undefined;
592+
const chunk = this.source.chunks.get(getObjectKey(id));
593+
if (chunk === undefined) return undefined;
594+
const { rank } = transform;
595+
const inverseModelToRenderLayerTransform = new Float32Array(
596+
transform.modelToRenderLayerTransform.length,
597+
);
598+
matrix.inverse(
599+
inverseModelToRenderLayerTransform,
600+
rank + 1,
601+
transform.modelToRenderLayerTransform,
602+
rank + 1,
603+
rank + 1,
604+
);
605+
const nearestPositionInModal = new Float32Array(rank);
606+
matrix.transformPoint(
607+
nearestPositionInModal,
608+
inverseModelToRenderLayerTransform,
609+
rank + 1,
610+
nearestTo,
611+
rank,
612+
);
613+
const { fragmentIds } = chunk;
614+
const closestVertex = new Float32Array(rank);
615+
let closestDistanceSq = Number.POSITIVE_INFINITY;
616+
for (const fragmentId of fragmentIds) {
617+
const fragmentChunk = this.source.fragmentSource.chunks.get(fragmentId);
618+
if (fragmentChunk === undefined) continue;
619+
const { state, meshData } = fragmentChunk;
620+
if (
621+
state !== ChunkState.SYSTEM_MEMORY &&
622+
state !== ChunkState.GPU_MEMORY
623+
) {
624+
continue;
625+
}
626+
const { vertexPositions } = meshData;
627+
if (vertexPositions.length < rank) continue;
628+
for (let i = 0; i < vertexPositions.length; i += rank) {
629+
let distanceSq = 0;
630+
for (let j = 0; j < rank; j++) {
631+
distanceSq += Math.pow(
632+
vertexPositions[i + j] - nearestPositionInModal[j],
633+
2,
634+
);
635+
}
636+
if (distanceSq < closestDistanceSq) {
637+
closestDistanceSq = distanceSq;
638+
for (let j = 0; j < rank; j++) {
639+
closestVertex[j] = vertexPositions[i + j];
640+
}
641+
}
642+
}
643+
}
644+
if (closestDistanceSq === Number.POSITIVE_INFINITY) return undefined;
645+
const layerCenter = new Float32Array(rank);
646+
matrix.transformPoint(
647+
layerCenter,
648+
transform.modelToRenderLayerTransform,
649+
rank + 1,
650+
closestVertex,
651+
rank,
652+
);
653+
return layerCenter;
654+
}
585655
}
586656

587657
export class ManifestChunk extends Chunk {

0 commit comments

Comments
 (0)