/// <summary> /// <para>Moves the Camera in a viewport toward a fixed point</para> /// </summary> public static bool Move(this ViewportInfo viewport, CGSize viewSize, double magnifcationFactor, CGPoint fixedScreenPoint) { if (viewport.IsCameraLocationLocked) { return(false); } var screenWidth = viewSize.Width; var screenHeight = viewSize.Height; if (1 > screenWidth || 1 > screenHeight) { return(false); } // move camera toward target to magnify if (magnifcationFactor > 0) { // if the screen point is not in the viewport, then ignore it. if (!fixedScreenPoint.IsEmpty) { if (fixedScreenPoint.X <= 0 || fixedScreenPoint.X >= screenWidth - 1 || fixedScreenPoint.Y <= 0 || fixedScreenPoint.Y >= screenHeight - 1) { fixedScreenPoint.X = 0; fixedScreenPoint.Y = 0; } } double frustumNear = viewport.FrustumNear; double frustumWidth = viewport.FrustumWidth; double frustumHeight = viewport.FrustumHeight; double d = 0.0; // dolly camera location and the target location... if (viewport.IsPerspectiveProjection) { const double miniumumTargetDistance = 0.000001; var cameraZ = viewport.CameraZ; var cameraLocation = viewport.CameraLocation; var target = viewport.TargetPoint; var v0 = target - cameraLocation; double targetDistance = (cameraLocation - target) * cameraZ; if (targetDistance >= 0.0) { double delta = (1.0 - (1.0 / magnifcationFactor)) * targetDistance; if (targetDistance - delta > miniumumTargetDistance) { v0.Unitize(); var l = delta * v0; var newLocation = cameraLocation + l; var newTarget = target + l; viewport.SetTarget(newTarget, newLocation, Rhino.Geometry.Vector3d.ZAxis); if (!fixedScreenPoint.IsEmpty) { d = (targetDistance / 2) / frustumNear; frustumWidth *= d; frustumHeight *= d; d = ((targetDistance / 2) - delta) / (targetDistance / 2); } } } } if (!fixedScreenPoint.IsEmpty && Math.Abs(d) > Double.Epsilon) { // lateral dolly to keep fixed_screen_point in same location on screen Rhino.Geometry.Vector3d scale = new Rhino.Geometry.Vector3d(1.0, 1.0, 1.0); scale.X = viewport.ViewScale.Width; scale.Y = viewport.ViewScale.Height; double fx = ((double)fixedScreenPoint.X / (double)screenWidth); double fy = ((double)fixedScreenPoint.Y / (double)screenHeight); double dx = ((0.5 - fx) * (1.0 - d) * frustumWidth) / scale.X; double dy = ((fy - 0.5) * (1.0 - d) * frustumHeight) / scale.Y; Rhino.Geometry.Vector3d dollyVector = dx * viewport.CameraX + dy * viewport.CameraY; var cameraLocation = viewport.CameraLocation; var target = viewport.TargetPoint; viewport.TargetPoint = target - dollyVector; viewport.SetCameraLocation(cameraLocation - dollyVector); } } return(true); }