Пример #1
0
 public static bool imageBoundAContainedInImageBoundB(ImageBounds A, ImageBounds B)
 {
     if (
         A.eastDeg  < B.eastDeg  && A.eastDeg   > B.westDeg   &&
         A.westDeg  > B.westDeg  && A.westDeg   < B.eastDeg   &&
         A.northDeg < B.northDeg && A.northDeg  > B.southDeg &&
         A.southDeg > B.southDeg && A.southDeg  < B.northDeg) return true;
     else return false;
 }
Пример #2
0
        public ProjectSummary readPolygonCoverageData(XmlReader tr, String ProjectName)
        {
            ///////////////////////////////////////////////////////////////////////
            //read in the original client polygon outline of the site
            ///////////////////////////////////////////////////////////////////////

            bool completedProjectPolygon        = false;
            bool completedProjectData           = false;
            bool completedMissionImageBounds    = false;

            ProjectSummary projSum = new ProjectSummary();

            projSum.coverageType = COVERAGE_TYPE.polygon;

            projSum.ProjectName = ProjectName;  //this is the name of the kml file -- maybe should use the name of the placemark???
            projSum.ProjectPolygon = new List<PointD>();
            projSum.msnSum = new List<MissionSummary>();

            //photocenters are on a regular grid with a fixed origin -- redined from the input file
            projSum.gridOrigin = new PointD(0.0, 0.0);

            //inspecting the header is complete --- new interrogate the remainder
            while (tr.Read() && !completedProjectData)
            {
                if (tr.IsStartElement() && tr.Name == "Placemark")
                {
                    while (tr.Read() && !completedProjectPolygon)
                    {
                        if (tr.IsStartElement() && tr.Name == "name")
                        {
                            tr.Read();
                            //the Placemark name should be the same as the mission plan kml name
                            if (tr.Value == ProjectName) //here we check to see if the placemark name is the input kml filename
                            {
                                while (tr.Read() && !completedProjectPolygon)
                                {
                                    if (tr.IsStartElement() && tr.Name == "coordinates")
                                    {
                                        tr.Read();
                                        char[] delimiterChars = { ',', ' ', '\t', '\n', '\r' };   //these delimiters were determined by looking at a file ...
                                        string[] coordinateValues = tr.Value.ToString().Split(delimiterChars);

                                        //the "value" is the text between the <coordinates> and </coordinates>
                                        //below we read the complete string value and split it into separate substrings -- ugly but it works
                                        //the substrings contain the individual coordinate values with some ""s and the heigts are "0".

                                        //get the quantitative lat/long values from the text array ... there are a number of ""s in the text file ...
                                        //each Google point has three values : longitude, Latitude, height -- we assume the height is zero here
                                        int k = 0; int i = 0;
                                        while (i < coordinateValues.Count())
                                        {
                                            if (coordinateValues[i] != "")
                                            {

                                                double lat = Convert.ToDouble(coordinateValues[i + 1]);
                                                double lon = Convert.ToDouble(coordinateValues[i]);
                                                projSum.ProjectPolygon.Add(new PointD(lon, lat));
                                                k++;  //index of the storage array

                                                //increment the split array by 3 because the points are lat,lon,height
                                                i += 3;  //increment by 3 to get the next coordinate
                                            }
                                            else i++;  //here we skip the ""s in the text array
                                        }
                                        completedProjectPolygon = true;

                                    }
                                }
                            }
                            else
                            {
                                MessageBox.Show("The mission plan file has the wrong format \n The Placemark name is not the same as the kml file name");
                            }
                        }
                    }
                }  //end of getting projectPolygon stored as a Placemark

                //////////////////////////////////////////////////////////////////////////////////
                //read in the Project-specific Data for this Project
                //////////////////////////////////////////////////////////////////////////////////

                //get the geodetic bopunds of the project polygon
                if (tr.IsStartElement() && tr.Name == "north" && !completedProjectData)
                {
                    tr.Read();
                    projSum.ProjectImage.northDeg = Convert.ToDouble(tr.Value);
                }
                if (tr.IsStartElement() && tr.Name == "south" && !completedProjectData)
                {
                    tr.Read();
                    projSum.ProjectImage.southDeg = Convert.ToDouble(tr.Value);
                }
                if (tr.IsStartElement() && tr.Name == "east" && !completedProjectData)
                {
                    tr.Read();
                    projSum.ProjectImage.eastDeg = Convert.ToDouble(tr.Value);
                }
                if (tr.IsStartElement() && tr.Name == "west" && !completedProjectData)
                {
                    tr.Read();
                    projSum.ProjectImage.westDeg = Convert.ToDouble(tr.Value);
                }

                if (tr.IsStartElement() && tr.Name == "downRangePhotoSpacingMeters" && !completedProjectData)
                {
                    tr.Read();
                    projSum.downrangeTriggerSpacing = Convert.ToDouble(tr.Value);
                }

                if (tr.IsStartElement() && tr.Name == "crossRangeSwathWidth" && !completedProjectData)
                {
                    tr.Read();
                    projSum.crossRangeSwathWidth = Convert.ToDouble(tr.Value);
                }

                if (tr.IsStartElement() && tr.Name == "numberOfMissons" && !completedProjectData)
                {
                    tr.Read();
                    projSum.numberOfMissions = Convert.ToInt32(tr.Value);
                }

                if (tr.IsStartElement() && tr.Name == "UTMZone" && !completedProjectData)
                {
                    tr.Read();
                    projSum.UTMZone = tr.Value;
                }

                if (tr.IsStartElement() && tr.Name == "gridOriginUTMNorthing" && !completedProjectData)
                {
                    tr.Read();
                    projSum.gridOrigin.Y = 1.0;
                    projSum.gridOrigin.Y = Convert.ToDouble(tr.Value);
                }
                if (tr.IsStartElement() && tr.Name == "gridOriginUTMEasting" && !completedProjectData)
                {
                    tr.Read();
                    projSum.gridOrigin.X = Convert.ToDouble(tr.Value);
                    ///////////////////////////////////////////////////////////////////////////////////
                    completedProjectData = true;   ///Easting is the last one of the data elements
                    ///////////////////////////////////////////////////////////////////////////////////
                }
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //read in the bounds of the mission images -- images are stored separately in a folder: ProjectName_Background\background_YY.jpg
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            List<ImageBounds> MissionImage = new List<ImageBounds>(); // we will use this later to fill the mission Summarys

            while (tr.Read() && !completedMissionImageBounds)
            {
                if (tr.IsStartElement() && tr.Name == "name")  //takes us to the folder containing the mission images
                {
                    tr.Read();
                    if (tr.Value == " Summary Images")  //verifies that this is the correct folder
                    {
                        int missionImageBoundRead = 0;
                        while (tr.Read() && missionImageBoundRead < projSum.numberOfMissions)  //loop over all image bounds in the folder
                        {
                            if (tr.IsStartElement() && tr.Name == "name")  //found the name element for next mission image bounds
                            {
                                while (tr.Read() && missionImageBoundRead < projSum.numberOfMissions)
                                {
                                    if (tr.Value == " Summary_" + missionImageBoundRead.ToString("D3") + " ")  //found correct mission name
                                    {
                                        ImageBounds ib = new ImageBounds(); // fill an image bounds structure
                                        while (tr.Read())
                                        {
                                            if (tr.IsStartElement() && tr.Name == "north")
                                            {
                                                tr.Read();
                                                ib.northDeg = Convert.ToDouble(tr.Value);
                                            }

                                            if (tr.IsStartElement() && tr.Name == "east")
                                            {
                                                tr.Read();
                                                ib.eastDeg = Convert.ToDouble(tr.Value);
                                            }

                                            if (tr.IsStartElement() && tr.Name == "south")
                                            {
                                                tr.Read();
                                                ib.southDeg = Convert.ToDouble(tr.Value);
                                            }

                                            if (tr.IsStartElement() && tr.Name == "west")
                                            {
                                                tr.Read();
                                                ib.westDeg = Convert.ToDouble(tr.Value);

                                                MissionImage.Add(ib);  //fill the image bounds structure

                                                missionImageBoundRead++;  //the west is always the last element
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        completedMissionImageBounds = true;
                    }
                }
            }

            /////////////////////////////////////////////////////////////////////////////
            //  read in the per-mission data
            //  the sets of information
            //  (1)  mission-specific parameters
            //  (2)  mission-specfic polygon
            //  (3)  flight line ends
            /////////////////////////////////////////////////////////////////////////////

            //////////////////////////////////////////////////////////////////////
            //read in the mission-specific data values for this mission
            //////////////////////////////////////////////////////////////////////

            int missionNumberCounter = 0;
            int flightLineNumber = 0;   //flight line number increment sequentially across each mission --- are not renumbered at a mission

            while (missionNumberCounter < projSum.numberOfMissions)
            {

                bool completedPerMissionData = false;
                //we are at the top of a mission summary dataset
                MissionSummary msnSum = new MissionSummary();

                while (tr.Read() && !completedPerMissionData)  //loop here til finished the mission-specific parameters
                {
                    if (tr.IsStartElement() && tr.Name == "missionNumber")
                    {
                        tr.Read();
                        int missionNumber = Convert.ToInt32(tr.Value);
                        while (tr.Read() && !completedPerMissionData)
                        {
                            if (tr.IsStartElement() && tr.Name == "numFLs")
                            {
                                tr.Read();
                                msnSum.numberOfFlightlines = Convert.ToInt32(tr.Value);
                            }

                            if (tr.IsStartElement() && tr.Name == "flightAltMSL")
                            {
                                tr.Read();
                                msnSum.flightAltMSLft = Convert.ToDouble(tr.Value);
                                completedPerMissionData = true;
                            }

                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////
                //read in the mission-specific polygon formed from flight line endpoints
                ////////////////////////////////////////////////////////////////////////////////////////////////

                bool completedThisMissionPolygon = false;
                while (tr.Read() && !completedThisMissionPolygon)  //loop here til finished the mission-specific polygon
                {
                    msnSum.missionGeodeticPolygon = new List<PointD>();

                    while (tr.Read() && !completedThisMissionPolygon)
                    {

                        //first get the mission polygon
                        if (tr.IsStartElement() && tr.Name == "name")
                        {
                            tr.Read();
                            if (tr.Value == " MissionPolygon_" + missionNumberCounter.ToString("D2") + " ")
                            {
                                while (tr.Read())
                                {
                                    if (tr.IsStartElement() && tr.Name == "coordinates")
                                    {
                                        tr.Read();
                                        char[] delimiterChars = { ',', ' ', '\t', '\n', '\r' };   //these delimiters were determined by looking at a file ...
                                        string[] coordinateValues = tr.Value.ToString().Split(delimiterChars);

                                        //the "value" is the text between the <coordinates> and </coordinates>
                                        //below we read the complete string value and split it into separate substrings -- ugly but it works
                                        //the substrings contain the individual coordinate values with some ""s and the heigts are "0".

                                        //get the quantitative lat/long values from the text array ... there are a number of ""s in the text file ...
                                        //each Google point has three values : longitude, Latitude, height -- we assume the height is zero here
                                        int k = 0; int i = 0;
                                        while (i < coordinateValues.Count())
                                        {
                                            if (coordinateValues[i] != "")
                                            {

                                                double lat = Convert.ToDouble(coordinateValues[i + 1]);
                                                double lon = Convert.ToDouble(coordinateValues[i]);

                                                msnSum.missionGeodeticPolygon.Add(new PointD(lon, lat));

                                                k++;  //index of the storage array

                                                //increment the split array by 3 because the points are lat,lon,height
                                                i += 3;  //increment by 3 to get the next coordinate
                                            }
                                            else i++;  //here we skip the ""s in the text array
                                        }
                                        completedThisMissionPolygon = true;
                                        break;
                                    }
                                }
                            }

                        }

                    }
                }  //end of completedThisMissionPolygon

                ////////////////////////////////////////////////////////////////
                //read the flight line data for each mission
                ////////////////////////////////////////////////////////////////

                bool completedThisMissionFlightLines = false;
                int flightlinesCounterInMission = 0;
                double FLLengthMeters = 0;
                msnSum.FlightLinesCurrentPlan = new List<endPoints>();
                while (tr.Read() && !completedThisMissionFlightLines)  //loop here til read in all the flight lines for this mission
                {
                        //first get the mission polygon
                    if (tr.IsStartElement() && tr.Name == "name")
                    {

                        tr.Read();
                        // FlightlineNumber_000
                        if (tr.Value == " FlightlineNumber_" + flightLineNumber.ToString("D3") + " ")
                        {
                            while (tr.Read())
                            {
                                //  <lengthMeters>25266.9</lengthMeters>
                                if (tr.IsStartElement() && tr.Name == "lengthMeters")
                                {
                                    tr.Read();
                                    FLLengthMeters = Convert.ToDouble(tr.Value);
                                }

                                if (tr.IsStartElement() && tr.Name == "coordinates")
                                {
                                    tr.Read();
                                    char[] delimiterChars = { ',', ' ', '\t', '\n', '\r' };   //these delimiters were determined by looking at a file ...
                                    string[] coordinateValues = tr.Value.ToString().Split(delimiterChars);

                                    //the "value" is the text between the <coordinates> and </coordinates>
                                    //below we read the complete string value and split it into separate substrings -- ugly but it works
                                    //the substrings contain the individual coordinate values with some ""s and the heigts are "0".

                                    //get the quantitative lat/long values from the text array ... there are a number of ""s in the text file ...
                                    //each Google point has three values : longitude, Latitude, height -- we assume the height is zero here
                                    int k = 0; int i = 0;
                                    PointD[] ends = new PointD[2];
                                    while (i < coordinateValues.Count())
                                    {
                                        if (coordinateValues[i] != "")
                                        {

                                            double lat = Convert.ToDouble(coordinateValues[i + 1]);
                                            double lon = Convert.ToDouble(coordinateValues[i]);
                                            ends[k] = new PointD(lon, lat);

                                            k++;  //index of the storage array

                                            //increment the split array by 3 because the points are lat,lon,height
                                            i += 3;  //increment by 3 to get the next coordinate
                                        }
                                        else i++;  //here we skip the ""s in the text array
                                    }

                                    //NOTE:  the structure for the flight line info includes the original sequally-numbered flight line numbers
                                    //       But the FlightLinesCurrentPlan List is indexed from [0] to numFlightLinesThis mission
                                    //photocenter offset (0) added to allow numbering adjustment for reflown lines
                                    msnSum.FlightLinesCurrentPlan.Add(new endPoints(flightLineNumber, ends[0], ends[1],FLLengthMeters,0));

                                    flightlinesCounterInMission++;
                                    flightLineNumber++;
                                    if (flightlinesCounterInMission == msnSum.numberOfFlightlines)
                                    {
                                        completedThisMissionFlightLines = true;

                                        msnSum.MissionImage = MissionImage[missionNumberCounter];  //MissionImage was filled earlier

                                        missionNumberCounter++;  //increment the mission counter
                                    }

                                    //completedThisMissionFlightLines = true;
                                    break;
                                }
                            }
                        }

                    }
                }

                //at this time declare the mission as zero-percent complete
                //fill this in when we anayze the prior flown missions
                msnSum.percentComplete = 0;

                projSum.msnSum.Add(msnSum);

            }  //end of collectiong the mission data

            return projSum;

            //////////////////////////////////////////////////////////////
            // the Project Summary for Waldo_FCS is Complete
            //////////////////////////////////////////////////////////////
        }
Пример #3
0
        public linearFeatureCoverageSummary readLinearFeatureCoverageData(XmlReader tr, String ProjectName)
        {
            ///////////////////////////////////////////////////////////////////////
            //read in the input kml describing the line feature coverage
            ///////////////////////////////////////////////////////////////////////

            //input kml linear feature -- dont need this
            //project map bounds
            //path information (trigger spacing, origin, UTM zone)
            //table of information -- need some of this
            //takeoff airport -- dont need this
            //along-path map bounds -- need this
            //path specific data -- dont need this
            //smoothed trajectory -- need this
            //center projection -- dont need
            //image endpoints  -- dont need

            bool completedreadingProjectMapBounds       = false;
            bool completedReadingPathInformation        = false;
            bool completedReadingSmoothedPathPoints     = false;

            linearFeatureCoverageSummary LFSummary = new linearFeatureCoverageSummary();
            LFSummary.gridOrigin = new PointD();

            //get the project map bounds
            //how do I exit this loop ???
            //TODO:  test to see if the kml file projectName is the same as the kml fileName
            while (tr.Read() && !completedreadingProjectMapBounds)
            {
                if (tr.EOF) break;
                if (tr.IsStartElement() && tr.Name == "GroundOverlay")
                {
                    while (tr.Read() && !completedreadingProjectMapBounds)
                    {
                        if (tr.IsStartElement() && tr.Name == "name")
                        {
                            tr.Read();
                            //we are looking for the name "project Map" where we will get the map bounds
                            if (tr.Value == "Project Map")
                            {
                                int numBounds = 0;
                                while (tr.Read() && !completedreadingProjectMapBounds)
                                {
                                    if (tr.IsStartElement() && tr.Name == "north")
                                    {
                                        tr.Read();
                                        LFSummary.ProjectImage.northDeg = Convert.ToDouble(tr.Value);

                                        numBounds++;
                                    }
                                    if (tr.IsStartElement() && tr.Name == "south")
                                    {
                                        tr.Read();
                                        LFSummary.ProjectImage.southDeg = Convert.ToDouble(tr.Value);
                                        numBounds++;
                                    }
                                    if (tr.IsStartElement() && tr.Name == "east")
                                    {
                                        tr.Read();
                                        LFSummary.ProjectImage.eastDeg = Convert.ToDouble(tr.Value);
                                        numBounds++;
                                    }
                                    if (tr.IsStartElement() && tr.Name == "west")
                                    {
                                        tr.Read();
                                        LFSummary.ProjectImage.westDeg = Convert.ToDouble(tr.Value);
                                        numBounds++;
                                    }
                                    if (numBounds == 4) completedreadingProjectMapBounds = true;
                                }
                            }
                        }
                    }
                }
            }// end of:   get the project map bounds
            if (tr.EOF)
            {
                MessageBox.Show("Bad map bounds format for the input kml file -- exiting");
                Environment.Exit(-1);
            }

            int numPathInfo = 0;
            while (tr.Read() && !completedReadingPathInformation)
            {
                if (tr.EOF) break;
                if (tr.IsStartElement() && tr.Name == "downRangePhotoSpacingMeters")
                {
                    tr.Read();
                    LFSummary.photocenterSpacing = Convert.ToDouble(tr.Value);
                    numPathInfo++;
                }

                if (tr.IsStartElement() && tr.Name == "numberOfPaths")
                {
                    tr.Read();
                    LFSummary.numberParallelPaths = Convert.ToInt32(tr.Value);
                    numPathInfo++;
                }

                if (tr.IsStartElement() && tr.Name == "UTMZone")
                {
                    tr.Read();
                    LFSummary.UTMZone = tr.Value;
                    numPathInfo++;
                }

                if (tr.IsStartElement() && tr.Name == "gridOriginUTMNorthing")
                {
                    tr.Read();
                    LFSummary.gridOrigin.Y = Convert.ToDouble(tr.Value);
                    numPathInfo++;
                }

                if (tr.IsStartElement() && tr.Name == "gridOriginUTMEasting")
                {
                    tr.Read();
                    LFSummary.gridOrigin.X = Convert.ToDouble(tr.Value);
                    numPathInfo++;
                }

                if (tr.IsStartElement() && tr.Name == "proNavGain")
                {
                    tr.Read();
                    LFSummary.proNavGain = Convert.ToDouble(tr.Value);
                    numPathInfo++;
                }
                if (tr.IsStartElement() && tr.Name == "rabbitAheadDistance")
                {
                    tr.Read();
                    LFSummary.plannedRabbitDistanceAhead = Convert.ToDouble(tr.Value);
                    numPathInfo++;
                }
                if (tr.IsStartElement() && tr.Name == "flightAltAGLft")
                {
                    tr.Read();
                    LFSummary.flightAltAGLft = Convert.ToDouble(tr.Value);
                    numPathInfo++;
                }

                if (numPathInfo == 8)completedReadingPathInformation = true;

            }  // end of:   get the path info
            if (tr.EOF)
            {
                MessageBox.Show("Bad path info format for the input kml file -- exiting");
                Environment.Exit(-1);
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //read in the bounds of the mission images ProjectName_Background\background_YY.jpg
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            LFSummary.paths = new List<pathDescription>();

            int numPathsProcessedForBounds = 0;
            while (tr.Read() && numPathsProcessedForBounds < LFSummary.numberParallelPaths)
            {
                if (tr.EOF) break;
                //read til we get the top of the next set of image bounds for a path
                if (tr.IsStartElement() && tr.Name == "numBGImagesThisPath")
                {
                    tr.Read();
                    int numImagesThisPath = Convert.ToInt32(tr.Value);
                    int pathImageBoundsRead = 0;
                    pathDescription path = new pathDescription();
                    path.imageBounds = new List<ImageBounds>();

                    //read off a complete set of bounds for a path
                    while (tr.Read() && pathImageBoundsRead < numImagesThisPath)  //loop over all image bounds in the folder
                    {
                        //read a complete set of image bounds
                        ImageBounds ib = new ImageBounds(); // fill an image bounds structure
                        int numBounds = 0;
                        while (tr.Read() && numBounds < 4)
                        {
                            if (tr.IsStartElement() && tr.Name == "north")
                            {
                                tr.Read();
                                ib.northDeg = Convert.ToDouble(tr.Value);
                                numBounds++;
                            }

                            if (tr.IsStartElement() && tr.Name == "east")
                            {
                                tr.Read();
                                ib.eastDeg = Convert.ToDouble(tr.Value);
                                numBounds++;
                            }

                            if (tr.IsStartElement() && tr.Name == "south")
                            {
                                tr.Read();
                                ib.southDeg = Convert.ToDouble(tr.Value);
                                numBounds++;
                            }

                            if (tr.IsStartElement() && tr.Name == "west")
                            {
                                tr.Read();
                                ib.westDeg = Convert.ToDouble(tr.Value);
                                numBounds++;
                            }
                        }
                        path.imageBounds.Add(ib);

                        pathImageBoundsRead++;
                    }
                    LFSummary.paths.Add(path);
                    numPathsProcessedForBounds++;
               }
            }  //end of reading in the map bounds along the paths

            if (tr.EOF)
            {
                MessageBox.Show("Bad path info format for the input kml file -- exiting");
                Environment.Exit(-1);
            }

            //read in the smoothed trajectory for each path
            UTM2Geodetic utm = new UTM2Geodetic();

            //we are ready to read off the coordinates of the smoothed trajectory
            int numPathsProcessed = 0;
            while (tr.Read() && !completedReadingSmoothedPathPoints)
            {
                if (tr.EOF) break;
                if (tr.IsStartElement() && tr.Name == "name")
                {
                    tr.Read();
                    //we will encounter this statement "numberParallelPaths"  times
                    if (tr.Value == "Smoothed Linear Feature Trajectory")
                    {

                        pathDescription path = LFSummary.paths[numPathsProcessed];
                        path.pathGeoDeg = new List<PointD>();
                        path.pathUTM = new List<PointD>();
                        path.commandedAltAlongPath = new List<double>();
                        bool thisPathComplete = false;
                        while (tr.Read() && !thisPathComplete)
                        {
                            //locate the coordinate tag for this path
                            if (tr.IsStartElement() && tr.Name == "coordinates")
                            {
                                tr.Read(); //read the complete coordinate dataset
                                char[] delimiterChars = { ',', ' ', '\t', '\n', '\r' };   //these delimiters were determined by looking at a file ...
                                //create a character string with all characters separated by a delimeter
                                string[] coordinateValues = tr.Value.ToString().Split(delimiterChars);

                                //the "value" is the text between the <coordinates> and </coordinates>
                                //below we read the complete string value and split it into separate substrings -- ugly but it works
                                //the substrings contain the individual coordinate values with some ""s and the heigts are "0".

                                //get the quantitative lat/long values from the text array ... there are a number of ""s in the text file ...
                                //each Google point has three values : longitude, Latitude, height -- we assume the height is zero here
                                int k = 0; int i = 0;
                                while (i < coordinateValues.Count())
                                {
                                    if (coordinateValues[i] != "")
                                    {
                                        double lat = Convert.ToDouble(coordinateValues[i + 1]);
                                        double lon = Convert.ToDouble(coordinateValues[i]);
                                        double alt = Convert.ToDouble(coordinateValues[i + 2]);

                                        path.pathGeoDeg.Add(new PointD(lon, lat) );
                                        path.commandedAltAlongPath.Add(alt);

                                        //convert the geodetic to UTM
                                        double UTMNorthing = 0.0, UTMEasting = 0.0;
                                        utm.LLtoUTM(lat * utm.Deg2Rad, lon * utm.Deg2Rad, ref UTMNorthing, ref UTMEasting, ref LFSummary.UTMZone, true);
                                        path.pathUTM.Add(new PointD(UTMEasting, UTMNorthing));

                                        k++;  //index of the storage array

                                        //increment the split array by 3 because the points are lat,lon,height
                                        i += 3;  //increment by 3 to get the next coordinate
                                    }
                                    else i++;  //here we skip the ""s in the text array
                                }
                                thisPathComplete = true;
                                numPathsProcessed++;
                            }

                        }  //end of while numPathsProcessed < LFSummary.numberParallelPaths

                        if (numPathsProcessed == LFSummary.numberParallelPaths)
                                   completedReadingSmoothedPathPoints = true;
                    }
                }
            }
            if (tr.EOF)
            {
                MessageBox.Show("Bad smoothed trajectory format for the input kml file -- exiting");
                Environment.Exit(-1);
            }

            return LFSummary;

            //////////////////////////////////////////////////////////////
            // the Project Summary for Waldo_FCS is Complete
            //////////////////////////////////////////////////////////////
        }
Пример #4
0
 private Point GeoToPix(PointD LonLat, ImageBounds _ib, double _lat2PixMultiplier, double _lon2PixMultiplier)
 {
     ///////////////////////////////////////////////////////////////////////////////////
     //maps are known to represent a rectangle of latitude and longitude
     //displayed bmp images are 640*lat2PixMultiplier X  480*lat2PixMultiplier
     //This procedure computes pixel coordinates from geodetic coordinates
     //bmp image pixels are sclaed to geodetic coordinates using the elements of ib
     ///////////////////////////////////////////////////////////////////////////////////
     Point pt = new Point();
     pt.Y = Convert.ToInt32((LonLat.Y - _ib.northDeg) * _lat2PixMultiplier);  //this rounds
     pt.X = Convert.ToInt32((LonLat.X - _ib.westDeg)  * _lon2PixMultiplier);  //this rounds
     return pt;
 }
Пример #5
0
        private void generateNewMergedMap(int pathNumber, int currentAlongPathMap, ImageBounds displayImageBounds)
        {
            //Form a new mergedMap from currentAlongPathMap+1 and currentAlongPathMap+2
            //get new mergedMap bounds
            ImageBounds ib0 = LFSum.paths[pathNumber].imageBounds[currentAlongPathMap];
            ImageBounds ib1 = LFSum.paths[pathNumber].imageBounds[currentAlongPathMap + 1];

            //find the merged geodetic bounds from the map descriptions from the mission plan
            ib0 = LFSum.paths[pathNumber].imageBounds[currentAlongPathMap];
            ib1 = LFSum.paths[pathNumber].imageBounds[currentAlongPathMap + 1];

            //assume merged map boounds are from "currentAlongPathMap + 1" and update as required
            mergedMapBounds = ib1;
            if (ib0.northDeg > ib1.northDeg) mergedMapBounds.northDeg = ib0.northDeg;
            if (ib0.southDeg < ib1.southDeg) mergedMapBounds.southDeg = ib0.southDeg;
            if (ib0.eastDeg > ib1.eastDeg) mergedMapBounds.eastDeg = ib0.eastDeg;
            if (ib0.westDeg < ib1.westDeg) mergedMapBounds.westDeg = ib0.westDeg;

            //map names as stored during the mission plan
            alongPathImageName1 = FlightPlanFolder + LFSum.ProjectName + "_Background\\linearMap_" + pathNumber.ToString("D2")
                + "_" + currentAlongPathMap.ToString("D3") + ".png";
            alongPathImageName2 = FlightPlanFolder + LFSum.ProjectName + "_Background\\linearMap_" + pathNumber.ToString("D2")
                + "_" + (currentAlongPathMap + 1).ToString("D3") + ".png";

            //set the map scaling parameters for the mergedMap
            lon2PixMultiplier = mergedMapMultiplier * mapWidth / (mergedMapBounds.eastDeg - mergedMapBounds.westDeg);
            lat2PixMultiplier = -mergedMapMultiplier * mapHeight / (mergedMapBounds.northDeg - mergedMapBounds.southDeg);

            //below statement allows use of class member ib within the geoToPix and PixToGeo  .. klutzy: need to fix this ...
            ib = mergedMapBounds;

            //alongPath map bounds pixel coordinates within the mergedMap
            //used to fill the merged map with the two along-path components
            Point alongPathMapNW_0 = GeoToPix(new PointD(ib0.westDeg, ib0.northDeg));
            Point alongPathMapNW_1 = GeoToPix(new PointD(ib1.westDeg, ib1.northDeg));
            Point alongPathMapSE_0 = GeoToPix(new PointD(ib0.eastDeg, ib0.southDeg));
            Point alongPathMapSE_1 = GeoToPix(new PointD(ib1.eastDeg, ib1.southDeg));

            //get graphics object that allows us to draw onto the mergedMap bitmap: mergedMap
            //from setupLinearMission:   mergedMap = new Bitmap(mergedMapMultiplier * mapWidth, mergedMapMultiplier * mapHeight);
            Graphics g1 = Graphics.FromImage(mergedMap);

            //set pixel-space rectangle within mergedMap wherein we draw the alongPath map 0
            Rectangle rect0 = new Rectangle(alongPathMapNW_0.X, alongPathMapNW_0.Y,
                alongPathMapSE_0.X - alongPathMapNW_0.X,
                alongPathMapSE_0.Y - alongPathMapNW_0.Y);

            //set pixel-space rectangle within mergedMap wherein we draw the alongPath map 1
            Rectangle rect1 = new Rectangle(alongPathMapNW_1.X, alongPathMapNW_1.Y,
                alongPathMapSE_1.X - alongPathMapNW_1.X,
                alongPathMapSE_1.Y - alongPathMapNW_1.Y);

            //draw the alongPath maps onto the merged map bitmap object
            g1.DrawImage(Image.FromFile(alongPathImageName1), rect0);
            g1.DrawImage(Image.FromFile(alongPathImageName2), rect1);

            //mergedMap.Save(@"C://temp//testImage1.png");

            //draw the paths onto the mergedMap that now contains the map components
            for (int j = 0; j < LFSum.paths.Count; j++)
            {
                for (int i = 1; i < LFSum.paths[j].pathGeoDeg.Count; i++)
                {
                    Point p1 = GeoToPix(LFSum.paths[j].pathGeoDeg[i - 1]);
                    Point p2 = GeoToPix(LFSum.paths[j].pathGeoDeg[i]);
                    g1.DrawLine(new Pen(Color.Black, 1), p1, p2);
                }
            }

            //show the semi-infinite line
            g1.DrawLine(new Pen(Color.Blue, 1), GeoToPix(FPGeometry.semiInfiniteFLstartGeo), GeoToPix(LFSum.paths[pathNumber].pathGeoDeg[0] ));

            //recreate the trigger point locations on this new mergedMap
            triggerPointsOnMergedMap.Clear();
            //Console.WriteLine(" points before  in triggerPointsOnMergedMap = " + triggerPointsOnMergedMap.Count.ToString());
            foreach (PointD p in LFSum.paths[pathNumber].triggerPoints)  //trigger points stored as geodetic
            {
                //Console.WriteLine("     " + p.X.ToString() + "   " + p.Y.ToString());
                triggerPointsOnMergedMap.Add(GeoToPix(p));
            }
            //Console.WriteLine(" points after in triggerPointsOnMergedMap = " + triggerPointsOnMergedMap.Count.ToString());

            g1.Dispose();
        }
Пример #6
0
        private ImageBounds generateDisplayMapBounds(int pathNumber)
        {
            //define a 4mi x 3mi UTM rectangle about the current aircraft position
            //that is:  +/-2 mi (EW) and +/-1.5mi (NS) about the aircraft location
            //this defines the geospatial rectangle of the map will be displayed on the Mission Form

            //bounds for the 4X3 mi rectangle in UTM
            PointD NWdisplayBoundUTM = new PointD(platFormPosVel.UTMPos.X - 2 * 5280.0 * 0.3048, platFormPosVel.UTMPos.Y + 1.5 * 5280.0 * 0.3048);
            PointD SEdisplayBoundUTM = new PointD(platFormPosVel.UTMPos.X + 2 * 5280.0 * 0.3048, platFormPosVel.UTMPos.Y - 1.5 * 5280.0 * 0.3048);

            //convert the 4X3 rectangle bounds to geodetic
            PointD NWdisplayBoundGeo = new PointD();
            utm.UTMtoLL(NWdisplayBoundUTM, LFSum.UTMZone, ref NWdisplayBoundGeo);
            PointD SEdisplayBoundGeo = new PointD();
            utm.UTMtoLL(SEdisplayBoundUTM, LFSum.UTMZone, ref SEdisplayBoundGeo);

            ImageBounds displayImageBounds = new ImageBounds();
            displayImageBounds.northDeg = NWdisplayBoundGeo.Y;
            displayImageBounds.southDeg = SEdisplayBoundGeo.Y;
            displayImageBounds.eastDeg = SEdisplayBoundGeo.X;
            displayImageBounds.westDeg = NWdisplayBoundGeo.X;

            return displayImageBounds;
        }
Пример #7
0
        //constructor for the linearFeature coverage form
        public Mission(String _FlightPlanFolder, String _MissionDataFolder, String MissionDateStringNameIn, int _missionNumber, 
            linearFeatureCoverageSummary _LFSum, LogFile _logFile,
            NavInterfaceMBed navIF_In, SDKHandler cameraIn, bool simulatedMission_, bool hardwareAttached_, Image _projectImage)
        {
            InitializeComponent();

            coverageType = COVERAGE_TYPE.linearFeature;

            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

            posVel_ = new PosVel();

            //set the mission image
            this.Width = (int)(mapScaleFactor * mapWidth);
            this.Height = (int)(mapScaleFactor * mapHeight);
            //this.Width = 640;    //pixel height of the form
            //this.Height = 480;   //pixel width of the form

            //retrieve local variables from the arguments
            missionNumber = _missionNumber;
            LFSum = _LFSum;
            MissionDataFolder = _MissionDataFolder;
            FlightPlanFolder = _FlightPlanFolder;

            navIF_ = navIF_In;
            camera = cameraIn;
            logFile = _logFile;
            MissionDateStringName = MissionDateStringNameIn;

            projectImage = _projectImage;

            //NOTE: if the simulatedMission=true, we will always generate the platform state from the software
            // If hardwareAttached=true, we will collect the IMU and GPS
            simulatedMission = simulatedMission_;
            hardwareAttached = hardwareAttached_;

            //st up the form to allow keydown events only in the simulation
            if (simulatedMission)
            {
                this.KeyPreview = true;
            }

            timeFromTrigger     = new Stopwatch();
            //showMessage       = new Stopwatch();
            elapsedTime         = new Stopwatch();
            getPosVelTimer      = new Stopwatch();

            //placeholder for the first of the path image bounds
            ib = LFSum.paths[0].imageBounds[0];  //placeholder for the project image bounds

            //multiplier used for pix-to-geodetic conversion for the project map -- scales lat/lon to pixels
            //NOTE -- we do the drawing on top of a bitmap sized to the mapWidth, mapHeight -- then stretch to fit the actual screen
            lon2PixMultiplier =  mapWidth /  (ib.eastDeg - ib.westDeg);
            lat2PixMultiplier = -mapHeight / (ib.northDeg - ib.southDeg);  //"-" cause vertical map direction is positive towards the south
            //lon2PixMultiplier =  mapWidth / (ib.eastDeg - ib.westDeg);
            //lat2PixMultiplier = -mapHeight / (ib.northDeg - ib.southDeg);  //"-" cause vertical map direction is positive towards the south

            platFormPosVel = new PosVel();
            platFormPosVel.GeodeticPos = new PointD(0.0, 0.0);
            platFormPosVel.UTMPos = new PointD(0.0, 0.0);

            //this will hold the locations of the aircraft over a period of time
            crumbTrail = new Point[numberCrumbTrailPoints];

            labelPilotMessage.Visible = false;

            //form the along-Path distance at each point (vertex)
            //will be used for interpolating the commanded altitude along the path
            for (int j = 0; j < LFSum.paths.Count; j++ )
            {
                LFSum.paths[j].alongPathDistanceAtVertex = new List<double>();
                double cumulativeDistance = 0;
                for (int i=0; i<LFSum.paths[j].pathUTM.Count; i++)
                    if (i == 0) LFSum.paths[j].alongPathDistanceAtVertex.Add(0.0);
                else
                {
                    double delX = LFSum.paths[j].pathUTM[i].X - LFSum.paths[j].pathUTM[i - 1].X;
                    double delY = LFSum.paths[j].pathUTM[i].Y - LFSum.paths[j].pathUTM[i - 1].Y;
                    cumulativeDistance += Math.Sqrt(delX * delX + delY * delY);
                    LFSum.paths[j].alongPathDistanceAtVertex.Add(cumulativeDistance);
                }
            }
        }
Пример #8
0
        private void setupLinearFeatureMission(int pathNumber)
        {
            //////////////////////////////////////
            //called from btn_OK_clicked
            //initializes the simuation
            //////////////////////////////////////

            //simulation trajectory start point in pixel coordinates
            Point startPlatformPoint = new Point(FlightLineStartPix.X, FlightLineStartPix.Y);

            this.lblFlightAlt.Visible = false;
            this.lblFlightLines.Visible = false;
            this.lblMissionNumber.Visible = false;

            btnOK.Visible = true;  //dont need this anymore --- reset to visible if we return to a selected mission

            btnBack.Text = "EXIT"; // this is a better name because we exit the realtime mission and return to the mission selection Form
            //note we can exit a mission in the middle of a line and renter the mission at the exited point.

            //get all flightline geometry that is invariant for traveling along this path
            FPGeometry = new FlightPathLineGeometry(pathNumber, LFSum);

            utm = new UTM2Geodetic();

            //initialize the position when in sim mode
            if (simulatedMission)
            {
                ////////////////////////////////////////////////////////////////////////////////
                //set the position along the semi-infinite line at the start of the first path
                ////////////////////////////////////////////////////////////////////////////////

                PointD startUTM = new PointD();
                //simulation is initiated 5000m from the start and headed towards the start
                startUTM.X = LFSum.paths[pathNumber].pathUTM[0].X + 2000.0 * FPGeometry.unitAwayFromStartUTM.X + 100.0 * FPGeometry.unitAwayFromStartUTM.Y;
                startUTM.Y = LFSum.paths[pathNumber].pathUTM[0].Y + 2000.0 * FPGeometry.unitAwayFromStartUTM.Y - 100.0 * FPGeometry.unitAwayFromStartUTM.X;

                PointD startGeo = new PointD();
                utm.UTMtoLL(startUTM, LFSum.UTMZone, ref startGeo);

                platFormPosVel.UTMPos.X = startUTM.X;
                platFormPosVel.UTMPos.Y = startUTM.Y;
                platFormPosVel.GeodeticPos.X = startGeo.X;
                platFormPosVel.GeodeticPos.Y = startGeo.Y;
                //set the altitude at the initial commanded altitude (input in ft)
                platFormPosVel.altitude = LFSum.paths[0].commandedAltAlongPath[0] * 0.3048;

                //////////////////////////////////////////////////////////
                speed = 51.4;   // 100 knots
                //////////////////////////////////////////////////////////

                platFormPosVel.velD = 0.0;
                //negative sigh cause velocity towards the start of the path
                platFormPosVel.velE = -speed * FPGeometry.unitAwayFromStartUTM.X;
                platFormPosVel.velN = -speed * FPGeometry.unitAwayFromStartUTM.Y;

            }

            FPGeometry.getPlatformToFLGeometry(platFormPosVel);

            //pre-load the crumbtrail array prior to the start point
            //for (int i = 0; i < numberCrumbTrailPoints; i++) crumbTrail[i] = startPlatformPoint;

            //merged maps combine two along-path maps so the moving map shows all the subtended terrain
            //set up the first mergedMap
            mergedMapBounds = new ImageBounds(); //initialize this using first 2 images

            currentAlongPathMap = 0;
            triggerCountAlongpath = 0;

            mergedMap = new Bitmap(mergedMapMultiplier * mapWidth, mergedMapMultiplier * mapHeight);

            //triggerPointsOnMergedMap saves the camera trigger points along the merged map
            //used to present the crumb trail
            LFSum.paths[pathNumber].triggerPoints = new List<PointD>();
            //tempTriggerPoints = new List<PointD>();
            triggerPointsOnMergedMap = new List<Point>();

            ImageBounds displayImageBounds = generateDisplayMapBounds(pathNumber);
            //generate the first merged map for this path
            generateNewMergedMap(pathNumber, currentAlongPathMap, displayImageBounds);

            //this is hardwired in btn_OK
            deltaT = 0.25;

            //no crumbtrail used for the linear path
            numberCrumbTrailPoints = 5;

            bm3 = new Bitmap(mapWidth, mapHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            prepLinearFeatureBitmapForPaint();
        }
Пример #9
0
        private void prepLinearFeatureBitmapForPaint()
        {
            /////////////////////////////////////////////////////////////////////////////////////
            //called from realTimeAction
            //for the linearFeature --- most of the realtime linearFeature action occurs here
            //realTime action is called in a real-time loop that is in btnOK_click
            /////////////////////////////////////////////////////////////////////////////////////

            //the aircraft position is available from other processes ongoing in the realTimeAction loop
            //all trigger responses from camera (image placed on camera HD) are also handled in realTimeAction
            //but trigger request is handled here.

            //general strategy for mergedMap prep to treat the moving map display
            //A set of fixed-size alongpath maps are available from the mission planning
            //use a rectangle about the aircraft position to determine if we need a new mergedMap
            //a mergedMap is formed from two rectangular alongPathMaps that are centered along the path at regular intervals
            //for each aircraft position, determine a 4mi x 3mi geodetic rectangular around the aircraft wherein we will display a map
            //test to see if this rectangle is fully contained in the next (currentpath+1) alongPathMap
            //if yes, then generate a new mergedMap from currentMap and currentMap + 1

            //define a 4mi x 3mi UTM rectangle about the current aircraft position
            //that is:  +/-2 mi (EW) and +/-1.5mi (NS) about the aircraft location
            //this defines the geospatial rectangle of the map that will be displayed on the Mission Form
            ImageBounds displayImageBounds = generateDisplayMapBounds(pathNumber);
            //we will map this 4X3 mi rectangle about the aircraft location into the display map.

            //////////////////////////////////////////////////////////////////////////////////////
            //must treat the case where the aircraft moves off the alongPathMap sequence!!!
            //test if this displayMap bounds is within the current alongPathMap.
            //if yes, do nothing. if no, is it in the next alongPathMap
            //if yes, then create a new merged map from the current map and the next map
            //if no, then see if the displayMap is in ANY alongPathMap (to handle case where we reenter the alongpathap sequence)
            //if yes, then set the currentMap to this alongPathMap
            //if no, then set the mergedMap to the a static (non-moving) projectMap
            ///////////////////////////////////////////////////////////////////////////////////////

            bool aircraftWithinAlongPathMaps = true;

            //test if this aircraft-centric 4X3 mi rectangle is inside the next alongPathMap
            //if yes, then create a new mergedMap using the next alongPathMap
            int lastAlongPathMap = LFSum.paths[pathNumber].imageBounds.Count;
            //if (currentAlongPathMap < LFSum.paths[pathNumber].imageBounds.Count - 2)
            {
                if (polygonMath.imageBoundAContainedInImageBoundB(displayImageBounds, LFSum.paths[pathNumber].imageBounds[currentAlongPathMap]) ||
                    polygonMath.imageBoundAContainedInImageBoundB(displayImageBounds, LFSum.paths[pathNumber].imageBounds[lastAlongPathMap-1]))
                {
                    //do nothing -- the currentAlongPath is correct
                    if (!mergedMapAvailable)
                    {
                        generateNewMergedMap(pathNumber, currentAlongPathMap, displayImageBounds);
                        mergedMapAvailable = true;
                        Console.WriteLine("creating a new mergedMap when none available for current alongPathMap  " + currentAlongPathMap.ToString());
                    }
                }
                else if ( currentAlongPathMap < (LFSum.paths[pathNumber].imageBounds.Count - 2) &&   //test for running out of alongPathMaps
                    polygonMath.imageBoundAContainedInImageBoundB(displayImageBounds, LFSum.paths[pathNumber].imageBounds[currentAlongPathMap + 1]))
                {
                    currentAlongPathMap++;

                    //generate a new mergedMap from which we will cut the portion to display on the moving map
                    generateNewMergedMap(pathNumber, currentAlongPathMap, displayImageBounds);
                    mergedMapAvailable = true;
                    Console.WriteLine("create a new MergedMap at " + missionTimerTicks.ToString() + "  currentAlongPathMap= " + currentAlongPathMap.ToString());
                }
                else
                {
                    //test to see if we are in any alongPathMap
                    bool notInAnyAlongPathMap = true;
                    for (int i = 0; i < LFSum.paths[pathNumber].imageBounds.Count; i++)
                    {
                        if (polygonMath.imageBoundAContainedInImageBoundB(displayImageBounds, LFSum.paths[pathNumber].imageBounds[i]))
                        {
                            currentAlongPathMap = i;

                            //current map in last alongPathMap --- back it up so we can form mergedMap with currentAlongPathMap+1
                            if (currentAlongPathMap == LFSum.paths[pathNumber].imageBounds.Count - 1) currentAlongPathMap--;

                            //generate a new mergedMap from which we will cut the portion to display on the moving map
                            generateNewMergedMap(pathNumber, currentAlongPathMap, displayImageBounds);
                            mergedMapAvailable = true;
                            notInAnyAlongPathMap = false;
                            Console.WriteLine("Located a new alongPathMap from searching all maps");
                            break;
                        }
                    }

                    if (notInAnyAlongPathMap)  // set the projectMap as a static (non-moving) map
                    {

                        aircraftWithinAlongPathMaps = false;
                        mergedMapAvailable = false;

                        //re set the map scaling parameters for the overview projectMap
                        lon2PixMultiplier =  mapWidth /  (LFSum.ProjectImage.eastDeg  - LFSum.ProjectImage.westDeg);
                        lat2PixMultiplier = -mapHeight / (LFSum.ProjectImage.northDeg - LFSum.ProjectImage.southDeg);
                        ib = LFSum.ProjectImage;
                        //lon2PixMultiplier, lat2PixMultiplier, ib -- are used internal to GeoToPix to set the map scaling

                        //get graphics object that allows us to draw onto the static projectMap
                        //from setupLinearMission:   mergedMap = new Bitmap(mergedMapMultiplier * mapWidth, mergedMapMultiplier * mapHeight);
                        Graphics g2 = Graphics.FromImage(bm3);
                        g2.DrawImage(projectImage, 0, 0);  //fixed invariant (non-moving map)

                        //draw the paths onto the projectMap
                        for (int j = 0; j < LFSum.paths.Count; j++)
                        {
                            for (int i = 1; i < LFSum.paths[j].pathGeoDeg.Count; i++)
                            {
                                Point p1 = GeoToPix(LFSum.paths[j].pathGeoDeg[i - 1]);
                                Point p2 = GeoToPix(LFSum.paths[j].pathGeoDeg[i]);
                                g2.DrawLine(new Pen(Color.Black, 1), p1, p2);
                            }
                        }

                        //show the semi-infinite line on the project map
                        g2.DrawLine(new Pen(Color.Blue, 1), GeoToPix(FPGeometry.semiInfiniteFLstartGeo), GeoToPix(LFSum.paths[pathNumber].pathGeoDeg[0]));

                        //recreate the trigger point locations on this project
                        triggerPointsOnMergedMap.Clear();
                        //Console.WriteLine(" points before  in triggerPointsOnMergedMap = " + triggerPointsOnMergedMap.Count.ToString());
                        foreach (PointD p in LFSum.paths[pathNumber].triggerPoints)  //trigger points stored as geodetic
                        {
                            //Console.WriteLine("     " + p.X.ToString() + "   " + p.Y.ToString());
                            triggerPointsOnMergedMap.Add(GeoToPix(p));
                        }

                        //show a circle on the projectMap to locate the aircraft
                        Point acp = GeoToPix(platFormPosVel.GeodeticPos);
                        g2.DrawEllipse(new Pen(Color.Black,2), acp.X, acp.Y, 3, 3) ;

                        g2.Dispose();
                    }

                    //if in no alongPathMap -- set the merged map to the projectMap
                }
            }//end of the test of

            if (aircraftWithinAlongPathMaps)
            {
                Graphics g1 = Graphics.FromImage(mergedMap);

                //show the past image trigger circles as they are taken
                foreach (Point p in triggerPointsOnMergedMap)
                {
                    //draw a circle with diam 6 pixels at each of the trigger points for this mergedMap
                    g1.DrawEllipse(new Pen(Color.Red, 1), p.X - 3, p.Y - 3, 6, 6);
                }

                //destination of the portion of the merged map to display on the Mission form (the complete form)
                Point[] destPoints = { new Point(0, 0), new Point(mapWidth, 0), new Point(0, mapHeight) };

                //form rectangle defining the portion of the merged map to display on the Mission Form
                //the merged map has a fixed size and scaling set in setupLinearFeatureMission()
                //GeoToPix scaliong is set up for the merged map
                Point NWdisplayBoundPix = GeoToPix(new PointD(displayImageBounds.westDeg, displayImageBounds.northDeg));  //scaled to the merged map
                Point SEdisplayBoundPix = GeoToPix(new PointD(displayImageBounds.eastDeg, displayImageBounds.southDeg));  //scaled to the merged map

                //rectangle in the mergedMap where we get the 4X3 mi map portion
                Rectangle displayRect = new Rectangle(NWdisplayBoundPix,
                    new Size(SEdisplayBoundPix.X - NWdisplayBoundPix.X, SEdisplayBoundPix.Y - NWdisplayBoundPix.Y));

                //graphics object for the Mission Form that will be displayed in the Paint event
                //bm3 is 640 X 480
                Graphics g3 = Graphics.FromImage(bm3);

                //place the 4mi X 3 mi portion of the merged map onto the Mission Form
                g3.DrawImage(mergedMap, destPoints, displayRect, GraphicsUnit.Pixel);

                //show the stick aircraft in the center of the Mission Form
                stickAircraftForMovingMap(g3);

                //Console.WriteLine(" miss distance (m) = " + (100.0 * FPGeometry.LOSRate * LFSum.plannedRabbitDistanceAhead / FPGeometry.velMag).ToString() );
                drawStickPlane(ref g3,
                    (int)(100.0 * FPGeometry.LOSRate * (LFSum.plannedRabbitDistanceAhead / FPGeometry.velMag)),
                    (int)(FPGeometry.headingToPath * Rad2Deg) );

                g3.Dispose();

                setupSteeringBarGFraphic(bm3);

                //heading-to-path is +pi to -pi
                //only allow photos if the heading-to-path is +/- 30 deg -- tolerance as in the polygon mission
                //TGO is computed only if we are with a tolerance distance from the flight line
                //if heading-to-path in tolerance and distanceAlongPath < 0 then TGO = -distanceAlongPath / velMag
                //if distance to next path start is < pathLength, TGO = distanceToNextPathStart / velMag
                //if (heading-to-path in tolerance and distanceAlongPath > 0

                //trigger management while within the path endpoints
                if (FPGeometry.distanceFromStartAlongPath > triggerCountAlongpath * LFSum.photocenterSpacing &&
                    FPGeometry.distanceFromStartAlongPath < FPGeometry.pathlengthMeters )
                {
                    //send a request to the mbed to fire the trigger
                    //the image is snapped about 0.23 seconds after this request
                    triggerCountAlongpath++;

                    //LFSum.paths[pathNumber].triggerPoints.Add(platFormPosVel.GeodeticPos);
                    LFSum.paths[pathNumber].triggerPoints.Add(new PointD(platFormPosVel.GeodeticPos.X, platFormPosVel.GeodeticPos.Y));

                    //add this trigger point to the mergedMap display
                    triggerPointsOnMergedMap.Add(GeoToPix(platFormPosVel.GeodeticPos));

                    //offset = 0 -- no longer used
                    //missionNumber = -1 for the path coverage tso missionNumber no in photocenter label
                    kmlTriggerWriter.writePhotoCenterRec(-1, pathNumber, 0, triggerCountAlongpath, platFormPosVel);

                    Console.WriteLine("snap a picture " + missionTimerTicks.ToString() + "   " + triggerCountAlongpath.ToString());

                    TGO = (FPGeometry.pathlengthMeters - FPGeometry.distanceFromStartAlongPath) / FPGeometry.velMag;

                    //write the kml file for the trigger
                }

                if (FPGeometry.distanceFromStartAlongPath < 0)
                {
                    TGO = -FPGeometry.distanceFromStartAlongPath / FPGeometry.velMag;
                }
                if (inTurnAroundForLinearFeature) TGO = missionTimerTicks / 1000.0 - TimeFromExitingLastPath;

                //detect the end of this path and transition to the next path
                double pathSwitchExtension = 0.0;  ///extends the switch just for the simulation
                if (simulatedMission) pathSwitchExtension = 2000.0;
                if (FPGeometry.distanceFromStartAlongPath > (FPGeometry.pathlengthMeters + pathSwitchExtension) && !inTurnAroundForLinearFeature)
                {
                    //fire one last trigger at the exct of the flight line
                    triggerCountAlongpath++;

                    //set the exit tie for the TGO computation
                    TimeFromExitingLastPath = 0;

                    //increment the path counter
                    pathNumber++;

                    //detect the last path
                    if (pathNumber >= LFSum.paths.Count)
                    {
                        pathNumber = LFSum.paths.Count - 1;
                        lastPathHasBeenFlown = true;
                    }

                    currentAlongPathMap = 0;
                    mergedMapAvailable = false;
                    triggerCountAlongpath = 0;

                    Console.WriteLine(" switched path :  " + pathNumber.ToString());

                    if (simulatedMission)  //end of the line turn management
                    {
                        //turn the aircraft around ...
                        inTurnAroundForLinearFeature = true;        //logic flag declaring in the turn
                        nextPathInitialHeading = FPGeometry.heading + Math.PI;    //store the desired heading along the nextPath
                        double maxBank = 45.0;                      //max bank in the turn -- enables a fast turn
                        double turnRadiusAtMaxBank = speed * speed / (9.806 * Math.Tan(maxBank * Deg2Rad)); // turn radius at the max bank
                        gammaDotInTurn = speed / turnRadiusAtMaxBank;  //turn rotation rate at the max bank for coordinated turn

                        //compute the turn direction to the startpoint of next path
                        //compute vector from the startPoint of next Path to the current platform
                        //UTM.X = Easting and UTM.Y = Northing  -- vector direction towards the platform
                        PointD vec = new PointD(
                            LFSum.paths[pathNumber].pathUTM[0].X - platFormPosVel.UTMPos.X,
                            LFSum.paths[pathNumber].pathUTM[0].Y - platFormPosVel.UTMPos.Y);

                        //form cross-product of velocity and above vector. X is to the north & Y to the east for below cross product
                        turnDirection = platFormPosVel.velN * vec.X - platFormPosVel.velE * vec.Y;

                        //if crossProduct is positive (Z-axis pointed down) -- turn to the right (CW)
                        gammaDotInTurn = Math.Sign(turnDirection) * gammaDotInTurn;
                    }

                    //note:  the path is reversed in the mission plan
                    //even paths (0, 2, 4, 6) are start-to-end relative to the plan input path
                    FPGeometry = new FlightPathLineGeometry(pathNumber, LFSum);
                    FPGeometry.getPlatformToFLGeometry(platFormPosVel);

                    //clear and reset the trigger file so it can be refilled this path
                    LFSum.paths[pathNumber].triggerPoints = new List<PointD>();
                }

            }  //end of test for within alongPathMaps

            if (!inTurnAroundForLinearFeature)
                        FPGeometry.getPlatformToFLGeometry(platFormPosVel);

            //if sim -- update the sim -- done regardless of the map status
            if (simulatedMission)
            {
                //this is a classic proportional navigation guidance law -- LOS rate is computed in FLGeometry
                //the ProNav gain below is 3.0 .....
                double gammaDot = 0.0;
                if (inTurnAroundForLinearFeature)
                {

                    heading = Math.Atan2(platFormPosVel.velE, platFormPosVel.velN);
                    gammaDot = gammaDotInTurn;
                    //find sine and cosine of the angle between the current heading and desired heading
                    double sin = Math.Cos(heading) * Math.Sin(nextPathInitialHeading) - Math.Sin(heading) * Math.Cos(nextPathInitialHeading);
                    double cos = Math.Cos(heading) * Math.Cos(nextPathInitialHeading) + Math.Sin(heading) * Math.Sin(nextPathInitialHeading);
                    //transition out of the turn when we have turned so that we have crossed the desired heading
                    if (cos > 0 && Math.Sign(turnDirection)*sin < 0) inTurnAroundForLinearFeature = false;
                }
                else
                    gammaDot = 3.0 * FPGeometry.LOSRate;

                //user inputs a "X" to toggle the autosteering ....
                //use can use the right and left arrow keys to steer the plane in heading
                if (useAutoSteering && !lastPathHasBeenFlown)
                        FPGeometry.heading += gammaDot * deltaT;

                platFormPosVel.velE = speed * Math.Sin(FPGeometry.heading);
                platFormPosVel.velN = speed * Math.Cos(FPGeometry.heading);
                platFormPosVel.velD = speed * Math.Sin(simulationPitch);

                platFormPosVel.UTMPos.X += platFormPosVel.velE * deltaT;
                platFormPosVel.UTMPos.Y += platFormPosVel.velN * deltaT;
                platFormPosVel.altitude -= platFormPosVel.velD * deltaT;

                //platform position is delivered back the Display preparation in Geodetic
                //because thats what the GICS will give us
                utm.UTMtoLL(platFormPosVel.UTMPos.Y, platFormPosVel.UTMPos.X, LFSum.UTMZone, ref platFormPosVel.GeodeticPos.Y, ref platFormPosVel.GeodeticPos.X);
            }
            else  // the position and velocity state are provided by the GPS data
            {
                platFormPosVel.GeodeticPos.X = posVel_.GeodeticPos.X;
                platFormPosVel.GeodeticPos.Y = posVel_.GeodeticPos.Y;
                platFormPosVel.altitude = posVel_.altitude;
                platFormPosVel.velN = posVel_.velN;
                platFormPosVel.velE = posVel_.velE;
                platFormPosVel.velD = posVel_.velD;
                speed = Math.Sqrt(platFormPosVel.velN * platFormPosVel.velN + platFormPosVel.velE * platFormPosVel.velE);
            }
        }
Пример #10
0
        private void preparePolygonMissionDisplayfixedBackground()
        {
            /////////////////////////////////////////////////////////////////////////////////////////////////
            //prepare that part of the mission display that does not change when you are within a mission
            //this includes the basic underlay map and the mission flight lines
            //we also change the underlay map here if we exit the zoomed mission map
            /////////////////////////////////////////////////////////////////////////////////////////////////

            String MissionMap;
            if (UseZImapForPolygonMission)
            {
                //load the Mission Map from the flight maps folder -- prepared with the mission planner
                MissionMap = FlightPlanFolder + ps.ProjectName + @"_Background\Background_" + missionNumber.ToString("D2") + ".png";

                //ib is used internally to the GeoToPix procedures
                ib = ps.msnSum[missionNumber].MissionImage;  //placeholder for the Mission image bounds
            }
            else
            {
                MissionMap = FlightPlanFolder + ps.ProjectName + @"_Background\ProjectMap.png";
                ib = ps.ProjectImage;
            }
            //multiplier used for pix-to-geodetic conversion for the project map -- scales lat/lon to pixels
            //NOTE -- we do the drawing on top of a bitmap sized to the mapWidth, mapHeight -- then stretch to fit the actual screen
            lon2PixMultiplier =  mapWidth / (ib.eastDeg - ib.westDeg);
            lat2PixMultiplier = -mapHeight / (ib.northDeg - ib.southDeg);  //"-" cause vertical map direction is positive towards the south

            //the mission maps may be in either PNG or JPG -- based on the implementation of the mission planner
            if (File.Exists(MissionMap))
                img = Image.FromFile(MissionMap); //get an image object from the stored file
            else
            {
                MessageBox.Show(" there is no mission map present:  \n" + MissionMap, "ERROR", MessageBoxButtons.OKCancel);
                Application.Exit();
            }

            //declare a bitmap using the Mission map img width and height for the size specifications
            //  img.Width, img.Height  are 640 X 480 based on the Google map download limits
            bm1 = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            //the graphics object lets us place graphics into the currently-blank bm1 bitmap
            Graphics g = Graphics.FromImage(bm1);  //create a graphics object from the base map image

            //initialize the bm1 base bitmap with the mission map
            //other drawings will be added to the base image to reflect changes from the base image
            g.DrawImage(img, 0, 0);     //img is the mission background image defined above

            //draw all the flightlines onto bm1 --- dont need to do this but once for each time the mission is changed
            //draw the flight lines ONCE on the bm1 background image and generate a new background image
            for (int i=0; i<ps.msnSum[missionNumber].FlightLinesCurrentPlan.Count; i++)
            {
                endPoints ep = ps.msnSum[missionNumber].FlightLinesCurrentPlan[i];
                //draw the flight lines
                if (priorFlownFLs[i])
                    g.DrawLine(new Pen(Color.Green, 2), GeoToPix(ep.start), GeoToPix(ep.end));
                else
                    g.DrawLine(new Pen(Color.Red, 2), GeoToPix(ep.start), GeoToPix(ep.end));
            }

            //show the zoomed-in map boundary if we are on the zoomed-out map
            if (!UseZImapForPolygonMission)
            {
                //we are in the zoomed out map --- show the ZI map rectangle on the ZO map
                PointD NWGeo = new PointD(ps.msnSum[missionNumber].MissionImage.westDeg, ps.msnSum[missionNumber].MissionImage.northDeg);
                PointD SEGeo = new PointD(ps.msnSum[missionNumber].MissionImage.eastDeg, ps.msnSum[missionNumber].MissionImage.southDeg);
                Point NWPix = GeoToPix(NWGeo);
                Point SEPix = GeoToPix(SEGeo);
                g.DrawRectangle(new Pen(Color.Gray, 1), NWPix.X, NWPix.Y, SEPix.X - NWPix.X, SEPix.Y - NWPix.Y);
            }

            //get the flight line spacing if there is more than one flightline
            //this assumes a constant flight line spacing and that the flight lines are parallel
            //TODO: the flight line spacing should be in the mission plan -- assume parallel flight lines in UTM
            if (ps.msnSum[missionNumber].numberOfFlightlines > 1)
            {
                //start and end of the first flight line in lat/lon
                double latS1 = ps.msnSum[missionNumber].FlightLinesCurrentPlan[0].start.Y;
                double lonS1 = ps.msnSum[missionNumber].FlightLinesCurrentPlan[0].start.X;
                double latE1 = ps.msnSum[missionNumber].FlightLinesCurrentPlan[0].end.Y;
                double lonE1 = ps.msnSum[missionNumber].FlightLinesCurrentPlan[0].end.X;
                //start point of the second flight line
                double lat2 = ps.msnSum[missionNumber].FlightLinesCurrentPlan[1].start.Y;
                double lon2 = ps.msnSum[missionNumber].FlightLinesCurrentPlan[1].start.X;
                //convert  lat/lon points to UTM so we can use vector arithmetic
                PointD lineStart = new PointD(0, 0), lineEnd = new PointD(0, 0), point2Test = new PointD(0, 0);
                utm.LLtoUTM(latS1 * Deg2Rad, lonS1 * Deg2Rad, ref lineStart.Y, ref lineStart.X, ref ps.UTMZone, true);
                utm.LLtoUTM(latE1 * Deg2Rad, lonE1 * Deg2Rad, ref lineEnd.Y, ref lineEnd.X, ref ps.UTMZone, true);
                utm.LLtoUTM(lat2 * Deg2Rad, lon2 * Deg2Rad, ref point2Test.Y, ref point2Test.X, ref ps.UTMZone, true);
                //
                //double L = Math.Sqrt(  (UTMX2 - UTMX1) * (UTMX2 - UTMX1) + (UTMY2 - UTMY1) * (UTMY2 - UTMY1) );
                //flightLineSpacing = L * Math.Cos(  Math.Atan2( (UTMY2 - UTMY1) , (UTMX2 - UTMX1) ) );

                PointD del = lineStart - point2Test;
                //angleRad is measured from North positive clockwise
                FLangleRad = Math.Atan2((lineEnd.X - lineStart.X), (lineEnd.Y - lineStart.Y));
                //confusing: the below math assumes X is to the north and Y is to the east
                double D = del.Y * Math.Cos(FLangleRad) + del.X * Math.Sin(FLangleRad);
                double Vx = del.Y - D * Math.Cos(FLangleRad);
                double Vy = del.X - D * Math.Sin(FLangleRad);

                flightLineSpacing = Math.Sqrt(Vx * Vx + Vy * Vy);

                //the flight line spacing is also read in from the input kml file ...
                //double dd1 = ps.crossRangeSwathWidth - flightLineSpacing;
            }

            //NOTE: all bitmaps sized to the mapWidth & mapHeight -- stretched to fit screen in Paint
            //bm2 will contain the base map plus the semiinfinite extended blue current flightline
            bm2 = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            //bm3 will add to bm2 the crumb trail, current aircraft location, and photocenters
            //these different bitmaps are created to reduce the overhead of preparing the refreshed bitmap
            //note that preparing bm3 has the least overhead -- adding minimally to bm2
            // img.Width, img.Height are 640 X 480 based on google map download limits
            bm3 = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            //initially set the bm2 and bm3 images to the base map bm1
            Graphics g2 = Graphics.FromImage(bm2);
            g2.DrawImage(bm1, 0, 0);
            Graphics g3 = Graphics.FromImage(bm3);
            g3.DrawImage(bm1, 0, 0);
            //bm3 is what is drawn at the Paint event at the refresh

            g2.Dispose();
            g3.Dispose();

            setupSteeringBarGFraphic(bm1);

            //computes total images from the flight plan
            totalImagesThisMission = getTotalImagesThisMission();
        }
Пример #11
0
 private PointD PixToGeo(Point pt, ImageBounds _ib, double _lat2PixMultiplier, double _lon2PixMultiplier)
 {
     ///////////////////////////////////////////////////////////////////////////////////
     //maps are known to represent a rectangle of latitude and longitude
     //displayed bmp images are 640*lat2PixMultiplier X  480*lat2PixMultiplier
     //This procedure computes geodetic coordinates from pixel coordinates
     //bmp image pixels are scaled to geodetic coordinates using the elements of ib
     ///////////////////////////////////////////////////////////////////////////////////
     PointD Gpt = new PointD(0.0, 0.0); ;
     Gpt.X = _ib.westDeg  + (double)pt.X / (double)_lon2PixMultiplier;
     Gpt.Y = _ib.northDeg + (double)pt.Y / (double)_lat2PixMultiplier;
     return Gpt;
 }
Пример #12
0
        //constructor for MissionSelection Form for polygon mission
        public MissionSelection(ProjectSummary _ps, String _FlightPlanFolder, LogFile _logFile,
            NavInterfaceMBed navIF_In, SDKHandler cameraIn, bool hardwareAttached_, SettingsManager _settings, String _MissionDateString)
        {
            InitializeComponent();

            posVel_ = new PosVel();

            //set the flight plans folder and the Project Summary structure from the prior Project Selection
            FlightPlanFolder = _FlightPlanFolder;
            ps = _ps;
            navIF_ = navIF_In;
            camera = cameraIn;
            hardwareAttached = hardwareAttached_;
            settings = _settings;
            MissionDateString = _MissionDateString;
            logFile = _logFile;

            projectName = ps.ProjectName;

            //there is a separate constructor for the linearFeature coverage type
            coverageType = COVERAGE_TYPE.polygon;

            //getPosVelTimer = new Stopwatch();
            utm = new UTM2Geodetic();

            /////////////////////////////////////////////////////////////////////////////////////
            //set up the project polygon and the individual Mission polygons in pixel units
            /////////////////////////////////////////////////////////////////////////////////////

            //set of points in Pixels that we use to draw the project polygon onto the project map
            //creats space for an array of Point structures tha will hold the project polygon
            projectPolyPointsPix = new Point[ps.ProjectPolygon.Count];

            //lat/lon image bounds from the mission plan
            ib = ps.ProjectImage;  //placeholder for the project image bounds NOTE:  this is also used elsewhere

            //multiplier used for pix-to-geodetic conversion for the project map -- scales lat/lon to pixels
            // TODO:  ugly --- cant we do this exactly???
            //lon2PixMultiplier = mapScaleFactor * mapWidth / (ib.eastDeg - ib.westDeg);
            //lat2PixMultiplier = -mapScaleFactor * mapHeight / (ib.northDeg - ib.southDeg);  //"-" cause vertical map direction is positive towards the south
            lon2PixMultiplier =  mapWidth  / (ib.eastDeg - ib.westDeg);
            lat2PixMultiplier = -mapHeight / (ib.northDeg - ib.southDeg);  //"-" cause vertical map direction is positive towards the south

            //create the project polygon in pixel units -- once
            for (int i = 0; i < ps.ProjectPolygon.Count; i++)
                projectPolyPointsPix[i] = GeoToPix(ps.ProjectPolygon[i]);  //just uses a linear scaling

            //create the mission polygons (one per mission) in pixel units
            //used to form the clickable region on the project map
            missionPolysInPix = new List<Point[]>();
            for (int i = 0; i < ps.msnSum.Count; i++)
            {
                Point [] pts = new Point[ps.msnSum[i].missionGeodeticPolygon.Count];
                for (int j = 0; j < ps.msnSum[i].missionGeodeticPolygon.Count; j++)
                    pts[j] = GeoToPix(ps.msnSum[i].missionGeodeticPolygon[j]);
                missionPolysInPix.Add(pts);
            }
        }
Пример #13
0
        //constructor for MissionSelection Form Linear Feature mission
        public MissionSelection(linearFeatureCoverageSummary _LFSum, String _FlightPlanFolder, LogFile _logFile,
            NavInterfaceMBed navIF_In, SDKHandler cameraIn, bool hardwareAttached_, SettingsManager _settings, String _MissionDateString)
        {
            InitializeComponent();

            posVel_ = new PosVel();

            //set the flight plans folder and the Project Summary structure from the prior Project Selection
            FlightPlanFolder = _FlightPlanFolder;
            LFSum = _LFSum;
            navIF_ = navIF_In;
            camera = cameraIn;
            hardwareAttached = hardwareAttached_;
            settings = _settings;
            MissionDateString = _MissionDateString;
            logFile = _logFile;

            projectName = LFSum.ProjectName;

            //this is a specific constructor for the linear feature coverage type
            coverageType = COVERAGE_TYPE.linearFeature;

            getPosVelTimer = new Stopwatch();
            utm = new UTM2Geodetic();

            //lat/lon image bounds from the mission plan
            ib = LFSum.ProjectImage;  //placeholder for the project image bounds NOTE:  this is also used elsewhere

            //multiplier used for pix-to-geodetic conversion for the project map -- scales lat/lon to pixels
            // TODO:  ugly --- cant we do this exactly???
            //lon2PixMultiplier = mapScaleFactor * mapWidth / (ib.eastDeg - ib.westDeg);
            //lat2PixMultiplier = -mapScaleFactor * mapHeight / (ib.northDeg - ib.southDeg);  //"-" cause vertical map direction is positive towards the south
            lon2PixMultiplier =  mapWidth / (ib.eastDeg   - ib.westDeg);
            lat2PixMultiplier = -mapHeight / (ib.northDeg - ib.southDeg);  //"-" cause vertical map direction is positive towards the south
        }