Skip to content

Commit

Permalink
Fix Bounding Box download modal and node selection (#5624)
Browse files Browse the repository at this point in the history
* add load precomputeed mesh to context menu in view and skeleton only mode

* consistent context menu naming

* fix segment id icon in dark mode

* fix linting

* fix export bounding box modal not rendering

* reduce far clipping plane for node selection to directly in front of the camera

* add changelog entry

* fix that actual clippingDistance setting could not be tweaked for plane mode

* use actual far value when rendering to texture

* rename destroy to handleClose

* add disclaimer comment to withFarClipping

* fix node picking in 3D viewport

* incorporate PR feedback

Co-authored-by: Norman Rzepka <[email protected]>
Co-authored-by: Philipp Otto <[email protected]>
Co-authored-by: Philipp Otto <[email protected]>
  • Loading branch information
4 people authored Jul 21, 2021
1 parent c8f0147 commit e1d38d8
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 35 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Fixed a bug where dataset uploads of zips with just one file inside failed. [#5534](https://github.com/scalableminds/webknossos/pull/5534)
- Fixed a benign error message when a dataset without a segmentation layer was opened in view mode or with a skeleton-only annotation. [#5583](https://github.com/scalableminds/webknossos/pull/5583)
- Fixed crashing tree tab which could happen when dragging a node and then switching directly to another tab (e.g., comments) and then back again. [#5573](https://github.com/scalableminds/webknossos/pull/5573)
- Fixed a bug that the selection of nodes in the skeleton tool was possible for nodes far behind the position and thus prevented creating new nodes. [#5624](https://github.com/scalableminds/webknossos/pull/5624)
- Fixed that the UI allowed mutating trees in the tree tab (dragging/creating/deleting trees and groups) in read-only tracings. [#5573](https://github.com/scalableminds/webknossos/pull/5573)
- Fixed "Create a new tree group for this file" setting in front-end import when a group id of 0 was used in the NML. [#5573](https://github.com/scalableminds/webknossos/pull/5573)
- Fixed a bug that caused a distortion when moving or zooming in the maximized 3d viewport. [#5550](https://github.com/scalableminds/webknossos/pull/5550)
- Fixed a bug that prevented focusing the login fields when being prompted to login after trying to view a dataset without being logged in.[#5521](https://github.com/scalableminds/webknossos/pull/5577)
- Fixed a bug that prevented the modal to export data of a bounding box to tiff files to open up. [#5624](https://github.com/scalableminds/webknossos/pull/5624)
- Fixed that the 3d view content disappeared permanently if the 3d view was resized to not be visible. [#5588](https://github.com/scalableminds/webknossos/pull/5588)
- The following changes belong to [#5384](https://github.com/scalableminds/webknossos/pull/5384):
- Removed "Highlight hovered cells" setting (highlight on hover will always be done).
Expand Down
5 changes: 5 additions & 0 deletions frontend/javascripts/oxalis/controller/camera_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ class CameraController extends React.PureComponent<Props> {
this.props.cameras[planeId].bottom = -height / 2;
this.props.cameras[planeId].top = height / 2;

// We only set the `near` value here. The effect of far=clippingDistance is
// achieved by offsetting the plane onto which is rendered by the amount
// of clippingDistance. Theoretically, `far` could be set here too, however,
// this leads to imprecision related bugs which cause the planes to not render
// for certain clippingDistance values.
this.props.cameras[planeId].near = -clippingDistance;
this.props.cameras[planeId].updateProjectionMatrix();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,7 @@ export function maybeGetNodeIdFromPosition(
let { width, height } = getInputCatcherRect(Store.getState(), plane);
width = Math.round(width);
height = Math.round(height);

const buffer = renderToTexture(plane, pickingScene, camera);
const buffer = renderToTexture(plane, pickingScene, camera, true);
// Beware of the fact that new browsers yield float numbers for the mouse position
// Subtract the CSS border as the renderer viewport is smaller than the inputcatcher
const borderWidth = OUTER_CSS_BORDER;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import LinkButton from "components/link_button";
import Toast from "libs/toast";
import * as Utils from "libs/utils";
import api from "oxalis/api/internal_api";
import { type Vector3, type ControlMode, ControlModeEnum } from "oxalis/constants";
import Constants, { type Vector3, type ControlMode, ControlModeEnum } from "oxalis/constants";
import {
enforceSkeletonTracing,
getActiveNode,
Expand Down Expand Up @@ -101,6 +101,7 @@ type DatasetSettingsProps = {|
onChangeEnableAutoBrush: (active: boolean) => void,
isAutoBrushEnabled: boolean,
controlMode: ControlMode,
isArbitraryMode: boolean,
|};

function DownsampleVolumeModal({ visible, hideDownsampleVolumeModal, magsToDownsample }) {
Expand Down Expand Up @@ -740,13 +741,24 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps, State> {
value={userConfiguration.particleSize}
onChange={this.onChangeUser.particleSize}
/>
<NumberSliderSetting
label={settings.clippingDistanceArbitrary}
min={userSettings.clippingDistanceArbitrary.minimum}
max={userSettings.clippingDistanceArbitrary.maximum}
value={userConfiguration.clippingDistanceArbitrary}
onChange={this.onChangeUser.clippingDistanceArbitrary}
/>
{this.props.isArbitraryMode ? (
<NumberSliderSetting
label={settings.clippingDistanceArbitrary}
min={userSettings.clippingDistanceArbitrary.minimum}
max={userSettings.clippingDistanceArbitrary.maximum}
value={userConfiguration.clippingDistanceArbitrary}
onChange={this.onChangeUser.clippingDistanceArbitrary}
/>
) : (
<LogSliderSetting
label={settings.clippingDistance}
roundTo={3}
min={userSettings.clippingDistance.minimum}
max={userSettings.clippingDistance.maximum}
value={userConfiguration.clippingDistance}
onChange={this.onChangeUser.clippingDistance}
/>
)}
<SwitchSetting
label={settings.overrideNodeRadius}
value={userConfiguration.overrideNodeRadius}
Expand Down Expand Up @@ -809,6 +821,7 @@ const mapStateToProps = (state: OxalisState) => ({
task: state.task,
controlMode: state.temporaryConfiguration.controlMode,
isAutoBrushEnabled: state.temporaryConfiguration.isAutoBrushEnabled,
isArbitraryMode: Constants.MODES_ARBITRARY.includes(state.temporaryConfiguration.viewMode),
});

const mapDispatchToProps = (dispatch: Dispatch<*>) => ({
Expand Down
27 changes: 25 additions & 2 deletions frontend/javascripts/oxalis/view/rendering_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import constants, {
ArbitraryViewport,
OrthoViewColors,
OrthoViewValues,
OrthoViews,
} from "oxalis/constants";
import { getInputCatcherRect } from "oxalis/model/accessors/view_mode_accessor";
import getSceneController from "oxalis/controller/scene_controller_provider";
Expand Down Expand Up @@ -43,16 +44,37 @@ export function renderToTexture(
plane: OrthoView | typeof ArbitraryViewport,
scene?: typeof THREE.Scene,
camera?: typeof THREE.Camera,
// When withFarClipping is true, the user-specified clipping distance is used.
// Note that the data planes might not be included in the rendered texture, since
// these are exactly offset by the clipping distance. Currently, `withFarClipping`
// is only used for node picking (which does not render the data planes), which is why
// this behavior is not problematic for us.
withFarClipping?: boolean,
clearColor?: number,
): Uint8Array {
const SceneController = getSceneController();
const { renderer, scene: defaultScene } = SceneController;
const state = Store.getState();
scene = scene || defaultScene;
camera = camera || scene.getObjectByName(plane);

// Don't respect withFarClipping for the TDViewport as we don't do any clipping for
// nodes there.
if (withFarClipping && plane !== OrthoViews.TDView) {
const isArbitraryMode = constants.MODES_ARBITRARY.includes(
state.temporaryConfiguration.viewMode,
);
camera = camera.clone();
camera.far = isArbitraryMode
? state.userConfiguration.clippingDistanceArbitrary
: state.userConfiguration.clippingDistance;

camera.updateProjectionMatrix();
}
clearColor = clearColor != null ? clearColor : 0x000000;

renderer.autoClear = true;
let { width, height } = getInputCatcherRect(Store.getState(), plane);
let { width, height } = getInputCatcherRect(state, plane);
width = Math.round(width);
height = Math.round(height);

Expand All @@ -71,6 +93,7 @@ export function renderToTexture(
renderer.render(scene, camera);
renderer.readRenderTargetPixels(renderTarget, 0, 0, width, height, buffer);
renderer.setRenderTarget(null);

return buffer;
}

Expand All @@ -91,7 +114,7 @@ export async function downloadScreenshot() {

// $FlowIssue[prop-missing] planeId cannot be arbitraryViewport in OrthoViewColors access
const clearColor = OrthoViewValues.includes(planeId) ? OrthoViewColors[planeId] : 0xffffff;
const buffer = renderToTexture(planeId, null, null, clearColor);
const buffer = renderToTexture(planeId, null, null, false, clearColor);

// eslint-disable-next-line no-await-in-loop
const blob = await convertBufferToImage(buffer, width, height);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Tooltip } from "antd";
import { PlusSquareOutlined } from "@ant-design/icons";
import type { Dispatch } from "redux";
import { connect } from "react-redux";
import React from "react";
import React, { useState } from "react";
import _ from "lodash";

import type { APIDataset } from "types/api_flow_types";
Expand All @@ -20,7 +20,6 @@ import { getDatasetExtentInVoxel } from "oxalis/model/accessors/dataset_accessor
import { setUserBoundingBoxesAction } from "oxalis/model/actions/annotation_actions";
import * as Utils from "libs/utils";

import renderIndependently from "libs/render_independently";
import ExportBoundingBoxModal from "oxalis/view/right-border-tabs/export_bounding_box_modal";

type BoundingBoxTabProps = {
Expand All @@ -30,6 +29,7 @@ type BoundingBoxTabProps = {
};

function BoundingBoxTab(props: BoundingBoxTabProps) {
const [selectedBoundingBoxForExport, setSelectedBoundingBoxForExport] = useState(null);
const { tracing, dataset, onChangeBoundingBoxes } = props;
const { userBoundingBoxes } = getSomeTracing(tracing);

Expand Down Expand Up @@ -76,20 +76,6 @@ function BoundingBoxTab(props: BoundingBoxTabProps) {
onChangeBoundingBoxes(updatedUserBoundingBoxes);
}

function handleExportUserBoundingBox(id: number) {
const selectedBoundingBox = userBoundingBoxes.find(boundingBox => boundingBox.id === id);
if (selectedBoundingBox) {
renderIndependently(destroy => (
<ExportBoundingBoxModal
dataset={dataset}
tracing={tracing}
boundingBox={selectedBoundingBox.boundingBox}
destroy={destroy}
/>
));
}
}

return (
<div className="padded-tab-content" style={{ minWidth: 300 }}>
{userBoundingBoxes.length > 0 ? (
Expand All @@ -103,7 +89,7 @@ function BoundingBoxTab(props: BoundingBoxTabProps) {
isVisible={bb.isVisible}
onChange={_.partial(handleChangeUserBoundingBox, bb.id)}
onDelete={_.partial(handleDeleteUserBoundingBox, bb.id)}
onExport={_.partial(handleExportUserBoundingBox, bb.id)}
onExport={_.partial(setSelectedBoundingBoxForExport, bb)}
/>
))
) : (
Expand All @@ -120,6 +106,14 @@ function BoundingBoxTab(props: BoundingBoxTabProps) {
/>
</Tooltip>
</div>
{selectedBoundingBoxForExport != null ? (
<ExportBoundingBoxModal
dataset={dataset}
tracing={tracing}
boundingBox={selectedBoundingBoxForExport.boundingBox}
handleClose={() => setSelectedBoundingBoxForExport(null)}
/>
) : null}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import * as Utils from "libs/utils";
import { useSelector } from "react-redux";

type Props = {
destroy: () => void,
handleClose: () => void,
tracing: ?Tracing,
dataset: APIDataset,
boundingBox: BoundingBoxType,
Expand All @@ -32,7 +32,7 @@ type LayerInfos = {
isColorLayer: ?boolean,
};

const ExportBoundingBoxModal = ({ destroy, dataset, boundingBox, tracing }: Props) => {
const ExportBoundingBoxModal = ({ handleClose, dataset, boundingBox, tracing }: Props) => {
const [startedExports, setStartedExports] = useState([]);
const volumeTracing = tracing != null ? tracing.volume : null;
const annotationId = tracing != null ? tracing.annotationId : null;
Expand All @@ -50,10 +50,6 @@ const ExportBoundingBoxModal = ({ destroy, dataset, boundingBox, tracing }: Prop
);
const existsActivePersistentMapping = isMappingEnabled && !isMergerModeEnabled;

const handleClose = () => {
destroy();
};

const exportKey = (layerInfos: LayerInfos) =>
(layerInfos.layerName || "") + (layerInfos.tracingId || "");

Expand Down

0 comments on commit e1d38d8

Please sign in to comment.