Пример #1
0
        /// <summary>
        /// 导出桥梁,隧道或路基的中线
        /// </summary>
        /// <param name="latlonPoints"></param>
        /// <param name="TXT"></param>
        private void exportMiddleLine(CRailwayProject prj, StreamWriter DoubleFile, StreamWriter SingleFile, string prjType)
        {
            string          fileNameExt = ".max.x";
            StreamWriter    TXT;
            OnePrj          aprj;
            List <Vector3d> earthCoreSysPoints = new List <Vector3d>();
            List <Vector3d> dsMaxPoints        = new List <Vector3d>();
            List <int>      sIndex             = new List <int>(); // 如果工点里程过长,拆分为不超过3.5 KM作为一段生成模型
            int             startN             = 0;

            // int n = 0;
            if (!prj.mIsValid)
            {
                return;
            }

            for (startN = 0; startN < prj.mPath.mPointCount - 350; startN += 300)
            {
                sIndex.Add(startN);
            }
            sIndex.Add(startN);

            double[] m, x, y, z, d;
            bool     isDouble;
            string   sp;

            isDouble = prj.mPath.getMiddleLine(out m, out x, out y, out z, out d);
            if (isDouble)
            {
                TXT = DoubleFile;
                sp  = "d";
            }
            else
            {
                TXT = SingleFile;
                sp  = "s";
            }
            for (int j = 0; j < sIndex.Count; j++)
            {
                int fromIdx = sIndex[j];
                int toIdx;
                if (j == sIndex.Count - 1)
                {
                    toIdx = m.Length - 1;
                }
                else
                {
                    toIdx = sIndex[j + 1];
                }
                double prjLength = prj.mPath.mLength;
                switch (prjType)
                {
                case "bridge":
                    if (isDouble)
                    {
                        dbridgeCount++;
                        aprj = new OnePrj(j, prjType, prj.ProjectName, sp + prjType + dbridgeCount + fileNameExt, prjLength,
                                          x[sIndex[j]], y[sIndex[j]], z[sIndex[j]]);
                    }
                    else
                    {
                        sbridgeCount++;
                        aprj = new OnePrj(j, prjType, prj.ProjectName, sp + prjType + sbridgeCount + fileNameExt, prjLength,
                                          x[sIndex[j]], y[sIndex[j]], z[sIndex[j]]);
                    }
                    projectList.Add(aprj);
                    break;

                case "road":
                    if (isDouble)
                    {
                        droadCount++;
                        aprj = new OnePrj(j, prjType, prj.ProjectName, sp + prjType + droadCount + fileNameExt, prjLength,
                                          x[sIndex[j]], y[sIndex[j]], z[sIndex[j]]);
                    }
                    else
                    {
                        sroadCount++;
                        aprj = new OnePrj(j, prjType, prj.ProjectName, sp + prjType + sroadCount + fileNameExt, prjLength,
                                          x[sIndex[j]], y[sIndex[j]], z[sIndex[j]]);
                    }
                    projectList.Add(aprj);
                    break;

                case "tunnel":
                    if (isDouble)
                    {
                        dtunnelCount++;
                        aprj = new OnePrj(j, prjType, prj.ProjectName, sp + prjType + dtunnelCount + fileNameExt, prjLength,
                                          x[sIndex[j]], y[sIndex[j]], z[sIndex[j]]);
                    }
                    else
                    {
                        stunnelCount++;
                        aprj = new OnePrj(j, prjType, prj.ProjectName, sp + prjType + stunnelCount + fileNameExt, prjLength,
                                          x[sIndex[j]], y[sIndex[j]], z[sIndex[j]]);
                    }
                    projectList.Add(aprj);
                    break;
                }


                TXT.Write(prjLength + "  ");
                TXT.Write(prj.ProjectName + "  ");
                TXT.WriteLine(j);
                earthCoreSysPoints.Clear();
                dsMaxPoints.Clear();
                for (int i = fromIdx; i <= toIdx; i++)
                {
                    double radius = WorldSettings.EquatorialRadius /* 米 */ + z[i];
                    earthCoreSysPoints.Add(MathEngine.SphericalToCartesianD(y[i], x[i], radius)); // 米
                }
                //foreach (LatLonAl p in latlonPoints)
                //{
                //    double radius = WorldSettings.EquatorialRadius/* 米 */ + p.altitude;
                //    earthCoreSysPoints.Add(MathEngine.SphericalToCartesianD(p.latitude, p.longitude, radius)); // 米
                //}

                // 经测试 地球窗口的世界坐标系原点在地球球心,x轴指向0纬0经,右手系,z轴指向北极点,测试语句:
                // Vector3 latlon_test = MathEngine.CartesianToSpherical(5001,1, 1);
                Vector3d k_prime = new Vector3d(earthCoreSysPoints[0]); k_prime = k_prime.Normalize();
                Vector3d i_prime = Vector3d.Transform(earthCoreSys_YAxis, Matrix4d.RotationZ((prj.mPath.mx[fromIdx] * PI / 180)));
                Vector3d j_prime = Vector3d.Cross(k_prime, i_prime); j_prime = j_prime.Normalize();
                Matrix4d mm      = new Matrix4d();


                // mm是正交矩阵,求逆就是求转置。
                mm.M11 = i_prime.X; mm.M12 = j_prime.X; mm.M13 = k_prime.X;
                mm.M21 = i_prime.Y; mm.M22 = j_prime.Y; mm.M23 = k_prime.Y;
                mm.M31 = i_prime.Z; mm.M32 = j_prime.Z; mm.M33 = k_prime.Z;
                mm.M41 = mm.M42 = mm.M43 = 0;
                mm.M14 = mm.M24 = mm.M34 = 0;
                mm.M44 = 1;

                // 把三维中线(地球球心坐标系)上 起点之外的点 转换为 3ds max世界坐标 (起点作原点)
                for (int i = 1; i <= toIdx - fromIdx; i++)
                {
                    Vector3d vv = new Vector3d(earthCoreSysPoints[i].X - earthCoreSysPoints[0].X, earthCoreSysPoints[i].Y - earthCoreSysPoints[0].Y, earthCoreSysPoints[i].Z - earthCoreSysPoints[0].Z);
                    dsMaxPoints.Add(Vector3d.Transform(vv, mm));
                }
                // 输出
                List <Vector3d> straight_opt = new List <Vector3d>();
                straight_opt.Add(dsMaxPoints[0]);
                straight_opt.Add(dsMaxPoints[1]);

                for (int i = 2; i < dsMaxPoints.Count; i++)
                {
                    Vector3d a        = dsMaxPoints[i] - straight_opt[straight_opt.Count - 1];
                    Vector3d b        = straight_opt[straight_opt.Count - 1] - straight_opt[straight_opt.Count - 2];
                    double   costheta = Vector3d.Dot(a, b) / a.Length / b.Length;
                    double   sintheta = Math.Sqrt(1 - costheta * costheta);
                    if (sintheta < Threshold)
                    {
                        straight_opt.Last().X = dsMaxPoints[i].X;
                        straight_opt.Last().Y = dsMaxPoints[i].Y;
                        straight_opt.Last().Z = dsMaxPoints[i].Z;
                    }
                    else
                    {
                        straight_opt.Add(dsMaxPoints[i]);
                    }
                }
                foreach (Vector3d p in straight_opt)
                {
                    TXT.Write(p.X);
                    TXT.Write(' ');
                    TXT.Write(p.Y);
                    TXT.Write(' ');
                    TXT.Write(p.Z);
                    TXT.Write(' ');
                }
                TXT.WriteLine();
            }
        }
Пример #2
0
        /// <summary>
        /// This is where we do our rendering
        /// Called from UI thread = UI code safe in this function
        /// </summary>
        public override void Render(DrawArgs drawArgs)
        {
            if (!isInitialized || (this.world.Name == "Earth" && World.Settings.EnableAtmosphericScattering))
            {
                return;
            }

            // Camera & Device shortcuts ;)
            CameraBase camera = drawArgs.WorldCamera;
            Device     device = drawArgs.device;

            //if(camera.Altitude > 200e3) return;

            Point3d cameraPos            = camera.Position;
            double  distToCenterOfPlanet = (camera.Altitude + camera.WorldRadius);

            // Create or refresh SkyGradient dome
            if (mesh == null || lastAltitude != camera.Altitude)
            {
                // Compute distance to horizon and dome radius
                double tangentalDistance = Math.Sqrt(distToCenterOfPlanet * distToCenterOfPlanet - camera.WorldRadius * camera.WorldRadius);
                double domeRadius        = tangentalDistance;

                // horizon latitude
                double horizonLat = (-Math.PI / 2 + Math.Acos(tangentalDistance / distToCenterOfPlanet)) * 180 / Math.PI;

                // zenith latitude
                double zenithLat = 90;
                if (camera.Altitude >= thickness)
                {
                    double tangentalDistanceZenith = Math.Sqrt(distToCenterOfPlanet * distToCenterOfPlanet - (camera.WorldRadius + thickness) * (camera.WorldRadius + thickness));
                    zenithLat = (-Math.PI / 2 + Math.Acos(tangentalDistanceZenith / distToCenterOfPlanet)) * 180 / Math.PI;
                }
                if (camera.Altitude < thickness && camera.Altitude > thickness * 0.8)
                {
                    zenithLat = (thickness - camera.Altitude) / (thickness - thickness * 0.8) * 90;
                }
                // new mesh
                if (mesh != null)
                {
                    mesh.Dispose();
                }
                mesh         = ColoredSphere(device, domeRadius, horizonLat, zenithLat, 128, 24);
                lastAltitude = camera.Altitude;
            }

            // set texture to null
            device.SetTexture(0, null);
            device.TextureState[0].ColorOperation = TextureOperation.BlendCurrentAlpha;
            device.VertexFormat = CustomVertex.PositionColored.Format;

            // save world and projection transform
            Matrix origWorld      = device.Transform.World;
            Matrix origProjection = device.Transform.Projection;

            // move SkyGradient dome
            Matrix4d SkyGradientTrans;
            Point3d  cameraCoord = MathEngine.CartesianToSpherical(cameraPos.X, cameraPos.Y, cameraPos.Z);
            double   camLat      = cameraCoord.Y;
            double   camLon      = cameraCoord.Z;

            SkyGradientTrans = Matrix4d.Translation(0, 0, distToCenterOfPlanet);
            SkyGradientTrans = Matrix4d.Multiply(SkyGradientTrans, Matrix4d.RotationY(-camLat + Math.PI / 2));
            SkyGradientTrans = Matrix4d.Multiply(SkyGradientTrans, Matrix4d.RotationZ(camLon));

            device.Transform.World = ConvertDX.FromMatrix4d(SkyGradientTrans);

            // Recenter
            Recenter(drawArgs);

            // Save fog status
            bool origFog = device.RenderState.FogEnable;

            device.RenderState.FogEnable = false;

            // Set new one (to avoid being clipped) - probably better ways of doing this?
            double aspectRatio = (double)device.Viewport.Width / device.Viewport.Height;

            device.Transform.Projection = ConvertDX.FromMatrix4d(Matrix4d.PerspectiveFovRH(camera.Fov.Radians, aspectRatio, 1000, 30000000.0));

            // draw
            //device.RenderState.FillMode = FillMode.WireFrame;
            mesh.DrawSubset(0);

            // Restore device states
            device.RenderState.FillMode      = FillMode.Solid;
            device.Transform.World           = origWorld;
            device.Transform.Projection      = origProjection;
            device.RenderState.FogEnable     = origFog;
            device.RenderState.ZBufferEnable = true;

            // Fog effect
            if (useFog)
            {
                // Compute distance to horizon and camera altitude
                double tangentalDistance = Math.Sqrt(distToCenterOfPlanet * distToCenterOfPlanet - camera.WorldRadius * camera.WorldRadius);
                double a = camera.Altitude;
                device.RenderState.FogEnable    = true;
                device.RenderState.FogColor     = horizonColor;
                device.RenderState.FogTableMode = FogMode.Linear;
                device.RenderState.FogStart     = (float)(a * nearFactor);
                device.RenderState.FogEnd       = (float)(tangentalDistance * farFactor);
            }
        }