Пример #1
0
        public COVERAGE_TYPE polygonGeometry()
        {
            ///////////////////////////////////////////////////////////////////////
            // get the mean polygon location and the polygon area
            // convert all vertices to UTM
            // get the UTM zone that will be used
            // get recangular bounding box
            // determine the orientation of the point-scatter covariance ellipse
            ///////////////////////////////////////////////////////////////////////
            utm = new UTM2Geodetic();  //class for LL to UTM conversion

            for (int i = 0; i < polygons.Count; i++)
            {
                //local copy of the polygon -- re-inserted into the polygon list at the end of this procedure
                Polygon p = polygons[i];

                int numLatLonPoints = p.latitudeDeg.Count;

                //mean Northing and Easting from mean lat/lon -- also use this to get the UTMZone that will be held fixed for this polygon
                p.meanNorthing = 0.0;
                p.meanEasting = 0.0;

                //NOTE:  get the UTMZone here (for the polygon mean location) that will be used for the whole project
                utm.LLtoUTM(p.meanLatDeg * Deg2Rad, p.meanLonDeg * Deg2Rad, ref p.meanNorthing, ref p.meanEasting, ref p.UTMZone, false);
                //the UTM zone will be held constant across the polygon points -- deals with polys that cross UTM zones

                //get the Northing and Easting from the lat/lon poly points
                double northing = 0.0, easting = 0.0;
                p.maxNorthing = -9999999.0; p.maxEasting = -999999999.0; p.minNorthing = 999999999.0; p.minEasting = 99999999999.0;
                p.maxLatDeg = -99999.0; p.maxLonDeg = -9999999.0; p.minLatDeg = 99999.0; p.minLonDeg = 999999.0;
                double CovXX = 0.0, CovYY = 0.0, CovXY = 0.0;  //covariance of the UTM poly points
                for (int ipnts = 0; ipnts < numLatLonPoints; ipnts++)
                {
                    utm.LLtoUTM(p.latitudeDeg[ipnts] * Deg2Rad, p.longitudeDeg[ipnts] * Deg2Rad, ref northing, ref easting, ref p.UTMZone, true);
                    p.Northing.Add(northing); p.Easting.Add(easting);

                    if (northing > p.maxNorthing) p.maxNorthing = northing;
                    if (northing < p.minNorthing) p.minNorthing = northing;
                    if (easting > p.maxEasting) p.maxEasting = easting;
                    if (easting < p.minEasting) p.minEasting = easting;

                    if (p.latitudeDeg[ipnts]  > p.maxLatDeg) p.maxLatDeg = p.latitudeDeg[ipnts];
                    if (p.latitudeDeg[ipnts]  < p.minLatDeg) p.minLatDeg = p.latitudeDeg[ipnts];
                    if (p.longitudeDeg[ipnts] > p.maxLonDeg) p.maxLonDeg = p.longitudeDeg[ipnts];
                    if (p.longitudeDeg[ipnts] < p.minLonDeg) p.minLonDeg = p.longitudeDeg[ipnts];

                    //covariance elements used to compute the principal axes of the polygon
                    //here we are assuming a north (X), east (Y), down (Z) corrdinatate system
                    CovYY += (easting  - p.meanEasting)  * (easting - p.meanEasting);
                    CovXX += (northing - p.meanNorthing) * (northing - p.meanNorthing);
                    CovXY += (easting  - p.meanEasting)  * (northing - p.meanNorthing);
                }

                CovYY /= 1000*numLatLonPoints;
                CovXX /= 1000*numLatLonPoints;
                CovXY /= 1000*numLatLonPoints;

                //Compute the orientation of the principal axis of the covariance ellipse
                //this is used to determine the best flying direction

                //eigenvalues of covariance matrix -- see below site for equations for eigenvalues/vectors for 2D matrix
                //    people.csail.mit.edu/bkph/articles/Eigenvectors.pdf
                double det = Math.Sqrt( (CovXX - CovYY)*(CovXX - CovYY) + 4.0 * CovXY * CovXY );
                double lambda1 = ( CovXX + CovYY +  det )/ 2.0;
                double lambda2 = ( CovXX + CovYY -  det )/ 2.0;
                //the larger of these is the length of the major axis
                //smaller is length of the minor axis

                //the angle associated with the larger eigenvalue is the angle of the major axis
                //eigenvectors should be 90 deg apart
                if (lambda1 > lambda2)
                {
                    //eigenvectors of covariance matrix
                    double eigen1X = 2.0 * CovXY;
                    double eigen1Y = CovYY - CovXX + det;
                    double ang1 = Math.Atan(eigen1Y / eigen1X) * Constants.Rad2Deg;
                    p.rotationAngleDeg = ang1;
                }
                else
                {
                    //eigenvectors of covariance matrix
                    double eigen2X = 2.0 * CovXY;
                    double eigen2Y = CovYY - CovXX - det;
                    double ang2 = Math.Atan(eigen2Y / eigen2X) * Constants.Rad2Deg;
                    p.rotationAngleDeg = ang2;
                }
                //reflect a negative major axis direction by 180 deg (major axis can go either direction)
                if (p.rotationAngleDeg < 0) p.rotationAngleDeg += 180.0;

                //this must be done after creating the UTM Northing & Easting from the geodetic coordinates
                polygonMath polyMath = new polygonMath(p.Easting, p.Northing, datasetFolder);

                //compute rectangle bounds using the principal axes
                double maxAlongPA = -9999999999, minAlongPA = 9999999999, distanceA = 0.0;
                double maxOrthoPA = -9999999999, minOrthoPA = 9999999999, distanceO = 0.0;
                for (int ipnts = 0; ipnts < numLatLonPoints; ipnts++)
                {
                    //note below that the X components is Northing and the Y components are Easting
                    //The "line" is defined by its origin and rotation angle (positive east of north)
                    //the "point" is the ipnts vertex of the polygon
                    distanceO = polyMath.distanceFromPoint2Line(  //distance orthogonal to the pricipal axis
                        new PointD(p.meanNorthing, p.meanEasting),
                        p.rotationAngleDeg,
                        new PointD(p.Northing[ipnts], p.Easting[ipnts]));
                    distanceA = polyMath.distanceFromPoint2Line(  //distance orthogonal to the pricipal axis
                        new PointD(p.meanNorthing, p.meanEasting),
                        p.rotationAngleDeg + 90,
                        new PointD(p.Northing[ipnts], p.Easting[ipnts]));

                    if (distanceA > maxAlongPA) maxAlongPA = distanceA;
                    if (distanceA < minAlongPA) minAlongPA = distanceA;
                    if (distanceO > maxOrthoPA) maxOrthoPA = distanceO;
                    if (distanceO < minOrthoPA) minOrthoPA = distanceO;
                }

                //length and width of a bounding box with long-side along principal axis
                //length should always be larger than the width
                double lengthKm = (maxAlongPA - minAlongPA) / 1000.0;
                double widthKm = (maxOrthoPA - minOrthoPA)  / 1000.0;
                //Constants.Log("Principal Axis bounding box: " + lengthKm.ToString("F1") + " X " + widthKm.ToString("F1"));
                //if (lengthKm < widthKm)
                //    MessageBox.Show("Principal axes of polygon not longer than minor axis");

                //principal axis direction is defined by p.rotationAngleDeg
                //set the corner of the principal axes bounding box to be negative-going along the major and minor axis
                //this corner will also become the origion of the flight line reference coordinate system
                //this will correspond to a south-east corner for a north-going princpal axis

                p.boundingBoxCornerNorthing =
                    Math.Cos(p.rotationAngleDeg * Constants.Deg2Rad) * (p.meanNorthing + minAlongPA) +
                    Math.Sin(p.rotationAngleDeg * Constants.Deg2Rad) * (p.meanEasting + minOrthoPA);
                p.boundingBoxCornerEasting =
                   -Math.Sin(p.rotationAngleDeg * Constants.Deg2Rad) * (p.meanNorthing + minAlongPA) +
                    Math.Cos(p.rotationAngleDeg * Constants.Deg2Rad) * (p.meanEasting + minOrthoPA);

                //TODO:  should just return the polygon points and fill the p structure after the return
                p.areasqkm = polyMath.areaOfPolygon();
                p.areasqmi = p.areasqkm * 1000000.0 / ((0.3048 * 5280.0) * (0.3048 * 5280.0));

                Constants.Log("");
                if (p.polyCoverageType == COVERAGE_TYPE.polygon)
                {
                    Constants.Log("Polygon area: " + p.areasqmi.ToString("F3") + "  (sqmi)   " + p.areasqkm.ToString("F3") + "  (sqkm)");
                }
                else if (p.polyCoverageType == COVERAGE_TYPE.linearFeature)
                {
                    double pathRange = polyMath.pathLength();
                    Constants.Log("Path length: " + (pathRange/0.3048/5280.0).ToString("F2") +
                        " (mi)  " + (pathRange/1000.0).ToString("F2") + " (km)");
                }
                Constants.Log("");

                ///////////////////////////////////////////////////////////////////////////////////////////////
                //write the summary information for this polygon
                //outfile.WriteLine();
                outfile.WriteLine("PolygonName:  {0}   PolyPoints= {1,4}  Area= {2,9:####.00} (kmsq) {3,9:####.00} (sqmi)",
                        p.PolygonName, numLatLonPoints.ToString(), p.areasqkm, p.areasqmi);
                //foreach (airport apt in apts)
                //       outfile.WriteLine("   {0,50}  distance (mi) {1,8:####.00}", apt.name, apt.distanceToPolyCenterMi);
                /////////////////////////////////////////////////////////////////////////////////////////////////

                //we have modified a copy of the polygon object -- re-insert it into the polygon list
                polygons[i] = p;
            }

            //NOTE: here we are assuming that all the coverage types are identical
            //generally we only use a single coverage for a mission plan session
            return polygons[0].polyCoverageType;
        }
Пример #2
0
        public ReflyPlanner(String _reflyKmlPathFilename, Polygon _p)
        {
            reflyKmlPathFilename = _reflyKmlPathFilename;
            p = _p;

            UTM2Geodetic utm = new UTM2Geodetic();

            XmlTextReader textReader = new XmlTextReader(reflyKmlPathFilename);  //associate the textReader with input file
            while (textReader.Read())
            {
                textReader.MoveToElement();
                if (textReader.IsStartElement() && textReader.Name == "coordinates")
                {
                    /////////////////////////////////////////////////////////////////////
                    //read in and process the coordinates into refly line segments
                    /////////////////////////////////////////////////////////////////////

                    textReader.Read();  //here we read the complete set of coordinates as a single string
                    //textReader.Value contains a string with all the polygon coordinates
                    char[] delimiterChars = { ',', ' ', '\t', '\n', '\r' };   //these delimiters were determined by looking at a file ...
                    //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".
                    string[] coordinateValues = textReader.Value.ToString().Split(delimiterChars);

                    //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;
                    double lat1=0.0, lat2=0.0, lon1=0.0, lon2=0.0;
                    while (i < coordinateValues.Count())
                    {
                        if (coordinateValues[i] != "")
                        {

                            lat1 = Convert.ToDouble(coordinateValues[i + 1]);
                            lon1 = Convert.ToDouble(coordinateValues[i]);

                            //odd-even numbered (k) points are the endpoints
                            if ( (k+1) % 2 == 0)
                            {
                                //have found a segment pair of lat/lon points
                                //order the start/end points so the start end is to the south
                                endPoints ep = new endPoints();
                                if (lat1 > lat2)
                                {
                                    ep.endLat = lat1;
                                    ep.endLon = lon1;
                                    ep.startLat = lat2;
                                    ep.startLon = lon2;
                                }
                                else
                                {
                                    ep.endLat = lat2;
                                    ep.endLon = lon2;
                                    ep.startLat = lat1;
                                    ep.startLon = lon1;
                                }
                                utm.LLtoUTM(ep.startLat * Deg2Rad, ep.startLon * Deg2Rad, ref ep.startUTMY, ref ep.startUTMX, ref p.UTMZone, true);
                                utm.LLtoUTM(ep.endLat * Deg2Rad, ep.endLon * Deg2Rad, ref ep.endUTMY, ref ep.endUTMX, ref p.UTMZone, true);

                                reflySegments.Add(ep);
                            }

                            lat2 = lat1;
                            lon2 = lon1;

                            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
                    }
                }
            }
        }