Пример #1
0
        private PixelInformation getIlluminationDirectionPerRenderingPixel(SpacecraftState sc, uint x, uint y)
        {
            PixelInformation PixelOut = new PixelInformation();
            Vector3D c_pos = sc.getPosition();

            // STEP 1: Visibility Test
            Vector3D rayDirection = (sc.getPOVDirection() + (((1 + Convert.ToDouble(this._height) - (2 * Convert.ToDouble(y))) / (2 * Convert.ToDouble(this._height))) * sc.getPOVUp()) - (((1 + Convert.ToDouble(this._width) - (2 * Convert.ToDouble(x))) / (2 * Convert.ToDouble(this._width))) * sc.getPOVRight())).unit();
            double discriminant = 4 * Math.Pow(c_pos * rayDirection, 2) - 4 * (rayDirection * rayDirection) * (c_pos * c_pos) + 4 * (rayDirection * rayDirection) * Math.Pow(_moon_radius, 2);

            bool encounter = false;
            Vector3D p_surf = new Vector3D();

            if (discriminant < 0)
            {
                // no encounter
            }
            else if (discriminant == 0)
            {
                // one intersection
                encounter = true;
                double t = (-2 * (c_pos * rayDirection)) / (2 * (rayDirection * rayDirection));

                p_surf = c_pos + rayDirection * t;
            }
            else
            {
                // two intersections
                encounter = true;
                double t1 = (-2 * (c_pos * rayDirection) + Math.Sqrt(discriminant)) / (2 * (rayDirection * rayDirection));
                double t2 = (-2 * (c_pos * rayDirection) - Math.Sqrt(discriminant)) / (2 * (rayDirection * rayDirection));

                Vector3D ray_point1 = c_pos + rayDirection * t1;
                Vector3D ray_point2 = c_pos + rayDirection * t2;
                double ray_norm1 = (ray_point1 - c_pos).norm();
                double ray_norm2 = (ray_point2 - c_pos).norm();

                if (ray_norm1 < ray_norm2)
                {
                    p_surf = ray_point1;
                }
                else
                {
                    p_surf = ray_point2;
                }
            }

            if (encounter)
            {
                /*
                    Pixel shows the Moon's surface: Continue with executing steps 2 - 8.
                */
                double x1 = Convert.ToDouble(x);
                double y1 = Convert.ToDouble(y);

                // STEP 2: Obtaining the Surface Hit Point
                PixelOut.lat = tools.rad2deg((Math.PI / 2) - Math.Acos(p_surf.z() / _moon_radius));
                PixelOut.lon = tools.rad2deg(Math.Atan2(p_surf.y(), p_surf.x()));

                // STEP 3: Calculation of the Sun's direction
                Vector3D hat_p_surf = p_surf.unit();
                Vector3D hat_d_sun = (sc.getSunPosition() - p_surf).unit();

                // STEP 4: Derivation of the Local Tangent Plane of the Surface Hit Point (nothing to do here)
                // STEP 5: Determination of a Subsurface Point of the Solar Illumination Direction on the Local Tangent Plane
                double lambda_5 = -(1000 * (hat_d_sun.x() * hat_p_surf.x() + hat_d_sun.y() * hat_p_surf.y() + hat_d_sun.z() * hat_p_surf.z())) / (hat_p_surf.x() * hat_p_surf.x() + hat_p_surf.y() * hat_p_surf.y() + hat_p_surf.z() * hat_p_surf.z());
                Vector3D p_local = p_surf + 1000 * hat_d_sun + lambda_5 * hat_p_surf;

                // STEP 6: Local Illumination Direction
                Vector3D hat_d_local = (p_local - c_pos).unit();

                /// STEP 7: Projection of the Local Illumination Point to the Image Plane
                Vector3D k = c_pos + sc.getPOVDirection();
                Vector3D c_up = sc.getPOVUp();
                Vector3D c_right = sc.getPOVRight();
                double w = Convert.ToDouble(this._width);
                double h = Convert.ToDouble(this._height);

                double x2 =
                    (
                        -2 * w * c_pos.y() * c_up.z() * hat_d_local.x() - c_right.y() * c_up.z() * hat_d_local.x() - w * c_right.y() * c_up.z() * hat_d_local.x()
                        + 2 * w * c_pos.x() * c_up.z() * hat_d_local.y() + c_right.x() * c_up.z() * hat_d_local.y() + w * c_right.x() * c_up.z() * hat_d_local.y()
                        + 2 * w * c_pos.z() * (c_up.y() * hat_d_local.x() - c_up.x() * hat_d_local.y())
                        + (1 + w) * c_right.z() * (c_up.y() * hat_d_local.x() - c_up.x() * hat_d_local.y())
                        + 2 * w * c_pos.y() * c_up.x() * hat_d_local.z() + c_right.y() * c_up.x() * hat_d_local.z() + w * c_right.y() * c_up.x() * hat_d_local.z()
                        - 2 * w * c_pos.x() * c_up.y() * hat_d_local.z() - c_right.x() * c_up.y() * hat_d_local.z() - w * c_right.x() * c_up.y() * hat_d_local.z()
                        - 2 * w * c_up.z() * hat_d_local.y() * k.x() + 2 * w * c_up.y() * hat_d_local.z() * k.x() + 2 * w * c_up.z() * hat_d_local.x() * k.y() - 2 * w * c_up.x() * hat_d_local.z() * k.y()
                        - 2 * w * c_up.y() * hat_d_local.x() * k.z() + 2 * w * c_up.x() * hat_d_local.y() * k.z()
                    )/(
                        2 * (c_right.z() * (c_up.y() * hat_d_local.x() - c_up.x() * hat_d_local.y()) + c_right.y() * (-c_up.z() * hat_d_local.x() + c_up.x() * hat_d_local.z()) + c_right.x() * (c_up.z() * hat_d_local.y() - c_up.y() * hat_d_local.z()))
                    );

                double y2 =
                    (
                        -c_right.z() * c_up.y() * hat_d_local.x() - h * c_right.z() * c_up.y() * hat_d_local.x() + c_right.y() * c_up.z() * hat_d_local.x()
                        + h * c_right.y() * c_up.z() * hat_d_local.x() - 2 * h * c_pos.x() * c_right.z() * hat_d_local.y() + c_right.z() * c_up.x() * hat_d_local.y()
                        + h * c_right.z() * c_up.x() * hat_d_local.y() - c_right.x() * c_up.z() * hat_d_local.y() - h * c_right.x() * c_up.z() * hat_d_local.y()
                        + c_pos.z() * (-2 * h * c_right.y() * hat_d_local.x() + 2 * h * c_right.x() * hat_d_local.y()) + 2 * h * c_pos.x() * c_right.y() * hat_d_local.z()
                        - c_right.y() * c_up.x() * hat_d_local.z() - h * c_right.y() * c_up.x() * hat_d_local.z() + c_right.x() * c_up.y() * hat_d_local.z()
                        + h * c_right.x() * c_up.y() * hat_d_local.z() + 2 * h * c_pos.y() * (c_right.z() * hat_d_local.x() - c_right.x() * hat_d_local.z())
                        + 2 * h * c_right.z() * hat_d_local.y() * k.x() - 2 * h * c_right.y() * hat_d_local.z() * k.x() - 2 * h * c_right.z() * hat_d_local.x() * k.y()
                        + 2 * h * c_right.x() * hat_d_local.z() * k.y() + 2 * h * c_right.y() * hat_d_local.x() * k.z() - 2 * h * c_right.x() * hat_d_local.y() * k.z()
                    )/(
                        2 * (c_right.z() * (-c_up.y() * hat_d_local.x() + c_up.x() * hat_d_local.y()) + c_right.y() * (c_up.z() * hat_d_local.x() - c_up.x() * hat_d_local.z()) + c_right.x() * (-c_up.z() * hat_d_local.y() + c_up.y() * hat_d_local.z()))
                    );

                // STEP 8: The Local Solar Illumination Angle
                Vector2D v1 = new Vector2D(0, 1000);
                Vector2D v2 = new Vector2D(x2-x1, y2-y1);

                if (v2.x() > 0)
                {
                    PixelOut.IlluminationAngle = tools.rad2deg(Math.Acos((v1 * v2) / (v1.norm() * v2.norm())));
                }
                else
                {
                    PixelOut.IlluminationAngle = tools.rad2deg(2 * Math.PI - Math.Acos((v1 * v2) / (v1.norm() * v2.norm())));
                }
                PixelOut.exists = true;

                return PixelOut;
            }
            else
            {
                // next grid sample point
                return PixelOut;
            }
        }
Пример #2
0
        private void generatePOVRayFile(SpacecraftState sc, string filename)
        {
            ArrayList filetext = new ArrayList();
            Vector3D scPos = sc.getPosition();
            Vector3D sunPos = sc.getSunPosition();

            /* POV-Ray file */
            /* ============ */

                filetext.Add("#version 3.7;");
                filetext.Add("");
                filetext.Add("#declare Orange = rgb <1,0.5,0>;");
                filetext.Add("#declare Red = rgb <1,0,0>;");
                filetext.Add("#declare Yellow = rgb <1,1,0>;");
                filetext.Add("#declare moon = texture");
                filetext.Add("                {");
                filetext.Add("                  pigment { color rgb<0.8, 0.8, 0.8> }");
                filetext.Add("                  finish");
                filetext.Add("                  {");
                filetext.Add("                    ambient 0.0");
                filetext.Add("                    diffuse 0.8");
                filetext.Add("                  }");
                filetext.Add("                }");
                filetext.Add("");
                filetext.Add("global_settings");
                filetext.Add("{");
                filetext.Add("   charset utf8");
                filetext.Add("   assumed_gamma 1.0");
                filetext.Add("}");
                filetext.Add("");
                filetext.Add("camera");
                filetext.Add("{");
                filetext.Add("  perspective");
                filetext.Add("  location <" + scPos.x()/1000 + ", " + scPos.y()/1000 + ", " + scPos.z()/1000 + ">");
                filetext.Add("  right <" + sc.getPOVRight().x().ToString("0.0000000") + ", " + sc.getPOVRight().y().ToString("0.0000000") + ", " + sc.getPOVRight().z().ToString("0.0000000") + ">");
                filetext.Add("  up <" + sc.getPOVUp().x().ToString("0.0000000") + ", " + sc.getPOVUp().y().ToString("0.0000000") + ", " + sc.getPOVUp().z().ToString("0.0000000") + ">");
                filetext.Add("  direction <" + sc.getPOVDirection().x().ToString("0.0000000") + ", " + sc.getPOVDirection().y().ToString("0.0000000") + ", " + sc.getPOVDirection().z().ToString("0.0000000") + ">");
                filetext.Add("}");
                filetext.Add("");
                if (!Program.ignoreSun)
                {
                    filetext.Add("light_source");
                    filetext.Add("{");
                    filetext.Add("  <" + sunPos.x() / 1000 + ", " + sunPos.y() / 1000 + ", " + sunPos.z() / 1000 + ">");
                    filetext.Add("  color rgb<1, 1, 1>");
                    filetext.Add("  looks_like");
                    filetext.Add("  {");
                    filetext.Add("    sphere");
                    filetext.Add("    {");
                    filetext.Add("      0, 1000");
                    filetext.Add("      pigment { rgbt 1 }");
                    filetext.Add("      hollow");
                    filetext.Add("      interior");
                    filetext.Add("      {");
                    filetext.Add("        media");
                    filetext.Add("        {");
                    filetext.Add("          emission 1");
                    filetext.Add("          density");
                    filetext.Add("          {");
                    filetext.Add("            spherical");
                    filetext.Add("            density_map");
                    filetext.Add("            {");
                    filetext.Add("              [0 rgb 0]");
                    filetext.Add("              [60 Orange]");
                    filetext.Add("              [80 Red]");
                    filetext.Add("              [100 Yellow]");
                    filetext.Add("            }");
                    filetext.Add("            scale 1000");
                    filetext.Add("          }");
                    filetext.Add("        }");
                    filetext.Add("      }");
                    filetext.Add("    }");
                    filetext.Add("  }");
                    filetext.Add("}");
                }
                else
                {
                    filetext.Add("light_source");
                    filetext.Add("{");
                    filetext.Add("  <" + scPos.x() / 1000 + ", " + scPos.y() / 1000 + ", " + scPos.z() / 1000 + ">");
                    filetext.Add("  color rgb<1, 1, 1>");
                    filetext.Add("}");
                }
                filetext.Add("");

                // Dynamical Surface Pattern Selection Algorithm (DSPSA)
                ArrayList pattern = new ArrayList();
                for (double y = 1; y <= this._height; y++)
                {
                    for (double x = 1; x <= this._width; x++)
                    {
                        Vector3D rayDirection = sc.getPOVDirection() + (((1 + this._height - (2 * y)) / (2 * this._height)) * sc.getPOVUp()) - (((1 + this._width - (2 * x)) / (2 * this._width)) * sc.getPOVRight());
                        this.DSPSA(rayDirection, scPos, pattern);
                    }
                }

                foreach (string str in pattern)
                {
                    filetext.Add("#include \"" + this._pattern_repos + this._res + "\\pattern_LDEM_" + this._res + str + ".inc\"");
                }

                /*  FOR DEBUG: diplay three dots as axis marker
                filetext.Add("sphere { <1800,0,0>, 100 pigment { color rgb <1.0, 0.0, 0.0> } finish { ambient 1.0 diffuse 1.0 } no_shadow }");
                filetext.Add("sphere { <0,1800,0>, 100 pigment { color rgb <1.0, 1.0, 0.0> } finish { ambient 1.0 diffuse 1.0 } no_shadow }");
                filetext.Add("sphere { <0,0,1800>, 100 pigment { color rgb <0.0, 1.0, 0.0> } finish { ambient 1.0 diffuse 1.0 } no_shadow }");
                */

                filetext.Add("");
                filetext.Add("//-------------------------DEBUG INFORMATION-------------------------------------------------------------------------------------------------------");
                filetext.Add("// MSISF Version: " + Program.VERSION);
                filetext.Add("// Config:");
                filetext.Add("//   SimTime:              " + sc.getTime().ToString(Program.scientificFormat));
                filetext.Add("//   s/c position:         [" + scPos.x().ToString(Program.scientificFormat) + "," + scPos.y().ToString(Program.scientificFormat) + "," + scPos.z().ToString(Program.scientificFormat) + "]");
                filetext.Add("//   s/c orientation:      [" + sc.getOrientation().v().x().ToString(Program.scientificFormat) + "," + sc.getOrientation().v().y().ToString(Program.scientificFormat) + "," + sc.getOrientation().v().z().ToString(Program.scientificFormat) + "," + sc.getOrientation().r().ToString(Program.scientificFormat) + "]");
                filetext.Add("//-----------------------END DEBUG INFORMATION------------------------------------------------------------------------------------------------------");

                TextWriter file = new System.IO.StreamWriter(filename + ".pov", false);
                foreach (string line in filetext)
                {
                    file.WriteLine(line);
                }
                file.Close();

                string md5 = tools.md5File(filename + ".pov");
                file = new System.IO.StreamWriter(filename + ".pov", true);
                file.WriteLine("// " + md5);
                file.Close();

            /* META INFORMATION FILE (XML FILE) */
            /* ================================ */

                filetext = new ArrayList();
                filetext.Add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
                filetext.Add("<!DOCTYPE MSISRendering SYSTEM \"../lib/MSISRendering.dtd\">");
                filetext.Add("<MSISRendering>");

                // GENERAL INFORMATION
                filetext.Add("    <GeneralInformation>");
                filetext.Add("        <SimulationTime>");
                filetext.Add("            <MJD>" + sc.getTime().ToString(Program.scientificFormat) + "</MJD>");
                filetext.Add("            <UTC>" + tools.MJDtoUTC(sc.getTime()).ToString("s") + "Z</UTC>");
                filetext.Add("        </SimulationTime>");
                filetext.Add("        <CameraPosition unit=\"m\">");
                filetext.Add("            <Vector3D x=\"" + sc.getPosition().x().ToString(Program.scientificFormat) + "\" y=\"" + sc.getPosition().y().ToString(Program.scientificFormat) + "\" z=\"" + sc.getPosition().z().ToString(Program.scientificFormat) + "\" />");
                filetext.Add("        </CameraPosition>");
                filetext.Add("        <CameraOrientation>");
                filetext.Add("            <Quaternion r=\"" + sc.getOrientation().r().ToString(Program.scientificFormat) + "\" x=\"" + sc.getOrientation().v().x().ToString(Program.scientificFormat) + "\" y=\"" + sc.getOrientation().v().y().ToString(Program.scientificFormat) + "\" z=\"" + sc.getOrientation().v().z().ToString(Program.scientificFormat) + "\" />");
                filetext.Add("        </CameraOrientation>");
                filetext.Add("        <SunPosition unit=\"m\">");
                filetext.Add("            <Vector3D x=\"" + sc.getSunPosition().x().ToString(Program.scientificFormat) + "\" y=\"" + sc.getSunPosition().y().ToString(Program.scientificFormat) + "\" z=\"" + sc.getSunPosition().z().ToString(Program.scientificFormat) + "\" />");
                filetext.Add("        </SunPosition>");
                filetext.Add("        <FlightAltitude unit=\"m\">" + (sc.getPosition().norm() - 1.73715E6).ToString(Program.scientificFormat) + "</FlightAltitude>");
                filetext.Add("        <SurfaceResolution unit=\"px/deg\">" + this._res.ToString() + "</SurfaceResolution>");
                filetext.Add("        <FOV unit=\"deg\">" + this._FOV.ToString() + "</FOV>");
                filetext.Add("        <MSISVersion>" + Program.VERSION + "</MSISVersion>");
                filetext.Add("        <CommandLine>" + Program.commandLineString +"</CommandLine>");
                filetext.Add("    </GeneralInformation>");

                // PIXEL INFORMATION
                filetext.Add("    <PixelInformation>");
                for(uint y = this.gridV; y <= this._height; y += this.gridV)
                {
                    for(uint x = this.gridH; x <= this._width; x += this.gridH)
                    {
                        PixelInformation PixelMetaData = new PixelInformation();
                        // if getIlluminationDirectionPerRenderingPixel() returns false, the Moon's
                        // surface has not been hit (the respective pixel shows the space background)
                        PixelMetaData = getIlluminationDirectionPerRenderingPixel(sc, x, y);
                        if (PixelMetaData.exists)
                        {
                            filetext.Add("        <Pixel h=\"" + x.ToString() + "\" v=\"" + y.ToString() + "\">");
                            filetext.Add("            <SelenographicCoordinates lat=\"" + PixelMetaData.lat.ToString(Program.scientificFormat) + "\" lon=\"" + PixelMetaData.lon.ToString(Program.scientificFormat) + "\" units=\"deg\" />");
                            filetext.Add("            <IlluminationDirection unit=\"deg\">" + PixelMetaData.IlluminationAngle.ToString(Program.scientificFormat) + "</IlluminationDirection>");
                            filetext.Add("        </Pixel>");
                            sc.PixelInfo.Add(new Vector2D(Convert.ToDouble(x), Convert.ToDouble(y)), PixelMetaData);
                        }
                    }
                }
                filetext.Add("    </PixelInformation>");

                filetext.Add("</MSISRendering>");

                file = new System.IO.StreamWriter(filename + ".xml", false);
                foreach (string line in filetext)
                {
                    file.WriteLine(line);
                }
                file.Close();
        }