Example #1
0
 public double degBetween(OrderedTriple t) {
   return Rotater.rad2Deg(radBetween(t));
 }
  private void extractProjection() throws TransformationException {

    Projection proj = null;
    Scaler ncpScale = null;

    String lonType = h.getStringValue("CTYPE" + lonAxis).substring(5, 8);
    String latType = h.getStringValue("CTYPE" + latAxis).substring(5, 8);
    if (!lonType.equals(latType)) {
      throw new TransformationException(
          "Inconsistent projection in FITS header: " + lonType + "," + latType);
    }

    if (lonType.equals("AIT")) {
      proj = new Projection("Ait");

    } else if (lonType.equals("CAR")) {
      proj = new Projection("Car");
      // Allow non-central latitudes for the Cartesian projection.
      try {
        double lon = h.getDoubleValue("CRVAL" + lonAxis);
        if (lon != 0) {
          proj.setReference(toRadians(lon), 0);
        }
      } catch (Exception e) {
        System.err.println("Unable to read reference longitude in Cartesian projection");
      }

    } else if (lonType.equals("CSC")) {
      proj = new Projection("Csc");

    } else if (lonType.equals("SFL") || lonType.equals("GLS")) {
      proj = new Projection("Sfl");

    } else if (lonType.equals("TOA")) {
      proj = new Projection("Toa");

    } else {

      double crval1 = h.getDoubleValue("CRVAL" + lonAxis, NaN);
      double crval2 = h.getDoubleValue("CRVAL" + latAxis, NaN);

      if (isNaN(crval1 + crval2)) {
        throw new TransformationException("Unable to find reference coordinates in FITS header");
      }

      wcsKeys.put("CRVAL1", crval1);
      wcsKeys.put("CRVAL2", crval2);

      if (lonType.equals("TAN")
          || lonType.equals("SIN")
          || lonType.equals("ZEA")
          || lonType.equals("ARC")
          || lonType.equals("STG")) {

        String type = lonType.substring(0, 1) + lonType.substring(1, 3).toLowerCase();
        proj = new Projection(type, new double[] {toRadians(crval1), toRadians(crval2)});

        double lonpole = h.getDoubleValue("LONPOLE", NaN);
        if (!isNaN(lonpole)) {
          wcsKeys.put("LONPOLE", lonpole);
        }
        //  ---- Following is probably erroneous -----
        // The WCS standard indicates that the default LONPOLE for
        // a projection is 180 when the CRVAL latitude is less than
        // the native latitude of the projection (90 degrees for the projections
        // handled here) and 0 otherwise.  This means that for a projection
        // around the pole the default lonpole is 0.  Some data (the SFD surveys)
        // seem to require that we do a rotation of 180 degrees to accommodate
        // this.  However we do not implement this unless the LONPOLE is
        // explicitly given since this seems non-intuitive to me and I suspect
        // that a user who is not careful enough to specify a LONPOLE in this
        // situation probably doesn't understand what is going on anyway.
        // ----- We now assume that our standard processing of
        // ----- zenithal projections handles lonpole of 180 and that
        // ----- this is the default for all zenithal images.
        // ----- Previously we assumed that we were using lonPole=0 at
        // ----- at the poles, but we weren't....
        //

        if (!isNaN(lonpole)) {
          double lonDefault = 180;
          if (lonpole != lonDefault) {

            Rotater r = proj.getRotater();

            Rotater lon = new Rotater("Z", toRadians(lonpole - lonDefault), 0, 0);
            if (r != null) {
              proj.setRotater(r.add(lon));
            } else {
              proj.setRotater(lon);
            }
          }
        }

      } else if (lonType.equals("NCP")) {

        // Sin projection with projection centered at pole.
        double[] xproj = new double[] {toRadians(crval1), PI / 2};
        if (crval2 < 0) {
          xproj[1] = -xproj[1];
        }

        double poleOffset = sin(xproj[1] - toRadians(crval2));
        // Have we handled South pole here?

        proj = new Projection("Sin", xproj);

        // NCP scales the Y-axis to accommodate the distortion of the SIN projection away
        // from the pole.
        ncpScale = new Scaler(0, poleOffset, 1, 0, 0, 1);
        ncpScale = ncpScale.add(new Scaler(0., 0., 1, 0, 0, 1 / sin(toRadians(crval2))));

      } else {
        throw new TransformationException("Unsupported projection type:" + lonType);
      }
    }

    this.proj = proj;
    if (ncpScale != null) {
      this.scale = ncpScale;
    }
    add(proj.getRotater());
    add(proj.getProjecter());
    add(ncpScale); // Ignored if null
  }