You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2798 lines
78 KiB
JavaScript
2798 lines
78 KiB
JavaScript
import * as THREE from "./lib/three.module.js";
|
|
|
|
import { ViewManager } from "./view.js";
|
|
import { FastToolBox, FloatLabelManager } from "./floatlabel.js";
|
|
import { Mouse } from "./mouse.js";
|
|
import { BoxEditor, BoxEditorManager } from "./box_editor.js";
|
|
import { ImageContextManager } from "./image.js";
|
|
import { globalObjectCategory, categoryZh } from "./obj_cfg.js";
|
|
|
|
import { objIdManager } from "./obj_id_list.js";
|
|
import { Header } from "./header.js";
|
|
import { BoxOp } from "./box_op.js";
|
|
import { AutoAdjust } from "./auto-adjust.js";
|
|
import { PlayControl } from "./play.js";
|
|
import { reloadWorldList, saveWorldList } from "./save.js";
|
|
import { logger, create_logger } from "./log.js";
|
|
import { autoAnnotate } from "./auto_annotate.js";
|
|
import { Calib } from "./calib.js";
|
|
import { Trajectory } from "./trajectory.js";
|
|
import { ContextMenu } from "./context_menu.js";
|
|
import { InfoBox } from "./info_box.js";
|
|
import { CropScene } from "./crop_scene.js";
|
|
import { ConfigUi } from "./config_ui.js";
|
|
import { MovableView } from "./popup_dialog.js";
|
|
import { globalKeyDownManager } from "./keydown_manager.js";
|
|
import { vector_range } from "./util.js";
|
|
import { checkScene } from "./error_check.js";
|
|
|
|
function Editor(editorUi, wrapperUi, editorCfg, data, name = "editor") {
|
|
// create logger before anything else.
|
|
create_logger(
|
|
editorUi.querySelector("#log-wrapper"),
|
|
editorUi.querySelector("#log-button")
|
|
);
|
|
this.logger = logger;
|
|
|
|
this.editorCfg = editorCfg;
|
|
this.sideview_enabled = true;
|
|
this.editorUi = editorUi;
|
|
this.wrapperUi = wrapperUi;
|
|
this.container = null;
|
|
this.name = name;
|
|
|
|
this.data = data;
|
|
this.scene = null;
|
|
this.renderer = null;
|
|
this.selected_box = null;
|
|
this.windowWidth = null;
|
|
this.windowHeight = null;
|
|
this.floatLabelManager = null;
|
|
this.operation_state = {
|
|
key_pressed: false,
|
|
box_navigate_index: 0,
|
|
};
|
|
this.view_state = {
|
|
lock_obj_track_id: "",
|
|
lock_obj_in_highlight: false, // focus mode
|
|
autoLock: function (trackid, focus) {
|
|
this.lock_obj_track_id = trackid;
|
|
this.lock_obj_in_highlight = focus;
|
|
},
|
|
};
|
|
this.calib = new Calib(this.data, this);
|
|
|
|
this.header = null;
|
|
this.imageContextManager = null;
|
|
this.boxOp = null;
|
|
this.boxEditorManager = null;
|
|
this.params = {};
|
|
|
|
this.currentMainEditor = this; // who is on focus, this or batch-editor-manager?
|
|
|
|
this.init = function (editorUi) {
|
|
let self = this;
|
|
this.editorUi = editorUi;
|
|
|
|
this.playControl = new PlayControl(this.data);
|
|
|
|
this.configUi = new ConfigUi(
|
|
editorUi.querySelector("#config-button"),
|
|
editorUi.querySelector("#config-wrapper"),
|
|
this
|
|
);
|
|
|
|
this.header = new Header(
|
|
editorUi.querySelector("#header"),
|
|
this.data,
|
|
this.editorCfg,
|
|
(e) => {
|
|
this.scene_changed(e.currentTarget.value);
|
|
//event.currentTarget.blur();
|
|
},
|
|
(e) => {
|
|
this.frame_changed(e);
|
|
},
|
|
(e) => {
|
|
this.object_changed(e);
|
|
},
|
|
(e) => {
|
|
this.camera_changed(e);
|
|
}
|
|
);
|
|
|
|
//
|
|
// that way, the operation speed may be better
|
|
// if we load all worlds, we can speed up batch-mode operations, but the singl-world operations slows down.
|
|
// if we use two seperate scenes. can we solve this problem?
|
|
//
|
|
this.scene = new THREE.Scene();
|
|
this.mainScene = this.scene; //new THREE.Scene();
|
|
|
|
this.data.set_webglScene(this.scene, this.mainScene);
|
|
|
|
this.renderer = new THREE.WebGLRenderer({
|
|
antialias: true,
|
|
preserveDrawingBuffer: true,
|
|
});
|
|
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
|
|
this.container = editorUi.querySelector("#container");
|
|
this.container.appendChild(this.renderer.domElement);
|
|
|
|
this.boxOp = new BoxOp(this.data);
|
|
this.viewManager = new ViewManager(
|
|
this.container,
|
|
this.scene,
|
|
this.mainScene,
|
|
this.renderer,
|
|
function () {
|
|
self.render();
|
|
},
|
|
function (box) {
|
|
self.on_box_changed(box);
|
|
},
|
|
this.editorCfg
|
|
);
|
|
|
|
this.imageContextManager = new ImageContextManager(
|
|
this.editorUi.querySelector("#content"),
|
|
this.editorUi.querySelector("#camera-selector"),
|
|
this.editorCfg,
|
|
(lidar_points) => this.on_img_click(lidar_points)
|
|
);
|
|
|
|
if (!this.editorCfg.disableRangeCircle) this.addRangeCircle();
|
|
|
|
this.floatLabelManager = new FloatLabelManager(
|
|
this.editorUi,
|
|
this.container,
|
|
this.viewManager.mainView,
|
|
function (box) {
|
|
self.selectBox(box);
|
|
}
|
|
);
|
|
this.fastToolBox = new FastToolBox(
|
|
this.editorUi.querySelector("#obj-editor"),
|
|
(event) => this.handleFastToolEvent(event)
|
|
);
|
|
//this.controlGui = this.init_gui();
|
|
|
|
this.axis = new THREE.AxesHelper(1);
|
|
|
|
this.scene.add(this.axis);
|
|
|
|
window.addEventListener(
|
|
"resize",
|
|
function () {
|
|
self.onWindowResize();
|
|
},
|
|
false
|
|
);
|
|
|
|
if (!this.editorCfg.disableMainViewKeyDown) {
|
|
// this.container.onmouseenter = (event)=>{
|
|
// this.container.focus();
|
|
// };
|
|
|
|
// this.container.onmouseleave = (event)=>{
|
|
// this.container.blur();
|
|
// };
|
|
|
|
//this.container.addEventListener( 'keydown', function(e){self.keydown(e);} );
|
|
//this.editorUi.addEventListener( 'keydown', e=>this.keydown(e); );
|
|
|
|
this.keydownHandler = (event) => this.keydown(event);
|
|
//this.keydownDisabled = false;
|
|
//document.removeEventListener('keydown', this.keydownHandler);
|
|
//document.addEventListener( 'keydown', this.keydownHandler);
|
|
globalKeyDownManager.register(this.keydownHandler, "main editor");
|
|
}
|
|
|
|
this.globalKeyDownManager = globalKeyDownManager;
|
|
|
|
this.objectTrackView = new Trajectory(
|
|
this.editorUi.querySelector("#object-track-wrapper")
|
|
);
|
|
|
|
this.infoBox = new InfoBox(this.editorUi.querySelector("#info-wrapper"));
|
|
|
|
this.cropScene = new CropScene(
|
|
this.editorUi.querySelector("#crop-scene-wrapper"),
|
|
this
|
|
);
|
|
|
|
this.contextMenu = new ContextMenu(
|
|
this.editorUi.querySelector("#context-menu-wrapper")
|
|
);
|
|
|
|
this.boxEditorManager = new BoxEditorManager(
|
|
document.querySelector("#batch-box-editor"),
|
|
this.viewManager,
|
|
this.objectTrackView,
|
|
this.editorCfg,
|
|
this.boxOp,
|
|
this.header,
|
|
this.contextMenu,
|
|
this.configUi,
|
|
(b) => this.on_box_changed(b),
|
|
(b, r) => this.remove_box(b, r), // on box remove
|
|
() => {
|
|
// this.on_load_world_finished(this.data.world);
|
|
// this.imageContextManager.hide();
|
|
// this.floatLabelManager.hide();
|
|
// this.viewManager.mainView.disable();
|
|
// this.boxEditor.hide();
|
|
// this.hideGridLines();
|
|
// this.controlGui.hide();
|
|
}
|
|
); //func_on_annotation_reloaded
|
|
this.boxEditorManager.hide();
|
|
|
|
let boxEditorUi = this.editorUi.querySelector("#main-box-editor-wrapper");
|
|
this.boxEditor = new BoxEditor(
|
|
boxEditorUi,
|
|
null, // no box editor manager
|
|
this.viewManager,
|
|
this.editorCfg,
|
|
this.boxOp,
|
|
(b) => this.on_box_changed(b),
|
|
(b) => this.remove_box(b),
|
|
"main-boxe-ditor"
|
|
);
|
|
this.boxEditor.detach(); // hide it
|
|
this.boxEditor.setResize("both");
|
|
this.boxEditor.moveHandle = new MovableView(
|
|
boxEditorUi.querySelector("#focuscanvas"),
|
|
boxEditorUi.querySelector("#sub-views"),
|
|
() => {
|
|
this.boxEditor.update();
|
|
this.render();
|
|
}
|
|
);
|
|
|
|
this.mouse = new Mouse(
|
|
this.viewManager.mainView,
|
|
this.operation_state,
|
|
this.container,
|
|
this.editorUi,
|
|
function (ev) {
|
|
self.handleLeftClick(ev);
|
|
},
|
|
function (ev) {
|
|
self.handleRightClick(ev);
|
|
},
|
|
function (x, y, w, h, ctl, shift) {
|
|
self.handleSelectRect(x, y, w, h, ctl, shift);
|
|
}
|
|
);
|
|
|
|
this.autoAdjust = new AutoAdjust(this.boxOp, this.mouse, this.header);
|
|
|
|
//this.projectiveViewOps.hide();
|
|
|
|
if (!this.editorCfg.disableGrid) this.installGridLines();
|
|
|
|
window.onbeforeunload = function () {
|
|
return "Exit?";
|
|
//if we return nothing here (just calling return;) then there will be no pop-up question at all
|
|
//return;
|
|
};
|
|
|
|
this.onWindowResize();
|
|
};
|
|
|
|
this.run = function () {
|
|
//this.animate();
|
|
this.render();
|
|
//$( "#maincanvas" ).resizable();
|
|
|
|
this.imageContextManager.init_image_op(() => this.selected_box);
|
|
|
|
this.add_global_obj_type();
|
|
};
|
|
|
|
this.hide = function () {
|
|
this.wrapperUi.style.display = "none";
|
|
};
|
|
this.show = function () {
|
|
this.wrapperUi.style.display = "block";
|
|
};
|
|
|
|
this.moveRangeCircle = function (world) {
|
|
if (this.rangeCircle.parent) {
|
|
world.webglGroup.add(this.rangeCircle);
|
|
}
|
|
};
|
|
|
|
this.addRangeCircle = function () {
|
|
var h = 1;
|
|
|
|
var body = [];
|
|
|
|
var segments = 64;
|
|
for (var i = 0; i < segments; i++) {
|
|
var theta1 = ((2 * Math.PI) / segments) * i;
|
|
var x1 = Math.cos(theta1);
|
|
var y1 = Math.sin(theta1);
|
|
|
|
var theta2 = ((2 * Math.PI) / segments) * ((i + 1) % segments);
|
|
var x2 = Math.cos(theta2);
|
|
var y2 = Math.sin(theta2);
|
|
|
|
body.push(x1, y1, h, x2, y2, h);
|
|
body.push(0.6 * x1, 0.6 * y1, h, 0.6 * x2, 0.6 * y2, h);
|
|
body.push(2.0 * x1, 2.0 * y1, h, 2.0 * x2, 2.0 * y2, h);
|
|
}
|
|
|
|
this.data.dbg.alloc();
|
|
var bbox = new THREE.BufferGeometry();
|
|
bbox.setAttribute("position", new THREE.Float32BufferAttribute(body, 3));
|
|
|
|
var box = new THREE.LineSegments(
|
|
bbox,
|
|
new THREE.LineBasicMaterial({
|
|
color: 0x888800,
|
|
linewidth: 1,
|
|
opacity: 0.5,
|
|
transparent: true,
|
|
})
|
|
);
|
|
|
|
box.scale.x = 50;
|
|
box.scale.y = 50;
|
|
box.scale.z = -3;
|
|
box.position.x = 0;
|
|
box.position.y = 0;
|
|
box.position.z = 0;
|
|
box.computeLineDistances();
|
|
this.rangeCircle = box;
|
|
this.scene.add(box);
|
|
};
|
|
|
|
this.showRangeCircle = function (show) {
|
|
if (show) {
|
|
if (this.data.world) {
|
|
this.data.world.webglGroup.add(this.rangeCircle);
|
|
}
|
|
} else {
|
|
if (this.rangeCircle.parent)
|
|
this.rangeCircle.parent.remove(this.rangeCircle);
|
|
}
|
|
|
|
this.render();
|
|
};
|
|
|
|
this.hideGridLines = function () {
|
|
var svg = this.editorUi.querySelector("#grid-lines-wrapper");
|
|
svg.style.display = "none";
|
|
};
|
|
this.showGridLines = function () {
|
|
var svg = this.editorUi.querySelector("#grid-lines-wrapper");
|
|
svg.style.display = "";
|
|
};
|
|
this.installGridLines = function () {
|
|
var svg = this.editorUi.querySelector("#grid-lines-wrapper");
|
|
|
|
for (var i = 1; i < 10; i++) {
|
|
const line = document.createElementNS(
|
|
"http://www.w3.org/2000/svg",
|
|
"line"
|
|
);
|
|
line.setAttribute("x1", "0%");
|
|
line.setAttribute("y1", String(i * 10) + "%");
|
|
line.setAttribute("x2", "100%");
|
|
line.setAttribute("y2", String(i * 10) + "%");
|
|
line.setAttribute("class", "grid-line");
|
|
svg.appendChild(line);
|
|
}
|
|
|
|
for (var i = 1; i < 10; i++) {
|
|
const line = document.createElementNS(
|
|
"http://www.w3.org/2000/svg",
|
|
"line"
|
|
);
|
|
line.setAttribute("y1", "0%");
|
|
line.setAttribute("x1", String(i * 10) + "%");
|
|
line.setAttribute("y2", "100%");
|
|
line.setAttribute("x2", String(i * 10) + "%");
|
|
line.setAttribute("class", "grid-line");
|
|
svg.appendChild(line);
|
|
}
|
|
};
|
|
|
|
this.handleFastToolEvent = function (event) {
|
|
let self = this;
|
|
switch (event.currentTarget.id) {
|
|
case "label-del":
|
|
self.remove_selected_box();
|
|
self.header.updateModifiedStatus();
|
|
break;
|
|
case "label-gen-id":
|
|
//self.autoAdjust.mark_bbox(self.selected_box);
|
|
//event.currentTarget.blur();
|
|
let id = objIdManager.generateNewUniqueId();
|
|
self.fastToolBox.setValue(
|
|
self.selected_box.obj_type,
|
|
id,
|
|
self.selected_box.obj_attr
|
|
);
|
|
|
|
self.setObjectId(id);
|
|
break;
|
|
case "label-copy":
|
|
if (!this.selected_box.obj_track_id) {
|
|
this.infoBox.show("Error", "Please assign object track ID.");
|
|
} else {
|
|
self.autoAdjust.mark_bbox(self.selected_box);
|
|
}
|
|
break;
|
|
|
|
case "label-paste":
|
|
//this.autoAdjust.smart_paste(self.selected_box, null, (b)=>this.on_box_changed(b));
|
|
this.boxOp.auto_rotate_xyz(
|
|
this.selected_box,
|
|
null,
|
|
null,
|
|
(b) => this.on_box_changed(b),
|
|
"noscaling"
|
|
);
|
|
//event.currentTarget.blur();
|
|
break;
|
|
|
|
case "label-batchedit":
|
|
{
|
|
if (!this.ensureBoxTrackIdExist()) break;
|
|
|
|
if (!this.ensurePreloaded()) break;
|
|
|
|
this.header.setObject(this.selected_box.obj_track_id);
|
|
this.editBatch(
|
|
this.data.world.frameInfo.scene,
|
|
this.data.world.frameInfo.frame,
|
|
this.selected_box.obj_track_id,
|
|
this.selected_box.obj_type
|
|
);
|
|
}
|
|
break;
|
|
|
|
case "label-trajectory":
|
|
this.showTrajectory();
|
|
break;
|
|
|
|
case "label-edit":
|
|
event.currentTarget.blur();
|
|
self.selectBox(self.selected_box);
|
|
break;
|
|
|
|
// case "label-reset":
|
|
// event.currentTarget.blur();
|
|
// if (self.selected_box){
|
|
// //switch_bbox_type(this.selected_box.obj_type);
|
|
// self.transform_bbox("reset");
|
|
// }
|
|
// break;
|
|
|
|
case "label-highlight":
|
|
event.currentTarget.blur();
|
|
if (self.selected_box.in_highlight) {
|
|
self.cancelFocus(self.selected_box);
|
|
self.view_state.lock_obj_in_highlight = false;
|
|
} else {
|
|
self.focusOnSelectedBox(self.selected_box);
|
|
}
|
|
break;
|
|
|
|
case "label-rotate":
|
|
event.currentTarget.blur();
|
|
self.transform_bbox("z_rotate_reverse");
|
|
break;
|
|
|
|
case "object-category-selector":
|
|
this.object_category_changed(event);
|
|
break;
|
|
case "object-track-id-editor":
|
|
this.object_track_id_changed(event);
|
|
break;
|
|
case "attr-input":
|
|
this.object_attribute_changed(event.currentTarget.value);
|
|
break;
|
|
default:
|
|
this.handleContextMenuEvent(event);
|
|
break;
|
|
}
|
|
};
|
|
|
|
this.cancelFocus = function (box) {
|
|
box.in_highlight = false;
|
|
//view_state.lock_obj_in_highlight = false; // when user unhighlight explicitly, set it to false
|
|
this.data.world.lidar.cancel_highlight(box);
|
|
this.floatLabelManager.restore_all();
|
|
|
|
this.viewManager.mainView.save_orbit_state(box.scale);
|
|
this.viewManager.mainView.orbit.reset();
|
|
};
|
|
|
|
this.focusOnSelectedBox = function (box) {
|
|
if (this.editorCfg.disableMainView) return;
|
|
|
|
if (box) {
|
|
this.data.world.lidar.highlight_box_points(box);
|
|
|
|
this.floatLabelManager.hide_all();
|
|
this.viewManager.mainView.orbit.saveState();
|
|
|
|
//this.viewManager.mainView.camera.position.set(this.selected_box.position.x+this.selected_box.scale.x*3, this.selected_box.position.y+this.selected_box.scale.y*3, this.selected_box.position.z+this.selected_box.scale.z*3);
|
|
|
|
let posG = this.data.world.lidarPosToScene(box.position);
|
|
this.viewManager.mainView.orbit.target.x = posG.x;
|
|
this.viewManager.mainView.orbit.target.y = posG.y;
|
|
this.viewManager.mainView.orbit.target.z = posG.z;
|
|
|
|
this.viewManager.mainView.restore_relative_orbit_state(box.scale);
|
|
this.viewManager.mainView.orbit.update();
|
|
|
|
this.render();
|
|
box.in_highlight = true;
|
|
this.view_state.lock_obj_in_highlight = true;
|
|
}
|
|
};
|
|
|
|
this.showTrajectory = function () {
|
|
if (!this.selected_box) return;
|
|
|
|
if (!this.selected_box.obj_track_id) {
|
|
console.error("no track id");
|
|
return;
|
|
}
|
|
|
|
let tracks = this.data.worldList.map((w) => {
|
|
let box = w.annotation.findBoxByTrackId(this.selected_box.obj_track_id);
|
|
let ann = null;
|
|
if (box) {
|
|
ann = w.annotation.boxToAnn(box);
|
|
ann.psr.position = w.lidarPosToUtm(ann.psr.position);
|
|
ann.psr.rotation = w.lidarRotToUtm(ann.psr.rotation);
|
|
}
|
|
return [w.frameInfo.frame, ann, w === this.data.world];
|
|
});
|
|
|
|
tracks.sort((a, b) => (a[0] > b[0] ? 1 : -1));
|
|
|
|
this.objectTrackView.setObject(
|
|
this.selected_box.obj_type,
|
|
this.selected_box.obj_track_id,
|
|
tracks,
|
|
(targetFrame) => {
|
|
//onExit
|
|
this.load_world(this.data.world.frameInfo.scene, targetFrame);
|
|
}
|
|
);
|
|
};
|
|
|
|
// return true to close contextmenu
|
|
// return false to keep contextmenu
|
|
this.handleContextMenuEvent = function (event) {
|
|
switch (event.currentTarget.id) {
|
|
case "cm-play-2fps":
|
|
this.playControl.play((w) => {
|
|
this.on_load_world_finished(w);
|
|
}, 2);
|
|
break;
|
|
case "cm-play-10fps":
|
|
this.playControl.play((w) => {
|
|
this.on_load_world_finished(w);
|
|
}, 10);
|
|
break;
|
|
case "cm-play-20fps":
|
|
this.playControl.play((w) => {
|
|
this.on_load_world_finished(w);
|
|
}, 20);
|
|
break;
|
|
case "cm-play-50fps":
|
|
this.playControl.play((w) => {
|
|
this.on_load_world_finished(w);
|
|
}, 50);
|
|
break;
|
|
case "cm-paste":
|
|
{
|
|
let box = this.add_box_on_mouse_pos_by_ref();
|
|
|
|
if (!event.shiftKey) {
|
|
logger.log("paste without auto-adjusting");
|
|
this.boxOp.auto_rotate_xyz(
|
|
box,
|
|
null,
|
|
null,
|
|
(b) => this.on_box_changed(b),
|
|
"noscaling"
|
|
);
|
|
}
|
|
}
|
|
break;
|
|
case "cm-prev-frame":
|
|
this.previous_frame();
|
|
break;
|
|
case "cm-next-frame":
|
|
this.next_frame();
|
|
break;
|
|
case "cm-last-frame":
|
|
this.last_frame();
|
|
break;
|
|
case "cm-first-frame":
|
|
this.first_frame();
|
|
break;
|
|
case "cm-go-to-10hz":
|
|
this.load_world(
|
|
this.data.world.frameInfo.scene + "_10hz",
|
|
this.data.world.frameInfo.frame
|
|
);
|
|
|
|
// {
|
|
// let link = document.createElement("a");
|
|
// //link.download=`${this.data.world.frameInfo.scene}-${this.data.world.frameInfo.frame}-webgl`;
|
|
// link.href="http://localhost";
|
|
// link.target="_blank";
|
|
// link.click();
|
|
// }
|
|
break;
|
|
case "cm-go-to-full-2hz":
|
|
this.load_world(
|
|
this.data.world.frameInfo.scene + "_full_2hz",
|
|
this.data.world.frameInfo.frame
|
|
);
|
|
break;
|
|
|
|
case "cm-go-to-2hz":
|
|
this.load_world(
|
|
this.data.world.frameInfo.scene.split("_")[0],
|
|
this.data.world.frameInfo.frame
|
|
);
|
|
break;
|
|
|
|
case "cm-save":
|
|
saveWorldList(this.data.worldList);
|
|
break;
|
|
|
|
case "cm-reload":
|
|
{
|
|
reloadWorldList([this.data.world], () => {
|
|
this.on_load_world_finished(this.data.world);
|
|
this.header.updateModifiedStatus();
|
|
});
|
|
}
|
|
break;
|
|
|
|
case "cm-reload-all":
|
|
{
|
|
let modifiedFrames = this.data.worldList.filter(
|
|
(w) => w.annotation.modified
|
|
);
|
|
|
|
if (modifiedFrames.length > 0) {
|
|
this.infoBox.show(
|
|
"Confirm",
|
|
`Discard changes to ${modifiedFrames.length} frames, continue to reload?`,
|
|
["yes", "no"],
|
|
(choice) => {
|
|
if (choice == "yes") {
|
|
reloadWorldList(this.data.worldList, () => {
|
|
this.on_load_world_finished(this.data.world);
|
|
this.header.updateModifiedStatus();
|
|
});
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
reloadWorldList(this.data.worldList, () => {
|
|
this.on_load_world_finished(this.data.world);
|
|
this.header.updateModifiedStatus();
|
|
});
|
|
|
|
objIdManager.forceUpdate();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case "cm-stop":
|
|
this.playControl.stop_play();
|
|
break;
|
|
case "cm-pause":
|
|
this.playControl.pause_resume_play();
|
|
break;
|
|
|
|
case "cm-prev-object":
|
|
this.select_previous_object();
|
|
break;
|
|
|
|
case "cm-next-object":
|
|
this.select_previous_object();
|
|
break;
|
|
|
|
case "cm-show-frame-info":
|
|
{
|
|
let info = {
|
|
"scend-id": this.data.world.frameInfo.scene,
|
|
frame: this.data.world.frameInfo.frame,
|
|
};
|
|
|
|
if (this.data.world.frameInfo.sceneMeta.desc) {
|
|
info = {
|
|
...info,
|
|
...this.data.world.frameInfo.sceneMeta.desc,
|
|
};
|
|
}
|
|
|
|
this.infoBox.show(
|
|
"Frame info - " + this.data.world.frameInfo.scene,
|
|
JSON.stringify(info, null, "<br>")
|
|
);
|
|
}
|
|
break;
|
|
|
|
case "cm-show-stat":
|
|
{
|
|
let scene = this.data.world.frameInfo.scene;
|
|
objIdManager.load_obj_ids_of_scene(scene, (objs) => {
|
|
let info = {
|
|
objects: objs.length,
|
|
boxes: objs.reduce((a, b) => a + b.count, 0),
|
|
frames: this.data.world.frameInfo.sceneMeta.frames.length,
|
|
};
|
|
|
|
this.infoBox.show(
|
|
"Stat - " + scene,
|
|
JSON.stringify(info, null, "<br>")
|
|
);
|
|
});
|
|
}
|
|
break;
|
|
/// object
|
|
|
|
case "cm-check-scene":
|
|
{
|
|
let scene = this.data.world.frameInfo.scene;
|
|
checkScene(scene);
|
|
logger.show();
|
|
logger.errorBtn.onclick();
|
|
}
|
|
break;
|
|
case "cm-reset-view":
|
|
this.resetView();
|
|
break;
|
|
case "cm-delete":
|
|
this.remove_selected_box();
|
|
this.header.updateModifiedStatus();
|
|
break;
|
|
|
|
case "cm-edit-multiple-instances":
|
|
this.enterBatchEditMode();
|
|
|
|
break;
|
|
case "cm-auto-ann-background":
|
|
{
|
|
this.autoAnnInBackground();
|
|
}
|
|
break;
|
|
case "cm-interpolate-background":
|
|
{
|
|
this.interpolateInBackground();
|
|
}
|
|
break;
|
|
case "cm-show-trajectory":
|
|
this.showTrajectory();
|
|
break;
|
|
|
|
case "cm-select-as-ref":
|
|
if (!this.selected_box.obj_track_id) {
|
|
this.infoBox.show("Error", "Please assign object track ID.");
|
|
return false;
|
|
} else {
|
|
this.autoAdjust.mark_bbox(this.selected_box);
|
|
}
|
|
break;
|
|
|
|
case "cm-change-id-to-ref":
|
|
if (!this.ensureRefObjExist()) break;
|
|
|
|
this.setObjectId(this.autoAdjust.marked_object.ann.obj_id);
|
|
this.fastToolBox.setValue(
|
|
this.selected_box.obj_type,
|
|
this.selected_box.obj_track_id,
|
|
this.selected_box.obj_attr
|
|
);
|
|
|
|
break;
|
|
case "cm-change-id-to-ref-in-scene":
|
|
if (!this.ensureBoxTrackIdExist()) break;
|
|
if (!this.ensurePreloaded()) break;
|
|
if (!this.ensureRefObjExist()) break;
|
|
|
|
this.data.worldList.forEach((w) => {
|
|
let box = w.annotation.boxes.find(
|
|
(b) =>
|
|
b.obj_track_id === this.selected_box.obj_track_id &&
|
|
b.obj_type === this.selected_box.obj_type
|
|
);
|
|
if (box && box !== this.selected_box) {
|
|
box.obj_track_id = this.autoAdjust.marked_object.ann.obj_id;
|
|
w.annotation.setModified();
|
|
}
|
|
});
|
|
|
|
this.setObjectId(this.autoAdjust.marked_object.ann.obj_id);
|
|
this.fastToolBox.setValue(
|
|
this.selected_box.obj_type,
|
|
this.selected_box.obj_track_id,
|
|
this.selected_box.obj_attr
|
|
);
|
|
|
|
break;
|
|
case "cm-follow-ref":
|
|
if (!this.ensureBoxTrackIdExist()) break;
|
|
if (!this.ensurePreloaded()) break;
|
|
this.autoAdjust.followsRef(this.selected_box);
|
|
this.header.updateModifiedStatus();
|
|
this.editBatch(
|
|
this.data.world.frameInfo.scene,
|
|
this.data.world.frameInfo.frame,
|
|
this.selected_box.obj_track_id,
|
|
this.selected_box.obj_type
|
|
);
|
|
break;
|
|
case "cm-follow-static-objects":
|
|
if (!this.ensureBoxTrackIdExist()) break;
|
|
if (!this.ensurePreloaded()) break;
|
|
this.autoAdjust.followStaticObjects(this.selected_box);
|
|
this.header.updateModifiedStatus();
|
|
|
|
this.editBatch(
|
|
this.data.world.frameInfo.scene,
|
|
this.data.world.frameInfo.frame,
|
|
this.selected_box.obj_track_id,
|
|
this.selected_box.obj_type
|
|
);
|
|
|
|
break;
|
|
case "cm-sync-followers":
|
|
if (!this.ensurePreloaded()) break;
|
|
this.autoAdjust.syncFollowers(this.selected_box);
|
|
this.header.updateModifiedStatus();
|
|
this.render();
|
|
break;
|
|
|
|
case "cm-delete-obj":
|
|
{
|
|
//let saveList=[];
|
|
this.data.worldList.forEach((w) => {
|
|
let box = w.annotation.boxes.find(
|
|
(b) => b.obj_track_id === this.selected_box.obj_track_id
|
|
);
|
|
if (box && box !== this.selected_box) {
|
|
w.annotation.unload_box(box);
|
|
w.annotation.remove_box(box);
|
|
//saveList.push(w);
|
|
w.annotation.setModified();
|
|
}
|
|
});
|
|
|
|
//saveWorldList(saveList);
|
|
this.remove_selected_box();
|
|
this.header.updateModifiedStatus();
|
|
}
|
|
break;
|
|
|
|
case "cm-modify-obj-type":
|
|
{
|
|
if (!this.ensurePreloaded()) break;
|
|
//let saveList=[];
|
|
this.data.worldList.forEach((w) => {
|
|
let box = w.annotation.boxes.find(
|
|
(b) => b.obj_track_id === this.selected_box.obj_track_id
|
|
);
|
|
if (box && box !== this.selected_box) {
|
|
box.obj_type = this.selected_box.obj_type;
|
|
box.obj_attr = this.selected_box.obj_attr;
|
|
//saveList.push(w);
|
|
w.annotation.setModified();
|
|
}
|
|
});
|
|
|
|
//saveWorldList(saveList);
|
|
this.header.updateModifiedStatus();
|
|
}
|
|
break;
|
|
|
|
case "cm-modify-obj-size":
|
|
{
|
|
if (!this.ensurePreloaded()) break;
|
|
//let saveList=[];
|
|
this.data.worldList.forEach((w) => {
|
|
let box = w.annotation.boxes.find(
|
|
(b) => b.obj_track_id == this.selected_box.obj_track_id
|
|
);
|
|
if (box && box !== this.selected_box) {
|
|
box.scale.x = this.selected_box.scale.x;
|
|
box.scale.y = this.selected_box.scale.y;
|
|
box.scale.z = this.selected_box.scale.z;
|
|
//saveList.push(w);
|
|
|
|
w.annotation.setModified();
|
|
}
|
|
});
|
|
|
|
//saveWorldList(saveList);
|
|
this.header.updateModifiedStatus();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
console.log("unhandled", event.currentTarget.id, event.type);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
// this.animate= function() {
|
|
// let self=this;
|
|
// requestAnimationFrame( function(){self.animate();} );
|
|
// this.viewManager.mainView.orbit_orth.update();
|
|
// };
|
|
|
|
this.render = function () {
|
|
this.viewManager.mainView.render();
|
|
this.boxEditor.boxView.render();
|
|
|
|
this.floatLabelManager.update_all_position();
|
|
if (this.selected_box) {
|
|
this.fastToolBox.setPos(
|
|
this.floatLabelManager.getLabelEditorPos(this.selected_box.obj_local_id)
|
|
);
|
|
}
|
|
};
|
|
|
|
this.resetView = function (targetPos) {
|
|
if (!targetPos) {
|
|
let center = this.data.world.lidar.computeCenter();
|
|
targetPos = { ...center }; //{x:0, y:0, z:50};
|
|
targetPos.z += 50;
|
|
} else targetPos.z = 50;
|
|
|
|
let pos = this.data.world.lidarPosToScene(targetPos);
|
|
this.viewManager.mainView.orbit.object.position.set(pos.x, pos.y, pos.z); //object is camera
|
|
this.viewManager.mainView.orbit.target.set(pos.x, pos.y, 0);
|
|
this.viewManager.mainView.orbit.update();
|
|
this.render();
|
|
};
|
|
|
|
this.scene_changed = async function (sceneName) {
|
|
//var sceneName = event.currentTarget.value;
|
|
|
|
if (sceneName.length == 0) {
|
|
return;
|
|
}
|
|
|
|
console.log("choose sceneName " + sceneName);
|
|
var meta = this.data.getMetaBySceneName(sceneName);
|
|
|
|
if (!meta) {
|
|
this.editorUi.querySelector("#frame-selector").innerHTML =
|
|
"<option>结构</option>";
|
|
meta = await this.data.readSceneMetaData(sceneName);
|
|
}
|
|
|
|
var frame_selector_str = meta.frames
|
|
.map(function (f) {
|
|
return "<option value=" + f + ">" + f + "</option>";
|
|
})
|
|
.reduce(function (x, y) {
|
|
return x + y;
|
|
}, "<option>结构</option>");
|
|
|
|
this.editorUi.querySelector("#frame-selector").innerHTML =
|
|
frame_selector_str;
|
|
|
|
if (meta.camera) {
|
|
this.imageContextManager.updateCameraList(meta.camera);
|
|
}
|
|
|
|
//load_obj_ids_of_scene(sceneName);
|
|
};
|
|
|
|
this.frame_changed = function (event) {
|
|
var sceneName = this.editorUi.querySelector("#scene-selector").value;
|
|
console.log(sceneName,'--------------')
|
|
if (sceneName.length == 0 && this.data.world) {
|
|
sceneName = this.data.world.frameInfo.scene;
|
|
}
|
|
|
|
if (sceneName.length == 0) {
|
|
return;
|
|
}
|
|
|
|
var frame = event.currentTarget.value;
|
|
console.log(sceneName, frame);
|
|
this.load_world(sceneName, frame);
|
|
event.currentTarget.blur();
|
|
};
|
|
|
|
this.ensureBoxTrackIdExist = function () {
|
|
if (!this.selected_box.obj_track_id) {
|
|
this.infoBox.show("Error", "Please assign object track ID.");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
this.ensureRefObjExist = function () {
|
|
if (!this.autoAdjust.marked_object) {
|
|
this.infoBox.show("Notice", "No reference object was selected");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
this.ensurePreloaded = function () {
|
|
let worldList = this.data.worldList.filter(
|
|
(w) => w.frameInfo.scene == this.data.world.frameInfo.scene
|
|
);
|
|
worldList = worldList.sort(
|
|
(a, b) => a.frameInfo.frame_index - b.frameInfo.frame_index
|
|
);
|
|
|
|
let meta = this.data.get_current_world_scene_meta();
|
|
|
|
let allLoaded = worldList
|
|
.map((w) => w.preloaded())
|
|
.reduce((a, b) => a && b, true);
|
|
|
|
if (
|
|
(worldList.length < meta.frames.length && worldList.length <= 60) ||
|
|
!allLoaded
|
|
) {
|
|
this.data.forcePreloadScene(
|
|
this.data.world.frameInfo.scene,
|
|
this.data.world
|
|
);
|
|
|
|
this.infoBox.show(
|
|
"Notice",
|
|
`Loading scene in background. Please try again later.`
|
|
);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
this.interpolateInBackground = function () {
|
|
if (!this.ensureBoxTrackIdExist()) return;
|
|
|
|
if (!this.ensurePreloaded()) return;
|
|
|
|
let worldList = this.data.worldList.filter(
|
|
(w) => w.frameInfo.scene == this.data.world.frameInfo.scene
|
|
);
|
|
worldList = worldList.sort(
|
|
(a, b) => a.frameInfo.frame_index - b.frameInfo.frame_index
|
|
);
|
|
let boxList = worldList.map((w) =>
|
|
w.annotation.findBoxByTrackId(this.selected_box.obj_track_id)
|
|
);
|
|
|
|
let applyIndList = boxList.map((b) => true);
|
|
this.boxOp
|
|
.interpolateAsync(worldList, boxList, applyIndList)
|
|
.then((ret) => {
|
|
this.header.updateModifiedStatus();
|
|
this.viewManager.render();
|
|
});
|
|
};
|
|
this.enterBatchEditMode = function () {
|
|
if (!this.ensureBoxTrackIdExist()) return;
|
|
|
|
if (!this.ensurePreloaded()) return;
|
|
|
|
this.header.setObject(this.selected_box.obj_track_id);
|
|
|
|
this.editBatch(
|
|
this.data.world.frameInfo.scene,
|
|
this.data.world.frameInfo.frame,
|
|
this.selected_box.obj_track_id,
|
|
this.selected_box.obj_type
|
|
);
|
|
};
|
|
|
|
this.autoAnnInBackground = function () {
|
|
if (!this.ensureBoxTrackIdExist()) return;
|
|
|
|
if (!this.ensurePreloaded()) return;
|
|
|
|
let worldList = this.data.worldList.filter(
|
|
(w) => w.frameInfo.scene == this.data.world.frameInfo.scene
|
|
);
|
|
worldList = worldList.sort(
|
|
(a, b) => a.frameInfo.frame_index - b.frameInfo.frame_index
|
|
);
|
|
|
|
let boxList = worldList.map((w) =>
|
|
w.annotation.findBoxByTrackId(this.selected_box.obj_track_id)
|
|
);
|
|
|
|
let onFinishOneBox = (i) => {
|
|
this.viewManager.render();
|
|
};
|
|
let applyIndList = boxList.map((b) => true);
|
|
let dontRotate = false;
|
|
|
|
this.boxOp
|
|
.interpolateAndAutoAdjustAsync(
|
|
worldList,
|
|
boxList,
|
|
onFinishOneBox,
|
|
applyIndList,
|
|
dontRotate
|
|
)
|
|
.then((ret) => {
|
|
this.header.updateModifiedStatus();
|
|
});
|
|
};
|
|
|
|
this.editBatch = function (sceneName, frame, objectTrackId, objectType) {
|
|
//this.keydownDisabled = true;
|
|
// hide something
|
|
this.imageContextManager.hide();
|
|
this.floatLabelManager.hide();
|
|
|
|
//this.floatLabelManager.showFastToolbox();
|
|
|
|
this.viewManager.mainView.disable();
|
|
this.boxEditor.hide();
|
|
this.hideGridLines();
|
|
//this.controlGui.hide();
|
|
this.editorUi.querySelector("#selectors").style.display = "none";
|
|
//this.editorUi.querySelector("#object-selector").style.display='none';
|
|
this.currentMainEditor = this.boxEditorManager;
|
|
|
|
this.boxEditorManager.edit(
|
|
this.data,
|
|
this.data.getMetaBySceneName(sceneName),
|
|
frame,
|
|
objectTrackId,
|
|
objectType,
|
|
(targetFrame, targetTrackId) => {
|
|
//on exit
|
|
this.currentMainEditor = this;
|
|
//this.keydownDisabled = false;
|
|
this.viewManager.mainView.enable();
|
|
|
|
this.imageContextManager.show();
|
|
this.floatLabelManager.show();
|
|
|
|
if (targetTrackId) this.view_state.lock_obj_track_id = targetTrackId;
|
|
|
|
this.on_load_world_finished(this.data.world);
|
|
|
|
// if (this.selected_box){
|
|
// // attach again, restore box.boxEditor
|
|
// // obj type/id may have changed in batch mode
|
|
// this.floatLabelManager.set_object_track_id(this.selected_box.obj_local_id, this.selected_box.obj_track_id);
|
|
// this.boxEditor.attachBox(this.selected_box);
|
|
// this.boxEditor.update();
|
|
|
|
// // update fasttoolbox
|
|
// this.fastToolBox.setValue(this.selected_box.obj_type, this.selected_box.obj_track_id, this.selected_box.obj_attr);
|
|
// }
|
|
|
|
this.showGridLines();
|
|
this.render();
|
|
//this.controlGui.show();
|
|
this.editorUi.querySelector("#selectors").style.display = "inherit";
|
|
|
|
if (targetFrame) {
|
|
this.load_world(this.data.world.frameInfo.scene, targetFrame, () => {
|
|
// onfinished
|
|
this.makeVisible(targetTrackId);
|
|
});
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
this.gotoObjectFrame = function (frame, objId) {
|
|
this.load_world(this.data.world.frameInfo.scene, frame, () => {
|
|
// onfinished
|
|
this.makeVisible(objId);
|
|
});
|
|
};
|
|
|
|
this.makeVisible = function (targetTrackId) {
|
|
let box = this.data.world.annotation.findBoxByTrackId(targetTrackId);
|
|
|
|
if (box) {
|
|
if (this.selected_box != box) {
|
|
this.selectBox(box);
|
|
}
|
|
|
|
this.resetView({ x: box.position.x, y: box.position.y, z: 50 });
|
|
}
|
|
};
|
|
|
|
this.object_changed = function (event) {
|
|
var sceneName = this.data.world.frameInfo.scene; //this.editorUi.querySelector("#scene-selector").value;
|
|
|
|
let objectTrackId = event.currentTarget.value;
|
|
let obj = objIdManager.getObjById(objectTrackId);
|
|
|
|
this.editBatch(sceneName, null, objectTrackId, obj.category);
|
|
};
|
|
|
|
this.camera_changed = function (event) {
|
|
var camera_name = event.currentTarget.value;
|
|
|
|
this.data.set_active_image(camera_name);
|
|
this.imageContextManager.render_2d_image();
|
|
|
|
event.currentTarget.blur();
|
|
};
|
|
|
|
this.downloadWebglScreenShot = function () {
|
|
let link = document.createElement("a");
|
|
link.download = `${this.data.world.frameInfo.scene}-${this.data.world.frameInfo.frame}-webgl`;
|
|
link.href = this.renderer.domElement.toDataURL("image/png", 1);
|
|
link.click();
|
|
};
|
|
|
|
this.showLog = function () {};
|
|
|
|
this.annotateByAlg1 = function () {
|
|
autoAnnotate(this.data.world, () =>
|
|
this.on_load_world_finished(this.data.world)
|
|
);
|
|
};
|
|
|
|
this.object_category_changed = function (event) {
|
|
if (this.selected_box) {
|
|
let category = event.currentTarget.value;
|
|
|
|
this.selected_box.obj_type = category;
|
|
this.floatLabelManager.set_object_type(
|
|
this.selected_box.obj_local_id,
|
|
this.selected_box.obj_type
|
|
);
|
|
// this.header.mark_changed_flag();
|
|
// this.updateBoxPointsColor(this.selected_box);
|
|
// this.imageContextManager.boxes_manager.update_obj_type(this.selected_box.obj_local_id, this.selected_box.obj_type);
|
|
|
|
// this.render();
|
|
this.on_box_changed(this.selected_box);
|
|
|
|
//todo: we don't know if the old one is already deleted.
|
|
// could use object count number?
|
|
objIdManager.addObject({
|
|
category: this.selected_box.obj_type,
|
|
id: this.selected_box.obj_track_id,
|
|
});
|
|
}
|
|
};
|
|
|
|
this.setObjectId = function (id) {
|
|
this.selected_box.obj_track_id = id;
|
|
this.floatLabelManager.set_object_track_id(
|
|
this.selected_box.obj_local_id,
|
|
this.selected_box.obj_track_id
|
|
);
|
|
|
|
this.view_state.lock_obj_track_id = id;
|
|
|
|
//this.header.mark_changed_flag();
|
|
this.on_box_changed(this.selected_box);
|
|
|
|
//
|
|
objIdManager.addObject({
|
|
category: this.selected_box.obj_type,
|
|
id: this.selected_box.obj_track_id,
|
|
});
|
|
};
|
|
|
|
this.object_track_id_changed = function (event) {
|
|
if (this.selected_box) {
|
|
var id = event.currentTarget.value;
|
|
this.setObjectId(id);
|
|
}
|
|
};
|
|
|
|
this.object_attribute_changed = function (value) {
|
|
if (this.selected_box) {
|
|
this.selected_box.obj_attr = value;
|
|
this.floatLabelManager.set_object_attr(
|
|
this.selected_box.obj_local_id,
|
|
value
|
|
);
|
|
this.data.world.annotation.setModified();
|
|
this.header.updateModifiedStatus();
|
|
}
|
|
};
|
|
|
|
// this.updateSubviewRangeByWindowResize= function(box){
|
|
|
|
// if (box === null)
|
|
// return;
|
|
|
|
// if (box.boxEditor)
|
|
// box.boxEditor.onWindowResize();
|
|
|
|
// this.render();
|
|
// };
|
|
|
|
this.handleRightClick = function (event) {
|
|
// select new object
|
|
|
|
if (!this.data.world) {
|
|
return;
|
|
}
|
|
|
|
if (event.shiftKey || event.ctrlKey) {
|
|
// if ctrl or shift hold, don't select any object.
|
|
this.contextMenu.show("world", event.layerX, event.layerY, this);
|
|
return;
|
|
}
|
|
|
|
var intersects = this.mouse.getIntersects(
|
|
this.mouse.onUpPosition,
|
|
this.data.world.annotation.boxes
|
|
);
|
|
if (intersects.length > 0) {
|
|
//var object = intersects[ 0 ].object;
|
|
var object = intersects[0].object;
|
|
let target_obj = object.userData.object;
|
|
if (target_obj == undefined) {
|
|
// helper
|
|
target_obj = object;
|
|
}
|
|
|
|
if (target_obj != this.selected_box) {
|
|
this.selectBox(target_obj);
|
|
}
|
|
|
|
// this.hide_world_context_menu();
|
|
// this.show_object_context_menu(event.layerX, event.layerY);
|
|
this.contextMenu.show("object", event.layerX, event.layerY, this);
|
|
} else {
|
|
// if no object is selected, popup context menu
|
|
//var pos = getMousePosition(renderer.domElement, event.clientX, event.clientY );
|
|
this.contextMenu.show("world", event.layerX, event.layerY, this);
|
|
}
|
|
};
|
|
|
|
this.show_world_context_menu = function (posX, posY) {
|
|
let menu = this.editorUi.querySelector("#context-menu");
|
|
menu.style.display = "inherit";
|
|
menu.style.left = posX + "px";
|
|
menu.style.top = posY + "px";
|
|
this.editorUi.querySelector("#context-menu-wrapper").style.display =
|
|
"block";
|
|
};
|
|
|
|
this.hide_world_context_menu = function () {
|
|
let menu = this.editorUi.querySelector("#context-menu");
|
|
menu.style.display = "none";
|
|
};
|
|
|
|
this.show_object_context_menu = function (posX, posY) {
|
|
let menu = this.editorUi.querySelector("#object-context-menu");
|
|
menu.style.display = "inherit";
|
|
menu.style.left = posX + "px";
|
|
menu.style.top = posY + "px";
|
|
this.editorUi.querySelector("#context-menu-wrapper").style.display =
|
|
"block";
|
|
};
|
|
|
|
this.hide_object_context_menu = function () {
|
|
let menu = this.editorUi.querySelector("#object-context-menu");
|
|
menu.style.display = "none";
|
|
};
|
|
|
|
this.on_img_click = function (lidar_point_indices) {
|
|
console.log(lidar_point_indices);
|
|
|
|
var self = this;
|
|
let obj_type = "Car";
|
|
this.data.world.lidar.set_spec_points_color(lidar_point_indices, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1,
|
|
});
|
|
this.data.world.lidar.update_points_color();
|
|
this.render();
|
|
//return;
|
|
|
|
let pos = this.data.world.lidar.get_centroid(lidar_point_indices);
|
|
pos.z = 0;
|
|
|
|
let rotation = {
|
|
x: 0,
|
|
y: 0,
|
|
z: this.viewManager.mainView.camera.rotation.z + Math.PI / 2,
|
|
};
|
|
|
|
let obj_cfg = globalObjectCategory.get_obj_cfg_by_type(obj_type);
|
|
let scale = {
|
|
x: obj_cfg.size[0],
|
|
y: obj_cfg.size[1],
|
|
z: obj_cfg.size[2],
|
|
};
|
|
|
|
let box = this.add_box(pos, scale, rotation, obj_type, "");
|
|
self.boxOp.auto_rotate_xyz(box, null, null, function (b) {
|
|
self.on_box_changed(b);
|
|
});
|
|
|
|
return;
|
|
/*
|
|
var box = this.data.world.lidar.create_box_by_points(lidar_point_indices, this.viewManager.mainView.camera);
|
|
|
|
|
|
this.scene.add(box);
|
|
|
|
this.imageContextManager.boxes_manager.add_box(box);
|
|
|
|
|
|
this.boxOp.auto_shrink_box(box);
|
|
|
|
|
|
// guess obj type here
|
|
|
|
box.obj_type = guess_obj_type_by_dimension(box.scale);
|
|
|
|
this.floatLabelManager.add_label(box);
|
|
|
|
this.selectBox(box);
|
|
this.on_box_changed(box);
|
|
|
|
|
|
this.boxOp.auto_rotate_xyz(box, function(){
|
|
box.obj_type = guess_obj_type_by_dimension(box.scale);
|
|
self.floatLabelManager.set_object_type(box.obj_local_id, box.obj_type);
|
|
self.floatLabelManager.update_label_editor(box.obj_type, box.obj_track_id);
|
|
self.on_box_changed(box);
|
|
});
|
|
*/
|
|
};
|
|
|
|
this.handleSelectRect = function (x, y, w, h, ctrl, shift) {
|
|
// y = y+h;
|
|
// x = x*2-1;
|
|
// y = -y*2+1;
|
|
// w *= 2;
|
|
// h *= 2;
|
|
|
|
// x,y: start cornor, w: width, h: height
|
|
|
|
/*
|
|
console.log("main select rect", x,y,w,h);
|
|
|
|
this.viewManager.mainView.camera.updateProjectionMatrix();
|
|
this.data.world.select_points_by_view_rect(x,y,w,h, this.viewManager.mainView.camera);
|
|
render();
|
|
render_2d_image();
|
|
*/
|
|
|
|
// check if any box is inside the rectangle
|
|
|
|
this.viewManager.mainView.camera.updateProjectionMatrix();
|
|
|
|
let boxes = this.data.world.annotation.find_boxes_inside_rect(
|
|
x,
|
|
y,
|
|
w,
|
|
h,
|
|
this.viewManager.mainView.camera
|
|
);
|
|
if (boxes.length > 0) {
|
|
if (boxes.length == 1) {
|
|
this.selectBox(boxes[0]);
|
|
} else {
|
|
// this is dangerous
|
|
// for (let b in boxes){
|
|
// this.remove_box(boxes[b],false)
|
|
// }
|
|
// this.render();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
let points = this.data.world.lidar.select_points_by_view_rect(
|
|
x,
|
|
y,
|
|
w,
|
|
h,
|
|
this.viewManager.mainView.camera
|
|
);
|
|
|
|
// show color
|
|
//this.render();
|
|
|
|
// return;
|
|
// // create new box
|
|
// var self=this;
|
|
var center_pos = this.mouse.get_screen_location_in_world(
|
|
x + w / 2,
|
|
y + h / 2
|
|
);
|
|
center_pos = this.data.world.scenePosToLidar(center_pos);
|
|
|
|
let initRoationZ =
|
|
this.viewManager.mainView.camera.rotation.z + Math.PI / 2;
|
|
|
|
let box = this.create_box_by_points(points, initRoationZ);
|
|
|
|
let id = objIdManager.generateNewUniqueId();
|
|
box.obj_track_id = id;
|
|
|
|
//this.scene.add(box);
|
|
|
|
if (!shift) {
|
|
try {
|
|
this.boxOp.auto_shrink_box(box);
|
|
} catch (e) {
|
|
logger.log(e);
|
|
}
|
|
}
|
|
|
|
// guess obj type here
|
|
|
|
box.obj_type = globalObjectCategory.guess_obj_type_by_dimension(box.scale);
|
|
|
|
objIdManager.addObject({
|
|
category: box.obj_type,
|
|
id: box.obj_track_id,
|
|
});
|
|
|
|
this.imageContextManager.boxes_manager.add_box(box);
|
|
this.floatLabelManager.add_label(box);
|
|
|
|
this.selectBox(box);
|
|
this.on_box_changed(box);
|
|
|
|
if (!shift) {
|
|
this.boxOp.auto_rotate_xyz(box, () => {
|
|
box.obj_type = globalObjectCategory.guess_obj_type_by_dimension(
|
|
box.scale
|
|
);
|
|
this.floatLabelManager.set_object_type(box.obj_local_id, box.obj_type);
|
|
this.fastToolBox.setValue(box.obj_type, box.obj_track_id, box.obj_attr);
|
|
this.on_box_changed(box);
|
|
});
|
|
}
|
|
|
|
//floatLabelManager.add_label(box);
|
|
};
|
|
|
|
this.create_box_by_points = function (points, rotationZ) {
|
|
let localRot = this.data.world.sceneRotToLidar(
|
|
new THREE.Euler(0, 0, rotationZ, "XYZ")
|
|
);
|
|
|
|
let transToBoxMatrix = new THREE.Matrix4()
|
|
.makeRotationFromEuler(localRot)
|
|
.setPosition(0, 0, 0)
|
|
.invert();
|
|
|
|
// var trans = transpose(euler_angle_to_rotate_matrix({x:0,y:0,z:rotation_z}, {x:0, y:0, z:0}), 4);
|
|
|
|
let relative_position = [];
|
|
let v = new THREE.Vector3();
|
|
points.forEach(function (p) {
|
|
v.set(p[0], p[1], p[2]);
|
|
let boxP = v.applyMatrix4(transToBoxMatrix);
|
|
relative_position.push([boxP.x, boxP.y, boxP.z]);
|
|
});
|
|
|
|
var relative_extreme = vector_range(relative_position);
|
|
var scale = {
|
|
x: relative_extreme.max[0] - relative_extreme.min[0],
|
|
y: relative_extreme.max[1] - relative_extreme.min[1],
|
|
z: relative_extreme.max[2] - relative_extreme.min[2],
|
|
};
|
|
|
|
// enlarge scale a little
|
|
|
|
let center = this.boxOp.translateBoxInBoxCoord(localRot, {
|
|
x: (relative_extreme.max[0] + relative_extreme.min[0]) / 2,
|
|
y: (relative_extreme.max[1] + relative_extreme.min[1]) / 2,
|
|
z: (relative_extreme.max[2] + relative_extreme.min[2]) / 2,
|
|
});
|
|
|
|
return this.data.world.annotation.add_box(
|
|
center,
|
|
scale,
|
|
localRot,
|
|
"Unknown",
|
|
""
|
|
);
|
|
};
|
|
|
|
this.handleLeftClick = function (event) {
|
|
if (event.ctrlKey) {
|
|
//Ctrl+left click to smart paste!
|
|
//smart_paste();
|
|
} else {
|
|
//select box /unselect box
|
|
if (
|
|
!this.data.world ||
|
|
(!this.data.world.annotation.boxes &&
|
|
this.data.world.radars.radarList.length == 0 &&
|
|
!this.calib.calib_box)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
let all_boxes = this.data.world.annotation.boxes.concat(
|
|
this.data.world.radars.getAllBoxes()
|
|
);
|
|
all_boxes = all_boxes.concat(this.data.world.aux_lidars.getAllBoxes());
|
|
|
|
if (this.calib.calib_box) {
|
|
all_boxes.push(this.calib.calib_box);
|
|
}
|
|
|
|
let intersects = this.mouse.getIntersects(
|
|
this.mouse.onUpPosition,
|
|
all_boxes
|
|
);
|
|
|
|
if (intersects.length == 0) {
|
|
if (this.data.world.radar_box) {
|
|
intersects = this.mouse.getIntersects(this.mouse.onUpPosition, [
|
|
this.data.world.radar_box,
|
|
]);
|
|
}
|
|
}
|
|
|
|
if (intersects.length > 0) {
|
|
//var object = intersects[ 0 ].object;
|
|
var object = intersects[0].object;
|
|
if (object.userData.object !== undefined) {
|
|
// helper
|
|
this.selectBox(object.userData.object);
|
|
} else {
|
|
this.selectBox(object);
|
|
}
|
|
} else {
|
|
this.unselectBox(null);
|
|
}
|
|
|
|
//render();
|
|
}
|
|
};
|
|
|
|
this.select_locked_object = function () {
|
|
var self = this;
|
|
if (this.view_state.lock_obj_track_id != "") {
|
|
var box = this.data.world.annotation.boxes.find(function (x) {
|
|
return x.obj_track_id == self.view_state.lock_obj_track_id;
|
|
});
|
|
|
|
if (box) {
|
|
this.selectBox(box);
|
|
|
|
if (self.view_state.lock_obj_in_highlight) {
|
|
this.focusOnSelectedBox(box);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// new_object
|
|
this.unselectBox = function (new_object, keep_lock) {
|
|
if (new_object == null) {
|
|
if (
|
|
this.viewManager.mainView &&
|
|
this.viewManager.mainView.transform_control.visible
|
|
) {
|
|
//unselect first time
|
|
this.viewManager.mainView.transform_control.detach();
|
|
} else {
|
|
//unselect second time
|
|
if (this.selected_box) {
|
|
// restore from highlight
|
|
if (this.selected_box.in_highlight) {
|
|
this.cancelFocus(this.selected_box);
|
|
|
|
if (!keep_lock) {
|
|
this.view_state.lock_obj_in_highlight = false;
|
|
}
|
|
} else {
|
|
// unselected finally
|
|
//this.selected_box.material.color = new THREE.Color(parseInt("0x"+get_obj_cfg_by_type(this.selected_box.obj_type).color.slice(1)));
|
|
//this.selected_box.material.opacity = this.data.cfg.box_opacity;
|
|
this.boxOp.unhighlightBox(this.selected_box);
|
|
//this.floatLabelManager.unselect_box(this.selected_box.obj_local_id, this.selected_box.obj_type);
|
|
this.fastToolBox.hide();
|
|
|
|
if (!keep_lock) {
|
|
this.view_state.lock_obj_track_id = "";
|
|
}
|
|
|
|
this.imageContextManager.boxes_manager.onBoxUnselected(
|
|
this.selected_box.obj_local_id,
|
|
this.selected_box.obj_type
|
|
);
|
|
this.selected_box = null;
|
|
this.boxEditor.detach();
|
|
|
|
this.onSelectedBoxChanged(null);
|
|
}
|
|
} else {
|
|
// just an empty click
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
// selected other box
|
|
//unselect all
|
|
this.viewManager.mainView.transform_control.detach();
|
|
|
|
if (this.selected_box) {
|
|
// restore from highlight
|
|
|
|
if (this.selected_box.in_highlight) {
|
|
this.cancelFocus(this.selected_box);
|
|
if (!keep_lock) {
|
|
this.view_state.lock_obj_in_highlight = false;
|
|
}
|
|
}
|
|
|
|
this.selected_box.material.color = new THREE.Color(
|
|
parseInt(
|
|
"0x" +
|
|
globalObjectCategory
|
|
.get_obj_cfg_by_type(this.selected_box.obj_type)
|
|
.color.slice(1)
|
|
)
|
|
);
|
|
this.selected_box.material.opacity = this.data.cfg.box_opacity;
|
|
//this.floatLabelManager.unselect_box(this.selected_box.obj_local_id);
|
|
this.fastToolBox.hide();
|
|
this.imageContextManager.boxes_manager.onBoxUnselected(
|
|
this.selected_box.obj_local_id,
|
|
this.selected_box.obj_type
|
|
);
|
|
|
|
this.selected_box = null;
|
|
this.boxEditor.detach();
|
|
if (!keep_lock) this.view_state.lock_obj_track_id = "";
|
|
}
|
|
}
|
|
|
|
this.render();
|
|
};
|
|
|
|
this.selectBox = function (object) {
|
|
if (this.selected_box != object) {
|
|
// unselect old bbox
|
|
|
|
var in_highlight = false;
|
|
|
|
if (this.selected_box) {
|
|
in_highlight = this.selected_box.in_highlight;
|
|
this.unselectBox(this.selected_box);
|
|
}
|
|
|
|
// select me, the first time
|
|
this.selected_box = object;
|
|
|
|
// switch camera
|
|
if (!this.editorCfg.disableMainImageContext) {
|
|
var best_camera = this.imageContextManager.choose_best_camera_for_point(
|
|
this.selected_box.world.frameInfo.sceneMeta,
|
|
this.selected_box.position
|
|
);
|
|
|
|
if (best_camera) {
|
|
//var image_changed = this.data.set_active_image(best_camera);
|
|
|
|
// if (image_changed){
|
|
// this.editorUi.querySelector("#camera-selector").value=best_camera;
|
|
// this.imageContextManager.boxes_manager.display_image();
|
|
// }
|
|
|
|
this.imageContextManager.setBestCamera(best_camera);
|
|
}
|
|
}
|
|
|
|
// highlight box
|
|
// shold change this id if the current selected box changed id.
|
|
this.view_state.lock_obj_track_id = object.obj_track_id;
|
|
|
|
//this.floatLabelManager.select_box(this.selected_box.obj_local_id);
|
|
|
|
this.fastToolBox.setPos(
|
|
this.floatLabelManager.getLabelEditorPos(this.selected_box.obj_local_id)
|
|
);
|
|
this.fastToolBox.setValue(
|
|
object.obj_type,
|
|
object.obj_track_id,
|
|
object.obj_attr
|
|
);
|
|
this.fastToolBox.show();
|
|
|
|
this.boxOp.highlightBox(this.selected_box);
|
|
|
|
if (in_highlight) {
|
|
this.focusOnSelectedBox(this.selected_box);
|
|
}
|
|
|
|
this.save_box_info(object); // this is needed since when a frame is loaded, all box haven't saved anything.
|
|
// we could move this to when a frame is loaded.
|
|
this.boxEditor.attachBox(object);
|
|
this.onSelectedBoxChanged(object);
|
|
} else {
|
|
//reselect the same box
|
|
if (this.viewManager.mainView.transform_control.visible) {
|
|
this.change_transform_control_view();
|
|
} else {
|
|
//select me the second time
|
|
//object.add(this.viewManager.mainView.transform_control);
|
|
this.viewManager.mainView.transform_control.attach(object);
|
|
}
|
|
}
|
|
|
|
this.render();
|
|
};
|
|
|
|
this.adjustContainerSize = function () {
|
|
let editorRect = this.editorUi.getBoundingClientRect();
|
|
let headerRect = this.editorUi
|
|
.querySelector("#header")
|
|
.getBoundingClientRect();
|
|
|
|
this.container.style.height = editorRect.height - headerRect.height + "px";
|
|
};
|
|
|
|
this.onWindowResize = function () {
|
|
this.adjustContainerSize();
|
|
this.boxEditorManager.onWindowResize();
|
|
|
|
// use clientwidth and clientheight to resize container
|
|
// but use scrollwidth/height to place other things.
|
|
if (
|
|
this.windowWidth != this.container.clientWidth ||
|
|
this.windowHeight != this.container.clientHeight
|
|
) {
|
|
//update_mainview();
|
|
if (this.viewManager.mainView) this.viewManager.mainView.onWindowResize();
|
|
|
|
if (this.boxEditor) this.boxEditor.update("dontrender");
|
|
|
|
this.windowWidth = this.container.clientWidth;
|
|
this.windowHeight = this.container.clientHeight;
|
|
this.renderer.setSize(this.windowWidth, this.windowHeight);
|
|
|
|
//this.viewManager.updateViewPort();
|
|
|
|
// update sideview svg if there exists selected box
|
|
// the following update is called in updateSubviewRangeByWindowResize
|
|
// if (this.selected_box){
|
|
// this.projectiveViewOps.update_view_handle(this.selected_box);
|
|
// }
|
|
}
|
|
|
|
this.viewManager.render();
|
|
};
|
|
|
|
this.change_transform_control_view = function () {
|
|
if (this.viewManager.mainView.transform_control.mode == "scale") {
|
|
this.viewManager.mainView.transform_control.setMode("translate");
|
|
this.viewManager.mainView.transform_control.showY = true;
|
|
this.viewManager.mainView.transform_control.showX = true;
|
|
this.viewManager.mainView.transform_control.showz = true;
|
|
} else if (
|
|
this.viewManager.mainView.transform_control.mode == "translate"
|
|
) {
|
|
this.viewManager.mainView.transform_control.setMode("rotate");
|
|
this.viewManager.mainView.transform_control.showY = false;
|
|
this.viewManager.mainView.transform_control.showX = false;
|
|
this.viewManager.mainView.transform_control.showz = true;
|
|
} else if (this.viewManager.mainView.transform_control.mode == "rotate") {
|
|
this.viewManager.mainView.transform_control.setMode("scale");
|
|
this.viewManager.mainView.transform_control.showY = true;
|
|
this.viewManager.mainView.transform_control.showX = true;
|
|
this.viewManager.mainView.transform_control.showz = true;
|
|
}
|
|
};
|
|
|
|
this.add_box_on_mouse_pos_by_ref = function () {
|
|
let globalP = this.mouse.get_mouse_location_in_world();
|
|
// trans pos to world local pos
|
|
let pos = this.data.world.scenePosToLidar(globalP);
|
|
|
|
let refbox = this.autoAdjust.marked_object.ann;
|
|
pos.z = refbox.psr.position.z;
|
|
|
|
let id = refbox.obj_id;
|
|
|
|
if (
|
|
this.autoAdjust.marked_object.frame == this.data.world.frameInfo.frame
|
|
) {
|
|
id = "";
|
|
}
|
|
|
|
let box = this.add_box(
|
|
pos,
|
|
refbox.psr.scale,
|
|
refbox.psr.rotation,
|
|
refbox.obj_type,
|
|
id,
|
|
refbox.obj_attr
|
|
);
|
|
|
|
return box;
|
|
};
|
|
|
|
this.add_box_on_mouse_pos = function (obj_type) {
|
|
// todo: move to this.data.world
|
|
let globalP = this.mouse.get_mouse_location_in_world();
|
|
|
|
// trans pos to world local pos
|
|
let pos = this.data.world.scenePosToLidar(globalP);
|
|
|
|
var rotation = new THREE.Euler(
|
|
0,
|
|
0,
|
|
this.viewManager.mainView.camera.rotation.z + Math.PI / 2,
|
|
"XYZ"
|
|
);
|
|
rotation = this.data.world.sceneRotToLidar(rotation);
|
|
|
|
var obj_cfg = globalObjectCategory.get_obj_cfg_by_type(obj_type);
|
|
var scale = {
|
|
x: obj_cfg.size[0],
|
|
y: obj_cfg.size[1],
|
|
z: obj_cfg.size[2],
|
|
};
|
|
|
|
pos.z = -1.8 + scale.z / 2; // -1.8 is height of lidar
|
|
|
|
let id = objIdManager.generateNewUniqueId();
|
|
|
|
objIdManager.addObject({
|
|
category: obj_type,
|
|
id: id,
|
|
});
|
|
|
|
let box = this.add_box(pos, scale, rotation, obj_type, id);
|
|
|
|
return box;
|
|
};
|
|
|
|
this.add_box = function (
|
|
pos,
|
|
scale,
|
|
rotation,
|
|
obj_type,
|
|
obj_track_id,
|
|
obj_attr
|
|
) {
|
|
let box = this.data.world.annotation.add_box(
|
|
pos,
|
|
scale,
|
|
rotation,
|
|
obj_type,
|
|
obj_track_id,
|
|
obj_attr
|
|
);
|
|
|
|
this.floatLabelManager.add_label(box);
|
|
|
|
this.imageContextManager.boxes_manager.add_box(box);
|
|
|
|
this.selectBox(box);
|
|
return box;
|
|
};
|
|
|
|
this.save_box_info = function (box) {
|
|
box.last_info = {
|
|
//obj_type: box.obj_type,
|
|
position: {
|
|
x: box.position.x,
|
|
y: box.position.y,
|
|
z: box.position.z,
|
|
},
|
|
rotation: {
|
|
x: box.rotation.x,
|
|
y: box.rotation.y,
|
|
z: box.rotation.z,
|
|
},
|
|
scale: {
|
|
x: box.scale.x,
|
|
y: box.scale.y,
|
|
z: box.scale.z,
|
|
},
|
|
};
|
|
};
|
|
|
|
// axix, xyz, action: scale, move, direction, up/down
|
|
this.transform_bbox = function (command) {
|
|
if (!this.selected_box) return;
|
|
|
|
switch (command) {
|
|
case "x_move_up":
|
|
this.boxOp.translate_box(this.selected_box, "x", 0.05);
|
|
break;
|
|
case "x_move_down":
|
|
this.boxOp.translate_box(this.selected_box, "x", -0.05);
|
|
break;
|
|
case "x_scale_up":
|
|
this.selected_box.scale.x *= 1.01;
|
|
break;
|
|
case "x_scale_down":
|
|
this.selected_box.scale.x /= 1.01;
|
|
break;
|
|
|
|
case "y_move_up":
|
|
this.boxOp.translate_box(this.selected_box, "y", 0.05);
|
|
break;
|
|
case "y_move_down":
|
|
this.boxOp.translate_box(this.selected_box, "y", -0.05);
|
|
break;
|
|
case "y_scale_up":
|
|
this.selected_box.scale.y *= 1.01;
|
|
break;
|
|
case "y_scale_down":
|
|
this.selected_box.scale.y /= 1.01;
|
|
break;
|
|
|
|
case "z_move_up":
|
|
this.selected_box.position.z += 0.05;
|
|
break;
|
|
case "z_move_down":
|
|
this.selected_box.position.z -= 0.05;
|
|
break;
|
|
case "z_scale_up":
|
|
this.selected_box.scale.z *= 1.01;
|
|
break;
|
|
case "z_scale_down":
|
|
this.selected_box.scale.z /= 1.01;
|
|
break;
|
|
|
|
case "z_rotate_left":
|
|
this.selected_box.rotation.z += 0.01;
|
|
break;
|
|
case "z_rotate_right":
|
|
this.selected_box.rotation.z -= 0.01;
|
|
break;
|
|
|
|
case "z_rotate_reverse":
|
|
if (this.selected_box.rotation.z > 0) {
|
|
this.selected_box.rotation.z -= Math.PI;
|
|
} else {
|
|
this.selected_box.rotation.z += Math.PI;
|
|
}
|
|
break;
|
|
case "reset":
|
|
this.selected_box.rotation.x = 0;
|
|
this.selected_box.rotation.y = 0;
|
|
this.selected_box.rotation.z = 0;
|
|
this.selected_box.position.z = 0;
|
|
break;
|
|
}
|
|
|
|
this.on_box_changed(this.selected_box);
|
|
};
|
|
|
|
// function switch_bbox_type(target_type){
|
|
// if (!this.selected_box)
|
|
// return;
|
|
|
|
// if (!target_type){
|
|
// target_type = get_next_obj_type_name(this.selected_box.obj_type);
|
|
// }
|
|
|
|
// this.selected_box.obj_type = target_type;
|
|
// var obj_cfg = get_obj_cfg_by_type(target_type);
|
|
// this.selected_box.scale.x=obj_cfg.size[0];
|
|
// this.selected_box.scale.y=obj_cfg.size[1];
|
|
// this.selected_box.scale.z=obj_cfg.size[2];
|
|
|
|
// this.floatLabelManager.set_object_type(this.selected_box.obj_local_id, this.selected_box.obj_type);
|
|
// this.floatLabelManager.update_label_editor(this.selected_box.obj_type, this.selected_box.obj_track_id);
|
|
|
|
// }
|
|
|
|
this.keydown = function (ev) {
|
|
// if (this.keydownDisabled)
|
|
// return;
|
|
|
|
this.operation_state.key_pressed = true;
|
|
|
|
switch (ev.key) {
|
|
case "+":
|
|
case "=":
|
|
this.data.scale_point_size(1.2);
|
|
this.render();
|
|
break;
|
|
case "-":
|
|
this.data.scale_point_size(0.8);
|
|
this.render();
|
|
break;
|
|
case "1":
|
|
this.select_previous_object();
|
|
break;
|
|
case "2":
|
|
this.select_next_object();
|
|
break;
|
|
case "3":
|
|
case "PageUp":
|
|
this.previous_frame();
|
|
break;
|
|
case "PageDown":
|
|
case "4":
|
|
this.next_frame();
|
|
break;
|
|
case "p":
|
|
this.downloadWebglScreenShot();
|
|
break;
|
|
|
|
// case 'v':
|
|
// this.change_transform_control_view();
|
|
// break;
|
|
/*
|
|
case 'm':
|
|
case 'M':
|
|
smart_paste();
|
|
break;
|
|
case 'N':
|
|
case 'n':
|
|
//add_bbox();
|
|
//header.mark_changed_flag();
|
|
break;
|
|
case 'B':
|
|
case 'b':
|
|
switch_bbox_type();
|
|
self.header.mark_changed_flag();
|
|
self.on_box_changed(this.selected_box);
|
|
break;
|
|
*/
|
|
case "z": // X
|
|
this.viewManager.mainView.transform_control.showX =
|
|
!this.viewManager.mainView.transform_control.showX;
|
|
break;
|
|
case "x": // Y
|
|
this.viewManager.mainView.transform_control.showY =
|
|
!this.viewManager.mainView.transform_control.showY;
|
|
break;
|
|
case "c": // Z
|
|
if (ev.ctrlKey) {
|
|
this.mark_bbox(this.selected_box);
|
|
} else {
|
|
this.viewManager.mainView.transform_control.showZ =
|
|
!this.viewManager.mainView.transform_control.showZ;
|
|
}
|
|
break;
|
|
case " ": // Spacebar
|
|
//this.viewManager.mainView.transform_control.enabled = ! this.viewManager.mainView.transform_control.enabled;
|
|
this.playControl.pause_resume_play();
|
|
break;
|
|
|
|
case "5":
|
|
case "6":
|
|
case "7":
|
|
this.boxEditor.boxView.views[ev.key - 5].cameraHelper.visible =
|
|
!this.boxEditor.boxView.views[ev.key - 5].cameraHelper.visible;
|
|
this.render();
|
|
break;
|
|
|
|
case "s":
|
|
if (ev.ctrlKey) {
|
|
saveWorldList(this.data.worldList);
|
|
} else if (this.selected_box) {
|
|
let v = Math.max(
|
|
this.editorCfg.moveStep * this.selected_box.scale.x,
|
|
0.02
|
|
);
|
|
this.boxOp.translate_box(this.selected_box, "x", -v);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
case "w":
|
|
if (this.selected_box) {
|
|
let v = Math.max(
|
|
this.editorCfg.moveStep * this.selected_box.scale.x,
|
|
0.02
|
|
);
|
|
this.boxOp.translate_box(this.selected_box, "x", v);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
case "a":
|
|
if (this.selected_box) {
|
|
let v = Math.max(
|
|
this.editorCfg.moveStep * this.selected_box.scale.y,
|
|
0.02
|
|
);
|
|
this.boxOp.translate_box(this.selected_box, "y", v);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
case "d":
|
|
if (this.selected_box) {
|
|
let v = Math.max(
|
|
this.editorCfg.moveStep * this.selected_box.scale.y,
|
|
0.02
|
|
);
|
|
this.boxOp.translate_box(this.selected_box, "y", -v);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
|
|
case "q":
|
|
if (this.selected_box) {
|
|
this.boxOp.rotate_z(
|
|
this.selected_box,
|
|
this.editorCfg.rotateStep,
|
|
false
|
|
);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
case "e":
|
|
if (this.selected_box) {
|
|
this.boxOp.rotate_z(
|
|
this.selected_box,
|
|
-this.editorCfg.rotateStep,
|
|
false
|
|
);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
case "r":
|
|
if (this.selected_box) {
|
|
//this.transform_bbox("z_rotate_left");
|
|
this.boxOp.rotate_z(
|
|
this.selected_box,
|
|
this.editorCfg.rotateStep,
|
|
true
|
|
);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
|
|
case "f":
|
|
if (this.selected_box) {
|
|
//this.transform_bbox("z_rotate_right");
|
|
this.boxOp.rotate_z(
|
|
this.selected_box,
|
|
-this.editorCfg.rotateStep,
|
|
true
|
|
);
|
|
this.on_box_changed(this.selected_box);
|
|
}
|
|
break;
|
|
case "g":
|
|
this.transform_bbox("z_rotate_reverse");
|
|
break;
|
|
case "t":
|
|
//this.transform_bbox("reset");
|
|
this.showTrajectory();
|
|
break;
|
|
case "v":
|
|
this.enterBatchEditMode();
|
|
break;
|
|
case "d":
|
|
case "D":
|
|
if (ev.ctrlKey) {
|
|
this.remove_selected_box();
|
|
this.header.updateModifiedStatus();
|
|
}
|
|
break;
|
|
case "Delete":
|
|
this.remove_selected_box();
|
|
this.header.updateModifiedStatus();
|
|
break;
|
|
case "Escape":
|
|
if (this.selected_box) {
|
|
this.unselectBox(null);
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
this.previous_frame = function () {
|
|
if (!this.data.meta) return;
|
|
|
|
var scene_meta = this.data.get_current_world_scene_meta();
|
|
|
|
var frame_index = this.data.world.frameInfo.frame_index - 1;
|
|
|
|
if (frame_index < 0) {
|
|
console.log("first frame");
|
|
this.infoBox.show("信息:", "当前已是第一帧");
|
|
return;
|
|
}
|
|
|
|
this.load_world(scene_meta.scene, scene_meta.frames[frame_index]);
|
|
};
|
|
|
|
this.last_frame = function () {
|
|
let scene_meta = this.data.get_current_world_scene_meta();
|
|
this.load_world(
|
|
scene_meta.scene,
|
|
scene_meta.frames[scene_meta.frames.length - 1]
|
|
);
|
|
};
|
|
this.first_frame = function () {
|
|
let scene_meta = this.data.get_current_world_scene_meta();
|
|
this.load_world(scene_meta.scene, scene_meta.frames[0]);
|
|
};
|
|
|
|
this.next_frame = function () {
|
|
if (!this.data.meta) return;
|
|
|
|
var scene_meta = this.data.get_current_world_scene_meta();
|
|
|
|
var num_frames = scene_meta.frames.length;
|
|
|
|
var frame_index = this.data.world.frameInfo.frame_index + 1;
|
|
|
|
if (frame_index >= num_frames) {
|
|
console.log("last frame");
|
|
this.infoBox.show("信息:", "当前已是最后一帧");
|
|
return;
|
|
}
|
|
|
|
this.load_world(scene_meta.scene, scene_meta.frames[frame_index]);
|
|
};
|
|
|
|
this.select_next_object = function () {
|
|
var self = this;
|
|
if (this.data.world.annotation.boxes.length <= 0) return;
|
|
|
|
if (this.selected_box) {
|
|
this.operation_state.box_navigate_index =
|
|
this.data.world.annotation.boxes.findIndex(function (x) {
|
|
return self.selected_box == x;
|
|
});
|
|
}
|
|
|
|
this.operation_state.box_navigate_index += 1;
|
|
this.operation_state.box_navigate_index %=
|
|
this.data.world.annotation.boxes.length;
|
|
|
|
this.selectBox(
|
|
this.data.world.annotation.boxes[this.operation_state.box_navigate_index]
|
|
);
|
|
};
|
|
|
|
this.select_previous_object = function () {
|
|
var self = this;
|
|
if (this.data.world.annotation.boxes.length <= 0) return;
|
|
|
|
if (this.selected_box) {
|
|
this.operation_state.box_navigate_index =
|
|
this.data.world.annotation.boxes.findIndex(function (x) {
|
|
return self.selected_box == x;
|
|
});
|
|
}
|
|
|
|
this.operation_state.box_navigate_index +=
|
|
this.data.world.annotation.boxes.length - 1;
|
|
this.operation_state.box_navigate_index %=
|
|
this.data.world.annotation.boxes.length;
|
|
|
|
this.selectBox(
|
|
this.data.world.annotation.boxes[this.operation_state.box_navigate_index]
|
|
);
|
|
};
|
|
|
|
// this.centerMainView =function(){
|
|
// let offset = this.data.world.coordinatesOffset;
|
|
// this.viewManager.mainView.orbit.target.x += offset[0];
|
|
// this.viewManager.mainView.orbit.target.y += offset[1];
|
|
// this.viewManager.mainView.orbit.target.z += offset[2];
|
|
// };
|
|
|
|
this.on_load_world_finished = function (world) {
|
|
document.title = "SUSTech POINTS-" + world.frameInfo.scene;
|
|
// switch view positoin
|
|
this.moveAxisHelper(world);
|
|
this.moveRangeCircle(world);
|
|
this.lookAtWorld(world);
|
|
this.unselectBox(null, true);
|
|
this.unselectBox(null, true);
|
|
this.render();
|
|
this.imageContextManager.attachWorld(world);
|
|
this.imageContextManager.render_2d_image();
|
|
this.render2dLabels(world);
|
|
this.update_frame_info(world.frameInfo.scene, world.frameInfo.frame);
|
|
|
|
this.select_locked_object();
|
|
|
|
//load_obj_ids_of_scene(world.frameInfo.scene);
|
|
objIdManager.setCurrentScene(world.frameInfo.scene);
|
|
|
|
// preload after the first world loaded
|
|
// otherwise the loading of the first world would be too slow
|
|
this.data.preloadScene(world.frameInfo.scene, world);
|
|
};
|
|
this.moveAxisHelper = function (world) {
|
|
world.webglGroup.add(this.axis);
|
|
};
|
|
|
|
this.mainViewOffset = [0, 0, 0];
|
|
|
|
this.lookAtWorld = function (world) {
|
|
let newOffset = [
|
|
world.coordinatesOffset[0] - this.mainViewOffset[0],
|
|
world.coordinatesOffset[1] - this.mainViewOffset[1],
|
|
world.coordinatesOffset[2] - this.mainViewOffset[2],
|
|
];
|
|
|
|
this.mainViewOffset = world.coordinatesOffset;
|
|
|
|
this.viewManager.mainView.orbit.target.x += newOffset[0];
|
|
this.viewManager.mainView.orbit.target.y += newOffset[1];
|
|
this.viewManager.mainView.orbit.target.z += newOffset[2];
|
|
|
|
this.viewManager.mainView.camera.position.x += newOffset[0];
|
|
this.viewManager.mainView.camera.position.y += newOffset[1];
|
|
this.viewManager.mainView.camera.position.z += newOffset[2];
|
|
|
|
this.viewManager.mainView.orbit.update();
|
|
};
|
|
|
|
this.load_world = async function (sceneName, frame, onFinished) {
|
|
this.data.dbg.dump();
|
|
|
|
logger.log(`load ${sceneName}, ${frame}`);
|
|
|
|
var self = this;
|
|
//stop if current world is not ready!
|
|
if (this.data.world && !this.data.world.preloaded()) {
|
|
console.error("current world is still loading.");
|
|
return;
|
|
}
|
|
|
|
if (this.selected_box && this.selected_box.in_highlight) {
|
|
this.cancelFocus(this.selected_box);
|
|
}
|
|
|
|
if (
|
|
this.viewManager.mainView &&
|
|
this.viewManager.mainView.transform_control.visible
|
|
) {
|
|
//unselect first time
|
|
this.viewManager.mainView.transform_control.detach();
|
|
}
|
|
|
|
var world = await this.data.getWorld(sceneName, frame);
|
|
|
|
if (world) {
|
|
this.data.activate_world(world, function () {
|
|
self.on_load_world_finished(world);
|
|
if (onFinished) onFinished();
|
|
});
|
|
}
|
|
};
|
|
|
|
this.remove_box = function (box, render = true) {
|
|
if (box === this.selected_box) {
|
|
this.unselectBox(null, true);
|
|
this.unselectBox(null, true); //twice to safely unselect.
|
|
this.selected_box = null;
|
|
//this.remove_selected_box();
|
|
}
|
|
|
|
this.do_remove_box(box, false); // render later.
|
|
|
|
// this should be after do-remove-box
|
|
// subview renderings don't need to be done again after
|
|
// the box is removed.
|
|
if (box.boxEditor) {
|
|
if (box.boxEditor) {
|
|
box.boxEditor.detach("donthide");
|
|
} else {
|
|
console.error("what?");
|
|
}
|
|
}
|
|
|
|
this.header.updateModifiedStatus();
|
|
|
|
if (render) this.render();
|
|
};
|
|
|
|
this.remove_selected_box = function () {
|
|
this.remove_box(this.selected_box);
|
|
};
|
|
|
|
(this.do_remove_box = function (box, render = true) {
|
|
if (!box.annotator) this.restore_box_points_color(box, render);
|
|
|
|
this.imageContextManager.boxes_manager.remove_box(box.obj_local_id);
|
|
|
|
this.floatLabelManager.remove_box(box);
|
|
this.fastToolBox.hide();
|
|
|
|
//this.selected_box.dispose();
|
|
|
|
box.world.annotation.unload_box(box);
|
|
box.world.annotation.remove_box(box);
|
|
|
|
box.world.annotation.setModified();
|
|
}),
|
|
(this.clear = function () {
|
|
this.header.clear_box_info();
|
|
//this.editorUi.querySelector("#image").innerHTML = '';
|
|
|
|
this.unselectBox(null);
|
|
this.unselectBox(null);
|
|
|
|
this.header.clear_frame_info();
|
|
|
|
this.imageContextManager.clear_main_canvas();
|
|
this.boxEditor.detach();
|
|
|
|
this.data.world.unload();
|
|
this.data.world = null; //dump it
|
|
this.floatLabelManager.remove_all_labels();
|
|
this.fastToolBox.hide();
|
|
this.render();
|
|
});
|
|
|
|
this.update_frame_info = function (scene, frame) {
|
|
var self = this;
|
|
this.header.set_frame_info(scene, frame, function (sceneName) {
|
|
self.scene_changed(sceneName);
|
|
});
|
|
};
|
|
|
|
//box edited
|
|
this.on_box_changed = function (box) {
|
|
if (!this.imageContextManager.hidden())
|
|
this.imageContextManager.boxes_manager.update_box(box);
|
|
|
|
this.header.update_box_info(box);
|
|
//floatLabelManager.update_position(box, false); don't update position, or the ui is annoying.
|
|
|
|
box.world.annotation.setModified();
|
|
|
|
this.updateBoxPointsColor(box);
|
|
this.save_box_info(box);
|
|
|
|
if (box.boxEditor) {
|
|
box.boxEditor.onBoxChanged();
|
|
} else {
|
|
console.error("what?");
|
|
}
|
|
|
|
this.autoAdjust.syncFollowers(box);
|
|
|
|
// if (box === this.data.world.radar_box){
|
|
// this.data.world.move_radar(box);
|
|
// }
|
|
|
|
if (box.on_box_changed) {
|
|
box.on_box_changed();
|
|
}
|
|
|
|
this.header.updateModifiedStatus();
|
|
this.render();
|
|
};
|
|
|
|
// box removed, restore points color.
|
|
this.restore_box_points_color = function (box, render = true) {
|
|
if (this.data.cfg.color_obj != "no") {
|
|
box.world.lidar.reset_box_points_color(box);
|
|
box.world.lidar.update_points_color();
|
|
if (render) this.render();
|
|
}
|
|
};
|
|
|
|
this.updateBoxPointsColor = function (box) {
|
|
if (this.data.cfg.color_obj != "no") {
|
|
if (box.last_info) {
|
|
box.world.lidar.set_box_points_color(box.last_info, {
|
|
x: this.data.cfg.point_brightness,
|
|
y: this.data.cfg.point_brightness,
|
|
z: this.data.cfg.point_brightness,
|
|
});
|
|
}
|
|
|
|
box.world.lidar.set_box_points_color(box);
|
|
box.world.lidar.update_points_color();
|
|
}
|
|
};
|
|
|
|
this.onSelectedBoxChanged = function (box) {
|
|
if (box) {
|
|
this.header.update_box_info(box);
|
|
// this.floatLabelManager.update_position(box, true);
|
|
// this.fastToolBox.setPos(this.floatLabelManager.getLabelEditorPos(box.obj_local_id));
|
|
this.imageContextManager.boxes_manager.onBoxSelected(
|
|
box.obj_local_id,
|
|
box.obj_type
|
|
);
|
|
|
|
//this.boxEditor.attachBox(box);
|
|
|
|
this.render();
|
|
//this.boxEditor.boxView.render();
|
|
|
|
//this.updateSubviewRangeByWindowResize(box);
|
|
} else {
|
|
this.header.clear_box_info();
|
|
}
|
|
};
|
|
|
|
this.render2dLabels = function (world) {
|
|
if (this.editorCfg.disableMainView) return;
|
|
|
|
this.floatLabelManager.remove_all_labels();
|
|
var self = this;
|
|
world.annotation.boxes.forEach(function (b) {
|
|
self.floatLabelManager.add_label(b);
|
|
});
|
|
|
|
if (this.selected_box) {
|
|
//this.floatLabelManager.select_box(this.selected_box.obj_local_id)
|
|
this.fastToolBox.show();
|
|
this.fastToolBox.setValue(
|
|
this.selected_box.obj_type,
|
|
this.selected_box.obj_track_id,
|
|
this.selected_box.obj_attr
|
|
);
|
|
}
|
|
};
|
|
|
|
this.add_global_obj_type = function () {
|
|
var self = this;
|
|
var sheet = window.document.styleSheets[1];
|
|
|
|
let obj_type_map = globalObjectCategory.obj_type_map;
|
|
|
|
for (var o in obj_type_map) {
|
|
var rule =
|
|
"." +
|
|
o +
|
|
"{color:" +
|
|
obj_type_map[o].color +
|
|
";" +
|
|
"stroke:" +
|
|
obj_type_map[o].color +
|
|
";" +
|
|
"fill:" +
|
|
obj_type_map[o].color +
|
|
"22" +
|
|
";" +
|
|
"}";
|
|
sheet.insertRule(rule, sheet.cssRules.length);
|
|
}
|
|
|
|
function color_str(v) {
|
|
let c = Math.round(v * 255);
|
|
if (c < 16) return "0" + c.toString(16);
|
|
else return c.toString(16);
|
|
}
|
|
|
|
for (let idx = 0; idx <= 32; idx++) {
|
|
let c = globalObjectCategory.get_color_by_id(idx);
|
|
let color = "#" + color_str(c.x) + color_str(c.y) + color_str(c.z);
|
|
|
|
var rule =
|
|
".color-" +
|
|
idx +
|
|
"{color:" +
|
|
color +
|
|
";" +
|
|
"stroke:" +
|
|
color +
|
|
";" +
|
|
"fill:" +
|
|
color +
|
|
"22" +
|
|
";" +
|
|
"}";
|
|
sheet.insertRule(rule, sheet.cssRules.length);
|
|
}
|
|
|
|
// obj type selector
|
|
var options = "";
|
|
for (var o in obj_type_map) {
|
|
options +=
|
|
'<option value="' + o + '" class="' + o + '">' + categoryZh[o] + "</option>";
|
|
}
|
|
|
|
this.editorUi.querySelector(
|
|
"#floating-things #object-category-selector"
|
|
).innerHTML = options;
|
|
//this.editorUi.querySelector("#batch-editor-tools-wrapper #object-category-selector").innerHTML = options;
|
|
|
|
// submenu of new
|
|
var items = "";
|
|
for (var o in obj_type_map) {
|
|
items +=
|
|
'<div class="menu-item cm-new-item ' +
|
|
o +
|
|
'" id="cm-new-' +
|
|
o +
|
|
'" uservalue="' +
|
|
o +
|
|
'"><div class="menu-item-text">' +
|
|
categoryZh[o] +
|
|
"</div></div>";
|
|
}
|
|
|
|
this.editorUi.querySelector("#new-submenu").innerHTML = items;
|
|
|
|
this.contextMenu.installMenu(
|
|
"newSubMenu",
|
|
this.editorUi.querySelector("#new-submenu"),
|
|
(event) => {
|
|
let obj_type = event.currentTarget.getAttribute("uservalue");
|
|
let box = self.add_box_on_mouse_pos(obj_type);
|
|
//switch_bbox_type(event.currentTarget.getAttribute("uservalue"));
|
|
//self.boxOp.grow_box(box, 0.2, {x:2, y:2, z:3});
|
|
//self.auto_shrink_box(box);
|
|
//self.on_box_changed(box);
|
|
|
|
let noscaling = event.shiftKey;
|
|
|
|
self.boxOp.auto_rotate_xyz(
|
|
box,
|
|
null,
|
|
null,
|
|
function (b) {
|
|
self.on_box_changed(b);
|
|
},
|
|
noscaling
|
|
);
|
|
return true;
|
|
}
|
|
);
|
|
|
|
// // install click actions
|
|
// for (var o in obj_type_map){
|
|
// this.editorUi.querySelector("#cm-new-"+o).onclick = (event)=>{
|
|
|
|
// // hide context men
|
|
// // let context menu object handle this.
|
|
// // this.editorUi.querySelector("#context-menu-wrapper").style.display="none";
|
|
|
|
// // process event
|
|
// var obj_type = event.currentTarget.getAttribute("uservalue");
|
|
// let box = self.add_box_on_mouse_pos(obj_type);
|
|
// //switch_bbox_type(event.currentTarget.getAttribute("uservalue"));
|
|
// //self.boxOp.grow_box(box, 0.2, {x:2, y:2, z:3});
|
|
// //self.auto_shrink_box(box);
|
|
// //self.on_box_changed(box);
|
|
|
|
// self.boxOp.auto_rotate_xyz(box, null, null, function(b){
|
|
// self.on_box_changed(b);
|
|
// });
|
|
|
|
// }
|
|
// }
|
|
};
|
|
|
|
this.interpolate_selected_object = function () {
|
|
let scene = this.data.world.frameInfo.scene;
|
|
let frame = this.data.world.frameInfo.frame;
|
|
let obj_id = this.selected_box.obj_track_id;
|
|
|
|
this.boxOp.interpolate_selected_object(scene, obj_id, frame, (s, fs) => {
|
|
this.onAnnotationUpdatedByOthers(s, fs);
|
|
});
|
|
};
|
|
|
|
this.onAnnotationUpdatedByOthers = function (scene, frames) {
|
|
this.data.onAnnotationUpdatedByOthers(scene, frames);
|
|
};
|
|
|
|
this.init(editorUi);
|
|
}
|
|
|
|
export { Editor };
|