public FlightPathLineGeometry( int _pathNumber, linearFeatureCoverageSummary _LFSum) { //////////////////////////////////////////////////////////////////////////////// //path: a set of smoothed trajectory points defined from the mission planned //compute those variables that are constant across the path //////////////////////////////////////////////////////////////////////////////// LFSum = _LFSum; pathNumber = _pathNumber; UTM2Geodetic utm = new UTM2Geodetic(); //set up the polygon (point list) math procedures polyMath = new polygonMath(LFSum.paths[pathNumber].pathUTM); //get the semi-infinite line extending beyond the path at the start and end int count = LFSum.paths[pathNumber].pathGeoDeg.Count; unitAwayFromEndUTM = new PointD(); unitAwayFromStartUTM = new PointD(); //semi-infinite line use for drawing a line extending beyond the path end unitAwayFromEndUTM = LFSum.paths[pathNumber].pathUTM[count - 1] - LFSum.paths[pathNumber].pathUTM[count - 2]; unitAwayFromStartUTM = LFSum.paths[pathNumber].pathUTM[0] - LFSum.paths[pathNumber].pathUTM[1]; double delSMag = Math.Sqrt(unitAwayFromStartUTM.X * unitAwayFromStartUTM.X + unitAwayFromStartUTM.Y * unitAwayFromStartUTM.Y); unitAwayFromStartUTM = unitAwayFromStartUTM / delSMag; double delEMag = Math.Sqrt(unitAwayFromEndUTM.X * unitAwayFromEndUTM.X + unitAwayFromEndUTM.Y * unitAwayFromEndUTM.Y); unitAwayFromEndUTM = unitAwayFromEndUTM / delEMag; //semi-infinite line ate start and end in UTM coordinates PointD semiInfiniteFLstartUTM = LFSum.paths[pathNumber].pathUTM[0] + 10000.0 * unitAwayFromStartUTM; PointD semiInfiniteFLendUTM = LFSum.paths[pathNumber].pathUTM[count - 1] + 10000.0 * unitAwayFromEndUTM; //convert to geodetic semiInfiniteFLstartGeo = new PointD(); semiInfiniteFLendGeo = new PointD(); utm.UTMtoLL(semiInfiniteFLstartUTM, LFSum.UTMZone, ref semiInfiniteFLstartGeo); utm.UTMtoLL(semiInfiniteFLendUTM, LFSum.UTMZone, ref semiInfiniteFLendGeo); //compute the path length pathlengthMeters = 0.0; for (int i = 1; i < LFSum.paths[pathNumber].pathUTM.Count; i++) { double delX = LFSum.paths[pathNumber].pathUTM[i].X - LFSum.paths[pathNumber].pathUTM[i - 1].X; double delY = LFSum.paths[pathNumber].pathUTM[i].Y - LFSum.paths[pathNumber].pathUTM[i - 1].Y; double magDel = Math.Sqrt(delX * delX + delY * delY); pathlengthMeters += magDel; } //number of expected photocenters numPhotoCenters = (int)(pathlengthMeters / LFSum.photocenterSpacing + 1.0); }
public List<endPoints> UpdateFlightLinesPerPriorFlownMissions(int missionNumber) { ///////////////////////////////////////////////////////////////////////////////////////////// //use the MissionUpdateFlightlines structure (fromn the constructor) to update the flight lines //the new flight lines replace the old flight lines //the initial prior flightline analysis provided a structure //that contained only data from the flown missions. //This procedure creates a replica of the mission plan flight lines, //for a specific mission, that are adjusted to remove the prior flown lines (and segments) ///////////////////////////////////////////////////////////////////////////////////////////// UTM2Geodetic utm = new UTM2Geodetic(); //needs to be in a utility procedure available to all in the solution //test to see if pre-flown mission dataset contain this mission int preFlownMissionIndex = 0; //mission index from the flightline analysis bool thisMissionWasPreflown = false; foreach (MissionUpdateFlightlines msnUpdate in projUpdate.msnUpdate) { if (missionNumber == msnUpdate.missionNumber) { thisMissionWasPreflown = true; break; } preFlownMissionIndex++; } //////////////////////////////////////////////////////////////////////////////////////////// //this is the updates flight line dataset that replicates the data in the original plan List<endPoints> FLUpdateList = new List<endPoints>(); //return value //////////////////////////////////////////////////////////////////////////////////////////// //if this mission was not reflown -- just copy the old data to the replica if (!thisMissionWasPreflown) { for (int iFL = 0; iFL < projSum.msnSum[missionNumber].numberOfFlightlines; iFL++) FLUpdateList.Add(projSum.msnSum[missionNumber].FlightLinesCurrentPlan[iFL]); return FLUpdateList; } //if here, the mission was reflown -- generate the replica. //NOTE: all flightlines were likely not preflown -- just a part of them. //this is an index into the preflown-analysis structure indicating the reflown line int nextFlownFL = 0; //cycle through ALL flight lines for this mission for (int iFL = 0; iFL < projSum.msnSum[missionNumber].numberOfFlightlines; iFL++) { bool thisFlightLineWasPreflown = false; //the "if" below skips the checks on the remaining lines if we are beyond the nuber of reflown lines if (nextFlownFL >= projUpdate.msnUpdate[preFlownMissionIndex].flightLineUpdate.Count) thisFlightLineWasPreflown = false; //this is the test to see if we have reflown this line = iFL else if (iFL == projUpdate.msnUpdate[preFlownMissionIndex].flightLineUpdate[nextFlownFL].FLNumber) thisFlightLineWasPreflown = true; if (!thisFlightLineWasPreflown) //if not reflown -- just copy the old data { FLUpdateList.Add(projSum.msnSum[missionNumber].FlightLinesCurrentPlan[iFL]); } else //create a new flightline dataset { // NOTE: we convert the initial geodetic ends to UTM for the now endpoint computations // this is to maintain precision //found a pre-flown flightline PointD FLendGeo = projSum.msnSum[missionNumber].FlightLinesCurrentPlan[iFL].end; PointD FLstartGeo = projSum.msnSum[missionNumber].FlightLinesCurrentPlan[iFL].start; PointD FLendUTM = new PointD(0.0, 0.0); PointD FLstartUTM = new PointD(0.0, 0.0); //convert the original planned flight line ends to UTM -- could pass these in from the original plan //NOTTE: maintain the same utm zone fro the mission planning -- else big trouble!!! utm.LLtoUTM(FLstartGeo.Y * utm.Deg2Rad, FLstartGeo.X * utm.Deg2Rad, ref FLstartUTM.Y, ref FLstartUTM.X, ref projSum.UTMZone, true); utm.LLtoUTM(FLendGeo.Y * utm.Deg2Rad, FLendGeo.X * utm.Deg2Rad, ref FLendUTM.Y, ref FLendUTM.X, ref projSum.UTMZone, true); //below are the start and end photocenters as determined from the prior-flown mission analysis //NOTE: the start is geodetically fixed -- e.g., at the south end for a NS flightline int startPhotoCenter = projUpdate.msnUpdate[preFlownMissionIndex].flightLineUpdate[nextFlownFL].early; int endPhotoCenter = projUpdate.msnUpdate[preFlownMissionIndex].flightLineUpdate[nextFlownFL].late; PointD newStartUTM = new PointD(0.0, 0.0); PointD newEndUTM = new PointD(0.0, 0.0); // just a comparison of the computed and input flightline lengths ... it checks: JEK 1/26/2012 double FLMag1 = projSum.msnSum[missionNumber].FlightLinesCurrentPlan[iFL].FLLengthMeters; //double FLMag2 = Math.Sqrt((FLendUTM.X - FLstartUTM.X) * (FLendUTM.X - FLstartUTM.X) + (FLendUTM.Y - FLstartUTM.Y) * (FLendUTM.Y - FLstartUTM.Y)); //proportionally space the new photocenters along the origional flightine -- in UTM space newStartUTM = FLstartUTM + (startPhotoCenter * projSum.downrangeTriggerSpacing / FLMag1) * (FLendUTM - FLstartUTM); newEndUTM = FLstartUTM + (endPhotoCenter * projSum.downrangeTriggerSpacing / FLMag1) * (FLendUTM - FLstartUTM); PointD newStartGeo = new PointD(0.0, 0.0); PointD newEndGeo = new PointD(0.0, 0.0); //now convert them back to geodetic utm.UTMtoLL(newStartUTM.Y, newStartUTM.X, projSum.UTMZone, ref newStartGeo.Y, ref newStartGeo.X); utm.UTMtoLL(newEndUTM.Y, newEndUTM.X, projSum.UTMZone, ref newEndGeo.Y, ref newEndGeo.X); endPoints epts = new endPoints(); //temporary structure //fill the temporary structure //this used the 2D geometry and will work for NS or EW flight lines epts.FLLengthMeters = (endPhotoCenter - startPhotoCenter) * projSum.downrangeTriggerSpacing; epts.end = newEndGeo; epts.start = newStartGeo; //this is the global project flight line number -- not a local number used for this mission epts.FlightLineNumber = projSum.msnSum[missionNumber].FlightLinesCurrentPlan[iFL].FlightLineNumber; //below is important to allow flight line updates that include partial flown lines. //all photocenters are given a unique name in the original flight plan //we must keep this original name for the photocenters //the names are based on the distance from the geodetic fixed otiginal start location // so we have to keep the offset for the updated flight lines from the original plan epts.photoCenterOffset = startPhotoCenter; //fill the replical flight line structure FLUpdateList.Add(epts); //increment the index into the preflown flightline analysis structure nextFlownFL++; } //end of filling the new flightline record } //end of filling the individual flight lines (iFL) return FLUpdateList; //filled replica of the original flightplan fllightlines for this mission }
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(); }