CauldronDevelopmentLLC / CAMotics

Open-Source Simulation & Computer Aided Machining - A 3-axis CNC GCode simulator
Other
602 stars 140 forks source link

Better isometric view snap. #289

Open jcoffland opened 5 years ago

jcoffland commented 5 years ago

When you press the isometric view buttons the workpiece does not always snap perfectly to the screen size. The ideal zoom level could be computed from the view frustum.

Javascript code using THREE.js for this:

var bbox = this.get_model_bounds();

// Compute new camera position
var center = bbox.getCenter(new THREE.Vector3());
var offset = new THREE.Vector3();

if (view == 'isometric') {offset.y -= 1; offset.z += 1;}
if (view == 'front')  offset.y -= 1;
if (view == 'back')   offset.y += 1;
if (view == 'left')   offset.x -= 1;
if (view == 'right')  offset.x += 1;
if (view == 'top')    offset.z += 1;
if (view == 'bottom') offset.z -= 1;
offset.normalize();

// Initial camera position
var position = new THREE.Vector3().copy(center).add(offset);
this.camera.position.copy(position);
this.camera.lookAt(center); // Get correct camera orientation

var theta = this.camera.fov / 180 * Math.PI; // View angle
var cameraLine = new THREE.Line3(center, position);
var cameraUp = new THREE.Vector3().copy(this.camera.up)
    .applyQuaternion(this.camera.quaternion);
var cameraLeft =
    new THREE.Vector3().copy(offset).cross(cameraUp).normalize();

var corners = [
  new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.min.z),
  new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.max.z),
  new THREE.Vector3(bbox.min.x, bbox.max.y, bbox.min.z),
  new THREE.Vector3(bbox.min.x, bbox.max.y, bbox.max.z),
  new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.min.z),
  new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.max.z),
  new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.min.z),
  new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.max.z),
]

var dist = this.camera.near; // Min camera dist

for (var i = 0; i < corners.length; i++) {
  // Project on to camera line
  var p1 = cameraLine.closestPointToPoint(corners[i], false, new THREE.Vector3());

  // Compute distance from projection to center
  var d = p1.distanceTo(center);
  if (cameraLine.closestPointToPointParameter(p1, false) < 0) d = -d;

  // Compute up line
  var up = new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraUp));

  // Project on to up line
  var p2 = up.closestPointToPoint(corners[i], false, new THREE.Vector3());

  // Compute length
  var l = p1.distanceTo(p2);

  // Update min camera distance
  dist = Math.max(dist, d + l / Math.tan(theta / 2));

  // Compute left line
  var left = new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraLeft));

  // Project on to left line
  var p3 = left.closestPointToPoint(corners[i], false, new THREE.Vector3());

  // Compute length
  l = p1.distanceTo(p3);

  // Update min camera distance
  dist = Math.max(dist, d + l / Math.tan(theta / 2) / this.camera.aspect);
}