Example #1
0
        /// <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);
        }