14#include "BasisFunction.h" 
   15#include "BoxcarCachingAlgorithm.h" 
   17#include "Interpolator.h" 
   18#include "LeastSquares.h" 
   20#include "ProcessRubberSheet.h" 
   21#include "TileManager.h" 
   23#include "UniqueIOCachingAlgorithm.h" 
   37    p_bandChangeFunct = NULL;
 
   42    p_startQuadSize = startSize;
 
   43    p_endQuadSize = endSize;
 
   46    m_patchStartSample = 1;
 
   50    m_patchSampleIncrement = 4;
 
   51    m_patchLineIncrement = 4;
 
 
  103                             int samples, 
int lines,
 
  104                             int sampleIncrement, 
int lineIncrement) {
 
  106    m_patchStartSample = startSample;
 
  107    m_patchStartLine = startLine;
 
  108    m_patchSamples = samples;
 
  109    m_patchLines = lines;
 
  110    m_patchSampleIncrement = sampleIncrement;
 
  111    m_patchLineIncrement = lineIncrement;
 
 
  137      string m = 
"You must specify exactly one input cube";
 
  141      string m = 
"You must specify exactly one output cube";
 
  146    p_lineMap.resize(p_startQuadSize);
 
  147    p_sampMap.resize(p_startQuadSize);
 
  149    for (
unsigned int pos = 0; pos < p_lineMap.size(); pos++) {
 
  150      p_lineMap[pos].resize(p_startQuadSize);
 
  151      p_sampMap[pos].resize(p_startQuadSize);
 
  158    Portal iportal(interp.Samples(), interp.Lines(),
 
  160                         interp.HotSample(), interp.HotLine());
 
  166    if (p_bandChangeFunct == NULL) {
 
  172      long long int tilesPerBand = otile.Tiles() / 
OutputCubes[0]->bandCount();
 
  174      for (
long long int tile = 1; tile <= tilesPerBand; tile++) {
 
  175        bool useLastTileMap = 
false;
 
  176        for (
int band = 1; band <= 
OutputCubes[0]->bandCount(); band++) {
 
  177          otile.SetTile(tile, band);
 
  180          if (p_startQuadSize <= 2 || min(
OutputCubes[0]->lineCount(), 
OutputCubes[0]->sampleCount()) <= p_startQuadSize) {
 
  181            SlowGeom(otile, iportal, trans, interp);
 
  184            QuadTree(otile, iportal, trans, interp, useLastTileMap);
 
  187          useLastTileMap = 
true;
 
  195      int lastOutputBand = -1;
 
  197      for (otile.begin(); !otile.end(); otile++) {
 
  199        if (lastOutputBand != otile.Band()) {
 
  200          lastOutputBand = otile.Band();
 
  202          p_bandChangeFunct(lastOutputBand);
 
  205        if (p_startQuadSize <= 2) {
 
  206          SlowGeom(otile, iportal, trans, interp);
 
  209          QuadTree(otile, iportal, trans, interp, 
false);
 
 
  234    p_bandChangeFunct = funct;
 
 
  241    double outputSamp, outputLine;
 
  242    double inputSamp, inputLine;
 
  243    int outputBand = otile.Band();
 
  245    for (
int i = 0; i < otile.size(); i++) {
 
  246      outputSamp = otile.Sample(i);
 
  247      outputLine = otile.Line(i);
 
  250      if (trans.Xform(inputSamp, inputLine, outputSamp, outputLine)) {
 
  251        if ((inputSamp < 0.5) || (inputLine < 0.5) ||
 
  252            (inputLine > 
InputCubes[0]->lineCount() + 0.5) ||
 
  253            (inputSamp > 
InputCubes[0]->sampleCount() + 0.5)) {
 
  258          iportal.SetPosition(inputSamp, inputLine, outputBand);
 
  260          otile[i] = interp.Interpolate(inputSamp, inputLine,
 
  261                                        iportal.DoubleBuffer());
 
  271  void ProcessRubberSheet::QuadTree(TileManager &otile, Portal &iportal,
 
  272                                    Transform &trans, Interpolator &interp,
 
  273                                    bool useLastTileMap) {
 
  276    vector<Quad *> quadTree;
 
  278    if (!useLastTileMap) {
 
  280      Quad *quad = 
new Quad;
 
  281      quad->sline = otile.Line();
 
  282      quad->ssamp = otile.Sample();
 
  284      quad->eline = otile.Line(otile.size() - 1);
 
  285      quad->esamp = otile.Sample(otile.size() - 1);
 
  286      quad->slineTile = otile.Line();
 
  287      quad->ssampTile = otile.Sample();
 
  289      quadTree.push_back(quad);
 
  293      while (quadTree.size() > 0) {
 
  294        ProcessQuad(quadTree, trans, p_lineMap, p_sampMap);
 
  299    int outputBand = otile.Band();
 
  300    for (
int i = 0, line = 0; line < p_startQuadSize; line++) {
 
  301      for (
int samp = 0; samp < p_startQuadSize; samp++, i++) {
 
  302        double inputLine = p_lineMap[line][samp];
 
  303        double inputSamp = p_sampMap[line][samp];
 
  304        if (inputLine != NULL8) {
 
  305          iportal.SetPosition(inputSamp, inputLine, outputBand);
 
  307          otile[i] = interp.Interpolate(inputSamp, inputLine,
 
  308                                        iportal.DoubleBuffer());
 
  331                                    int sline, 
int eline, 
int increment) {
 
  333    for (
int line = sline; line <= eline; line += increment) {
 
  334      for (
int sample = ssamp; sample <= esamp; sample += increment) {
 
  338        if (trans.Xform(sjunk, ljunk, sample, line)) {
 
 
  349  void ProcessRubberSheet::ProcessQuad(std::vector<Quad *> &quadTree,
 
  351                           std::vector< std::vector<double> > &lineMap,
 
  352                           std::vector< std::vector<double> > &sampMap) {
 
  354    Quad *quad = quadTree[0];
 
  355    double oline[4], osamp[4];
 
  356    double iline[4], isamp[4];
 
  360    oline[0] = quad->sline;
 
  361    osamp[0] = quad->ssamp;
 
  362    if (!trans.Xform(isamp[0], iline[0], osamp[0], oline[0])) {
 
  367    oline[1] = quad->sline;
 
  368    osamp[1] = quad->esamp;
 
  369    if (!trans.Xform(isamp[1], iline[1], osamp[1], oline[1])) {
 
  374    oline[2] = quad->eline;
 
  375    osamp[2] = quad->ssamp;
 
  376    if (!trans.Xform(isamp[2], iline[2], osamp[2], oline[2])) {
 
  381    oline[3] = quad->eline;
 
  382    osamp[3] = quad->esamp;
 
  383    if (!trans.Xform(isamp[3], iline[3], osamp[3], oline[3])) {
 
  390    if (badCorner == 4) {
 
  391      if ((quad->eline - quad->sline) < p_endQuadSize) {
 
  392        SlowQuad(quadTree, trans, lineMap, sampMap);
 
  395        if (p_forceSamp != 
Null && p_forceLine != 
Null) {
 
  396          if (p_forceSamp >= quad->ssamp && p_forceSamp <= quad->esamp &&
 
  397              p_forceLine >= quad->sline && p_forceLine <= quad->eline) {
 
  403        int centerSample = (quad->ssamp + quad->esamp) / 2;
 
  404        int centerLine   = (quad->sline + quad->eline) / 2;
 
  421        if (
TestLine(trans, quad->ssamp + 1, quad->esamp - 1,
 
  422                    quad->sline, quad->sline, 4) ||
 
  424            TestLine(trans, quad->ssamp + 1, quad->esamp - 1,
 
  425                     quad->eline, quad->eline, 4) ||
 
  427            TestLine(trans, quad->ssamp, quad->ssamp,
 
  428                     quad->sline + 1, quad->eline - 1, 4) ||
 
  430            TestLine(trans, quad->esamp, quad->esamp,
 
  431                     quad->sline + 1, quad->eline - 1, 4) ||
 
  433            TestLine(trans, centerSample, centerSample,
 
  434                     quad->sline + 1, quad->eline - 1, 4) ||
 
  436            TestLine(trans, quad->ssamp + 1, quad->esamp - 1,
 
  437                     centerLine, centerLine, 4)) {
 
  445        for (
int i = quad->sline; i <= quad->eline; i++) {
 
  446          for (
int j = quad->ssamp; j <= quad->esamp; j++) {
 
  447            lineMap[i-quad->slineTile][j-quad->ssampTile] = NULL8;
 
  451        quadTree.erase(quadTree.begin());
 
  475      if ((quad->eline - quad->sline) < p_endQuadSize) {
 
  476        SlowQuad(quadTree, trans, lineMap, sampMap);
 
  489    for (
int i = 0; i < 4; i++) {
 
  492      A[i][2] = oline[i] * osamp[i];
 
  500    if ((detA = Det4x4(A)) == 0.0) {
 
  501      if ((quad->eline - quad->sline) < p_endQuadSize) {
 
  502        SlowQuad(quadTree, trans, lineMap, sampMap);
 
  514    for (
int j = 0; j < 4; j++) {
 
  515      memmove(B, A, 16 * 
sizeof(
double));
 
  517      for (
int i = 0; i < 4; i++) {
 
  521      lineCoef[j] = Det4x4(B) / detA;
 
  526    for (
int j = 0; j < 4; j++) {
 
  527      memmove(B, A, 16 * 
sizeof(
double));
 
  529      for (
int i = 0; i < 4; i++) {
 
  533      sampCoef[j] = Det4x4(B) / detA;
 
  537    double quadMidLine = (quad->sline + quad->eline) / 2.0;
 
  538    double quadMidSamp = (quad->ssamp + quad->esamp) / 2.0;
 
  539    double midLine, midSamp;
 
  541    if (!trans.Xform(midSamp, midLine, quadMidSamp, quadMidLine)) {
 
  542      if ((quad->eline - quad->sline) < p_endQuadSize) {
 
  543        SlowQuad(quadTree, trans, lineMap, sampMap);
 
  551    double cmidLine = lineCoef[0] * quadMidLine +
 
  552                      lineCoef[1] * quadMidSamp +
 
  553                      lineCoef[2] * quadMidLine * quadMidSamp +
 
  556    double cmidSamp = sampCoef[0] * quadMidLine +
 
  557                      sampCoef[1] * quadMidSamp +
 
  558                      sampCoef[2] * quadMidLine * quadMidSamp +
 
  561    if ((abs(cmidSamp - midSamp) > 0.5) || (abs(cmidLine - midLine) > 0.5)) {
 
  562      if ((quad->eline - quad->sline) < p_endQuadSize) {
 
  563        SlowQuad(quadTree, trans, lineMap, sampMap);
 
  573    double ulLine = lineCoef[0] * (double) quad->sline +
 
  574                    lineCoef[1] * (
double) quad->ssamp +
 
  575                    lineCoef[2] * (double) quad->sline * (
double) quad->ssamp +
 
  578    double ulSamp = sampCoef[0] * (double) quad->sline +
 
  579                    sampCoef[1] * (
double) quad->ssamp +
 
  580                    sampCoef[2] * (double) quad->sline * (
double) quad->ssamp +
 
  585    double lineChangeWrLine = lineCoef[0] + lineCoef[2] * (double) quad->ssamp;
 
  586    double sampChangeWrLine = sampCoef[0] + sampCoef[2] * (double) quad->ssamp;
 
  588    for (
int ol = quad->sline; ol <= quad->eline; ol++) {
 
  591      double lineChangeWrSamp = lineCoef[1] + lineCoef[2] * (double) ol;
 
  592      double sampChangeWrSamp = sampCoef[1] + sampCoef[2] * (double) ol;
 
  595      double cline = ulLine;
 
  596      double csamp = ulSamp;
 
  599      int startSamp = quad->ssamp - quad->ssampTile;
 
  600      std::vector<double> &lineVect = lineMap[ol-quad->slineTile];
 
  601      std::vector<double> &sampleVect = sampMap[ol-quad->slineTile];
 
  604      for (
int os = quad->ssamp; os <= quad->esamp; os++) {
 
  605        lineVect[startSamp] = cline;
 
  606        sampleVect[startSamp] = csamp;
 
  610        cline += lineChangeWrSamp;
 
  611        csamp += sampChangeWrSamp;
 
  615      ulLine += lineChangeWrLine;
 
  616      ulSamp += sampChangeWrLine;
 
  621    quadTree.erase(quadTree.begin());
 
  626  void ProcessRubberSheet::SplitQuad(std::vector<Quad *> &quadTree) {
 
  629    Quad *quad = quadTree[0];
 
  630    int n = (quad->eline - quad->sline + 1) / 2;
 
  635    q1->eline = quad->sline + n - 1;
 
  636    q1->esamp = quad->ssamp + n - 1;
 
  637    quadTree.push_back(q1);
 
  642    q2->eline = quad->sline + n - 1;
 
  643    q2->ssamp = quad->ssamp + n;
 
  644    quadTree.push_back(q2);
 
  649    q3->sline = quad->sline + n;
 
  650    q3->esamp = quad->ssamp + n - 1;
 
  651    quadTree.push_back(q3);
 
  656    q4->sline = quad->sline + n;
 
  657    q4->ssamp = quad->ssamp + n;
 
  658    quadTree.push_back(q4);
 
  662    quadTree.erase(quadTree.begin());
 
  667  void ProcessRubberSheet::SlowQuad(std::vector<Quad *> &quadTree,
 
  669                                    std::vector< std::vector<double> > &lineMap,
 
  670                                    std::vector< std::vector<double> > &sampMap) {
 
  673    Quad *quad = quadTree[0];
 
  677    for (
int oline = quad->sline; oline <= quad->eline; oline++) {
 
  678      int lineIndex = oline - quad->slineTile;
 
  679      for (
int osamp = quad->ssamp; osamp <= quad->esamp; osamp++) {
 
  680        int sampIndex = osamp - quad->ssampTile;
 
  681        lineMap[lineIndex][sampIndex] = NULL8;
 
  682        if (trans.Xform(isamp, iline, (
double) osamp, (
double) oline)) {
 
  683          if ((isamp >= 0.5) ||
 
  685              (iline <= 
InputCubes[0]->lineCount() + 0.5) ||
 
  686              (isamp <= 
InputCubes[0]->sampleCount() + 0.5)) {
 
  687            lineMap[lineIndex][sampIndex] = iline;
 
  688            sampMap[lineIndex][sampIndex] = isamp;
 
  696    quadTree.erase(quadTree.begin());
 
  701  double ProcessRubberSheet::Det4x4(
double m[4][4]) {
 
  705    cofact [0][0] = m[1][1];
 
  706    cofact [0][1] = m[1][2];
 
  707    cofact [0][2] = m[1][3];
 
  708    cofact [1][0] = m[2][1];
 
  709    cofact [1][1] = m[2][2];
 
  710    cofact [1][2] = m[2][3];
 
  711    cofact [2][0] = m[3][1];
 
  712    cofact [2][1] = m[3][2];
 
  713    cofact [2][2] = m[3][3];
 
  714    double det = m[0][0] * Det3x3(cofact);
 
  716    cofact [0][0] = m[1][0];
 
  717    cofact [0][1] = m[1][2];
 
  718    cofact [0][2] = m[1][3];
 
  719    cofact [1][0] = m[2][0];
 
  720    cofact [1][1] = m[2][2];
 
  721    cofact [1][2] = m[2][3];
 
  722    cofact [2][0] = m[3][0];
 
  723    cofact [2][1] = m[3][2];
 
  724    cofact [2][2] = m[3][3];
 
  725    det -= m[0][1] * Det3x3(cofact);
 
  727    cofact [0][0] = m[1][0];
 
  728    cofact [0][1] = m[1][1];
 
  729    cofact [0][2] = m[1][3];
 
  730    cofact [1][0] = m[2][0];
 
  731    cofact [1][1] = m[2][1];
 
  732    cofact [1][2] = m[2][3];
 
  733    cofact [2][0] = m[3][0];
 
  734    cofact [2][1] = m[3][1];
 
  735    cofact [2][2] = m[3][3];
 
  736    det += m[0][2] * Det3x3(cofact);
 
  738    cofact [0][0] = m[1][0];
 
  739    cofact [0][1] = m[1][1];
 
  740    cofact [0][2] = m[1][2];
 
  741    cofact [1][0] = m[2][0];
 
  742    cofact [1][1] = m[2][1];
 
  743    cofact [1][2] = m[2][2];
 
  744    cofact [2][0] = m[3][0];
 
  745    cofact [2][1] = m[3][1];
 
  746    cofact [2][2] = m[3][2];
 
  747    det -= m[0][3] * Det3x3(cofact);
 
  754  double ProcessRubberSheet::Det3x3(
double m[3][3]) {
 
  756    return m[0][0] * m[1][1] * m[2][2] -
 
  757           m[0][0] * m[1][2] * m[2][1] -
 
  758           m[0][1] * m[1][0] * m[2][2] +
 
  759           m[0][1] * m[1][2] * m[2][0] +
 
  760           m[0][2] * m[1][0] * m[2][1] -
 
  761           m[0][2] * m[1][1] * m[2][0];
 
  792      string m = 
"You must specify exactly one input cube";
 
  796      string m = 
"You must specify exactly one output cube";
 
  801    Portal iportal(interp.Samples(), interp.Lines(),
 
  803                   interp.HotSample(), interp.HotLine());
 
  806    int patchesPerBand = 0;
 
  807    for (
int line = m_patchStartLine; line <= 
InputCubes[0]->lineCount();
 
  808          line += m_patchLineIncrement) {
 
  809      for (
int samp = m_patchStartSample;
 
  811            samp += m_patchSampleIncrement) {
 
  816    int patchCount = 
InputCubes[0]->bandCount() * patchesPerBand;
 
  840    for (
int band=1; band <= 
InputCubes[0]->bandCount(); band++) {
 
  841      if (p_bandChangeFunct != NULL) p_bandChangeFunct(band);
 
  842      iportal.SetPosition(1,1,band);
 
  844      for (
int line = m_patchStartLine;
 
  846            line += m_patchLineIncrement) {
 
  847        for (
int samp = m_patchStartSample;
 
  850          transformPatch((
double)samp, (
double)(samp + m_patchSamples - 1),
 
  851                         (
double)line, (
double)(line + m_patchLines - 1),
 
  852                         iportal, trans, interp);
 
 
  860  void ProcessRubberSheet::transformPatch(
double ssamp, 
double esamp,
 
  861                                          double sline, 
double eline,
 
  869      if (ssamp == esamp) ssamp = esamp - 1;
 
  873      if (sline == eline) sline = eline - 1;
 
  878    QVector<double> isamps;
 
  879    QVector<double> ilines;
 
  880    QVector<double> osamps;
 
  881    QVector<double> olines;
 
  885    if (trans.Xform(tsamp,tline,ssamp,sline)) {
 
  886      isamps.push_back(ssamp);
 
  887      ilines.push_back(sline);
 
  888      osamps.push_back(tsamp);
 
  889      olines.push_back(tline);
 
  893    if (trans.Xform(tsamp,tline,esamp,sline)) {
 
  894      isamps.push_back(esamp);
 
  895      ilines.push_back(sline);
 
  896      osamps.push_back(tsamp);
 
  897      olines.push_back(tline);
 
  901    if (trans.Xform(tsamp,tline,ssamp,eline)) {
 
  902      isamps.push_back(ssamp);
 
  903      ilines.push_back(eline);
 
  904      osamps.push_back(tsamp);
 
  905      olines.push_back(tline);
 
  909    if (trans.Xform(tsamp,tline,esamp,eline)) {
 
  910      isamps.push_back(esamp);
 
  911      ilines.push_back(eline);
 
  912      osamps.push_back(tsamp);
 
  913      olines.push_back(tline);
 
  918    if (isamps.size() == 0) {
 
  923    if (isamps.size() < 4) {
 
  924      splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
  929    int osampMin = (int) osamps[0];
 
  930    int osampMax = (int) (osamps[0] + 0.5);
 
  931    int olineMin = (int) olines[0];
 
  932    int olineMax = (int) (olines[0] + 0.5);
 
  933    for (
int i = 1; i < osamps.size(); i++) {
 
  934      if (osamps[i] < osampMin) osampMin = (int) osamps[i];
 
  935      if (osamps[i] > osampMax) osampMax = (int) (osamps[i] + 0.5);
 
  936      if (olines[i] < olineMin) olineMin = (int) olines[i];
 
  937      if (olines[i] > olineMax) olineMax = (int) (olines[i] + 0.5);
 
  942    if (osampMax < 1) 
return;
 
  943    if (olineMax < 1) 
return;
 
  944    if (osampMin > 
OutputCubes[0]->sampleCount()) 
return;
 
  945    if (olineMin > 
OutputCubes[0]->lineCount()) 
return;
 
  948    if (osampMin < 1) osampMin = 1;
 
  949    if (olineMin < 1) olineMin = 1;
 
  966    if (osampMax - osampMin + 1.0 > 
OutputCubes[0]->sampleCount() * 0.50) {
 
  967      splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
  970    if (olineMax - olineMin + 1.0 > 
OutputCubes[0]->lineCount() * 0.50) {
 
  971      splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
  976    BasisFunction isampFunc(
"Ax+By+C",3,3);
 
  977    LeastSquares isampLSQ(isampFunc);
 
  979    BasisFunction ilineFunc(
"Dx+Ey+F",3,3);
 
  980    LeastSquares ilineLSQ(ilineFunc);
 
  983      for (
int i=0; i < isamps.size(); i++) {
 
  984        std::vector<double> vars;
 
  985        vars.push_back(osamps[i]);
 
  986        vars.push_back(olines[i]);
 
  989        isampLSQ.AddKnown(vars,isamps[i]);
 
  990        ilineLSQ.AddKnown(vars,ilines[i]);
 
  996    catch (IException &e) {
 
  997      splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
 1002    for (
int i=0; i<isamps.size(); i++) {
 
 1003      if (fabs(isampLSQ.Residual(i)) > 0.5) {
 
 1004        splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
 1007      if (fabs(ilineLSQ.Residual(i)) > 0.5) {
 
 1008        splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
 1017    double csamp = (ssamp + esamp) / 2.0;
 
 1018    double cline = (sline + eline) / 2.0;
 
 1019    if (trans.Xform(tsamp,tline,csamp,cline)) {
 
 1020      std::vector<double> vars;
 
 1021      vars.push_back(tsamp);
 
 1022      vars.push_back(tline);
 
 1023      vars.push_back(1.0);
 
 1025      double isamp = isampFunc.Evaluate(vars);
 
 1026      double iline = ilineFunc.Evaluate(vars);
 
 1028      double err = (csamp - isamp) * (csamp - isamp) +
 
 1029                   (cline - iline) * (cline - iline);
 
 1031        splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
 1036      splitPatch(ssamp, esamp, sline, eline, iportal, trans, interp);
 
 1041    double A = isampFunc.Coefficient(0);
 
 1042    double B = isampFunc.Coefficient(1);
 
 1043    double C = isampFunc.Coefficient(2);
 
 1045    double D = ilineFunc.Coefficient(0);
 
 1046    double E = ilineFunc.Coefficient(1);
 
 1047    double F = ilineFunc.Coefficient(2);
 
 1052    Brick oBrick(*
OutputCubes[0], osampMax-osampMin+1, olineMax-olineMin+1, 1);
 
 1053    oBrick.SetBasePosition(osampMin, olineMin, iportal.Band());
 
 1056    bool foundNull = 
false;
 
 1057    for (
int oline = olineMin; oline <= olineMax; oline++) {
 
 1058      double isamp = A * osampMin + B * oline + C;
 
 1059      double iline = D * osampMin + 
E * oline + F;
 
 1060      double isampChangeWRTosamp = A;
 
 1061      double ilineChangeWRTosamp = D;
 
 1062      for (
int osamp = osampMin; osamp <= osampMax;
 
 1063            osamp++, isamp += isampChangeWRTosamp, iline += ilineChangeWRTosamp) {
 
 1065        iportal.SetPosition(isamp, iline, iportal.Band());
 
 1067        double dn = interp.Interpolate(isamp, iline, iportal.DoubleBuffer());
 
 1068        oBrick[brickIndex] = dn;
 
 1069        if (dn == 
Null) foundNull = 
true;
 
 1086      Brick readBrick(*
OutputCubes[0], osampMax-osampMin+1, olineMax-olineMin+1, 1);
 
 1087      readBrick.SetBasePosition(osampMin, olineMin, iportal.Band());
 
 1089      for (brickIndex = 0; brickIndex<(osampMax-osampMin+1)*(olineMax-olineMin+1); brickIndex++) {
 
 1090        if (readBrick[brickIndex] != 
Null) {
 
 1091          oBrick[brickIndex] = readBrick[brickIndex];
 
 1103  void ProcessRubberSheet::splitPatch(
double ssamp, 
double esamp,
 
 1104                                       double sline, 
double eline, Portal &iportal,
 
 1105                                       Transform &trans, Interpolator &interp) {
 
 1108    if ((esamp - ssamp < 0.1) && (eline - sline < 0.1)) 
return;
 
 1111    double midSamp = (esamp + ssamp) / 2.0;
 
 1112    double midLine = (eline + sline) / 2.0;
 
 1114    transformPatch(ssamp, midSamp,
 
 1116                   iportal, trans, interp);
 
 1117    transformPatch(midSamp, esamp,
 
 1119                   iportal, trans, interp);
 
 1120    transformPatch(ssamp, midSamp,
 
 1122                   iportal, trans, interp);
 
 1123    transformPatch(midSamp, esamp,
 
 1125                   iportal, trans, interp);
 
This algorithm is designed for applications that jump around between a couple of spots in the cube wi...
 
@ Programmer
This error is for when a programmer made an API call that was illegal.
 
Buffer for containing a two dimensional section of an image.
 
std::vector< Isis::Cube * > InputCubes
A vector of pointers to opened Cube objects.
 
Isis::Progress * p_progress
Pointer to a Progress object.
 
std::vector< Isis::Cube * > OutputCubes
A vector of pointers to allocated Cube objects.
 
virtual void StartProcess(Transform &trans, Interpolator &interp)
Applies a Transform and an Interpolator to every pixel in the output cube.
 
virtual void processPatchTransform(Transform &trans, Interpolator &interp)
Applies a Transform and an Interpolator to small patches.
 
ProcessRubberSheet(int startSize=128, int endSize=8)
Constructs a ProcessRubberSheet class with the default tile size range.
 
virtual void BandChange(void(*funct)(const int band))
Registers a function to be called when the current output cube band number changes.
 
virtual void setPatchParameters(int startSample, int startLine, int samples, int lines, int sampleIncrement, int lineIncrement)
This method allows the programmer to override the default values for patch parameters used in the pat...
 
bool TestLine(Transform &trans, int ssamp, int esamp, int sline, int eline, int increment)
This function walks a line (or rectangle) and tests a point every increment pixels.
 
void SetMaximumSteps(const int steps)
This sets the maximum number of steps in the process.
 
void CheckStatus()
Checks and updates the status.
 
Buffer manager, for moving through a cube in tiles.
 
This algorithm is designed for applications that jump around between a couple of spots in the cube wi...
 
const double E
Sets some basic constants for use in ISIS programming.
 
This is free and unencumbered software released into the public domain.
 
const double Null
Value for an Isis Null pixel.
 
Namespace for the standard library.