feat:初始一次js文件格式化

main
陈炎群 5 months ago
parent f374f4c12c
commit d4602681c7

File diff suppressed because it is too large Load Diff

@ -1,463 +1,469 @@
import {
import {transpose, matmul2, euler_angle_to_rotate_matrix_3by3,normalizeAngle } from "./util.js"; transpose,
matmul2,
euler_angle_to_rotate_matrix_3by3,
normalizeAngle,
} from "./util.js";
import { logger } from "./log.js"; import { logger } from "./log.js";
// todo: this module needs a proper name // todo: this module needs a proper name
function AutoAdjust(boxOp, mouse, header){ function AutoAdjust(boxOp, mouse, header) {
this.boxOp = boxOp, (this.boxOp = boxOp), (this.mouse = mouse);
this.mouse = mouse; this.header = header;
this.header = header; var marked_object = null;
var marked_object = null;
// mark bbox, which will be used as reference-bbox of an object.
// mark bbox, which will be used as reference-bbox of an object. this.mark_bbox = function (box) {
this.mark_bbox=function(box){ if (box) {
if (box){ this.marked_object = {
this.marked_object = { frame: box.world.frameInfo.frame,
frame: box.world.frameInfo.frame, scene: box.world.frameInfo.scene,
scene: box.world.frameInfo.scene, ann: box.world.annotation.boxToAnn(box),
ann: box.world.annotation.boxToAnn(box), };
}
logger.log(`selected reference objcet ${this.marked_object}`);
logger.log(`selected reference objcet ${this.marked_object}`);
this.header.set_ref_obj(this.marked_object);
this.header.set_ref_obj(this.marked_object); }
};
this.followStaticObjects = function (box) {
let world = box.world;
let staticObjects = world.annotation.boxes
.filter((b) => b != box && b.obj_attr && b.obj_attr.search("static") >= 0)
.map((refObj) => {
let coord = euler_angle_to_rotate_matrix_3by3(refObj.rotation);
let trans = transpose(coord, 3);
let p = [
box.position.x - refObj.position.x,
box.position.y - refObj.position.y,
box.position.z - refObj.position.z,
];
let relativePos = matmul2(trans, p, 3);
let relativeRot = {
x: normalizeAngle(box.rotation.x - refObj.rotation.x),
y: normalizeAngle(box.rotation.y - refObj.rotation.y),
z: normalizeAngle(box.rotation.z - refObj.rotation.z),
};
let distance = Math.sqrt(
relativePos[0] * relativePos[0] +
relativePos[1] * relativePos[1] +
relativePos[2] * relativePos[2]
);
return {
obj_track_id: refObj.obj_track_id,
relativePos,
relativeRot,
distance,
};
});
let worldList = box.world.data.worldList;
//let saveList = [];
worldList.forEach((w) => {
if (w === box.world) {
//current frame
return;
}
let existedBox = w.annotation.boxes.find(
(b) => b.obj_track_id == box.obj_track_id
);
if (existedBox && !existedBox.annotator) {
// have same objects annotated.
// if its generated by machine, lets overwrite it
return;
}
let candPoseSets = staticObjects.map((refObj) => {
let refObjInW = w.annotation.boxes.find(
(b) => b.obj_track_id == refObj.obj_track_id
);
if (!refObjInW) {
// not found refobj in this world, give up
return null;
}
let relativePos = refObj.relativePos;
let relativeRot = refObj.relativeRot;
let coord = euler_angle_to_rotate_matrix_3by3(refObjInW.rotation);
let rp = matmul2(coord, relativePos, 3);
let newObjPos = {
x: refObjInW.position.x + rp[0],
y: refObjInW.position.y + rp[1],
z: refObjInW.position.z + rp[2],
};
let newObjRot = {
x: normalizeAngle(refObjInW.rotation.x + relativeRot.x),
y: normalizeAngle(refObjInW.rotation.y + relativeRot.y),
z: normalizeAngle(refObjInW.rotation.z + relativeRot.z),
};
return {
distance: refObj.distance,
weight: Math.exp(-refObj.distance * (refObjInW.annotator ? 1 : 0.1)),
position: newObjPos,
rotation: newObjRot,
};
});
candPoseSets = candPoseSets.filter((p) => !!p);
if (candPoseSets.length == 0) {
return;
}
// calculate mean pos/rot
let denorm = candPoseSets.reduce((a, b) => a + b.weight, 0);
let newObjPos = { x: 0, y: 0, z: 0 };
let newObjRot = { x: 0, y: 0, z: 0, cosZ: 0, sinZ: 0 };
candPoseSets.forEach((p) => {
newObjPos.x += p.position.x * p.weight;
newObjPos.y += p.position.y * p.weight;
newObjPos.z += p.position.z * p.weight;
newObjRot.x += p.rotation.x * p.weight;
newObjRot.y += p.rotation.y * p.weight;
//newObjRot.z += p.rotation.z * p.weight;
newObjRot.cosZ += Math.cos(p.rotation.z) * p.weight;
newObjRot.sinZ += Math.sin(p.rotation.z) * p.weight;
});
newObjPos.x /= denorm;
newObjPos.y /= denorm;
newObjPos.z /= denorm;
newObjRot.x /= denorm;
newObjRot.y /= denorm;
newObjRot.cosZ /= denorm;
newObjRot.sinZ /= denorm;
newObjRot.z = Math.atan2(newObjRot.sinZ, newObjRot.cosZ);
// ignor distant objects
if (pointsGlobalConfig.ignoreDistantObject) {
let objDistance = Math.sqrt(
newObjPos.x * newObjPos.x +
newObjPos.y * newObjPos.y +
newObjPos.z * newObjPos.z
);
if ((box.scale.z < 2 && objDistance > 100) || objDistance > 150) {
return;
} }
}; }
this.followStaticObjects = function(box) { // apply
let world = box.world; if (existedBox) {
let staticObjects = world.annotation.boxes. existedBox.position.x = newObjPos.x;
filter(b=>b!=box && b.obj_attr && b.obj_attr.search('static')>=0). existedBox.position.y = newObjPos.y;
map(refObj=>{ existedBox.position.z = newObjPos.z;
let coord = euler_angle_to_rotate_matrix_3by3(refObj.rotation);
let trans = transpose(coord, 3); existedBox.rotation.x = newObjRot.x;
let p = [box.position.x - refObj.position.x, existedBox.rotation.y = newObjRot.y;
box.position.y - refObj.position.y, existedBox.rotation.z = newObjRot.z;
box.position.z - refObj.position.z];
let relativePos = matmul2(trans, p, 3); existedBox.scale.x = box.scale.x;
let relativeRot = { existedBox.scale.y = box.scale.y;
x: normalizeAngle(box.rotation.x - refObj.rotation.x), existedBox.scale.z = box.scale.z;
y: normalizeAngle(box.rotation.y - refObj.rotation.y),
z: normalizeAngle(box.rotation.z - refObj.rotation.z), existedBox.annotator = "S";
};
logger.log(`modified box in ${w}`);
} else {
let distance = Math.sqrt(relativePos[0]*relativePos[0] + relativePos[1]*relativePos[1] + relativePos[2]*relativePos[2]); let newBox = w.annotation.add_box(
return { newObjPos,
obj_track_id: refObj.obj_track_id, box.scale,
relativePos, newObjRot,
relativeRot, box.obj_type,
distance box.obj_track_id,
box.obj_attr
} );
}); newBox.annotator = "S";
let worldList = box.world.data.worldList; w.annotation.load_box(newBox);
//let saveList = []; logger.log(`inserted box in ${w}`);
worldList.forEach(w=>{ }
if (w === box.world){
//current frame console.log("added box in ", w.frameInfo.frame);
return; //saveList.push(w);
} w.annotation.setModified();
});
let existedBox = w.annotation.boxes.find(b=>b.obj_track_id == box.obj_track_id); };
if (existedBox && !existedBox.annotator)
{ this.followsRef = function (box) {
// have same objects annotated. //find ref object in current frame
// if its generated by machine, lets overwrite it let world = box.world;
return; let refObj = world.annotation.boxes.find(
} (b) => b.obj_track_id == this.marked_object.ann.obj_id
);
let candPoseSets = staticObjects.map(refObj=>{ if (refObj) {
console.log("found ref obj in current frame");
let refObjInW = w.annotation.boxes.find(b=>b.obj_track_id == refObj.obj_track_id); world.annotation.setModified();
if (!refObjInW){
// not found refobj in this world, give up //compute relative position
return null; // represent obj in coordinate system of refobj
}
let coord = euler_angle_to_rotate_matrix_3by3(refObj.rotation);
let relativePos = refObj.relativePos; let trans = transpose(coord, 3);
let relativeRot = refObj.relativeRot; let p = [
box.position.x - refObj.position.x,
let coord = euler_angle_to_rotate_matrix_3by3(refObjInW.rotation); box.position.y - refObj.position.y,
box.position.z - refObj.position.z,
let rp = matmul2(coord, relativePos, 3); ];
let newObjPos = { const relativePos = matmul2(trans, p, 3);
x: refObjInW.position.x + rp[0], const relativeRot = {
y: refObjInW.position.y + rp[1], x: box.rotation.x - refObj.rotation.x,
z: refObjInW.position.z + rp[2], y: box.rotation.y - refObj.rotation.y,
}; z: box.rotation.z - refObj.rotation.z,
};
let newObjRot = {
x: normalizeAngle(refObjInW.rotation.x + relativeRot.x), let worldList = box.world.data.worldList;
y: normalizeAngle(refObjInW.rotation.y + relativeRot.y), //let saveList = [];
z: normalizeAngle(refObjInW.rotation.z + relativeRot.z) worldList.forEach((w) => {
}; if (w === box.world) {
//current frame
return;
return {
distance: refObj.distance,
weight: Math.exp(-refObj.distance * (refObjInW.annotator?1:0.1)),
position: newObjPos,
rotation: newObjRot,
};
});
candPoseSets = candPoseSets.filter(p=>!!p);
if (candPoseSets.length == 0) {
return;
}
// calculate mean pos/rot
let denorm = candPoseSets.reduce((a,b)=>a+b.weight, 0);
let newObjPos = {x:0, y:0, z:0};
let newObjRot = {x:0, y:0, z:0, cosZ: 0, sinZ:0};
candPoseSets.forEach(p=>{
newObjPos.x += p.position.x * p.weight;
newObjPos.y += p.position.y * p.weight;
newObjPos.z += p.position.z * p.weight;
newObjRot.x += p.rotation.x * p.weight;
newObjRot.y += p.rotation.y * p.weight;
//newObjRot.z += p.rotation.z * p.weight;
newObjRot.cosZ += Math.cos(p.rotation.z) * p.weight;
newObjRot.sinZ += Math.sin(p.rotation.z) * p.weight;
});
newObjPos.x /= denorm;
newObjPos.y /= denorm;
newObjPos.z /= denorm;
newObjRot.x /= denorm;
newObjRot.y /= denorm;
newObjRot.cosZ /= denorm;
newObjRot.sinZ /= denorm;
newObjRot.z = Math.atan2(newObjRot.sinZ, newObjRot.cosZ);
// ignor distant objects
if (pointsGlobalConfig.ignoreDistantObject){
let objDistance = Math.sqrt(newObjPos.x * newObjPos.x + newObjPos.y * newObjPos.y + newObjPos.z * newObjPos.z);
if ((box.scale.z < 2 && objDistance > 100) || objDistance > 150)
{
return;
}
}
// apply
if (existedBox){
existedBox.position.x = newObjPos.x;
existedBox.position.y = newObjPos.y;
existedBox.position.z = newObjPos.z;
existedBox.rotation.x = newObjRot.x;
existedBox.rotation.y = newObjRot.y;
existedBox.rotation.z = newObjRot.z;
existedBox.scale.x = box.scale.x;
existedBox.scale.y = box.scale.y;
existedBox.scale.z = box.scale.z;
existedBox.annotator="S";
logger.log(`modified box in ${w}`);
} else{
let newBox = w.annotation.add_box(newObjPos,
box.scale,
newObjRot,
box.obj_type,
box.obj_track_id,
box.obj_attr);
newBox.annotator="S";
w.annotation.load_box(newBox);
logger.log(`inserted box in ${w}`);
}
console.log("added box in ", w.frameInfo.frame);
//saveList.push(w);
w.annotation.setModified();
});
};
this.followsRef = function(box){
//find ref object in current frame
let world = box.world;
let refObj = world.annotation.boxes.find(b=>b.obj_track_id == this.marked_object.ann.obj_id);
if (refObj){
console.log("found ref obj in current frame");
world.annotation.setModified()
//compute relative position
// represent obj in coordinate system of refobj
let coord = euler_angle_to_rotate_matrix_3by3(refObj.rotation);
let trans = transpose(coord, 3);
let p = [box.position.x - refObj.position.x,
box.position.y - refObj.position.y,
box.position.z - refObj.position.z];
const relativePos = matmul2(trans, p, 3);
const relativeRot = {
x: box.rotation.x - refObj.rotation.x,
y: box.rotation.y - refObj.rotation.y,
z: box.rotation.z - refObj.rotation.z,
};
let worldList = box.world.data.worldList;
//let saveList = [];
worldList.forEach(w=>{
if (w === box.world){
//current frame
return;
}
let existedBox = w.annotation.boxes.find(b=>b.obj_track_id == box.obj_track_id);
if (existedBox && !existedBox.annotator)
{
// have same objects annotated.
// if its generated by machine, lets overwrite it
return;
}
let refObjInW = w.annotation.boxes.find(b=>b.obj_track_id == refObj.obj_track_id);
if (!refObjInW){
// not found refobj in this world, give up
return;
}
let coord = euler_angle_to_rotate_matrix_3by3(refObjInW.rotation);
let rp = matmul2(coord, relativePos, 3);
let newObjPos = {
x: refObjInW.position.x + rp[0],
y: refObjInW.position.y + rp[1],
z: refObjInW.position.z + rp[2],
};
let newObjRot = {
x: refObjInW.rotation.x + relativeRot.x,
y: refObjInW.rotation.y + relativeRot.y,
z: refObjInW.rotation.z + relativeRot.z
};
if (existedBox){
existedBox.position.x = newObjPos.x;
existedBox.position.y = newObjPos.y;
existedBox.position.z = newObjPos.z;
existedBox.rotation.x = newObjRot.x;
existedBox.rotation.y = newObjRot.y;
existedBox.rotation.z = newObjRot.z;
existedBox.scale.x = box.scale.x;
existedBox.scale.y = box.scale.y;
existedBox.scale.z = box.scale.z;
existedBox.annotator="F";
existedBox.follows = {
obj_track_id: refObj.obj_track_id,
relative_position: {
x: relativePos[0],
y: relativePos[1],
z: relativePos[2],
},
relative_rotation: relativeRot,
};
logger.log(`modified box in ${w}`);
} else{
let newBox = w.annotation.add_box(newObjPos,
box.scale,
newObjRot,
box.obj_type,
box.obj_track_id,
box.obj_attr);
newBox.annotator="F";
newBox.follows = {
obj_track_id: refObj.obj_track_id,
relative_position: {
x: relativePos[0],
y: relativePos[1],
z: relativePos[2],
},
relative_rotation: relativeRot,
};
w.annotation.load_box(newBox);
logger.log(`inserted box in ${w}`);
}
console.log("added box in ", w.frameInfo.frame);
//saveList.push(w);
w.annotation.setModified();
});
//saveWorldList(saveList);
} }
};
this.syncFollowers = function(box){ let existedBox = w.annotation.boxes.find(
let world = box.world; (b) => b.obj_track_id == box.obj_track_id
let allFollowers = world.annotation.boxes.filter(b=>b.follows && b.follows.obj_track_id === box.obj_track_id); );
if (allFollowers.length == 0){ if (existedBox && !existedBox.annotator) {
console.log("no followers"); // have same objects annotated.
return; // if its generated by machine, lets overwrite it
return;
} }
let refObj = box; let refObjInW = w.annotation.boxes.find(
let coord = euler_angle_to_rotate_matrix_3by3(refObj.rotation); (b) => b.obj_track_id == refObj.obj_track_id
);
if (!refObjInW) {
allFollowers.forEach(fb=>{ // not found refobj in this world, give up
let relpos = [fb.follows.relative_position.x, return;
fb.follows.relative_position.y,
fb.follows.relative_position.z,
];
let rp = matmul2(coord, relpos, 3);
fb.position.x = refObj.position.x + rp[0];
fb.position.y = refObj.position.y + rp[1];
fb.position.z = refObj.position.z + rp[2];
fb.rotation.x = refObj.rotation.x + fb.follows.relative_rotation.x;
fb.rotation.y = refObj.rotation.y + fb.follows.relative_rotation.y;
fb.rotation.z = refObj.rotation.z + fb.follows.relative_rotation.z;
});
};
this.paste_bbox=function(pos, add_box){
if (!pos)
pos = this.marked_object.ann.psr.position;
else
pos.z = this.marked_object.ann.psr.position.z;
return add_box(pos, this.marked_object.ann.psr.scale, this.marked_object.ann.psr.rotation,
this.marked_object.ann.obj_type, this.marked_object.ann.obj_id, this.marked_object.ann.obj_attr);
};
// this.auto_adjust_bbox=function(box, done, on_box_changed){
// saveWorld(function(){
// do_adjust(box, on_box_changed);
// });
// let _self =this;
// function do_adjust(box, on_box_changed){
// console.log("auto adjust highlighted bbox");
// var xhr = new XMLHttpRequest();
// // we defined the xhr
// xhr.onreadystatechange = function () {
// if (this.readyState != 4) return;
// if (this.status == 200) {
// console.log(this.responseText)
// console.log(box.position);
// console.log(box.rotation);
// var trans_mat = JSON.parse(this.responseText);
// var rotation = Math.atan2(trans_mat[4], trans_mat[0]) + box.rotation.z;
// var transform = {
// x: -trans_mat[3],
// y: -trans_mat[7],
// z: -trans_mat[11],
// }
// /*
// cos sin x
// -sin cos y
// */
// var new_pos = {
// x: Math.cos(-rotation) * transform.x + Math.sin(-rotation) * transform.y,
// y: -Math.sin(-rotation) * transform.x + Math.cos(-rotation) * transform.y,
// z: transform.z,
// };
// box.position.x += new_pos.x;
// box.position.y += new_pos.y;
// box.position.z += new_pos.z;
// box.scale.x = marked_object.scale.x;
// box.scale.y = marked_object.scale.y;
// box.scale.z = marked_object.scale.z;
// box.rotation.z -= Math.atan2(trans_mat[4], trans_mat[0]);
// console.log(box.position);
// console.log(box.rotation);
// on_box_changed(box);
// _self.header.mark_changed_flag();
// if (done){
// done();
// }
// }
// // end of state change: it can be after some time (async)
// };
// xhr.open('GET',
// "/auto_adjust"+"?scene="+marked_object.scene + "&"+
// "ref_frame=" + marked_object.frame + "&" +
// "object_id=" + marked_object.obj_track_id + "&" +
// "adj_frame=" + data.world.frameInfo.frame,
// true);
// xhr.send();
// }
// };
this.smart_paste=function(selected_box, add_box, on_box_changed){
var box = selected_box;
if (!box){
let sceneP = this.mouse.get_mouse_location_in_world()
// trans pos to world local pos
//let pos = this.data.world.scenePosToLidar(sceneP);
box = this.paste_bbox(pos, add_box);
} }
else if (this.marked_object){
box.scale.x = this.marked_object.ann.psr.scale.x; let coord = euler_angle_to_rotate_matrix_3by3(refObjInW.rotation);
box.scale.y = this.marked_object.ann.psr.scale.y;
box.scale.z = this.marked_object.ann.psr.scale.z; let rp = matmul2(coord, relativePos, 3);
let newObjPos = {
x: refObjInW.position.x + rp[0],
y: refObjInW.position.y + rp[1],
z: refObjInW.position.z + rp[2],
};
let newObjRot = {
x: refObjInW.rotation.x + relativeRot.x,
y: refObjInW.rotation.y + relativeRot.y,
z: refObjInW.rotation.z + relativeRot.z,
};
if (existedBox) {
existedBox.position.x = newObjPos.x;
existedBox.position.y = newObjPos.y;
existedBox.position.z = newObjPos.z;
existedBox.rotation.x = newObjRot.x;
existedBox.rotation.y = newObjRot.y;
existedBox.rotation.z = newObjRot.z;
existedBox.scale.x = box.scale.x;
existedBox.scale.y = box.scale.y;
existedBox.scale.z = box.scale.z;
existedBox.annotator = "F";
existedBox.follows = {
obj_track_id: refObj.obj_track_id,
relative_position: {
x: relativePos[0],
y: relativePos[1],
z: relativePos[2],
},
relative_rotation: relativeRot,
};
logger.log(`modified box in ${w}`);
} else {
let newBox = w.annotation.add_box(
newObjPos,
box.scale,
newObjRot,
box.obj_type,
box.obj_track_id,
box.obj_attr
);
newBox.annotator = "F";
newBox.follows = {
obj_track_id: refObj.obj_track_id,
relative_position: {
x: relativePos[0],
y: relativePos[1],
z: relativePos[2],
},
relative_rotation: relativeRot,
};
w.annotation.load_box(newBox);
logger.log(`inserted box in ${w}`);
} }
// this.auto_adjust_bbox(box,
// function(){saveWorld();},
// on_box_changed);
// this.header.mark_changed_flag();
this.boxOp.auto_rotate_xyz(box, null, null,
on_box_changed,
"noscaling");
};
}
console.log("added box in ", w.frameInfo.frame);
//saveList.push(w);
w.annotation.setModified();
});
//saveWorldList(saveList);
}
};
this.syncFollowers = function (box) {
let world = box.world;
let allFollowers = world.annotation.boxes.filter(
(b) => b.follows && b.follows.obj_track_id === box.obj_track_id
);
if (allFollowers.length == 0) {
console.log("no followers");
return;
}
let refObj = box;
let coord = euler_angle_to_rotate_matrix_3by3(refObj.rotation);
allFollowers.forEach((fb) => {
let relpos = [
fb.follows.relative_position.x,
fb.follows.relative_position.y,
fb.follows.relative_position.z,
];
let rp = matmul2(coord, relpos, 3);
fb.position.x = refObj.position.x + rp[0];
fb.position.y = refObj.position.y + rp[1];
fb.position.z = refObj.position.z + rp[2];
fb.rotation.x = refObj.rotation.x + fb.follows.relative_rotation.x;
fb.rotation.y = refObj.rotation.y + fb.follows.relative_rotation.y;
fb.rotation.z = refObj.rotation.z + fb.follows.relative_rotation.z;
});
};
this.paste_bbox = function (pos, add_box) {
if (!pos) pos = this.marked_object.ann.psr.position;
else pos.z = this.marked_object.ann.psr.position.z;
return add_box(
pos,
this.marked_object.ann.psr.scale,
this.marked_object.ann.psr.rotation,
this.marked_object.ann.obj_type,
this.marked_object.ann.obj_id,
this.marked_object.ann.obj_attr
);
};
// this.auto_adjust_bbox=function(box, done, on_box_changed){
// saveWorld(function(){
// do_adjust(box, on_box_changed);
// });
// let _self =this;
// function do_adjust(box, on_box_changed){
// console.log("auto adjust highlighted bbox");
// var xhr = new XMLHttpRequest();
// // we defined the xhr
// xhr.onreadystatechange = function () {
// if (this.readyState != 4) return;
// if (this.status == 200) {
// console.log(this.responseText)
// console.log(box.position);
// console.log(box.rotation);
// var trans_mat = JSON.parse(this.responseText);
// var rotation = Math.atan2(trans_mat[4], trans_mat[0]) + box.rotation.z;
// var transform = {
// x: -trans_mat[3],
// y: -trans_mat[7],
// z: -trans_mat[11],
// }
// /*
// cos sin x
// -sin cos y
// */
// var new_pos = {
// x: Math.cos(-rotation) * transform.x + Math.sin(-rotation) * transform.y,
// y: -Math.sin(-rotation) * transform.x + Math.cos(-rotation) * transform.y,
// z: transform.z,
// };
// box.position.x += new_pos.x;
// box.position.y += new_pos.y;
// box.position.z += new_pos.z;
// box.scale.x = marked_object.scale.x;
// box.scale.y = marked_object.scale.y;
// box.scale.z = marked_object.scale.z;
// box.rotation.z -= Math.atan2(trans_mat[4], trans_mat[0]);
// console.log(box.position);
// console.log(box.rotation);
// on_box_changed(box);
// _self.header.mark_changed_flag();
// if (done){
// done();
// }
// }
// // end of state change: it can be after some time (async)
// };
// xhr.open('GET',
// "/auto_adjust"+"?scene="+marked_object.scene + "&"+
// "ref_frame=" + marked_object.frame + "&" +
// "object_id=" + marked_object.obj_track_id + "&" +
// "adj_frame=" + data.world.frameInfo.frame,
// true);
// xhr.send();
// }
// };
this.smart_paste = function (selected_box, add_box, on_box_changed) {
var box = selected_box;
if (!box) {
let sceneP = this.mouse.get_mouse_location_in_world();
// trans pos to world local pos
//let pos = this.data.world.scenePosToLidar(sceneP);
box = this.paste_bbox(pos, add_box);
} else if (this.marked_object) {
box.scale.x = this.marked_object.ann.psr.scale.x;
box.scale.y = this.marked_object.ann.psr.scale.y;
box.scale.z = this.marked_object.ann.psr.scale.z;
}
// this.auto_adjust_bbox(box,
// function(){saveWorld();},
// on_box_changed);
// this.header.mark_changed_flag();
this.boxOp.auto_rotate_xyz(box, null, null, on_box_changed, "noscaling");
};
}
export {AutoAdjust} export { AutoAdjust };

@ -1,30 +1,39 @@
import { globalObjectCategory } from "./obj_cfg.js"; import { globalObjectCategory } from "./obj_cfg.js";
function autoAnnotate(world, done, alg) {
var xhr = new XMLHttpRequest();
// we defined the xhr
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
let anns = JSON.parse(this.responseText);
function autoAnnotate(world, done, alg){ anns.map(
var xhr = new XMLHttpRequest(); (a) =>
// we defined the xhr (a.obj_type = globalObjectCategory.guess_obj_type_by_dimension(
xhr.onreadystatechange = function () { a.psr.scale
if (this.readyState != 4) return; ))
);
if (this.status == 200) {
let anns = JSON.parse(this.responseText); // load annotations
world.annotation.reapplyAnnotation(anns);
anns.map(a=>a.obj_type = globalObjectCategory.guess_obj_type_by_dimension(a.psr.scale));
if (done) done();
// load annotations }
world.annotation.reapplyAnnotation(anns); };
if (done)
done();
}
};
xhr.open('GET', "/auto_annotate?"+"scene="+world.frameInfo.scene+"&frame="+world.frameInfo.frame, true);
xhr.send();
}
xhr.open(
"GET",
"/auto_annotate?" +
"scene=" +
world.frameInfo.scene +
"&frame=" +
world.frameInfo.frame,
true
);
xhr.send();
}
export {autoAnnotate} export { autoAnnotate };

@ -1,403 +1,387 @@
import * as THREE from './lib/three.module.js'; import * as THREE from "./lib/three.module.js";
import { PCDLoader } from './lib/PCDLoader.js'; import { PCDLoader } from "./lib/PCDLoader.js";
import { matmul, euler_angle_to_rotate_matrix_3by3} from "./util.js" import { matmul, euler_angle_to_rotate_matrix_3by3 } from "./util.js";
//todo: clean arrows //todo: clean arrows
function AuxLidar(sceneMeta, world, frameInfo, auxLidarName){ function AuxLidar(sceneMeta, world, frameInfo, auxLidarName) {
this.world = world; this.world = world;
this.frameInfo = frameInfo; this.frameInfo = frameInfo;
this.name = auxLidarName; this.name = auxLidarName;
this.sceneMeta = sceneMeta; this.sceneMeta = sceneMeta;
this.coordinatesOffset = world.coordinatesOffset; this.coordinatesOffset = world.coordinatesOffset;
this.showPointsOnly = true; this.showPointsOnly = true;
this.showCalibBox = false; this.showCalibBox = false;
//this.cssStyleSelector = this.sceneMeta.calib.aux_lidar[this.name].cssstyleselector; //this.cssStyleSelector = this.sceneMeta.calib.aux_lidar[this.name].cssstyleselector;
this.color = this.sceneMeta.calib.aux_lidar[this.name].color; this.color = this.sceneMeta.calib.aux_lidar[this.name].color;
if (!this.color) {
this.color = [
this.world.data.cfg.point_brightness,
this.world.data.cfg.point_brightness,
this.world.data.cfg.point_brightness,
];
}
this.lidar_points = null; // read from file, centered at 0
this.elements = null; // geometry points
this.preloaded = false;
this.loaded = false;
this.go_cmd_received = false;
this.webglScene = null;
this.on_go_finished = null;
this.go = function (webglScene, on_go_finished) {
this.webglScene = webglScene;
if (this.preloaded) {
if (this.elements) {
this.webglScene.add(this.elements.points);
if (this.showCalibBox) this.webglScene.add(this.calib_box);
}
this.loaded = true;
if (on_go_finished) on_go_finished();
}
if (!this.color) //anyway we save go cmd
{ {
this.color = [ this.go_cmd_received = true;
this.world.data.cfg.point_brightness, this.on_go_finished = on_go_finished;
this.world.data.cfg.point_brightness,
this.world.data.cfg.point_brightness,
];
} }
};
this.lidar_points = null; // read from file, centered at 0 this.showCalibBox = function () {
this.elements = null; // geometry points this.showCalibBox = true;
this.webglScene.add(this.calib_box);
this.preloaded = false; };
this.loaded = false;
this.hideCalibBox = function () {
this.showCalibBox = false;
this.webglScene.remove(this.calib_box);
};
this.get_unoffset_lidar_points = function () {
if (this.elements) {
let pts = this.elements.points.geometry.getAttribute("position").array;
return pts.map((p, i) => p - this.world.coordinatesOffset[i % 3]);
} else {
return [];
}
};
this.go_cmd_received = false; // todo: what if it's not preloaded yet
this.webglScene = null; this.unload = function (keep_box) {
this.on_go_finished = null; if (this.elements) {
this.go = function(webglScene, on_go_finished){ this.webglScene.remove(this.elements.points);
this.webglScene = webglScene; if (!this.showPointsOnly)
this.elements.arrows.forEach((a) => this.webglScene.remove(a));
if (this.preloaded){
if (this.elements){
this.webglScene.add(this.elements.points);
if (this.showCalibBox)
this.webglScene.add(this.calib_box);
}
this.loaded = true;
if (on_go_finished)
on_go_finished();
}
//anyway we save go cmd
{
this.go_cmd_received = true;
this.on_go_finished = on_go_finished;
}
};
this.showCalibBox = function(){ if (!keep_box) this.webglScene.remove(this.calib_box);
this.showCalibBox = true; }
this.webglScene.add(this.calib_box); this.loaded = false;
}; };
this.hideCalibBox = function(){ // todo: its possible to remove points before preloading,
this.showCalibBox = false; this.deleteAll = function (keep_box) {
this.webglScene.remove(this.calib_box); if (this.loaded) {
}; this.unload();
}
this.get_unoffset_lidar_points = function(){ if (this.elements) {
if (this.elements){ //this.scene.remove(this.points);
let pts = this.elements.points.geometry.getAttribute("position").array; this.world.data.dbg.free();
return pts.map((p,i)=>p-this.world.coordinatesOffset[i %3]);
}
else{
return [];
}
};
// todo: what if it's not preloaded yet if (this.elements.points) {
this.unload = function(keep_box){ this.elements.points.geometry.dispose();
if (this.elements){ this.elements.points.material.dispose();
this.webglScene.remove(this.elements.points); }
if (!this.showPointsOnly)
this.elements.arrows.forEach(a=>this.webglScene.remove(a));
if (!keep_box)
this.webglScene.remove(this.calib_box);
}
this.loaded = false;
};
// todo: its possible to remove points before preloading, if (this.elements.arrows) {
this.deleteAll = function(keep_box){ this.elements.arrows.forEach((a) => {
if (this.loaded){ this.world.data.dbg.free();
this.unload(); a.geometry.dispose();
} a.material.dispose();
});
}
if (this.elements){ this.elements = null;
//this.scene.remove(this.points); }
this.world.data.dbg.free();
if (this.elements.points)
{
this.elements.points.geometry.dispose();
this.elements.points.material.dispose();
}
if (this.elements.arrows)
{
this.elements.arrows.forEach(a=>{
this.world.data.dbg.free();
a.geometry.dispose();
a.material.dispose();
})
}
this.elements = null;
}
if (!keep_box && this.calib_box){ if (!keep_box && this.calib_box) {
this.world.data.dbg.free(); this.world.data.dbg.free();
this.calib_box.geometry.dispose(); this.calib_box.geometry.dispose();
this.calib_box.material.dispose(); this.calib_box.material.dispose();
this.calib_box = null; this.calib_box = null;
} }
}; };
this.filterPoints = function(position){ this.filterPoints = function (position) {
let filtered_position = []; let filtered_position = [];
if (pointsGlobalConfig.enableFilterPoints) if (pointsGlobalConfig.enableFilterPoints) {
{ for (let i = 0; i <= position.length; i += 3) {
for(let i = 0; i <= position.length; i+=3) if (position[i + 2] <= pointsGlobalConfig.filterPointsZ) {
{ filtered_position.push(position[i]);
if (position[i+2] <= pointsGlobalConfig.filterPointsZ) filtered_position.push(position[i + 1]);
{ filtered_position.push(position[i + 2]);
filtered_position.push(position[i]);
filtered_position.push(position[i+1]);
filtered_position.push(position[i+2]);
}
}
} }
}
}
return filtered_position; return filtered_position;
}; };
this.preload = function(on_preload_finished){ this.preload = function (on_preload_finished) {
this.on_preload_finished = on_preload_finished;
this.on_preload_finished = on_preload_finished;
var loader = new PCDLoader();
var _self = this;
loader.load( this.frameInfo.get_aux_lidar_path(this.name),
//ok
function ( pcd ) {
var position = pcd.position;
//_self.points_parse_time = new Date().getTime();
//console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "parse pionts ", _self.points_parse_time - _self.create_time, "ms");
_self.lidar_points = position;
// add one box to calibrate lidar with lidar
_self.calib_box = _self.createCalibBox();
// install callback for box changing
_self.calib_box.on_box_changed = ()=>{
_self.move_lidar(_self.calib_box);
};
//position = _self.transformPointsByOffset(position);
position = _self.move_points(_self.calib_box);
let elements = _self.buildGeometry(position);
_self.elements = elements;
//_self.points_backup = mesh;
_self._afterPreload();
},
// on progress,
function(){},
// on error
function(){
//error
console.log("load lidar failed.");
_self._afterPreload();
},
// on file loaded
function(){
//_self.points_readfile_time = new Date().getTime();
//console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "read file ", _self.points_readfile_time - _self.create_time, "ms");
}
);
};
// internal funcs below var loader = new PCDLoader();
this._afterPreload = function(){
this.preloaded = true;
console.log(`lidar ${this.auxLidarName} preloaded`);
if (this.on_preload_finished){
this.on_preload_finished();
}
if (this.go_cmd_received){
this.go(this.webglScene, this.on_go_finished);
}
};
this.createCalibBox = function(){ var _self = this;
if (this.sceneMeta.calib.aux_lidar && this.sceneMeta.calib.aux_lidar[this.name]){ loader.load(
return this.world.annotation.createCuboid( this.frameInfo.get_aux_lidar_path(this.name),
{ //ok
x: this.sceneMeta.calib.aux_lidar[this.name].translation[0] + this.coordinatesOffset[0], function (pcd) {
y: this.sceneMeta.calib.aux_lidar[this.name].translation[1] + this.coordinatesOffset[1], var position = pcd.position;
z: this.sceneMeta.calib.aux_lidar[this.name].translation[2] + this.coordinatesOffset[2],
},
{x:0.5, y:0.5, z:0.5},
{
x: this.sceneMeta.calib.aux_lidar[this.name].rotation[0],
y: this.sceneMeta.calib.aux_lidar[this.name].rotation[1],
z: this.sceneMeta.calib.aux_lidar[this.name].rotation[2],
},
"lidar",
this.name);
}else {
return this.world.annotation.createCuboid(
{x: this.coordinatesOffset[0],
y: this.coordinatesOffset[1],
z: this.coordinatesOffset[2]},
{x:0.5, y:0.5, z:0.5},
{x:0,y:0,z:0},
"lidar",
this.name);
}
};
this.buildPoints = function(position){ //_self.points_parse_time = new Date().getTime();
// build geometry //console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "parse pionts ", _self.points_parse_time - _self.create_time, "ms");
this.world.data.dbg.alloc(); _self.lidar_points = position;
let geometry = new THREE.BufferGeometry();
if ( position.length > 0 )
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) );
let pointColor = this.color;
let color=[];
for (var i =0; i< position.length; i+=3){
color.push(pointColor[0]);
color.push(pointColor[1]);
color.push(pointColor[2]);
}
geometry.addAttribute( 'color', new THREE.Float32BufferAttribute(color, 3 ) ); // add one box to calibrate lidar with lidar
_self.calib_box = _self.createCalibBox();
geometry.computeBoundingSphere(); // install callback for box changing
_self.calib_box.on_box_changed = () => {
// build material _self.move_lidar(_self.calib_box);
let pointSize = this.sceneMeta.calib.aux_lidar[this.name].point_size; };
if (!pointSize)
pointSize = 1;
let material = new THREE.PointsMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
//material.size = 2;
material.sizeAttenuation = false;
// build mesh //position = _self.transformPointsByOffset(position);
let mesh = new THREE.Points( geometry, material ); position = _self.move_points(_self.calib_box);
mesh.name = "lidar";
return mesh; let elements = _self.buildGeometry(position);
};
_self.elements = elements;
//_self.points_backup = mesh;
this.buildGeometry = function(position){ _self._afterPreload();
let points = this.buildPoints(position); },
return { // on progress,
points: points, function () {},
};
}; // on error
function () {
//error
console.log("load lidar failed.");
_self._afterPreload();
},
// on file loaded
function () {
//_self.points_readfile_time = new Date().getTime();
//console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "read file ", _self.points_readfile_time - _self.create_time, "ms");
}
);
};
// internal funcs below
this._afterPreload = function () {
this.preloaded = true;
console.log(`lidar ${this.auxLidarName} preloaded`);
if (this.on_preload_finished) {
this.on_preload_finished();
}
if (this.go_cmd_received) {
this.go(this.webglScene, this.on_go_finished);
}
};
this.createCalibBox = function () {
if (
this.sceneMeta.calib.aux_lidar &&
this.sceneMeta.calib.aux_lidar[this.name]
) {
return this.world.annotation.createCuboid(
{
x:
this.sceneMeta.calib.aux_lidar[this.name].translation[0] +
this.coordinatesOffset[0],
y:
this.sceneMeta.calib.aux_lidar[this.name].translation[1] +
this.coordinatesOffset[1],
z:
this.sceneMeta.calib.aux_lidar[this.name].translation[2] +
this.coordinatesOffset[2],
},
{ x: 0.5, y: 0.5, z: 0.5 },
{
x: this.sceneMeta.calib.aux_lidar[this.name].rotation[0],
y: this.sceneMeta.calib.aux_lidar[this.name].rotation[1],
z: this.sceneMeta.calib.aux_lidar[this.name].rotation[2],
},
"lidar",
this.name
);
} else {
return this.world.annotation.createCuboid(
{
x: this.coordinatesOffset[0],
y: this.coordinatesOffset[1],
z: this.coordinatesOffset[2],
},
{ x: 0.5, y: 0.5, z: 0.5 },
{ x: 0, y: 0, z: 0 },
"lidar",
this.name
);
}
};
this.buildPoints = function (position) {
// build geometry
this.world.data.dbg.alloc();
let geometry = new THREE.BufferGeometry();
if (position.length > 0)
geometry.addAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
let pointColor = this.color;
let color = [];
for (var i = 0; i < position.length; i += 3) {
color.push(pointColor[0]);
color.push(pointColor[1]);
color.push(pointColor[2]);
}
this.move_points = function(box){ geometry.addAttribute("color", new THREE.Float32BufferAttribute(color, 3));
let points = this.lidar_points;
let trans = euler_angle_to_rotate_matrix_3by3(box.rotation);
let rotated_points = matmul(trans, points, 3);
let translation=[box.position.x, box.position.y, box.position.z];
let translated_points = rotated_points.map((p,i)=>{
return p + translation[i % 3];
});
let filtered_position = this.filterPoints(translated_points); geometry.computeBoundingSphere();
return filtered_position;
};
// build material
let pointSize = this.sceneMeta.calib.aux_lidar[this.name].point_size;
if (!pointSize) pointSize = 1;
let material = new THREE.PointsMaterial({
size: pointSize,
vertexColors: THREE.VertexColors,
});
//material.size = 2;
material.sizeAttenuation = false;
this.move_lidar= function(box){ // build mesh
let mesh = new THREE.Points(geometry, material);
mesh.name = "lidar";
let translated_points = this.move_points(box); return mesh;
};
let elements = this.buildGeometry(translated_points); this.buildGeometry = function (position) {
let points = this.buildPoints(position);
// remove old points
this.unload(true);
this.deleteAll(true);
this.elements = elements; return {
//_self.points_backup = mesh; points: points,
if (this.go_cmd_received) // this should be always true
{
this.webglScene.add(this.elements.points);
if (!this.showPointsOnly)
this.elements.arrows.forEach(a=>this.webglScene.add(a));
}
}; };
};
this.move_points = function (box) {
let points = this.lidar_points;
let trans = euler_angle_to_rotate_matrix_3by3(box.rotation);
let rotated_points = matmul(trans, points, 3);
let translation = [box.position.x, box.position.y, box.position.z];
let translated_points = rotated_points.map((p, i) => {
return p + translation[i % 3];
});
let filtered_position = this.filterPoints(translated_points);
return filtered_position;
};
this.move_lidar = function (box) {
let translated_points = this.move_points(box);
let elements = this.buildGeometry(translated_points);
// remove old points
this.unload(true);
this.deleteAll(true);
this.elements = elements;
//_self.points_backup = mesh;
if (this.go_cmd_received) {
// this should be always true
this.webglScene.add(this.elements.points);
if (!this.showPointsOnly)
this.elements.arrows.forEach((a) => this.webglScene.add(a));
}
};
} }
function AuxLidarManager(sceneMeta, world, frameInfo){ function AuxLidarManager(sceneMeta, world, frameInfo) {
this.lidarList = []; this.lidarList = [];
if (world.data.cfg.enableAuxLidar && sceneMeta.aux_lidar){ if (world.data.cfg.enableAuxLidar && sceneMeta.aux_lidar) {
let lidars = []; let lidars = [];
for (let r in sceneMeta.calib.aux_lidar){
if (!sceneMeta.calib.aux_lidar[r].disable)
lidars.push(r);
}
this.lidarList = lidars.map(name=>{ for (let r in sceneMeta.calib.aux_lidar) {
return new AuxLidar(sceneMeta, world, frameInfo, name); if (!sceneMeta.calib.aux_lidar[r].disable) lidars.push(r);
});
} }
this.getAllBoxes = function() this.lidarList = lidars.map((name) => {
{ return new AuxLidar(sceneMeta, world, frameInfo, name);
if (this.showCalibBox) });
{ }
return this.lidarList.map(r=>r.calib_box);
}
else
{
return [];
}
};
this.preloaded = function(){ this.getAllBoxes = function () {
for (let r in this.lidarList){ if (this.showCalibBox) {
if (!this.lidarList[r].preloaded) return this.lidarList.map((r) => r.calib_box);
return false; } else {
} return [];
return true; }
}; };
this.go = function(webglScene, on_go_finished){ this.preloaded = function () {
this.lidarList.forEach(r=>r.go(webglScene, on_go_finished)); for (let r in this.lidarList) {
}; if (!this.lidarList[r].preloaded) return false;
}
return true;
};
this.preload = function(on_preload_finished){ this.go = function (webglScene, on_go_finished) {
this.lidarList.forEach(r=>r.preload(on_preload_finished)); this.lidarList.forEach((r) => r.go(webglScene, on_go_finished));
}; };
this.unload = function(){ this.preload = function (on_preload_finished) {
this.lidarList.forEach(r=>r.unload()); this.lidarList.forEach((r) => r.preload(on_preload_finished));
}; };
this.deleteAll = function(){ this.unload = function () {
this.lidarList.forEach(r=>r.deleteAll()); this.lidarList.forEach((r) => r.unload());
}; };
this.getOperableObjects = function(){ this.deleteAll = function () {
return this.lidarList.flatMap(r=>r.getOperableObjects()); this.lidarList.forEach((r) => r.deleteAll());
}; };
this.showCalibBox = false; this.getOperableObjects = function () {
this.showCalibBox = function(){ return this.lidarList.flatMap((r) => r.getOperableObjects());
this.showCalibBox = true; };
this.lidarList.forEach(r=>r.showCalibBox());
};
this.hideCalibBox = function(){ this.showCalibBox = false;
this.showCalibBox = false; this.showCalibBox = function () {
this.lidarList.forEach(r=>r.hideCalibBox()); this.showCalibBox = true;
} this.lidarList.forEach((r) => r.showCalibBox());
}; };
this.hideCalibBox = function () {
this.showCalibBox = false;
this.lidarList.forEach((r) => r.hideCalibBox());
};
}
export {AuxLidarManager} export { AuxLidarManager };

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,153 +1,177 @@
import {
import {rotation_matrix_to_euler_angle,euler_angle_to_rotate_matrix, matmul, transpose} from "./util.js" rotation_matrix_to_euler_angle,
euler_angle_to_rotate_matrix,
matmul,
transpose,
} from "./util.js";
//import {render_2d_image, update_image_box_projection} from "./image.js" //import {render_2d_image, update_image_box_projection} from "./image.js"
function Calib(data, editor){ function Calib(data, editor) {
this.data = data; this.data = data;
this.editor = editor; this.editor = editor;
var euler_angle={x:0, y:0, y:0}; var euler_angle = { x: 0, y: 0, y: 0 };
var translate = {x:0, y:0, z:0}; var translate = { x: 0, y: 0, z: 0 };
this.save_calibration = function(){ this.save_calibration = function () {
var scene_meta = data.meta[data.world.frameInfo.scene];
var scene_meta = data.meta[data.world.frameInfo.scene]; var active_camera_name = data.world.cameras.active_name;
var calib = scene_meta.calib.camera[active_camera_name];
var active_camera_name = data.world.cameras.active_name; var extrinsic = calib.extrinsic.map(function (x) {
var calib = scene_meta.calib.camera[active_camera_name] return x * 1.0;
});
var extrinsic = calib.extrinsic.map(function(x){return x*1.0;});
euler_angle = rotation_matrix_to_euler_angle(extrinsic);
euler_angle = rotation_matrix_to_euler_angle(extrinsic); translate = {
translate = { x: extrinsic[3] * 1.0,
x: extrinsic[3]*1.0, y: extrinsic[7] * 1.0,
y: extrinsic[7]*1.0, z: extrinsic[11] * 1.0,
z: extrinsic[11]*1.0,
};
console.log(extrinsic, euler_angle, translate);
let matrix = euler_angle_to_rotate_matrix(euler_angle, translate)
console.log("restoreed matrix",matrix);
this.editor.infoBox.show("calib", JSON.stringify(matrix));
}
this.reset_calibration = function(){
// to be done
this.editor.imageContextManager.render_2d_image();
}
this.calib_box = null;
this.show_camera_pos = function(){
this.editor.viewManager.mainView.dumpPose();
}; };
console.log(extrinsic, euler_angle, translate);
// show a manipulating box
this.start_calibration = function(){ let matrix = euler_angle_to_rotate_matrix(euler_angle, translate);
var scene_meta = this.data.meta[data.world.frameInfo.scene]; console.log("restoreed matrix", matrix);
var active_camera_name = this.data.world.cameras.active_name; this.editor.infoBox.show("calib", JSON.stringify(matrix));
var calib = scene_meta.calib.camera[active_camera_name] };
var extrinsic = calib.extrinsic.map(function(x){return x*1.0;});
let viewMatrix = [0, -1, 0, 0, //row vector this.reset_calibration = function () {
0, 0, -1, 0, // to be done
1, 0, 0, 0, this.editor.imageContextManager.render_2d_image();
0, 0, 0, 1]; };
function transpose_transmatrix(m){
//m=4*4 this.calib_box = null;
return [
m[0],m[4],m[8],m[3], this.show_camera_pos = function () {
m[1],m[5],m[9],m[7], this.editor.viewManager.mainView.dumpPose();
m[2],m[6],m[10],m[11], };
m[12],m[13],m[14],m[15],
// show a manipulating box
]; this.start_calibration = function () {
} var scene_meta = this.data.meta[data.world.frameInfo.scene];
var active_camera_name = this.data.world.cameras.active_name;
var calib = scene_meta.calib.camera[active_camera_name];
var extrinsic = calib.extrinsic.map(function (x) {
return x * 1.0;
});
let viewMatrix = [
0,
-1,
0,
0, //row vector
0,
0,
-1,
0,
1,
0,
0,
0,
0,
0,
0,
1,
];
function transpose_transmatrix(m) {
//m=4*4
return [
m[0],
m[4],
m[8],
m[3],
m[1],
m[5],
m[9],
m[7],
m[2],
m[6],
m[10],
m[11],
m[12],
m[13],
m[14],
m[15],
];
}
var op_matrix = matmul (transpose_transmatrix(viewMatrix), var op_matrix = matmul(
transpose_transmatrix(extrinsic), 4); transpose_transmatrix(viewMatrix),
transpose_transmatrix(extrinsic),
4
);
var euler_angle = rotation_matrix_to_euler_angle(op_matrix);
var translate = {
x: extrinsic[3] * 1.0,
y: extrinsic[7] * 1.0,
z: extrinsic[11] * 1.0,
};
var euler_angle = rotation_matrix_to_euler_angle(op_matrix); console.log(euler_angle, translate);
var translate = { this.show_camera_pos();
x: extrinsic[3]*1.0,
y: extrinsic[7]*1.0,
z: extrinsic[11]*1.0,
};
console.log(euler_angle, translate);
this.show_camera_pos();
if (!this.calib_box) {
if (!this.calib_box) this.calib_box = this.data.world.annotation.createCuboid(
{ {
this.calib_box = this.data.world.annotation.createCuboid( x: translate.x, // + this.data.world.coordinatesOffset[0],
{ y: translate.y, // + this.data.world.coordinatesOffset[1],
x: translate.x,// + this.data.world.coordinatesOffset[0], z: translate.z, // + this.data.world.coordinatesOffset[2]
y: translate.y,// + this.data.world.coordinatesOffset[1], },
z: translate.z, // + this.data.world.coordinatesOffset[2] { x: 1, y: 1, z: 1 },
}, {
{x:1,y:1, z:1}, x: euler_angle.x,
{ y: euler_angle.y,
x: euler_angle.x, z: euler_angle.z,
y: euler_angle.y, },
z: euler_angle.z "camera",
}, "camera"
"camera", );
"camera"
); this.data.world.scene.add(this.calib_box);
} else {
this.data.world.scene.add(this.calib_box); console.log("calib box exists.");
this.calib_box.position.x = translate.x; // + this.data.world.coordinatesOffset[0];
} this.calib_box.position.y = translate.y; // + this.data.world.coordinatesOffset[1];
else{ this.calib_box.position.z = translate.z; // + this.data.world.coordinatesOffset[2];
console.log("calib box exists.");
this.calib_box.position.x = translate.x;// + this.data.world.coordinatesOffset[0]; this.calib_box.rotation.x = euler_angle.x;
this.calib_box.position.y = translate.y;// + this.data.world.coordinatesOffset[1]; this.calib_box.rotation.y = euler_angle.y;
this.calib_box.position.z = translate.z;// + this.data.world.coordinatesOffset[2]; this.calib_box.rotation.z = euler_angle.z;
}
this.calib_box.rotation.x = euler_angle.x;
this.calib_box.rotation.y = euler_angle.y;
this.calib_box.rotation.z = euler_angle.z;
}
console.log(this.calib_box); console.log(this.calib_box);
this.editor.render(); this.editor.render();
this.calib_box.on_box_changed = ()=>{
console.log("calib box changed.");
let real_pos = {
x: this.calib_box.position.x,// - this.data.world.coordinatesOffset[0],
y: this.calib_box.position.y,// - this.data.world.coordinatesOffset[1],
z: this.calib_box.position.z,// - this.data.world.coordinatesOffset[2],
};
let extrinsic = euler_angle_to_rotate_matrix(this.calib_box.rotation, real_pos);
calib.extrinsic = transpose_transmatrix(matmul (viewMatrix, extrinsic, 4));
console.log("extrinsic", calib.extrinsic)
console.log("euler", euler_angle, "translate", translate);
this.editor.imageContextManager.render_2d_image();
}
this.calib_box.on_box_changed = () => {
console.log("calib box changed.");
let real_pos = {
}; x: this.calib_box.position.x, // - this.data.world.coordinatesOffset[0],
y: this.calib_box.position.y, // - this.data.world.coordinatesOffset[1],
function stop_calibration() z: this.calib_box.position.z, // - this.data.world.coordinatesOffset[2],
{ };
//tbd
let extrinsic = euler_angle_to_rotate_matrix(
this.calib_box.rotation,
real_pos
);
calib.extrinsic = transpose_transmatrix(matmul(viewMatrix, extrinsic, 4));
console.log("extrinsic", calib.extrinsic);
console.log("euler", euler_angle, "translate", translate);
this.editor.imageContextManager.render_2d_image();
}; };
};
/*
function stop_calibration() {
//tbd
}
/*
function calibrate(ax, value){ function calibrate(ax, value){
var scene_meta = data.meta[data.world.frameInfo.scene]; var scene_meta = data.meta[data.world.frameInfo.scene];
@ -189,8 +213,6 @@ function Calib(data, editor){
update_image_box_projection(selected_box); update_image_box_projection(selected_box);
} }
*/ */
}
};
export {Calib} export { Calib };

@ -1,121 +1,106 @@
class Config {
//dataCfg = {
class Config{ //disableLabels: true,
enablePreload = true;
//dataCfg = { color_points = "mono";
enableRadar = false;
//disableLabels: true, enableAuxLidar = false;
enablePreload = true; enableDynamicGroundLevel = true;
color_points = "mono";
enableRadar = false;
enableAuxLidar = false;
enableDynamicGroundLevel = true;
coordinateSystem = 'utm';
point_size = 1;
point_brightness = 0.6;
box_opacity = 1;
show_background = true;
color_obj = "category";
theme = "dark";
enableFilterPoints = false;
filterPointsZ = 2.0;
batchModeInstNumber = 20;
batchModeSubviewSize = {width: 130, height: 450};
// edit on one box, apply to all selected boxes.
linkEditorsInBatchMode = false;
// only rotate z in 'auto/interpolate' algs
enableAutoRotateXY = false;
autoSave = true;
autoUpdateInterpolatedBoxes = true;
hideId = false;
hideCategory = false;
moveStep = 0.01; // ratio, percentage
rotateStep = Math.PI/360;
ignoreDistantObject = true;
///editorCfg
//disableSceneSelector = true;
//disableFrameSelector = true;
//disableCameraSelector = true;
//disableFastToolbox= true;
//disableMainView= true;
//disableMainImageContext = true;
//disableGrid = true;
//disableRangeCircle = true;
//disableAxis = true;
//disableMainViewKeyDown = true;
//projectRadarToImage = true;
//projectLidarToImage = true;
constructor()
{
}
readItem(name, defaultValue, castFunc){ coordinateSystem = "utm";
let ret = window.localStorage.getItem(name);
if (ret)
{
if (castFunc)
return castFunc(ret);
else
return ret;
}
else
{
return defaultValue;
}
}
setItem(name, value) point_size = 1;
{ point_brightness = 0.6;
this[name] = value; box_opacity = 1;
if (typeof value == 'object') show_background = true;
value = JSON.stringify(value); color_obj = "category";
window.localStorage.setItem(name, value); theme = "dark";
}
toBool(v) enableFilterPoints = false;
{ filterPointsZ = 2.0;
return v==="true";
}
saveItems = [ batchModeInstNumber = 20;
["theme", null], batchModeSubviewSize = { width: 130, height: 450 };
["enableRadar", this.toBool],
["enablePreload", this.toBool], // edit on one box, apply to all selected boxes.
["enableAuxLidar", this.toBool], linkEditorsInBatchMode = false;
["enableFilterPoints", this.toBool],
["filterPointsZ", parseFloat], // only rotate z in 'auto/interpolate' algs
["color_points", null], enableAutoRotateXY = false;
["coordinateSystem", null], autoSave = true;
["batchModeInstNumber", parseInt],
["batchModeSubviewSize", JSON.parse], autoUpdateInterpolatedBoxes = true;
["enableAutoRotateXY", this.toBool],
["autoUpdateInterpolatedBoxes", this.toBool],
];
load()
{
this.saveItems.forEach(item=>{
let key = item[0];
let castFunc = item[1];
this[key] = this.readItem(key, this[key], castFunc);
})
}
};
export {Config}; hideId = false;
hideCategory = false;
moveStep = 0.01; // ratio, percentage
rotateStep = Math.PI / 360;
ignoreDistantObject = true;
///editorCfg
//disableSceneSelector = true;
//disableFrameSelector = true;
//disableCameraSelector = true;
//disableFastToolbox= true;
//disableMainView= true;
//disableMainImageContext = true;
//disableGrid = true;
//disableRangeCircle = true;
//disableAxis = true;
//disableMainViewKeyDown = true;
//projectRadarToImage = true;
//projectLidarToImage = true;
constructor() {}
readItem(name, defaultValue, castFunc) {
let ret = window.localStorage.getItem(name);
if (ret) {
if (castFunc) return castFunc(ret);
else return ret;
} else {
return defaultValue;
}
}
setItem(name, value) {
this[name] = value;
if (typeof value == "object") value = JSON.stringify(value);
window.localStorage.setItem(name, value);
}
toBool(v) {
return v === "true";
}
saveItems = [
["theme", null],
["enableRadar", this.toBool],
["enablePreload", this.toBool],
["enableAuxLidar", this.toBool],
["enableFilterPoints", this.toBool],
["filterPointsZ", parseFloat],
["color_points", null],
["coordinateSystem", null],
["batchModeInstNumber", parseInt],
["batchModeSubviewSize", JSON.parse],
["enableAutoRotateXY", this.toBool],
["autoUpdateInterpolatedBoxes", this.toBool],
];
load() {
this.saveItems.forEach((item) => {
let key = item[0];
let castFunc = item[1];
this[key] = this.readItem(key, this[key], castFunc);
});
}
}
export { Config };

@ -1,347 +1,335 @@
import { globalKeyDownManager } from "./keydown_manager.js"; import { globalKeyDownManager } from "./keydown_manager.js";
import {logger} from "./log.js"; import { logger } from "./log.js";
class ConfigUi{ class ConfigUi {
clickableItems = {
clickableItems = { "#cfg-increase-size": (event) => {
"#cfg-increase-size": (event)=>{ this.editor.data.scale_point_size(1.2);
this.editor.data.scale_point_size(1.2); this.editor.render();
this.editor.render(); this.editor.boxEditorManager.render();
this.editor.boxEditorManager.render(); return false;
return false; },
},
"#cfg-decrease-size": (event) => {
"#cfg-decrease-size": (event)=>{ this.editor.data.scale_point_size(0.8);
this.editor.data.scale_point_size(0.8); this.editor.render();
this.editor.render(); this.editor.boxEditorManager.render();
this.editor.boxEditorManager.render(); return false;
return false; },
},
"#cfg-increase-brightness": (event) => {
"#cfg-increase-brightness": (event)=>{ this.editor.data.scale_point_brightness(1.2);
this.editor.data.scale_point_brightness(1.2); this.editor.render();
this.editor.render(); this.editor.boxEditorManager.render();
this.editor.boxEditorManager.render(); return false;
return false; },
},
"#cfg-decrease-brightness": (event) => {
"#cfg-decrease-brightness": (event)=>{ this.editor.data.scale_point_brightness(0.8);
this.editor.data.scale_point_brightness(0.8); this.editor.render();
this.editor.render(); this.editor.boxEditorManager.render();
this.editor.boxEditorManager.render(); return false;
return false; },
},
"#cfg-take-screenshot": (event) => {
"#cfg-take-screenshot": (event)=>{ this.editor.downloadWebglScreenShot();
this.editor.downloadWebglScreenShot(); return true;
return true; },
},
"#cfg-show-log": (event) => {
"#cfg-show-log": (event)=>{ logger.show();
logger.show(); return true;
return true; },
},
"#cfg-start-calib": (event) => {
"#cfg-start-calib":(event)=>{ this.editor.calib.start_calibration();
this.editor.calib.start_calibration(); return true;
return true; },
},
"#cfg-show-calib": (event) => {
"#cfg-show-calib":(event)=>{ this.editor.calib.save_calibration();
this.editor.calib.save_calibration(); return true;
return true; },
},
// "#cfg-reset-calib":(event)=>{
// "#cfg-reset-calib":(event)=>{ // this.editor.calib.reset_calibration();
// this.editor.calib.reset_calibration(); // return true;
// return true; // }
// }
"#cfg-crop-scene": (event) => {
"#cfg-crop-scene": (event)=>{ this.editor.cropScene.show();
this.editor.cropScene.show();
return true;
return true; },
}, };
changeableItems = {
"#cfg-theme-select": (event) => {
let theme = event.currentTarget.value;
//let scheme = document.documentElement.className;
document.documentElement.className = "theme-" + theme;
pointsGlobalConfig.setItem("theme", theme);
this.editor.viewManager.setColorScheme();
this.editor.render();
this.editor.boxEditorManager.render();
return false;
},
"#cfg-hide-box-checkbox": (event) => {
let checked = event.currentTarget.checked;
//let scheme = document.documentElement.className;
if (checked) this.editor.data.set_box_opacity(0);
else this.editor.data.set_box_opacity(1);
this.editor.render();
this.editor.boxEditorManager.render();
return false;
},
"#cfg-hide-id-checkbox": (event) => {
let checked = event.currentTarget.checked;
this.editor.floatLabelManager.show_id(!checked);
return false;
},
"#cfg-hide-category-checkbox": (event) => {
let checked = event.currentTarget.checked;
this.editor.floatLabelManager.show_category(!checked);
return false;
},
"#cfg-hide-circle-ruler-checkbox": (event) => {
let checked = event.currentTarget.checked;
this.editor.showRangeCircle(!checked);
return false;
},
"#cfg-auto-rotate-xy-checkbox": (event) => {
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableAutoRotateXY", checked);
return false;
},
"#cfg-auto-update-interpolated-boxes-checkbox": (event) => {
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("autoUpdateInterpolatedBoxes", checked);
return false;
},
"#cfg-color-points-select": (event) => {
let value = event.currentTarget.value;
pointsGlobalConfig.setItem("color_points", value);
this.editor.data.worldList.forEach((w) => {
w.lidar.color_points();
w.lidar.update_points_color();
});
this.editor.render();
return false;
},
"#cfg-color-object-scheme": (event) => {
let value = event.currentTarget.value;
this.editor.data.set_obj_color_scheme(value);
this.editor.render();
this.editor.imageContextManager.render_2d_image();
this.editor.floatLabelManager.set_color_scheme(value);
this.editor.render2dLabels(this.editor.data.world);
this.editor.boxEditorManager.render();
return false;
},
"#cfg-batch-mode-inst-number": (event) => {
let batchSize = parseInt(event.currentTarget.value);
pointsGlobalConfig.setItem("batchModeInstNumber", batchSize);
this.editor.boxEditorManager.setBatchSize(batchSize);
return false;
},
"#cfg-coordinate-system-select": (event) => {
let coord = event.currentTarget.value;
pointsGlobalConfig.setItem("coordinateSystem", coord);
this.editor.data.worldList.forEach((w) => {
w.calcTransformMatrix();
});
this.editor.render();
},
"#cfg-data-aux-lidar-checkbox": (event) => {
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableAuxLidar", checked);
return false;
},
"#cfg-data-radar-checkbox": (event) => {
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableRadar", checked);
return false;
},
"#cfg-data-filter-points-checkbox": (event) => {
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableFilterPoints", checked);
return false;
},
"#cfg-data-filter-points-z": (event) => {
let z = event.currentTarget.value;
pointsGlobalConfig.setItem("filterPointsZ", z);
return false;
},
"#cfg-data-preload-checkbox": (event) => {
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enablePreload", checked);
return false;
},
};
ignoreItems = [
"#cfg-point-size",
"#cfg-point-brightness",
"#cfg-theme",
"#cfg-color-object",
"#cfg-menu-batch-mode-inst-number",
"#cfg-hide-box",
"#cfg-calib-camera-LiDAR",
"#cfg-experimental",
"#cfg-data",
];
subMenus = ["#cfg-experimental", "#cfg-data"];
constructor(button, wrapper, editor) {
this.button = button;
this.wrapper = wrapper;
this.editor = editor;
this.editorCfg = editor.editorCfg;
this.dataCfg = editor.data.cfg;
this.menu = this.wrapper.querySelector("#config-menu");
this.wrapper.onclick = () => {
this.hide();
}; };
changeableItems = { this.button.onclick = (event) => {
this.show(event.currentTarget);
"#cfg-theme-select":(event)=>{ };
let theme = event.currentTarget.value;
//let scheme = document.documentElement.className;
document.documentElement.className = "theme-"+theme;
pointsGlobalConfig.setItem("theme", theme);
this.editor.viewManager.setColorScheme();
this.editor.render();
this.editor.boxEditorManager.render();
return false;
},
"#cfg-hide-box-checkbox":(event)=>{
let checked = event.currentTarget.checked;
//let scheme = document.documentElement.className;
if (checked)
this.editor.data.set_box_opacity(0);
else
this.editor.data.set_box_opacity(1);
this.editor.render();
this.editor.boxEditorManager.render();
return false;
},
"#cfg-hide-id-checkbox":(event)=>{
let checked = event.currentTarget.checked;
this.editor.floatLabelManager.show_id(!checked);
return false;
},
"#cfg-hide-category-checkbox":(event)=>{
let checked = event.currentTarget.checked;
this.editor.floatLabelManager.show_category(!checked);
return false;
},
"#cfg-hide-circle-ruler-checkbox": (event)=>{
let checked = event.currentTarget.checked;
this.editor.showRangeCircle(!checked);
return false;
},
"#cfg-auto-rotate-xy-checkbox": (event)=>{
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableAutoRotateXY", checked);
return false;
},
'#cfg-auto-update-interpolated-boxes-checkbox': (event)=>{
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("autoUpdateInterpolatedBoxes", checked);
return false;
},
"#cfg-color-points-select": (event)=>{
let value = event.currentTarget.value;
pointsGlobalConfig.setItem("color_points", value);
this.editor.data.worldList.forEach(w=>{
w.lidar.color_points();
w.lidar.update_points_color();
});
this.editor.render();
return false;
},
"#cfg-color-object-scheme":(event)=>{
let value = event.currentTarget.value;
this.editor.data.set_obj_color_scheme(value);
this.editor.render();
this.editor.imageContextManager.render_2d_image();
this.editor.floatLabelManager.set_color_scheme(value);
this.editor.render2dLabels(this.editor.data.world);
this.editor.boxEditorManager.render();
return false;
},
"#cfg-batch-mode-inst-number":(event)=>{
let batchSize = parseInt(event.currentTarget.value);
pointsGlobalConfig.setItem("batchModeInstNumber", batchSize);
this.editor.boxEditorManager.setBatchSize(batchSize);
return false;
},
"#cfg-coordinate-system-select": (event)=>{
let coord = event.currentTarget.value;
pointsGlobalConfig.setItem("coordinateSystem", coord);
this.editor.data.worldList.forEach(w=>{
w.calcTransformMatrix();
});
this.editor.render();
},
"#cfg-data-aux-lidar-checkbox": (event)=>{
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableAuxLidar", checked); for (let item in this.clickableItems) {
return false; this.menu.querySelector(item).onclick = (event) => {
}, let ret = this.clickableItems[item](event);
if (ret) {
"#cfg-data-radar-checkbox": (event)=>{ this.hide();
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableRadar", checked);
return false;
},
"#cfg-data-filter-points-checkbox": (event)=>{
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enableFilterPoints", checked);
return false;
},
"#cfg-data-filter-points-z": (event)=>{
let z = event.currentTarget.value;
pointsGlobalConfig.setItem("filterPointsZ", z);
return false;
},
"#cfg-data-preload-checkbox": (event)=>{
let checked = event.currentTarget.checked;
pointsGlobalConfig.setItem("enablePreload", checked);
return false;
} }
}; event.stopPropagation();
};
}
ignoreItems = [ for (let item in this.changeableItems) {
"#cfg-point-size", this.menu.querySelector(item).onchange = (event) => {
"#cfg-point-brightness", let ret = this.changeableItems[item](event);
"#cfg-theme", if (ret) {
"#cfg-color-object", this.hide();
"#cfg-menu-batch-mode-inst-number",
"#cfg-hide-box",
"#cfg-calib-camera-LiDAR",
"#cfg-experimental",
"#cfg-data",
];
subMenus = [
"#cfg-experimental",
"#cfg-data",
];
constructor(button, wrapper, editor)
{
this.button = button;
this.wrapper = wrapper;
this.editor = editor;
this.editorCfg = editor.editorCfg;
this.dataCfg = editor.data.cfg;
this.menu = this.wrapper.querySelector("#config-menu");
this.wrapper.onclick = ()=>{
this.hide();
} }
this.button.onclick = (event)=>{ event.stopPropagation();
this.show(event.currentTarget); };
} }
for (let item in this.clickableItems) this.ignoreItems.forEach((item) => {
this.menu.querySelector(item).onclick = (event) => {
{ {
this.menu.querySelector(item).onclick = (event)=>{ event.stopPropagation();
let ret = this.clickableItems[item](event);
if (ret)
{
this.hide();
}
event.stopPropagation();
}
} }
};
for (let item in this.changeableItems) });
{
this.menu.querySelector(item).onchange = (event)=>{ this.subMenus.forEach((item) => {
let ret = this.changeableItems[item](event); this.menu.querySelector(item).onmouseenter = function (event) {
if (ret) if (this.timerId) {
{ clearTimeout(this.timerId);
this.hide(); this.timerId = null;
}
event.stopPropagation();
}
} }
this.ignoreItems.forEach(item=>{ event.currentTarget.querySelector(item + "-submenu").style.display =
this.menu.querySelector(item).onclick = (event)=>{ "inherit";
{ };
event.stopPropagation();
} this.menu.querySelector(item).onmouseleave = function (event) {
} let ui = event.currentTarget.querySelector(item + "-submenu");
}); this.timerId = setTimeout(() => {
ui.style.display = "none";
this.subMenus.forEach(item=>{ this.timerId = null;
this.menu.querySelector(item).onmouseenter = function(event){ }, 200);
if (this.timerId) };
{ });
clearTimeout(this.timerId);
this.timerId = null; this.menu.onclick = (event) => {
} event.stopPropagation();
};
event.currentTarget.querySelector(item +"-submenu").style.display="inherit";
}
this.menu.querySelector(item).onmouseleave = function(event){
let ui = event.currentTarget.querySelector(item +"-submenu");
this.timerId = setTimeout(()=>{
ui.style.display="none";
this.timerId = null;
},
200);
}
});
this.menu.onclick = (event)=>{
event.stopPropagation();
};
// init ui
this.menu.querySelector("#cfg-theme-select").value = pointsGlobalConfig.theme;
this.menu.querySelector("#cfg-data-aux-lidar-checkbox").checked = pointsGlobalConfig.enableAuxLidar;
this.menu.querySelector("#cfg-data-radar-checkbox").checked = pointsGlobalConfig.enableRadar;
this.menu.querySelector("#cfg-color-points-select").value = pointsGlobalConfig.color_points;
this.menu.querySelector("#cfg-coordinate-system-select").value = pointsGlobalConfig.coordinateSystem;
this.menu.querySelector("#cfg-batch-mode-inst-number").value = pointsGlobalConfig.batchModeInstNumber;
this.menu.querySelector("#cfg-data-filter-points-checkbox").checked = pointsGlobalConfig.enableFilterPoints;
this.menu.querySelector("#cfg-data-filter-points-z").value = pointsGlobalConfig.filterPointsZ;
this.menu.querySelector("#cfg-hide-id-checkbox").value = pointsGlobalConfig.hideId;
this.menu.querySelector("#cfg-hide-category-checkbox").value = pointsGlobalConfig.hideCategory;
this.menu.querySelector("#cfg-data-preload-checkbox").checked = pointsGlobalConfig.enablePreload;
this.menu.querySelector("#cfg-auto-rotate-xy-checkbox").checked = pointsGlobalConfig.enableAutoRotateXY;
this.menu.querySelector("#cfg-auto-update-interpolated-boxes-checkbox").checked = pointsGlobalConfig.autoUpdateInterpolatedBoxes;
}
show(target){
this.wrapper.style.display="inherit";
this.menu.style.right = "0px";
this.menu.style.top = target.offsetHeight + "px";
globalKeyDownManager.register((event)=>false, 'config');
}
hide(){
globalKeyDownManager.deregister('config');
this.wrapper.style.display="none";
}
// init ui
this.menu.querySelector("#cfg-theme-select").value =
pointsGlobalConfig.theme;
this.menu.querySelector("#cfg-data-aux-lidar-checkbox").checked =
pointsGlobalConfig.enableAuxLidar;
this.menu.querySelector("#cfg-data-radar-checkbox").checked =
pointsGlobalConfig.enableRadar;
this.menu.querySelector("#cfg-color-points-select").value =
pointsGlobalConfig.color_points;
this.menu.querySelector("#cfg-coordinate-system-select").value =
pointsGlobalConfig.coordinateSystem;
this.menu.querySelector("#cfg-batch-mode-inst-number").value =
pointsGlobalConfig.batchModeInstNumber;
this.menu.querySelector("#cfg-data-filter-points-checkbox").checked =
pointsGlobalConfig.enableFilterPoints;
this.menu.querySelector("#cfg-data-filter-points-z").value =
pointsGlobalConfig.filterPointsZ;
this.menu.querySelector("#cfg-hide-id-checkbox").value =
pointsGlobalConfig.hideId;
this.menu.querySelector("#cfg-hide-category-checkbox").value =
pointsGlobalConfig.hideCategory;
this.menu.querySelector("#cfg-data-preload-checkbox").checked =
pointsGlobalConfig.enablePreload;
this.menu.querySelector("#cfg-auto-rotate-xy-checkbox").checked =
pointsGlobalConfig.enableAutoRotateXY;
this.menu.querySelector(
"#cfg-auto-update-interpolated-boxes-checkbox"
).checked = pointsGlobalConfig.autoUpdateInterpolatedBoxes;
}
show(target) {
this.wrapper.style.display = "inherit";
this.menu.style.right = "0px";
this.menu.style.top = target.offsetHeight + "px";
globalKeyDownManager.register((event) => false, "config");
}
hide() {
globalKeyDownManager.deregister("config");
this.wrapper.style.display = "none";
}
} }
export { ConfigUi };
export {ConfigUi}

@ -1,199 +1,168 @@
import { globalKeyDownManager } from "./keydown_manager.js"; import { globalKeyDownManager } from "./keydown_manager.js";
class ContextMenu { class ContextMenu {
constructor(ui) constructor(ui) {
{ this.wrapperUi = ui;
this.wrapperUi = ui;
this.menus = {
this.menus = { world: ui.querySelector("#context-menu"),
world: ui.querySelector("#context-menu"), object: ui.querySelector("#object-context-menu"),
object: ui.querySelector("#object-context-menu"), boxEditor: ui.querySelector("#box-editor-context-menu"),
boxEditor: ui.querySelector("#box-editor-context-menu"), boxEditorManager: ui.querySelector("#box-editor-manager-context-menu"),
boxEditorManager: ui.querySelector("#box-editor-manager-context-menu"), playSubMenu: ui.querySelector("#play-submenu"),
playSubMenu: ui.querySelector("#play-submenu"), gotoSubMenu: ui.querySelector("#goto-submenu"),
gotoSubMenu: ui.querySelector("#goto-submenu"), fitSubMenu: ui.querySelector("#cm-fit-submenu"),
fitSubMenu: ui.querySelector("#cm-fit-submenu"), //thisSubMenu: ui.querySelector("#cm-this-submenu"),
//thisSubMenu: ui.querySelector("#cm-this-submenu"), };
};
for (let m in this.menus) {
for (let m in this.menus){ for (let i = 0; i < this.menus[m].children.length; i++) {
for (let i = 0; i < this.menus[m].children.length; i++) this.menus[m].children[i].onclick = (event) => {
{ //event.preventDefault();
this.menus[m].children[i].onclick = (event) => event.stopPropagation();
{
//event.preventDefault(); let ret = this.handler.handleContextMenuEvent(event);
event.stopPropagation(); if (ret) {
this.hide();
let ret = this.handler.handleContextMenuEvent(event); }
if (ret) };
{ }
this.hide();
}
}
}
}
let motherMenu = {
"#cm-goto": "#goto-submenu",
"#cm-new": "#new-submenu",
"#cm-play": "#play-submenu",
"#cm-fit": "#cm-fit-submenu",
//"#cm-this": "#cm-this-submenu",
};
for (let item in motherMenu)
{
let menu = ui.querySelector(item);
menu.onclick = (event)=>{
return false;
}
let self = this;
menu.onmouseenter = function(event){
if (this.timerId)
{
clearTimeout(this.timerId);
this.timerId = null;
}
let menu = event.currentTarget.querySelector(motherMenu[item]);
menu.style.display="inherit";
let motherMenuRect = event.currentTarget.getBoundingClientRect();
let posX = motherMenuRect.right;
let posY = motherMenuRect.bottom;
if (self.wrapperUi.clientHeight < posY + menu.clientHeight){
menu.style.bottom = "0%";
menu.style.top = "";
}
else{
menu.style.top = "0%";
menu.style.bottom = "";
}
if (self.wrapperUi.clientWidth < posX + menu.clientWidth){
menu.style.right = "100%";
menu.style.left = "";
}
else{
menu.style.left = "100%";
menu.style.right = "";
}
}
menu.onmouseleave = function(event){
let ui = event.currentTarget.querySelector(motherMenu[item]);
this.timerId = setTimeout(()=>{
ui.style.display="none";
this.timerId = null;
},
200);
}
}
this.wrapperUi.onclick = (event)=>{
this.hide();
event.preventDefault();
event.stopPropagation();
};
this.wrapperUi.oncontextmenu = (event)=>{
//event.currentTarget.style.display="none";
event.preventDefault();
event.stopPropagation();
};
} }
// install dynamic menu, like object new let motherMenu = {
installMenu(name, ui, funcHandler) "#cm-goto": "#goto-submenu",
{ "#cm-new": "#new-submenu",
this.menus[name] = ui; "#cm-play": "#play-submenu",
"#cm-fit": "#cm-fit-submenu",
for (let i = 0; i < ui.children.length; i++){ //"#cm-this": "#cm-this-submenu",
ui.children[i].onclick = (event) => };
{
//event.preventDefault(); for (let item in motherMenu) {
event.stopPropagation(); let menu = ui.querySelector(item);
menu.onclick = (event) => {
let ret = funcHandler(event); return false;
if (ret) };
{
this.hide(); let self = this;
} menu.onmouseenter = function (event) {
} if (this.timerId) {
clearTimeout(this.timerId);
this.timerId = null;
} }
}
hide() let menu = event.currentTarget.querySelector(motherMenu[item]);
{ menu.style.display = "inherit";
this.wrapperUi.style.display = "none";
globalKeyDownManager.deregister('context menu');
}
show(name, posX, posY, handler, funcSetPos) let motherMenuRect = event.currentTarget.getBoundingClientRect();
{ let posX = motherMenuRect.right;
this.handler = handler; let posY = motherMenuRect.bottom;
//hide all others if (self.wrapperUi.clientHeight < posY + menu.clientHeight) {
for (let m in this.menus) { menu.style.bottom = "0%";
if (m !== name) menu.style.top = "";
this.menus[m].style.display = 'none'; } else {
menu.style.top = "0%";
menu.style.bottom = "";
} }
// show if (self.wrapperUi.clientWidth < posX + menu.clientWidth) {
this.wrapperUi.style.display = "block"; menu.style.right = "100%";
menu.style.left = "";
} else {
menu.style.left = "100%";
menu.style.right = "";
}
};
menu.onmouseleave = function (event) {
let ui = event.currentTarget.querySelector(motherMenu[item]);
this.timerId = setTimeout(() => {
ui.style.display = "none";
this.timerId = null;
}, 200);
};
}
let menu = this.menus[name] this.wrapperUi.onclick = (event) => {
menu.style.display = "inherit"; this.hide();
event.preventDefault();
event.stopPropagation();
};
this.wrapperUi.oncontextmenu = (event) => {
//event.currentTarget.style.display="none";
event.preventDefault();
event.stopPropagation();
};
}
// install dynamic menu, like object new
installMenu(name, ui, funcHandler) {
this.menus[name] = ui;
for (let i = 0; i < ui.children.length; i++) {
ui.children[i].onclick = (event) => {
//event.preventDefault();
event.stopPropagation();
let ret = funcHandler(event);
if (ret) {
this.hide();
}
};
}
}
this.currentMenu = menu; hide() {
this.wrapperUi.style.display = "none";
globalKeyDownManager.deregister("context menu");
}
if (funcSetPos) show(name, posX, posY, handler, funcSetPos) {
{ this.handler = handler;
funcSetPos(menu);
}
else{
if (this.wrapperUi.clientHeight < posY + menu.clientHeight){
menu.style.top = (this.wrapperUi.clientHeight - menu.clientHeight) + "px";
}
else{
menu.style.top = posY+"px";
}
if (this.wrapperUi.clientWidth < posX + menu.clientWidth){
menu.style.left = (this.wrapperUi.clientWidth - menu.clientWidth) + "px";
}
else{
menu.style.left = posX+"px";
}
}
//hide all others
for (let m in this.menus) {
if (m !== name) this.menus[m].style.display = "none";
}
globalKeyDownManager.register((event)=>{ // show
this.wrapperUi.style.display = "block";
let menuRect = this.currentMenu.getBoundingClientRect(); let menu = this.menus[name];
let ret = this.handler.handleContextMenuKeydownEvent(event, menu.style.display = "inherit";
{x: menuRect.left, y: menuRect.top});
if (!ret)
{
this.hide();
}
return false; // false means don't propogate this.currentMenu = menu;
}, 'context menu');
}
if (funcSetPos) {
funcSetPos(menu);
} else {
if (this.wrapperUi.clientHeight < posY + menu.clientHeight) {
menu.style.top = this.wrapperUi.clientHeight - menu.clientHeight + "px";
} else {
menu.style.top = posY + "px";
}
}; if (this.wrapperUi.clientWidth < posX + menu.clientWidth) {
menu.style.left = this.wrapperUi.clientWidth - menu.clientWidth + "px";
} else {
menu.style.left = posX + "px";
}
}
export {ContextMenu}; globalKeyDownManager.register((event) => {
let menuRect = this.currentMenu.getBoundingClientRect();
let ret = this.handler.handleContextMenuKeydownEvent(event, {
x: menuRect.left,
y: menuRect.top,
});
if (!ret) {
this.hide();
}
return false; // false means don't propogate
}, "context menu");
}
}
export { ContextMenu };

@ -1,64 +1,54 @@
import { PopupDialog } from "./popup_dialog.js"; import { PopupDialog } from "./popup_dialog.js";
class CropScene extends PopupDialog {
class CropScene extends PopupDialog{ constructor(ui, editor) {
super(ui);
this.ui = ui; //wrapper
this.editor = editor;
constructor(ui, editor)
{ this.contentUi = this.ui.querySelector("#content");
super(ui);
let self = this;
this.ui = ui; //wrapper
this.editor = editor; this.ui.querySelector("#btn-generate").onclick = (event) => {
var xhr = new XMLHttpRequest();
this.contentUi = this.ui.querySelector("#content"); // we defined the xhr
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
let self = this;
if (this.status == 200) {
this.ui.querySelector("#btn-generate").onclick = (event)=>{ let ret = JSON.parse(this.responseText);
var xhr = new XMLHttpRequest(); self.contentUi.querySelector("#log").innerText = JSON.stringify(
// we defined the xhr ret,
xhr.onreadystatechange = function () { null,
if (this.readyState != 4) return; "\t"
);
if (this.status == 200) {
let ret = JSON.parse(this.responseText);
self.contentUi.querySelector("#log").innerText = JSON.stringify(ret, null,"\t");
}
};
xhr.open('POST', "/cropscene", true);
let para={
rawSceneId: this.editor.data.world.frameInfo.scene,
//id: this.ui.querySelector("#scene-id").value,
desc: this.ui.querySelector("#scene-desc").value,
startTime: this.ui.querySelector("#scene-start-time").value,
seconds: this.ui.querySelector("#scene-seconds").value
};
xhr.send(JSON.stringify(para));
} }
} };
xhr.open("POST", "/cropscene", true);
show() let para = {
{ rawSceneId: this.editor.data.world.frameInfo.scene,
//id: this.ui.querySelector("#scene-id").value,
let frameInfo = this.editor.data.world.frameInfo; desc: this.ui.querySelector("#scene-desc").value,
this.ui.querySelector("#scene-start-time").value=parseInt(frameInfo.frame)-10; startTime: this.ui.querySelector("#scene-start-time").value,
this.ui.querySelector("#scene-seconds").value=20; seconds: this.ui.querySelector("#scene-seconds").value,
this.contentUi.querySelector("#log").innerText = ""; };
super.show();
} xhr.send(JSON.stringify(para));
};
}
show() {
let frameInfo = this.editor.data.world.frameInfo;
this.ui.querySelector("#scene-start-time").value =
parseInt(frameInfo.frame) - 10;
this.ui.querySelector("#scene-seconds").value = 20;
this.contentUi.querySelector("#log").innerText = "";
super.show();
}
} }
export { CropScene };
export {CropScene};

@ -1,468 +1,436 @@
import { World } from "./world.js";
import { Debug } from "./debug.js";
import {World} from "./world.js"; import { logger } from "./log.js";
import {Debug} from "./debug.js";
import {logger} from "./log.js" class Data {
constructor(cfg) {
class Data this.cfg = cfg;
{ }
constructor(cfg) async readSceneList() {
{ const req = new Request("/get_all_scene_desc");
this.cfg = cfg; let init = {
method: "GET",
} //body: JSON.stringify({"points": data})
async readSceneList()
{
const req = new Request("/get_all_scene_desc");
let init = {
method: 'GET',
//body: JSON.stringify({"points": data})
};
// we defined the xhr
return fetch(req, init)
.then(response=>{
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}else{
return response.json();
}
})
.then(ret=>
{
console.log(ret);
this.sceneDescList = ret;
return ret;
})
.catch(reject=>{
console.log("error read scene list!");
});
}
async init(){
await this.readSceneList();
}
// multiple world support
// place world by a offset so they don't overlap
dbg = new Debug();
worldGap=1000.0;
worldList=[];
MaxWorldNumber=80;
createWorldIndex = 0; // this index shall not repeat, so it increases permanently
async getWorld(sceneName, frame, on_preload_finished){
// find in list
if (!this.meta[sceneName]){
await this.readSceneMetaData(sceneName)
}
if (!this.meta[sceneName])
{
logger.log("load scene failed", sceneName);
return null;
}
let world = this.worldList.find((w)=>{
return w.frameInfo.scene == sceneName && w.frameInfo.frame == frame;
})
if (world) // found!
return world;
world = this._createWorld(sceneName, frame, on_preload_finished);
return world;
};
_createWorld(sceneName, frame, on_preload_finished){
let [x,y,z] = this.allocateOffset();
console.log("create world",x,y,z);
let world = new World(this, sceneName, frame, [this.worldGap*x, this.worldGap*y, this.worldGap*z], on_preload_finished);
world.offsetIndex = [x,y,z];
this.createWorldIndex++;
this.worldList.push(world);
return world;
}; };
// we defined the xhr
findWorld(sceneName, frameIndex){
let world = this.worldList.find((w)=>{ return fetch(req, init)
return w.frameInfo.scene == sceneName && w.frameInfo.frame_index == frameIndex; .then((response) => {
}) if (!response.ok) {
if (world) // found! throw new Error(`HTTP error! status: ${response.status}`);
return world; } else {
else return response.json();
return null;
};
offsetList = [[0,0,0]];
lastSeedOffset = [0,0,0];
offsetsAliveCount = 0;
allocateOffset()
{
// we need to make sure the first frame loaded in a scene
// got to locate in [0,0,0]
if (this.offsetsAliveCount == 0)
{
//reset offsets.
this.offsetList = [[0,0,0]];
this.lastSeedOffset = [0,0,0];
}
if (this.offsetList.length == 0)
{
let [x,y,z] = this.lastSeedOffset;
if (x == y)
{
x = x+1;
y = 0;
}
else
{
y = y+1;
}
this.lastSeedOffset = [x, y, 0];
this.offsetList.push([x,y,0]);
if (x != 0) this.offsetList.push([-x,y,0]);
if (y != 0) this.offsetList.push([x,-y,0]);
if (x * y != 0) this.offsetList.push([-x,-y,0]);
if (x != y) {
this.offsetList.push([y,x,0]);
if (y != 0) this.offsetList.push([-y,x,0]);
if (x != 0) this.offsetList.push([y,-x,0]);
if (x * y != 0) this.offsetList.push([-y,-x,0]);
}
} }
})
let ret = this.offsetList.pop(); .then((ret) => {
this.offsetsAliveCount++; console.log(ret);
this.sceneDescList = ret;
return ret; return ret;
}; })
.catch((reject) => {
console.log("error read scene list!");
});
}
async init() {
await this.readSceneList();
}
// multiple world support
// place world by a offset so they don't overlap
dbg = new Debug();
worldGap = 1000.0;
worldList = [];
MaxWorldNumber = 80;
createWorldIndex = 0; // this index shall not repeat, so it increases permanently
async getWorld(sceneName, frame, on_preload_finished) {
// find in list
if (!this.meta[sceneName]) {
await this.readSceneMetaData(sceneName);
}
returnOffset(offset) if (!this.meta[sceneName]) {
{ logger.log("load scene failed", sceneName);
this.offsetList.push(offset); return null;
this.offsetsAliveCount--; }
};
deleteDistantWorlds(world){ let world = this.worldList.find((w) => {
let currentWorldIndex = world.frameInfo.frame_index; return w.frameInfo.scene == sceneName && w.frameInfo.frame == frame;
});
let disposable = (w)=>{ if (world)
let distant = Math.abs(w.frameInfo.frame_index - currentWorldIndex)>this.MaxWorldNumber; // found!
let active = w.everythingDone; return world;
if (w.annotation.modified)
{ world = this._createWorld(sceneName, frame, on_preload_finished);
console.log("deleting world not saved. stop.");
} return world;
}
return distant && !active && !w.annotation.modified;
} _createWorld(sceneName, frame, on_preload_finished) {
let [x, y, z] = this.allocateOffset();
console.log("create world", x, y, z);
let world = new World(
this,
sceneName,
frame,
[this.worldGap * x, this.worldGap * y, this.worldGap * z],
on_preload_finished
);
world.offsetIndex = [x, y, z];
this.createWorldIndex++;
this.worldList.push(world);
return world;
}
findWorld(sceneName, frameIndex) {
let world = this.worldList.find((w) => {
return (
w.frameInfo.scene == sceneName && w.frameInfo.frame_index == frameIndex
);
});
if (world)
// found!
return world;
else return null;
}
offsetList = [[0, 0, 0]];
lastSeedOffset = [0, 0, 0];
offsetsAliveCount = 0;
allocateOffset() {
// we need to make sure the first frame loaded in a scene
// got to locate in [0,0,0]
if (this.offsetsAliveCount == 0) {
//reset offsets.
this.offsetList = [[0, 0, 0]];
this.lastSeedOffset = [0, 0, 0];
}
let distantWorldList = this.worldList.filter(w=>disposable(w)); if (this.offsetList.length == 0) {
let [x, y, z] = this.lastSeedOffset;
distantWorldList.forEach(w=>{ if (x == y) {
this.returnOffset(w.offsetIndex); x = x + 1;
w.deleteAll(); y = 0;
}); } else {
y = y + 1;
}
this.lastSeedOffset = [x, y, 0];
this.worldList = this.worldList.filter(w=>!disposable(w));
}; this.offsetList.push([x, y, 0]);
deleteOtherWorldsExcept=function(keepScene){ if (x != 0) this.offsetList.push([-x, y, 0]);
// release resources if scene changed if (y != 0) this.offsetList.push([x, -y, 0]);
this.worldList.forEach(w=>{ if (x * y != 0) this.offsetList.push([-x, -y, 0]);
if (w.frameInfo.scene != keepScene){
this.returnOffset(w.offsetIndex);
w.deleteAll();
this.removeRefEgoPoseOfScene(w.frameInfo.scene);
}
})
this.worldList = this.worldList.filter(w=>w.frameInfo.scene==keepScene);
};
refEgoPose={}; if (x != y) {
getRefEgoPose(sceneName, currentPose) this.offsetList.push([y, x, 0]);
{
if (this.refEgoPose[sceneName]){
return this.refEgoPose[sceneName];
}
else{
this.refEgoPose[sceneName] = currentPose;
return currentPose;
}
}
removeRefEgoPoseOfScene(sceneName) if (y != 0) this.offsetList.push([-y, x, 0]);
{ if (x != 0) this.offsetList.push([y, -x, 0]);
if (this.refEgoPose[sceneName]) if (x * y != 0) this.offsetList.push([-y, -x, 0]);
delete this.refEgoPose[sceneName]; }
} }
forcePreloadScene(sceneName, currentWorld){ let ret = this.offsetList.pop();
//this.deleteOtherWorldsExcept(sceneName); this.offsetsAliveCount++;
let meta = currentWorld.sceneMeta;
let currentWorldIndex = currentWorld.frameInfo.frame_index; return ret;
let startIndex = Math.max(0, currentWorldIndex - this.MaxWorldNumber/2); }
let endIndex = Math.min(meta.frames.length, startIndex + this.MaxWorldNumber);
this._doPreload(sceneName, startIndex, endIndex); returnOffset(offset) {
this.offsetList.push(offset);
logger.log(`${endIndex - startIndex} frames created`); this.offsetsAliveCount--;
} }
preloadScene(sceneName, currentWorld){ deleteDistantWorlds(world) {
let currentWorldIndex = world.frameInfo.frame_index;
// clean other scenes. let disposable = (w) => {
this.deleteOtherWorldsExcept(sceneName); let distant =
this.deleteDistantWorlds(currentWorld); Math.abs(w.frameInfo.frame_index - currentWorldIndex) >
this.MaxWorldNumber;
let active = w.everythingDone;
if (w.annotation.modified) {
console.log("deleting world not saved. stop.");
}
if (!this.cfg.enablePreload) return distant && !active && !w.annotation.modified;
return;
this.forcePreloadScene(sceneName, currentWorld);
}; };
_doPreload(sceneName, startIndex, endIndex) let distantWorldList = this.worldList.filter((w) => disposable(w));
{
let meta = this.getMetaBySceneName(sceneName); distantWorldList.forEach((w) => {
this.returnOffset(w.offsetIndex);
let numLoaded = 0; w.deleteAll();
let _need_create = (frame)=>{ });
let world = this.worldList.find((w)=>{
return w.frameInfo.scene == sceneName && w.frameInfo.frame == frame; this.worldList = this.worldList.filter((w) => !disposable(w));
}) }
return !world; deleteOtherWorldsExcept = function (keepScene) {
} // release resources if scene changed
this.worldList.forEach((w) => {
let _do_create = (frame)=>{ if (w.frameInfo.scene != keepScene) {
this._createWorld(sceneName, frame); this.returnOffset(w.offsetIndex);
numLoaded++; w.deleteAll();
};
this.removeRefEgoPoseOfScene(w.frameInfo.scene);
let pendingFrames = meta.frames.slice(startIndex, endIndex).filter(_need_create); }
});
logger.log(`preload ${meta.scene} ${pendingFrames}`); this.worldList = this.worldList.filter(
// if (numLoaded > 0){ (w) => w.frameInfo.scene == keepScene
// meta.frames.slice(endIndex, Math.min(endIndex+5, meta.frames.length)).forEach(_do_create); );
// meta.frames.slice(Math.max(0, startIndex-5), startIndex).forEach(_do_create); };
// }
refEgoPose = {};
pendingFrames.forEach(_do_create); getRefEgoPose(sceneName, currentPose) {
if (this.refEgoPose[sceneName]) {
return this.refEgoPose[sceneName];
} else {
this.refEgoPose[sceneName] = currentPose;
return currentPose;
} }
}
removeRefEgoPoseOfScene(sceneName) {
if (this.refEgoPose[sceneName]) delete this.refEgoPose[sceneName];
}
reloadAllAnnotation=function(done){ forcePreloadScene(sceneName, currentWorld) {
this.worldList.forEach(w=>w.reloadAnnotation(done)); //this.deleteOtherWorldsExcept(sceneName);
}; let meta = currentWorld.sceneMeta;
onAnnotationUpdatedByOthers(scene, frames){
frames.forEach(f=>{
let world = this.worldList.find(w=>(w.frameInfo.scene==scene && w.frameInfo.frame==f));
if (world)
world.annotation.reloadAnnotation();
})
};
webglScene = null; let currentWorldIndex = currentWorld.frameInfo.frame_index;
set_webglScene=function(scene, mainScene){ let startIndex = Math.max(0, currentWorldIndex - this.MaxWorldNumber / 2);
this.webglScene = scene; let endIndex = Math.min(
this.webglMainScene = mainScene; meta.frames.length,
}; startIndex + this.MaxWorldNumber
);
scale_point_size(v){
this.cfg.point_size *= v;
// if (this.world){
// this.world.lidar.set_point_size(this.cfg.point_size);
// }
this.worldList.forEach(w=>{
w.lidar.set_point_size(this.cfg.point_size);
});
};
scale_point_brightness(v){ this._doPreload(sceneName, startIndex, endIndex);
this.cfg.point_brightness *= v;
// if (this.world){ logger.log(`${endIndex - startIndex} frames created`);
// this.world.lidar.recolor_all_points(); }
// }
this.worldList.forEach(w=>{ preloadScene(sceneName, currentWorld) {
w.lidar.recolor_all_points(); // clean other scenes.
}) this.deleteOtherWorldsExcept(sceneName);
}; this.deleteDistantWorlds(currentWorld);
set_box_opacity(opacity){ if (!this.cfg.enablePreload) return;
this.cfg.box_opacity = opacity;
this.worldList.forEach(w=>{ this.forcePreloadScene(sceneName, currentWorld);
w.annotation.set_box_opacity(this.cfg.box_opacity); }
});
};
toggle_background(){ _doPreload(sceneName, startIndex, endIndex) {
this.cfg.show_background = !this.cfg.show_background; let meta = this.getMetaBySceneName(sceneName);
if (this.cfg.show_background){ let numLoaded = 0;
this.world.lidar.cancel_highlight(); let _need_create = (frame) => {
} let world = this.worldList.find((w) => {
else{ return w.frameInfo.scene == sceneName && w.frameInfo.frame == frame;
this.world.lidar.hide_background(); });
}
};
set_obj_color_scheme(scheme){ return !world;
pointsGlobalConfig.color_obj = scheme;
// if (pointsGlobalConfig.color_obj != "no"){
// this.world.lidar.color_points();
// } else {
// this.world.lidar.set_points_color({
// x: this.cfg.point_brightness,
// y: this.cfg.point_brightness,
// z: this.cfg.point_brightness,
// });
// }
// this.world.lidar.update_points_color();
// this.world.annotation.color_boxes();
// toto: move to world
this.worldList.forEach(w=>{
if (pointsGlobalConfig.color_obj == "no")
{
w.lidar.color_points();
}
else
{
w.lidar.color_objects();
}
w.lidar.update_points_color();
w.annotation.color_boxes();
})
}; };
// active_camera_name = ""; let _do_create = (frame) => {
this._createWorld(sceneName, frame);
// // return null means not changed. numLoaded++;
// set_active_image(name){
// if (name === this.active_camera_name){
// return null;
// }
// this.active_camera_name = name;
// if (this.world){
// this.world.cameras.activate(name);
// }
// this.worldList.forEach(w=>w.cameras.activate(name));
// return name;
// };
world=null;
// this.future_world_buffer = [];
// this.put_world_into_buffer= function(world){
// this.future_world_buffer.push(world);
// };
// this.reset_world_buffer= function(){
// this.future_world_buffer=[];
// };
// this.activateMultiWorld=function(world, on_finished){
// world.activate(this.webglScene,
// null, //don't destroy old world
// on_finished);
// this.worldList.push(world);
// };
activate_world= function(world, on_finished, dontDestroyOldWorld){
if (dontDestroyOldWorld){
world.activate(this.webglScene, null, on_finished);
}
else{
var old_world = this.world; // current world, should we get current world later?
this.world = world; // swich when everything is ready. otherwise data.world is half-baked, causing mysterious problems.
world.activate(this.webglMainScene,
function(){
if (old_world)
old_world.unload();
},
on_finished);
}
}; };
let pendingFrames = meta.frames
.slice(startIndex, endIndex)
.filter(_need_create);
logger.log(`preload ${meta.scene} ${pendingFrames}`);
// if (numLoaded > 0){
// meta.frames.slice(endIndex, Math.min(endIndex+5, meta.frames.length)).forEach(_do_create);
// meta.frames.slice(Math.max(0, startIndex-5), startIndex).forEach(_do_create);
// }
pendingFrames.forEach(_do_create);
}
reloadAllAnnotation = function (done) {
this.worldList.forEach((w) => w.reloadAnnotation(done));
};
onAnnotationUpdatedByOthers(scene, frames) {
frames.forEach((f) => {
let world = this.worldList.find(
(w) => w.frameInfo.scene == scene && w.frameInfo.frame == f
);
if (world) world.annotation.reloadAnnotation();
});
}
webglScene = null;
set_webglScene = function (scene, mainScene) {
this.webglScene = scene;
this.webglMainScene = mainScene;
};
scale_point_size(v) {
this.cfg.point_size *= v;
// if (this.world){
// this.world.lidar.set_point_size(this.cfg.point_size);
// }
this.worldList.forEach((w) => {
w.lidar.set_point_size(this.cfg.point_size);
});
}
scale_point_brightness(v) {
this.cfg.point_brightness *= v;
// if (this.world){
// this.world.lidar.recolor_all_points();
// }
this.worldList.forEach((w) => {
w.lidar.recolor_all_points();
});
}
set_box_opacity(opacity) {
this.cfg.box_opacity = opacity;
this.worldList.forEach((w) => {
w.annotation.set_box_opacity(this.cfg.box_opacity);
});
}
toggle_background() {
this.cfg.show_background = !this.cfg.show_background;
if (this.cfg.show_background) {
this.world.lidar.cancel_highlight();
} else {
this.world.lidar.hide_background();
}
}
set_obj_color_scheme(scheme) {
pointsGlobalConfig.color_obj = scheme;
// if (pointsGlobalConfig.color_obj != "no"){
// this.world.lidar.color_points();
// } else {
// this.world.lidar.set_points_color({
// x: this.cfg.point_brightness,
// y: this.cfg.point_brightness,
// z: this.cfg.point_brightness,
// });
// }
// this.world.lidar.update_points_color();
// this.world.annotation.color_boxes();
// toto: move to world
this.worldList.forEach((w) => {
if (pointsGlobalConfig.color_obj == "no") {
w.lidar.color_points();
} else {
w.lidar.color_objects();
}
w.lidar.update_points_color();
w.annotation.color_boxes();
});
}
// active_camera_name = "";
// // return null means not changed.
// set_active_image(name){
// if (name === this.active_camera_name){
// return null;
// }
// this.active_camera_name = name;
// if (this.world){
// this.world.cameras.activate(name);
// }
// this.worldList.forEach(w=>w.cameras.activate(name));
// return name;
// };
world = null;
// this.future_world_buffer = [];
// this.put_world_into_buffer= function(world){
// this.future_world_buffer.push(world);
// };
// this.reset_world_buffer= function(){
// this.future_world_buffer=[];
// };
// this.activateMultiWorld=function(world, on_finished){
// world.activate(this.webglScene,
// null, //don't destroy old world
// on_finished);
// this.worldList.push(world);
// };
activate_world = function (world, on_finished, dontDestroyOldWorld) {
if (dontDestroyOldWorld) {
world.activate(this.webglScene, null, on_finished);
} else {
var old_world = this.world; // current world, should we get current world later?
this.world = world; // swich when everything is ready. otherwise data.world is half-baked, causing mysterious problems.
world.activate(
this.webglMainScene,
function () {
if (old_world) old_world.unload();
},
on_finished
);
}
};
meta = {}; //meta data meta = {}; //meta data
getMetaBySceneName = (sceneName)=>{
return this.meta[sceneName];
};
getMetaBySceneName = (sceneName) => {
return this.meta[sceneName];
};
get_current_world_scene_meta(){ get_current_world_scene_meta() {
return this.getMetaBySceneName(this.world.frameInfo.scene); return this.getMetaBySceneName(this.world.frameInfo.scene);
}; }
readSceneMetaData(sceneName) {
let self = this;
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
readSceneMetaData(sceneName) xhr.onreadystatechange = function () {
{ if (this.readyState != 4) return;
let self =this;
return new Promise(function(resolve, reject){
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState != 4)
return;
if (this.status == 200) {
let sceneMeta = JSON.parse(this.responseText);
self.meta[sceneName] = sceneMeta;
resolve(sceneMeta);
}
};
xhr.open('GET', `/scenemeta?scene=${sceneName}`, true);
xhr.send();
});
}
};
if (this.status == 200) {
let sceneMeta = JSON.parse(this.responseText);
self.meta[sceneName] = sceneMeta;
resolve(sceneMeta);
}
};
export {Data}; xhr.open("GET", `/scenemeta?scene=${sceneName}`, true);
xhr.send();
});
}
}
export { Data };

@ -1,18 +1,17 @@
function Debug(){ function Debug() {
this.res_count = 0; this.res_count = 0;
this.alloc = function(){ this.alloc = function () {
this.res_count++; this.res_count++;
}; };
this.free = function(){ this.free = function () {
this.res_count--; this.res_count--;
}; };
this.dump = function(){ this.dump = function () {
console.log(`number of resources: ${this.res_count}`); console.log(`number of resources: ${this.res_count}`);
} };
}; }
export {Debug};
export { Debug };

File diff suppressed because it is too large Load Diff

@ -1,78 +1,65 @@
class EgoPose {
constructor(sceneMeta, world, frameInfo) {
this.world = world;
this.data = this.world.data;
class EgoPose this.sceneMeta = sceneMeta;
{ }
constructor(sceneMeta, world, frameInfo)
{ preload(on_preload_finished) {
this.world = world; this.on_preload_finished = on_preload_finished;
this.data = this.world.data; this.load_ego_pose();
this.sceneMeta = sceneMeta; }
}
load_ego_pose() {
var xhr = new XMLHttpRequest();
preload(on_preload_finished) // we defined the xhr
{ var _self = this;
this.on_preload_finished = on_preload_finished; xhr.onreadystatechange = function () {
this.load_ego_pose(); if (this.readyState != 4) return;
};
if (this.status == 200) {
let egoPose = JSON.parse(this.responseText);
load_ego_pose(){ _self.egoPose = egoPose;
}
var xhr = new XMLHttpRequest();
// we defined the xhr console.log(_self.world.frameInfo.frame, "egopose", "loaded");
var _self = this; _self.preloaded = true;
xhr.onreadystatechange = function () {
if (this.readyState != 4) return; if (_self.on_preload_finished) {
_self.on_preload_finished();
if (this.status == 200) { }
let egoPose = JSON.parse(this.responseText); if (_self.go_cmd_received) {
_self.egoPose = egoPose; _self.go(this.webglScene, this.on_go_finished);
} }
console.log(_self.world.frameInfo.frame, "egopose", "loaded"); // end of state change: it can be after some time (async)
_self.preloaded = true;
if (_self.on_preload_finished){
_self.on_preload_finished();
}
if (_self.go_cmd_received){
_self.go(this.webglScene, this.on_go_finished);
}
// end of state change: it can be after some time (async)
};
xhr.open('GET', "/load_ego_pose"+"?scene="+this.world.frameInfo.scene+"&frame="+this.world.frameInfo.frame, true);
xhr.send();
}; };
xhr.open(
"GET",
"/load_ego_pose" +
"?scene=" +
this.world.frameInfo.scene +
"&frame=" +
this.world.frameInfo.frame,
true
);
xhr.send();
}
go_cmd_received = false;
on_go_finished = null;
go(webglScene, on_go_finished) {
if (this.preloaded) {
if (on_go_finished) on_go_finished();
} else {
this.go_cmd_received = true;
this.on_go_finished = on_go_finished;
}
}
go_cmd_received = false; unload() {}
on_go_finished = null;
go(webglScene, on_go_finished)
{
if (this.preloaded){
if (on_go_finished)
on_go_finished();
} else {
this.go_cmd_received = true;
this.on_go_finished = on_go_finished;
}
};
unload()
{
};
} }
export { EgoPose };
export{EgoPose}

@ -1,30 +1,27 @@
import { logger } from "./log.js"; import { logger } from "./log.js";
function checkScene(scene) {
const req = new Request(`/checkscene?scene=${scene}`);
let init = {
method: "GET",
//body: JSON.stringify({"points": data})
};
// we defined the xhr
function checkScene(scene) return fetch(req, init)
{ .then((response) => {
const req = new Request(`/checkscene?scene=${scene}`); if (!response.ok) {
let init = { throw new Error(`HTTP error! status: ${response.status}`);
method: 'GET', } else {
//body: JSON.stringify({"points": data}) return response.json();
}; }
// we defined the xhr
return fetch(req, init)
.then(response=>{
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}else{
return response.json();
}
}) })
.then(ret=> .then((ret) => {
{ logger.setErrorsContent(ret);
logger.setErrorsContent(ret);
}) })
.catch(reject=>{ .catch((reject) => {
console.log("error check scene!"); console.log("error check scene!");
}); });
} }
export {checkScene} export { checkScene };

File diff suppressed because it is too large Load Diff

@ -1,156 +1,192 @@
import { CubeRefractionMapping } from "./lib/three.module.js"; import { CubeRefractionMapping } from "./lib/three.module.js";
import {saveWorldList} from "./save.js" import { saveWorldList } from "./save.js";
var Header=function(ui, data, cfg, onSceneChanged, onFrameChanged, onObjectSelected, onCameraChanged){ var Header = function (
ui,
this.ui = ui; data,
this.data = data; cfg,
this.cfg = cfg; onSceneChanged,
this.boxUi = ui.querySelector("#box"); onFrameChanged,
this.refObjUi = ui.querySelector("#ref-obj"); onObjectSelected,
this.sceneSelectorUi = ui.querySelector("#scene-selector"); onCameraChanged
this.frameSelectorUi = ui.querySelector("#frame-selector"); ) {
this.objectSelectorUi = ui.querySelector("#object-selector"); this.ui = ui;
this.cameraSelectorUi = ui.querySelector("#camera-selector"); this.data = data;
this.changedMarkUi = ui.querySelector("#changed-mark"); this.cfg = cfg;
this.boxUi = ui.querySelector("#box");
this.onSceneChanged = onSceneChanged; this.refObjUi = ui.querySelector("#ref-obj");
this.onFrameChanged = onFrameChanged; this.sceneSelectorUi = ui.querySelector("#scene-selector");
this.onObjectSelected = onObjectSelected; this.frameSelectorUi = ui.querySelector("#frame-selector");
this.onCameraChanged = onCameraChanged; this.objectSelectorUi = ui.querySelector("#object-selector");
this.cameraSelectorUi = ui.querySelector("#camera-selector");
this.changedMarkUi = ui.querySelector("#changed-mark");
if (cfg.disableSceneSelector){
this.sceneSelectorUi.style.display="none"; this.onSceneChanged = onSceneChanged;
} this.onFrameChanged = onFrameChanged;
this.onObjectSelected = onObjectSelected;
if (cfg.disableFrameSelector){ this.onCameraChanged = onCameraChanged;
this.frameSelectorUi.style.display="none";
} if (cfg.disableSceneSelector) {
this.sceneSelectorUi.style.display = "none";
if (cfg.disableCameraSelector){ }
this.cameraSelectorUi.style.display="none";
} if (cfg.disableFrameSelector) {
this.frameSelectorUi.style.display = "none";
// update scene selector ui }
if (cfg.disableCameraSelector) {
this.cameraSelectorUi.style.display = "none";
}
this.updateSceneList = function(sceneDescList){
let scene_selector_str = "<option>--scene--</option>"; // update scene selector ui
for (let scene in sceneDescList)
{ this.updateSceneList = function (sceneDescList) {
if (data.sceneDescList[scene]) let scene_selector_str = "<option>--scene--</option>";
scene_selector_str += "<option value="+scene +">"+scene + " - " +data.sceneDescList[scene].scene + "</option>"; for (let scene in sceneDescList) {
else if (data.sceneDescList[scene])
scene_selector_str += "<option value="+scene +">"+scene+ "</option>"; scene_selector_str +=
} "<option value=" +
scene +
this.ui.querySelector("#scene-selector").innerHTML = scene_selector_str; ">" +
} scene +
" - " +
this.updateSceneList(this.data.sceneDescList); data.sceneDescList[scene].scene +
"</option>";
this.ui.querySelector("#btn-reload-scene-list").onclick = (event)=>{ else
let curentValue = this.sceneSelectorUi.value; scene_selector_str +=
"<option value=" + scene + ">" + scene + "</option>";
this.data.readSceneList().then((sceneDescList=>{
this.updateSceneList(sceneDescList);
this.sceneSelectorUi.value = curentValue;
}))
}
this.sceneSelectorUi.onchange = (e)=>{this.onSceneChanged(e);};
this.objectSelectorUi.onchange = (e)=>{this.onObjectSelected(e);};
this.frameSelectorUi.onchange = (e)=>{this.onFrameChanged(e);};
this.cameraSelectorUi.onchange = (e)=>{this.onCameraChanged(e);};
this.setObject = function(id)
{
this.objectSelectorUi.value = id;
} }
this.clear_box_info = function(){ this.ui.querySelector("#scene-selector").innerHTML = scene_selector_str;
this.boxUi.innerHTML = ''; };
};
this.updateSceneList(this.data.sceneDescList);
this.update_box_info = function(box){
var scale = box.scale; this.ui.querySelector("#btn-reload-scene-list").onclick = (event) => {
var pos = box.position; let curentValue = this.sceneSelectorUi.value;
var rotation = box.rotation;
var points_number = box.world.lidar.get_box_points_number(box); this.data.readSceneList().then((sceneDescList) => {
let distance = Math.sqrt(pos.x*pos.x + pos.y*pos.y).toFixed(2); this.updateSceneList(sceneDescList);
this.sceneSelectorUi.value = curentValue;
this.boxUi.innerHTML = "<span>" + box.obj_type +"-"+box.obj_track_id + });
(box.annotator? ("</span> | <span title='annotator'>" + box.annotator) : "") + };
"</span> | <span title='distance'>" + distance +
"</span> | <span title='position'>"+pos.x.toFixed(2) +" "+pos.y.toFixed(2) + " " + pos.z.toFixed(2) + this.sceneSelectorUi.onchange = (e) => {
"</span> | <span title='scale'>" +scale.x.toFixed(2) +" "+scale.y.toFixed(2) + " " + scale.z.toFixed(2) + this.onSceneChanged(e);
"</span> | <span title='rotation'>" + };
(rotation.x*180/Math.PI).toFixed(2)+" "+(rotation.y*180/Math.PI).toFixed(2)+" "+(rotation.z*180/Math.PI).toFixed(2)+ this.objectSelectorUi.onchange = (e) => {
"</span> | <span title = 'points'>" + this.onObjectSelected(e);
points_number + "</span> "; };
if (box.follows){ this.frameSelectorUi.onchange = (e) => {
this.boxUi.innerHTML += "| F:"+box.follows.obj_track_id; this.onFrameChanged(e);
} };
}, this.cameraSelectorUi.onchange = (e) => {
this.onCameraChanged(e);
this.set_ref_obj = function(marked_object){ };
this.refObjUi.innerHTML="| Ref: "+marked_object.scene+"/"+marked_object.frame+": "+marked_object.ann.obj_type+"-"+marked_object.ann.obj_id;
}, this.setObject = function (id) {
this.objectSelectorUi.value = id;
this.set_frame_info =function(scene, frame, on_scene_changed){ };
if (this.sceneSelectorUi.value != scene){ this.clear_box_info = function () {
this.sceneSelectorUi.value = scene; this.boxUi.innerHTML = "";
on_scene_changed(scene); };
}
(this.update_box_info = function (box) {
this.frameSelectorUi.value = frame; var scale = box.scale;
}, var pos = box.position;
var rotation = box.rotation;
this.clear_frame_info = function(scene, frame){ var points_number = box.world.lidar.get_box_points_number(box);
let distance = Math.sqrt(pos.x * pos.x + pos.y * pos.y).toFixed(2);
},
this.boxUi.innerHTML =
this.updateModifiedStatus = function(){ "<span>" +
let frames = this.data.worldList.filter(w=>w.annotation.modified); box.obj_type +
if (frames.length > 0) "-" +
{ box.obj_track_id +
this.ui.querySelector("#changed-mark").className = 'ui-button alarm-mark'; (box.annotator
} ? "</span> | <span title='annotator'>" + box.annotator
else : "") +
{ "</span> | <span title='distance'>" +
this.ui.querySelector("#changed-mark").className = 'ui-button'; distance +
} "</span> | <span title='position'>" +
pos.x.toFixed(2) +
" " +
pos.y.toFixed(2) +
" " +
pos.z.toFixed(2) +
"</span> | <span title='scale'>" +
scale.x.toFixed(2) +
" " +
scale.y.toFixed(2) +
" " +
scale.z.toFixed(2) +
"</span> | <span title='rotation'>" +
((rotation.x * 180) / Math.PI).toFixed(2) +
" " +
((rotation.y * 180) / Math.PI).toFixed(2) +
" " +
((rotation.z * 180) / Math.PI).toFixed(2) +
"</span> | <span title = 'points'>" +
points_number +
"</span> ";
if (box.follows) {
this.boxUi.innerHTML += "| F:" + box.follows.obj_track_id;
} }
}),
this.ui.querySelector("#changed-mark").onmouseenter = ()=>{ (this.set_ref_obj = function (marked_object) {
this.refObjUi.innerHTML =
let items = ""; "| Ref: " +
let frames = this.data.worldList.filter(w=>w.annotation.modified).map(w=>w.frameInfo); marked_object.scene +
frames.forEach(f=>{ "/" +
items += "<div class='modified-world-item'>" + f.frame + '</div>'; marked_object.frame +
}); ": " +
marked_object.ann.obj_type +
if (frames.length > 0){ "-" +
this.ui.querySelector("#changed-world-list").innerHTML = items; marked_object.ann.obj_id;
this.ui.querySelector("#changed-world-list-wrapper").style.display = 'inherit'; }),
} (this.set_frame_info = function (scene, frame, on_scene_changed) {
if (this.sceneSelectorUi.value != scene) {
this.sceneSelectorUi.value = scene;
on_scene_changed(scene);
}
this.frameSelectorUi.value = frame;
}),
(this.clear_frame_info = function (scene, frame) {}),
(this.updateModifiedStatus = function () {
let frames = this.data.worldList.filter((w) => w.annotation.modified);
if (frames.length > 0) {
this.ui.querySelector("#changed-mark").className =
"ui-button alarm-mark";
} else {
this.ui.querySelector("#changed-mark").className = "ui-button";
}
});
this.ui.querySelector("#changed-mark").onmouseenter = () => {
let items = "";
let frames = this.data.worldList
.filter((w) => w.annotation.modified)
.map((w) => w.frameInfo);
frames.forEach((f) => {
items += "<div class='modified-world-item'>" + f.frame + "</div>";
});
if (frames.length > 0) {
this.ui.querySelector("#changed-world-list").innerHTML = items;
this.ui.querySelector("#changed-world-list-wrapper").style.display =
"inherit";
} }
};
this.ui.querySelector("#changed-mark").onmouseleave = ()=>{ this.ui.querySelector("#changed-mark").onmouseleave = () => {
this.ui.querySelector("#changed-world-list-wrapper").style.display = 'none'; this.ui.querySelector("#changed-world-list-wrapper").style.display = "none";
} };
this.ui.querySelector("#save-button").onclick = ()=>{ this.ui.querySelector("#save-button").onclick = () => {
saveWorldList(this.data.worldList); saveWorldList(this.data.worldList);
} };
}; };
export { Header };
export {Header}

File diff suppressed because it is too large Load Diff

@ -1,115 +1,92 @@
import { globalKeyDownManager } from "./keydown_manager.js"; import { globalKeyDownManager } from "./keydown_manager.js";
import { PopupDialog } from "./popup_dialog.js"; import { PopupDialog } from "./popup_dialog.js";
class InfoBox extends PopupDialog {
mouseDown = false;
class InfoBox extends PopupDialog{ mouseDwwnPos = {};
mouseDown = false; constructor(ui) {
mouseDwwnPos = {}; super(ui);
this.contentUi = this.ui.querySelector("#info-content");
constructor(ui)
{ this.buttons = {
super(ui); yes: this.ui.querySelector("#btn-yes"),
no: this.ui.querySelector("#btn-no"),
this.contentUi = this.ui.querySelector("#info-content"); maximize: this.ui.querySelector("#btn-maximize"),
restore: this.ui.querySelector("#btn-restore"),
this.buttons = { exit: this.ui.querySelector("#btn-exit"),
"yes": this.ui.querySelector("#btn-yes"), };
"no": this.ui.querySelector("#btn-no"),
"maximize": this.ui.querySelector("#btn-maximize"), for (let btn in this.buttons) {
"restore": this.ui.querySelector("#btn-restore"), this.buttons[btn].onclick = () => {
"exit": this.ui.querySelector("#btn-exit"), this.hide(btn);
}; };
for (let btn in this.buttons)
{
this.buttons[btn].onclick = ()=>{
this.hide(btn);
}
}
this.ui.addEventListener("keydown", (ev)=>{
//anykey
if ( ev.shiftKey || ev.ctrlKey || ev.altKey)
{
//
}
else
{
this.hide();
ev.preventDefault();
ev.stopPropagation();
}
});
} }
this.ui.addEventListener("keydown", (ev) => {
//anykey
showButtons(btns){ if (ev.shiftKey || ev.ctrlKey || ev.altKey) {
for (let btn in this.buttons) //
{ } else {
this.buttons[btn].style.display = 'none'; this.hide();
} ev.preventDefault();
ev.stopPropagation();
for (let btn in btns) }
{ });
this.buttons[btns[btn]].style.display = ''; }
}
showButtons(btns) {
for (let btn in this.buttons) {
this.buttons[btn].style.display = "none";
} }
makeVisible(pointerPosition) for (let btn in btns) {
{ this.buttons[btns[btn]].style.display = "";
if (!pointerPosition)
{
//default pos
let parentRect = this.ui.getBoundingClientRect();
let viewRect = this.viewUi.getBoundingClientRect();
this.viewUi.style.top = (parentRect.top+parentRect.height/3) + "px";
this.viewUi.style.left = (parentRect.left+parentRect.width/2-viewRect.width/2) + "px";
}
else
{
let parentRect = this.ui.getBoundingClientRect();
let viewRect = this.viewUi.getBoundingClientRect();
let left = pointerPosition.x - viewRect.width/2;
if (left < parentRect.left) left = parentRect.left;
if (left + viewRect.width > parentRect.right)
left -= left + viewRect.width - parentRect.right;
let top = pointerPosition.y - viewRect.height/2;
if (top < parentRect.top)
top = parentRect.top;
if (top + viewRect.height > parentRect.bottom)
top -= top + viewRect.height - parentRect.bottom;
this.viewUi.style.top = top + "px";
this.viewUi.style.left = left + "px";
}
} }
}
makeVisible(pointerPosition) {
if (!pointerPosition) {
//default pos
let parentRect = this.ui.getBoundingClientRect();
let viewRect = this.viewUi.getBoundingClientRect();
this.viewUi.style.top = parentRect.top + parentRect.height / 3 + "px";
this.viewUi.style.left =
parentRect.left + parentRect.width / 2 - viewRect.width / 2 + "px";
} else {
let parentRect = this.ui.getBoundingClientRect();
let viewRect = this.viewUi.getBoundingClientRect();
let left = pointerPosition.x - viewRect.width / 2;
if (left < parentRect.left) left = parentRect.left;
if (left + viewRect.width > parentRect.right)
left -= left + viewRect.width - parentRect.right;
let top = pointerPosition.y - viewRect.height / 2;
if (top < parentRect.top) top = parentRect.top;
if (top + viewRect.height > parentRect.bottom)
top -= top + viewRect.height - parentRect.bottom;
this.viewUi.style.top = top + "px";
this.viewUi.style.left = left + "px";
}
}
show(title, content, btnList, onexit, pointerPosition) {
this.showButtons(btnList);
show(title, content, btnList, onexit, pointerPosition) this.titleUi.innerText = title;
{ this.contentUi.innerHTML = content;
this.showButtons(btnList);
this.titleUi.innerText = title;
this.contentUi.innerHTML = content;
super.show(onexit);
this.makeVisible(pointerPosition); super.show(onexit);
this.ui.focus(); this.makeVisible(pointerPosition);
}
this.ui.focus();
}
} }
export { InfoBox };
export {InfoBox};

@ -1,42 +1,30 @@
class KeyDownManager {
handlerList = [];
class KeyDownManager
{ // return id;
register(handler, name) {
handlerList = []; this.handlerList.push([name, handler]);
console.log("register keydown", name);
// return id; }
register(handler, name)
{ deregister(name) {
this.handlerList.push([name, handler]); console.log("deregister keydown", name);
console.log("register keydown", name); this.handlerList = this.handlerList.filter((v) => v[0] !== name);
} }
deregister(name) constructor() {
{ document.addEventListener("keydown", (event) => {
console.log("deregister keydown", name); for (let i = this.handlerList.length - 1; i >= 0; i--) {
this.handlerList = this.handlerList.filter(v=>v[0]!== name); let ret = this.handlerList[i][1](event);
}
if (!ret) {
constructor() break;
{ }
document.addEventListener( 'keydown', (event)=>{ }
});
for (let i = this.handlerList.length-1; i >= 0; i--) }
{
let ret = this.handlerList[i][1](event);
if (!ret)
{
break;
}
}
});
}
} }
var globalKeyDownManager = new KeyDownManager(); var globalKeyDownManager = new KeyDownManager();
export{globalKeyDownManager}; export { globalKeyDownManager };

File diff suppressed because it is too large Load Diff

@ -1,202 +1,213 @@
import { PopupDialog } from "./popup_dialog.js"; import { PopupDialog } from "./popup_dialog.js";
class LogWindow extends PopupDialog {
mouseDown = false;
mouseDwwnPos = {};
class LogWindow extends PopupDialog{
constructor(ui, btn) {
mouseDown = false; super(ui);
mouseDwwnPos = {};
this.btn = btn;
this.svg = btn.querySelector("#log-svg");
constructor(ui, btn)
{ this.logsContentUi = this.ui.querySelector("#content-logs");
super(ui); this.errorsContentUi = this.ui.querySelector("#content-errors");
this.clearBtn = this.ui.querySelector("#btn-clear");
this.btn = btn;
this.svg = btn.querySelector("#log-svg"); this.clearBtn.onclick = () => {
this.logsContentUi.innerHTML = "";
this.logsContentUi = this.ui.querySelector("#content-logs"); };
this.errorsContentUi = this.ui.querySelector("#content-errors"); this.log("Welcome!");
this.clearBtn = this.ui.querySelector("#btn-clear");
this.logBtn = this.ui.querySelector("#tab-log");
this.clearBtn.onclick = ()=>{ this.logsContentUi.innerHTML = ""; }; this.errorBtn = this.ui.querySelector("#tab-error");
this.log("Welcome!");
this.logBtn.onclick = () => {
this.logBtn = this.ui.querySelector("#tab-log"); this.logBtn.className = "tab-button tab-selected";
this.errorBtn = this.ui.querySelector("#tab-error"); this.errorBtn.className = "tab-button";
this.logBtn.onclick= ()=>{ this.logsContentUi.style.display = "inherit";
this.logBtn.className = "tab-button tab-selected"; this.errorsContentUi.style.display = "none";
this.errorBtn.className = "tab-button"; };
this.logsContentUi.style.display = 'inherit'; this.errorBtn.onclick = () => {
this.errorsContentUi.style.display = 'none'; this.errorBtn.className = "tab-button tab-selected";
} this.logBtn.className = "tab-button";
this.errorBtn.onclick= ()=>{ this.logsContentUi.style.display = "none";
this.errorBtn.className = "tab-button tab-selected"; this.errorsContentUi.style.display = "inherit";
this.logBtn.className = "tab-button"; };
}
this.logsContentUi.style.display = 'none';
this.errorsContentUi.style.display = 'inherit'; setErrorsContent(errors) {
} let summary = `${errors.length} warnings.<br>`;
} let text = errors
.map(
setErrorsContent(errors) (r) =>
{ `<a class='log-object-frame-id'>${r.frame_id},${r.obj_id}</a>, ${r.desc}<br>`
let summary = `${errors.length} warnings.<br>`; )
let text = errors.map(r=>`<a class='log-object-frame-id'>${r.frame_id},${r.obj_id}</a>, ${r.desc}<br>`).reduce((a,b)=>a+b, summary); .reduce((a, b) => a + b, summary);
this.errorsContentUi.innerHTML = text; this.errorsContentUi.innerHTML = text;
this.errorsContentUi.querySelectorAll(".log-object-frame-id").forEach(ele=>{ this.errorsContentUi
ele.onclick = (event)=>{ .querySelectorAll(".log-object-frame-id")
let obj = event.currentTarget.innerHTML.split(","); .forEach((ele) => {
console.log("click", obj); ele.onclick = (event) => {
window.editor.currentMainEditor.gotoObjectFrame(...obj); //frameid, objid let obj = event.currentTarget.innerHTML.split(",");
} console.log("click", obj);
}); window.editor.currentMainEditor.gotoObjectFrame(...obj); //frameid, objid
} };
});
}
setUi(ui)
{ setUi(ui) {}
} show() {
super.show();
show() }
{
super.show(); gettime() {
} let d = new Date();
return (
gettime() { "" +
let d = new Date(); d.getFullYear() +
return "" + d.getFullYear() + "-" + (d.getMonth() + 1) + "-" + d.getDate() + " " + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds(); "-" +
(d.getMonth() + 1) +
"-" +
d.getDate() +
" " +
d.getHours() +
":" +
d.getMinutes() +
":" +
d.getSeconds()
);
}
autoScroll = true;
updateAutoScrollFlag() {
let div = this.logsContentUi;
this.autoScroll = div.scrollHeight - 10 < div.scrollTop + div.clientHeight;
}
autoScrollOutput() {
let div = this.logsContentUi;
if (this.autoScroll) div.scrollTop = div.scrollHeight;
}
isInt(n) {
return n % 1 === 0;
}
buildLogStr(args) {
let thisstr = "";
for (let i in args) {
if (typeof args[i] == "number") {
thisstr +=
" <span class='number'>" +
(isInt(args[i]) ? args[i] : args[i].toFixed(6)) +
"</span>";
} else if ([".", ",", ":", ";"].find((c) => c == args[i])) {
thisstr += args[i];
} else {
thisstr += " " + args[i];
}
} }
autoScroll = true; return thisstr;
updateAutoScrollFlag() }
{
let div = this.logsContentUi;
this.autoScroll = (div.scrollHeight-10 < div.scrollTop + div.clientHeight);
}
autoScrollOutput(){
let div = this.logsContentUi;
if (this.autoScroll)
div.scrollTop = div.scrollHeight;
}
isInt(n) {
return n % 1 === 0;
}
buildLogStr(args) {
let thisstr = "";
for (let i in args) {
if (typeof args[i] == "number") {
thisstr += " <span class='number'>" + (isInt(args[i]) ? args[i] : args[i].toFixed(6)) + "</span>";
} else if ([".", ",", ":", ";"].find((c) => c == args[i])) {
thisstr += args[i];
} else {
thisstr += " " + args[i];
}
}
return thisstr;
}
logcolor(color) {
this.updateAutoScrollFlag();
let args = [...arguments];
console.log(...args.slice(1));
let old_content = this.logsContentUi.innerHTML;
let thisstr = this.gettime() + " ";
thisstr += this.buildLogStr(args.slice(1));
this.logid++;
this.logsContentUi.innerHTML = old_content + "<div id='log-" + this.logid + "' class='" + color + "'>" + thisstr + "</div>";
this.autoScrollOutput(); logcolor(color) {
} this.updateAutoScrollFlag();
let args = [...arguments];
console.log(...args.slice(1));
logid = 0; let old_content = this.logsContentUi.innerHTML;
maxLogLength = 10000; // stringLength;
log() {
this.svg.style.fill= this.logid %2 ? "red" : "green"; let thisstr = this.gettime() + " ";
thisstr += this.buildLogStr(args.slice(1));
this.updateAutoScrollFlag(); this.logid++;
console.log(...arguments);
let old_content = this.logsContentUi.innerHTML;
let thisstr = this.gettime() + " "; this.logsContentUi.innerHTML =
//let thisstr = ""; old_content +
thisstr += this.buildLogStr(arguments); "<div id='log-" +
this.logid +
"' class='" +
color +
"'>" +
thisstr +
"</div>";
this.logid++; this.autoScrollOutput();
}
if (old_content.length > this.maxLogLength)
{
old_content = old_content.slice(old_content.length-this.maxLogLength);
let firstLogPos = old_content.search("<div id=");
old_content = old_content.slice(firstLogPos);
}
this.logsContentUi.innerHTML = old_content + "<div id='log-" + this.logid + "'>" + thisstr + "</div>"; logid = 0;
this.autoScrollOutput(); maxLogLength = 10000; // stringLength;
} log() {
this.svg.style.fill = this.logid % 2 ? "red" : "green";
logappend() { this.updateAutoScrollFlag();
//console.log(...arguments);
this.updateAutoScrollFlag();
let thisstr = this.buildLogStr(arguments);
this.logsContentUi.querySelector("#log-" + this.logid).innerHTML += thisstr;
this.autoScrollOutput();
}
logappendcolor(color) { console.log(...arguments);
this.updateAutoScrollFlag(); let old_content = this.logsContentUi.innerHTML;
let args = [...arguments];
let thisstr = this.buildLogStr(args.slice(1));
let div = this.logsContentUi.querySelector("#log-" + this.logid);
div.className = color;
div.innerHTML += thisstr;
this.autoScrollOutput();
}
logonce() { let thisstr = this.gettime() + " ";
this.updateAutoScrollFlag(); //let thisstr = "";
let old_content = this.logsContentUi.innerHTML; thisstr += this.buildLogStr(arguments);
let thisstr = this.gettime() + " "; this.logid++;
thisstr += this.buildLogStr(arguments);
let laststr = this.logsContentUi.querySelector("#log-" + this.logid); if (old_content.length > this.maxLogLength) {
if (laststr && laststr.innerHTML && thisstr == laststr.innerHTML) old_content = old_content.slice(old_content.length - this.maxLogLength);
return; let firstLogPos = old_content.search("<div id=");
old_content = old_content.slice(firstLogPos);
this.logid++;
this.logsContentUi.innerHTML = old_content + "<div id='log-" + this.logid + "'>" + thisstr + "</div>";
this.autoScrollOutput();
} }
this.logsContentUi.innerHTML =
old_content + "<div id='log-" + this.logid + "'>" + thisstr + "</div>";
this.autoScrollOutput();
}
logappend() {
//console.log(...arguments);
this.updateAutoScrollFlag();
let thisstr = this.buildLogStr(arguments);
this.logsContentUi.querySelector("#log-" + this.logid).innerHTML += thisstr;
this.autoScrollOutput();
}
logappendcolor(color) {
this.updateAutoScrollFlag();
let args = [...arguments];
let thisstr = this.buildLogStr(args.slice(1));
let div = this.logsContentUi.querySelector("#log-" + this.logid);
div.className = color;
div.innerHTML += thisstr;
this.autoScrollOutput();
}
logonce() {
this.updateAutoScrollFlag();
let old_content = this.logsContentUi.innerHTML;
let thisstr = this.gettime() + " ";
thisstr += this.buildLogStr(arguments);
let laststr = this.logsContentUi.querySelector("#log-" + this.logid);
if (laststr && laststr.innerHTML && thisstr == laststr.innerHTML) return;
this.logid++;
this.logsContentUi.innerHTML =
old_content + "<div id='log-" + this.logid + "'>" + thisstr + "</div>";
this.autoScrollOutput();
}
} }
let logger = null; let logger = null;
function create_logger(ui, btn){ function create_logger(ui, btn) {
logger = new LogWindow(ui, btn); logger = new LogWindow(ui, btn);
} }
export{logger, create_logger}; export { logger, create_logger };

@ -1,64 +1,57 @@
import{Config} from "./config.js" import { Config } from "./config.js";
import{Editor} from "./editor.js" import { Editor } from "./editor.js";
import {Data} from './data.js' import { Data } from "./data.js";
let pointsGlobalConfig = new Config(); let pointsGlobalConfig = new Config();
window.pointsGlobalConfig = pointsGlobalConfig; window.pointsGlobalConfig = pointsGlobalConfig;
pointsGlobalConfig.load(); pointsGlobalConfig.load();
document.documentElement.className = "theme-" + pointsGlobalConfig.theme;
document.documentElement.className="theme-"+pointsGlobalConfig.theme; document.body.addEventListener("keydown", (event) => {
if (event.ctrlKey && "asdv".indexOf(event.key) !== -1) {
event.preventDefault();
document.body.addEventListener('keydown', event => { }
if (event.ctrlKey && 'asdv'.indexOf(event.key) !== -1) {
event.preventDefault()
}
}); });
async function createMainEditor(){ async function createMainEditor() {
let template = document.querySelector("#editor-template");
let template = document.querySelector('#editor-template'); let maindiv = document.querySelector("#main-editor");
let maindiv = document.querySelector("#main-editor");
let main_ui = template.content.cloneNode(true); let main_ui = template.content.cloneNode(true);
maindiv.appendChild(main_ui); // input parameter is changed after `append` maindiv.appendChild(main_ui); // input parameter is changed after `append`
let editorCfg = pointsGlobalConfig; let editorCfg = pointsGlobalConfig;
let dataCfg = pointsGlobalConfig; let dataCfg = pointsGlobalConfig;
let data = new Data(dataCfg); let data = new Data(dataCfg);
await data.init(); await data.init();
let editor = new Editor(maindiv.lastElementChild, maindiv, editorCfg, data, "main-editor") let editor = new Editor(
maindiv.lastElementChild,
maindiv,
editorCfg,
data,
"main-editor"
);
window.editor = editor; window.editor = editor;
editor.run(); editor.run();
return editor; return editor;
} }
async function start(){
async function start() {
let mainEditor = await createMainEditor(); let mainEditor = await createMainEditor();
let url_string = window.location.href;
let url_string = window.location.href
let url = new URL(url_string); let url = new URL(url_string);
//language //language
let scene = url.searchParams.get("scene"); let scene = url.searchParams.get("scene");
let frame = url.searchParams.get("frame"); let frame = url.searchParams.get("frame");
if (scene && frame) if (scene && frame) {
{
mainEditor.load_world(scene, frame); mainEditor.load_world(scene, frame);
} }
} }
start(); start();

File diff suppressed because it is too large Load Diff

@ -1,221 +1,222 @@
import * as THREE from "./lib/three.module.js";
import * as THREE from './lib/three.module.js';
function Mouse(
view,
op_state,
function Mouse(view, op_state, mainui_container, parentUi, on_left_click, on_right_click, on_select_rect){ mainui_container,
this.view=view; parentUi,
this.domElement = mainui_container; on_left_click,
this.parentUi = parentUi; on_right_click,
this.operation_state = op_state; on_select_rect
) {
this.view = view;
this.domElement.addEventListener( 'mousemove', (e)=>{this.onMouseMove(e);}, false ); this.domElement = mainui_container;
this.domElement.addEventListener( 'mousedown', (e)=>{this.onMouseDown(e);}, true ); this.parentUi = parentUi;
this.operation_state = op_state;
this.domElement.addEventListener(
this.raycaster = new THREE.Raycaster(); "mousemove",
this.onDownPosition = new THREE.Vector2(); (e) => {
this.onUpPosition = new THREE.Vector2(); this.onMouseMove(e);
},
false
this.handleLeftClick = on_left_click; );
this.handleRightClick = on_right_click; this.domElement.addEventListener(
this.handleSelectRect = on_select_rect; "mousedown",
(e) => {
this.onMouseDown(e);
var in_select_mode = false; },
var select_start_pos; true
var select_end_pos; );
this.get_mouse_location_in_world = function(){ this.raycaster = new THREE.Raycaster();
this.raycaster.setFromCamera( this.onUpPosition, this.view.camera ); this.onDownPosition = new THREE.Vector2();
var o = this.raycaster.ray.origin; this.onUpPosition = new THREE.Vector2();
var d = this.raycaster.ray.direction;
this.handleLeftClick = on_left_click;
var alpha = - o.z/d.z; this.handleRightClick = on_right_click;
var x = o.x + d.x*alpha; this.handleSelectRect = on_select_rect;
var y = o.y + d.y*alpha;
return {x:x, y:y, z:0}; var in_select_mode = false;
}; var select_start_pos;
var select_end_pos;
this.get_screen_location_in_world = function(x,y){ this.get_mouse_location_in_world = function () {
var screen_pos = new THREE.Vector2(); this.raycaster.setFromCamera(this.onUpPosition, this.view.camera);
screen_pos.x = x; var o = this.raycaster.ray.origin;
screen_pos.y = y; var d = this.raycaster.ray.direction;
this.raycaster.setFromCamera( screen_pos, this.view.camera ); var alpha = -o.z / d.z;
var o = this.raycaster.ray.origin; var x = o.x + d.x * alpha;
var d = this.raycaster.ray.direction; var y = o.y + d.y * alpha;
return { x: x, y: y, z: 0 };
var alpha = - o.z/d.z; };
var x = o.x + d.x*alpha;
var y = o.y + d.y*alpha; this.get_screen_location_in_world = function (x, y) {
return {x:x, y:y, z:0}; var screen_pos = new THREE.Vector2();
}; screen_pos.x = x;
screen_pos.y = y;
this.raycaster.setFromCamera(screen_pos, this.view.camera);
var o = this.raycaster.ray.origin;
this.getMousePosition = function( dom, offsetX, offsetY ) { var d = this.raycaster.ray.direction;
var alpha = -o.z / d.z;
return [offsetX/dom.clientWidth * 2 - 1, - offsetY/dom.clientHeight * 2 + 1]; var x = o.x + d.x * alpha;
var y = o.y + d.y * alpha;
}; return { x: x, y: y, z: 0 };
};
this.getIntersects = function( point, objects ) {
this.getMousePosition = function (dom, offsetX, offsetY) {
// mouse is temp var return [
let mouse = new THREE.Vector2(); (offsetX / dom.clientWidth) * 2 - 1,
mouse.set(point.x, point.y); (-offsetY / dom.clientHeight) * 2 + 1,
];
this.raycaster.setFromCamera( mouse, this.view.camera ); };
return this.raycaster.intersectObjects( objects, false ); // 2nd argument: recursive. this.getIntersects = function (point, objects) {
// mouse is temp var
}; let mouse = new THREE.Vector2();
mouse.set(point.x, point.y);
this.onMouseDown=function( event ) { this.raycaster.setFromCamera(mouse, this.view.camera);
in_select_mode = false; return this.raycaster.intersectObjects(objects, false); // 2nd argument: recursive.
};
if (event.which==3){
this.operation_state.key_pressed = false; this.onMouseDown = function (event) {
} else if (event.which == 1){ in_select_mode = false;
console.log("mouse left key down!");
if (event.ctrlKey || event.shiftKey){ if (event.which == 3) {
event.stopPropagation(); this.operation_state.key_pressed = false;
event.preventDefault(); } else if (event.which == 1) {
console.log("mouse left key down!");
in_select_mode = true; if (event.ctrlKey || event.shiftKey) {
event.stopPropagation();
select_start_pos={
x: event.offsetX,
y: event.offsetY,
}
}
}
var array = this.getMousePosition(this.domElement, event.offsetX, event.offsetY );
this.onDownPosition.fromArray( array );
console.log("mouse down", array);
this.domElement.addEventListener( 'mouseup', on_mouse_up, false );
}
this.onMouseMove=function( event ) {
event.preventDefault(); event.preventDefault();
//console.log(this.getMousePosition(this.domElement, event.offsetX, event.offsetY)); in_select_mode = true;
if (in_select_mode){ select_start_pos = {
x: event.offsetX,
select_end_pos={ y: event.offsetY,
x: event.offsetX, };
y: event.offsetY, }
}; }
if (event.offsetX != select_start_pos.x || event.offsetY != select_end_pos.y){
//draw select box
var sbox = this.parentUi.querySelector("#select-box");
sbox.style.display="inherit";
if (select_start_pos.x < select_end_pos.x){ var array = this.getMousePosition(
sbox.style.left = select_start_pos.x + 'px'; this.domElement,
sbox.style.width = select_end_pos.x - select_start_pos.x + 'px'; event.offsetX,
}else { event.offsetY
sbox.style.left = select_end_pos.x + 'px'; );
sbox.style.width = -select_end_pos.x + select_start_pos.x + 'px'; this.onDownPosition.fromArray(array);
} console.log("mouse down", array);
this.domElement.addEventListener("mouseup", on_mouse_up, false);
};
this.onMouseMove = function (event) {
event.preventDefault();
//console.log(this.getMousePosition(this.domElement, event.offsetX, event.offsetY));
if (in_select_mode) {
select_end_pos = {
x: event.offsetX,
y: event.offsetY,
};
if (
event.offsetX != select_start_pos.x ||
event.offsetY != select_end_pos.y
) {
//draw select box
var sbox = this.parentUi.querySelector("#select-box");
sbox.style.display = "inherit";
if (select_start_pos.x < select_end_pos.x) {
sbox.style.left = select_start_pos.x + "px";
sbox.style.width = select_end_pos.x - select_start_pos.x + "px";
} else {
sbox.style.left = select_end_pos.x + "px";
sbox.style.width = -select_end_pos.x + select_start_pos.x + "px";
}
if (select_start_pos.y < select_end_pos.y){ if (select_start_pos.y < select_end_pos.y) {
sbox.style.top = select_start_pos.y + 'px'; sbox.style.top = select_start_pos.y + "px";
sbox.style.height = select_end_pos.y - select_start_pos.y + 'px'; sbox.style.height = select_end_pos.y - select_start_pos.y + "px";
}else { } else {
sbox.style.top = select_end_pos.y + 'px'; sbox.style.top = select_end_pos.y + "px";
sbox.style.height = -select_end_pos.y + select_start_pos.y + 'px'; sbox.style.height = -select_end_pos.y + select_start_pos.y + "px";
}
}
} }
}
} }
};
var on_mouse_up = (e) => {
this.onMouseUp(e);
};
this.onMouseUp = function (event) {
this.domElement.removeEventListener("mouseup", on_mouse_up, false);
var array = this.getMousePosition(
this.domElement,
event.offsetX,
event.offsetY
);
this.onUpPosition.fromArray(array);
console.log("mouse up", array);
if (this.onDownPosition.distanceTo(this.onUpPosition) === 0) {
if (event.which == 3) {
//right click
// if no other key pressed, we consider this as a right click
if (!this.operation_state.key_pressed) {
console.log("right clicked.");
this.handleRightClick(event);
}
} else {
// left click
this.handleLeftClick(event);
}
var on_mouse_up = (e)=>{this.onMouseUp(e)}; in_select_mode = false;
return;
this.onMouseUp=function( event ) { }
this.domElement.removeEventListener( 'mouseup', on_mouse_up, false );
if (in_select_mode) {
var array = this.getMousePosition(this.domElement, event.offsetX, event.offsetY ); in_select_mode = false;
this.onUpPosition.fromArray( array );
console.log("mouse up", array); var sbox = this.parentUi.querySelector("#select-box");
sbox.style.display = "none";
if ( this.onDownPosition.distanceTo( this.onUpPosition ) === 0 ) { if (this.handleSelectRect) {
if (event.which == 3){ var x, y, w, h;
//right click
// if no other key pressed, we consider this as a right click
if (!this.operation_state.key_pressed){
console.log("right clicked.");
this.handleRightClick(event);
}
}
else{
// left click
this.handleLeftClick(event);
}
in_select_mode = false; if (this.onDownPosition.x < this.onUpPosition.x) {
return; x = this.onDownPosition.x;
w = this.onUpPosition.x - this.onDownPosition.x;
} else {
x = this.onUpPosition.x;
w = this.onDownPosition.x - this.onUpPosition.x;
} }
if (this.onDownPosition.y < this.onUpPosition.y) {
if (in_select_mode){ y = this.onDownPosition.y;
in_select_mode = false; h = this.onUpPosition.y - this.onDownPosition.y;
} else {
y = this.onUpPosition.y;
var sbox = this.parentUi.querySelector("#select-box"); h = this.onDownPosition.y - this.onUpPosition.y;
sbox.style.display="none";
if (this.handleSelectRect){
var x,y,w,h;
if (this.onDownPosition.x < this.onUpPosition.x){
x = this.onDownPosition.x;
w = this.onUpPosition.x - this.onDownPosition.x;
}
else{
x = this.onUpPosition.x;
w = this.onDownPosition.x - this.onUpPosition.x;
}
if (this.onDownPosition.y < this.onUpPosition.y){
y = this.onDownPosition.y;
h = this.onUpPosition.y - this.onDownPosition.y;
}
else{
y = this.onUpPosition.y;
h = this.onDownPosition.y - this.onUpPosition.y;
}
console.log("select rect",x,y,w,h);
this.handleSelectRect(x,y,w,h, event.ctrlKey, event.shiftKey);
}
} }
console.log("select rect", x, y, w, h);
this.handleSelectRect(x, y, w, h, event.ctrlKey, event.shiftKey);
}
} }
};
} }
export{Mouse} export { Mouse };

@ -1,172 +1,190 @@
// size is the dimension of the object in x/y/z axis, with unit meter. // size is the dimension of the object in x/y/z axis, with unit meter.
class ObjectCategory class ObjectCategory {
{ obj_type_map = {
Car: {
color: "#86af49",
obj_type_map = { size: [4.5, 1.8, 1.5],
Car: {color: '#86af49', size:[4.5, 1.8, 1.5], attr:["door open", "trunk open"]}, attr: ["door open", "trunk open"],
Pedestrian: {color: '#ff0000', size:[0.4, 0.5, 1.7], attr:["umbrella", "sitting", "squating", "bending over", "luggage"]}, },
Van: {color: '#00ff00', size:[4.5, 1.8, 1.5], attr:["door open", "trunk open"]}, Pedestrian: {
Bus: {color: '#ffff00', size:[13, 3, 3.5]}, color: "#ff0000",
Truck: {color: '#00ffff', size:[10., 2.8, 3]}, size: [0.4, 0.5, 1.7],
attr: ["umbrella", "sitting", "squating", "bending over", "luggage"],
ScooterRider: {color: '#ff8800', size:[1.6, 0.6, 1.6], attr:["umbrella", "1 passenger", "2 passengers", "3 passengers"]}, },
Scooter: {color: '#aaaa00', size:[1.6, 0.6, 1.0]}, Van: {
color: "#00ff00",
size: [4.5, 1.8, 1.5],
BicycleRider: {color: '#88ff00', size:[1.6, 0.6, 1.7], attr:["umbrella", "1 passenger", "2 passengers", "3 passengers"]}, attr: ["door open", "trunk open"],
Bicycle: {color: '#ff8800', size:[1.6, 0.6, 1.2], attr:["laying down"]}, },
Bus: { color: "#ffff00", size: [13, 3, 3.5] },
Truck: { color: "#00ffff", size: [10, 2.8, 3] },
Motorcycle: {color: '#aaaa00', size:[1.6, 0.6, 1.2], attr:["umbrella"]},
MotorcyleRider: {color: '#ff8800', size:[1.6, 0.6, 1.6], attr:["umbrella", "1 passenger", "2 passengers", "3 passengers"]}, ScooterRider: {
color: "#ff8800",
size: [1.6, 0.6, 1.6],
attr: ["umbrella", "1 passenger", "2 passengers", "3 passengers"],
PoliceCar: {color: '#86af49', size:[4.5, 1.8, 1.5]}, },
TourCar: {color: '#86af49', size:[4.4, 1.5, 2.2]}, Scooter: { color: "#aaaa00", size: [1.6, 0.6, 1.0] },
RoadWorker: {color: '#ff0000', size:[0.4, 0.5, 1.7]}, BicycleRider: {
Child: {color: '#ff0000', size:[0.4, 0.5, 1.2]}, color: "#88ff00",
size: [1.6, 0.6, 1.7],
//Crowd: {color: '#ff0000', size:[1.6, 0.6, 1.2]}, attr: ["umbrella", "1 passenger", "2 passengers", "3 passengers"],
},
BabyCart: {color: '#ff0000', size:[0.8, 0.5, 1.0]}, Bicycle: { color: "#ff8800", size: [1.6, 0.6, 1.2], attr: ["laying down"] },
Cart: {color: '#ff0000', size:[0.8, 0.5, 1.0]},
Cone: {color: '#ff0000', size:[0.3, 0.3, 0.6]}, Motorcycle: { color: "#aaaa00", size: [1.6, 0.6, 1.2], attr: ["umbrella"] },
FireHydrant: {color: '#ff0000', size:[0.4, 0.4, 0.6]}, MotorcyleRider: {
SaftyTriangle: {color: '#ff0000', size:[0.3, 0.4, 0.4]}, color: "#ff8800",
PlatformCart: {color: '#ff0000', size:[1.2, 0.8, 1.0]}, size: [1.6, 0.6, 1.6],
ConstructionCart: {color: '#ff0000', size:[1.2, 0.8, 1.0]}, attr: ["umbrella", "1 passenger", "2 passengers", "3 passengers"],
RoadBarrel: {color: '#ff0000', size:[0.5, 0.5, 0.6]}, },
TrafficBarrier: {color: '#ff0000', size:[1.5, 0.3, 1.2]},
LongVehicle: {color: '#ff0000', size:[16, 3, 3]}, PoliceCar: { color: "#86af49", size: [4.5, 1.8, 1.5] },
TourCar: { color: "#86af49", size: [4.4, 1.5, 2.2] },
BicycleGroup: {color: '#ff0000', size:[1.6, 0.6, 1.2]}, RoadWorker: { color: "#ff0000", size: [0.4, 0.5, 1.7] },
Child: { color: "#ff0000", size: [0.4, 0.5, 1.2] },
ConcreteTruck: {color: '#00ffff', size:[10., 2.8, 3]}, //Crowd: {color: '#ff0000', size:[1.6, 0.6, 1.2]},
Tram: {color: '#00ffff', size:[10., 2.8, 3]},
Excavator: {color: '#00ffff', size:[6., 3, 3]}, BabyCart: { color: "#ff0000", size: [0.8, 0.5, 1.0] },
Cart: { color: "#ff0000", size: [0.8, 0.5, 1.0] },
Animal: {color: '#00aaff', size:[1.6, 0.6, 1.2]}, Cone: { color: "#ff0000", size: [0.3, 0.3, 0.6] },
FireHydrant: { color: "#ff0000", size: [0.4, 0.4, 0.6] },
TrashCan: {color: '#00aaff', size:[0.6, 0.4, 1.0]}, SaftyTriangle: { color: "#ff0000", size: [0.3, 0.4, 0.4] },
PlatformCart: { color: "#ff0000", size: [1.2, 0.8, 1.0] },
ForkLift: {color: '#00aaff', size:[5.0, 1.2, 2.0]}, ConstructionCart: { color: "#ff0000", size: [1.2, 0.8, 1.0] },
Trimotorcycle: {color: '#00aaff', size:[2.6, 1.0, 1.6]}, RoadBarrel: { color: "#ff0000", size: [0.5, 0.5, 0.6] },
FreightTricycle: {color: '#00aaff', size:[2.6, 1.0, 1.6]}, TrafficBarrier: { color: "#ff0000", size: [1.5, 0.3, 1.2] },
Crane: {color: '#00aaff', size:[5.0, 1.2, 2.0]}, LongVehicle: { color: "#ff0000", size: [16, 3, 3] },
RoadRoller: {color: '#00aaff', size:[2.7, 1.5, 2.0]},
Bulldozer: {color: '#00aaff', size:[3.0, 2.0, 2.0]}, BicycleGroup: { color: "#ff0000", size: [1.6, 0.6, 1.2] },
DontCare: {color: '#00ff88', size:[4, 4, 3]}, ConcreteTruck: { color: "#00ffff", size: [10, 2.8, 3] },
Misc: {color: '#008888', size:[4.5, 1.8, 1.5]}, Tram: { color: "#00ffff", size: [10, 2.8, 3] },
Unknown: {color: '#008888', size:[4.5, 1.8, 1.5]}, Excavator: { color: "#00ffff", size: [6, 3, 3] },
Unknown1: {color: '#008888', size:[4.5, 1.8, 1.5]},
Unknown2: {color: '#008888', size:[4.5, 1.8, 1.5]}, Animal: { color: "#00aaff", size: [1.6, 0.6, 1.2] },
Unknown3: {color: '#008888', size:[4.5, 1.8, 1.5]},
Unknown4: {color: '#008888', size:[4.5, 1.8, 1.5]}, TrashCan: { color: "#00aaff", size: [0.6, 0.4, 1.0] },
Unknown5: {color: '#008888', size:[4.5, 1.8, 1.5]},
}; ForkLift: { color: "#00aaff", size: [5.0, 1.2, 2.0] },
Trimotorcycle: { color: "#00aaff", size: [2.6, 1.0, 1.6] },
FreightTricycle: { color: "#00aaff", size: [2.6, 1.0, 1.6] },
constructor(){ Crane: { color: "#00aaff", size: [5.0, 1.2, 2.0] },
RoadRoller: { color: "#00aaff", size: [2.7, 1.5, 2.0] },
} Bulldozer: { color: "#00aaff", size: [3.0, 2.0, 2.0] },
popularCategories = ["Car", "Pedestrian", "Van", "Bus", "Truck", "Scooter", "ScooterRider", "Bicycle", "BicycleRider"]; DontCare: { color: "#00ff88", size: [4, 4, 3] },
Misc: { color: "#008888", size: [4.5, 1.8, 1.5] },
guess_obj_type_by_dimension(scale){ Unknown: { color: "#008888", size: [4.5, 1.8, 1.5] },
Unknown1: { color: "#008888", size: [4.5, 1.8, 1.5] },
var max_score = 0; Unknown2: { color: "#008888", size: [4.5, 1.8, 1.5] },
var max_name = 0; Unknown3: { color: "#008888", size: [4.5, 1.8, 1.5] },
this.popularCategories.forEach(i=>{ Unknown4: { color: "#008888", size: [4.5, 1.8, 1.5] },
var o = this.obj_type_map[i]; Unknown5: { color: "#008888", size: [4.5, 1.8, 1.5] },
var scorex = o.size[0]/scale.x; };
var scorey = o.size[1]/scale.y;
var scorez = o.size[2]/scale.z; constructor() {}
if (scorex>1) scorex = 1/scorex; popularCategories = [
if (scorey>1) scorey = 1/scorey; "Car",
if (scorez>1) scorez = 1/scorez; "Pedestrian",
"Van",
if (scorex + scorey + scorez > max_score){ "Bus",
max_score = scorex + scorey + scorez; "Truck",
max_name = i; "Scooter",
} "ScooterRider",
}); "Bicycle",
"BicycleRider",
console.log("guess type", max_name); ];
return max_name;
guess_obj_type_by_dimension(scale) {
var max_score = 0;
var max_name = 0;
this.popularCategories.forEach((i) => {
var o = this.obj_type_map[i];
var scorex = o.size[0] / scale.x;
var scorey = o.size[1] / scale.y;
var scorez = o.size[2] / scale.z;
if (scorex > 1) scorex = 1 / scorex;
if (scorey > 1) scorey = 1 / scorey;
if (scorez > 1) scorez = 1 / scorez;
if (scorex + scorey + scorez > max_score) {
max_score = scorex + scorey + scorez;
max_name = i;
}
});
console.log("guess type", max_name);
return max_name;
}
global_color_idx = 0;
get_color_by_id(id) {
let idx = parseInt(id);
if (!idx) {
idx = this.global_color_idx;
this.global_color_idx += 1;
} }
global_color_idx = 0; idx %= 33;
get_color_by_id(id){ idx = (idx * 19) % 33;
let idx = parseInt(id);
if (!idx) return {
{ x: (idx * 8) / 256.0,
idx = this.global_color_idx; y: 1 - (idx * 8) / 256.0,
this.global_color_idx += 1; z: idx < 16 ? (idx * 2 * 8) / 256.0 : ((32 - idx) * 2 * 8) / 256.0,
} };
}
idx %= 33; get_color_by_category(category) {
idx = idx*19 % 33; let target_color_hex = parseInt(
"0x" + this.get_obj_cfg_by_type(category).color.slice(1)
);
return { return {
x: idx*8/256.0, x: target_color_hex / 256 / 256 / 255.0,
y: 1- idx*8/256.0, y: ((target_color_hex / 256) % 256) / 255.0,
z: (idx<16)?(idx*2*8/256.0):((32-idx)*2*8/256.0), z: (target_color_hex % 256) / 255.0,
}; };
} }
get_color_by_category(category){
let target_color_hex = parseInt("0x"+this.get_obj_cfg_by_type(category).color.slice(1));
return {
x: (target_color_hex/256/256)/255.0,
y: (target_color_hex/256 % 256)/255.0,
z: (target_color_hex % 256)/255.0,
};
}
get_obj_cfg_by_type(name){ get_obj_cfg_by_type(name) {
if (this.obj_type_map[name]){ if (this.obj_type_map[name]) {
return this.obj_type_map[name]; return this.obj_type_map[name];
} } else {
else{ return this.obj_type_map["Unknown"];
return this.obj_type_map["Unknown"];
}
} }
}
// name_array = [] // name_array = []
// build_name_array(){
// for (var n in this.obj_type_map){
// name_array.push(n);
// }
// }
// build_name_array(){
// for (var n in this.obj_type_map){
// name_array.push(n);
// }
// }
// get_next_obj_type_name(name){ // get_next_obj_type_name(name){
// if (name_array.length == 0) { // if (name_array.length == 0) {
// build_name_array(); // build_name_array();
// } // }
// var idx = name_array.findIndex(function(n){return n==name;}) // var idx = name_array.findIndex(function(n){return n==name;})
// idx+=1; // idx+=1;
// idx %= name_array.length; // idx %= name_array.length;
// return name_array[idx];
// }
// return name_array[idx];
// }
} }
let globalObjectCategory = new ObjectCategory(); let globalObjectCategory = new ObjectCategory();
export {globalObjectCategory}; export { globalObjectCategory };

@ -1,117 +1,119 @@
class ObjectIdManager {
maxId = 1;
objectList = [];
class ObjectIdManager //todo: should use all worldlist
{ generateNewUniqueId(world) {
maxId = 1; this.maxId += 1;
objectList = []; return this.maxId;
//todo: should use all worldlist }
generateNewUniqueId(world){
this.maxId += 1; scene = "";
return this.maxId; setCurrentScene(scene, done) {
} if (scene != this.scene) {
this.scene = scene;
scene = ""; this.load_obj_ids_of_scene(scene, done);
setCurrentScene(scene, done)
{
if (scene != this.scene)
{
this.scene = scene;
this.load_obj_ids_of_scene(scene, done);
}
}
forceUpdate(done)
{
this.load_obj_ids_of_scene(this.scene, done);
}
// should just tell editor
// don't change html elements directly.
setObjdIdListOptions()
{
let objSelOptions = this.objectList.map(function(c){
return "<option value="+c.id+">"+String(c.id) +"-"+ c.category+"</option>";
}).reduce(function(x,y){return x+y;},
"<option>--object--</option>");
document.getElementById("object-selector").innerHTML = objSelOptions;
let objIdsOptions = this.objectList.map(function(c){
return "<option value="+c.id+">"+c.category+"</option>";
}).reduce(function(x,y){return x+y;},
//"<option value='auto'></option><option value='new'></option>");
//"<option value='new'>suggest a new id</option>"
""
);
document.getElementById("obj-ids-of-scene").innerHTML = objIdsOptions;
} }
}
sortObjIdList()
{ forceUpdate(done) {
this.objectList = this.objectList.sort(function(x, y){ this.load_obj_ids_of_scene(this.scene, done);
return parseInt(x.id) - parseInt(y.id); }
});
} // should just tell editor
// don't change html elements directly.
// called when 1) new object 2) category/id modified setObjdIdListOptions() {
addObject(obj) let objSelOptions = this.objectList
{ .map(function (c) {
if (! this.objectList.find(x=>x.id == obj.id && x.category == obj.category)) return (
{ "<option value=" +
this.objectList.push(obj); c.id +
this.sortObjIdList(); ">" +
String(c.id) +
this.setObjdIdListOptions(); "-" +
c.category +
if (obj.id > this.maxId) "</option>"
{ );
this.maxId = parseInt(obj.id); })
} .reduce(function (x, y) {
} return x + y;
} }, "<option>--object--</option>");
document.getElementById("object-selector").innerHTML = objSelOptions;
load_obj_ids_of_scene(scene, done){
let objIdsOptions = this.objectList
var xhr = new XMLHttpRequest(); .map(function (c) {
// we defined the xhr return "<option value=" + c.id + ">" + c.category + "</option>";
let self =this; })
.reduce(
xhr.onreadystatechange = function() { function (x, y) {
if (this.readyState != 4) return x + y;
return; },
//"<option value='auto'></option><option value='new'></option>");
if (this.status == 200) { //"<option value='new'>suggest a new id</option>"
var ret = JSON.parse(this.responseText); ""
);
self.objectList = ret;
self.sortObjIdList(); document.getElementById("obj-ids-of-scene").innerHTML = objIdsOptions;
self.maxId = Math.max(...ret.map(function(x){return x.id;})); }
if (self.maxId < 0) // this is -infinity if there is no ids.
self.maxId = 0; sortObjIdList() {
this.objectList = this.objectList.sort(function (x, y) {
self.setObjdIdListOptions(); return parseInt(x.id) - parseInt(y.id);
});
if (done) }
done(ret)
} // called when 1) new object 2) category/id modified
addObject(obj) {
}; if (
!this.objectList.find((x) => x.id == obj.id && x.category == obj.category)
xhr.open('GET', "/objs_of_scene?scene="+scene, true); ) {
xhr.send(); this.objectList.push(obj);
} this.sortObjIdList();
this.setObjdIdListOptions();
getObjById(id)
{ if (obj.id > this.maxId) {
return this.objectList.find(x=>x.id == id); this.maxId = parseInt(obj.id);
}
} }
}
load_obj_ids_of_scene(scene, done) {
var xhr = new XMLHttpRequest();
// we defined the xhr
let self = this;
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
var ret = JSON.parse(this.responseText);
self.objectList = ret;
self.sortObjIdList();
self.maxId = Math.max(
...ret.map(function (x) {
return x.id;
})
);
if (self.maxId < 0)
// this is -infinity if there is no ids.
self.maxId = 0;
self.setObjdIdListOptions();
if (done) done(ret);
}
};
xhr.open("GET", "/objs_of_scene?scene=" + scene, true);
xhr.send();
}
getObjById(id) {
return this.objectList.find((x) => x.id == id);
}
} }
let objIdManager = new ObjectIdManager(); let objIdManager = new ObjectIdManager();
export { objIdManager };
export {objIdManager};

@ -1,192 +1,188 @@
import * as THREE from './lib/three.module.js'; import * as THREE from "./lib/three.module.js";
import { PCDLoader } from './lib/PCDLoader.js'; import { PCDLoader } from "./lib/PCDLoader.js";
import { OrbitControls } from './lib/OrbitControls.js'; import { OrbitControls } from "./lib/OrbitControls.js";
import { SelectionBox } from './lib/SelectionBox.js'; import { SelectionBox } from "./lib/SelectionBox.js";
import { SelectionHelper } from './lib/SelectionHelper.js'; import { SelectionHelper } from "./lib/SelectionHelper.js";
var container; var container;
var camera, controls, scene, renderer; var camera, controls, scene, renderer;
var camera; var camera;
var url_string = window.location.href;
var url_string = window.location.href
var url = new URL(url_string); var url = new URL(url_string);
//language //language
var pcd_file = url.searchParams.get("file"); var pcd_file = url.searchParams.get("file");
init(); init();
animate(); animate();
function init() { function init() {
document.body.addEventListener('keydown', event => { document.body.addEventListener("keydown", (event) => {
if (event.ctrlKey && 'asdv'.indexOf(event.key) !== -1) { if (event.ctrlKey && "asdv".indexOf(event.key) !== -1) {
event.preventDefault() event.preventDefault();
} }
}) });
scene = new THREE.Scene(); scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
camera = new THREE.PerspectiveCamera(
65,
window.innerWidth / window.innerHeight,
1,
800
);
camera.position.x = 0;
camera.position.z = 50;
camera.position.y = 0;
camera.up.set(0, 0, 1);
camera.lookAt(0, 0, 0);
renderer = new THREE.WebGLRenderer( { antialias: true } ); controls = new OrbitControls(camera, renderer.domElement);
renderer.setPixelRatio( window.devicePixelRatio ); controls.addEventListener("change", render); // call this only in static scenes (i.e., if there is no animation loop)
container = document.createElement("container");
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera( 65, window.innerWidth / window.innerHeight, 1, 800 ); container.appendChild(renderer.domElement);
camera.position.x = 0;
camera.position.z = 50;
camera.position.y = 0;
camera.up.set( 0, 0, 1);
camera.lookAt( 0, 0, 0 );
document.addEventListener("keydown", keydown);
controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
container = document.createElement( 'container' );
document.body.appendChild( container ); scene.add(new THREE.AxesHelper(2));
container.appendChild( renderer.domElement );
document.addEventListener("keydown", keydown) onWindowResize();
window.addEventListener("resize", onWindowResize, false);
scene.add( new THREE.AxesHelper( 2 ) ); load_all();
onWindowResize(); render();
window.addEventListener( 'resize', onWindowResize, false );
load_all();
render();
} }
function load_all(){ function load_all() {
load_pcd("pcd", pcd_file, 0xff0000); load_pcd("pcd", pcd_file, 0xff0000);
} }
function keydown(ev) {
function keydown( ev ) { switch (ev.key) {
case "+":
switch ( ev.key) { clouds["src"].material.size *= 1.2;
case '+': clouds["tgt"].material.size *= 1.2;
clouds["src"].material.size *= 1.2; clouds["out"].material.size *= 1.2;
clouds["tgt"].material.size *= 1.2; break;
clouds["out"].material.size *= 1.2; case "-":
break; clouds["src"].material.size /= 1.2;
case '-': clouds["tgt"].material.size /= 1.2;
clouds["src"].material.size /= 1.2; clouds["out"].material.size /= 1.2;
clouds["tgt"].material.size /= 1.2;
clouds["out"].material.size /= 1.2; break;
}
break;
}
} }
function onWindowResize() { function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight; camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix(); camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setSize(window.innerWidth, window.innerHeight);
} }
function animate() { function animate() {
requestAnimationFrame( animate ); requestAnimationFrame(animate);
controls.update(); controls.update();
render(); render();
} }
function render() {
function render(){ renderer.render(scene, camera);
renderer.render( scene, camera );
} }
function load_pcd(name, file, overall_color) {
var loader = new PCDLoader();
loader.load(file, function (pcd) {
var position = pcd.position;
var color = pcd.color;
var normal = pcd.normal;
// build geometry
var geometry = new THREE.BufferGeometry();
if (position.length > 0)
geometry.addAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
if (normal.length > 0)
geometry.addAttribute(
"normal",
new THREE.Float32BufferAttribute(normal, 3)
);
if (color.length > 0)
geometry.addAttribute(
"color",
new THREE.Float32BufferAttribute(color, 3)
);
geometry.computeBoundingSphere();
// build material
var material = new THREE.PointsMaterial({ size: 0.005 });
if (color.length > 0) {
material.vertexColors = VertexColors;
} else {
material.color.setHex(overall_color);
}
function load_pcd(name, file, overall_color){ //material.size = 0.1;
var loader = new PCDLoader();
loader.load( file,
function ( pcd ) {
var position = pcd.position;
var color = pcd.color;
var normal = pcd.normal;
// build geometry
var geometry = new THREE.BufferGeometry();
if ( position.length > 0 ) geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) );
if ( normal.length > 0 ) geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normal, 3 ) );
if ( color.length > 0 ) geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( color, 3 ) );
geometry.computeBoundingSphere();
// build material
var material = new THREE.PointsMaterial( { size: 0.005 } );
if ( color.length > 0 ) {
material.vertexColors = VertexColors;
} else {
material.color.setHex(overall_color );
}
//material.size = 0.1;
// build mesh // build mesh
var mesh = new THREE.Points( geometry, material ); var mesh = new THREE.Points(geometry, material);
mesh.name = "pcd"; mesh.name = "pcd";
//return mesh; //return mesh;
scene.add(mesh);
scene.add(mesh);
//var center = points.geometry.boundingSphere.center;
//controls.target.set( center.x, center.y, center.z );
//controls.update();
},
);
//var center = points.geometry.boundingSphere.center;
//controls.target.set( center.x, center.y, center.z );
//controls.update();
});
} }
var selectionBox = new SelectionBox(camera, scene);
var helper = new SelectionHelper(selectionBox, renderer, "selectBox");
var selectionBox = new SelectionBox( camera, scene ); document.addEventListener("mousedown", function (event) {
var helper = new SelectionHelper( selectionBox, renderer, 'selectBox' ); for (var item of selectionBox.collection) {
document.addEventListener( 'mousedown', function ( event ) { item.material.emissive.set(0x000000);
for ( var item of selectionBox.collection ) { }
item.material.emissive.set( 0x000000 ); selectionBox.startPoint.set(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
0.5
);
});
document.addEventListener("mousemove", function (event) {
if (helper.isDown) {
for (var i = 0; i < selectionBox.collection.length; i++) {
selectionBox.collection[i].material.emissive.set(0x000000);
} }
selectionBox.startPoint.set(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
0.5 );
} );
document.addEventListener( 'mousemove', function ( event ) {
if ( helper.isDown ) {
for ( var i = 0; i < selectionBox.collection.length; i ++ ) {
selectionBox.collection[ i ].material.emissive.set( 0x000000 );
}
selectionBox.endPoint.set(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
0.5 );
var allSelected = selectionBox.select();
for ( var i = 0; i < allSelected.length; i ++ ) {
allSelected[ i ].material.emissive.set( 0xffffff );
}
}
} );
document.addEventListener( 'mouseup', function ( event ) {
selectionBox.endPoint.set( selectionBox.endPoint.set(
( event.clientX / window.innerWidth ) * 2 - 1, (event.clientX / window.innerWidth) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1, -(event.clientY / window.innerHeight) * 2 + 1,
0.5 ); 0.5
);
var allSelected = selectionBox.select(); var allSelected = selectionBox.select();
for ( var i = 0; i < allSelected.length; i ++ ) { for (var i = 0; i < allSelected.length; i++) {
allSelected[ i ].material.emissive.set( 0xffffff ); allSelected[i].material.emissive.set(0xffffff);
} }
} ); }
});
document.addEventListener("mouseup", function (event) {
selectionBox.endPoint.set(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
0.5
);
var allSelected = selectionBox.select();
for (var i = 0; i < allSelected.length; i++) {
allSelected[i].material.emissive.set(0xffffff);
}
});

@ -1,155 +1,128 @@
function PlayControl(data) {
this.data = data;
this.stop_play_flag = true;
function PlayControl(data){ this.pause_play_flag = false;
this.data = data; this.pause_resume_play = function () {
this.stop_play_flag=true; this.pause_play_flag = !this.pause_play_flag;
this.pause_play_flag=false;
if (!this.pause_play_flag && !this.stop_play_flag) {
this.pause_resume_play=function(){ this.play(this.on_load_world_finished);
this.pause_play_flag=!this.pause_play_flag; }
};
if (!this.pause_play_flag && !this.stop_play_flag){
this.play(this.on_load_world_finished); this.stop_play = function () {
} this.stop_play_flag = true;
}; this.pause_play_flag = false;
};
this.stop_play=function(){ this.on_load_world_finished = null;
this.stop_play_flag=true; this.play = function (on_load_world_finished, fps = 2) {
this.pause_play_flag=false; this.on_load_world_finished = on_load_world_finished;
};
if (!this.data.meta) {
this.on_load_world_finished = null; console.log("no meta data! cannot play");
this.play=function(on_load_world_finished, fps=2){ return;
this.on_load_world_finished = on_load_world_finished; }
if (!this.data.meta){ // if (this.stop_play_flag == false && !resume){
console.log("no meta data! cannot play"); // return;
return; // }
}
this.stop_play_flag = false;
// if (this.stop_play_flag == false && !resume){ this.pause_play_flag = false;
// return;
// } var scene_meta = data.world.sceneMeta;
this.stop_play_flag = false; var scope = this;
this.pause_play_flag = false;
let start_frame = data.world.frameInfo.frame;
var scene_meta = data.world.sceneMeta;
let current_frame_index = scene_meta.frames.findIndex(function (x) {
var scope=this; return x == data.world.frameInfo.frame;
});
if (current_frame_index == scene_meta.frames.length - 1) {
//this is the last frmae
let start_frame = data.world.frameInfo.frame; // we go to first frame.
start_frame = scene_meta.frames[0];
let current_frame_index = scene_meta.frames.findIndex(function(x){return x == data.world.frameInfo.frame;}) }
if (current_frame_index == scene_meta.frames.length-1)
{ play_frame(scene_meta, start_frame, on_load_world_finished);
//this is the last frmae
// we go to first frame. async function play_frame(scene_meta, frame, on_load_world_finished) {
start_frame = scene_meta.frames[0]; if (!scope.stop_play_flag && !scope.pause_play_flag) {
} var world = await scope.data.getWorld(scene_meta.scene, frame);
if (world.preloaded()) {
play_frame(scene_meta, start_frame, on_load_world_finished); //found, data ready
scope.data.activate_world(world, function () {
//on load finished
async function play_frame(scene_meta, frame, on_load_world_finished){ //views[0].detach_control();
if (!scope.stop_play_flag && !scope.pause_play_flag) on_load_world_finished(world);
{
var world = await scope.data.getWorld(scene_meta.scene, frame) // play next frame
let frame_index = world.frameInfo.frame_index;
if (world.preloaded()) //found, data ready if (frame_index + 1 < scene_meta.frames.length) {
{ var next_frame = scene_meta.frames[frame_index + 1];
scope.data.activate_world( setTimeout(function () {
world, play_frame(scene_meta, next_frame, on_load_world_finished);
function(){//on load finished }, 1000 / fps);
//views[0].detach_control(); } else {
on_load_world_finished(world); scope.stop_play();
// play next frame
let frame_index = world.frameInfo.frame_index;
if (frame_index+1 < scene_meta.frames.length)
{
var next_frame = scene_meta.frames[frame_index+1];
setTimeout(
function(){
play_frame(scene_meta, next_frame, on_load_world_finished);
},
1000/fps);
}
else{
scope.stop_play();
}
});
}
else{
//not ready.
console.log("wait buffer!", frame);
setTimeout(
function(){
play_frame(scene_meta, frame, on_load_world_finished);
},
10);
}
} }
}; });
}; } else {
//not ready.
console.log("wait buffer!", frame);
// function play_current_scene_without_buffer(){ setTimeout(function () {
play_frame(scene_meta, frame, on_load_world_finished);
// if (!data.meta){ }, 10);
// console.log("no meta data! cannot play"); }
// return; }
// } }
};
// if (stop_play_flag== false){
// return; // function play_current_scene_without_buffer(){
// }
// if (!data.meta){
// stop_play_flag = false; // console.log("no meta data! cannot play");
// return;
// var scene_meta = data.get_current_world_scene_meta(); // }
// var sceneName= scene_meta.scene;
// if (stop_play_flag== false){
// play_frame(scene_meta, data.world.frameInfo.frame); // return;
// }
// function play_frame(scene_meta, frame){ // stop_play_flag = false;
// load_world(sceneName, frame);
// var scene_meta = data.get_current_world_scene_meta();
// var sceneName= scene_meta.scene;
// if (!stop_play_flag)
// { // play_frame(scene_meta, data.world.frameInfo.frame);
// var frame_index = scene_meta.frames.findIndex(function(x){return x == frame;});
// if (frame_index+1 < scene_meta.frames.length) // function play_frame(scene_meta, frame){
// { // load_world(sceneName, frame);
// next_frame = scene_meta.frames[frame_index+1];
// setTimeout( // if (!stop_play_flag)
// function(){ // {
// play_frame(scene_meta, next_frame); // var frame_index = scene_meta.frames.findIndex(function(x){return x == frame;});
// }, // if (frame_index+1 < scene_meta.frames.length)
// 100); // {
// } // next_frame = scene_meta.frames[frame_index+1];
// else{ // setTimeout(
// stop_play_flag = true; // function(){
// } // play_frame(scene_meta, next_frame);
// },
// } // 100);
// }; // }
// } // else{
// stop_play_flag = true;
// }
// }
// };
// }
} }
export { PlayControl };
export {PlayControl};

@ -1,185 +1,155 @@
class MovableView {
mouseDown = false;
mouseDownPos = null;
// move starts in dragableUi,
// movable in movableUi,
// the pos of posUi is set.
constructor(dragableUi, posUi, funcOnMove) {
let movableUi = document.getElementById("move-handle-wrapper");
dragableUi.addEventListener("mousedown", (event) => {
if (event.which == 1 && event.currentTarget == event.target) {
this.mouseDown = true;
this.mouseDownPos = { x: event.clientX, y: event.clientY };
movableUi.style.display = "inherit";
}
});
movableUi.addEventListener("mouseup", (event) => {
if (this.mouseDown) {
dragableUi.style.cursor = "";
event.stopPropagation();
event.preventDefault();
this.mouseDown = false;
movableUi.style.display = "none";
}
});
movableUi.addEventListener("mousemove", (event) => {
if (this.mouseDown) {
let posDelta = {
x: event.clientX - this.mouseDownPos.x,
y: event.clientY - this.mouseDownPos.y,
};
dragableUi.style.cursor = "move";
class MovableView this.mouseDownPos = { x: event.clientX, y: event.clientY };
{
mouseDown = false;
mouseDownPos = null;
// move starts in dragableUi,
// movable in movableUi,
// the pos of posUi is set.
constructor(dragableUi, posUi, funcOnMove)
{
let movableUi = document.getElementById("move-handle-wrapper");
dragableUi.addEventListener("mousedown", (event)=>{
if (event.which == 1 && event.currentTarget == event.target)
{
this.mouseDown = true;
this.mouseDownPos = {x: event.clientX, y:event.clientY};
movableUi.style.display="inherit";
}
});
movableUi.addEventListener("mouseup", (event)=>{
if (this.mouseDown){
dragableUi.style.cursor = "";
event.stopPropagation();
event.preventDefault();
this.mouseDown = false;
movableUi.style.display="none";
}
});
movableUi.addEventListener("mousemove", (event)=>{
if (this.mouseDown){
let posDelta = {
x: event.clientX - this.mouseDownPos.x,
y: event.clientY - this.mouseDownPos.y
};
dragableUi.style.cursor = "move";
this.mouseDownPos = {x: event.clientX, y:event.clientY};
let left = posUi.offsetLeft;
let top = posUi.offsetTop;
posUi.style.left = Math.max(0, (left + posDelta.x)) + 'px';
posUi.style.top = Math.max(0, (top + posDelta.y)) + 'px';
if (funcOnMove)
funcOnMove();
}
});
}
}
let left = posUi.offsetLeft;
let top = posUi.offsetTop;
class PopupDialog extends MovableView posUi.style.left = Math.max(0, left + posDelta.x) + "px";
{ posUi.style.top = Math.max(0, top + posDelta.y) + "px";
constructor(ui)
{
super(ui.querySelector("#header"), ui.querySelector("#view"));
this.ui = ui; //wrapper if (funcOnMove) funcOnMove();
this.viewUi = this.ui.querySelector("#view"); }
this.headerUi = this.ui.querySelector("#header"); });
this.titleUi = this.ui.querySelector("#title"); }
}
this.ui.onclick = ()=>{
this.hide();
};
this.ui.addEventListener("keydown", (event)=>{
if (event.key == 'Escape'){
this.hide();
event.preventDefault();
}
event.stopPropagation();
});
this.viewUi.onclick = function(event){
//event.preventDefault();
event.stopPropagation();
};
this.titleUi.onclick = function(event){
//event.preventDefault();
event.stopPropagation();
};
this.titleUi.addEventListener("mousedown", (event)=>{
//event.preventDefault();
event.stopPropagation();
});
this.titleUi.addEventListener("contextmenu", (event)=>{
event.stopPropagation();
})
// this.viewUi.addEventListener("contextmenu", (e)=>{
// e.stopPropagation();
// e.preventDefault();
// });
// this.ui.querySelector("#info-view").onclick = function(event){
// event.preventDefault();
// event.stopPropagation();
// };
this.ui.querySelector("#btn-exit").onclick = (event)=>{
this.hide();
}
this.maximizeButton = this.ui.querySelector("#btn-maximize")
if (this.maximizeButton)
{
this.maximizeButton.onclick = (event)=>{
let v = this.viewUi;
v.style.top = "0%";
v.style.left = "0%";
v.style.width = "100%";
v.style.height = "100%";
v.style["z-index"] = 5;
event.currentTarget.style.display = 'none';
this.ui.querySelector("#btn-restore").style.display = "inherit";
};
}
this.restoreButton = this.ui.querySelector("#btn-restore");
if (this.restoreButton) {
this.restoreButton.onclick = (event)=>{
let v = this.viewUi;
v.style.top = "20%";
v.style.left = "20%";
v.style.width = "60%";
v.style.height = "60%";
event.currentTarget.style.display = 'none';
this.ui.querySelector("#btn-maximize").style.display = "inherit";
};
}
class PopupDialog extends MovableView {
constructor(ui) {
super(ui.querySelector("#header"), ui.querySelector("#view"));
this.ui = ui; //wrapper
this.viewUi = this.ui.querySelector("#view");
this.headerUi = this.ui.querySelector("#header");
this.titleUi = this.ui.querySelector("#title");
this.ui.onclick = () => {
this.hide();
};
this.ui.addEventListener("keydown", (event) => {
if (event.key == "Escape") {
this.hide();
event.preventDefault();
}
event.stopPropagation();
});
this.viewUi.onclick = function (event) {
//event.preventDefault();
event.stopPropagation();
};
this.titleUi.onclick = function (event) {
//event.preventDefault();
event.stopPropagation();
};
this.titleUi.addEventListener("mousedown", (event) => {
//event.preventDefault();
event.stopPropagation();
});
this.titleUi.addEventListener("contextmenu", (event) => {
event.stopPropagation();
});
// this.viewUi.addEventListener("contextmenu", (e)=>{
// e.stopPropagation();
// e.preventDefault();
// });
// this.ui.querySelector("#info-view").onclick = function(event){
// event.preventDefault();
// event.stopPropagation();
// };
this.ui.querySelector("#btn-exit").onclick = (event) => {
this.hide();
};
this.maximizeButton = this.ui.querySelector("#btn-maximize");
if (this.maximizeButton) {
this.maximizeButton.onclick = (event) => {
let v = this.viewUi;
v.style.top = "0%";
v.style.left = "0%";
v.style.width = "100%";
v.style.height = "100%";
v.style["z-index"] = 5;
event.currentTarget.style.display = "none";
this.ui.querySelector("#btn-restore").style.display = "inherit";
};
} }
this.restoreButton = this.ui.querySelector("#btn-restore");
if (this.restoreButton) {
this.restoreButton.onclick = (event) => {
let v = this.viewUi;
v.style.top = "20%";
v.style.left = "20%";
v.style.width = "60%";
v.style.height = "60%";
event.currentTarget.style.display = "none";
this.ui.querySelector("#btn-maximize").style.display = "inherit";
};
}
}
hide(msg) {
this.ui.style.display = "none";
hide(msg) if (this.onExit) {
{ this.onExit(msg);
this.ui.style.display = 'none';
if (this.onExit)
{
this.onExit(msg);
}
}
show(onexit)
{
this.ui.style.display = 'inherit';
this.onExit = onexit;
//this.ui.focus();
} }
}
show(onexit) {
this.ui.style.display = "inherit";
this.onExit = onexit;
//this.ui.focus();
}
} }
export { PopupDialog, MovableView };
export {PopupDialog, MovableView}

@ -1,418 +1,423 @@
import * as THREE from './lib/three.module.js'; import * as THREE from "./lib/three.module.js";
import { PCDLoader } from './lib/PCDLoader.js'; import { PCDLoader } from "./lib/PCDLoader.js";
import { matmul, euler_angle_to_rotate_matrix_3by3} from "./util.js" import { matmul, euler_angle_to_rotate_matrix_3by3 } from "./util.js";
function Radar(sceneMeta, world, frameInfo, radarName){ function Radar(sceneMeta, world, frameInfo, radarName) {
this.world = world; this.world = world;
this.frameInfo = frameInfo; this.frameInfo = frameInfo;
this.name = radarName; this.name = radarName;
this.sceneMeta = sceneMeta; this.sceneMeta = sceneMeta;
this.coordinatesOffset = world.coordinatesOffset; this.coordinatesOffset = world.coordinatesOffset;
this.showPointsOnly = false; this.showPointsOnly = false;
this.showRadarBoxFlag = false; this.showRadarBoxFlag = false;
this.cssStyleSelector = this.sceneMeta.calib.radar[this.name].cssstyleselector; this.cssStyleSelector =
this.color = this.sceneMeta.calib.radar[this.name].color; this.sceneMeta.calib.radar[this.name].cssstyleselector;
this.velocityScale = 0.3; this.color = this.sceneMeta.calib.radar[this.name].color;
this.velocityScale = 0.3;
if (!this.color) {
this.color = [1.0, 0.0, 0.0];
}
this._radar_points_raw = null; // read from file, centered at 0
this.elements = null; // geometry points
this.preloaded = false;
this.loaded = false;
this.go_cmd_received = false;
this.webglScene = null;
this.on_go_finished = null;
this.go = function (webglScene, on_go_finished) {
this.webglScene = webglScene;
if (this.preloaded) {
if (this.elements) {
this.webglScene.add(this.elements.points);
if (!this.showPointsOnly)
this.elements.arrows.forEach((a) => this.webglScene.add(a));
if (this.showRadarBoxFlag) this.webglScene.add(this.radar_box);
}
this.loaded = true;
if (on_go_finished) on_go_finished();
}
//anyway we save go cmd
{
this.go_cmd_received = true;
this.on_go_finished = on_go_finished;
}
};
if (!this.color){ this.showRadarBox = function () {
this.color = [1.0, 0.0, 0.0]; this.showRadarBoxFlag = true;
this.webglScene.add(this.radar_box);
};
this.hideRadarBox = function () {
this.showRadarBoxFlag = false;
this.webglScene.remove(this.radar_box);
};
this.get_unoffset_radar_points = function () {
if (this.elements) {
let pts = this.elements.points.geometry.getAttribute("position").array;
return pts.map((p, i) => p - this.world.coordinatesOffset[i % 3]);
} else {
return [];
} }
};
this._radar_points_raw = null; // read from file, centered at 0 // todo: what if it's not preloaded yet
this.elements = null; // geometry points this.unload = function (keep_box) {
if (this.elements) {
this.webglScene.remove(this.elements.points);
if (!this.showPointsOnly)
this.elements.arrows.forEach((a) => this.webglScene.remove(a));
this.preloaded = false; if (!keep_box) this.webglScene.remove(this.radar_box);
}
this.loaded = false; this.loaded = false;
};
// todo: its possible to remove points before preloading,
this.deleteAll = function (keep_box) {
if (this.loaded) {
this.unload();
}
this.go_cmd_received = false; if (this.elements) {
this.webglScene = null; //this.scene.remove(this.points);
this.on_go_finished = null; this.world.data.dbg.free();
this.go = function(webglScene, on_go_finished){
this.webglScene = webglScene;
if (this.preloaded){ if (this.elements.points) {
if (this.elements){ this.elements.points.geometry.dispose();
this.webglScene.add(this.elements.points); this.elements.points.material.dispose();
}
if (!this.showPointsOnly) if (this.elements.arrows) {
this.elements.arrows.forEach(a=>this.webglScene.add(a)); this.elements.arrows.forEach((a) => {
this.world.data.dbg.free();
a.geometry.dispose();
a.material.dispose();
});
}
if (this.showRadarBoxFlag) this.elements = null;
this.webglScene.add(this.radar_box); }
}
this.loaded = true; if (!keep_box && this.radar_box) {
if (on_go_finished) this.world.data.dbg.free();
on_go_finished(); this.radar_box.geometry.dispose();
} this.radar_box.material.dispose();
this.radar_box = null;
//anyway we save go cmd }
{ };
this.go_cmd_received = true;
this.on_go_finished = on_go_finished; this.preload = function (on_preload_finished) {
} var loader = new PCDLoader();
};
var _self = this;
loader.load(
this.frameInfo.get_radar_path(this.name),
//ok
function (pcd) {
var position = pcd.position;
//var velocity = pcd.velocity;
// velocity is a vector anchored at position,
// we translate them into position of the vector head
var velocity = position.map(
(p, i) => pcd.velocity[i] + pcd.position[i]
);
this.showRadarBox = function(){ // scale velocity
this.showRadarBoxFlag = true; // velocity = velocity.map(v=>v*_self.velocityScale);
this.webglScene.add(this.radar_box);
};
this.hideRadarBox = function(){ //_self.points_parse_time = new Date().getTime();
this.showRadarBoxFlag = false; //console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "parse pionts ", _self.points_parse_time - _self.create_time, "ms");
this.webglScene.remove(this.radar_box); _self._radar_points_raw = position;
}; _self._radar_velocity_raw = velocity;
this.get_unoffset_radar_points = function(){ // add one box to calibrate radar with lidar
if (this.elements){ _self.radar_box = _self.createRadarBox();
let pts = this.elements.points.geometry.getAttribute("position").array;
return pts.map((p,i)=>p-this.world.coordinatesOffset[i %3]);
}
else{
return [];
}
};
// todo: what if it's not preloaded yet // install callback for box changing
this.unload = function(keep_box){ _self.radar_box.on_box_changed = () => {
if (this.elements){ _self.move_radar(_self.radar_box);
this.webglScene.remove(this.elements.points); };
if (!this.showPointsOnly)
this.elements.arrows.forEach(a=>this.webglScene.remove(a));
if (!keep_box)
this.webglScene.remove(this.radar_box);
}
this.loaded = false;
};
// todo: its possible to remove points before preloading, //position = _self.transformPointsByOffset(position);
this.deleteAll = function(keep_box){ position = _self.move_radar_points(_self.radar_box);
if (this.loaded){ velocity = _self.move_radar_velocity(_self.radar_box);
this.unload(); let elements = _self.buildRadarGeometry(position, velocity);
}
if (this.elements){
//this.scene.remove(this.points);
this.world.data.dbg.free();
if (this.elements.points)
{
this.elements.points.geometry.dispose();
this.elements.points.material.dispose();
}
if (this.elements.arrows)
{
this.elements.arrows.forEach(a=>{
this.world.data.dbg.free();
a.geometry.dispose();
a.material.dispose();
})
}
this.elements = null;
}
if (!keep_box && this.radar_box){
this.world.data.dbg.free();
this.radar_box.geometry.dispose();
this.radar_box.material.dispose();
this.radar_box = null;
}
};
_self.elements = elements;
//_self.points_backup = mesh;
this.preload = function(on_preload_finished){ _self._afterPreload();
var loader = new PCDLoader(); },
var _self = this; // on progress,
loader.load( this.frameInfo.get_radar_path(this.name), function () {},
//ok
function ( pcd ) { // on error
var position = pcd.position; function () {
//var velocity = pcd.velocity; //error
// velocity is a vector anchored at position, console.log("load radar failed.");
// we translate them into position of the vector head _self._afterPreload();
var velocity = position.map((p,i)=>pcd.velocity[i]+pcd.position[i]); },
// scale velocity // on file loaded
// velocity = velocity.map(v=>v*_self.velocityScale); function () {
//_self.points_readfile_time = new Date().getTime();
//_self.points_parse_time = new Date().getTime(); //console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "read file ", _self.points_readfile_time - _self.create_time, "ms");
//console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "parse pionts ", _self.points_parse_time - _self.create_time, "ms"); }
_self._radar_points_raw = position; );
_self._radar_velocity_raw = velocity; };
// add one box to calibrate radar with lidar // internal funcs below
_self.radar_box = _self.createRadarBox(); this._afterPreload = function () {
this.preloaded = true;
// install callback for box changing console.log(`radar ${this.radarname} preloaded`);
_self.radar_box.on_box_changed = ()=>{ if (this.on_preload_finished) {
_self.move_radar(_self.radar_box); this.on_preload_finished();
}; }
if (this.go_cmd_received) {
//position = _self.transformPointsByOffset(position); this.go(this.webglScene, this.on_go_finished);
position = _self.move_radar_points(_self.radar_box); }
velocity = _self.move_radar_velocity(_self.radar_box); };
let elements = _self.buildRadarGeometry(position, velocity);
_self.elements = elements;
//_self.points_backup = mesh;
_self._afterPreload();
},
// on progress,
function(){},
// on error
function(){
//error
console.log("load radar failed.");
_self._afterPreload();
},
// on file loaded
function(){
//_self.points_readfile_time = new Date().getTime();
//console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "read file ", _self.points_readfile_time - _self.create_time, "ms");
}
);
};
// internal funcs below this.createRadarBox = function () {
this._afterPreload = function(){ if (this.sceneMeta.calib.radar && this.sceneMeta.calib.radar[this.name]) {
this.preloaded = true; return this.world.annotation.createCuboid(
console.log(`radar ${this.radarname} preloaded`); {
if (this.on_preload_finished){ x:
this.on_preload_finished(); this.sceneMeta.calib.radar[this.name].translation[0] +
} this.coordinatesOffset[0],
if (this.go_cmd_received){ y:
this.go(this.webglScene, this.on_go_finished); this.sceneMeta.calib.radar[this.name].translation[1] +
} this.coordinatesOffset[1],
}; z:
this.sceneMeta.calib.radar[this.name].translation[2] +
this.coordinatesOffset[2],
},
{ x: 1, y: 1, z: 1 },
{
x: this.sceneMeta.calib.radar[this.name].rotation[0],
y: this.sceneMeta.calib.radar[this.name].rotation[1],
z: this.sceneMeta.calib.radar[this.name].rotation[2],
},
"radar",
this.name
);
} else {
return this.world.annotation.createCuboid(
{
x: this.coordinatesOffset[0],
y: this.coordinatesOffset[1],
z: this.coordinatesOffset[2],
},
{ x: 1, y: 1, z: 1 },
{ x: 0, y: 0, z: 0 },
"radar",
this.name
);
}
};
this.buildPoints = function (position) {
// build geometry
this.world.data.dbg.alloc();
let geometry = new THREE.BufferGeometry();
if (position.length > 0)
geometry.addAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
let pointColor = this.color;
let color = [];
for (var i = 0; i < position.length; i += 3) {
color.push(pointColor[0]);
color.push(pointColor[1]);
color.push(pointColor[2]);
}
this.createRadarBox = function(){ geometry.addAttribute("color", new THREE.Float32BufferAttribute(color, 3));
if (this.sceneMeta.calib.radar && this.sceneMeta.calib.radar[this.name]){
return this.world.annotation.createCuboid(
{
x: this.sceneMeta.calib.radar[this.name].translation[0] + this.coordinatesOffset[0],
y: this.sceneMeta.calib.radar[this.name].translation[1] + this.coordinatesOffset[1],
z: this.sceneMeta.calib.radar[this.name].translation[2] + this.coordinatesOffset[2],
},
{x:1,y:1, z:1},
{
x: this.sceneMeta.calib.radar[this.name].rotation[0],
y: this.sceneMeta.calib.radar[this.name].rotation[1],
z: this.sceneMeta.calib.radar[this.name].rotation[2],
},
"radar",
this.name);
}else {
return this.world.annotation.createCuboid(
{x: this.coordinatesOffset[0],
y: this.coordinatesOffset[1],
z: this.coordinatesOffset[2]},
{x:1,y:1, z:1},
{x:0,y:0,z:0},
"radar",
this.name);
}
};
this.buildPoints = function(position){ geometry.computeBoundingSphere();
// build geometry
this.world.data.dbg.alloc();
let geometry = new THREE.BufferGeometry();
if ( position.length > 0 )
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) );
let pointColor = this.color;
let color=[];
for (var i =0; i< position.length; i+=3){
color.push(pointColor[0]);
color.push(pointColor[1]);
color.push(pointColor[2]);
}
geometry.addAttribute( 'color', new THREE.Float32BufferAttribute(color, 3 ) );
geometry.computeBoundingSphere();
// build material
let pointSize = this.sceneMeta.calib.radar[this.name].point_size;
if (!pointSize)
pointSize = 2;
let material = new THREE.PointsMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
//material.size = 2;
material.sizeAttenuation = false;
// build mesh
let mesh = new THREE.Points( geometry, material );
mesh.name = "radar";
return mesh;
};
this.buildArrow = function(position, velocity){ // build material
var h = 0.5; let pointSize = this.sceneMeta.calib.radar[this.name].point_size;
if (!pointSize) pointSize = 2;
let p=position;
let v=velocity;
var body = [ let material = new THREE.PointsMaterial({
p[0],p[1],p[2], size: pointSize,
v[0],v[1],v[2], vertexColors: THREE.VertexColors,
]; });
//material.size = 2;
material.sizeAttenuation = false;
this.world.data.dbg.alloc(); // build mesh
var geo = new THREE.BufferGeometry(); let mesh = new THREE.Points(geometry, material);
geo.addAttribute( 'position', new THREE.Float32BufferAttribute(body, 3 ) ); mesh.name = "radar";
let color = this.color.map(c=>Math.round(c*255)).reduce((a,b)=>a*256+b, 0); return mesh;
};
var material = new THREE.LineBasicMaterial( { color: color, linewidth: 1, opacity: 1, transparent: true } ); this.buildArrow = function (position, velocity) {
var arrow = new THREE.LineSegments( geo, material ); var h = 0.5;
return arrow;
}
this.buildRadarGeometry = function(position, velocity){ let p = position;
let points = this.buildPoints(position); let v = velocity;
let arrows = []; var body = [p[0], p[1], p[2], v[0], v[1], v[2]];
if (!this.showPointsOnly)
{
for (let i = 0; i<position.length/3; i++)
{
let arr = this.buildArrow(position.slice(i*3, i*3+3), velocity.slice(i*3, i*3+3));
arrows.push(arr);
}
}
return {
points: points,
arrows: arrows
};
};
this.move_points = function(points, box){ this.world.data.dbg.alloc();
let trans = euler_angle_to_rotate_matrix_3by3(box.rotation); var geo = new THREE.BufferGeometry();
let rotated_points = matmul(trans, points, 3); geo.addAttribute("position", new THREE.Float32BufferAttribute(body, 3));
let translation=[box.position.x, box.position.y, box.position.z];
let translated_points = rotated_points.map((p,i)=>{
return p + translation[i % 3];
});
return translated_points;
};
this.move_radar_points = function(box){ let color = this.color
return this.move_points(this._radar_points_raw, box); .map((c) => Math.round(c * 255))
}; .reduce((a, b) => a * 256 + b, 0);
this.move_radar_velocity = function(box){ var material = new THREE.LineBasicMaterial({
return this.move_points(this._radar_velocity_raw, box); color: color,
} linewidth: 1,
opacity: 1,
transparent: true,
});
var arrow = new THREE.LineSegments(geo, material);
return arrow;
};
this.move_radar= function(box){ this.buildRadarGeometry = function (position, velocity) {
let points = this.buildPoints(position);
let translated_points = this.move_radar_points(box); let arrows = [];
let translated_velocity = this.move_radar_velocity(box);
let elements = this.buildRadarGeometry(translated_points, translated_velocity); if (!this.showPointsOnly) {
for (let i = 0; i < position.length / 3; i++) {
// remove old points let arr = this.buildArrow(
this.unload(true); position.slice(i * 3, i * 3 + 3),
this.deleteAll(true); velocity.slice(i * 3, i * 3 + 3)
);
arrows.push(arr);
}
}
this.elements = elements; return {
//_self.points_backup = mesh; points: points,
if (this.go_cmd_received) // this should be always true arrows: arrows,
{
this.webglScene.add(this.elements.points);
if (!this.showPointsOnly)
this.elements.arrows.forEach(a=>this.webglScene.add(a));
}
}; };
};
this.move_points = function (points, box) {
let trans = euler_angle_to_rotate_matrix_3by3(box.rotation);
let rotated_points = matmul(trans, points, 3);
let translation = [box.position.x, box.position.y, box.position.z];
let translated_points = rotated_points.map((p, i) => {
return p + translation[i % 3];
});
return translated_points;
};
this.move_radar_points = function (box) {
return this.move_points(this._radar_points_raw, box);
};
this.move_radar_velocity = function (box) {
return this.move_points(this._radar_velocity_raw, box);
};
this.move_radar = function (box) {
let translated_points = this.move_radar_points(box);
let translated_velocity = this.move_radar_velocity(box);
let elements = this.buildRadarGeometry(
translated_points,
translated_velocity
);
// remove old points
this.unload(true);
this.deleteAll(true);
this.elements = elements;
//_self.points_backup = mesh;
if (this.go_cmd_received) {
// this should be always true
this.webglScene.add(this.elements.points);
if (!this.showPointsOnly)
this.elements.arrows.forEach((a) => this.webglScene.add(a));
}
};
} }
function RadarManager(sceneMeta, world, frameInfo){ function RadarManager(sceneMeta, world, frameInfo) {
this.radarList = []; this.radarList = [];
if (world.data.cfg.enableRadar && sceneMeta.radar){ if (world.data.cfg.enableRadar && sceneMeta.radar) {
let radars = []; let radars = [];
for (let r in sceneMeta.calib.radar){
if (!sceneMeta.calib.radar[r].disable)
radars.push(r);
}
this.radarList = radars.map(name=>{ for (let r in sceneMeta.calib.radar) {
return new Radar(sceneMeta, world, frameInfo, name); if (!sceneMeta.calib.radar[r].disable) radars.push(r);
});
} }
this.getAllBoxes = function() this.radarList = radars.map((name) => {
{ return new Radar(sceneMeta, world, frameInfo, name);
if (this.showRadarBoxFlag) });
{ }
return this.radarList.map(r=>r.radar_box);
}
else
{
return [];
}
};
this.preloaded = function(){ this.getAllBoxes = function () {
for (let r in this.radarList){ if (this.showRadarBoxFlag) {
if (!this.radarList[r].preloaded) return this.radarList.map((r) => r.radar_box);
return false; } else {
} return [];
return true; }
}; };
this.go = function(webglScene, on_go_finished){ this.preloaded = function () {
this.radarList.forEach(r=>r.go(webglScene, on_go_finished)); for (let r in this.radarList) {
}; if (!this.radarList[r].preloaded) return false;
}
return true;
};
this.preload = function(on_preload_finished){ this.go = function (webglScene, on_go_finished) {
this.radarList.forEach(r=>r.preload(on_preload_finished)); this.radarList.forEach((r) => r.go(webglScene, on_go_finished));
}; };
this.unload = function(){ this.preload = function (on_preload_finished) {
this.radarList.forEach(r=>r.unload()); this.radarList.forEach((r) => r.preload(on_preload_finished));
}; };
this.deleteAll = function(){ this.unload = function () {
this.radarList.forEach(r=>r.deleteAll()); this.radarList.forEach((r) => r.unload());
}; };
this.getOperableObjects = function(){ this.deleteAll = function () {
return this.radarList.flatMap(r=>r.getOperableObjects()); this.radarList.forEach((r) => r.deleteAll());
}; };
this.showRadarBoxFlag = false; this.getOperableObjects = function () {
this.showRadarBox = function(){ return this.radarList.flatMap((r) => r.getOperableObjects());
this.showRadarBoxFlag = true; };
this.radarList.forEach(r=>r.showRadarBox());
};
this.hideRadarBox = function(){ this.showRadarBoxFlag = false;
this.showRadarBoxFlag = false; this.showRadarBox = function () {
this.radarList.forEach(r=>r.hideRadarBox()); this.showRadarBoxFlag = true;
} this.radarList.forEach((r) => r.showRadarBox());
}; };
this.hideRadarBox = function () {
this.showRadarBoxFlag = false;
this.radarList.forEach((r) => r.hideRadarBox());
};
}
export {RadarManager} export { RadarManager };

@ -1,234 +1,226 @@
import * as THREE from './lib/three.module.js'; import * as THREE from "./lib/three.module.js";
import { PCDLoader } from './lib/PCDLoader.js'; import { PCDLoader } from "./lib/PCDLoader.js";
import { OrbitControls } from './lib/OrbitControls.js'; import { OrbitControls } from "./lib/OrbitControls.js";
import { GUI } from './lib/dat.gui.module.js'; import { GUI } from "./lib/dat.gui.module.js";
import {TextFileLoader} from "./text_file_loader.js"; import { TextFileLoader } from "./text_file_loader.js";
var container, stats; var container, stats;
var camera, controls, scene, renderer; var camera, controls, scene, renderer;
var camera; var camera;
var params = { var params = {
src: true, src: true,
tgt: true, tgt: true,
out: true, out: true,
reload: load_all, reload: load_all,
}; };
var last_cloud_ind = { var last_cloud_ind = {
src: true, src: true,
tgt: true, tgt: true,
out: true, out: true,
} };
var clouds ={}; var clouds = {};
init(); init();
animate(); animate();
function init() { function init() {
document.body.addEventListener('keydown', event => { document.body.addEventListener("keydown", (event) => {
if (event.ctrlKey && 'asdv'.indexOf(event.key) !== -1) { if (event.ctrlKey && "asdv".indexOf(event.key) !== -1) {
event.preventDefault() event.preventDefault();
} }
}) });
scene = new THREE.Scene(); scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
camera = new THREE.PerspectiveCamera(
65,
window.innerWidth / window.innerHeight,
1,
800
);
camera.position.x = 0;
camera.position.z = 50;
camera.position.y = 0;
camera.up.set(0, 0, 1);
camera.lookAt(0, 0, 0);
renderer = new THREE.WebGLRenderer( { antialias: true } ); controls = new OrbitControls(camera, renderer.domElement);
renderer.setPixelRatio( window.devicePixelRatio ); controls.addEventListener("change", render); // call this only in static scenes (i.e., if there is no animation loop)
container = document.createElement("container");
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera( 65, window.innerWidth / window.innerHeight, 1, 800 ); container.appendChild(renderer.domElement);
camera.position.x = 0;
camera.position.z = 50;
camera.position.y = 0;
camera.up.set( 0, 0, 1);
camera.lookAt( 0, 0, 0 );
document.addEventListener("keydown", keydown);
controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
container = document.createElement( 'container' );
document.body.appendChild( container ); init_gui();
container.appendChild( renderer.domElement ); //scene.add( new THREE.AxesHelper( 2 ) );
document.addEventListener("keydown", keydown) onWindowResize();
window.addEventListener("resize", onWindowResize, false);
init_gui(); load_all();
//scene.add( new THREE.AxesHelper( 2 ) );
onWindowResize(); render();
window.addEventListener( 'resize', onWindowResize, false );
load_all();
render();
} }
function load_all(){ function load_all() {
clearAll();
clearAll(); load_pcd("src", "/temp/src.pcd", 0xff0000);
load_pcd("src", "/temp/src.pcd", 0xff0000); load_pcd("tgt", "/temp/tgt.pcd", 0x00ff00);
load_pcd("tgt", "/temp/tgt.pcd", 0x00ff00); load_pcd("out", "/temp/out.pcd", 0xffff00);
load_pcd("out", "/temp/out.pcd", 0xffff00); load_transform_matrix();
load_transform_matrix();
} }
function clearAll(){ function clearAll() {
remove(clouds["src"]);
remove(clouds["src"]); remove(clouds["tgt"]);
remove(clouds["tgt"]); remove(clouds["out"]);
remove(clouds["out"]);
clouds["src"] = null;
clouds["tgt"] = null;
clouds["our"] = null;
function remove(p){
if (p){
scene.remove(p);
p.geometry.dispose();
p.material.dispose();
}
}
}
clouds["src"] = null;
clouds["tgt"] = null;
clouds["our"] = null;
function keydown( ev ) { function remove(p) {
if (p) {
switch ( ev.key) { scene.remove(p);
case '+': p.geometry.dispose();
clouds["src"].material.size *= 1.2; p.material.dispose();
clouds["tgt"].material.size *= 1.2;
clouds["out"].material.size *= 1.2;
break;
case '-':
clouds["src"].material.size /= 1.2;
clouds["tgt"].material.size /= 1.2;
clouds["out"].material.size /= 1.2;
break;
} }
}
} }
function keydown(ev) {
switch (ev.key) {
case "+":
clouds["src"].material.size *= 1.2;
clouds["tgt"].material.size *= 1.2;
clouds["out"].material.size *= 1.2;
break;
case "-":
clouds["src"].material.size /= 1.2;
clouds["tgt"].material.size /= 1.2;
clouds["out"].material.size /= 1.2;
break;
}
}
function onWindowResize() { function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight; camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix(); camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setSize(window.innerWidth, window.innerHeight);
} }
function animate() { function animate() {
requestAnimationFrame( animate ); requestAnimationFrame(animate);
controls.update(); controls.update();
render(); render();
switch_cloud("src"); switch_cloud("src");
switch_cloud("tgt"); switch_cloud("tgt");
switch_cloud("out"); switch_cloud("out");
function switch_cloud(name){ function switch_cloud(name) {
if (params[name] != last_cloud_ind[name]){ if (params[name] != last_cloud_ind[name]) {
last_cloud_ind[name] = params[name]; last_cloud_ind[name] = params[name];
if (last_cloud_ind[name]){ if (last_cloud_ind[name]) {
scene.add(clouds[name]); scene.add(clouds[name]);
}else { } else {
scene.remove(clouds[name]); scene.remove(clouds[name]);
} }
}
} }
}
} }
function render() {
function render(){ renderer.render(scene, camera);
renderer.render( scene, camera );
} }
function load_transform_matrix(){ function load_transform_matrix() {
var loader = new TextFileLoader(); var loader = new TextFileLoader();
loader.load( "/temp/trans.json", loader.load("/temp/trans.json", function (json) {
function(json){ console.log(json);
console.log(json); var mat = JSON.parse(json);
var mat = JSON.parse(json);
var trans_html = "<table><tbody>";
var trans_html = "<table><tbody>"; for (var i = 0; i < 4; i++) {
for (var i = 0; i<4; i++){ trans_html += "<tr>";
for (var j = 0; j < 4; j++)
trans_html += "<tr>"; trans_html += "<td>" + mat[i * 4 + j] + "</td>";
for (var j =0; j<4; j++) trans_html += "</tr>";
trans_html += "<td>"+ mat[i*4+j] + "</td>"; }
trans_html += "</tr>" trans_html += "</tbody></table>";
} document.getElementById("info").innerHTML = trans_html;
trans_html += "</tbody></table>"; });
document.getElementById("info").innerHTML = trans_html;
}
)
} }
function load_pcd(name, file, overall_color){ function load_pcd(name, file, overall_color) {
var loader = new PCDLoader(); var loader = new PCDLoader();
loader.load( file, loader.load(file, function (pcd) {
function ( pcd ) { var position = pcd.position;
var position = pcd.position; var color = pcd.color;
var color = pcd.color; var normal = pcd.normal;
var normal = pcd.normal; // build geometry
// build geometry var geometry = new THREE.BufferGeometry();
var geometry = new THREE.BufferGeometry(); if (position.length > 0)
if ( position.length > 0 ) geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) ); geometry.addAttribute(
if ( normal.length > 0 ) geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normal, 3 ) ); "position",
if ( color.length > 0 ) geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( color, 3 ) ); new THREE.Float32BufferAttribute(position, 3)
);
geometry.computeBoundingSphere(); if (normal.length > 0)
// build material geometry.addAttribute(
"normal",
var material = new THREE.PointsMaterial( { size: 0.005 } ); new THREE.Float32BufferAttribute(normal, 3)
);
if ( color.length > 0 ) { if (color.length > 0)
material.vertexColors = VertexColors; geometry.addAttribute(
} else { "color",
material.color.setHex(overall_color ); new THREE.Float32BufferAttribute(color, 3)
} );
//material.size = 0.1; geometry.computeBoundingSphere();
// build material
var material = new THREE.PointsMaterial({ size: 0.005 });
if (color.length > 0) {
material.vertexColors = VertexColors;
} else {
material.color.setHex(overall_color);
}
// build mesh //material.size = 0.1;
var mesh = new THREE.Points( geometry, material ); // build mesh
mesh.name = "pcd";
//return mesh; var mesh = new THREE.Points(geometry, material);
if (params[name]) mesh.name = "pcd";
scene.add(mesh);
clouds[name] = mesh; //return mesh;
//var center = points.geometry.boundingSphere.center; if (params[name]) scene.add(mesh);
//controls.target.set( center.x, center.y, center.z );
//controls.update();
},
);
clouds[name] = mesh;
//var center = points.geometry.boundingSphere.center;
//controls.target.set( center.x, center.y, center.z );
//controls.update();
});
} }
function init_gui() {
var gui = new GUI();
var cfgFolder = gui.addFolder("View");
function init_gui(){ cfgFolder.add(params, "src");
var gui = new GUI(); cfgFolder.add(params, "tgt");
cfgFolder.add(params, "out");
var cfgFolder = gui.addFolder( 'View' ); cfgFolder.add(params, "reload");
cfgFolder.open();
gui.open();
cfgFolder.add( params, "src"); }
cfgFolder.add( params, "tgt");
cfgFolder.add( params, "out");
cfgFolder.add( params, "reload");
cfgFolder.open();
gui.open();
}

@ -1,148 +1,134 @@
import { Editor } from "./editor.js";
import { checkScene } from "./error_check.js";
import { logger } from "./log.js";
function reloadWorldList(worldList, done) {
var xhr = new XMLHttpRequest();
// we defined the xhr
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
let anns = JSON.parse(this.responseText);
import { Editor } from "./editor.js"; // load annotations
import { checkScene } from "./error_check.js"; anns.forEach((a) => {
import {logger} from "./log.js" let world = worldList.find((w) => {
return w.frameInfo.scene == a.scene && w.frameInfo.frame == a.frame;
});
if (world) {
world.annotation.reapplyAnnotation(a.annotation);
function reloadWorldList(worldList, done){ } else {
var xhr = new XMLHttpRequest(); console.error("bug?");
// we defined the xhr
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
let anns = JSON.parse(this.responseText);
// load annotations
anns.forEach(a=>{
let world = worldList.find(w=>{
return (w.frameInfo.scene == a.scene &&
w.frameInfo.frame == a.frame);
});
if (world){
world.annotation.reapplyAnnotation(a.annotation);
}
else{
console.error("bug?");
}
});
if (done)
done();
} }
});
if (done) done();
}
};
xhr.open("POST", "/loadworldlist", true);
let para = worldList.map((w) => {
return {
//todo: we could add an id, so as to associate world easily
scene: w.frameInfo.scene,
frame: w.frameInfo.frame,
}; };
});
xhr.open('POST', "/loadworldlist", true);
let para = worldList.map(w=>{
return {
//todo: we could add an id, so as to associate world easily
scene: w.frameInfo.scene,
frame: w.frameInfo.frame,
};
});
xhr.send(JSON.stringify(para));
}
xhr.send(JSON.stringify(para));
}
var saveDelayTimer = null; var saveDelayTimer = null;
var pendingSaveList = []; var pendingSaveList = [];
function saveWorldList(worldList){ function saveWorldList(worldList) {
//pendingSaveList = pendingSaveList.concat(worldList);
//pendingSaveList = pendingSaveList.concat(worldList); worldList.forEach((w) => {
if (!pendingSaveList.includes(w)) pendingSaveList.push(w);
});
worldList.forEach(w=>{ if (saveDelayTimer) {
if (!pendingSaveList.includes(w)) clearTimeout(saveDelayTimer);
pendingSaveList.push(w); }
});
if (saveDelayTimer) saveDelayTimer = setTimeout(
{ () => {
clearTimeout(saveDelayTimer); logger.log("save delay expired.");
}
saveDelayTimer = setTimeout(()=>{
logger.log("save delay expired.");
//pandingSaveList will be cleared soon. //pandingSaveList will be cleared soon.
let scene = pendingSaveList[0].frameInfo.scene; let scene = pendingSaveList[0].frameInfo.scene;
doSaveWorldList(pendingSaveList, ()=>{ doSaveWorldList(pendingSaveList, () => {
editor.header.updateModifiedStatus(); editor.header.updateModifiedStatus();
checkScene(scene); checkScene(scene);
}); });
//reset //reset
saveDelayTimer = null; saveDelayTimer = null;
pendingSaveList = []; pendingSaveList = [];
},
500
}, );
500);
} }
function doSaveWorldList(worldList, done) {
function doSaveWorldList(worldList, done) if (worldList.length > 0) {
{ if (worldList[0].data.cfg.disableLabels) {
if (worldList.length>0){ console.log("labels not loaded, save action is prohibitted.");
if (worldList[0].data.cfg.disableLabels){ return;
console.log("labels not loaded, save action is prohibitted.")
return;
}
} }
}
console.log(worldList.length, "frames"); console.log(worldList.length, "frames");
let ann = worldList.map(w=>{ let ann = worldList.map((w) => {
return { return {
scene: w.frameInfo.scene, scene: w.frameInfo.scene,
frame: w.frameInfo.frame, frame: w.frameInfo.frame,
annotation: w.annotation.toBoxAnnotations(), annotation: w.annotation.toBoxAnnotations(),
};
})
var xhr = new XMLHttpRequest();
xhr.open("POST", "/saveworldlist", true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
worldList.forEach(w=>{
w.annotation.resetModified();
})
logger.log(`saved: ${worldList[0].frameInfo.scene}: ${worldList.reduce((a,b)=>a+" "+b.frameInfo.frame, "")}`);
if(done){
done();
}
}
else{
window.editor.infoBox.show("Error", `save failed, status : ${this.status}`);
}
// end of state change: it can be after some time (async)
}; };
});
var xhr = new XMLHttpRequest();
xhr.open("POST", "/saveworldlist", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
worldList.forEach((w) => {
w.annotation.resetModified();
});
logger.log(
`saved: ${worldList[0].frameInfo.scene}: ${worldList.reduce(
(a, b) => a + " " + b.frameInfo.frame,
""
)}`
);
if (done) {
done();
}
} else {
window.editor.infoBox.show(
"Error",
`save failed, status : ${this.status}`
);
}
// end of state change: it can be after some time (async)
};
var b = JSON.stringify(ann); var b = JSON.stringify(ann);
//console.log(b); //console.log(b);
xhr.send(b); xhr.send(b);
} }
// function saveWorld(world, done){ // function saveWorld(world, done){
@ -160,7 +146,7 @@ function doSaveWorldList(worldList, done)
// xhr.onreadystatechange = function () { // xhr.onreadystatechange = function () {
// if (this.readyState != 4) return; // if (this.readyState != 4) return;
// if (this.status == 200) { // if (this.status == 200) {
// logger.log(`saved: ${world}`); // logger.log(`saved: ${world}`);
// world.annotation.resetModified(); // world.annotation.resetModified();
@ -173,10 +159,8 @@ function doSaveWorldList(worldList, done)
// done(); // done();
// } // }
// } // }
// // end of state change: it can be after some time (async) // // end of state change: it can be after some time (async)
// }; // };
@ -185,5 +169,4 @@ function doSaveWorldList(worldList, done)
// xhr.send(b); // xhr.send(b);
// } // }
export { saveWorldList, reloadWorldList };
export {saveWorldList, reloadWorldList}

@ -1,7 +1,6 @@
var settings= { var settings = {
ground_filter_height: 0.2, ground_filter_height: 0.2,
initial_z_position: -0.9, initial_z_position: -0.9,
};
} export { settings };
export {settings}

File diff suppressed because it is too large Load Diff

@ -1,80 +1,84 @@
import * as THREE from "./lib/three.module.js";
import * as THREE from './lib/three.module.js';
//import Stats from './lib/stats.module.js'; //import Stats from './lib/stats.module.js';
import { OrthographicTrackballControls } from './lib/OrthographicTrackballControls.js'; import { OrthographicTrackballControls } from "./lib/OrthographicTrackballControls.js";
var camera, controls, scene, renderer, stats; var camera, controls, scene, renderer, stats;
init(); init();
animate(); animate();
function init() { function init() {
camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 2000 ); camera = new THREE.OrthographicCamera(
camera.position.z = 1000; window.innerWidth / -2,
// world window.innerWidth / 2,
scene = new THREE.Scene(); window.innerHeight / 2,
scene.background = new THREE.Color( 0xcccccc ); window.innerHeight / -2,
scene.fog = new THREE.FogExp2( 0xcccccc, 0.001 ); 1,
var geometry = new THREE.CylinderBufferGeometry( 0, 10, 30, 4, 1 ); 2000
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true } ); );
for ( var i = 0; i < 50; i ++ ) { camera.position.z = 1000;
var mesh = new THREE.Mesh( geometry, material ); // world
mesh.position.x = ( Math.random() - 0.5 ) * 1000; scene = new THREE.Scene();
mesh.position.y = ( Math.random() - 0.5 ) * 1000; scene.background = new THREE.Color(0xcccccc);
mesh.position.z = ( Math.random() - 0.5 ) * 1000; scene.fog = new THREE.FogExp2(0xcccccc, 0.001);
mesh.updateMatrix(); var geometry = new THREE.CylinderBufferGeometry(0, 10, 30, 4, 1);
mesh.matrixAutoUpdate = false; var material = new THREE.MeshPhongMaterial({
scene.add( mesh ); color: 0xffffff,
} flatShading: true,
// lights });
var light = new THREE.DirectionalLight( 0xffffff ); for (var i = 0; i < 50; i++) {
light.position.set( 1, 1, 1 ); var mesh = new THREE.Mesh(geometry, material);
scene.add( light ); mesh.position.x = (Math.random() - 0.5) * 1000;
var light = new THREE.DirectionalLight( 0x002288 ); mesh.position.y = (Math.random() - 0.5) * 1000;
light.position.set( - 1, - 1, - 1 ); mesh.position.z = (Math.random() - 0.5) * 1000;
scene.add( light ); mesh.updateMatrix();
var light = new THREE.AmbientLight( 0x222222 ); mesh.matrixAutoUpdate = false;
scene.add( light ); scene.add(mesh);
// renderer }
renderer = new THREE.WebGLRenderer( { antialias: true } ); // lights
renderer.setPixelRatio( window.devicePixelRatio ); var light = new THREE.DirectionalLight(0xffffff);
renderer.setSize( window.innerWidth, window.innerHeight ); light.position.set(1, 1, 1);
document.body.appendChild( renderer.domElement ); scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
// renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
controls = new OrthographicTrackballControls( camera, renderer.domElement ); controls = new OrthographicTrackballControls(camera, renderer.domElement);
controls.rotateSpeed = 1.0; controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2; controls.zoomSpeed = 1.2;
controls.noZoom = false; controls.noZoom = false;
controls.noPan = false; controls.noPan = false;
controls.staticMoving = true; controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3; controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ]; controls.keys = [65, 83, 68];
controls.addEventListener( 'change', render ); controls.addEventListener("change", render);
//stats = new Stats();
//document.body.appendChild( stats.dom );
//stats = new Stats(); //
//document.body.appendChild( stats.dom ); window.addEventListener("resize", onWindowResize, false);
// //
window.addEventListener( 'resize', onWindowResize, false ); render();
//
render();
} }
function onWindowResize() { function onWindowResize() {
camera.left = window.innerWidth / - 2; camera.left = window.innerWidth / -2;
camera.right = window.innerWidth / 2; camera.right = window.innerWidth / 2;
camera.top = window.innerHeight / 2; camera.top = window.innerHeight / 2;
camera.bottom = window.innerHeight / - 2; camera.bottom = window.innerHeight / -2;
camera.updateProjectionMatrix(); camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize(); controls.handleResize();
render(); render();
} }
function animate() { function animate() {
requestAnimationFrame( animate ); requestAnimationFrame(animate);
controls.update(); controls.update();
//stats.update(); //stats.update();
} }
function render() { function render() {
renderer.render( scene, camera ); renderer.render(scene, camera);
} }

@ -1,57 +1,46 @@
import { import {
DefaultLoadingManager, DefaultLoadingManager,
FileLoader, FileLoader,
LoaderUtils, LoaderUtils,
} from "./lib/three.module.js"; } from "./lib/three.module.js";
var TextFileLoader = function ( manager ) { var TextFileLoader = function (manager) {
this.manager = manager !== undefined ? manager : DefaultLoadingManager;
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; this.littleEndian = true;
this.littleEndian = true;
}; };
TextFileLoader.prototype = { TextFileLoader.prototype = {
constructor: TextFileLoader,
constructor: TextFileLoader,
load: function (url, onLoad, onProgress, onError) {
load: function ( url, onLoad, onProgress, onError ) { var scope = this;
var scope = this; var loader = new FileLoader(scope.manager);
loader.setPath(scope.path);
var loader = new FileLoader( scope.manager ); loader.setResponseType("arraybuffer");
loader.setPath( scope.path ); loader.load(
loader.setResponseType( 'arraybuffer' ); url,
loader.load( url, function ( data ) { function (data) {
try {
try { var textData = LoaderUtils.decodeText(new Uint8Array(data));
var textData = LoaderUtils.decodeText( new Uint8Array( data ) ); onLoad(textData, url);
onLoad(textData, url); } catch (e) {
} catch ( e ) { if (onError) {
onError(e);
if ( onError ) { } else {
throw e;
onError( e ); }
}
} else { },
onProgress,
throw e; onError
);
} },
} setPath: function (value) {
this.path = value;
}, onProgress, onError ); return this;
},
},
setPath: function ( value ) {
this.path = value;
return this;
},
}; };
export { TextFileLoader }; export { TextFileLoader };

@ -1,173 +1,157 @@
import { PopupDialog } from "./popup_dialog.js"; import { PopupDialog } from "./popup_dialog.js";
class Trajectory extends PopupDialog {
mouseDown = false;
class Trajectory extends PopupDialog{
constructor(ui) {
mouseDown = false; super(ui);
this.ui = ui;
constructor(ui) this.ui.addEventListener("keydown", (event) => {
{ //anykey
super(ui);
this.ui = ui; if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
this.hide();
event.preventDefault();
this.ui.addEventListener("keydown", (event)=>{ //anykey event.stopPropagation();
}
if (!event.ctrlKey && !event.shiftKey && !event.altKey) });
{
this.hide(); this.tracksUi = this.ui.querySelector("#svg-arrows");
event.preventDefault();
event.stopPropagation(); this.svgUi = this.ui.querySelector("#object-track-svg");
}
}); this.svgUi.addEventListener("wheel", (event) => {
console.log("wheel", event.wheelDelta);
this.tracksUi = this.ui.querySelector("#svg-arrows"); let scaleRatio = event.wheelDelta / 2400;
this.svgUi = this.ui.querySelector("#object-track-svg"); if (event.ctrlKey) {
this.objScale *= 1 + scaleRatio;
this.svgUi.addEventListener("wheel", (event)=>{ } else {
console.log("wheel", event.wheelDelta); let clientLength = Math.min(
this.svgUi.clientWidth,
this.svgUi.clientHeight
let scaleRatio = event.wheelDelta/2400; );
if (event.ctrlKey) let currentTargetRect = event.currentTarget.getBoundingClientRect();
{ let eventOffsetX = event.pageX - currentTargetRect.left;
this.objScale *= 1 + (scaleRatio); let eventOffsetY = event.pageY - currentTargetRect.top;
}
else let x = (eventOffsetX / clientLength) * 1000;
{ let y = (eventOffsetY / clientLength) * 1000;
let clientLength = Math.min(this.svgUi.clientWidth, this.svgUi.clientHeight);
this.posTrans.x = x - (x - this.posTrans.x) * (1 + scaleRatio);
let currentTargetRect = event.currentTarget.getBoundingClientRect(); this.posTrans.y = y - (y - this.posTrans.y) * (1 + scaleRatio);
let eventOffsetX = event.pageX - currentTargetRect.left;
let eventOffsetY = event.pageY - currentTargetRect.top; this.posScale *= 1 + scaleRatio;
}
let x = eventOffsetX/clientLength*1000;
let y = eventOffsetY/clientLength*1000; this.redrawAll();
this.posTrans.x = x - (x-this.posTrans.x) * (1+scaleRatio); event.preventDefault();
this.posTrans.y = y - (y-this.posTrans.y) * (1+scaleRatio); event.stopPropagation();
return false;
this.posScale *= 1 + (scaleRatio); });
}
this.inMovingCanvas = false;
this.startPosForMovingCanvas = {};
this.redrawAll(); this.svgUi.addEventListener("mousedown", (event) => {
this.inMovingCanvas = true;
event.preventDefault(); this.startPosForMovingCanvas = { x: event.pageX, y: event.pageY };
event.stopPropagation(); });
this.svgUi.addEventListener("mouseup", (event) => {
return false; this.inMovingCanvas = false;
}); });
this.svgUi.addEventListener("mousemove", (event) => {
this.inMovingCanvas = false; if (this.inMovingCanvas) {
this.startPosForMovingCanvas = {}; let delta = {
this.svgUi.addEventListener("mousedown", (event)=>{ x: event.pageX - this.startPosForMovingCanvas.x,
this.inMovingCanvas = true; y: event.pageY - this.startPosForMovingCanvas.y,
this.startPosForMovingCanvas = {x: event.pageX, y:event.pageY};
});
this.svgUi.addEventListener("mouseup", (event)=>{
this.inMovingCanvas = false;
});
this.svgUi.addEventListener("mousemove", (event)=>{
if (this.inMovingCanvas)
{
let delta = {
x: event.pageX - this.startPosForMovingCanvas.x,
y: event.pageY - this.startPosForMovingCanvas.y
};
let clientLength = Math.min(this.svgUi.clientWidth, this.svgUi.clientHeight);
this.posTrans.x += delta.x / clientLength * 1000;
this.posTrans.y += delta.y / clientLength * 1000;
this.startPosForMovingCanvas = {x: event.pageX, y:event.pageY};
this.redrawAll();
}
});
this.resizeObserver = new ResizeObserver(elements=>{
if (elements[0].contentRect.height == 0)
return;
this.redrawAll();
});
this.resizeObserver.observe(this.viewUi);
}
viewScale = 1;
objScale = 1;
updateObjectScale()
{
let v = this.viewUi;
this.viewScale = Math.max(1000/v.clientHeight, 1000/v.clientWidth);
}
object = {};
setObject(objType, objId, tracks, funcOnExit) //tracks is a list of [frameId, x, y, direction], in order
{
this.object = {
type: objType,
id: objId,
tracks:tracks
}; };
this.funcOnExit = funcOnExit; let clientLength = Math.min(
//console.log(objType, objId, tracks); this.svgUi.clientWidth,
this.calculateCoordinateTransform(this.object.tracks); this.svgUi.clientHeight
this.redrawAll(); );
this.ui.focus(); this.posTrans.x += (delta.x / clientLength) * 1000;
} this.posTrans.y += (delta.y / clientLength) * 1000;
redrawAll() this.startPosForMovingCanvas = { x: event.pageX, y: event.pageY };
{
this.show();
this.clear();
this.updateObjectScale();
this.drawTracks(this.object);
this.drawScaler(); this.redrawAll();
}
});
this.resizeObserver = new ResizeObserver((elements) => {
if (elements[0].contentRect.height == 0) return;
this.redrawAll();
});
this.resizeObserver.observe(this.viewUi);
}
viewScale = 1;
objScale = 1;
updateObjectScale() {
let v = this.viewUi;
this.viewScale = Math.max(1000 / v.clientHeight, 1000 / v.clientWidth);
}
object = {};
setObject(
objType,
objId,
tracks,
funcOnExit //tracks is a list of [frameId, x, y, direction], in order
) {
this.object = {
type: objType,
id: objId,
tracks: tracks,
};
this.funcOnExit = funcOnExit;
//console.log(objType, objId, tracks);
this.calculateCoordinateTransform(this.object.tracks);
this.redrawAll();
this.ui.focus();
}
redrawAll() {
this.show();
this.clear();
this.updateObjectScale();
this.drawTracks(this.object);
this.drawScaler();
}
clear() {
let arrows = this.ui.querySelector("#svg-arrows").children;
if (arrows.length > 0) {
for (var c = arrows.length - 1; c >= 0; c--) {
arrows[c].remove();
}
} }
let scaler = this.ui.querySelector("#svg-scaler").children;
clear(){ if (scaler.length > 0) {
for (var c = scaler.length - 1; c >= 0; c--) {
let arrows = this.ui.querySelector("#svg-arrows").children; scaler[c].remove();
}
if (arrows.length>0){
for (var c=arrows.length-1; c >= 0; c--){
arrows[c].remove();
}
}
let scaler = this.ui.querySelector("#svg-scaler").children;
if (scaler.length>0){
for (var c=scaler.length-1; c >= 0; c--){
scaler[c].remove();
}
}
} }
}
/* /*
the viewbox is 1000 by 1000 the viewbox is 1000 by 1000
the drawing area is [100,900] by [100,900] the drawing area is [100,900] by [100,900]
@ -180,242 +164,225 @@ class Trajectory extends PopupDialog{
y goes north (up) y goes north (up)
*/ */
calculateCoordinateTransform(tracks) calculateCoordinateTransform(tracks) {
{ tracks = tracks.filter((x) => x[1]);
tracks = tracks.filter(x=>x[1]); let xs = tracks.map((x) => x[1].psr.position.x);
let xs = tracks.map(x=> x[1].psr.position.x); let max_x = Math.max(...xs); //, 0);
let max_x = Math.max(...xs);//, 0); let min_x = Math.min(...xs); //, 0);
let min_x = Math.min(...xs);//, 0);
let ys = tracks.map((x) => x[1].psr.position.y);
let ys = tracks.map(x=> x[1].psr.position.y); let max_y = Math.max(...ys); //, 0);
let max_y = Math.max(...ys);//, 0); let min_y = Math.min(...ys); //, 0);
let min_y = Math.min(...ys);//, 0);
let scale = Math.max(max_x - min_x, max_y - min_y);
let scale = Math.max(max_x - min_x, max_y - min_y);
if (scale == 0) scale = 1;
if (scale == 0) else scale = 800 / scale; // svg view is 1000*1000
scale = 1;
else this.posScale = scale;
scale = 800/scale; // svg view is 1000*1000 this.posTrans = {
x: -min_x * this.posScale + 100,
this.posScale = scale; y: max_y * this.posScale + 100,
this.posTrans = { };
x: - min_x * this.posScale + 100, }
y: max_y * this.posScale + 100
}; transform(x, y, theta, label, highlight) {
} return [
x * this.posScale + this.posTrans.x,
transform(x,y,theta,label, highlight) -y * this.posScale + this.posTrans.y,
{ x,
return [ y,
x * this.posScale + this.posTrans.x, theta,
- y * this.posScale + this.posTrans.y, label,
x, highlight,
y, ];
theta , }
label,
highlight drawOneTrace(x, y, orgX, orgY, theta, label, highlight) {
]; let svg = this.ui.querySelector("#svg-arrows");
let g = document.createElementNS("http://www.w3.org/2000/svg", "g");
g.innerHTML = `<title>${label}</title>`;
g.setAttribute("class", "one-track");
g.ondblclick = (e) => {
if (this.funcOnExit) {
this.hide();
this.funcOnExit(label);
}
};
if (highlight) {
g.setAttribute("class", "one-track object-track-current-frame");
} }
drawOneTrace(x, y, orgX, orgY, theta, label, highlight) svg.appendChild(g);
{
let svg = this.ui.querySelector("#svg-arrows"); let r = 5 * this.objScale;
let d = 25 * this.objScale;
let g = document.createElementNS("http://www.w3.org/2000/svg", 'g'); let a = 5 * this.objScale;
g.innerHTML = `<title>${label}</title>`;
g.setAttribute("class","one-track"); //wrapper circle
let p = document.createElementNS("http://www.w3.org/2000/svg", "circle");
g.ondblclick = (e)=>{ p.setAttribute("cx", x + ((d - r) / 2) * this.viewScale * Math.cos(theta));
if (this.funcOnExit){ p.setAttribute("cy", y - ((d - r) / 2) * this.viewScale * Math.sin(theta));
this.hide(); p.setAttribute("r", ((d + 2 * r) / 2) * this.viewScale);
this.funcOnExit(label); p.setAttribute("class", "track-wrapper");
}
}; g.appendChild(p);
if (highlight) //object
{ p = document.createElementNS("http://www.w3.org/2000/svg", "circle");
g.setAttribute("class", "one-track object-track-current-frame"); p.setAttribute("cx", x);
} p.setAttribute("cy", y);
p.setAttribute("r", r * this.viewScale);
svg.appendChild(g);
g.appendChild(p);
let r = 5 * this.objScale;
let d = 25 * this.objScale; // //arrow head
let a = 5 * this.objScale; // p = document.createElementNS("http://www.w3.org/2000/svg", 'line');
// p.setAttribute("x1", x + d * this.viewScale * Math.cos(theta));
//wrapper circle // p.setAttribute("y1", y - d * this.viewScale* Math.sin(theta));
let p = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
p.setAttribute("cx", x + (d-r)/2 * this.viewScale * Math.cos(theta)); // p.setAttribute("x2", x + d * this.viewScale * Math.cos(theta) - a * this.viewScale * Math.cos(Math.PI/6+theta));
p.setAttribute("cy", y - (d-r)/2 * this.viewScale* Math.sin(theta)); // p.setAttribute("y2", y - d * this.viewScale * Math.sin(theta) + a * this.viewScale * Math.sin(Math.PI/6+theta));
p.setAttribute("r", (d+2*r)/2 * this.viewScale); // g.appendChild(p);
p.setAttribute("class","track-wrapper");
// p = document.createElementNS("http://www.w3.org/2000/svg", 'line');
g.appendChild(p); // p.setAttribute("x1", x + d * this.viewScale * Math.cos(theta));
// p.setAttribute("y1", y - d * this.viewScale * Math.sin(theta));
//object
p = document.createElementNS("http://www.w3.org/2000/svg", 'circle'); // p.setAttribute("x2", x + d * this.viewScale * Math.cos(theta) - a * this.viewScale * Math.cos(-Math.PI/6+theta));
p.setAttribute("cx", x); // p.setAttribute("y2", y - d * this.viewScale * Math.sin(theta) + a * this.viewScale * Math.sin(-Math.PI/6+theta));
p.setAttribute("cy", y); // g.appendChild(p);
p.setAttribute("r", r * this.viewScale);
// direction
g.appendChild(p); p = document.createElementNS("http://www.w3.org/2000/svg", "line");
p.setAttribute("x1", x + r * this.viewScale * Math.cos(theta));
// //arrow head p.setAttribute("y1", y - r * this.viewScale * Math.sin(theta));
// p = document.createElementNS("http://www.w3.org/2000/svg", 'line');
// p.setAttribute("x1", x + d * this.viewScale * Math.cos(theta)); p.setAttribute("x2", x + d * this.viewScale * Math.cos(theta));
// p.setAttribute("y1", y - d * this.viewScale* Math.sin(theta)); p.setAttribute("y2", y - d * this.viewScale * Math.sin(theta));
g.appendChild(p);
// p.setAttribute("x2", x + d * this.viewScale * Math.cos(theta) - a * this.viewScale * Math.cos(Math.PI/6+theta));
// p.setAttribute("y2", y - d * this.viewScale * Math.sin(theta) + a * this.viewScale * Math.sin(Math.PI/6+theta)); // frame
// g.appendChild(p); // p = document.createElementNS("http://www.w3.org/2000/svg", 'text');
// p.setAttribute("x", x + 50 * this.scale);
// p = document.createElementNS("http://www.w3.org/2000/svg", 'line'); // p.setAttribute("y", y);
// p.setAttribute("x1", x + d * this.viewScale * Math.cos(theta)); // p.textContent = track[0];
// p.setAttribute("y1", y - d * this.viewScale * Math.sin(theta)); // g.appendChild(p);
// p.setAttribute("x2", x + d * this.viewScale * Math.cos(theta) - a * this.viewScale * Math.cos(-Math.PI/6+theta)); p = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
// p.setAttribute("y2", y - d * this.viewScale * Math.sin(theta) + a * this.viewScale * Math.sin(-Math.PI/6+theta)); p.setAttribute("x", x + 50 * this.viewScale);
// g.appendChild(p); p.setAttribute("y", y);
// p.setAttribute("width", 200 * this.scale);
p.setAttribute("font-size", 10 * this.viewScale + "px");
// direction p.setAttribute("class", "track-label");
p = document.createElementNS("http://www.w3.org/2000/svg", 'line');
p.setAttribute("x1", x + r * this.viewScale * Math.cos(theta)); let text = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
p.setAttribute("y1", y - r * this.viewScale* Math.sin(theta)); text.textContent = label;
p.appendChild(text);
p.setAttribute("x2", x + d * this.viewScale * Math.cos(theta));
p.setAttribute("y2", y - d * this.viewScale* Math.sin(theta)); g.appendChild(p);
g.appendChild(p); }
// frame calculateScalerUnit() {
// p = document.createElementNS("http://www.w3.org/2000/svg", 'text'); let x = 100 / this.posScale;
// p.setAttribute("x", x + 50 * this.scale); let e = 0;
// p.setAttribute("y", y);
// p.textContent = track[0]; while (x >= 10 || x < 1) {
// g.appendChild(p); if (x >= 10) {
e += 1;
p = document.createElementNS("http://www.w3.org/2000/svg", 'foreignObject'); x /= 10;
p.setAttribute("x", x + 50 * this.viewScale); } else if (x < 1) {
p.setAttribute("y", y); e -= 1;
// p.setAttribute("width", 200 * this.scale); x *= 10;
p.setAttribute("font-size", 10 * this.viewScale+"px"); }
p.setAttribute("class",'track-label');
let text = document.createElementNS("http://www.w3.org/1999/xhtml", 'div');
text.textContent = label;
p.appendChild(text);
g.appendChild(p);
} }
calculateScalerUnit() x = 10 * Math.pow(10, e);
{
let x = 100/this.posScale; return x;
let e = 0; }
while (x >= 10 || x < 1) drawScaler() {
{ let x = this.calculateScalerUnit();
if (x >= 10) let lineLen = x * this.posScale;
{
e += 1; let svg = this.ui.querySelector("#svg-scaler");
x /= 10; let g = document.createElementNS("http://www.w3.org/2000/svg", "g");
} svg.appendChild(g);
else if (x < 1)
{ //direction
e -= 1; let p = document.createElementNS("http://www.w3.org/2000/svg", "line");
x *= 10; p.setAttribute("x1", 100);
} p.setAttribute("y1", 900);
} p.setAttribute("x2", 100 + lineLen);
p.setAttribute("y2", 900);
x = 10 * Math.pow(10, e); g.appendChild(p);
return x; p = document.createElementNS("http://www.w3.org/2000/svg", "line");
} p.setAttribute("x1", 100);
p.setAttribute("y1", 900);
drawScaler() p.setAttribute("x2", 100);
{ p.setAttribute("y2", 900 - lineLen);
let x = this.calculateScalerUnit(); g.appendChild(p);
let lineLen = x * this.posScale;
p = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
let svg = this.ui.querySelector("#svg-scaler"); p.setAttribute("x", 105);
let g = document.createElementNS("http://www.w3.org/2000/svg", 'g'); p.setAttribute("y", 875);
svg.appendChild(g); // p.setAttribute("width", 200 * this.scale);
p.setAttribute("font-size", 10 * this.viewScale + "px");
//direction p.setAttribute("class", "scaler-label");
let p = document.createElementNS("http://www.w3.org/2000/svg", 'line'); let text = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
p.setAttribute("x1", 100); text.textContent = x.toString() + "m";
p.setAttribute("y1", 900); p.appendChild(text);
p.setAttribute("x2", 100+lineLen);
p.setAttribute("y2", 900); g.appendChild(p);
g.appendChild(p); }
p = document.createElementNS("http://www.w3.org/2000/svg", 'line'); drawTracks(object) {
p.setAttribute("x1", 100); this.titleUi.innerText = object.type + " " + +object.id;
p.setAttribute("y1", 900); let tracks = object.tracks;
p.setAttribute("x2", 100);
p.setAttribute("y2", 900-lineLen); tracks
g.appendChild(p); .filter((x) => x[1])
.map((track) => [
track[1].psr.position.x,
p = document.createElementNS("http://www.w3.org/2000/svg", 'foreignObject'); track[1].psr.position.y,
p.setAttribute("x", 105); track[1].psr.rotation.z,
p.setAttribute("y", 875); track[0],
// p.setAttribute("width", 200 * this.scale); track[2],
p.setAttribute("font-size", 10 * this.viewScale+"px"); ])
p.setAttribute("class",'scaler-label'); .map((x) => this.transform(...x))
let text = document.createElementNS("http://www.w3.org/1999/xhtml", 'div'); .forEach((x) => this.drawOneTrace(...x));
text.textContent = x.toString() + 'm';
p.appendChild(text); //ego car
//this.draw_ego_car(...this.transform(0,0,0,"",false).slice(0,2));
g.appendChild(p); }
draw_ego_car(x, y) {
} let svg = this.ui.querySelector("#svg-arrows");
let g = document.createElementNS("http://www.w3.org/2000/svg", "g");
drawTracks(object) g.innerHTML = `<title>Ego car</title>`;
{ g.setAttribute("id", "track-ego-car");
this.titleUi.innerText = object.type + " "+ + object.id; svg.appendChild(g);
let tracks = object.tracks;
let p = document.createElementNS("http://www.w3.org/2000/svg", "line");
p.setAttribute("x1", x - 10 * this.viewScale);
tracks.filter(x=>x[1]) p.setAttribute("y1", y);
.map(track=>[track[1].psr.position.x, track[1].psr.position.y, track[1].psr.rotation.z, track[0], track[2]]) p.setAttribute("x2", x + 10 * this.viewScale);
.map(x=>this.transform(...x)) p.setAttribute("y2", y);
.forEach(x=>this.drawOneTrace(...x)); g.appendChild(p);
//ego car p = document.createElementNS("http://www.w3.org/2000/svg", "line");
//this.draw_ego_car(...this.transform(0,0,0,"",false).slice(0,2)); p.setAttribute("x1", x);
} p.setAttribute("y1", y - 10 * this.viewScale);
p.setAttribute("x2", x);
p.setAttribute("y2", y + 10 * this.viewScale);
draw_ego_car(x,y) g.appendChild(p);
{ }
let svg = this.ui.querySelector("#svg-arrows");
let g = document.createElementNS("http://www.w3.org/2000/svg", 'g');
g.innerHTML = `<title>Ego car</title>`;
g.setAttribute("id", "track-ego-car");
svg.appendChild(g);
let p = document.createElementNS("http://www.w3.org/2000/svg", 'line');
p.setAttribute("x1", x-10 * this.viewScale);
p.setAttribute("y1", y);
p.setAttribute("x2", x+10 * this.viewScale);
p.setAttribute("y2", y);
g.appendChild(p);
p = document.createElementNS("http://www.w3.org/2000/svg", 'line');
p.setAttribute("x1", x);
p.setAttribute("y1", y-10 * this.viewScale);
p.setAttribute("x2", x);
p.setAttribute("y2", y+10 * this.viewScale);
g.appendChild(p);
}
} }
export { Trajectory };
export {Trajectory};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save