Ejemplo n.º 1
0
/**
 * See http://en.wikipedia.org/wiki/Latitude#Degree_length
 *
 * TODO: check if these calculatiosn (based on the oa2gm source code) are
 *       correct.  I guess not, because they both use 6371e3 for computing
 *       new latitudinal and longitudinal points.  This is not 100% correct.
 *       We should probably follow WGS84 or IERS 2003 ellipsoids.
 */
void Circle::discretize( std::vector<Coordinate>& coords, double resolution ) const
{

    // Each circle must have *at least* 360 points (or more if the specified resolution is
    // not satisfied when taking 360 points).
    const int min_nb_points = 360;
    int nbPoints = max((int)(2*pi*radius/resolution), min_nb_points);

    coords.clear();
    coords.reserve(nbPoints);

    double deg_lat, deg_lon;
    double angle;

    Coordinate centerCoord = center.getCoordinate();
    Latitude lat = centerCoord.getLatitude();
    Longitude lon = centerCoord.getLongitude();

    // Compute arcdegree of latitude respectively longitude difference of the center.
    double arcdegree_lat = lat.getArcDegree();
    double arcdegree_lon = lon.getArcDegree(lat);

    for (int i = 0; i < nbPoints; ++i)
    {
        angle = 2*pi*i/nbPoints;

        deg_lon = lon.getAngle() + getRadiusM()*cos(angle)/arcdegree_lon;
        deg_lat = lat.getAngle() + getRadiusM()*sin(angle)/arcdegree_lat;
        coords.push_back( Coordinate( deg_lat, deg_lon ) );
    }
}
Ejemplo n.º 2
0
  /**
   * Filters a list of points for points that are of the selected
   * Range or in the given range. The filtered list will appear in
   * the navtools point list display.
   * @internal
   *   @history 2009-01-08 Jeannie Walldren - Modified to remove
   *                          new filter points from the existing
   *                          filtered list. Previously, a new
   *                          filtered list was created from the
   *                          entire control net each time.
   *   @history 2010-06-03 Jeannie Walldren - Removed "std::"
   *                          since "using namespace std"
   *
   */
  void QnetPointRangeFilter::filter() {
    // Make sure there is a control net loaded
    if (controlNet() == NULL) {
      QMessageBox::information((QWidget *)parent(),
          "Error", "No points to filter");
      return;
    }

    // Make sure all the values we need have been entered by the user
    if ((m_minlat->text() == "") || (m_maxlat->text() == "") ||
        (m_minlon->text() == "") || (m_maxlon->text() == "")) {
      QMessageBox::information((QWidget *)parent(),
          "Error", "All lat/lon range values must be entered");
      return;
    }
    else {
      // Get the user entered values for the range
      double minlat = m_minlat->text().toDouble();
      double maxlat = m_maxlat->text().toDouble();
      double minlon = m_minlon->text().toDouble();
      double maxlon = m_maxlon->text().toDouble();

      // Make sure the lat values are in order
      if (minlat > maxlat) {
        QString msg = "The minimum latitude value must be less than the maximum latitude value";
        QMessageBox::information((QWidget *)parent(), "Error", msg);
        return;
      }
      // Make sure the lon values are in order
      else if (minlon > maxlon) {
        QString msg = "The minimum longitude value must be less than the maximum longitude value";
        QMessageBox::information((QWidget *)parent(), "Error", msg);
        return;
      }

      // Loop through each value of the filtered points list
      // checking to see if each point falls within the rangee
      // Loop in reverse order since removal list of elements affects index number
      for (int i = filteredPoints().size() - 1; i >= 0; i--) {
        // Get the current control point
        ControlPoint &cp = *(*controlNet())[filteredPoints()[i]];

        Latitude lat = cp.GetBestSurfacePoint().GetLatitude();
        Longitude lon = cp.GetBestSurfacePoint().GetLongitude();
        if (lat.inRange(Latitude(minlat,Angle::Degrees),Latitude(maxlat,Angle::Degrees)) &&
            lon.inRange(Longitude(minlon,Angle::Degrees),Longitude(maxlon,Angle::Degrees))) {
          continue;
        }
        else {
          filteredPoints().removeAt(i);
        }

      }
    }

    // Tell the navtool that a list has been filtered and it needs to update
    emit filteredListModified();
    return;
  }
Ejemplo n.º 3
0
static std::string latlon(const Latitude latitude, const Longitude longitude) {
	if( latitude.is_valid() && longitude.is_valid() ) {
		return latlon_abs_normalized(latitude.normalized(), "SN") + " " + latlon_abs_normalized(longitude.normalized(), "WE");
	} else if( latitude.is_not_available() && longitude.is_not_available() ) {
		return "not available";
	} else {
		return "invalid";
	}
}
Ejemplo n.º 4
0
/**
 * Determines the difference in solar time between two longitudes at the same
 * clock time (expressed in the same time zone), that is, at the same point in
 * time
 *
 * For a longitude east of the other longitude, the solar time is later, thus,
 * the returned value is positive.
 *
 * @param other another longitude
 * @return the difference in solar time, in seconds
 * @see clockTimeOffsetTo
 */
double Longitude::solarTimeOffsetTo (const Longitude &other)
{
	double dLon=normalized ().getValue ()-other.normalized ().getValue ();

	// 360° -- 1 day (86400 s)
	return dLon/360*86400;
}
Ejemplo n.º 5
0
// Compute the radius at the lat/lon
Distance GetRadius(QString filename, Latitude lat, Longitude lon) {
  Cube cube(filename, "r");
  Sensor sensor(cube);
  sensor.SetGround(SurfacePoint(lat, lon, sensor.LocalRadius(lat, lon)));
  Distance radius = sensor.LocalRadius();
  if(!radius.isValid()) {
    QString msg = "Could not determine radius from DEM at lat/lon [";
    msg += toString(lat.degrees()) + "," + toString(lon.degrees()) + "]";
    throw IException(IException::Unknown, msg, _FILEINFO_);
  }
  return radius;
}
Ejemplo n.º 6
0
 /**
  * Returns whether the lat/lon position was set successfully in the camera
  * model or projection.
  *
  * @param lat The universal latitude or ring radius for ring planes
  * @param lon The universal longitude or ring longitude (azimuth) for ring planes
  *
  * @return Returns true if the lat/lon position was set successfully, and
  *         false if it was not
  */
 bool UniversalGroundMap::SetGround(Latitude lat, Longitude lon) {
   if(p_camera != NULL) {
     if(p_camera->SetGround(lat, lon)) {  // This should work for rings (radius,azimuth)
       return p_camera->InCube();
     }
     else {
       return false;
     }
   }
   else {
     double universalLat = lat.degrees();
     double universalLon = lon.degrees();
     return p_projection->SetUniversalGround(universalLat, universalLon);  // This should work for rings (radius,azimuth)
   }
 }
Ejemplo n.º 7
0
void Parser::handleLine(const std::string& line)
{
    smatch matches;

    if ( regex_match(line, matches, regexMap.find(REGEX_COMMENT)->second) )
    {
        // do nothing.
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AC)->second) )
    {
        airspaces.push_back(new Airspace);

        setCurrentDirection('+');
        currentArcCenter.reset();

        // Assign the parsed class to the current airspace.
        string matched_text( matches[1].first, matches[1].second );
        getCurrentAirspace()->setClass( parseAirspaceClass(matched_text) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AN)->second) )
    {
        string airspace_name( matches[1].first, matches[1].second );
        getCurrentAirspace()->setName(airspace_name);
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AH)->second) )
    {
        string airspace_ceiling(matches[1].first, matches[1].second);
        getCurrentAirspace()->setCeilingString(airspace_ceiling);
        getCurrentAirspace()->setCeiling( parseAltitude(airspace_ceiling) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AL)->second) )
    {
        string airspace_floor(matches[1].first, matches[1].second);
        getCurrentAirspace()->setFloorString(airspace_floor);
        getCurrentAirspace()->setFloor( parseAltitude(airspace_floor) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_AT)->second) )
    {
        string airspace_coordinate(matches[1].first, matches[1].second);
        getCurrentAirspace()->add( Label(getCurrentAirspace()->getName(), parseCoordinate(airspace_coordinate)) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_VX)->second) )
    {
        string matched_text(matches[1].first, matches[1].second);
        setCurrentArcCenter(parseCoordinate(matched_text));
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_VD)->second) )
    {
        string direction_string;
        for (unsigned int i = 1; i < matches.size(); ++i)
        {
            direction_string.assign(matches[i].first, matches[i].second);
        }
        setCurrentDirection(direction_string[0]);
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DP)->second) )
    {
        string point_coordinate( matches[1].first, matches[1].second );
        getCurrentAirspace()->add( new Point(parseCoordinate(point_coordinate)) );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DA)->second) )
    {
        // Read the matched values and create our Arc.
        string radiusNM(   matches[1].first, matches[1].second );
        string angleStart( matches[2].first, matches[2].second );
        string angleEnd(   matches[3].first, matches[3].second );

        Arc arc( *(getCurrentArcCenter()), atof(radiusNM.c_str()),
                 atof(angleStart.c_str()), atof(angleEnd.c_str()), getCurrentDirection());

        getCurrentAirspace()->add( &arc );
        return;
    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DB)->second) )
    {
        // We have a DB-record, now check if the coords are specified correctly...
        string dbcoords( matches[1].first, matches[1].second );
        if ( regex_match(dbcoords, matches, regexMap.find(REGEX_DB_COORDS)->second) )
        {
            // Fetch the start and end coordinate for this arc.
            string coord1( matches[1].first, matches[1].second );
            string coord2( matches[2].first, matches[2].second );
            Coordinate c1 = parseCoordinate(coord1);
            Coordinate c2 = parseCoordinate(coord2);

            std::shared_ptr<Coordinate> currentArcCenter = getCurrentArcCenter();

            // Retrieve latitude and longitude of the arc-center.
            Latitude lat = currentArcCenter->getLatitude();
            Longitude lon = currentArcCenter->getLongitude();

            // Compute arcdegree of latitude respectively longitude, based on the center's coordinates.
            double arcdegree_lat = lat.getArcDegree();
            double arcdegree_lon = lon.getArcDegree(lat);

            // Compute start and end angle (in standard coordinate frame!)
            // Note that we have to take into account the arcdegrees here!!!
            double dLat1 = ( c1.getLatitude().getAngle()  - currentArcCenter->getLatitude().getAngle()  )*arcdegree_lat;
            double dLon1 = ( c1.getLongitude().getAngle() - currentArcCenter->getLongitude().getAngle() )*arcdegree_lon;
            double dLat2 = ( c2.getLatitude().getAngle()  - currentArcCenter->getLatitude().getAngle()  )*arcdegree_lat;
            double dLon2 = ( c2.getLongitude().getAngle() - currentArcCenter->getLongitude().getAngle() )*arcdegree_lon;
            double startAngle = 180.0*atan2(dLat1, dLon1)/pi;
            double endAngle   = 180.0*atan2(dLat2, dLon2)/pi;

            // Convert start and end angle to airspace coordinate frame.
            startAngle = 90 - startAngle;
            endAngle   = 90 - endAngle;

            // Use maximum of the two radii (for safety reasons).
            //double radius = max( c1.getDistance(getCurrentCoordinate()), c2.getDistance(getCurrentCoordinate()) );
            // Use minimum of the two radii.
            //double radius = min( c1.getDistance(getCurrentCoordinate()), c2.getDistance(getCurrentCoordinate()) );
            // Use average of the two radii.
            double radius = ( c1.getDistance(*currentArcCenter) + c2.getDistance(*currentArcCenter) )*0.5;

            // Add the arc points to this space's Polygon.
            getCurrentAirspace()->add( new Arc(*currentArcCenter,
                                               radius/1852.0, startAngle, endAngle, getCurrentDirection()) );
        }
        else
        {
            cout << "\nERROR: invalid coordinate string specification in DB-record: " << line << endl;
            exit(1);
        }

    }

    if ( regex_match(line, matches, regexMap.find(REGEX_DC)->second) )
    {
        // Get circle radius (in Nautical Miles) from what we've just read.
        string radiusNM;
        radiusNM.assign(matches[1].first, matches[1].second);

        // Add circle to this Airspace.
        Point center(*(getCurrentArcCenter()));
        getCurrentAirspace()->add(new Circle(center, atof(radiusNM.c_str())));

    }
}
Ejemplo n.º 8
0
  /**
   * Find the lat/lon range of the image. This will use the image footprint,
   *   camera, or projection in order to find a good result.
   *
   * @param Cube* This is required for estimation. You can pass in NULL (it will
   *              disable estimation).
   * @param minLat This is an output: minimum latitude
   * @param maxLat This is an output: maximum latitude
   * @param minLon This is an output: minimum longitude
   * @param maxLon This is an output: maximum longitude
   * @param allowEstimation If this is true then extra efforts will be made to
   *     guess the ground range of the input. This can still fail.
   * @return True if a ground range was found, false if no ground range could
   *     be determined. Some lat/lon results may still be populated; their
   *     values are undefined.
   */
  bool UniversalGroundMap::GroundRange(Cube *cube, Latitude &minLat,
      Latitude &maxLat, Longitude &minLon, Longitude &maxLon,
      bool allowEstimation) {
    // Do we need a RingRange method?
    // For now just return false
    if (HasCamera())
      if (p_camera->target()->shape()->name() == "Plane") return false;
    if (HasProjection()) 
      if (p_projection->projectionType() == Projection::RingPlane) return false;

    minLat = Latitude();
    maxLat = Latitude();
    minLon = Longitude();
    maxLon = Longitude();

    // If we have a footprint, use it
    try {
      if (cube) {
        ImagePolygon poly;
        cube->read(poly);
        geos::geom::MultiPolygon *footprint = PolygonTools::MakeMultiPolygon(
            poly.Polys()->clone());

        geos::geom::Geometry *envelope = footprint->getEnvelope();
        geos::geom::CoordinateSequence *coords = envelope->getCoordinates();

        for (unsigned int i = 0; i < coords->getSize(); i++) {
          const geos::geom::Coordinate &coord = coords->getAt(i);

          Latitude coordLat(coord.y, Angle::Degrees);
          Longitude coordLon(coord.x, Angle::Degrees);

          if (!minLat.isValid() || minLat > coordLat)
            minLat = coordLat;
          if (!maxLat.isValid() || maxLat < coordLat)
            maxLat = coordLat;

          if (!minLon.isValid() || minLon > coordLon)
            minLon = coordLon;
          if (!maxLon.isValid() || maxLon < coordLon)
            maxLon = coordLon;
        }

        delete coords;
        coords = NULL;

        delete envelope;
        envelope = NULL;

        delete footprint;
        footprint = NULL;
      }
    }
    catch (IException &) {
    }

    if (!minLat.isValid() || !maxLat.isValid() ||
        !minLon.isValid() || !maxLon.isValid()) {
      if (HasCamera()) {
        // Footprint failed, ask the camera
        PvlGroup mappingGrp("Mapping");
        mappingGrp += PvlKeyword("LatitudeType", "Planetocentric");
        mappingGrp += PvlKeyword("LongitudeDomain", "360");
        mappingGrp += PvlKeyword("LongitudeDirection", "PositiveEast");

        Pvl mappingPvl;
        mappingPvl += mappingGrp;
        double minLatDouble;
        double maxLatDouble;
        double minLonDouble;
        double maxLonDouble;
        p_camera->GroundRange(
            minLatDouble, maxLatDouble,
            minLonDouble, maxLonDouble, mappingPvl);
        minLat = Latitude(minLatDouble, Angle::Degrees);
        maxLat = Latitude(maxLatDouble, Angle::Degrees);
        minLon = Longitude(minLonDouble, Angle::Degrees);
        maxLon = Longitude(maxLonDouble, Angle::Degrees);
      }
      else if (HasProjection()) {
        // Footprint failed, look in the mapping group
        PvlGroup mappingGrp = p_projection->Mapping();
        if (mappingGrp.hasKeyword("MinimumLatitude") &&
            mappingGrp.hasKeyword("MaximumLatitude") &&
            mappingGrp.hasKeyword("MinimumLongitude") &&
            mappingGrp.hasKeyword("MaximumLongitude")) {

          minLat = Latitude(mappingGrp["MinimumLatitude"],
                            mappingGrp, Angle::Degrees);
          maxLat = Latitude(mappingGrp["MaximumLatitude"],
                            mappingGrp, Angle::Degrees);
          minLon = Longitude(mappingGrp["MinimumLongitude"],
                             mappingGrp, Angle::Degrees);
          maxLon = Longitude(mappingGrp["MaximumLongitude"],
                             mappingGrp, Angle::Degrees);

        }
        else if (allowEstimation && cube) {
          // Footprint and mapping failed... no lat/lon range of any kind is
          //   available. Let's test points in the image to try to make our own
          //   extent.
          QList<QPointF> imagePoints;

          // Reset to TProjection
          TProjection *tproj = (TProjection *) p_projection;

                    /*
           * This is where we're testing:
           *
           *  |---------------|
           *  |***************|
           *  |**     *     **|
           *  |*  *   *   *  *|
           *  |*    * * *    *|
           *  |***************|
           *  |*    * * *    *|
           *  |*  *   *   *  *|
           *  |**     *     **|
           *  |***************|
           *  |---------------|
           *
           * We'll test at the edges, a plus (+) and an (X) to help DEMs work.
           */

          int sampleCount = cube->sampleCount();
          int lineCount = cube->lineCount();

          int stepsPerLength = 20; //number of steps per length
          double aspectRatio = (double)lineCount / (double)sampleCount;
          double xStepSize = sampleCount / stepsPerLength;
          double yStepSize = xStepSize * aspectRatio;

          if (lineCount > sampleCount) {
            aspectRatio = (double)sampleCount / (double)lineCount;
            yStepSize = lineCount / stepsPerLength;
            xStepSize = yStepSize * aspectRatio;
          }

          double yWalked = 0.5;

          //3 vertical lines
          for (int i = 0; i < 3; i++) {
            double xValue = 0.5 + ( i * (sampleCount / 2) );

            while (yWalked <= lineCount) {
              imagePoints.append( QPointF(xValue, yWalked) );
              yWalked += yStepSize;
            }

            yWalked = 0.5;
          }

          double xWalked = 0.5;

          //3 horizontal lines
          for (int i = 0; i < 3; i++) {
            double yValue = 0.5 + ( i * (lineCount / 2) );

            while (xWalked <= sampleCount) {
              imagePoints.append( QPointF(xWalked, yValue) );
              xWalked += xStepSize;
            }

            xWalked = 0.5;
          }

          double xDiagonalWalked = 0.5;
          double yDiagonalWalked = 0.5;
          xStepSize = sampleCount / stepsPerLength;
          yStepSize = lineCount / stepsPerLength;

          //Top-Down Diagonal
          while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked <= lineCount) ) {
            imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
            xDiagonalWalked += xStepSize;
            yDiagonalWalked += yStepSize;
          }

          xDiagonalWalked = 0.5;

          //Bottom-Up Diagonal
          while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked >= 0) ) {
            imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
            xDiagonalWalked += xStepSize;
            yDiagonalWalked -= yStepSize;
          }

          foreach (QPointF imagePoint, imagePoints) {
            if (tproj->SetWorld(imagePoint.x(), imagePoint.y())) {
              Latitude latResult(tproj->UniversalLatitude(),
                                 Angle::Degrees);
              Longitude lonResult(tproj->UniversalLongitude(),
                                  Angle::Degrees);
              if (minLat.isValid())
                minLat = qMin(minLat, latResult);
              else
                minLat = latResult;

              if (maxLat.isValid())
                maxLat = qMax(maxLat, latResult);
              else
                maxLat = latResult;

              if (minLon.isValid())
                minLon = qMin(minLon, lonResult);
              else
                minLon = lonResult;

              if (maxLon.isValid())
                maxLon = qMax(maxLon, lonResult);
              else
                maxLon = lonResult;
            }
          }
        }
      }
    }
Ejemplo n.º 9
0
  /** Compute undistorted focal plane coordinate from ground position
   *
   * @param lat Planetocentric latitude in degrees
   * @param lon Planetocentric longitude in degrees
   *
   * @return @b bool Indicates whether the conversion was successful
   *
   * @internal
   * @history 2007-04-18  Tracie Sucharski - Added check for reasonable
   *                             match when attempting to find closest
   *                             lat/lon in map arrays.
   * @history 2007-09-14  Tracie Sucharski - Added check for longitude
   *                             outside min/max bounds.  Don't know why
   *                             this wasn't put in before (lat check was
   *                             in), was it oversight, or did I take it out
   *                             for some reason???
   * @history 2007-12-14  Tracie Sucharski - Remove resolution test, too
   *                            image dependent and the resolution for vims is
   *                            incorrect due to the instrument having
   *                            rectangular pixels.
   * @history 2008-01-02  Tracie Sucharski -  Check validity of resulting
   *                            sample and line against edge of starting
   *                            ending pixels (0.5/Parent+0.5) instead of
   *                            center of pixels.
   * @history 2012-12-03  Tracie Sucharski - Check for valid minLat/maxLat, minLon/maxLon.  If 
   *                            none are valid, this means the latMap and lonMap have no valid
   *                            data, therefore we cannot back project, so return false.
   *
   */
  bool VimsGroundMap::SetGround(const Latitude &lat, const Longitude &lon) {

    QVector3D xyz;
    if (p_camera->target()->shape()->name() == "Plane") {
        double radius = lat.degrees();
        if(radius <= 0.0)
          return false;

        double xCheck = radius * 0.001 * cos(lon.radians());
        double yCheck = radius * 0.001 * sin(lon.radians());

        xyz.setX(xCheck);
        xyz.setY(yCheck);
        xyz.setZ(0.);
      }
    else {
        //  Convert lat/lon to x/y/z
        Distance radius = p_camera->LocalRadius(lat, lon);
        SpiceDouble pB[3];
        latrec_c(radius.kilometers(), lon.radians(), lat.radians(), pB);

        xyz.setX(pB[0]);
        xyz.setY(pB[1]);
        xyz.setZ(pB[2]);
    }

    double minDist = DBL_MAX;
    int minSamp = -1;
    int minLine = -1;

    //  Find closest points  ??? what tolerance ???
    for (int line = 0; line < p_camera->ParentLines(); line++) {
      for (int samp = 0; samp < p_camera->ParentSamples(); samp++) {

        if (p_xyzMap[line][samp].isNull()) continue;

        //  Subtract map from coordinate then get length
        QVector3D deltaXyz = xyz - p_xyzMap[line][samp];
        if (deltaXyz.length() < minDist) {
          minDist = deltaXyz.length();
          minSamp = samp;
          minLine = line;
        }
      }
    }

    //-----------------------------------------------------------------
    //  If dist is less than some ??? tolerance ??? this is the
    //  closest point.  Use this point and surrounding 8 pts as
    //  control pts.
    //----------------------------------------------------------------
    if (minDist >= DBL_MAX) return false;

    //-------------------------------------------------------------
    //  Set-up for LU decomposition (least2 fit).
    //  Assume we will have 9 control points, this may not be true
    //  and will need to be adjusted before the final solution.
    //-------------------------------------------------------------
    BasisFunction sampXyzBasis("Sample", 4, 4);
    BasisFunction lineXyzBasis("Line", 4, 4);
    LeastSquares sampXyzLsq(sampXyzBasis);
    LeastSquares lineXyzLsq(lineXyzBasis);
    vector<double> knownXyz(4);

    //  Solve using x/y/z
    for (int line = minLine - 1; line < minLine + 2; line++) {
      if (line < 0 || line > p_camera->ParentLines() - 1) continue;
      for (int samp = minSamp - 1; samp < minSamp + 2; samp++) {
        //  Check for edges
        if (samp < 0 || samp > p_camera->ParentSamples() - 1) continue;
        if (p_xyzMap[line][samp].isNull()) continue;

        knownXyz[0] = p_xyzMap[line][samp].x();
        knownXyz[1] = p_xyzMap[line][samp].y();
        knownXyz[2] = p_xyzMap[line][samp].z();
        knownXyz[3] = 1;
        sampXyzLsq.AddKnown(knownXyz, samp + 1);
        lineXyzLsq.AddKnown(knownXyz, line + 1);
      }
    }

    if (sampXyzLsq.Knowns() < 4) return false;

    sampXyzLsq.Solve();
    lineXyzLsq.Solve();

    //  Solve for sample, line position corresponding to input lat, lon
    knownXyz[0] = xyz.x();
    knownXyz[1] = xyz.y();
    knownXyz[2] = xyz.z();
    knownXyz[3] = 1;
    double inSamp = sampXyzLsq.Evaluate(knownXyz);
    double inLine = lineXyzLsq.Evaluate(knownXyz);


    if (inSamp < 0.5 || inSamp > p_camera->ParentSamples() + 0.5 ||
        inLine < 0.5 || inLine > p_camera->ParentLines() + 0.5) {
      return false;
    }

    p_camera->IgnoreProjection(true);
    p_camera->SetImage(inSamp, inLine);
    p_camera->IgnoreProjection(false);
    if (!p_camera->HasSurfaceIntersection()) return false;

    p_focalPlaneX = inSamp;
    p_focalPlaneY = inLine;

    return true;
  }
Ejemplo n.º 10
0
void IsisMain() {

  UserInterface &ui = Application::GetUserInterface();

  FileList addList(ui.GetFileName("ADDLIST"));

  bool log = false;
  FileName logFile;
  if (ui.WasEntered("LOG")) {
    log = true;
    logFile = ui.GetFileName("LOG");
  }
  Pvl results;
  results.setName("cnetadd_Results");
  PvlKeyword added("FilesAdded");
  PvlKeyword omitted("FilesOmitted");
  PvlKeyword pointsModified("PointsModified");

  bool checkMeasureValidity = ui.WasEntered("DEFFILE");
  ControlNetValidMeasure validator;
  if (checkMeasureValidity) {
    Pvl deffile(ui.GetFileName("DEFFILE"));
    validator = ControlNetValidMeasure(deffile);
  }

  SerialNumberList *fromSerials = ui.WasEntered("FROMLIST") ?
    new SerialNumberList(ui.GetFileName("FROMLIST")) : new SerialNumberList();

  ControlNet inNet = ControlNet(ui.GetFileName("CNET"));
  inNet.SetUserName(Application::UserName());
  inNet.SetModifiedDate(iTime::CurrentLocalTime()); //This should be done in ControlNet's Write fn

  QString retrievalOpt = ui.GetString("RETRIEVAL");
  PvlKeyword duplicates("DupSerialNumbers");
  if (retrievalOpt == "REFERENCE") {
    FileList list1(ui.GetFileName("FROMLIST"));
    SerialNumberList addSerials(ui.GetFileName("ADDLIST"));

    //Check for duplicate files in the lists by serial number
    for (int i = 0; i < addSerials.Size(); i++) {

      // Check for duplicate SNs accross the lists
      if (fromSerials->HasSerialNumber(addSerials.SerialNumber(i))) {
        duplicates.addValue(addSerials.FileName(i));
      }

      // Check for duplicate SNs within the addlist
      for (int j = i + 1; j < addSerials.Size(); j++) {
        if (addSerials.SerialNumber(i) == addSerials.SerialNumber(j)) {
          QString msg = "Add list files [" + addSerials.FileName(i) + "] and [";
          msg += addSerials.FileName(j) + "] share the same serial number.";
          throw IException(IException::User, msg, _FILEINFO_);
        }
      }
    }

    // Get the lat/long coords from the existing reference measure
    setControlPointLatLon(*fromSerials, inNet);
  }
  else {
    for (int cp = 0; cp < inNet.GetNumPoints(); cp++) {
      // Get the surface point from the current control point
      ControlPoint *point = inNet.GetPoint(cp);
      SurfacePoint surfacePoint = point->GetBestSurfacePoint();

      if (!surfacePoint.Valid()) {
        QString msg = "Unable to retreive lat/lon from Control Point [";
        msg += point->GetId() + "]. RETREIVAL=POINT cannot be used unless ";
        msg += "all Control Points have Latitude/Longitude keywords.";
        throw IException(IException::User, msg, _FILEINFO_);
      }

      g_surfacePoints[point->GetId()] = surfacePoint;
    }
  }

  FileName outNetFile(ui.GetFileName("ONET"));

  Progress progress;
  progress.SetText("Adding Images");
  progress.SetMaximumSteps(addList.size());
  progress.CheckStatus();

  STRtree coordTree;
  QList<ControlPoint *> pointList;
  bool usePolygon = ui.GetBoolean("POLYGON");
  if (usePolygon) {
    for (int cp = 0; cp < inNet.GetNumPoints(); cp++) {
      ControlPoint *point = inNet.GetPoint(cp);
      SurfacePoint surfacePoint = g_surfacePoints[point->GetId()];

      Longitude lon = surfacePoint.GetLongitude();
      Latitude lat = surfacePoint.GetLatitude();

      Coordinate *coord = new Coordinate(lon.degrees(), lat.degrees());
      Envelope *envelope = new Envelope(*coord);
      coordTree.insert(envelope, point);
    }
  }
  else {
    for (int cp = 0; cp < inNet.GetNumPoints(); cp++) {
      pointList.append(inNet.GetPoint(cp));
    }
  }

  // Loop through all the images
  for (int img = 0; img < addList.size(); img++) {
    Cube cube;
    cube.open(addList[img].toString());
    Pvl *cubepvl = cube.label();
    QString sn = SerialNumber::Compose(*cubepvl);
    Camera *cam = cube.camera();

    // Loop through all the control points
    QList<ControlPoint *> validPoints = usePolygon ?
        getValidPoints(cube, coordTree) : pointList;

    bool imageAdded = false;
    for (int cp = 0; cp < validPoints.size(); cp++) {
      ControlPoint *point = validPoints[cp];

      // If the point is locked and Apriori source is "AverageOfMeasures"
      // then do not add the measures.
      if (point->IsEditLocked() &&
          point->GetAprioriSurfacePointSource() ==
              ControlPoint::SurfacePointSource::AverageOfMeasures) {
        continue;
      }

      if (point->HasSerialNumber(sn)) continue;

      // Only use the surface point's latitude and longitude, rely on the DEM
      // for computing the radius.  We do this because otherwise we will receive
      // inconsistent results from successive runs of this program if the
      // different DEMs are used, or the point X, Y, Z was generated from the
      // ellipsoid.
      SurfacePoint surfacePoint = g_surfacePoints[point->GetId()];
      if (cam->SetGround(
              surfacePoint.GetLatitude(), surfacePoint.GetLongitude())) {

        // Make sure the samp & line are inside the image
        if (cam->InCube()) {
          ControlMeasure *newCm = new ControlMeasure();
          newCm->SetCoordinate(cam->Sample(), cam->Line(), ControlMeasure::Candidate);
          newCm->SetAprioriSample(cam->Sample());
          newCm->SetAprioriLine(cam->Line());
          newCm->SetCubeSerialNumber(sn);
          newCm->SetDateTime();
          newCm->SetChooserName("Application cnetadd");

          // Check the measure for DEFFILE validity
          if (checkMeasureValidity) {
            if (!validator.ValidEmissionAngle(cam->EmissionAngle())) {
              //TODO: log that it was Emission Angle that failed the check
              newCm->SetIgnored(true);
            }
            else if (!validator.ValidIncidenceAngle(cam->IncidenceAngle())) {
              //TODO: log that it was Incidence Angle that failed the check
              newCm->SetIgnored(true);
            }
            else if (!validator.ValidResolution(cam->resolution())) {
              //TODO: log that it was Resolution that failed the check
              newCm->SetIgnored(true);
            }
            else if (!validator.PixelsFromEdge((int)cam->Sample(), (int)cam->Line(), &cube)) {
              //TODO: log that it was Pixels from Edge that failed the check
              newCm->SetIgnored(true);
            }
            else {
              Portal portal(1, 1, cube.pixelType());
              portal.SetPosition(cam->Sample(), cam->Line(), 1);
              cube.read(portal);
              if (!validator.ValidDnValue(portal[0])) {
                //TODO: log that it was DN that failed the check
                newCm->SetIgnored(true);
              }
            }
          }

          point->Add(newCm); // Point takes ownership

          // Record the modified Point and Measure
          g_modifications[point->GetId()].insert(newCm->GetCubeSerialNumber());
          newCm = NULL; // Do not delete because the point has ownership

          if (retrievalOpt == "POINT" && point->GetNumMeasures() == 1)
            point->SetIgnored(false);

          imageAdded = true;
        }
      }
    }

    cubepvl = NULL;
    cam = NULL;

    if (log) {
      PvlKeyword &logKeyword = (imageAdded) ? added : omitted;
      logKeyword.addValue(addList[img].baseName());
    }

    progress.CheckStatus();
  }

  if (log) {
    // Add the list of modified points to the output log file
    QList<QString> modifiedPointsList = g_modifications.keys();
    for (int i = 0; i < modifiedPointsList.size(); i++)
      pointsModified += modifiedPointsList[i];

    results.addKeyword(added);
    results.addKeyword(omitted);
    results.addKeyword(pointsModified);
    if (duplicates.size() > 0) {
      results.addKeyword(duplicates);
    }

    results.write(logFile.expanded());
  }

  // List the modified points
  if (ui.WasEntered("MODIFIEDPOINTS")) {
    FileName pointList(ui.GetFileName("MODIFIEDPOINTS"));

    // Set up the output file for writing
    std::ofstream out_stream;
    out_stream.open(pointList.expanded().toAscii().data(), std::ios::out);
    out_stream.seekp(0, std::ios::beg);   //Start writing from beginning of file

    QList<QString> modifiedPointsList = g_modifications.keys();
    for (int i = 0; i < modifiedPointsList.size(); i++)
      out_stream << modifiedPointsList[i].toStdString() << std::endl;

    out_stream.close();
  }

  // Modify the inNet to only have modified points/measures
  if (ui.GetString("EXTRACT") == "MODIFIED") {
    for (int cp = inNet.GetNumPoints() - 1; cp >= 0; cp--) {
      ControlPoint *point = inNet.GetPoint(cp);

      // If the point was not modified, delete
      // Even get rid of edit locked points in this case
      if (!g_modifications.contains(point->GetId())) {
        point->SetEditLock(false);
        inNet.DeletePoint(cp);
      }
      // Else, remove the unwanted measures from the modified point
      else {
        for (int cm = point->GetNumMeasures() - 1; cm >= 0; cm--) {
          ControlMeasure *measure = point->GetMeasure(cm);

          // Even get rid of edit locked measures in this case
          if (point->GetRefMeasure() != measure &&
              !g_modifications[point->GetId()].contains(
                  measure->GetCubeSerialNumber())) {
            measure->SetEditLock(false);
            point->Delete(cm);
          }
        }
      }
    }
  }

  // Generate the TOLIST if wanted
  if (ui.WasEntered("TOLIST")) {
    SerialNumberList toList;

    SerialNumberList addSerials(ui.GetFileName("ADDLIST"));

    const QList<QString> snList = inNet.GetCubeSerials();
    for (int i = 0; i < snList.size(); i++) {
      QString sn = snList[i];

      if (addSerials.HasSerialNumber(sn))
        toList.Add(addSerials.FileName(sn));
      else if (fromSerials->HasSerialNumber(sn))
        toList.Add(fromSerials->FileName(sn));
    }

    IString name(ui.GetFileName("TOLIST"));
    std::fstream out_stream;
    out_stream.open(name.c_str(), std::ios::out);
    out_stream.seekp(0, std::ios::beg); //Start writing from beginning of file

    for (int f = 0; f < (int) toList.Size(); f++)
      out_stream << toList.FileName(f) << std::endl;

    out_stream.close();
  }

  inNet.Write(outNetFile.expanded());

  delete fromSerials;
}