Note: The default ITS GitLab runner is a shared resource and is subject to slowdowns during heavy usage.
You can run your own GitLab runner that is dedicated just to your group if you need to avoid processing delays.

Commit 04ce4a31 authored by bernie wang's avatar bernie wang
Browse files

added documentation and refactored Box into box.js

parent 0340790b
function Box(anchor, cursor, angle, boundingBox, boxHelper) {
this.id = id; // id (int) of Box
this.object_id = null; // object id (string)
this.color = new THREE.Color( 1,0,0 ); // color of corner points
this.angle = angle; // orientation of bounding box
this.anchor = anchor; // point where bounding box was created
this.cursor = cursor.clone(); // cursor
this.added = false; // (boolean) whether the box has been added to boundingboxes
this.boundingBox = boundingBox; // Box3; sets the size of the box
this.boxHelper = boxHelper; // BoxHelper; helps visualize the box
this.geometry = new THREE.Geometry(); // geometry for corner/rotating points
// visualizes the corners (in the non-rotated coordinates) of the box
this.points = new THREE.Points( this.geometry, pointMaterial );
this.points.frustumCulled = false; // allows
this.colors = []; // colors of the corner points
// add colors to points geometry
for (var i = 0; i < 6; i++) {
this.colors.push( this.color.clone().multiplyScalar( 7 ) );
}
this.geometry.colors = this.colors;
// order of corners is max, min, topleft, bottomright
this.geometry.vertices.push(anchor);
this.geometry.vertices.push(cursor);
this.geometry.vertices.push(anchor.clone());
this.geometry.vertices.push(cursor.clone());
this.geometry.vertices.push(getCenter(anchor.clone(), cursor.clone()));
}
// method for resizing bounding box given cursor coordinates
//
// since BoxHelper3 draws a box in the same orientation as that of the point cloud,
// we take the anchor and cursor, rotate them by the angle of the camera, draw the box,
// then rotate the box back
function resize(box, cursor) {
// checks and executes only if anchor does not overlap with cursor to avoid 0 determinant
if (cursor.x != box.anchor.x && cursor.y != box.anchor.y && cursor.z != box.anchor.z) {
var v1 = cursor.clone();
var v2 = box.anchor.clone();
v1.y = 0;
v2.y = 0;
// rotate cursor and anchor
rotate(v1, v2, box.angle);
// calculating corner points and rotating point
var minVector = getMin(v1, v2);
var maxVector = getMax(v1, v2);
var topLeft = getTopLeft(v1, v2);
var bottomRight = getBottomRight(v1, v2);
var topCenter = getCenter(topLeft, maxVector);
var bottomCenter = getCenter(minVector, bottomRight);
// need to do this to make matrix invertible
maxVector.y = 0.00001;
// setting bounding box limits
box.boundingBox.set(minVector.clone(), maxVector.clone());
// rotate BoxHelper back
box.boxHelper.rotation.y = box.angle;
// setting y coordinate back to zero since we are done with drawing
maxVector.y = 0;
// rotate back the corner points
rotate(minVector, maxVector, -box.angle);
rotate(topLeft, bottomRight, -box.angle);
rotate(topCenter, bottomCenter, -box.angle);
// set updated corner points used to resize box
box.geometry.vertices[0] = maxVector.clone();
box.geometry.vertices[1] = minVector.clone();
box.geometry.vertices[2] = topLeft.clone();
box.geometry.vertices[3] = bottomRight.clone();
box.geometry.vertices[4] = bottomCenter.clone();
// tell scene to update corner points
box.geometry.verticesNeedUpdate = true;
}
}
// method to rotate bounding box by clicking and dragging rotate point,
// which is the top center point on the bounding box
function rotateBox(box, cursor) {
// get corner points
var maxVector = box.geometry.vertices[0].clone();
var minVector = box.geometry.vertices[1].clone();
var topLeft = box.geometry.vertices[2].clone();
var bottomRight = box.geometry.vertices[3].clone();
var topCenter = getCenter(maxVector, topLeft);
var bottomCenter = box.geometry.vertices[4].clone();
// get relative angle of cursor with respect to
var center = getCenter(maxVector, minVector);
var angle = getAngle(center, bottomCenter, cursor, topCenter);
// update angle of Box and bounding box
box.angle = box.angle + angle;
box.boxHelper.rotation.y = box.angle;
// rotate and update corner points
rotate(minVector, maxVector, -angle);
rotate(topLeft, bottomRight, -angle);
rotate(topCenter, bottomCenter, -angle);
box.geometry.vertices[0] = maxVector.clone();
box.geometry.vertices[1] = minVector.clone();
box.geometry.vertices[2] = topLeft.clone();
box.geometry.vertices[3] = bottomRight.clone();
box.geometry.vertices[4] = bottomCenter.clone();
// tell scene to update corner points
box.geometry.verticesNeedUpdate = true;
}
// gets angle between v1 and v2 with respect to origin
//
// v3 is an optional reference point that should be v1's reflection about the origin,
// but is needed to get the correct sign of the angle
function getAngle(origin, v1, v2, v3) {
v1 = v1.clone();
v2 = v2.clone();
origin = origin.clone();
v1.sub(origin);
v2.sub(origin);
v1.y = 0;
v2.y = 0;
v1.normalize();
v2.normalize();
var angle = Math.acos(Math.min(1.0, v1.dot(v2)));
if (v3) {
v3 = v3.clone();
v3.sub(origin);
// calculates distance between v1 and v2 when v1 is rotated by angle
var temp1 = v1.clone();
rotate(temp1, v3.clone(), angle);
var d1 = distance2D(temp1, v2);
// calculates distance between v1 and v2 when v1 is rotated by -angle
var temp2 = v1.clone();
rotate(temp2, v3.clone(), -angle);
var d2 = distance2D(temp2, v2);
// compares distances to determine sign of angle
if (d2 > d1) {
angle = -angle;
}
}
return angle;
}
// highlights closest corner point that intersects with cursor
function highlightCorners() {
// get closest intersection with cursor
var intersection = intersectWithCorner();
if (intersection) {
// get closest point and its respective box
var box = intersection[0];
var p = intersection[1];
// get index of closest point
var closestIdx = closestPoint(p, box.geometry.vertices);
// if there was a previously hovered box, change its color back to red
if (hoverBox) {
changePointColor(hoverBox, hoverIdx, new THREE.Color(7, 0, 0));
}
// update hover box
hoverBox = box;
hoverIdx = closestIdx;
changePointColor(hoverBox, hoverIdx, new THREE.Color(0, 0, 7));
} else {
// change color of previously hovered box back to red
if (hoverBox) {
changePointColor(hoverBox, hoverIdx, new THREE.Color(7, 0, 0));
}
// set hover box to null since there is no intersection
hoverBox = null;
}
}
// changes and updates a box's point's color given point index and color
function changePointColor(box, idx, color) {
box.colors[idx] = color;
box.geometry.colorsNeedUpdate = true;
}
// method to translate bounding box given a reference point
function moveBox(box, v) {
// get difference in x and z coordinates between cursor when
// box was selected and current cursor position
var dx = v.x - box.cursor.x;
var dz = v.z - box.cursor.z;
// update all points related to box by dx and dz
box.anchor.x += dx;
box.anchor.z += dz;
box.cursor = v.clone();
for (var i = 0; i < box.geometry.vertices.length; i++) {
var p = box.geometry.vertices[i];
p.x += dx;
p.z += dz;
}
// shift bounding box given new corner points
var maxVector = box.geometry.vertices[0].clone();
var minVector = box.geometry.vertices[1].clone();
var topLeft = box.geometry.vertices[2].clone();
var bottomRight = box.geometry.vertices[3].clone();
var topCenter = getCenter(maxVector, topLeft);
var bottomCenter = box.geometry.vertices[4].clone();
rotate(maxVector, minVector, box.angle);
rotate(topLeft, bottomRight, box.angle);
rotate(topCenter, bottomCenter, box.angle);
// need to do this to make matrix invertible
maxVector.y += 0.0000001;
box.boundingBox.set(minVector, maxVector);
// tell scene to update corner points
box.geometry.verticesNeedUpdate = true;
}
// method to change color of bounding box
function changeBoundingBoxColor(box, color) {
var boxHelperCopy = new THREE.Box3Helper( box.boundingBox, color );
scene.add(boxHelperCopy);
scene.remove(box.boxHelper);
box.boxHelper = boxHelperCopy;
boxHelperCopy.rotation.y = box.angle;
}
// method to add box to boundingBoxes and object id table
function addBox(box) {
boundingBoxes.push(box);
id++;
addRow(box);
}
// method to highlight box given cursor
function selectBox(box, cursor) {
selectedBox = box;
if (box && cursor) {
selectedBox.cursor = cursor;
}
updateHoverBoxes(cursor);
changeBoundingBoxColor(box, new THREE.Color( 0,0,7 ) );
}
\ No newline at end of file
......@@ -48,34 +48,25 @@ init();
var id = 0;
// animate();
// Should be in init?
var sphereGeometry, sphereMaterial;
function generatePointCloud( vertices, color ) {
var geometry = new THREE.Geometry();
var colors = [];
var k = 0;
var stride = 4;
function normalizeColors(vertices, color) {
var maxColor = Number.NEGATIVE_INFINITY;
var minColor = Number.POSITIVE_INFINITY;
var intensities = [];
for ( var i = 0, l = vertices.length / 4; i < l; i ++ ) {
// creates new vector from a cluster and adds to geometry
var v = new THREE.Vector3( vertices[ stride * k + 1 ],
vertices[ stride * k + 2 ], vertices[ stride * k ] );
var colors = [];
yCoords.push(vertices[ stride * k + 2 ]);
k = 0;
var stride = 4;
// finds max and min z coordinates
for ( var i = 0, l = vertices.length / 4; i < l; i ++ ) {
if (vertices[ stride * k + 2] > maxColor) {
maxColor = vertices[ stride * k + 2];
}
if (vertices[ stride * k + 2] < minColor) {
minColor = vertices[ stride * k + 2];
}
geometry.vertices.push( v );
intensities.push(vertices[ stride * k + 2]);
k++;
}
......@@ -86,6 +77,10 @@ function generatePointCloud( vertices, color ) {
var min = getMinElement(filteredIntensities);
var max = getMaxElement(filteredIntensities);
// normalize colors
// if greater than 2 sd from mean, set to max color
// if less than 2 sd from mean, set to min color
// ortherwise normalize color based on min and max z-coordinates
for ( var i = 0; i < intensities.length; i ++ ) {
var intensity = intensities[i];
if (intensities[i] - mean >= 2 * sd) {
......@@ -97,8 +92,31 @@ function generatePointCloud( vertices, color ) {
}
colors[i] = ( color.clone().multiplyScalar( intensity * 2 ) );
}
return colors;
}
function generatePointCloud( vertices, color ) {
var geometry = new THREE.Geometry();
var k = 0;
var stride = 4;
for ( var i = 0, l = vertices.length / 4; i < l; i ++ ) {
// creates new vector from a cluster and adds to geometry
var v = new THREE.Vector3( vertices[ stride * k + 1 ],
vertices[ stride * k + 2 ], vertices[ stride * k ] );
// stores y coordinates into yCoords
yCoords.push(vertices[ stride * k + 2 ]);
// add vertex to geometry
geometry.vertices.push( v );
k++;
}
geometry.colors = colors;
geometry.colors = normalizeColors(vertices, color);
geometry.computeBoundingBox();
var material = new THREE.PointsMaterial( { size: pointSize, sizeAttenuation: false, vertexColors: THREE.VertexColors } );
......@@ -109,79 +127,38 @@ function generatePointCloud( vertices, color ) {
}
function Box(anchor, cursor, angle, boundingBox, boxHelper) {
this.color = new THREE.Color( 1,0,0 );
this.angle = angle;
this.anchor = anchor;
this.geometry = new THREE.Geometry();
// visualizes the corners (in the non-rotated coordinates) of the box
this.points = new THREE.Points( this.geometry, pointMaterial );
this.boundingBox = boundingBox; // Box3; sets the size of the box
this.boxHelper = boxHelper; // BoxHelper; helps visualize the box
this.colors = []; // colors of the corner points
for (var i = 0; i < 6; i++) {
this.colors.push( this.color.clone().multiplyScalar( 7 ) );
}
this.geometry.colors = this.colors;
this.cursor = cursor.clone();
// order of corners is max, min, topleft, bottomright
this.geometry.vertices.push(anchor);
this.geometry.vertices.push(cursor);
this.geometry.vertices.push(anchor.clone());
this.geometry.vertices.push(cursor.clone());
this.geometry.vertices.push(getCenter(anchor.clone(), cursor.clone()));
this.points.frustumCulled = false;
this.added = false;
this.id = id;
this.object_id = null;
}
// called first, populates scene and initializes renderer
function init() {
var container = document.getElementById( 'container' );
scene = new THREE.Scene();
clock = new THREE.Clock();
// set up PerspectiveCamera
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
// camera.position.y = 25;
// camera.position.z = 37;
camera.position.set(0, 100, 0);
camera.lookAt(new THREE.Vector3(0,0,0));
sphereGeometry = new THREE.SphereGeometry( 0.1, 32, 32 );
sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000, flatShading: THREE.FlatShading } );
//
grid = new THREE.GridHelper( 200, 20, 0xffffff, 0xffffff );
scene.add( grid );
//
// set up renderer
renderer = new THREE.WebGLRenderer({preserveDrawingBuffer: true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//
raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = threshold;
//
stats = new Stats();
container.appendChild( stats.dom );
//
controls = new THREE.OrbitControls( camera, renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
......@@ -190,15 +167,14 @@ function init() {
document.getElementById('container').addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mousemove', updateMouse, false );
document.getElementById( 'save' ).addEventListener( 'click', save, false );
// document.getElementById( 'export' ).addEventListener( 'click', save_image, false );
document.getElementById( 'move' ).addEventListener( 'click', moveMode, false );
document.getElementById( 'move2D' ).addEventListener( 'click', move2DMode, false );
// document.getElementById( 'label' ).addEventListener( 'click', labelMode, false );
document.getElementById( 'file_input' ).addEventListener( 'change', upload_file, false );
document.addEventListener("keydown", onKeyDown); //or however you are calling your method
document.addEventListener("keyup", onKeyUp);
}
// controller for pressing hotkeys
function onKeyDown(event) {
if (event.ctrlKey) {
toggleControl(false);
......@@ -213,12 +189,12 @@ function onKeyDown(event) {
deleteSelectedBox();
break;
case 68:
// toggleControl(false);
default:
break;
}
}
// controller for releasing hotkeys
function onKeyUp(event) {
var KeyID = event.keyCode;
switch(KeyID)
......@@ -229,6 +205,7 @@ function onKeyUp(event) {
}
}
// toggles between move2D and move3D
function toggleControl(b) {
if (b) {
controls.enabled = b;
......@@ -241,17 +218,24 @@ function toggleControl(b) {
}
}
// deletes selected box when delete key pressed
function deleteSelectedBox() {
if (selectedBox) {
scene.remove(selectedBox.points);
scene.remove(selectedBox.boxHelper);
// deletes corresponding row in object id table
deleteRow(selectedBox.id);
// removes selected box from array of currently hovered boxes
for (var i = 0; i < hoverBoxes.length; i++) {
if (hoverBoxes[i] == selectedBox) {
hoverBoxes.splice(i, 1);
break;
}
}
// removes selected box from array of bounding boxes
for (var i = 0; i < boundingBoxes.length; i++) {
if (boundingBoxes[i] == selectedBox) {
boundingBoxes.splice(i, 1);
......@@ -259,17 +243,18 @@ function deleteSelectedBox() {
}
}
// removes selected box
selectedBox = null;
}
}
// removes row of object id table given corrensponding bounding box id
function deleteRow(id) {
var row = getRow(id);
row.remove();
}
// gets 2D mouse coordinates
function updateMouse( event ) {
event.preventDefault();
mouse2D.x = ( event.clientX / window.innerWidth ) * 2 - 1;
......@@ -277,201 +262,77 @@ function updateMouse( event ) {
}
function resize(box, cursor) {
if (cursor.x != box.anchor.x && cursor.y != box.anchor.y && cursor.z != box.anchor.z) {
var v1 = cursor.clone();
var v2 = box.anchor.clone();
v1.y = 0;
v2.y = 0;
// for rotation
rotate(v1, v2, box.angle);
var minVector = getMin(v1, v2);
var maxVector = getMax(v1, v2);
var topLeft = getTopLeft(v1, v2);
var bottomRight = getBottomRight(v1, v2);
var topCenter = getCenter(topLeft, maxVector);
var bottomCenter = getCenter(minVector, bottomRight);
maxVector.y = 0.00001; // need to do this to make matrix invertible
box.boundingBox.set(minVector.clone(), maxVector.clone());
// for rotation
box.boxHelper.rotation.y = box.angle;
maxVector.y = 0;
rotate(minVector, maxVector, -box.angle);
rotate(topLeft, bottomRight, -box.angle);
rotate(topCenter, bottomCenter, -box.angle);
// set corner points
box.geometry.vertices[0] = maxVector.clone();
box.geometry.vertices[1] = minVector.clone();
box.geometry.vertices[2] = topLeft.clone();
box.geometry.vertices[3] = bottomRight.clone();
box.geometry.vertices[4] = bottomCenter.clone();
box.geometry.verticesNeedUpdate = true;
}
}
function rotateBox(box, cursor) {
var maxVector = box.geometry.vertices[0].clone();
var minVector = box.geometry.vertices[1].clone();
var topLeft = box.geometry.vertices[2].clone();
var bottomRight = box.geometry.vertices[3].clone();
var topCenter = getCenter(maxVector, topLeft);
var bottomCenter = box.geometry.vertices[4].clone();
var center = getCenter(maxVector, minVector);
var angle = getAngle(center, bottomCenter, cursor, topCenter);
box.angle = box.angle + angle;
box.boxHelper.rotation.y = box.angle;
rotate(minVector, maxVector, -angle);
rotate(topLeft, bottomRight, -angle);
rotate(topCenter, bottomCenter, -angle);
box.geometry.vertices[0] = maxVector.clone();
box.geometry.vertices[1] = minVector.clone();
box.geometry.vertices[2] = topLeft.clone();
box.geometry.vertices[3] = bottomRight.clone();
box.geometry.vertices[4] = bottomCenter.clone();
box.geometry.verticesNeedUpdate = true;
}
function getAngle(origin, v1, v2, v3) {
v1 = v1.clone();
v2 = v2.clone();
origin = origin.clone();
v1.sub(origin);
v2.sub(origin);
v1.y = 0;
v2.y = 0;
v1.normalize();
v2.normalize();
var angle = Math.acos(Math.min(1.0, v1.dot(v2)));
if (v3) {
v3 = v3.clone();
v3.sub(origin);