private HitTestResultBehavior HitTestCallback(HitTestResult result)
        {
            RayMeshGeometry3DHitTestResult rayHit = result as RayMeshGeometry3DHitTestResult;
            ProjectionCamera      camera          = _viewport3D.Viewport.Camera as ProjectionCamera;
            HitTestResultBehavior result2;

            if (rayHit != null && rayHit.ModelHit != null)
            {
                Model3D  model    = rayHit.ModelHit;
                Visual3D visual3D = rayHit.VisualHit;
                if (visual3D != null)
                {
                    if (string.Compare(Convert.ToString(visual3D.GetValue(FrameworkElement.NameProperty)), "CurveVisual") != 0)
                    {
                        result2 = HitTestResultBehavior.Continue;
                        return(result2);
                    }
                }
                MeshGeometry3D mesh = rayHit.MeshHit;
                if (mesh != null)
                {
                    Point3D p  = mesh.Positions[rayHit.VertexIndex1];
                    Point3D p2 = mesh.Positions[rayHit.VertexIndex2];
                    Point3D p3 = mesh.Positions[rayHit.VertexIndex3];
                    double  x  = p.X * rayHit.VertexWeight1 + p2.X * rayHit.VertexWeight2 + p3.X * rayHit.VertexWeight3;
                    double  y  = p.Y * rayHit.VertexWeight1 + p2.Y * rayHit.VertexWeight2 + p3.Y * rayHit.VertexWeight3;
                    double  z  = p.Z * rayHit.VertexWeight1 + p2.Z * rayHit.VertexWeight2 + p3.Z * rayHit.VertexWeight3;

                    // point in local coordinates
                    Point3D localPoint = new Point3D(x, y, z);
                    Point3D p4         = localPoint;

                    // transform to global coordinates

                    // first transform the Model3D hierarchy
                    GeneralTransform3D t2 = Viewport3DHelper.GetTransform(rayHit.VisualHit, rayHit.ModelHit);
                    if (t2 != null)
                    {
                        p4 = t2.Transform(p4);
                    }

                    // then transform the Visual3D hierarchy up to the Viewport3D ancestor
                    GeneralTransform3D t3 = Viewport3DHelper.GetTransform(_viewport3D.Viewport, rayHit.VisualHit);
                    if (t3 != null)
                    {
                        p4 = t3.Transform(p4);
                    }
                    double distance = (camera.Position - p4).LengthSquared;
                    if (distance < _minimumDistance)
                    {
                        _minimumDistance = distance;
                        _nearestPt       = localPoint;
                        _nearestNormal   = Vector3D.CrossProduct(p2 - p, p3 - p);
                        _rayhit          = rayHit;
                    }
                }
            }
            result2 = HitTestResultBehavior.Continue;
            return(result2);
        }
        /// <summary>
        /// Intersects the specified source mesh geometry with the specified plane.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="inverseTransform">The inverse transform of the source.</param>
        /// <param name="plane">The plane.</param>
        /// <param name="complement">Cut with the complement set if set to <c>true</c>.</param>
        /// <returns>The intersected geometry.</returns>
        private MeshGeometry3D Intersect(MeshGeometry3D source, GeneralTransform3D inverseTransform, Plane3D plane, bool complement)
        {
            var p  = inverseTransform.Transform(plane.Position);
            var p2 = inverseTransform.Transform(plane.Position + plane.Normal);
            var n  = p2 - p;

            if (complement)
            {
                n *= -1;
            }

            return(MeshGeometryHelper.Cut(source, p, n));
        }
        /// <summary>
        /// Update the transformation on the controlled object as the dragged-mouse moves. (Ignore if the motion's not part of a drag).
        ///
        /// </summary>
        public void mouseMove(System.Windows.Input.MouseEventArgs e)
        {
            // if not in drag, ignore
            // if in drag,
            //   note that current point may not lie on sphere!
            //   compute rotation taking start-point to current point
            //   concatenate that with initial transform

            if (_inDrag)
            {
                Debug.Print("In drag!");
                Point3D            currPoint = spherePointFromMousePosition(e.GetPosition(_viewport3D));
                Point3D            origin    = new Point3D(0, 0, 0);
                GeneralTransform3D tt        = _initialTransform.Inverse;

                Vector3D vec1 = tt.Transform(_startPoint) - tt.Transform(origin);
                Vector3D vec2 = tt.Transform(currPoint) - tt.Transform(origin);
                Debug.Print("  vec1: " + vec1.ToString());
                Debug.Print("  vec2: " + vec2.ToString());
                vec1.Normalize();
                vec2.Normalize();
                // Now build an arcball interaction to take vec1 to vec2 and past it (i.e., double the rotation):

                double            angle           = 2 * Math.Acos(Vector3D.DotProduct(vec1, vec2));
                Vector3D          axis            = Vector3D.CrossProduct(vec1, vec2);
                RotateTransform3D rotateTransform = new RotateTransform3D();
                rotateTransform.Rotation = new AxisAngleRotation3D(axis, 180 * angle / Math.PI);
                Debug.Print("axis: " + axis.ToString());
                Debug.Print("angle: " + angle.ToString());

                Transform3DGroup tg = new Transform3DGroup();
                tg.Children.Add(rotateTransform);
                tg.Children.Add(_initialTransform);

                _controlled.Transform = tg;
            }
        }