USGS

Isis 3.0 Application Source Code Reference

Home

shade.cpp

Go to the documentation of this file.
00001 #include <cmath>
00002 #include "Isis.h"
00003 #include "ProcessByBoxcar.h"
00004 #include "Constants.h"
00005 #include "SpecialPixel.h"
00006 
00007 using namespace std;
00008 using namespace Isis;
00009 
00010 double pixelResolution;
00011 double saz;
00012 double zenith;
00013 
00014 void shade(Buffer &in, double &v);
00015 
00016 void IsisMain() {
00017 
00018   const double DEG2RAD = PI / 180.0;
00019   ProcessByBoxcar p;
00020 
00021   UserInterface &ui = Application::GetUserInterface();
00022 
00023   // Open the input cube
00024   Cube *inCube = p.SetInputCube("FROM");
00025 
00026   // Allocate the output cube
00027   p.SetOutputCube("TO");
00028 
00029   p.SetBoxcarSize(3, 3);
00030 
00031   // Read user parameters
00032   // This parameter as used by the algorithm is 0-360 with 0 at 3 o'clock,
00033   // increasing in the clockwise direction. The value taken in from the user is
00034   // 0-360 with 0 at 12 o'clock increasing in the clockwise direction.
00035   saz = ui.GetDouble("AZIMUTH");
00036   saz += 270;
00037   if(saz > 360) saz -= 360;
00038   saz *= DEG2RAD;
00039 
00040   // This parameter as used by the algorithm is 0-90 as the angle to the light source,
00041   // this means 90 is at the horizon and 0 is directly overhead.
00042   zenith = ui.GetDouble("ZENITH");
00043   zenith *= DEG2RAD;
00044 
00045   // Get from labels or from user
00046   if(ui.WasEntered("PIXELRESOL")) {
00047     pixelResolution = ui.GetDouble("PIXELRESOL");
00048   }
00049   else {
00050     if(inCube->getLabel()->FindObject("IsisCube").HasGroup("Mapping")) {
00051       pixelResolution = inCube->getLabel()->FindObject("IsisCube").FindGroup("Mapping")["PixelResolution"];
00052     }
00053     else {
00054       string msg = "The file [" + ui.GetFilename("FROM") + "] does not have a mapping group,"
00055                    + " you must enter a Pixel Resolution";
00056       throw iException::Message(iException::User, msg, _FILEINFO_);
00057     }
00058   }
00059 
00060   p.StartProcess(shade);
00061   p.EndProcess();
00062 
00063 }
00064 
00065 // Shade processing routine
00066 void shade(Buffer &in, double &v) {
00067 
00068   // first we just check to make sure that we don't have any special pixels
00069   bool specials = false;
00070   for(int i = 0; i < in.size(); ++i) {
00071     if(IsSpecial(in[i])) {
00072       specials = true;
00073     }
00074   }
00075 
00076   // if we have any special pixels we bail out (well ok just set to null)
00077   if(specials) {
00078     v = Isis::Null;
00079   }
00080   else {
00081     /* if we have a 3x3 section that doesn't have an special pixels we hit that 3x3
00082     / against two gradients
00083 
00084       [-1 0 1 ]   [-1 -1 -1 ]
00085       [-1 0 1 ]   [ 0  0  0 ]
00086       [-1 0 1 ]   [ 1  1  1 ]
00087 
00088       These two gradients are not special in any way aside from that they are
00089       are orthogonal. they can be replaced if someone has reason as long as they
00090       stay orthogonal to eachoher. (for those that don't know orthoginal means
00091       for matrix A: A * transpose(A) = I where I is the identity matrix).
00092 
00093     */
00094 
00095     double p = ((-1) * in[0] + (0) * in[1] + (1) * in[2]
00096                 + (-1) * in[3] + (0) * in[4] + (1) * in[5]
00097                 + (-1) * in[6] + (0) * in[7] + (1) * in[8]) / (3.0 * pixelResolution);
00098 
00099     double q = ((-1) * in[0] + (-1) * in[1] + (-1) * in[2]
00100                 + (0) * in[3] + (0) * in[4] + (0) * in[5]
00101                 + (1) * in[6] + (1) * in[7] + (1) * in[8]) / (3.0 * pixelResolution);
00102 
00103     /* after we hit them by the gradients the formula in order to make the shade is
00104 
00105                           1 + p0*p + q0*q
00106     shade =  -------------------------------------------------
00107                sqrt(1 + p*p + Q*q) + sqrt(1 + p0*p0 + q0*q0)
00108 
00109     where p0 = -cos( sun azimuth ) * tan( solar elevation ) and
00110           q0 = -sin( sun azimuth ) * tan( solar elevation )
00111 
00112     and p and q are the two orthogonal gradients of the data (calculated above)
00113 
00114     this equation comes from
00115     Horn, B.K.P. (1982). "Hill shading and the reflectance map". Geo-processing, v. 2, no. 1, p. 65-146.
00116 
00117     It is avaliable online at http://people.csail.mit.edu/bkph/papers/Hill-Shading.pdf
00118     */
00119     double p0 = -cos(saz) * tan(zenith);
00120     double q0 = -sin(saz) * tan(zenith);
00121 
00122     double numerator = 1.0 + p0 * p + q0 * q;
00123 
00124     double denominator = sqrt(1 + p * p + q * q) + sqrt(1 + p0 * p0 + q0 * q0);
00125 
00126     v = numerator / denominator;
00127 
00128   }
00129 }