예제 #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
        public void doCalculationsLogic(Spacecraft sc, double time)
        {
            int step = sc.addSpacecraftState(time);
            SpacecraftState scState = sc.getSpacecraftState(step);

            double simTime = sc.getSpacecraftState(step).getTime();
            Vector3D position = sc.getSpacecraftState(step).getPosition();
            Vector3D sun_position = sc.getSpacecraftState(step).getSunPosition();
            Quaternion orientation = sc.getSpacecraftState(step).getOrientation();

            Console.WriteLine("  Simulation time point #" + this.loopCount.ToString("D5") + ": " + simTime + " MJD (" + tools.MJDtoUTC(simTime).ToString("s") + " UTC)");
            Console.WriteLine("  --------------------------------------------------------------------------------------------------------------");
            Console.WriteLine();
            Console.WriteLine("    Calculating spacecraft position at given simulation time...");
            Console.WriteLine("      Result:");
            Console.WriteLine("        x = " + position.x().ToString(Program.scientificFormat) + " m      (" + tools.m2AU(position.x()).ToString(Program.scientificFormat) + " AU)");
            Console.WriteLine("        y = " + position.y().ToString(Program.scientificFormat) + " m      (" + tools.m2AU(position.y()).ToString(Program.scientificFormat) + " AU)");
            Console.WriteLine("        z = " + position.z().ToString(Program.scientificFormat) + " m      (" + tools.m2AU(position.z()).ToString(Program.scientificFormat) + " AU)");
            Console.WriteLine();
            if (sc.isOrientationGiven())
            {
                Console.WriteLine("    Calculating spacecraft orientation at given simulation time...");
                Console.WriteLine("      Result (Quaternion):");
                Console.WriteLine("        q_0 = " + orientation.r().ToString(Program.scientificFormat));
                Console.WriteLine("        q_1 = " + orientation.v().x().ToString(Program.scientificFormat));
                Console.WriteLine("        q_2 = " + orientation.v().y().ToString(Program.scientificFormat));
                Console.WriteLine("        q_3 = " + orientation.v().z().ToString(Program.scientificFormat));
                Console.WriteLine();
            }
            Console.WriteLine("    Calculating Sun position at given simulation time...");
            Console.WriteLine("      Result:");
            Console.WriteLine("        x = " + sun_position.x().ToString(Program.scientificFormat) + " m      (" + tools.m2AU(sun_position.x()).ToString(Program.scientificFormat) + " AU)");
            Console.WriteLine("        y = " + sun_position.y().ToString(Program.scientificFormat) + " m      (" + tools.m2AU(sun_position.y()).ToString(Program.scientificFormat) + " AU)");
            Console.WriteLine("        z = " + sun_position.z().ToString(Program.scientificFormat) + " m      (" + tools.m2AU(sun_position.z()).ToString(Program.scientificFormat) + " AU)");
            Console.WriteLine();

            string filename = this.getOutputPath() + "MoonSurfIllumSim_step_" + this.loopCount.ToString("D5");
            Console.WriteLine("    Ray tracing scene (Dynamical Surface Pattern Selection Algorithm - DSPSA)...");
            this.generatePOVRayFile(sc.getSpacecraftState(step), filename);
            Console.WriteLine("    POV-Ray file written to \"" + filename + ".pov\"");
            Console.WriteLine("    Rendering using POV-Ray...");

            Process pov = new Process();
            pov.StartInfo.FileName = this._pov_path + "pvengine64.exe";
            pov.StartInfo.Arguments = "/EXIT Quality=11 Antialias_Depth=3 Antialias=On Antialias_Threshold=0.1 Jitter_Amount=0.5 Jitter=On Width=" + this._width + " Height=" + this._height + " Antialias=On Antialias_Threshold=0.3 /RENDER \"" + filename + ".pov\"";
            pov.Start();
            pov.WaitForExit();

            if (Program.writeAnnotation)
            {
                Console.WriteLine("    Regenerating rendering with annotations...");
                FileStream myStream = new FileStream(filename + ".png", FileMode.Open);
                Image myBitmap = Image.FromStream(myStream);
                myStream.Close();
                myStream.Dispose();
                Graphics g = Graphics.FromImage(myBitmap);
                //g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                float fontSize = (float)Convert.ToDouble(this._width) * 0.0095F;
                Font myFont = new Font("Consolas", fontSize);
                Quaternion rotQuat;

                if (sc.isOrientationGiven())
                {
                    rotQuat = scState.getOrientation();
                }
                else
                {
                    double phi = Math.Atan2(scState.getPosition().y(), scState.getPosition().x());
                    double theta = Math.Acos(scState.getPosition().z() / (scState.getPosition().norm()));
                    rotQuat = new RotationQuaternion(new Vector3D(0, 1, 0), theta) * new RotationQuaternion(new Vector3D(0, 0, 1), -phi);
                }

                // Local Solar Illumination Angle
                Pen pen = new Pen(Color.Red, 2);
                pen.StartCap = LineCap.SquareAnchor;
                pen.EndCap = LineCap.Round;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                SolidBrush redBrush = new SolidBrush(Color.Red);

                foreach (var pixel in scState.PixelInfo)
                {
                    double x1 = pixel.Key.x();
                    double y1 = pixel.Key.y();

                    Vector2D endPoint = new Vector2D(x1, y1) + new Vector2D(0, this.gridH/2).rotate(tools.deg2rad(pixel.Value.IlluminationAngle));

                    g.DrawLine(pen, new Point(Convert.ToInt32(x1), Convert.ToInt32(y1)), new Point(Convert.ToInt32(endPoint.x()), Convert.ToInt32(endPoint.y())));
                    g.FillEllipse(redBrush, (float)x1 - 3F,  (float)y1 - 3F, 6, 6);
                }

                // Annotations to be written
                g.DrawString("Simulation Timecode:        " + scState.getTime().ToString(Program.scientificFormat) + " MJD (" + tools.MJDtoUTC(simTime).ToString("s") + "Z UTC)", myFont, Brushes.White, new PointF(2 * fontSize, 1 * 1.8F * fontSize));
                g.DrawString("S/C Position:               [" + scState.getPosition().x().ToString(Program.scientificFormat) + "," + scState.getPosition().y().ToString(Program.scientificFormat) + "," + scState.getPosition().z().ToString(Program.scientificFormat) + "] m", myFont, Brushes.White, new PointF(2 * fontSize, 2 * 1.8F * fontSize));
                g.DrawString("S/C Orientation Quaternion: [" + rotQuat.v().x().ToString(Program.scientificFormat) + "," + rotQuat.v().y().ToString(Program.scientificFormat) + "," + rotQuat.v().z().ToString(Program.scientificFormat) + "," + rotQuat.r().ToString(Program.scientificFormat) + "]", myFont, Brushes.White, new PointF(2 * fontSize, 3 * 1.8F * fontSize));
                g.DrawString("Sun Position:               [" + scState.getSunPosition().x().ToString(Program.scientificFormat) + "," + scState.getSunPosition().y().ToString(Program.scientificFormat) + "," + scState.getSunPosition().z().ToString(Program.scientificFormat) + "] m", myFont, Brushes.White, new PointF(2 * fontSize, 4 * 1.8F * fontSize));
                g.DrawString("Flight Altitude over MMR:   " + (scState.getPosition().norm() - 1.73715E6).ToString(Program.scientificFormat) + " m", myFont, Brushes.White, new PointF(2 * fontSize, 5 * 1.8F * fontSize));
                g.DrawString("Surface Mesh Resolution:    " + this._res.ToString() + " px/deg", myFont, Brushes.White, new PointF(2 * fontSize, 6 * 1.8F * fontSize));
                g.DrawString("FOV:                        " + this._FOV.ToString() + " deg (hor. & vert.), optics: perspective camera", myFont, Brushes.White, new PointF(2 * fontSize, 7 * 1.8F * fontSize));
                g.DrawString("Moon Surface Illumination Simulation Framework (MSISF), v" + Program.VERSION, new Font("Tahoma", fontSize), Brushes.White, new PointF(2 * fontSize, (float)Convert.ToDouble(this._height) - 3 * 1.8F * fontSize));
                g.DrawString("B.Eng. René Schwarz (rene-schwarz.com), more Information: http://go.rene-schwarz.com/masters-thesis", new Font("Tahoma", fontSize), Brushes.White, new PointF(2 * fontSize, (float)Convert.ToDouble(this._height) - 2 * 1.8F * fontSize));

                myBitmap.Save(filename + ".annotated.png");
                myBitmap.Dispose();
            }

            Console.WriteLine();
            Console.WriteLine();

            this.loopCount++;
        }