예제 #1
0
bool BandMath::createReturnValue(string partialResultsName)
{
   // Set the short and long result names
   FactoryResource<Filename> pFilename;
   string shortResultsName;
   string longResultsName;
   if (pFilename.get() != NULL)
   {
      pFilename->setFullPathAndName(mpCube->getFilename());
      shortResultsName = pFilename->getTitle() + " = " + partialResultsName;
      longResultsName = pFilename->getPath() + "/" + pFilename->getTitle() + " = " + partialResultsName;
   }
   mResultsName = longResultsName;

   const RasterDataDescriptor* pOrigDescriptor = dynamic_cast<RasterDataDescriptor*>(mpCube->getDataDescriptor());
   const vector<DimensionDescriptor>& origRows = pOrigDescriptor->getRows();
   const vector<DimensionDescriptor>& origColumns = pOrigDescriptor->getColumns();

   mpResultData = NULL;

   unsigned int bandCount = mCubeBands;
   if (mbCubeMath == false)
   {
      bandCount = 1;
   }

   RasterElement* pParent = NULL;
   if (mbAsLayerOnExistingView)
   {
      pParent = mpCube;
   }
   RasterElement* pRaster = RasterUtilities::createRasterElement(mResultsName, origRows.size(),
      origColumns.size(), bandCount, FLT4BYTES, BIP, pOrigDescriptor->getProcessingLocation() == IN_MEMORY, pParent);

   if (pRaster == NULL)
   {
      mstrProgressString = "Error creating result raster element";
      meGabbiness = ERRORS;
      displayErrorMessage();
      mbError = true;
      return false;
   }

   if (!mbAsLayerOnExistingView)
   {
      // need to copy classification since parent was NULL in call to createRasterElement
      pRaster->copyClassification(mpCube);

      // make copies of existing GcpLists only if going into a new view
      vector<DataElement*> gcps = mpDataModel->getElements(mpCube, "GcpList");
      if (!gcps.empty())
      {
         vector<DataElement*>::iterator iter;
         for (iter = gcps.begin(); iter != gcps.end(); ++iter)
         {
            GcpList* theGcp = dynamic_cast<GcpList*>(*iter);
            theGcp->copy(theGcp->getName(), pRaster);
         }
      }
   }

   mpResultData = pRaster;

   RasterDataDescriptor* pDescriptor = dynamic_cast<RasterDataDescriptor*>
      (mpResultData->getDataDescriptor());
   if (pDescriptor != NULL)
   {
      // Rows
      vector<DimensionDescriptor> rows = pDescriptor->getRows();
      for (unsigned int i = 0; i < origRows.size(); ++i)
      {
         // Original number
         DimensionDescriptor origRow = origRows[i];
         if (origRow.isOriginalNumberValid() == true)
         {
            rows[i].setOriginalNumber(origRow.getOriginalNumber());
         }
      }
      pDescriptor->setRows(rows);

      // Columns
      vector<DimensionDescriptor> columns = pDescriptor->getColumns();
      for (unsigned int i = 0; i < origColumns.size(); ++i)
      {
         // Original number
         DimensionDescriptor origColumn = origColumns[i];
         if (origColumn.isOriginalNumberValid() == true)
         {
            columns[i].setOriginalNumber(origColumn.getOriginalNumber());
         }
      }
      pDescriptor->setColumns(columns);
   }

   return true;
}
예제 #2
0
bool GcpGeoreference::execute(PlugInArgList* pInArgList, PlugInArgList* pOutArgList)
{
   StepResource pStep("Run GCP Georeference", "app", "296120A0-1CD5-467E-A501-934BCA7775EA");

   Progress* pProgress = pInArgList->getPlugInArgValue<Progress>(Executable::ProgressArg());
   mpProgress = pProgress;

   FAIL_IF(!isBatch(), "Interactive mode is not supported.", return false);

   int numPoints;
   PlugInArg* pArg = NULL;

   mpRaster = pInArgList->getPlugInArgValue<RasterElement>(Executable::DataElementArg());
   FAIL_IF(mpRaster == NULL, "Unable to find raster element input", return false);

   GcpList* pGcpList = NULL;
   if (mpGui != NULL)
   {
      mOrder = mpGui->getOrder();

      string gcpListName = mpGui->getGcpListName();
      if (gcpListName.empty() == false)
      {
         pGcpList = static_cast<GcpList*>(mpDataModel->getElement(gcpListName,
            TypeConverter::toString<GcpList>(), mpRaster));
      }
   }
   else
   {
      pInArgList->getPlugInArgValue<int>("Order", mOrder);
      pGcpList = pInArgList->getPlugInArgValue<GcpList>(Georeference::GcpListArg());
   }

   if (pGcpList != NULL)
   {
      pStep->addProperty("gcpList", pGcpList->getName());
   }
   pStep->addProperty("polynomialOrder", mOrder);

   FAIL_IF(pGcpList == NULL, "Unable to find GCP list.", return false);

   if ((mOrder <= 0) || (mOrder > MAX_ORDER))
   {
      if (mpProgress)
      {
         stringstream buffer;
         buffer << "Invalid polynomial order: " << mOrder << "\nThe order must be between 1 and " <<
            MAX_ORDER << " (inclusive)";
         mpProgress->updateProgress(buffer.str(), 0, ERRORS);
      }
      pStep->addProperty("Max Polynomial Order", MAX_ORDER);
      pStep->finalize(Message::Failure, "Invalid polynomial order");
      return false;
   }

   mReverseOrder = min(MAX_ORDER, mOrder+1);

   int numCoeffs = COEFFS_FOR_ORDER(mOrder);
   numPoints = pGcpList->getSelectedPoints().size();
   if (numPoints < numCoeffs)
   {
      if (mpProgress)
      {
         stringstream buffer;
         buffer << "Too few ground control points.\n" << "A polynomial fit of order " << mOrder <<
            "\nrequires at least " << numCoeffs << " GCPs.";
         mpProgress->updateProgress(buffer.str(), 0, ERRORS);
      }
      pStep->addProperty("Required GCPs", numCoeffs);
      pStep->finalize(Message::Failure, "Too few ground control points");
      return false;
   }

   int numReverseCoeffs = COEFFS_FOR_ORDER(mReverseOrder);
   vector<double> latCoeffs(numCoeffs);
   vector<double> lonCoeffs(numCoeffs);
   vector<double> pXCoeffs(numReverseCoeffs);
   vector<double> pYCoeffs(numReverseCoeffs);
   vector<LocationType> latlonValues(numPoints);
   vector<LocationType> pixelValues(numPoints);
   double maxLonSeparation(0.0);

   list<GcpPoint>::const_iterator it;
   unsigned int i;
   unsigned int j;
   for (i = 0, it = pGcpList->getSelectedPoints().begin(); 
               it != pGcpList->getSelectedPoints().end();
               ++it, ++i)
   {
      pixelValues[i] = it->mPixel;
      latlonValues[i] = it->mCoordinate;
   }

   // Find the maximum separation to determine if it is the antimeridian or the poles
   for (i = 0; i < pGcpList->getSelectedPoints().size(); ++i)
   {
      for (j = i + 1; j < pGcpList->getSelectedPoints().size(); ++j)
      {
         if (fabs(latlonValues[i].mY - latlonValues[j].mY) > maxLonSeparation)
         {
            maxLonSeparation = fabs(latlonValues[i].mY - latlonValues[j].mY);
         }
      }
   }

   bool badValues = true;
   bool badPixelValues = true;
   for (i = 0; i < pGcpList->getSelectedPoints().size(); ++i)
   {
      for (j = i + 1; j < pGcpList->getSelectedPoints().size(); ++j)
      {
         if (fabs(latlonValues[i].mX - latlonValues[j].mX) > 1e-20)
         {
            badValues = false;
            break;
         }
         if (fabs(latlonValues[i].mY - latlonValues[j].mY) > 1e-20)
         {
            badValues = false;
            break;
         }
      }
   }

   #pragma message(__FILE__ "(" STRING(__LINE__) ") : warning : This is a short term solution " \
   "the draw method in LatLonLayer needs to be changed! (mconsidi)")
   // Special lon cases of the Antimeridian and poles
   // A value of more than 180.0 in maxLonSeparation indicates a special condition
   if (maxLonSeparation > 180.0)
   {
      for (i = 0; i < pGcpList->getSelectedPoints().size(); ++i)
      {
         if (latlonValues[i].mY < 0.0)
         {
            latlonValues[i].mY = 360.0 + latlonValues[i].mY;
         }
      }
   }

   if (badValues)
   {
      mMessageText = "All GCPs have the same value.";
      if (mpProgress)
      {
         mpProgress->updateProgress(mMessageText, 0, ERRORS);
      }
      pStep->finalize(Message::Failure, mMessageText);
      return false;
   }

   for (i = 0; i < pGcpList->getSelectedPoints().size(); ++i)
   {
      for (j = i + 1; j < pGcpList->getSelectedPoints().size(); ++j)
      {
         if (fabs(pixelValues[i].mX - pixelValues[j].mX) > 1e-20)
         {
            badPixelValues = false;
            break;
         }
         if (fabs(pixelValues[i].mY - pixelValues[j].mY) > 1e-20)
         {
            badPixelValues = false;
            break;
         }
      }
   }

   if (badPixelValues)
   {
      mMessageText = "All GCPs have the same pixel location value.";
      if (mpProgress)
      {
         mpProgress->updateProgress(mMessageText, 0, ERRORS);
      }
      pStep->finalize(Message::Failure, mMessageText);
      return false;
   }

   mMessageText = "GcpGeoreference started.";
   if (mpProgress)
   {
      mpProgress->updateProgress(mMessageText, 0, NORMAL);
   }

   bool success = computeFit(pixelValues, latlonValues, 0, latCoeffs);
   if (success)
   {
      success = computeFit(pixelValues, latlonValues, 1, lonCoeffs);
   }

   const RasterDataDescriptor* pDescriptor = dynamic_cast<const RasterDataDescriptor*>(mpRaster->getDataDescriptor());
   if (pDescriptor != NULL)
   {
      setCubeSize(pDescriptor->getRowCount(), pDescriptor->getColumnCount());
   }

   copy(latCoeffs.begin(), latCoeffs.end(), mLatCoefficients);
   copy(lonCoeffs.begin(), lonCoeffs.end(), mLonCoefficients);

   // Generate a gridSize x gridSize grid of GCPs calculated from the 
   // frontwards (pixel-to-lat/lon) polynomial. Then generate the reverse 
   // (lat/lon-to-pixel) polynomial from this grid of GCPs.
   const int gridSize = 30;
   pixelValues.clear();
   latlonValues.clear();
   for (i = 0; i < gridSize; ++i)
   {
      for (j = 0; j < gridSize; ++j)
      {
         LocationType pixel;
         LocationType latlon;
         pixel.mX = i * mNumColumns / gridSize;
         pixel.mY = j * mNumRows / gridSize;
         latlon.mX = computePolynomial(pixel, mOrder, latCoeffs);
         latlon.mY = computePolynomial(pixel, mOrder, lonCoeffs);
         pixelValues.push_back(pixel);
         latlonValues.push_back(latlon);
      }
   }

   if (success)
   {
      success = computeFit(latlonValues, pixelValues, 0, pXCoeffs);
   }
   if (success)
   {
      success = computeFit(latlonValues, pixelValues, 1, pYCoeffs);
   }

   copy(pXCoeffs.begin(), pXCoeffs.end(), mXCoefficients);
   copy(pYCoeffs.begin(), pYCoeffs.end(), mYCoefficients);

   list<GcpPoint> newPoints;
   list<GcpPoint>::iterator npIter;
   for (i = 0, it = pGcpList->getSelectedPoints().begin(); it != pGcpList->getSelectedPoints().end(); ++it, ++i)
   {
      GcpPoint newPoint;
      newPoint.mPixel.mX = it->mPixel.mX;
      newPoint.mPixel.mY = it->mPixel.mY;
      newPoint.mCoordinate.mX = it->mCoordinate.mX;
      newPoint.mCoordinate.mY = it->mCoordinate.mY;
      // If maxLonSeparation > 180.0 then this is a special case
      if (maxLonSeparation > 180.0 && newPoint.mCoordinate.mY < 0.0)
      {
         newPoint.mCoordinate.mY = newPoint.mCoordinate.mY + 360.0;
      }
      LocationType newPixel = geoToPixel(newPoint.mCoordinate);
      newPoint.mRmsError.mX = fabs(newPixel.mX - newPoint.mPixel.mX);
      newPoint.mRmsError.mY = fabs(newPixel.mY - newPoint.mPixel.mY);
      newPoints.push_back(newPoint);
   }

   pGcpList->clearPoints();
   pGcpList->addPoints(newPoints);

   mpGui = NULL;

   if (mpRaster != NULL)
   {
      mpRaster->setGeoreferencePlugin(this);
   }

   pStep->finalize(Message::Success);
   if (mpProgress)
   {
      mpProgress->updateProgress("GcpGeoreference finished.", 0, NORMAL);
   }

   return true;
}