示例#1
0
        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);
        }
示例#2
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
        }
示例#3
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();
        }