/// <summary>
        /// Export an a perspective or orthographic sensor
        /// </summary>
        /// <param name="parent">The parent node in the output XML document</param>
        /// <param name="obj">The RhinoViewport instance to be exported</param>
        /// <returns>true if any content was exported</returns>
        private bool ExportSensor(XmlElement parent, RhinoViewport view)
        {
            bool perspective  = view.IsPerspectiveProjection;
            bool orthographic = view.IsParallelProjection;

            if (!perspective && !orthographic)
            {
                Log("Warning: camera type not supported -- ignoring.");
                return(false);
            }

            double left, right, bottom, top, near, far;

            view.GetFrustum(out left, out right, out bottom, out top, out near, out far);

            XmlElement sensorElement = m_xmlDocument.CreateElement("sensor");

            sensorElement.SetAttribute("type", perspective ? "perspective" : "orthographic");
            Transform toWorld = view.GetTransform(CoordinateSystem.Camera, CoordinateSystem.World);

            toWorld = toWorld * Transform.Mirror(new Plane(new Point3d(0, 0, 0), new Vector3d(0, 0, -1)));
            toWorld = toWorld * Transform.Mirror(new Plane(new Point3d(0, 0, 0), new Vector3d(-1, 0, 0)));
            XmlElement toWorldElement = MakeProperty("toWorld", toWorld);

            if (perspective)
            {
                double focusDistance = view.CameraLocation.DistanceTo(view.CameraTarget);
                double halfDiag, halfVert, halfHoriz;
                view.GetCameraAngle(out halfDiag, out halfVert, out halfHoriz);
                toWorld = toWorld * Transform.Mirror(new Plane(new Point3d(0, 0, 0), new Vector3d(0, 0, -1)));
                sensorElement.AppendChild(MakeProperty("fovAxis", "diagonal"));
                sensorElement.AppendChild(MakeProperty("fov", 2 * halfDiag * 180 / Math.PI));
                sensorElement.AppendChild(MakeProperty("focusDistance", focusDistance));
            }
            else
            {
                XmlElement scaleNode = m_xmlDocument.CreateElement("scale");
                double     scale     = (right - left) / 2;
                scaleNode.SetAttribute("x", ToStringHelper(scale));
                scaleNode.SetAttribute("y", ToStringHelper(scale));
                toWorldElement.PrependChild(scaleNode);
            }

            // Some extra room for nativating using the interactive viewer
            near /= 10; far *= 10;

            sensorElement.AppendChild(toWorldElement);
            sensorElement.AppendChild(MakeProperty("nearClip", near));
            sensorElement.AppendChild(MakeProperty("farClip", far));

            XmlElement filmElement = m_xmlDocument.CreateElement("film");

            filmElement.SetAttribute("type", "hdrfilm");
            filmElement.AppendChild(MakeProperty("width", m_settings.xres));
            filmElement.AppendChild(MakeProperty("height", m_settings.yres));
            sensorElement.AppendChild(filmElement);

            XmlElement samplerElement = m_xmlDocument.CreateElement("sampler");

            samplerElement.SetAttribute("type", "independent");
            samplerElement.AppendChild(MakeProperty("sampleCount", m_settings.samplesPerPixel));
            sensorElement.AppendChild(samplerElement);

            parent.AppendChild(sensorElement);
            return(true);
        }
        //モデル座標から図面の座標へ変換
        public Point3d CoordinateTransformation(Point3d world_position)
        {
            double halfDiagonalAngle, halfVerticalAngle, halfHorizontalAngle, nearDistance;

            camera.GetCameraAngle(out halfDiagonalAngle, out halfVerticalAngle, out halfHorizontalAngle);

            ///////////////////////
            //view transformation//
            ///////////////////////

            //カメラのZ軸と図面のZ軸を揃える
            Vector3d vec_norm = NormalVector(camera.CameraZ, Vector3d.ZAxis); //回転の軸
            double   angle    = VectorAngle(-Vector3d.ZAxis, camera.CameraZ); //角度

            double[,] m1 = new double[4, 4];
            m1[0, 0]     = vec_norm.X * vec_norm.X * (1 - Math.Cos(angle)) + Math.Cos(angle);
            m1[1, 0]     = vec_norm.X * vec_norm.Y * (1 - Math.Cos(angle)) + vec_norm.Z * Math.Sin(angle);
            m1[2, 0]     = vec_norm.Z * vec_norm.X * (1 - Math.Cos(angle)) - vec_norm.Y * Math.Sin(angle);
            m1[0, 1]     = vec_norm.X * vec_norm.Y * (1 - Math.Cos(angle)) - vec_norm.Z * Math.Sin(angle);
            m1[1, 1]     = vec_norm.Y * vec_norm.Y * (1 - Math.Cos(angle)) + Math.Cos(angle);
            m1[2, 1]     = vec_norm.Y * vec_norm.Z * (1 - Math.Cos(angle)) + vec_norm.X * Math.Sin(angle);
            m1[0, 2]     = vec_norm.Z * vec_norm.X * (1 - Math.Cos(angle)) + vec_norm.Y * Math.Sin(angle);
            m1[1, 2]     = vec_norm.Y * vec_norm.Z * (1 - Math.Cos(angle)) - vec_norm.X * Math.Sin(angle);
            m1[2, 2]     = vec_norm.Z * vec_norm.Z * (1 - Math.Cos(angle)) + Math.Cos(angle);
            m1[3, 3]     = 1;

            //カメラの上方向と図面のY軸を揃える
            double angle2 = VectorAngle(camera.CameraX, Vector3d.XAxis);

            double[,] m2 = new double[4, 4];
            m2[0, 0]     = Math.Cos(angle2);
            m2[1, 0]     = Math.Sin(angle2);
            m2[0, 1]     = -Math.Sin(angle2);
            m2[1, 1]     = Math.Cos(angle2);
            m2[2, 2]     = 1;
            m2[3, 3]     = 1;

            //カメラの位置を原点に揃える
            double[,] pos_cameralocation = MultiplyMatrices(MultiplyMatrices(PointToMatrix(camera.CameraLocation), m1), m2);//m1,m2による変換後のカメラの位置を求める
            Vector3d vec_location = new Vector3d(pos_cameralocation[0, 0], pos_cameralocation[0, 1], pos_cameralocation[0, 2]);

            double[,] m3 = new double[4, 4];
            m3[0, 0]     = 1;
            m3[1, 1]     = 1;
            m3[2, 2]     = 1;
            m3[3, 0]     = -vec_location.X;
            m3[3, 1]     = -vec_location.Y;
            m3[3, 2]     = -vec_location.Z;
            m3[3, 3]     = 1;

            double[,] screen1 = MultiplyMatrices(PointToMatrix(world_position), m1);
            double[,] screen2 = MultiplyMatrices(screen1, m2);
            double[,] screen3 = MultiplyMatrices(screen2, m3);

            //////////////////////////////
            //purojection transformation//
            //////////////////////////////

            Plane planenear, planefar;

            camera.GetFrustumNearPlane(out planenear);
            camera.GetFrustumFarPlane(out planefar);

            double dis_near = camera.CameraLocation.DistanceTo(planenear.Origin); //カメラとNearPlaneの距離を求める
            double dis_far  = camera.CameraLocation.DistanceTo(planefar.Origin);  //カメラとFarPlaneの距離を求める

            //x座標,y座標の値によって正負を返す
            double direction_y = 1;
            double direction_x = 1;

            if (screen3[0, 1] < 0)
            {
                direction_y = -1;
            }

            if (screen3[0, 0] < 0)
            {
                direction_x = -1;
            }

            double angle_y = VectorAngle(Vector3d.ZAxis, new Vector3d(0, screen3[0, 1], screen3[0, 2]));
            double angle_x = VectorAngle(Vector3d.ZAxis, new Vector3d(screen3[0, 0], 0, screen3[0, 2]));
            double sy      = 1 - direction_y * ((screen3[0, 2] - dis_near) * Math.Tan(angle_y)) / screen3[0, 1];
            double sx      = 1 - direction_x * ((screen3[0, 2] - dis_near) * Math.Tan(angle_x)) / screen3[0, 0];

            double[,] m4 = new double[4, 4];

            m4[0, 0] = sx;
            m4[1, 1] = sy;
            m4[2, 2] = 0;
            m4[3, 3] = 1;

            double[,] screen4 = MultiplyMatrices(screen3, m4);

            /////////////////////////
            //screen transformation//
            /////////////////////////

            //変換した座標をビューポートのサイズに合わせる
            double[,] m5 = new double[4, 4];

            List <Point3d> nearrec = new List <Point3d>();

            nearrec.AddRange(camera.GetNearRect());

            //NearPlaneとビューポートの大きさの比率を求める
            double sx5 = camera.Size.Width / nearrec[0].DistanceTo(nearrec[1]);
            double sy5 = camera.Size.Height / nearrec[0].DistanceTo(nearrec[2]);

            m5[0, 0] = sx5;
            m5[1, 1] = sy5;
            m5[3, 3] = 1;

            double[,] screen5 = MultiplyMatrices(screen4, m5);

            Point3d pos_screen = new Point3d(screen5[0, 0], screen5[0, 1], screen5[0, 2]);

            return(pos_screen);
        }