//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); } }
public PriorFlownMissions(String FlightPlanFolder, ProjectSummary _projSum) { projUpdate = new ProjectUpdateFlightLines(); //this is the struct containing all missions that will be prepared herein projUpdate.msnUpdate = new List<MissionUpdateFlightlines>(); //flight line structure for an individual mission projSum = _projSum; //input mission planning file extracted from the project plan kml debugFile = new StreamWriter(@"C:\temp\priorMissisons.txt"); debugFile.WriteLine("Analyzing the pre-flown missions "); int missionCounter = 0; //loop through all the missions for this project foreach (MissionSummary msnSum in projSum.msnSum) { //mission folder definition String MissionDataFolder = FlightPlanFolder + projSum.ProjectName + @"\Mission_" + missionCounter.ToString("D3") + @"\Data\"; debugFile.WriteLine("testing for missionFolder: " + MissionDataFolder); //is there are no prior missions flown, continue to the next mission if (!Directory.Exists(MissionDataFolder)) { missionCounter++; continue; } debugFile.WriteLine(" folder found"); //NOTE: we only add to the structure if there is a prior-flown folder // if there are no prior flown missions, there will be nothing inthe structure; //temporary mission structure filled below and added to projUpdate MissionUpdateFlightlines missionUpdate = new MissionUpdateFlightlines(); missionUpdate.missionNumber = missionCounter; //flight line List to be filled and added to the structure missionUpdate.flightLineUpdate = new List<FirstLastUnflownPhotocenter>(); //get the String Collection of as-flown kml file names in each of the mission data folders //we sould make these trigger file -- need to separate the simulated mssions and the live missions String[] kmlFlightFiles = Directory.GetFiles(MissionDataFolder, "*Triggers.kml"); debugFile.WriteLine("Found" + kmlFlightFiles.ToString() + " .kml files"); //this will become a collection of all the photocenters names for all prior flown missions with this mission number List<String> collectedImages = new List<String>(); //loop through each of the pre-flown kml files that recorded photocenters //st is the name of a preflown flight line foreach (String st in kmlFlightFiles) { debugFile.WriteLine("getting prior flown photocenters from: " + st); ///////////////////////////////////////////////////////////////////////////////////// ///Read the kml file and get the photocenter names ........... ///////////////////////////////////////////////////////////////////////////////////// XmlTextReader tr = new XmlTextReader(st); int imagesTaken = 0; while (!tr.EOF && tr.Read()) //loop through all the kml elements { if (tr.Name == "Placemark" && tr.IsStartElement()) //locate each placemark -- these contain the photocenters { while (!tr.EOF && tr.Read()) { if (tr.IsStartElement() && tr.Name == "name") //photocenter name stores the MissionNumber_FlightLine_photocenterNumber { if (!tr.EOF) { tr.Read(); collectedImages.Add(tr.Value); //for the collection of all photocenters imagesTaken++; } } } } } if (imagesTaken == 0) { //MessageBox.Show("poorly formed kml file -- deleting " + st); debugFile.WriteLine("deleted Bad kml Triggers file --- delete."); tr.Close(); File.Delete(st); } } debugFile.WriteLine("found " + collectedImages.Count.ToString() + " total photocenters for all kml files"); //sort the collection in ascending order "Mission#_FL#_pohto#" //photocenter names increase from Start-to-End (e.g., start at South for NS lines) collectedImages.Sort(); debugFile.WriteLine(); foreach (String s in collectedImages) debugFile.WriteLine(s); debugFile.WriteLine(); debugFile.WriteLine("Completed Sort of the image strings"); //compute the total photocenters to be collected for this mission -- used to compute the percent complete int totalPhotoCentersRequiredThisMission = 0; foreach (endPoints ep in projSum.msnSum[missionCounter].FlightLinesCurrentPlan) totalPhotoCentersRequiredThisMission += Convert.ToInt32(ep.FLLengthMeters / projSum.downrangeTriggerSpacing) + 1; debugFile.WriteLine("Total photocenters required to complete this mission: " + totalPhotoCentersRequiredThisMission.ToString()); //we will compute this below to get the overall percent completion based on all prior-flown missions int photoCentersCollectedThisMission = 0; //do this for flight line zero and then do again when we get a new flight line int currentFlightLine = 0; int numPhotoCenters = 1 + Convert.ToInt32(projSum.msnSum[missionCounter].FlightLinesCurrentPlan[currentFlightLine].FLLengthMeters / projSum.downrangeTriggerSpacing); int[] photoCentersCollected = new int[10*numPhotoCenters]; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// //now we have a sorted list of all images collected for this mission and for all flightlines //go through the list selecting each flight line in order to assess the earliest and latest uncollected images ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// int totalPhotoCentersCollected = 0; // this includes repeated photos --- may collect some PCs multiple times // this value photoCentersCollectedThisMission --- counts the uniquely collected photocenters foreach (String st in collectedImages) { int missionNumber=0; int flightlineNumber=0; int photoCenter=0; //these values are placed into a string that is the image name in the kml file try { missionNumber = Convert.ToInt32(st.Substring(0, 3)); //this will always be a constant } catch { MessageBox.Show(" bad missionNumber in kml file: " + st.Substring(0, 3)); } try { flightlineNumber = Convert.ToInt32(st.Substring(4, 2)); } catch { MessageBox.Show(" bad flightlineNumber in kml file: " + st.Substring(4, 2)); } try { photoCenter = Convert.ToInt32(st.Substring(7, 3)); } catch { MessageBox.Show(" bad photoCenter in kml file: " + st.Substring(7, 3)); } //the "currentFlightLine" starts at zero and increments when we observe a new flight line number //NOTE: we must exit this at the very last record in the collection so that FL record will be processed try { if (currentFlightLine == flightlineNumber) { totalPhotoCentersCollected++; photoCentersCollected[photoCenter] += 1; if (st != collectedImages.Last()) continue; } } catch { MessageBox.Show(" bad photoCenter value: " + photoCenter); } //here we have detected a new flight that was previously flown -- so process the last one int early = 999; //if no photos collected for this flight line, earliest is zero int late = 0; //if no photos collected for this flight line, latest is at the end if (totalPhotoCentersCollected > 0) { //when we get here we have completed the assessment of currentFlightLine //now get the earliest uncollected image and the latest uncollected image. for (int pc = 0; pc < numPhotoCenters; pc++) { if (photoCentersCollected[pc] == 0) { if (pc < early) early = pc; if (pc > late) late = pc; } } //break when we find an uncollected image // if early (earliest uncollected image) is = numPhotoCenters-1, we have a complete flight line } //for (int j = 0; j < numPhotoCenters; j++) //{ // debugFile.WriteLine(currentFlightLine.ToString("D2") + " " + j.ToString("D2") + " " + photoCentersCollected[j].ToString("D2")); //} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //refly partial flight line strategy //we may have deviated fro the line in the middle and got back on. //we would need to refly ony the center portion //note this could have happened twice on a long line //for example, we got image 0-10, missed 11-15, got 16-30, missed 31-35, and gotthe remainder 36-55 //we would refly photocenters: 11-35 for this case. Starting with the earliest miss and ending with the latest miss /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// FirstLastUnflownPhotocenter elPC; if (early == 999) early = 0; //early == 999 means ALL expected images were collected -- completed flight line elPC.early = early; //earliest of the unflown images elPC.late = late; //latest of the unflown images debugFile.WriteLine("expected photos " + numPhotoCenters.ToString("D3") + " Earliest uncollected " + early.ToString("D3") + " Latest uncollected " + late.ToString("D3")); if (early == (numPhotoCenters - 1)) photoCentersCollectedThisMission += numPhotoCenters; else photoCentersCollectedThisMission += numPhotoCenters - (late - early); //the updated flightline must cover images from "early to "late" elPC.FLNumber = currentFlightLine; //fill the early/late structure for this flightline missionUpdate.numberOfFlightLines = projSum.msnSum[missionNumber].numberOfFlightlines; missionUpdate.flightLineUpdate.Add(elPC); currentFlightLine++; if (currentFlightLine >= projSum.msnSum[missionCounter].numberOfFlightlines) break; numPhotoCenters = Convert.ToInt32(projSum.msnSum[missionCounter].FlightLinesCurrentPlan[currentFlightLine].FLLengthMeters / projSum.downrangeTriggerSpacing) + 1; photoCentersCollected = new int[10*numPhotoCenters]; //why do this? we found a new flight line and need to accept the first of its images totalPhotoCentersCollected++; photoCentersCollected[photoCenter] += 1; } //completed the flight line asFlown analysis for this Mission //fill the mission update structure projUpdate.numberOfMissions = projSum.numberOfMissions; missionUpdate.percentCompleted = 100.0 * (double)photoCentersCollectedThisMission / (double)totalPhotoCentersRequiredThisMission; projUpdate.msnUpdate.Add(missionUpdate); debugFile.WriteLine("completed the prior flown analysis for mission " + missionCounter); missionCounter++; } // end of the per mission loop debugFile.WriteLine("completed the prior flown analysis for all missions "); debugFile.Close(); }
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 ////////////////////////////////////////////////////////////// }
//constructor for the polygon coverage form public Mission(String _FlightPlanFolder, String _MissionDataFolder, String MissionDateStringNameIn, int _missionNumber, ProjectSummary _ps, bool[] _priorFlownFLs, LogFile _logFile, NavInterfaceMBed navIF_In, SDKHandler cameraIn, bool _simulatedMission, bool _hardwareAttached, StreamWriter _reflyFile, Image _projectImage) { InitializeComponent(); coverageType = COVERAGE_TYPE.polygon; //we use a separate constructor for the linearFeature mission this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; //set the mission image -- mapWidth & mapHeight = 640 X 480 based on the Google Earth map download limits this.Width = (int)(mapScaleFactor * mapWidth); //mapscaleFactor scales the map to fit a screen size of 1024 X 768 this.Height = (int)(mapScaleFactor * mapHeight); //this.Width = 640; //pixel height of the form //this.Height = 480; //pixel width of the form posVel_ = new PosVel(); //retrieve local variables from the arguments missionNumber = _missionNumber; ps = _ps; MissionDataFolder = _MissionDataFolder; FlightPlanFolder = _FlightPlanFolder; priorFlownFLs = _priorFlownFLs; //this contains the completed flight lines so they arent reflown reflyFile = _reflyFile; //write the completed flight line indices to this file projectImage = _projectImage; //contains the complete project image in case the display runs off the smaller maps navIF_ = navIF_In; camera = cameraIn; logFile = _logFile; MissionDateStringName = MissionDateStringNameIn; //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; timeFromTrigger = new Stopwatch(); elapsedTime = new Stopwatch(); getPosVelTimer = new Stopwatch(); timePastEndfFlightline = new Stopwatch(); ////ib is used internally to the GeoToPix procedures ////we will need to reset the ib & PixMultipliers if we have to use the Project map (plane exits mission map) //ib = ps.msnSum[missionNumber].MissionImage; //placeholder for the Mission 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 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]; //shows the "waiting sats" message labelPilotMessage.Visible = false; //get the max flight line length for this mission -- should come from the missionPlan //used to establish a region before and after the flightlines where flightlinecapture is allowed for (int i = 0; i < ps.msnSum[missionNumber].FlightLinesCurrentPlan.Count; i++) { if (ps.msnSum[missionNumber].FlightLinesCurrentPlan[i].FLLengthMeters > maxFlightLineLength) maxFlightLineLength = ps.msnSum[missionNumber].FlightLinesCurrentPlan[i].FLLengthMeters; } }
public CurrentFlightLineGeometry( int missionNumber, int flightLineNumber, ProjectSummary _ps, bool[] _priorFlownFLs) { //////////////////////////////////////////////////////////////////// //do all the stuff that does not vary with the aircraft location //////////////////////////////////////////////////////////////////// ps = _ps; priorFlownFLs = _priorFlownFLs; UTM2Geodetic utm = new UTM2Geodetic(); Rad2Deg = 180.0 / Math.Acos(-1.0); Deg2Rad = Math.Acos(-1.0) / 180.0; FLendUTM = new PointD(0.0, 0.0); FLstartUTM = new PointD(0.0, 0.0); FLP1endUTM = new PointD(0.0, 0.0); FLP1startUTM = new PointD(0.0, 0.0); //set up the parameters of the flight line independent of the aircraft Platform FLendGeo = ps.msnSum[missionNumber].FlightLinesCurrentPlan[flightLineNumber].end; FLstartGeo = ps.msnSum[missionNumber].FlightLinesCurrentPlan[flightLineNumber].start; //utm flight line endpoints utm.LLtoUTM(FLstartGeo.Y * Deg2Rad, FLstartGeo.X * Deg2Rad, ref FLstartUTM.Y, ref FLstartUTM.X, ref ps.UTMZone, true); utm.LLtoUTM(FLendGeo.Y * Deg2Rad, FLendGeo.X * Deg2Rad, ref FLendUTM.Y, ref FLendUTM.X, ref ps.UTMZone, true); // the number 10 means that the semi-infinite line extensions are 10 times longer than the flightline .... PointD del = 10 * (FLendGeo - FLstartGeo); //semi-infinite line use for drawing a line extending beyond the FL ends semiInfiniteFLstartGeo = FLstartGeo - del; semiInfiniteFLendGeo = FLendGeo + del; FLlengthSq = (FLendUTM.X - FLstartUTM.X) * (FLendUTM.X - FLstartUTM.X) + (FLendUTM.Y - FLstartUTM.Y) * (FLendUTM.Y - FLstartUTM.Y); FLlengthMeters = Math.Sqrt(FLlengthSq); start2EndFlightLineUnit = new PointD((FLendUTM.X - FLstartUTM.X) / FLlengthMeters, (FLendUTM.Y - FLstartUTM.Y) / FLlengthMeters); //next flight line data -- what happens on the last flightlne ?? if (flightLineNumber < (ps.msnSum[missionNumber].numberOfFlightlines-1) ) { //this is redundant with code where the currentFlightLine is switched // nextFlightlineNumber should be kept as a part of flightline geometry nextFlightlineNumber = flightLineNumber + 1; while (priorFlownFLs[nextFlightlineNumber]) { if (nextFlightlineNumber >= priorFlownFLs.Count() - 1) break; nextFlightlineNumber++; } PointD FLP1endGeo = ps.msnSum[missionNumber].FlightLinesCurrentPlan[nextFlightlineNumber].end; PointD FLP1startGeo = ps.msnSum[missionNumber].FlightLinesCurrentPlan[nextFlightlineNumber].start; utm.LLtoUTM(FLP1startGeo.Y * Deg2Rad, FLP1startGeo.X * Deg2Rad, ref FLP1startUTM.Y, ref FLP1startUTM.X, ref ps.UTMZone, true); utm.LLtoUTM(FLP1endGeo.Y * Deg2Rad, FLP1endGeo.X * Deg2Rad, ref FLP1endUTM.Y, ref FLP1endUTM.X, ref ps.UTMZone, true); //works for all flightline aspects -- assumes the flightlines are parallel //project start-to-start (RS) and end-to-end (RE) vectors onto current flightline start-to-end unit vector double delSX = FLP1startUTM.X - FLstartUTM.X; double delSY = FLP1startUTM.Y - FLstartUTM.Y; double RS = start2EndFlightLineUnit.X * delSX + start2EndFlightLineUnit.Y * delSY; double delEX = FLP1endUTM.X - FLendUTM.X; double delEY = FLP1endUTM.Y - FLendUTM.Y; double RE = start2EndFlightLineUnit.X * delEX + start2EndFlightLineUnit.Y * delEY; if (RS < 0.0) ExtensionBeforeStart = -RS; if (RE > 0.0) ExtensionBeyondEnd = RE; //below works for only NS missions //if (FLP1endUTM.Y > FLendUTM.Y) ExtensionBeyondEnd = FLP1endUTM.Y - FLendUTM.Y; //if (FLP1startUTM.Y < FLstartUTM.Y) ExtensionBeforeStart = FLstartUTM.Y - FLP1startUTM.Y; } //the "+1" ensures a photocenter at the start of the flight line and at the end of the flight line. //The start/ends of the line have been placed on a grid with fixed downrange spacing for the complete project numPhotoCenters = Convert.ToInt32( FLlengthMeters / ps.downrangeTriggerSpacing) + 1; //used to record the successful completion of a photocenter //set to true after we have recorded the image on the storage media successfulImagesCollected = new bool[numPhotoCenters+10]; //store the photocenter locations in pixel coordinates TriggerPoints = new Point[numPhotoCenters + 10]; for (int i = 0; i < numPhotoCenters + 10; i++) { successfulImagesCollected[i] = false; TriggerPoints[i] = new Point(); } }