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