/** * Calculates the lat/lon of the ControlNet. * * @param incubes The filename of the list of cubes in the ControlNet * @param cnet The filename of the ControlNet */ void setControlPointLatLon(SerialNumberList &snl, ControlNet &cnet) { CubeManager manager; manager.SetNumOpenCubes(50); //Should keep memory usage to around 1GB Progress progress; progress.SetText("Calculating Lat/Lon"); progress.SetMaximumSteps(cnet.GetNumPoints()); progress.CheckStatus(); for (int cp = 0; cp < cnet.GetNumPoints(); cp++) { ControlPoint *point = cnet.GetPoint(cp); ControlMeasure *cm = point->GetRefMeasure(); Cube *cube = manager.OpenCube(snl.FileName(cm->GetCubeSerialNumber())); try { cube->camera()->SetImage(cm->GetSample(), cm->GetLine()); g_surfacePoints[point->GetId()] = cube->camera()->GetSurfacePoint(); } catch (IException &e) { QString msg = "Unable to create camera for cube file ["; msg += snl.FileName(cm->GetCubeSerialNumber()) + "]"; throw IException(e, IException::Unknown, msg, _FILEINFO_); } cube = NULL; //Do not delete, manager still has ownership progress.CheckStatus(); } manager.CleanCubes(); }
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; }
/** * FindCnetRef traverses all the control points and measures in the network and checks for * valid Measure which passes the Emission Incidence Angle, DN value tests and chooses the * measure with the best Resolution criteria as the reference. Creates a new control network * with these adjustments. * * @author Sharmila Prasad (5/25/2010) * @history 2010-10-04 Sharmila Prasad - Modified for Binary CNet (Edit Lock) * * @param pNewNet - Modified output Control Net * */ void CnetRefByResolution::FindCnetRef(ControlNet &pNewNet) { // Process each existing control point in the network int iPointsModified = 0; int iMeasuresModified = 0; int iRefChanged = 0; //Status Report mStatus.SetText("Choosing Reference by Resolution..."); mStatus.SetMaximumSteps(pNewNet.GetNumPoints()); mStatus.CheckStatus(); //mPvlLog += GetStdOptions(); for (int point = 0; point < pNewNet.GetNumPoints(); ++point) { ControlPoint *newPnt = pNewNet.GetPoint(point); bool bError = false; // Create a copy of original control point const ControlPoint origPnt(*newPnt); mdResVector.clear(); // Logging PvlObject pvlPointObj("PointDetails"); pvlPointObj += Isis::PvlKeyword("PointId", newPnt->GetId()); // Edit Lock Option bool bPntEditLock = newPnt->IsEditLocked(); if (!bPntEditLock) { newPnt->SetDateTime(Application::DateTime()); } else { pvlPointObj += Isis::PvlKeyword("Reference", "No Change, PointEditLock"); } int iNumMeasuresLocked = newPnt->GetNumLockedMeasures(); bool bRefLocked = newPnt->GetRefMeasure()->IsEditLocked(); int numMeasures = newPnt->GetNumMeasures(); int iRefIndex = -1; if (newPnt->IsReferenceExplicit()) iRefIndex = newPnt->IndexOfRefMeasure(); QString istrTemp; std::vector <PvlGroup> pvlGrpVector; int iBestIndex = 0; // Only perform the interest operation on points of type "Free" and // Points having atleast 1 measure and Point is not Ignored // Check for EditLock in the Measures and also verfify that // only a Reference Measure can be Locked else error if (!newPnt->IsIgnored() && newPnt->GetType() == ControlPoint::Free && numMeasures > 0 && (iNumMeasuresLocked == 0 || (iNumMeasuresLocked > 0 && bRefLocked))) { int iNumIgnore = 0; QString istrTemp; for (int measure = 0; measure < newPnt->GetNumMeasures(); ++measure) { ControlMeasure *newMsr = newPnt->GetMeasure(measure); bool bMeasureLocked = newMsr->IsEditLocked(); double dSample = newMsr->GetSample(); double dLine = newMsr->GetLine(); QString sn = newMsr->GetCubeSerialNumber(); if (!bPntEditLock && !bMeasureLocked) { newMsr->SetDateTime(Application::DateTime()); newMsr->SetChooserName("Application cnetref(Resolution)"); } // Log PvlGroup pvlMeasureGrp("MeasureDetails"); pvlMeasureGrp += Isis::PvlKeyword("SerialNum", sn); pvlMeasureGrp += Isis::PvlKeyword("OriginalLocation", LocationString(dSample, dLine)); if (bMeasureLocked) pvlMeasureGrp += Isis::PvlKeyword("EditLock", "True"); if (!newMsr->IsIgnored()) { Cube *measureCube = mCubeMgr.OpenCube(mSerialNumbers.FileName(sn)); MeasureValidationResults results = ValidStandardOptions(newMsr, measureCube, &pvlMeasureGrp); if (!results.isValid()) { if (bPntEditLock) { pvlMeasureGrp += Isis::PvlKeyword("UnIgnored", "Failed Validation Test but not Ignored as Point EditLock is True"); } else if (bMeasureLocked) { pvlMeasureGrp += Isis::PvlKeyword("UnIgnored", "Failed Validation Test but not Ignored as Measure EditLock is True"); } else { pvlMeasureGrp += Isis::PvlKeyword("Ignored", "Failed Validation Test"); newMsr->SetIgnored(true); iNumIgnore++; } } // valid measure else { if (!bPntEditLock && !bRefLocked) { newMsr->SetType(ControlMeasure::Candidate); newMsr->SetIgnored(false); mdResVector.push_back(mdResolution); } } } // Ignore == false else { pvlMeasureGrp += Isis::PvlKeyword("Ignored", "Originally Ignored"); iNumIgnore++; } if (newMsr != origPnt.GetMeasure(measure)) { iMeasuresModified++; } //newPnt.UpdateMeasure(newMsr); // Redesign fixed this pvlGrpVector.push_back(pvlMeasureGrp); }// end Measure if ((newPnt->GetNumMeasures() - iNumIgnore) < 2) { if (bPntEditLock) { pvlPointObj += Isis::PvlKeyword("UnIgnored", "Good Measures less than 2 but not Ignored as Point EditLock is True"); } else { newPnt->SetIgnored(true); pvlPointObj += Isis::PvlKeyword("Ignored", "Good Measures less than 2"); } } // Set the Reference if the Point is unlocked and Reference measure is unlocked if (!newPnt->IsIgnored() && !bPntEditLock && !bRefLocked) { iBestIndex = GetReferenceByResolution(newPnt); if (iBestIndex >= 0 && !newPnt->GetMeasure(iBestIndex)->IsIgnored()) { newPnt->SetRefMeasure(iBestIndex); //newPnt.UpdateMeasure(cm); // Redesign fixed this pvlGrpVector[iBestIndex] += Isis::PvlKeyword("Reference", "true"); } else { if (iBestIndex < 0 && meType == Range) { pvlPointObj += Isis::PvlKeyword("NOTE", "No Valid Measures within the Resolution Range. Reference defaulted to the first Measure"); } iBestIndex = 0; newPnt->SetRefMeasure(iBestIndex); //newPnt.UpdateMeasure(cm); // Redesign fixed this // Log info, if Point not locked, apriori source == Reference and a new reference if (iRefIndex != iBestIndex && newPnt->GetAprioriSurfacePointSource() == ControlPoint::SurfacePointSource::Reference) { pvlGrpVector[iBestIndex] += Isis::PvlKeyword("AprioriSource", "Reference is the source and has changed"); } } } for (int i = 0; i < newPnt->GetNumMeasures(); i++) { pvlPointObj += pvlGrpVector[i]; } } // end Free else { int iComment = 0; if (numMeasures == 0) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "No Measures in the Point"); } if (newPnt->IsIgnored()) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "Point was originally Ignored"); } if (newPnt->GetType() == ControlPoint::Fixed) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "Fixed Point"); } else if (newPnt->GetType() == ControlPoint::Constrained) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "Constrained Point"); } if (iNumMeasuresLocked > 0 && !bRefLocked) { pvlPointObj += Isis::PvlKeyword("Error", "Point has a Measure with EditLock set to true " "but the Reference is not Locked"); bError = true; } else { for (int measure = 0; measure < newPnt->GetNumMeasures(); measure++) { ControlMeasure *cm = newPnt->GetMeasure(iBestIndex); cm->SetDateTime(Application::DateTime()); cm->SetChooserName("Application cnetref(Resolution)"); //newPnt.UpdateMeasure(cm); // Redesign fixed this } } } if (*newPnt != origPnt) { iPointsModified++; } if (!bError && !newPnt->IsIgnored() && newPnt->IsReferenceExplicit() && iBestIndex != iRefIndex && !bPntEditLock && !bRefLocked) { iRefChanged++; PvlGroup pvlRefChangeGrp("ReferenceChangeDetails"); if (iRefIndex >= 0) { pvlRefChangeGrp += Isis::PvlKeyword("PrevSerialNumber", origPnt.GetMeasure(iRefIndex)->GetCubeSerialNumber()); pvlRefChangeGrp += Isis::PvlKeyword("PrevResolution", toString(mdResVector[iRefIndex])); istrTemp = QString((int)origPnt.GetMeasure(iRefIndex)->GetSample()); istrTemp += ","; istrTemp += QString((int)origPnt.GetMeasure(iRefIndex)->GetLine()); pvlRefChangeGrp += Isis::PvlKeyword("PrevLocation", istrTemp); } else { pvlRefChangeGrp += Isis::PvlKeyword("PrevReference", "Not Set"); } pvlRefChangeGrp += Isis::PvlKeyword("NewSerialNumber", newPnt->GetMeasure(iBestIndex)->GetCubeSerialNumber()); QString sKeyName = "NewHighestResolution"; if (meType == Low) { sKeyName = "NewLeastResolution"; } else if (meType == Mean) { pvlRefChangeGrp += Isis::PvlKeyword("MeanResolution", toString(GetMeanResolution())); sKeyName = "NewResolutionNeartoMean"; } else if (meType == Nearest) { sKeyName = "NewResolutionNeartoValue"; } else if (meType == Range) { sKeyName = "NewResolutionInRange"; } pvlRefChangeGrp += Isis::PvlKeyword(sKeyName, toString(mdResVector[iBestIndex])); istrTemp = QString((int)newPnt->GetMeasure(iBestIndex)->GetSample()); istrTemp += ","; istrTemp += QString((int)newPnt->GetMeasure(iBestIndex)->GetLine()); pvlRefChangeGrp += Isis::PvlKeyword("NewLocation", istrTemp); pvlPointObj += pvlRefChangeGrp; } else { pvlPointObj += Isis::PvlKeyword("Reference", "No Change"); } //pNewNet.UpdatePoint(newPnt); // Redesign fixed this mPvlLog += pvlPointObj; mStatus.CheckStatus(); }// end Point // CnetRef Change Statistics mStatisticsGrp += Isis::PvlKeyword("PointsModified", toString(iPointsModified)); mStatisticsGrp += Isis::PvlKeyword("ReferenceChanged", toString(iRefChanged)); mStatisticsGrp += Isis::PvlKeyword("MeasuresModified", toString(iMeasuresModified)); mPvlLog += mStatisticsGrp; }
/** The ISIS smtk main application */ void IsisMain() { UserInterface &ui = Application::GetUserInterface(); // Open the first cube. It is the left hand image. Cube lhImage; CubeAttributeInput &attLeft = ui.GetInputAttribute("FROM"); vector<QString> bandLeft = attLeft.bands(); lhImage.setVirtualBands(bandLeft); lhImage.open(ui.GetFileName("FROM"),"r"); // Open the second cube, it is geomertricallty altered. We will be matching the // first to this one by attempting to compute a sample/line offsets Cube rhImage; CubeAttributeInput &attRight = ui.GetInputAttribute("MATCH"); vector<QString> bandRight = attRight.bands(); rhImage.setVirtualBands(bandRight); rhImage.open(ui.GetFileName("MATCH"),"r"); // Ensure only single bands if (lhImage.bandCount() != 1 || rhImage.bandCount() != 1) { QString msg = "Input Cubes must have only one band!"; throw IException(IException::User,msg,_FILEINFO_); } // Both images must have a Camera and can also have a Projection. We will // only deal with a Camera, however as a projected, non-mosaicked image // uses a Projection internal to the Camera object. Camera *lhCamera = NULL; Camera *rhCamera = NULL; try { lhCamera = lhImage.camera(); rhCamera = rhImage.camera(); } catch (IException &ie) { QString msg = "Both input images must have a camera"; throw IException(ie, IException::User, msg, _FILEINFO_); } // Since we are generating a DEM, we must turn off any existing // DEM that may have been initialized with spiceinit. lhCamera->IgnoreElevationModel(true); rhCamera->IgnoreElevationModel(true); // Get serial number QString serialLeft = SerialNumber::Compose(lhImage, true); QString serialRight = SerialNumber::Compose(rhImage, true); // This still precludes band to band registrations. if (serialLeft == serialRight) { QString sLeft = FileName(lhImage.fileName()).name(); QString sRight = FileName(rhImage.fileName()).name(); if (sLeft == sRight) { QString msg = "Cube Serial Numbers must be unique - FROM=" + serialLeft + ", MATCH=" + serialRight; throw IException(IException::User,msg,_FILEINFO_); } serialLeft = sLeft; serialRight = sRight; } Progress prog; prog.SetText("Finding Initial Seeds"); int nl = lhImage.lineCount(); int ns = lhImage.sampleCount(); BigInt numAttemptedInitialPoints = 0; // Declare Gruen matcher SmtkMatcher matcher(ui.GetFileName("REGDEF"), &lhImage, &rhImage); // Get line/sample linc/sinc parameters int space = ui.GetInteger("SPACE"); int linc (space), sinc(space); // Do we have a seed points from a control net file? bool useseed = ui.WasEntered("CNET"); // Base points on an input cnet SmtkQStack gstack; double lastEigen(0.0); if (useseed) { ControlNet cnet(ui.GetFileName("CNET")); prog.SetMaximumSteps(cnet.GetNumPoints()); prog.CheckStatus(); gstack.reserve(cnet.GetNumPoints()); for (int cpIndex = 0; cpIndex < cnet.GetNumPoints(); cpIndex ++) { ControlPoint *cp = cnet.GetPoint(cpIndex); if (!cp->IsIgnored()) { ControlMeasure *cmLeft(0), *cmRight(0); for(int cmIndex = 0; cmIndex < cp->GetNumMeasures(); cmIndex ++) { ControlMeasure *cm = cp->GetMeasure(cmIndex); if (!cm->IsIgnored()) { if (cm->GetCubeSerialNumber() == serialLeft) cmLeft = cp->GetMeasure(cmIndex); if (cm->GetCubeSerialNumber() == serialRight) cmRight = cp->GetMeasure(cmIndex); } } // If we have both left and right images in the control point, save it if ( (cmLeft != 0) && (cmRight != 0) ) { Coordinate left = Coordinate(cmLeft->GetLine(), cmLeft->GetSample()); Coordinate right = Coordinate(cmRight->GetLine(), cmRight->GetSample()); SmtkPoint spnt = matcher.Create(left, right); // Insert the point (unregistered) if ( spnt.isValid() ) { int line = (int) cmLeft->GetLine(); int samp = (int) cmLeft->GetSample(); matcher.isValid(spnt); gstack.insert(qMakePair(line, samp), spnt); lastEigen = spnt.GoodnessOfFit(); } } } prog.CheckStatus(); } } else { // We want to create a grid of control points that is N rows by M columns. int rows = (lhImage.lineCount() + linc - 1)/linc; int cols = (lhImage.sampleCount() + sinc - 1)/sinc; prog.SetMaximumSteps(rows * cols); prog.CheckStatus(); // First pass stack and eigen value statistics SmtkQStack fpass; fpass.reserve(rows * cols); Statistics temp_mev; // Loop through grid of points and get statistics to compute // initial set of points for (int line = linc / 2 + 1; line < nl; line += linc) { for (int samp = sinc / 2 + 1 ; samp < ns; samp += sinc) { numAttemptedInitialPoints ++; SmtkPoint spnt = matcher.Register(Coordinate(line,samp)); if ( spnt.isValid() ) { matcher.isValid(spnt); fpass.insert(qMakePair(line, samp), spnt); temp_mev.AddData(spnt.GoodnessOfFit()); } prog.CheckStatus(); } } // Now select a subset of fpass points as the seed points cout << "Number of Potential Seed Points: " << fpass.size() << "\n"; cout << "Min / Max Eigenvalues Matched: " << temp_mev.Minimum() << ", " << temp_mev.Maximum() << "\n"; // How many seed points are requested double nseed = ui.GetDouble("NSEED"); int inseed; if (nseed >= 1.0) inseed = (int) nseed; else if (nseed > 0.0) inseed = (int) (nseed * (double) (fpass.size())); else inseed = (int) ((double) (fpass.size()) * 0.05); double seedsample = ui.GetDouble("SEEDSAMPLE"); // Generate a new stack gstack.reserve(inseed); while ((gstack.size() < inseed) && (!fpass.isEmpty() )) { SmtkQStack::iterator bestm; if (seedsample <= 0.0) { bestm = matcher.FindSmallestEV(fpass); } else { bestm = matcher.FindExpDistEV(fpass, seedsample, temp_mev.Minimum(), temp_mev.Maximum()); } // Add point to stack if (bestm != fpass.end()) { Coordinate right = bestm.value().getRight(); matcher.isValid(bestm.value()); gstack.insert(bestm.key(), bestm.value()); lastEigen = bestm.value().GoodnessOfFit(); fpass.erase(bestm); } } // If a user wants to see the seed network, write it out here if (ui.WasEntered("OSEEDNET")) { WriteCnet(ui.GetFileName("OSEEDNET"), gstack, lhCamera->target()->name(), serialLeft, serialRight); } } /////////////////////////////////////////////////////////////////////// // All done with seed points. Sanity check ensures we actually found // some. /////////////////////////////////////////////////////////////////////// if (gstack.size() <= 0) { QString msg = "No seed points found - may need to check Gruen parameters."; throw IException(IException::User, msg, _FILEINFO_); } // Report seed point status if (!useseed) { cout << "Number of Seed Points used: " << gstack.size() << "\n"; cout << "EV of last Seed Point: " << lastEigen << "\n"; } else { cout << "Number of Manual Seed Points: " << gstack.size() << "\n"; } // Use seed points (in stack) to grow SmtkQStack bmf; bmf.reserve(gstack.size()); // Probably need much more but for starters... BigInt numOrigPoints = gstack.size(); BigInt passpix2 = 0; int subcbox = ui.GetInteger("SUBCBOX"); int halfBox((subcbox-1)/2); while (!gstack.isEmpty()) { SmtkQStackIter cstack = matcher.FindSmallestEV(gstack); // Print number on stack if ((gstack.size() % 1000) == 0) { cout << "Number on Stack: " << gstack.size() << ". " << cstack.value().GoodnessOfFit() << "\n"; } // Test to see if already determined SmtkQStackIter bmfPt = bmf.find(cstack.key()); if (bmfPt == bmf.end()) { // Its not in the final stack, process it // Retrieve the point SmtkPoint spnt = cstack.value(); // Register if its not already registered if (!spnt.isRegistered()) { spnt = matcher.Register(spnt, spnt.getAffine()); } // Still must check for validity if the point was just registered, // otherwise should be good if ( spnt.isValid() ) { passpix2++; bmf.insert(cstack.key(), spnt); // inserts (0,0) offset excluded below int line = cstack.key().first; int sample = cstack.key().second; // Determine match points double eigen(spnt.GoodnessOfFit()); for (int sampBox = -halfBox ; sampBox <= halfBox ; sampBox++ ) { int csamp = sample + sampBox; for (int lineBox = -halfBox ; lineBox <= halfBox ; lineBox++) { int cline = line + lineBox; if ( !( (sampBox == 0) && (lineBox == 0)) ) {// Already added above SmtkQPair dupPair(cline, csamp); SmtkQStackIter temp = bmf.find(dupPair); SmtkPoint bmfpnt; if (temp != bmf.end()) { if (temp.value().GoodnessOfFit() > eigen) { // Create cloned point with better fit bmfpnt = matcher.Clone(spnt, Coordinate(cline,csamp)); } } else { // ISIS2 is BMF(SAMP,LINE,7) .EQ VALID_MAX4) // Clone new point for insert bmfpnt = matcher.Clone(spnt, Coordinate(cline,csamp)); } // Add if good point if (bmfpnt.isValid()) { bmf.insert(dupPair, bmfpnt); } } } } // Grow stack with spacing adding info to stack for (int i = -1 ; i <= 1 ; i ++) { // Sample for (int j = -1 ; j <= 1 ; j ++) { // Line // Don't re-add the original sample, line if ( !((i == 0) && (j == 0)) ) { // Grow based upon spacing double ssamp = sample + (i * space); double sline = line + (j * space); Coordinate pnt = Coordinate(sline, ssamp); SmtkPoint gpnt = matcher.Clone(spnt, pnt); if ( gpnt.isValid() ) { SmtkQPair growpt((int) sline, (int) ssamp); // double check we don't have a finalized result at this position SmtkQStackIter temp = bmf.find(growpt); if(temp == bmf.end()) { gstack.insert(growpt, gpnt); } } } } } } } // Remove the current point from the grow stack (hole) gstack.erase(cstack); } ///////////////////////////////////////////////////////////////////////// // All done with creating points. Perform output options. ///////////////////////////////////////////////////////////////////////// // If a TO parameter was specified, create DEM with errors if (ui.WasEntered("TO")) { // Create the output DEM cout << "\nCreating output DEM from " << bmf.size() << " points.\n"; Process p; Cube *icube = p.SetInputCube("FROM"); Cube *ocube = p.SetOutputCube("TO", icube->sampleCount(), icube->lineCount(), 3); p.ClearInputCubes(); int boxsize = ui.GetInteger("BOXSIZE"); double plotdist = ui.GetDouble("PLOTDIST"); TileManager dem(*ocube), eigen(*ocube), stErr(*ocube); dem.SetTile(1, 1); // DEM Data/elevation stErr.SetTile(1, 2); // Error in stereo computation eigen.SetTile(1, 3); // Eigenvalue of the solution int nBTiles(eigen.Tiles()/3); // Total tiles / 3 bands prog.SetText("Creating DEM"); prog.SetMaximumSteps(nBTiles); prog.CheckStatus(); Statistics stAng; while ( !eigen.end() ) { // Must use the last band for this!! PointPlot tm = for_each(bmf.begin(), bmf.end(), PointPlot(dem, plotdist)); tm.FillPoints(*lhCamera, *rhCamera, boxsize, dem, stErr, eigen, &stAng); ocube->write(dem); ocube->write(stErr); ocube->write(eigen); dem.next(); stErr.next(); eigen.next(); prog.CheckStatus(); } // Report Stereo separation angles PvlGroup stresultsPvl("StereoSeparationAngle"); stresultsPvl += PvlKeyword("Minimum", toString(stAng.Minimum()), "deg"); stresultsPvl += PvlKeyword("Average", toString(stAng.Average()), "deg"); stresultsPvl += PvlKeyword("Maximum", toString(stAng.Maximum()), "deg"); stresultsPvl += PvlKeyword("StandardDeviation", toString(stAng.StandardDeviation()), "deg"); Application::Log(stresultsPvl); // Update the label with BandBin keywords PvlKeyword filter("FilterName", "Elevation", "meters"); filter.addValue("ElevationError", "meters"); filter.addValue("GoodnessOfFit", "unitless"); PvlKeyword center("Center", "1.0"); center.addValue("1.0"); center.addValue("1.0"); PvlGroup &bandbin = ocube->label()->findGroup("BandBin", PvlObject::Traverse); bandbin.addKeyword(filter, PvlContainer::Replace); bandbin.addKeyword(center, PvlContainer::Replace); center.setName("Width"); bandbin.addKeyword(center, PvlContainer::Replace); p.EndProcess(); } // If a cnet file was entered, write the ControlNet pvl to the file if (ui.WasEntered("ONET")) { WriteCnet(ui.GetFileName("ONET"), bmf, lhCamera->target()->name(), serialLeft, serialRight); } // Create output data PvlGroup totalPointsPvl("Totals"); totalPointsPvl += PvlKeyword("AttemptedPoints", toString(numAttemptedInitialPoints)); totalPointsPvl += PvlKeyword("InitialSuccesses", toString(numOrigPoints)); totalPointsPvl += PvlKeyword("GrowSuccesses", toString(passpix2)); totalPointsPvl += PvlKeyword("ResultingPoints", toString(bmf.size())); Application::Log(totalPointsPvl); Pvl arPvl = matcher.RegistrationStatistics(); PvlGroup smtkresultsPvl("SmtkResults"); smtkresultsPvl += PvlKeyword("SpiceOffImage", toString(matcher.OffImageErrorCount())); smtkresultsPvl += PvlKeyword("SpiceDistanceError", toString(matcher.SpiceErrorCount())); arPvl.addGroup(smtkresultsPvl); for(int i = 0; i < arPvl.groups(); i++) { Application::Log(arPvl.group(i)); } // add the auto registration information to print.prt PvlGroup autoRegTemplate = matcher.RegTemplate(); Application::Log(autoRegTemplate); // Don't need the cubes opened anymore lhImage.close(); rhImage.close(); }
ControlNet * CnetEditorWidget::filteredNetwork() const { ControlNet * filteredCnet = new ControlNet(*m_controlNet); QList<AbstractTreeItem *> networkItems = m_pointModel->getItems(0, -1, AbstractTreeModel::MeasureItems | AbstractTreeModel::PointItems, true); // Iterate through our copy of the cnet, deleting anything that doesn't // exactly match our networkItems. for (int pointIndex = filteredCnet->GetNumPoints() - 1; pointIndex >= 0; pointIndex--) { if (networkItems.isEmpty()) { ControlPoint *cp = filteredCnet->GetPoint(pointIndex); cp->SetEditLock(false); for (int measureIndex = 0; measureIndex < cp->GetNumMeasures(); measureIndex++) { cp->GetMeasure(measureIndex)->SetEditLock(false); } filteredCnet->DeletePoint(cp); } else if (networkItems.last()->getPointerType() == AbstractTreeItem::Point) { ControlPoint *networkItemsCp = (ControlPoint *)networkItems.last()->getPointer(); ControlPoint *cp = filteredCnet->GetPoint(pointIndex); if (cp->GetId() != networkItemsCp->GetId()) { cp->SetEditLock(false); for (int measureIndex = 0; measureIndex < cp->GetNumMeasures(); measureIndex++) { cp->GetMeasure(measureIndex)->SetEditLock(false); } filteredCnet->DeletePoint(cp); } else { networkItems.removeLast(); } } else if (networkItems.last()->getPointerType() == AbstractTreeItem::Measure) { ControlPoint *cp = filteredCnet->GetPoint(pointIndex); ControlMeasure *networkItemsCm = (ControlMeasure *)networkItems.last()->getPointer(); if (cp->GetId() != networkItemsCm->Parent()->GetId()) { cp->SetEditLock(false); for (int measureIndex = 0; measureIndex < cp->GetNumMeasures(); measureIndex++) { cp->GetMeasure(measureIndex)->SetEditLock(false); } filteredCnet->DeletePoint(cp); } else { // Our CP stays, figure out which CMs stay. for (int measureIndex = cp->GetNumMeasures() - 1; networkItemsCm && measureIndex >= 0; measureIndex--) { ControlMeasure *cm = cp->GetMeasure(measureIndex); if (cm->GetCubeSerialNumber() != networkItemsCm->GetCubeSerialNumber()) { cm->SetEditLock(false); cp->Delete(cm); } else { networkItems.removeLast(); networkItemsCm = NULL; if (networkItems.last()->getPointerType() == AbstractTreeItem::Measure) { networkItemsCm = (ControlMeasure *)networkItems.last()->getPointer(); } } } // We still need to verify the copied CP at this index... although // nothing should go wrong, we know things do go wrong so do // the verify instead of just tossing the last networkItems item. pointIndex++; } } } return filteredCnet; }
/** * Slot to set apriori on selected Points from Navigator list box * * @author 2011-03-24 Tracie Sucharski * * @internal * @todo This method should be temporary until the control point editor * comes online. If this stick around, needs to be re-disigned- * put in a separate class?? * * @history 2011-04-04 Tracie Sucharski - Grey out userEntered if more than * a single point is selected. Grey out lat,lon,radius * edits if UserEntered is not selected. * @history 2011-04-13 Tracie Sucharski - If single point selected, fill in * LineEdit's with current controlPoint values. * @history 2011-04-19 Tracie Sucharski - Redesign using modeless dialog. * @history 2011-04-26 Tracie Sucharski - Move from QnetNavTool to * QnetSetAprioriDialog. */ void QnetSetAprioriDialog::setApriori() { double latSigma = Null; double lat = Null; double lonSigma = Null; double lon = Null; double radiusSigma = Null; double radius = Null; if (latitudeConstraintsGroupBox->isChecked()) { if (userEnteredRadioButton->isChecked() && aprioriLatEdit->text() != "") { lat = aprioriLatEdit->text().toDouble(); } if (latSigmaEdit->text() != "") { latSigma = latSigmaEdit->text().toDouble(); } } if (longitudeConstraintsGroupBox->isChecked()) { if (userEnteredRadioButton->isChecked() && aprioriLonEdit->text() != "") { lon = aprioriLonEdit->text().toDouble(); } if (lonSigmaEdit->text() != "") { lonSigma = lonSigmaEdit->text().toDouble(); } } if (radiusConstraintsGroupBox->isChecked()) { if (userEnteredRadioButton->isChecked() && aprioriRadiusEdit->text() != "") { radius = aprioriRadiusEdit->text().toDouble(); } if (radiusSigmaEdit->text() != "") { radiusSigma = radiusSigmaEdit->text().toDouble(); } } // If the SetAprioriPoint group box selected, set aprioriSurfacePoint for // those points not editLocked. for (int i = 0; i < m_points.size(); i++) { QString id = m_points.at(i)->text(); ControlPoint *pt = m_qnetTool->controlNet()->GetPoint(id); if (pt->IsEditLocked()) continue; if (!pt->HasAprioriCoordinates()) { QString msg = "Point [" + id + "] does not have an Apriori coordinate. " "Make sure to save the ground source measurement then the Point before " "setting the sigmas. The sigmas for this point will not be set."; QMessageBox::warning((QWidget *)parent(), "Warning", msg); continue; } if (pointSourceGroupBox->isChecked()) { if (referenceMeasureRadioButton->isChecked()) { ControlMeasure *m = pt->GetRefMeasure(); // Find camera from network camera list int camIndex = m_qnetTool->serialNumberList()->SerialNumberIndex( m->GetCubeSerialNumber()); Camera *cam = m_qnetTool->controlNet()->Camera(camIndex); cam->SetImage(m->GetSample(),m->GetLine()); pt->SetAprioriSurfacePoint(cam->GetSurfacePoint()); pt->SetAprioriSurfacePointSource(ControlPoint::SurfacePointSource::Reference); } else if (averageMeasuresRadioButton->isChecked()) { pt->ComputeApriori(); // Do not need to set AprioriSurfacePointSource or AprioriRadiusSource, // ComputeApriori does this for us. } else if (userEnteredRadioButton->isChecked()) { pt->SetAprioriSurfacePoint(SurfacePoint( Latitude(lat, Angle::Degrees), Longitude(lon, Angle::Degrees), Distance(radius,Distance::Meters))); pt->SetAprioriSurfacePointSource(ControlPoint::SurfacePointSource::User); pt->SetAprioriRadiusSource(ControlPoint::RadiusSource::User); } } try { // Read Surface point from the control point and set the sigmas, // first set the target radii SurfacePoint spt = pt->GetAprioriSurfacePoint(); vector<Distance> targetRadii = m_qnetTool->controlNet()->GetTargetRadii(); spt.SetRadii(Distance(targetRadii[0]), Distance(targetRadii[1]), Distance(targetRadii[2])); spt.SetSphericalSigmasDistance(Distance(latSigma,Distance::Meters), Distance(lonSigma,Distance::Meters), Distance(radiusSigma,Distance::Meters)); // Write the surface point back out to the controlPoint pt->SetAprioriSurfacePoint(spt); // TODO: Is the following line necessary, should error be thrown // for free or fixed pts? //pt->SetType(ControlPoint::Constrained); emit pointChanged(id); emit netChanged(); } catch (IException &e) { QString message = "Error setting sigmas. \n"; message += e.toString(); QMessageBox::critical((QWidget *)parent(),"Error",message); QApplication::restoreOverrideCursor(); // Sigmas failed, but surface pt coordinate was set emit pointChanged(id); emit netChanged(); return; } } }