-
Notifications
You must be signed in to change notification settings - Fork 29
Allow permanent dataset layer rotation in dataset settings #8159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
235a133
WIP: add rotations settings for each axis
1a7ced3
WIP: first version allowing to set a rotation for each layer
a51608b
reduce rotation max to 270 degrees as 0 == 360
4fe4645
keep axis rotation as put in by the user
492e590
Merge branch 'master' of github.com:scalableminds/webknossos into all…
61a554f
WIP: allow multiple transformations per layer
56c8de9
Merge branch 'master' of github.com:scalableminds/webknossos into all…
6942141
remove combining affine transformations only
2855272
fix flycam dummy matrix
3beae60
clean up
423faa8
WIP: make rotation setting for complete dataset & add translation to …
99f1688
add debugging code & notes for bug that no data layer are transforme…
9132f87
fix rotation seting by using storing transformations in row major order
b007368
Merge branch 'master' of github.com:scalableminds/webknossos into all…
3e650a6
WIP: allow multiple layer to be rendered natively
930295f
finish allowing to toggle all transformations off and on
073c3da
Merge branch 'master' of github.com:scalableminds/webknossos into all…
53fb553
fix transformations for annotations
82bdc8a
fix linting
86d0b42
undo change to save natively rendered layer names. Instead only save …
5f9a301
fix rendering transforms for volume layers without fallback & fix ini…
47e5173
Merge branch 'master' of github.com:scalableminds/webknossos into all…
1cd5578
clean up code for pr review
9485c13
add changelog entry
7f32183
Merge branch 'master' of github.com:scalableminds/webknossos into all…
9c08ab0
apply pr feedback
868585c
adjust logic when toggling transformations is allowed according to di…
7c1f5db
- rename file with transformation accessors
c22372d
Merge branch 'master' of github.com:scalableminds/webknossos into all…
582bdf0
Merge branch 'master' of github.com:scalableminds/webknossos into all…
3f8fbcb
apply minifeedback fro coderabbit
0619206
fix cyclic dependency
b6269a7
organize imports
d2548e3
Merge remote-tracking branch 'origin' into allow-perma-dataset-rotation
58dd946
fix auto merge errors
3f1bdb9
fix hovered segment id highlighting when volume layer is rendered wit…
47f4037
orga imports
bae0048
avoid magic number when expecting length of transformation which is r…
0cb6992
remove additional use of magic number
7be8f18
Merge branch 'master' of github.com:scalableminds/webknossos into all…
3c06db5
fix applying segmentation layer transform to hovered cell highlighting
9809a37
Merge branch 'master' of github.com:scalableminds/webknossos into all…
f1b92a5
use position in volume layer space when retrieving segmentation id fr…
44fa5fa
do not allow to toggle transformations on layers that cannot have a t…
1d00a5d
Merge branch 'master' of github.com:scalableminds/webknossos into all…
472c1a8
Merge branch 'master' into allow-perma-dataset-rotation
MichaelBuessemeyer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
191 changes: 191 additions & 0 deletions
191
frontend/javascripts/dashboard/dataset/dataset_rotation_form_item.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
import { InfoCircleOutlined } from "@ant-design/icons"; | ||
import { Col, Form, type FormInstance, InputNumber, Row, Slider, Tooltip, Typography } from "antd"; | ||
import FormItem from "antd/es/form/FormItem"; | ||
import { | ||
AXIS_TO_TRANSFORM_INDEX, | ||
EXPECTED_TRANSFORMATION_LENGTH, | ||
IDENTITY_TRANSFORM, | ||
doAllLayersHaveTheSameRotation, | ||
fromCenterToOrigin, | ||
fromOriginToCenter, | ||
getRotationMatrixAroundAxis, | ||
} from "oxalis/model/accessors/dataset_layer_transformation_accessor"; | ||
import BoundingBox from "oxalis/model/bucket_data_handling/bounding_box"; | ||
import { useCallback, useEffect, useMemo } from "react"; | ||
import type { APIDataLayer } from "types/api_flow_types"; | ||
import { FormItemWithInfo } from "./helper_components"; | ||
|
||
const { Text } = Typography; | ||
|
||
type AxisRotationFormItemProps = { | ||
form: FormInstance | undefined; | ||
axis: "x" | "y" | "z"; | ||
}; | ||
|
||
function getDatasetBoundingBoxFromLayers(layers: APIDataLayer[]): BoundingBox | undefined { | ||
if (!layers || layers.length === 0) { | ||
return undefined; | ||
} | ||
let datasetBoundingBox = BoundingBox.fromBoundBoxObject(layers[0].boundingBox); | ||
for (let i = 1; i < layers.length; i++) { | ||
datasetBoundingBox = datasetBoundingBox.extend( | ||
BoundingBox.fromBoundBoxObject(layers[i].boundingBox), | ||
); | ||
} | ||
return datasetBoundingBox; | ||
} | ||
|
||
export const AxisRotationFormItem: React.FC<AxisRotationFormItemProps> = ({ | ||
form, | ||
axis, | ||
}: AxisRotationFormItemProps) => { | ||
const dataLayers: APIDataLayer[] = Form.useWatch(["dataSource", "dataLayers"], form); | ||
const datasetBoundingBox = useMemo( | ||
() => getDatasetBoundingBoxFromLayers(dataLayers), | ||
[dataLayers], | ||
); | ||
// Update the transformations in case the user changes the dataset bounding box. | ||
useEffect(() => { | ||
if ( | ||
datasetBoundingBox == null || | ||
dataLayers[0].coordinateTransformations?.length !== EXPECTED_TRANSFORMATION_LENGTH || | ||
!form | ||
) { | ||
return; | ||
} | ||
const rotationValues = form.getFieldValue(["datasetRotation"]); | ||
const transformations = [ | ||
fromCenterToOrigin(datasetBoundingBox), | ||
getRotationMatrixAroundAxis("x", rotationValues["x"]), | ||
getRotationMatrixAroundAxis("y", rotationValues["y"]), | ||
getRotationMatrixAroundAxis("z", rotationValues["z"]), | ||
fromOriginToCenter(datasetBoundingBox), | ||
]; | ||
const dataLayersWithUpdatedTransforms = dataLayers.map((layer) => { | ||
return { | ||
...layer, | ||
coordinateTransformations: transformations, | ||
}; | ||
}); | ||
form.setFieldValue(["dataSource", "dataLayers"], dataLayersWithUpdatedTransforms); | ||
}, [datasetBoundingBox, dataLayers, form]); | ||
|
||
const setMatrixRotationsForAllLayer = useCallback( | ||
(rotationInDegrees: number): void => { | ||
if (!form) { | ||
return; | ||
} | ||
const dataLayers: APIDataLayer[] = form.getFieldValue(["dataSource", "dataLayers"]); | ||
const datasetBoundingBox = getDatasetBoundingBoxFromLayers(dataLayers); | ||
if (datasetBoundingBox == null) { | ||
return; | ||
} | ||
|
||
const rotationInRadians = rotationInDegrees * (Math.PI / 180); | ||
const rotationMatrix = getRotationMatrixAroundAxis(axis, rotationInRadians); | ||
const dataLayersWithUpdatedTransforms: APIDataLayer[] = dataLayers.map((layer) => { | ||
let transformations = layer.coordinateTransformations; | ||
if (transformations == null || transformations.length !== EXPECTED_TRANSFORMATION_LENGTH) { | ||
transformations = [ | ||
fromCenterToOrigin(datasetBoundingBox), | ||
IDENTITY_TRANSFORM, | ||
IDENTITY_TRANSFORM, | ||
IDENTITY_TRANSFORM, | ||
fromOriginToCenter(datasetBoundingBox), | ||
]; | ||
} | ||
transformations[AXIS_TO_TRANSFORM_INDEX[axis]] = rotationMatrix; | ||
return { | ||
...layer, | ||
coordinateTransformations: transformations, | ||
}; | ||
}); | ||
form.setFieldValue(["dataSource", "dataLayers"], dataLayersWithUpdatedTransforms); | ||
}, | ||
[axis, form], | ||
); | ||
return ( | ||
<Row gutter={24}> | ||
<Col span={16}> | ||
<FormItemWithInfo | ||
name={["datasetRotation", axis]} | ||
label={`${axis.toUpperCase()} Axis Rotation`} | ||
info={`Change the datasets rotation around the ${axis}-axis.`} | ||
colon={false} | ||
> | ||
<Slider min={0} max={270} step={90} onChange={setMatrixRotationsForAllLayer} /> | ||
</FormItemWithInfo> | ||
</Col> | ||
<Col span={8} style={{ marginRight: -12 }}> | ||
<FormItem | ||
name={["datasetRotation", axis]} | ||
colon={false} | ||
label=" " /* Whitespace label is needed for correct formatting*/ | ||
> | ||
<InputNumber | ||
min={0} | ||
max={270} | ||
step={90} | ||
precision={0} | ||
onChange={(value: number | null) => | ||
// InputNumber might be called with null, so we need to check for that. | ||
value != null && setMatrixRotationsForAllLayer(value) | ||
} | ||
/> | ||
</FormItem> | ||
</Col> | ||
</Row> | ||
); | ||
}; | ||
|
||
type AxisRotationSettingForDatasetProps = { | ||
form: FormInstance | undefined; | ||
}; | ||
|
||
export type DatasetRotation = { | ||
x: number; | ||
y: number; | ||
z: number; | ||
}; | ||
|
||
export const AxisRotationSettingForDataset: React.FC<AxisRotationSettingForDatasetProps> = ({ | ||
form, | ||
}: AxisRotationSettingForDatasetProps) => { | ||
const dataLayers: APIDataLayer[] = form?.getFieldValue(["dataSource", "dataLayers"]); | ||
const isRotationOnly = useMemo(() => doAllLayersHaveTheSameRotation(dataLayers), [dataLayers]); | ||
|
||
if (!isRotationOnly) { | ||
return ( | ||
<Tooltip | ||
title={ | ||
<div> | ||
Each layers transformations must be equal and each layer needs exactly 5 affine | ||
transformation with the following schema: | ||
<ul> | ||
<li>Translation to the origin</li> | ||
<li>Rotation around the x-axis</li> | ||
<li>Rotation around the y-axis</li> | ||
<li>Rotation around the z-axis</li> | ||
<li>Translation back to the original position</li> | ||
</ul> | ||
To easily enable this setting, delete all coordinateTransformations of all layers in the | ||
advanced tab, save and reload the dataset settings. | ||
</div> | ||
} | ||
> | ||
<Text type="secondary"> | ||
Setting a dataset's rotation is only supported when all layers have the same rotation | ||
transformation. <InfoCircleOutlined /> | ||
</Text> | ||
</Tooltip> | ||
); | ||
} | ||
|
||
return ( | ||
<div> | ||
<AxisRotationFormItem form={form} axis="x" /> | ||
<AxisRotationFormItem form={form} axis="y" /> | ||
<AxisRotationFormItem form={form} axis="z" /> | ||
</div> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.