Example #1
0
        inline void contour2d(const MATRIX        &d,
                              const unit_t         ilb,
                              const unit_t         iub,
                              const unit_t         jlb,
                              const unit_t         jub,
                              const ARRAY         &x,
                              const ARRAY         &y,
                              const array<double> &z,
                              void (*proc)(double,double,double,double,double,void *),
                              void  *args
                              )
        {
#define xsect(p1,p2) (h[p2]*xh[p1]-h[p1]*xh[p2])/(h[p2]-h[p1])
#define ysect(p1,p2) (h[p2]*yh[p1]-h[p1]*yh[p2])/(h[p2]-h[p1])
            int m3,case_value;
            double x1=0,x2=0,y1=0,y2=0;
            double h[5];
            int    sh[5];
            double xh[5],yh[5];
            static const unit_t im[4] = {0,1,1,0},jm[4]={0,0,1,1};
            static const int    castab[3][3][3] =
            {
                { {0,0,8},{0,2,5},{7,6,9} },
                { {0,3,4},{1,3,1},{4,3,0} },
                { {9,6,7},{5,2,0},{8,0,0} }
            };
            double temp1,temp2;
            
            const size_t nc  = z.size();
            const double zlo = z[1];
            const double zhi = z[nc];
            for(unit_t j=(jub-1);j>=jlb;--j)
            {
                for(unit_t i=ilb;i<iub;++i)
                {
                    temp1 = min_of<double>(d[i][j],d[i][j+1]);
                    temp2 = min_of<double>(d[i+1][j],d[i+1][j+1]);
                    const double dmin  = min_of(temp1,temp2);
                    temp1 = max_of<double>(d[i][j],d[i][j+1]);
                    temp2 = max_of<double>(d[i+1][j],d[i+1][j+1]);
                    const double dmax  = max_of(temp1,temp2);
                    if( (dmax<zlo) || (dmin>zhi) )
                    {
                        continue;
                    }
                    for(size_t k=1;k<=nc;k++)
                    {
                        const double level = z[k];
                        if ( level<dmin || level>dmax )
                        {
                            continue;
                        }
                        for(int m=4;m>=0;--m)
                        {
                            if (m > 0)
                            {
                                h[m]  = double(d[i+im[m-1]][j+jm[m-1]])-level;
                                xh[m] = double(x[i+im[m-1]]);
                                yh[m] = double(y[j+jm[m-1]]);
                            }
                            else
                            {
                                h[0]  = 0.25 * (h[1]+h[2]+h[3]+h[4]);
                                xh[0] = 0.50 * (double(x[i])+double(x[i+1]));
                                yh[0] = 0.50 * (double(y[j])+double(y[j+1]));
                            }
                            if (h[m] > 0.0)
                                sh[m] = 1;
                            else if (h[m] < 0.0)
                                sh[m] = -1;
                            else
                                sh[m] = 0;
                        }
                        
                        /*
                         Note: at this stage the relative heights of the corners and the
                         centre are in the h array, and the corresponding coordinates are
                         in the xh and yh arrays. The centre of the box is indexed by 0
                         and the 4 corners by 1 to 4 as shown below.
                         Each triangle is then indexed by the parameter m, and the 3
                         vertices of each triangle are indexed by parameters m1,m2,and m3.
                         It is assumed that the centre of the box is always vertex 2
                         though this isimportant only when all 3 vertices lie exactly on
                         the same contour level, in which case only the side of the box
                         is drawn.
                         vertex 4 +-------------------+ vertex 3
                         | \               / |
                         |   \    m-3    /   |
                         |     \       /     |
                         |       \   /       |
                         |  m=2    X   m=2   |       the centre is vertex 0
                         |       /   \       |
                         |     /       \     |
                         |   /    m=1    \   |
                         | /               \ |
                         vertex 1 +-------------------+ vertex 2
                         */
                        /* Scan each triangle in the box */
                        for(int m=1;m<=4;m++) {
                            const int m1 = m;
                            const int m2 = 0;
                            if (m != 4)
                            {
                                m3 = m + 1;
                            }
                            else
                            {
                                m3 = 1;
                            }
                            m3 = (m!=4) ? (m+1) : 1;
                            if ((case_value = castab[sh[m1]+1][sh[m2]+1][sh[m3]+1]) == 0)
                                continue;
                            switch (case_value) {
                                case 1: /* Line between vertices 1 and 2 */
                                    x1 = xh[m1];
                                    y1 = yh[m1];
                                    x2 = xh[m2];
                                    y2 = yh[m2];
                                    break;
                                case 2: /* Line between vertices 2 and 3 */
                                    x1 = xh[m2];
                                    y1 = yh[m2];
                                    x2 = xh[m3];
                                    y2 = yh[m3];
                                    break;
                                case 3: /* Line between vertices 3 and 1 */
                                    x1 = xh[m3];
                                    y1 = yh[m3];
                                    x2 = xh[m1];
                                    y2 = yh[m1];
                                    break;
                                case 4: /* Line between vertex 1 and side 2-3 */
                                    x1 = xh[m1];
                                    y1 = yh[m1];
                                    x2 = xsect(m2,m3);
                                    y2 = ysect(m2,m3);
                                    break;
                                case 5: /* Line between vertex 2 and side 3-1 */
                                    x1 = xh[m2];
                                    y1 = yh[m2];
                                    x2 = xsect(m3,m1);
                                    y2 = ysect(m3,m1);
                                    break;
                                case 6: /* Line between vertex 3 and side 1-2 */
                                    x1 = xh[m3];
                                    y1 = yh[m3];
                                    x2 = xsect(m1,m2);
                                    y2 = ysect(m1,m2);
                                    break;
                                case 7: /* Line between sides 1-2 and 2-3 */
                                    x1 = xsect(m1,m2);
                                    y1 = ysect(m1,m2);
                                    x2 = xsect(m2,m3);
                                    y2 = ysect(m2,m3);
                                    break;
                                case 8: /* Line between sides 2-3 and 3-1 */
                                    x1 = xsect(m2,m3);
                                    y1 = ysect(m2,m3);
                                    x2 = xsect(m3,m1);
                                    y2 = ysect(m3,m1);
                                    break;
                                case 9: /* Line between sides 3-1 and 1-2 */
                                    x1 = xsect(m3,m1);
                                    y1 = ysect(m3,m1);
                                    x2 = xsect(m1,m2);
                                    y2 = ysect(m1,m2);
                                    break;
                                default:
                                    break;
                            }
                            
                            /* Finally draw the line */
                            if(proc)
                            {
                                proc(x1,y1,x2,y2,level,args);
                            }
                        } /* m */
                    } /* k - contour */
                } /* i */
            } /* j */
        }
Example #2
0
/*
   Derivation from the fortran version of CONREC by Paul Bourke
   view            ! view of the data
   ilb,iub         ! bounds for first coordinate (column), inclusive
   jlb,jub         ! bounds for second coordinate (row), inclusive
   xCoords         ! column coordinates (first index)
   yCoords         ! row coordinates (second index)
   nc              ! number of contour levels
   z               ! contour levels in increasing order
*/
static Carta::Lib::Algorithms::ContourConrec::Result
conrecFaster(
    Carta::Lib::NdArray::RawViewInterface * view,
    int ilb,
    int iub,
    int jlb,
    int jub,
    const VD & xCoords,
    const VD & yCoords,
    int nc,
    double * z
    )
{
    // we will only need two rows in memory at any given time
//    int nRows = jub - jlb + 1;
    int nCols = iub - ilb + 1;
    double * rows[2] {
        nullptr, nullptr
    };
    std::vector < double > row1( nCols ), row2( nCols );
    rows[0] = & row1[0];
    rows[1] = & row2[0];
    int nextRowToReadIn = 0;

    auto updateRows = [&] () -> void {
        CARTA_ASSERT( nextRowToReadIn < view-> dims()[1] );

        // make a row view into the view
        SliceND rowSlice;
        rowSlice.next().start( nextRowToReadIn ).end( nextRowToReadIn + 1 );
        auto rawRowView = view-> getView( rowSlice );
        nextRowToReadIn++;

        // make a double view of this raw row view
        Carta::Lib::NdArray::Double dview( rawRowView, true );

        // shift the row up
        // note: we could avoid this memory copy if we swapped row[] pointers instead,
        // and alternately read in the data into row1,row2..., for a miniscule performance
        // gain and lot more complicated algorithm
        row1 = row2;

        // read in the data into row2
        int i = 0;
        dview.forEach([&] ( const double & val ) {
                          row2[i++] = val;
                      }
                      );
        CARTA_ASSERT( i == nCols );
    };
    updateRows();

//    NdArray::Double doubleView( view, false );
//    auto acc = [& doubleView] ( int col, int row ) {
//        return doubleView.get( { col, row }
//                               );
//    };

    // to keep the data accessor easy, we use this lambda, and hope the compiler
    // optimizes it into an inline expression... :)
    auto acc = [&] ( int col, int row ) {
        row -= nextRowToReadIn - 2;
        return rows[row][col];
    };

    Carta::Lib::Algorithms::ContourConrec::Result result;
    if ( nc < 1 ) {
        return result;
    }
    result.resize( nc );

#define xsect( p1, p2 ) ( h[p2] * xh[p1] - h[p1] * xh[p2] ) / ( h[p2] - h[p1] )
#define ysect( p1, p2 ) ( h[p2] * yh[p1] - h[p1] * yh[p2] ) / ( h[p2] - h[p1] )

    int m1, m2, m3, case_value;
    double dmin, dmax, x1 = 0, x2 = 0, y1 = 0, y2 = 0;
    int i, j, k, m;
    double h[5];
    int sh[5];
    double xh[5], yh[5];
    int im[4] = {
        0, 1, 1, 0
    }, jm[4] = {
        0, 0, 1, 1
    };
    int castab[3][3][3] = {
        { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } },
        { { 0, 3, 4 }, { 1, 3, 1 }, { 4, 3, 0 } },
        { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } }
    };
    double temp1, temp2;

    // original code went from bottom to top, not sure why
    //    for ( j = ( jub - 1 ) ; j >= jlb ; j-- ) {
    for ( j = jlb ; j < jub ; j++ ) {
        updateRows();
        for ( i = ilb ; i < iub ; i++ ) {
            temp1 = std::min( acc( i, j ), acc( i, j + 1 ) );
            temp2 = std::min( acc( i + 1, j ), acc( i + 1, j + 1 ) );
            dmin = std::min( temp1, temp2 );

            // early abort if one of the values is not finite
            if ( ! std::isfinite( dmin ) ) {
                continue;
            }
            temp1 = std::max( acc( i, j ), acc( i, j + 1 ) );
            temp2 = std::max( acc( i + 1, j ), acc( i + 1, j + 1 ) );
            dmax = std::max( temp1, temp2 );
            if ( dmax < z[0] || dmin > z[nc - 1] ) {
                continue;
            }
            for ( k = 0 ; k < nc ; k++ ) {
                if ( z[k] < dmin || z[k] > dmax ) {
                    continue;
                }
                for ( m = 4 ; m >= 0 ; m-- ) {
                    if ( m > 0 ) {
                        h[m] = acc( i + im[m - 1], j + jm[m - 1] ) - z[k];
                        xh[m] = xCoords[i + im[m - 1]];
                        yh[m] = yCoords[j + jm[m - 1]];
                    }
                    else {
                        h[0] = 0.25 * ( h[1] + h[2] + h[3] + h[4] );
                        xh[0] = 0.50 * ( xCoords[i] + xCoords[i + 1] );
                        yh[0] = 0.50 * ( yCoords[j] + yCoords[j + 1] );
                    }
                    if ( h[m] > 0.0 ) {
                        sh[m] = 1;
                    }
                    else if ( h[m] < 0.0 ) {
                        sh[m] = - 1;
                    }
                    else {
                        sh[m] = 0;
                    }
                }

                /*
                   Note: at this stage the relative heights of the corners and the
                   centre are in the h array, and the corresponding coordinates are
                   in the xh and yh arrays. The centre of the box is indexed by 0
                   and the 4 corners by 1 to 4 as shown below.
                   Each triangle is then indexed by the parameter m, and the 3
                   vertices of each triangle are indexed by parameters m1,m2,and m3.
                   It is assumed that the centre of the box is always vertex 2
                   though this isimportant only when all 3 vertices lie exactly on
                   the same contour level, in which case only the side of the box
                   is drawn.
                      vertex 4 +-------------------+ vertex 3
                               | \               / |
                               |   \    m-3    /   |
                               |     \       /     |
                               |       \   /       |
                               |  m=2    X   m=2   |       the centre is vertex 0
                               |       /   \       |
                               |     /       \     |
                               |   /    m=1    \   |
                               | /               \ |
                      vertex 1 +-------------------+ vertex 2
                */
                /* Scan each triangle in the box */
                for ( m = 1 ; m <= 4 ; m++ ) {
                    m1 = m;
                    m2 = 0;
                    if ( m != 4 ) {
                        m3 = m + 1;
                    }
                    else {
                        m3 = 1;
                    }
                    if ( ( case_value = castab[sh[m1] + 1][sh[m2] + 1][sh[m3] + 1] ) == 0 ) {
                        continue;
                    }
                    switch ( case_value )
                    {
                    case 1 : /* Line between vertices 1 and 2 */
                        x1 = xh[m1];
                        y1 = yh[m1];
                        x2 = xh[m2];
                        y2 = yh[m2];
                        break;
                    case 2 : /* Line between vertices 2 and 3 */
                        x1 = xh[m2];
                        y1 = yh[m2];
                        x2 = xh[m3];
                        y2 = yh[m3];
                        break;
                    case 3 : /* Line between vertices 3 and 1 */
                        x1 = xh[m3];
                        y1 = yh[m3];
                        x2 = xh[m1];
                        y2 = yh[m1];
                        break;
                    case 4 : /* Line between vertex 1 and side 2-3 */
                        x1 = xh[m1];
                        y1 = yh[m1];
                        x2 = xsect( m2, m3 );
                        y2 = ysect( m2, m3 );
                        break;
                    case 5 : /* Line between vertex 2 and side 3-1 */
                        x1 = xh[m2];
                        y1 = yh[m2];
                        x2 = xsect( m3, m1 );
                        y2 = ysect( m3, m1 );
                        break;
                    case 6 : /* Line between vertex 3 and side 1-2 */
                        x1 = xh[m3];
                        y1 = yh[m3];
                        x2 = xsect( m1, m2 );
                        y2 = ysect( m1, m2 );
                        break;
                    case 7 : /* Line between sides 1-2 and 2-3 */
                        x1 = xsect( m1, m2 );
                        y1 = ysect( m1, m2 );
                        x2 = xsect( m2, m3 );
                        y2 = ysect( m2, m3 );
                        break;
                    case 8 : /* Line between sides 2-3 and 3-1 */
                        x1 = xsect( m2, m3 );
                        y1 = ysect( m2, m3 );
                        x2 = xsect( m3, m1 );
                        y2 = ysect( m3, m1 );
                        break;
                    case 9 : /* Line between sides 3-1 and 1-2 */
                        x1 = xsect( m3, m1 );
                        y1 = ysect( m3, m1 );
                        x2 = xsect( m1, m2 );
                        y2 = ysect( m1, m2 );
                        break;
                    default :
                        break;
                    } // switch

                    // add the line segment to the result
                    // ConrecLine( x1, y1, x2, y2, k );
                    if ( std::isfinite( x1 ) && std::isfinite( y1 ) && std::isfinite( x2 ) &&
                         std::isfinite( y2 ) ) {
                        QPolygonF poly;
                        poly.append( QPointF( x1, y1 ) );
                        poly.append( QPointF( x2, y2 ) );
                        result[k].push_back( poly );
                    }
                } /* m */
            } /* k - contour */
        } /* i */
    } /* j */
    return result;

#undef xsect
#undef ysect
} // conrecFaster
Example #3
0
/*
   This is the original C code, pasted verbatim.

   Derivation from the fortran version of CONREC by Paul Bourke
   d               ! matrix of data to contour
   ilb,iub,jlb,jub ! index bounds of data matrix
   x               ! data matrix column coordinates
   y               ! data matrix row coordinates
   nc              ! number of contour levels
   z               ! contour levels in increasing order
*/
void
Contour( double * * d, int ilb, int iub, int jlb, int jub,
         double * x, double * y, int nc, double * z,
         void ( * ConrecLine )( double, double, double, double, double ) )
{
#define xsect( p1, p2 ) ( h[p2] * xh[p1] - h[p1] * xh[p2] ) / ( h[p2] - h[p1] )
#define ysect( p1, p2 ) ( h[p2] * yh[p1] - h[p1] * yh[p2] ) / ( h[p2] - h[p1] )

    int m1, m2, m3, case_value;
    double dmin, dmax, x1 = 0, x2 = 0, y1 = 0, y2 = 0;
    int i, j, k, m;
    double h[5];
    int sh[5];
    double xh[5], yh[5];
    int im[4] = {
        0, 1, 1, 0
    }, jm[4] = {
        0, 0, 1, 1
    };
    int castab[3][3][3] = {
        { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } },
        { { 0, 3, 4 }, { 1, 3, 1 }, { 4, 3, 0 } },
        { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } }
    };
    double temp1, temp2;

    for ( j = ( jub - 1 ) ; j >= jlb ; j-- ) {
        for ( i = ilb ; i <= iub - 1 ; i++ ) {
            temp1 = MIN( d[i][j], d[i][j + 1] );
            temp2 = MIN( d[i + 1][j], d[i + 1][j + 1] );
            dmin = MIN( temp1, temp2 );
            temp1 = MAX( d[i][j], d[i][j + 1] );
            temp2 = MAX( d[i + 1][j], d[i + 1][j + 1] );
            dmax = MAX( temp1, temp2 );
            if ( dmax < z[0] || dmin > z[nc - 1] ) {
                continue;
            }
            for ( k = 0 ; k < nc ; k++ ) {
                if ( z[k] < dmin || z[k] > dmax ) {
                    continue;
                }
                for ( m = 4 ; m >= 0 ; m-- ) {
                    if ( m > 0 ) {
                        h[m] = d[i + im[m - 1]][j + jm[m - 1]] - z[k];
                        xh[m] = x[i + im[m - 1]];
                        yh[m] = y[j + jm[m - 1]];
                    }
                    else {
                        h[0] = 0.25 * ( h[1] + h[2] + h[3] + h[4] );
                        xh[0] = 0.50 * ( x[i] + x[i + 1] );
                        yh[0] = 0.50 * ( y[j] + y[j + 1] );
                    }
                    if ( h[m] > 0.0 ) {
                        sh[m] = 1;
                    }
                    else if ( h[m] < 0.0 ) {
                        sh[m] = - 1;
                    }
                    else {
                        sh[m] = 0;
                    }
                }

                /*
                   Note: at this stage the relative heights of the corners and the
                   centre are in the h array, and the corresponding coordinates are
                   in the xh and yh arrays. The centre of the box is indexed by 0
                   and the 4 corners by 1 to 4 as shown below.
                   Each triangle is then indexed by the parameter m, and the 3
                   vertices of each triangle are indexed by parameters m1,m2,and m3.
                   It is assumed that the centre of the box is always vertex 2
                   though this isimportant only when all 3 vertices lie exactly on
                   the same contour level, in which case only the side of the box
                   is drawn.
                      vertex 4 +-------------------+ vertex 3
                               | \               / |
                               |   \    m-3    /   |
                               |     \       /     |
                               |       \   /       |
                               |  m=2    X   m=2   |       the centre is vertex 0
                               |       /   \       |
                               |     /       \     |
                               |   /    m=1    \   |
                               | /               \ |
                      vertex 1 +-------------------+ vertex 2
                */
                /* Scan each triangle in the box */
                for ( m = 1 ; m <= 4 ; m++ ) {
                    m1 = m;
                    m2 = 0;
                    if ( m != 4 ) {
                        m3 = m + 1;
                    }
                    else {
                        m3 = 1;
                    }
                    if ( ( case_value = castab[sh[m1] + 1][sh[m2] + 1][sh[m3] + 1] ) == 0 ) {
                        continue;
                    }
                    switch ( case_value )
                    {
                    case 1 : /* Line between vertices 1 and 2 */
                        x1 = xh[m1];
                        y1 = yh[m1];
                        x2 = xh[m2];
                        y2 = yh[m2];
                        break;
                    case 2 : /* Line between vertices 2 and 3 */
                        x1 = xh[m2];
                        y1 = yh[m2];
                        x2 = xh[m3];
                        y2 = yh[m3];
                        break;
                    case 3 : /* Line between vertices 3 and 1 */
                        x1 = xh[m3];
                        y1 = yh[m3];
                        x2 = xh[m1];
                        y2 = yh[m1];
                        break;
                    case 4 : /* Line between vertex 1 and side 2-3 */
                        x1 = xh[m1];
                        y1 = yh[m1];
                        x2 = xsect( m2, m3 );
                        y2 = ysect( m2, m3 );
                        break;
                    case 5 : /* Line between vertex 2 and side 3-1 */
                        x1 = xh[m2];
                        y1 = yh[m2];
                        x2 = xsect( m3, m1 );
                        y2 = ysect( m3, m1 );
                        break;
                    case 6 : /* Line between vertex 3 and side 1-2 */
                        x1 = xh[m3];
                        y1 = yh[m3];
                        x2 = xsect( m1, m2 );
                        y2 = ysect( m1, m2 );
                        break;
                    case 7 : /* Line between sides 1-2 and 2-3 */
                        x1 = xsect( m1, m2 );
                        y1 = ysect( m1, m2 );
                        x2 = xsect( m2, m3 );
                        y2 = ysect( m2, m3 );
                        break;
                    case 8 : /* Line between sides 2-3 and 3-1 */
                        x1 = xsect( m2, m3 );
                        y1 = ysect( m2, m3 );
                        x2 = xsect( m3, m1 );
                        y2 = ysect( m3, m1 );
                        break;
                    case 9 : /* Line between sides 3-1 and 1-2 */
                        x1 = xsect( m3, m1 );
                        y1 = ysect( m3, m1 );
                        x2 = xsect( m1, m2 );
                        y2 = ysect( m1, m2 );
                        break;
                    default :
                        break;
                    } // switch

                    /* Finally draw the line */
                    ConrecLine( x1, y1, x2, y2, z[k] );
                } /* m */
            } /* k - contour */
        } /* i */
    } /* j */
} // Contour
Example #4
0
void conrec(vw::ImageView<float>& dem, PointContourSet& cset,
                    int cint, float nodataval,
                    std::list<ContourSegment>& seglist) {
    int m1,m2,m3,case_value;
    double zmin,zmax;
    register int c,i,j,m;
    double h[5];
    int sh[5];
    double xh[5], yh[5];
    int im[4] = {0,1,1,0}, jm[4] = {0,0,1,1};
    int castab[3][3][3] =
        { { {0,0,8},{0,2,5},{7,6,9} },
          { {0,3,4},{1,3,1},{4,3.0} },
          { {9,6,7},{5,2,0},{8,0,0} } };
    ContourSegment seg;

    vw::vw_out(vw::InfoMessage, "console") << "Running CONREC\n";
    vw::vw_out(vw::DebugMessage, "console") << "\tFinding contours\n";
    for (i=0; i < dem.cols()-1; i++) {
        for (j=0; j < dem.rows()-1; j++) {
            zmin = min_nodata( min_nodata(dem(i,j),   dem(i,j+1),   nodataval),
                               min_nodata(dem(i+1,j), dem(i+1,j+1), nodataval),
                               nodataval);
            if (zmin == nodataval) continue;

            zmax = max_nodata( max_nodata(dem(i,j),   dem(i,j+1),   nodataval),
                               max_nodata(dem(i+1,j), dem(i+1,j+1), nodataval),
                               nodataval);

            int cmin = ceil(zmin / cint) * cint;
            int cmax = floor(zmax / cint) * cint;
            for (c = cmin; c <= cmax; c += cint) {
                //printf("(%d,%d) c: %d\n",i,j,c);
                int goodvals = 0;
                h[0] = 0;
                for (m = 4; m >= 0; m--) {
                    if (m > 0) {
                        if (dem(i+im[m-1], j+jm[m-1]) == nodataval)
                            h[m] = nodataval;
                        else {
                            h[m] = dem(i+im[m-1], j+jm[m-1]) - c;
                            h[0] += h[m];
                            goodvals++;
                        }
                        xh[m] = i + im[m-1];
                        yh[m] = j + jm[m-1];
                        //printf("h[%d]: %0.2f (%0.2f)\n",m,dem(i+im[m-1],j+jm[m-1]),h[m]);
                    } else {
                        h[0] /= goodvals;
                        xh[0] = i + 0.5;
                        yh[0] = j + 0.5;
                        //printf("h[%d]: ... (%0.2f)\n",m,h[m]);
                    }


                    if (h[m] > 0.0)
                        sh[m] = 1;
                    else if (h[m] < 0.0)
                        sh[m] = -1;
                    else
                        sh[m] = 0;
                }
                //=================================================================
                //
                // Note: at this stage the relative heights of the corners and the
                // centre are in the h array, and the corresponding coordinates are
                // in the xh and yh arrays. The centre of the box is indexed by 0
                // and the 4 corners by 1 to 4 as shown below.
                // Each triangle is then indexed by the parameter m, and the 3
                // vertices of each triangle are indexed by parameters m1,m2,and
                // m3.
                // It is assumed that the centre of the box is always vertex 2
                // though this isimportant only when all 3 vertices lie exactly on
                // the same contour level, in which case only the side of the box
                // is drawn.
                //
                //
                //      vertex 4 +-------------------+ vertex 3
                //               | \               / |
                //               |   \    m-3    /   |
                //               |     \       /     |
                //               |       \   /       |
                //               |  m=4    X   m=2   |       the centre is vertex 0
                //               |       /   \       |
                //               |     /       \     |
                //               |   /    m=1    \   |
                //               | /               \ |
                //      vertex 1 +-------------------+ vertex 2
                //
                //
                //
                //               Scan each triangle in the box
                //
                //=================================================================
                for (m=1;m<=4;m++) {
                    m1 = m;
                    m2 = 0;
                    m3 = (m==4) ? 1 : m+1;

                    if (h[m1] == nodataval || h[m3] == nodataval)
                        continue;

                    case_value = castab[sh[m1]+1][sh[m2]+1][sh[m3]+1];
                    if (case_value!=0) {
                        ContourSegment seg;
                        seg.level = c;
                        switch (case_value) {
                            //===========================================================
                            //     Case 1 - Line between vertices 1 and 2
                            //===========================================================
                            case 1:
                                seg.a = ContourPoint(xh[m1], yh[m2]);
                                seg.b = ContourPoint(xh[m2], yh[m2]);
                                break;
                            //===========================================================
                            //     Case 2 - Line between vertices 2 and 3
                            //===========================================================
                            case 2:
                                seg.a = ContourPoint(xh[m2], yh[m2]);
                                seg.b = ContourPoint(xh[m3], yh[m3]);
                                break;
                            //===========================================================
                            //     Case 3 - Line between vertices 3 and 1
                            //===========================================================
                            case 3:
                                seg.a = ContourPoint(xh[m3], yh[m3]);
                                seg.b = ContourPoint(xh[m1], yh[m1]);
                                break;
                            //===========================================================
                            //     Case 4 - Line between vertex 1 and side 2-3
                            //===========================================================
                            case 4:
                                seg.a = ContourPoint(xh[m1], yh[m1]);
                                seg.b = ContourPoint(xsect(m2,m3), ysect(m2,m3));
                                break;
                            //===========================================================
                            //     Case 5 - Line between vertex 2 and side 3-1
                            //===========================================================
                            case 5:
                                seg.a = ContourPoint(xh[m2], yh[m2]);
                                seg.b = ContourPoint(xsect(m3,m1), ysect(m3,m1));
                                break;
                            //===========================================================
                            //     Case 6 - Line between vertex 3 and side 1-2
                            //===========================================================
                            case 6:
                                seg.a = ContourPoint(xh[m3], yh[m3]);
                                seg.b = ContourPoint(xsect(m1,m2), ysect(m1,m2));
                                break;
                            //===========================================================
                            //     Case 7 - Line between sides 1-2 and 2-3
                            //===========================================================
                            case 7:
                                seg.a = ContourPoint(xsect(m1,m2), ysect(m1,m2));
                                seg.b = ContourPoint(xsect(m2,m3), ysect(m2,m3));
                                break;
                            //===========================================================
                            //     Case 8 - Line between sides 2-3 and 3-1
                            //===========================================================
                            case 8:
                                seg.a = ContourPoint(xsect(m2,m3), ysect(m2,m3));
                                seg.b = ContourPoint(xsect(m3,m1), ysect(m3,m1));
                                break;
                            //===========================================================
                            //     Case 9 - Line between sides 3-1 and 1-2
                            //===========================================================
                            case 9:
                                seg.a = ContourPoint(xsect(m3,m1), ysect(m3,m1));
                                seg.b = ContourPoint(xsect(m1,m2), ysect(m1,m2));
                                break;
                            default:
                                break;
                        }
                        seglist.push_back(seg);
                    }
                }
            }
        }
    }
    vw::vw_out(vw::DebugMessage, "console")
        << "\tCONREC found " << seglist.size() << " segments" << std::endl;
}