QList<ControlPoint *> getValidPoints(Cube &cube, STRtree &coordTree) { ImagePolygon poly; try { cube.read(poly); } catch (IException &e) { QString msg = "Footprintinit must be run prior to running cnetadd"; msg += " with POLYGON=TRUE for cube [" + cube.fileName() + "]"; throw IException(e, IException::User, msg, _FILEINFO_); } std::vector<void *> matches; MultiPolygon *polys = poly.Polys(); for (unsigned int i = 0; i < polys->getNumGeometries(); i++) { const Geometry *geometry = polys->getGeometryN(i); const Envelope *boundingBox = geometry->getEnvelopeInternal(); coordTree.query(boundingBox, matches); } QList<ControlPoint *> results; for (unsigned int i = 0; i < matches.size(); i++) { results.append((ControlPoint *) matches[i]); } return results; }
/** * Find the lat/lon range of the image. This will use the image footprint, * camera, or projection in order to find a good result. * * @param Cube* This is required for estimation. You can pass in NULL (it will * disable estimation). * @param minLat This is an output: minimum latitude * @param maxLat This is an output: maximum latitude * @param minLon This is an output: minimum longitude * @param maxLon This is an output: maximum longitude * @param allowEstimation If this is true then extra efforts will be made to * guess the ground range of the input. This can still fail. * @return True if a ground range was found, false if no ground range could * be determined. Some lat/lon results may still be populated; their * values are undefined. */ bool UniversalGroundMap::GroundRange(Cube *cube, Latitude &minLat, Latitude &maxLat, Longitude &minLon, Longitude &maxLon, bool allowEstimation) { // Do we need a RingRange method? // For now just return false if (HasCamera()) if (p_camera->target()->shape()->name() == "Plane") return false; if (HasProjection()) if (p_projection->projectionType() == Projection::RingPlane) return false; minLat = Latitude(); maxLat = Latitude(); minLon = Longitude(); maxLon = Longitude(); // If we have a footprint, use it try { if (cube) { ImagePolygon poly; cube->read(poly); geos::geom::MultiPolygon *footprint = PolygonTools::MakeMultiPolygon( poly.Polys()->clone()); geos::geom::Geometry *envelope = footprint->getEnvelope(); geos::geom::CoordinateSequence *coords = envelope->getCoordinates(); for (unsigned int i = 0; i < coords->getSize(); i++) { const geos::geom::Coordinate &coord = coords->getAt(i); Latitude coordLat(coord.y, Angle::Degrees); Longitude coordLon(coord.x, Angle::Degrees); if (!minLat.isValid() || minLat > coordLat) minLat = coordLat; if (!maxLat.isValid() || maxLat < coordLat) maxLat = coordLat; if (!minLon.isValid() || minLon > coordLon) minLon = coordLon; if (!maxLon.isValid() || maxLon < coordLon) maxLon = coordLon; } delete coords; coords = NULL; delete envelope; envelope = NULL; delete footprint; footprint = NULL; } } catch (IException &) { } if (!minLat.isValid() || !maxLat.isValid() || !minLon.isValid() || !maxLon.isValid()) { if (HasCamera()) { // Footprint failed, ask the camera PvlGroup mappingGrp("Mapping"); mappingGrp += PvlKeyword("LatitudeType", "Planetocentric"); mappingGrp += PvlKeyword("LongitudeDomain", "360"); mappingGrp += PvlKeyword("LongitudeDirection", "PositiveEast"); Pvl mappingPvl; mappingPvl += mappingGrp; double minLatDouble; double maxLatDouble; double minLonDouble; double maxLonDouble; p_camera->GroundRange( minLatDouble, maxLatDouble, minLonDouble, maxLonDouble, mappingPvl); minLat = Latitude(minLatDouble, Angle::Degrees); maxLat = Latitude(maxLatDouble, Angle::Degrees); minLon = Longitude(minLonDouble, Angle::Degrees); maxLon = Longitude(maxLonDouble, Angle::Degrees); } else if (HasProjection()) { // Footprint failed, look in the mapping group PvlGroup mappingGrp = p_projection->Mapping(); if (mappingGrp.hasKeyword("MinimumLatitude") && mappingGrp.hasKeyword("MaximumLatitude") && mappingGrp.hasKeyword("MinimumLongitude") && mappingGrp.hasKeyword("MaximumLongitude")) { minLat = Latitude(mappingGrp["MinimumLatitude"], mappingGrp, Angle::Degrees); maxLat = Latitude(mappingGrp["MaximumLatitude"], mappingGrp, Angle::Degrees); minLon = Longitude(mappingGrp["MinimumLongitude"], mappingGrp, Angle::Degrees); maxLon = Longitude(mappingGrp["MaximumLongitude"], mappingGrp, Angle::Degrees); } else if (allowEstimation && cube) { // Footprint and mapping failed... no lat/lon range of any kind is // available. Let's test points in the image to try to make our own // extent. QList<QPointF> imagePoints; // Reset to TProjection TProjection *tproj = (TProjection *) p_projection; /* * This is where we're testing: * * |---------------| * |***************| * |** * **| * |* * * * *| * |* * * * *| * |***************| * |* * * * *| * |* * * * *| * |** * **| * |***************| * |---------------| * * We'll test at the edges, a plus (+) and an (X) to help DEMs work. */ int sampleCount = cube->sampleCount(); int lineCount = cube->lineCount(); int stepsPerLength = 20; //number of steps per length double aspectRatio = (double)lineCount / (double)sampleCount; double xStepSize = sampleCount / stepsPerLength; double yStepSize = xStepSize * aspectRatio; if (lineCount > sampleCount) { aspectRatio = (double)sampleCount / (double)lineCount; yStepSize = lineCount / stepsPerLength; xStepSize = yStepSize * aspectRatio; } double yWalked = 0.5; //3 vertical lines for (int i = 0; i < 3; i++) { double xValue = 0.5 + ( i * (sampleCount / 2) ); while (yWalked <= lineCount) { imagePoints.append( QPointF(xValue, yWalked) ); yWalked += yStepSize; } yWalked = 0.5; } double xWalked = 0.5; //3 horizontal lines for (int i = 0; i < 3; i++) { double yValue = 0.5 + ( i * (lineCount / 2) ); while (xWalked <= sampleCount) { imagePoints.append( QPointF(xWalked, yValue) ); xWalked += xStepSize; } xWalked = 0.5; } double xDiagonalWalked = 0.5; double yDiagonalWalked = 0.5; xStepSize = sampleCount / stepsPerLength; yStepSize = lineCount / stepsPerLength; //Top-Down Diagonal while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked <= lineCount) ) { imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) ); xDiagonalWalked += xStepSize; yDiagonalWalked += yStepSize; } xDiagonalWalked = 0.5; //Bottom-Up Diagonal while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked >= 0) ) { imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) ); xDiagonalWalked += xStepSize; yDiagonalWalked -= yStepSize; } foreach (QPointF imagePoint, imagePoints) { if (tproj->SetWorld(imagePoint.x(), imagePoint.y())) { Latitude latResult(tproj->UniversalLatitude(), Angle::Degrees); Longitude lonResult(tproj->UniversalLongitude(), Angle::Degrees); if (minLat.isValid()) minLat = qMin(minLat, latResult); else minLat = latResult; if (maxLat.isValid()) maxLat = qMax(maxLat, latResult); else maxLat = latResult; if (minLon.isValid()) minLon = qMin(minLon, lonResult); else minLon = lonResult; if (maxLon.isValid()) maxLon = qMax(maxLon, lonResult); else maxLon = lonResult; } } } } }
void IsisMain() { UserInterface &ui = Application::GetUserInterface(); Cube cube; cube.open(ui.GetFileName("FROM"), "rw"); // Make sure cube has been run through spiceinit try { cube.camera(); } catch(IException &e) { string msg = "Spiceinit must be run before initializing the polygon"; throw IException(e, IException::User, msg, _FILEINFO_); } Progress prog; prog.SetMaximumSteps(1); prog.CheckStatus(); QString sn = SerialNumber::Compose(cube); ImagePolygon poly; if(ui.WasEntered("MAXEMISSION")) { poly.Emission(ui.GetDouble("MAXEMISSION")); } if(ui.WasEntered("MAXINCIDENCE")) { poly.Incidence(ui.GetDouble("MAXINCIDENCE")); } if(ui.GetString("LIMBTEST") == "ELLIPSOID") { poly.EllipsoidLimb(true); } int sinc = 1; int linc = 1; IString incType = ui.GetString("INCTYPE"); if(incType.UpCase() == "VERTICES") { poly.initCube(cube); sinc = linc = (int)(0.5 + (((poly.validSampleDim() * 2) + (poly.validLineDim() * 2) - 3.0) / ui.GetInteger("NUMVERTICES"))); if (sinc < 1.0 || linc < 1.0) sinc = linc = 1.0; } else if (incType.UpCase() == "LINCSINC"){ sinc = ui.GetInteger("SINC"); linc = ui.GetInteger("LINC"); } else { string msg = "Invalid INCTYPE option[" + incType + "]"; throw IException(IException::Programmer, msg, _FILEINFO_); } bool precision = ui.GetBoolean("INCREASEPRECISION"); try { poly.Create(cube, sinc, linc, 1, 1, 0, 0, 1, precision); } catch (IException &e) { QString msg = "Cannot generate polygon for [" + ui.GetFileName("FROM") + "]"; throw IException(e, IException::User, msg, _FILEINFO_); } if(ui.GetBoolean("TESTXY")) { Pvl cubeLab(ui.GetFileName("FROM")); PvlGroup inst = cubeLab.findGroup("Instrument", Pvl::Traverse); QString target = inst["TargetName"]; PvlGroup radii = Projection::TargetRadii(target); Pvl map(ui.GetFileName("MAP")); PvlGroup &mapping = map.findGroup("MAPPING"); if(!mapping.hasKeyword("TargetName")) mapping += Isis::PvlKeyword("TargetName", target); if(!mapping.hasKeyword("EquatorialRadius")) mapping += Isis::PvlKeyword("EquatorialRadius", (QString)radii["EquatorialRadius"]); if(!mapping.hasKeyword("PolarRadius")) mapping += Isis::PvlKeyword("PolarRadius", (QString)radii["PolarRadius"]); if(!mapping.hasKeyword("LatitudeType")) mapping += Isis::PvlKeyword("LatitudeType", "Planetocentric"); if(!mapping.hasKeyword("LongitudeDirection")) mapping += Isis::PvlKeyword("LongitudeDirection", "PositiveEast"); if(!mapping.hasKeyword("LongitudeDomain")) mapping += Isis::PvlKeyword("LongitudeDomain", "360"); if(!mapping.hasKeyword("CenterLatitude")) mapping += Isis::PvlKeyword("CenterLatitude", "0"); if(!mapping.hasKeyword("CenterLongitude")) mapping += Isis::PvlKeyword("CenterLongitude", "0"); sinc = poly.getSinc(); linc = poly.getLinc(); bool polygonGenerated = false; while (!polygonGenerated) { Projection *proj = NULL; geos::geom::MultiPolygon *xyPoly = NULL; try { proj = ProjectionFactory::Create(map, true); xyPoly = PolygonTools::LatLonToXY(*poly.Polys(), proj); polygonGenerated = true; } catch (IException &e) { if (precision && sinc > 1 && linc > 1) { sinc = sinc * 2 / 3; linc = linc * 2 / 3; poly.Create(cube, sinc, linc); } else { delete proj; delete xyPoly; e.print(); // This should be a NAIF error QString msg = "Cannot calculate XY for ["; msg += ui.GetFileName("FROM") + "]"; throw IException(e, IException::User, msg, _FILEINFO_); } } delete proj; delete xyPoly; } } cube.deleteBlob("Polygon", sn); cube.write(poly); if(precision) { PvlGroup results("Results"); results.addKeyword(PvlKeyword("SINC", toString(sinc))); results.addKeyword(PvlKeyword("LINC", toString(linc))); Application::Log(results); } Process p; p.SetInputCube("FROM"); p.WriteHistory(cube); cube.close(); prog.CheckStatus(); }
int main () { Isis::Preference::Preferences(true); /** * @brief Test ImagePolygon object for accuracy and correct behavior. * * @author 2005-11-22 Tracie Sucharski * * @history 2007-01-19 Tracie Sucharski, Removed ToGround method (for now) * because of round off problems going back and forth between * lat/lon,line/samp. * @history 2007-01-31 Tracie Sucharski, Added WKT method to return polygon * in string as WKT. * @history 2007-11-09 Tracie Sucharski, Remove WKT method, geos now has * a method to return a WKT string. * @history 2007-11-20 Tracie Sucharski, Added test for sub-polys */ // simple MOC image string inFile = "/usgs/cpkgs/isis3/data/mgs/testData/ab102401.cub"; //string inFile = "/work1/tsucharski/poly/I17621017RDR_lev2.cub"; // same MOC image, but sinusoidal projection //string inFile = "/farm/prog1/tsucharski/isis3/ab102401.lev2.cub"; // same MOC image, but sinusoidal projection , doctored left edge //string inFile = "/farm/prog1/tsucharski/isis3/ab102401.lev2.leftTrim.cub"; // MOC north pole image //string inFile = "/work1/tsucharski/isis3/poly/e0202226.lev1.cub"; // MOC image with 0/360 boundary // orkin //string inFile = "/farm/prog1/tsucharski/isis3/cubes/m0101631.lev1.cub"; // blackflag //string inFile = "/work1/tsucharski/isis3/poly/m0101631.lev1.cub"; // galileo ssi image //string inFile = "/farm/prog1/tsucharski/isis3/6700r.cub"; // Open the cube Cube cube; Cube cube1; cube.Open(inFile,"r"); ImagePolygon poly; try { poly.Create(cube); } catch (iException &e) { std::string msg = "Cannot create polygon for [" + cube.Filename() + "]"; throw iException::Message(iException::Programmer,msg,_FILEINFO_); } // write poly as WKT std::cout<< poly.Polys()->toString()<<std::endl; // Test sub-poly option try { poly.Create(cube,12,1,384,640,385); } catch (iException &e) { std::string msg = "Cannot create sub-polygon for [" + cube.Filename() + "]"; throw iException::Message(iException::Programmer,msg,_FILEINFO_); } // write poly as WKT std::cout<< poly.Polys()->toString()<<std::endl; // Test lower quality option try { poly.Create(cube,10,12,1,384,640,385); } catch (iException &e) { std::string msg = "Cannot create lower quality polygon for [" + cube.Filename() + "]"; throw iException::Message(iException::Programmer,msg,_FILEINFO_); } // write poly as WKT std::cout<< poly.Polys()->toString()<<std::endl; cube.Close(); }