コード例 #1
0
void BpDocument::barYMinMax( int yid, double &yMin, double &yMax )
{
    // Store the x-variable range and step size in locals.
    int    bars  = ( tableRows() < graphMaxBars )
                 ? tableRows()
                 : graphMaxBars ;
    int    vid   = yid;
    int    vStep = tableVars();
    double val;
    yMin = yMax = tableVal( yid );
    for ( int row = 1;
          row <= bars;
          row++ )
    {
        val  = tableVal( vid );
        vid += vStep;
        yMin = ( val < yMin ) ? val : yMin;
        yMax = ( val > yMax ) ? val : yMax;
    }
    return;
}
コード例 #2
0
void BpDocument::graphYMinMax( int yid, double &yMin, double &yMax )
{
    // Store the step size and number of curves
    int vStep  = tableCols() * tableVars();
    int curves = ( tableCols() < graphMaxLines )
               ? ( tableCols() )
               : graphMaxLines;
    bool firstOne = true;
    double val;
    int vid;
    yMin = yMax = 0.;

    // Loop for each zVar family curve value in this graph (or at least once!).
    // Note that zVar count is in tableCols(), e.g. each column stores a curve,
    // and zVar values are in tableCol( col ).
    for ( int col = 0;
          col < curves;
          col++ )
    {
        // tableVal( vid ) offset of first y-value for this curve.
        vid = yid + col * tableVars();
        // Examine every y point for this curve.
        // Note number of points is in tableRows().
        for ( int point = 0;
              point < tableRows();
              point++ )
        {
            val = tableVal( vid );
            vid += vStep;
            // If this is the first point, initialize yMin and yMax.
            if ( firstOne )
            {
                yMin = yMax = val;
                firstOne = false;
            }
            // otherwise accumulate yMin and yMax.
            else
            {
                yMin = ( val < yMin ) ? val : yMin;
                yMax = ( val > yMax ) ? val : yMax;
            }
        }
    } // Next z-variable curve.
    return;
}
コード例 #3
0
void BpDocument::composeLineGraph( int yid, EqVar *xVar, EqVar *yVar,
    EqVar *zVar, GraphAxleParms *xParms, GraphAxleParms *yParms )
{
    //--------------------------------------------------------------------------
    // 1: Set up fonts, pens, and colors used by this graph
    //--------------------------------------------------------------------------

    // Graph fonts
    QFont  textFont( property()->string( "graphTextFontFamily" ),
                    property()->integer( "graphTextFontSize" ) );
    QColor textColor( property()->color( "graphTextFontColor" ) );
    QPen   textPen( textColor );
    // How many colors are requested?
    QString colorName( property()->color( "graphLineColor" ) );
    int colors = 1;
    if ( colorName == "rainbow" )
    {
        colors = property()->integer( "graphRainbowColors" );
    }
    // Allocate number of requested colors.
    QColor *color = new QColor [colors];
    checkmem( __FILE__, __LINE__, color, "QColor color", colors );
    int colorId = 0;
    // If only 1 color...
    if ( colors == 1 )
    {
        color[0].setNamedColor( colorName );
    }
    // else if rainbow colors are requested...
    else
    {
        // todo - add some code to check conflicts with graphBackgroundColor
        // and graphGridColor (if graphGridWidth > 0 ).
        int hue = 0;
        for ( colorId = 0;
              colorId < colors;
              colorId++ )
        {
            color[colorId].setHsv( hue, 255, 255);
            hue += 360 / colors;
        }
        colorId = 0;
    }
    // Set up line width and color
    int lineWidth = property()->integer( "graphLineWidth" );
    QPen pen( color[0], lineWidth, SolidLine );

    //--------------------------------------------------------------------------
    // 2: Create the graph and add its curves.
    //--------------------------------------------------------------------------

    // Initialize graph and variables
    Graph      g;
    GraphLine *line[graphMaxLines];
    double     l_x[graphMaxSteps];
    double     l_y[graphMaxSteps];
    int        curves = ( tableCols() < graphMaxLines )
                  ? ( tableCols() )
                  : ( graphMaxLines );
    int        points = tableRows();
    int        vStep  = tableCols() * tableVars();

    // Loop for each zVar family curve value in this graph (or at least once!).
    // Note that zVar count is in tableCols(), e.g. each column stores a curve,
    // and zVar values are in tableCol( col ).
    int col, vid;
    for ( col = 0;
          col < curves;
          col++ )
    {
        // tableVal[] offset of first y-value for this curve.
        vid = yid + col * tableVars();
        // Set up the y[point] array for this curve.
        // Note number of points is in tableRows() and
        // point x values are in tableRow( point ).
        for ( int point = 0;
              point < points;
              point++ )
        {
            l_x[point] = tableRow( point );
            l_y[point] = tableVal( vid );
            vid += vStep;
        }
        // If we're out of colors, start over.
        if ( colorId >= colors )
        {
            colorId = 0;
        }
        // Create a graph line (with its own copy of the data).
        pen.setColor( color[colorId++] );
        line[col] = g.addGraphLine( points, l_x, l_y, pen );
    } // Next z-variable curve.

    //--------------------------------------------------------------------------
    // 3: Add curve labels if there is more than 1 curve.
    //--------------------------------------------------------------------------

    QString label;
    if ( curves > 1 )
    {
        colorId = 0;

#define GRAPH_LABEL_METHOD_1

#ifdef GRAPH_LABEL_METHOD_1
        // Label x array index step size between labels
        int j1 = points / curves;
        if ( j1 < 1 )
        {
            j1 = 1;
        }
        // Label x array index offset
        int j0 = j1 / 2;
#endif
        double xLabel, yLabel;
        int idx;
        // Loop for each z-variable curve.
        for ( col = 0;
              col < curves;
              col++ )
        {
            // Get a new color for the curve.
            if ( colorId >= colors )
            {
                colorId = 0;
            }
            // Set the curve label.
            if ( zVar->isDiscrete() )
            {
                int iid = (int) tableCol( col );
                label = zVar->m_itemList->itemName( iid );
            }
            else if ( zVar->isContinuous() )
            {
				int decimals = zVar->m_displayDecimals;
                label.sprintf( "%1.*f",
                    zVar->m_displayDecimals, tableCol( col ) );
				// Remove all trailing zeros
				while ( decimals && label.endsWith( "0" ) )
				{
					label = label.left( label.length()-1 );
					decimals--;
				}
            }

#ifdef GRAPH_LABEL_METHOD_1
            // Determine an x-axis index for the label position.
            idx = ( j0 + col * j1 ) % points;
            xLabel = line[col]->m_x[idx];
            yLabel = line[col]->m_y[idx];
#endif

#ifdef GRAPH_LABEL_METHOD_2
            // NEW LABEL POSITIONING METHOD STARTS HERE
            // Find the x position where this variable has the maximum y
            // clearance
            // Loop for each x value for this curve
            idx = 0;
            double dMax = 0;
            double dir  = 1.;
            double yMin = yParms->m_axleMin;
            double yMax = yParms->m_axleMax;
            for ( int row=1; row<tableRows()-1; row++ )
            {
                // Find vertical clearance above and below this x point
                double y0 = m_eqTree->getResult( row, col, yid );
                // Don't consider locations outside the viewport
                if ( y0 < yMin || y0 > yMax )
                {
                    continue;
                }
                double below = y0 - yMin;
                double above = yMax - y0;
                double dist, y1;
                // Loop for each family member curve
                for ( int c=0; c<curves; c++ )
                {
                    // Skip self
                    if ( c == col )
                    {
                        continue;
                    }
                    y1 = m_eqTree->getResult( row, c, yid );
                    y1 = ( y1 < yMax ) ? y1 : yMax;
                    y1 = ( y1 > yMin ) ? y1 : yMin;
                    // Shrink vertical clearance above and below this x point?
                    if ( y0 <= y1 )
                    {
                        dist = y1 - y0;
                        above = ( dist < above ) ? dist : above;
                    }
                    else
                    {
                        dist = y0 - y1;
                        below = ( dist < below ) ? dist : below;
                    }
                }
                // Is this the maximum vertical clearance so far?
                if ( above + below > dMax )
                {
                    dMax = above + below;
                    idx  = row;
                    dir  = ( above > below ) ? 1. : -1;
                }
            }
            xLabel = line[col]->m_x[idx];
            double offset = dir * 0.02 * ( yMax - yMin );
            yLabel = line[col]->m_y[idx] + offset;
#endif
            // Set the label text, font, color, and position.
            line[col]->setGraphLineLabel( label, xLabel, yLabel, textFont,
                QColor( color[colorId++] ) );
        } // Next curve.

        // Add a z-variable label to the graph.
        label = *(zVar->m_label);
        if ( zVar->isContinuous() )
        {
            label = *(zVar->m_label) + "\n" + zVar->displayUnits(true);
        }
        g.setMultipleCurveLabel( label );
    }

    //--------------------------------------------------------------------------
    // 4: Compose the graph and add an output page to draw it onto
    //--------------------------------------------------------------------------

    composeGraphBasics( &g, true, xVar, yVar, zVar, curves, xParms, yParms );

    // Create a separate output page for this graph.
    QString text("");
    translate( text, "BpDocument:Graphs:By" );
    label = *(yVar->m_label) + " " + text + " " + *(xVar->m_label);
    if ( curves > 1 )
    {
        translate( text, "BpDocument:Graphs:And" );
        label += " " + text + " " + *(zVar->m_label);
    }
    startNewPage( label, TocLineGraph );

    // This is how we save the graph and its composer.
    m_composer->graph( g,
        m_pageSize->m_marginLeft
            + m_pageSize->m_bodyWd * property()->real( "graphXOffset" ),
        m_pageSize->m_marginTop
            + m_pageSize->m_bodyHt * property()->real( "graphYOffset" ),
        m_pageSize->m_bodyWd * property()->real( "graphScaleWidth" ),
        m_pageSize->m_bodyHt * property()->real( "graphScaleHeight" )
    );

    // Be polite and stop the composer.
    m_composer->end();
    delete[] color;
    return;
}
コード例 #4
0
bool BpDocument::composeGraphs( bool lineGraphs, bool showDialogs )
{

    // Bar graph settings
    int    tics = 2;
    double max  = 100.;
    double min  = 0.;
    // Line graph settings
    if ( lineGraphs )
    {
        tics = 11;
        max = tableRow( tableRows()-1 );
        min = tableRow(0);
    }
    GraphAxleParms *xParms = new GraphAxleParms( min, max, tics );
    checkmem( __FILE__, __LINE__, xParms, "GraphAxleParms xParms", 1 );
    if ( lineGraphs && min > 0.
      && property()->boolean( "graphXOriginAtZero" ) )
    {
        xParms->useOrigin();
    }

    // Determine the x-, y-, and z-variables.
    EqVar *xVar = m_eqTree->m_rangeVar[0];
    EqVar *zVar = m_eqTree->m_rangeVar[1];
    EqVar *yVar = 0;

    //--------------------------------------------------------------------------
    // 2: Determine nice axis parameters for the x- and all the y-variables.
    //--------------------------------------------------------------------------

    // Initialize the Y axle for each graph to a nice range
    QPtrList<GraphAxleParms> *yParmsList = new QPtrList<GraphAxleParms>();
    yParmsList->setAutoDelete( true );
    GraphAxleParms *yParms = 0;
    int yid;
    for ( yid = 0;
          yid < tableVars();
          yid++ )
    {
        yVar = tableVar( yid );
        yParms = 0;
        // The yVar must be continuous.
        if ( yVar->isContinuous() )
        {
            // Get Y range
            if ( lineGraphs )
            {
                graphYMinMax( yid, min, max );
            }
            else
            {
                barYMinMax( yid, min, max );
            }
            // Determine and store nice axis parameters
            tics = 11;
            yParms = new GraphAxleParms( min, max, tics );
            checkmem( __FILE__, __LINE__, yParms, "GraphAxleParms yParms", 1 );
            yParmsList->append( yParms );
            // If bar graph, or line graphs must start at origin
            if ( min > 0. )
            {
                if ( ! lineGraphs
                    || property()->boolean( "graphYOriginAtZero" ) )
                {
                    yParms->useOrigin();
                }
            }
            // If min and max are the same, make them different
            if ( min == max )
            {
                yParms->setAxle( min-1., max+1., 3 );
            }
        }
    }

    //--------------------------------------------------------------------------
    // 1: Allow the user to change the axle parameters.
    //--------------------------------------------------------------------------

    if ( showDialogs
      && property()->boolean( "graphYUserRange" ) )
    {
        GraphLimitsDialog *dialog =
            new GraphLimitsDialog( this, yParmsList, "graphLimitsDialog" );
        checkmem( __FILE__, __LINE__, dialog, "GraphLimitsDialog dialog", 1 );
        if ( dialog->exec() == QDialog::Accepted )
        {
            dialog->store();
        }
        delete dialog;  dialog = 0;
    }

    //--------------------------------------------------------------------------
    // 3: Draw each graph.
    //--------------------------------------------------------------------------

    // Set up the progress dialog.
    int step = 0;
    int steps = tableVars();
    QString text(""), button("");
    if ( lineGraphs )
    {
        translate( text, "BpDocument:Graphs:DrawingLineGraphs" );
    }
    else
    {
        translate( text, "BpDocument:Graphs:DrawingBarGraphs" );
    }
    translate( button, "BpDocument:Graphs:Abort" );
    QProgressDialog *progress = new QProgressDialog(
        QString( text ).arg( steps ), button, steps );
    Q_CHECK_PTR( progress );
    progress->setMinimumDuration( 0 );
    progress->setProgress( 0 );

    // Loop for each output variable: one graph is composed per output variable.
    bool result = true;
    for ( yid = 0, yParms = yParmsList->first();
          yid < tableVars();
          yid++ )
    {
        yVar = tableVar( yid );
        // The yVar must be continuous.
        if ( yVar->isContinuous() )
        {
            // Recompute nice Y axis
            //min = ( yParms->m_axleMin < yParms->m_dataMin )
            //    ? yParms->m_axleMin
            //    : yParms->m_dataMin;
            min = yParms->m_axleMin;
            //max = ( yParms->m_axleMax > yParms->m_dataMax )
            //    ? yParms->m_axleMax
            //    : yParms->m_dataMax;
            max = yParms->m_axleMax;
            // If min and max are the same, make them different
            tics = 11;
            if ( min == max )
            {
                yParms->setAxle( min-1., max+1., 3 );
            }
            // Compose this graph.
            if ( lineGraphs )
            {
                composeLineGraph( yid, xVar, yVar, zVar, xParms, yParms );
            }
            else
            {
                composeBarGraph( yid, xVar, yVar, xParms, yParms );
            }
            // Update progress dialog.
            progress->setProgress( ++step );
            qApp->processEvents();
            if ( progress->wasCancelled() )
            {
                result = false;
                break;
            }
            yParms = yParmsList->next();
        }
    }
    // Cleanup and return.
    delete progress;    progress = 0;
    delete xParms;      xParms = 0;
    delete yParmsList;  yParmsList = 0;
    return( result );
}
コード例 #5
0
void BpDocument::composeBarGraph( int yid, EqVar *xVar, EqVar *yVar,
        GraphAxleParms *xParms, GraphAxleParms *yParms )
{
    //--------------------------------------------------------------------------
    // 1: Set up fonts, pens, and colors used by this graph
    //--------------------------------------------------------------------------

    // Graph fonts.
    QFont textFont( property()->string( "graphTextFontFamily" ),
                    property()->integer( "graphTextFontSize" ) );
    QColor textColor( property()->color( "graphTextFontColor" ) );
    QPen textPen( textColor );

    // How many colors are requested?
    QString colorName( property()->color( "graphBarColor" ) );
    int colors = 1;
    if ( colorName == "rainbow" )
    {
        colors = property()->integer( "graphRainbowColors" );
    }
    // Allocate number of requested colors.
    QColor *color = new QColor [colors];
    checkmem( __FILE__, __LINE__, color, "QColor color", colors );
    int colorId = 0;
    // If only 1 color...
    if ( colors == 1 )
    {
        color[0].setNamedColor( colorName );
    }
    // else if rainbow colors are requested.
    else
    {
        // \todo - add some code to check conflicts with graphBackgroundColor
        // and graphGridColor (if graphGridWidth > 0 ).
        int hue = 0;
        for ( colorId = 0;
              colorId < colors;
              colorId++ )
        {
            color[colorId].setHsv( hue, 255, 255);
            hue += 360 / colors;
        }
        colorId = 0;
    }
    // Setup bar brush and color
    QBrush barBrush( color[colorId], Qt::SolidPattern );

    //--------------------------------------------------------------------------
    // 2: Create the graph and its text and axles.
    //--------------------------------------------------------------------------

    // Initialize graph and variables
    Graph g;
    int bars  = ( tableRows() < graphMaxBars )
              ? tableRows()
              : graphMaxBars ;
    int vStep = tableVars();

    // Draw thew basic graph (axis and text)
    composeGraphBasics( &g, false, xVar, yVar, 0, bars, xParms, yParms );

    //--------------------------------------------------------------------------
    // 3: Add the bars.
    //--------------------------------------------------------------------------

    // Each bar occupies 2/3 of its x range, plus a 1/3 padding on right.
    double xMin = xParms->m_axleMin;
    double xMax = xParms->m_axleMax;
    double xMinorStep = ( xMax - xMin ) / (double) ( 3 * bars + 1 );
    double xMajorStep = 3. * xMinorStep;

    // Create each data bar and add it to the graph.
    double x0, x1, y0, y1, xl;
    double yl = 0.;
    double rotation = 0.;
    QString label;
    int row, vid;
    for ( row = 0, vid = yid;
          row < bars;
          row++, vid += vStep )
    {
        x0 = xMin + xMinorStep + row * xMajorStep;
        x1 = xMin + ( row + 1 ) * xMajorStep;
        y0 = yParms->m_axleMin;
        y1 = tableVal( vid );
        xl = 0.5 * (x0 + x1) ;

        // If we're out of colors, start over.
        if ( colorId >= colors )
        {
            colorId = 0;
        }

        // Set the bar brush to this color.
        barBrush.setColor( color[colorId++] );

        // Create the graph bar.
        GraphBar *bar = g.addGraphBar( x0, y0, x1, y1, barBrush, textPen );

        // Create the bar label.
        int iid = (int) tableRow( row );
        label = xVar->m_itemList->itemName( iid );
        bar->setGraphBarLabel( label, xl, yl, textFont, textColor, rotation );
    }

    //--------------------------------------------------------------------------
    // 4: Add an output page on which to draw the graph.
    //--------------------------------------------------------------------------

    // Create a separate page for this graph.
    QString text("");
    translate( text, "BpDocument:Graphs:By" );
    label = QString( "%1 %2 %3" )
        .arg( *(yVar->m_label) )
        .arg( text )
        .arg( *(xVar->m_label) );
    startNewPage( label, TocBarGraph );

    // This is how we save the graph and its composer.
    m_composer->graph( g,
        m_pageSize->m_marginLeft
            + m_pageSize->m_bodyWd * property()->real( "graphXOffset" ),
        m_pageSize->m_marginTop
            + m_pageSize->m_bodyHt * property()->real( "graphYOffset" ),
        m_pageSize->m_bodyWd * property()->real( "graphScaleWidth" ),
        m_pageSize->m_bodyHt * property()->real( "graphScaleHeight" )
    );

    // Be polite and stop the composer.
    m_composer->end();
    delete[] color;
    return;
}
コード例 #6
0
void BpDocument::composeTable3Spreadsheet( FILE *fptr, int vid,
        EqVar *rowVar, EqVar *colVar )
{
    EqVar *outVar = tableVar(vid);
    QString qStr;
    int iid;
    // Two blank lines between tables
    fprintf( fptr, "\n\n" );
    fprintf( fptr, "%s\t%s\n",
             (*(outVar->m_label)).latin1(),
             ( outVar->isContinuous() ) ? outVar->displayUnits().latin1() : "" );
    fprintf( fptr, "%s\t%s\n",
             (*(rowVar->m_label)).latin1(),
             ( rowVar->isContinuous() ) ? rowVar->displayUnits().latin1() : "" );
    fprintf( fptr, "%s\t%s\n",
             (*(colVar->m_label)).latin1(),
             ( colVar->isContinuous() ) ? colVar->displayUnits().latin1() : "" );

    // First column header row
    fprintf( fptr, "\n" );
    fprintf( fptr, "%s\t \t%s\t%s\n",
             (*(rowVar->m_hdr0)).latin1(),
             (*(colVar->m_hdr0)).latin1(),
             (*(colVar->m_hdr1)).latin1() );

    // Second column header row
    fprintf( fptr, "%s", (*(rowVar->m_hdr1)).latin1() );
    int row, col;
    for ( col = 0; col < tableCols(); col++ )
    {
        if ( colVar->isDiscrete() )
        {
            iid = (int) tableCol( col );
            qStr = colVar->m_itemList->itemName( iid );
        }
        else if ( colVar->isContinuous() )
        {
            // CDB DECIMALS MOD
            if ( false )
            {
                qStr.sprintf( " %1.*f",	colVar->m_displayDecimals, tableCol( col ) );
            }
            else
            {
                qStr.sprintf( " %1.*f", m_colDecimals, tableCol( col ) );
            }
        }
        fprintf( fptr, "\t%s", qStr.latin1() );
    }
    fprintf( fptr, "\n" );

    // Table body
    int out = vid;
    for ( row = 0; row < tableRows(); row++ )
    {
        // Row value is in the first column
        if ( rowVar->isDiscrete() )
        {
            iid = (int) tableRow( row );
            qStr = rowVar->m_itemList->itemName( iid );
        }
        else if ( rowVar->isContinuous() )
        {
            // CDB DECIMALS MOD
            if ( false )
            {
                qStr.sprintf( "%1.*f", rowVar->m_displayDecimals, tableRow( row ) );
            }
            else
            {
                qStr.sprintf( "%1.*f", m_rowDecimals, tableRow( row ) );
            }
        }
        fprintf( fptr, "%s", qStr.latin1() );
        // Remaining columns
        for ( col = 0; col < tableCols(); col++ )
        {
            if ( outVar->isDiscrete() )
            {
                iid = (int) tableVal( out );
                qStr = outVar->m_itemList->itemName( iid );
            }
            else if ( outVar->isContinuous() )
            {
                qStr.sprintf( "%1.*f",
                              outVar->m_displayDecimals, tableVal( out ) );
            }
            fprintf( fptr, "\t%s", qStr.latin1() );
            out += tableVars();
        }   // Next table column
        fprintf( fptr, "\n" );
    } // Next table row
    return;
}
コード例 #7
0
void BpDocument::composeTable3( int vid, EqVar *rowVar, EqVar *colVar )
{
    // START THE STANDARD PREAMBLE USED BY ALL TABLE COMPOSITION FUNCTIONS.
    // WIN98 requires that we actually create a font here and use it for
    // font metrics rather than using the widget's font.
    QFont subTitleFont( property()->string( "tableSubtitleFontFamily" ),
                        property()->integer( "tableSubtitleFontSize" ) );
    QPen subTitlePen( property()->color( "tableSubtitleFontColor" ) );
    QFontMetrics subTitleMetrics( subTitleFont );

    QFont textFont( property()->string( "tableTextFontFamily" ),
                    property()->integer( "tableTextFontSize" ) );
    QPen textPen( property()->color( "tableTextFontColor" ) );
    QFontMetrics textMetrics( textFont );

    QFont titleFont( property()->string( "tableTitleFontFamily" ),
                     property()->integer( "tableTitleFontSize" ) );
    QPen titlePen( property()->color( "tableTitleFontColor" ) );
    QFontMetrics titleMetrics( titleFont );

    QFont valueFont( property()->string( "tableValueFontFamily" ),
                     property()->integer( "tableValueFontSize" ) );
    QPen valuePen( property()->color( "tableValueFontColor" ) );
    QFontMetrics valueMetrics( valueFont );

    bool doRowBg = property()->boolean( "tableRowBackgroundColorActive" );
    QBrush rowBrush( property()->color( "tableRowBackgroundColor" ),
                     Qt::SolidPattern );

    QString text("");

    // Store pixel resolution into local variables.
    double yppi  = m_screenSize->m_yppi;
    double xppi  = m_screenSize->m_xppi;
    double m_padWd = m_pageSize->m_padWd;

    // Determine the height of the various display fonts.
    double textHt, titleHt, valueHt, rowHt, x0, x1;
    textHt  = ( textMetrics.lineSpacing()  + m_screenSize->m_padHt ) / yppi;
    titleHt = ( titleMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi;
    valueHt = ( valueMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi;
    rowHt   = ( textHt > valueHt )
              ? textHt
              : valueHt;
    // END THE STANDARD PREAMBLE USED BY ALL TABLE COMPOSITION FUNCTIONS.

    // Determine the number of rows we can display on a page.
    int rowsPerPage = (int)
                      ( ( m_pageSize->m_bodyHt - 5. * titleHt - 4. * textHt ) / rowHt );

    // Number of pages the table requires to accomodate all the rows.
    int pagesLong = 1 + (int) ( tableRows() / rowsPerPage );

    // Arrays to hold the output values' column information.
    // Page on which the output value column appears.
    int *colPage = new int[ tableCols() ];
    checkmem( __FILE__, __LINE__, colPage, "int colPage", tableCols() );
    // Horizontal position of each output value column.
    double *colXPos = new double[ tableCols() ];
    checkmem( __FILE__, __LINE__, colXPos, "double colXPos", tableCols() );
    // Column header text.
    QString *colText = new QString[ tableCols() ];
    checkmem( __FILE__, __LINE__, colText, "double colText", tableCols() );

    // Prescription shading?
    bool doRx = property()->boolean( "tableShading" );
    bool doBlank = property()->boolean( "tableShadingBlank" );

    // Determine the row variable's (left-most) column width.
    int row, iid, cell;
    double len;
    QString qStr;
    // Start wide enough to hold the variable name and units.
    double rowWd = m_padWd
                   + ( (double) headerWidth( rowVar, textMetrics ) / xppi );
    // Enlarge it to hold the fattest row value.
    m_rowDecimals = 0;
    for ( row = 0;
            row < tableRows();
            row++ )
    {
        if ( rowVar->isDiscrete() )
        {
            iid = (int) tableRow( row );
            qStr = rowVar->m_itemList->itemName( iid ) + "MMM";
        }
        else if ( rowVar->isContinuous() )
        {
            // CDB DECIMALS MOD
            if ( false )
            {
                qStr.sprintf( "%1.*fMMM", rowVar->m_displayDecimals, tableRow( row ) );
            }
            else
            {
                // Start with 6 decimals for this row value
                int decimals = 6;
                qStr.sprintf( "%1.*f", decimals, tableRow( row ) );
                // Remove all trailing zeros
                while ( qStr.endsWith( "0" ) )
                {
                    qStr = qStr.left( qStr.length()-1 );
                    decimals--;
                }
                // Update m_rowDecimals digits
                m_rowDecimals = ( decimals > m_rowDecimals ) ? decimals : m_rowDecimals;
                qStr.append( "MWM" );
            }
        }
        len = (double) textMetrics.width( qStr ) / xppi;
        if ( len > rowWd )
        {
            rowWd = len;
        }
    }
    // Find the fattest output value for this table variable.
    int col;
    int out = vid;
    EqVar *outVar = tableVar(vid);
    double colWd = 0;
    for ( row = 0;
            row < tableRows();
            row++ )
    {
        for ( col = 0;
                col < tableCols();
                col++ )
        {
            if ( outVar->isDiscrete() )
            {
                iid = (int) tableVal( out );
                qStr = outVar->m_itemList->itemName( iid ) + "WM";
            }
            else if ( outVar->isContinuous() )
            {
                qStr.sprintf( "%1.*fWM",
                              outVar->m_displayDecimals, tableVal( out ) );
            }
            len = (double) textMetrics.width( qStr ) / xppi;
            if ( len > colWd )
            {
                colWd = len;
            }
            out += tableVars();
        }   // Next table column.
    } // Next table row.

    // Set the column header value text.
    m_colDecimals = 0;
    for ( col = 0;
            col < tableCols();
            col++ )
    {
        if ( colVar->isDiscrete() )
        {
            iid = (int) tableCol( col );
            colText[col] = colVar->m_itemList->itemName( iid );
        }
        else if ( colVar->isContinuous() )
        {
            // CDB DECIMALS MOD
            if ( false )
            {
                colText[col].sprintf( " %1.*f",	colVar->m_displayDecimals, tableCol( col ) );
            }
            else
            {
                // Start with 6 decimals for this row value
                int decimals = 6;
                colText[col].sprintf( " %1.*f", decimals, tableCol( col ) );
                // Remove all trailing zeros
                while ( colText[col].endsWith( "0" ) )
                {
                    colText[col] = colText[col].left( colText[col].length()-1 );
                    decimals--;
                }
                // Update Decimals digits
                m_colDecimals = ( decimals > m_colDecimals ) ? decimals : m_colDecimals;
            }
        }
        // Expand the column width to accomodate the header value text?
        len = (double) textMetrics.width( colText[col] ) / xppi;
        if ( len > colWd )
        {
            colWd = len;
        }
    }   // Next table column.
    // CDB DECIMALS MOD
    for ( col = 0;  col < tableCols(); col++ )
    {
        if ( colVar->isContinuous() )
        {
            colText[col].sprintf( " %1.*f", m_colDecimals, tableCol( col ) );
        }
    }
    // Add padding between each column.
    colWd += m_padWd;

    // Determine each column's position on each page.
    int pagesWide = 1;
    // Horizontal position of first column on the first page.
    double xpos = m_pageSize->m_bodyLeft + rowWd + 2. * m_padWd;
    for ( col = 0;
            col < tableCols();
            col++ )
    {
        // If past the right page edge, start a new page.
        if ( xpos + colWd > m_pageSize->m_bodyRight )
        {
            // The table page width has just increased.
            pagesWide++;
            // This will be the first column on the new page.
            xpos = m_pageSize->m_bodyLeft + rowWd + 2. * m_padWd;
        }
        // Store the page and position of this output variable's column.
        colXPos[col] = xpos;
        colPage[col] = pagesWide;
        // Update the position pointer.
        xpos += ( 2. * m_padWd + colWd );
    }

    // Determine the column title width (inches).
    double colTitleWd = textMetrics.width( *(colVar->m_label) ) / xppi;
    if ( ( textMetrics.width( colVar->m_displayUnits ) / xppi ) > colTitleWd )
    {
        colTitleWd = textMetrics.width( colVar->m_displayUnits ) / xppi;
    }
    colTitleWd += ( 2. * m_padWd );

    // Determine an offset shift to center each pageAcross.
    double *shift = new double[ pagesWide + 1 ];
    checkmem( __FILE__, __LINE__, shift, "double shift", pagesWide + 1 );
    for ( col = 0;
            col < tableCols();
            col++ )
    {
        // Table must be at least this wide.
        double minLeft = m_pageSize->m_bodyLeft + rowWd + 2. * m_padWd + colTitleWd;
        // Does it need to be wider to accomodate this column?
        if ( colXPos[col] + colWd > minLeft )
        {
            minLeft = colXPos[col] + colWd;
        }
        // Just the last column of each page finally gets stored in shift[].
        shift[colPage[col]] = 0.5 * ( m_pageSize->m_bodyRight - minLeft );
    }

    // Start drawing the table.
    double yPos, s, bgLeft, bgRight, rightEdge, leftEdge;
    int i;
    // Loop for each page down.
    int thisPage = 1;
    for ( int pageDown = 1;
            pageDown <= pagesLong;
            pageDown++ )
    {
        // Loop for each page across.
        for ( int pageAcross = 1;
                pageAcross <= pagesWide;
                pageAcross++, thisPage++ )
        {
            // Table title indicates the table portion
            translate( text, "BpDocument:Table:PageOf",
                       *(tableVar(vid)->m_label),
                       QString( "%1" ).arg( thisPage ),
                       QString( "%1" ).arg( pagesLong * pagesWide ) );

            // Start a new page
            startNewPage( text, TocTable );
            yPos = m_pageSize->m_marginTop + titleHt;

            // Draw a map of where we are.
            composePageMap( ( 2. * titleHt - 0.1 ), pagesLong, pagesWide,
                            pagesLong, pagesWide, 1, 1, pageDown-1, pageAcross-1 );

            // Display the table title::description
            m_composer->font( titleFont );          // use tableTitleFont
            m_composer->pen( titlePen );            // use tableTitleFontColor
            qStr = m_eqTree->m_eqCalc->docDescriptionStore().stripWhiteSpace();
            m_composer->text(
                m_pageSize->m_marginLeft,   yPos,   // start at UL corner
                m_pageSize->m_bodyWd,       titleHt,// width and height
                Qt::AlignVCenter|Qt::AlignHCenter,  // center alignement
                qStr );                             // display description
            yPos += titleHt;

            // Display the table title::variable
            m_composer->font( subTitleFont );       // use tableSubtitleFont
            m_composer->pen( subTitlePen );         // use tableSubtitleFontColor
            qStr = *(outVar->m_label);
            if ( outVar->isContinuous() )
            {
                qStr = *(outVar->m_label) + " " + outVar->displayUnits(true);
            }
            m_composer->text(
                m_pageSize->m_marginLeft,   yPos,   // start at UL corner
                m_pageSize->m_bodyWd,       titleHt,// width and height
                Qt::AlignVCenter|Qt::AlignHCenter,  // center alignment
                qStr );                             // table variable name
            yPos += titleHt;

            // Display the table title::portion
            //m_composer->text(
            //    m_pageSize->m_marginLeft,   yPos,
            //    m_pageSize->m_bodyWd,       titleHt,
            //    Qt::AlignVCenter|Qt::AlignHCenter,
            //    portion );
            //yPos += titleHt;
            yPos += titleHt;

            // Everything else on this page is shifted
            s = shift[pageAcross];

            // Determine left and right edges of the table.
            leftEdge = -1;
            for ( col = 0;
                    col < tableCols();
                    col++ )
            {
                if ( pageAcross == colPage[col] )
                {
                    rightEdge = colXPos[col] + colWd + s;
                    if ( leftEdge < 0. )
                    {
                        leftEdge = colXPos[col] + s;
                    }
                }
            }
            // Must be at least wide enough to accomodate column header text.
            if ( rightEdge < leftEdge + colTitleWd )
            {
                rightEdge = leftEdge + colTitleWd;
            }
            bgLeft = m_pageSize->m_marginLeft + s - m_padWd ;
            bgRight = rightEdge - leftEdge + rowWd + 4 * m_padWd ;

            // Display a colored row column header background?
            if ( doRowBg )
            {
                m_composer->fill(
                    bgLeft,     yPos,
                    bgRight,    3 * textHt,
                    rowBrush );
            }
            // Display the row column header0.
            m_composer->font( textFont );           // use tableTextFont
            m_composer->pen( textPen );             // use tableTextFontColor
            m_composer->text(
                m_pageSize->m_marginLeft + s,   yPos,
                rowWd,                          textHt,
                Qt::AlignVCenter|Qt::AlignLeft,
                *(rowVar->m_hdr0) );

            // Display the row column header1.
            m_composer->text(
                m_pageSize->m_marginLeft + s,   yPos + textHt,
                rowWd,                          textHt,
                Qt::AlignVCenter|Qt::AlignLeft,
                *(rowVar->m_hdr1) );

            // Display the row column units.
            m_composer->text(
                m_pageSize->m_marginLeft + s,   yPos + 2. * textHt,
                rowWd,                          textHt,
                Qt::AlignVCenter|Qt::AlignLeft,
                rowVar->displayUnits() );
            // Display the row column header underline
            // only if we are not coloring row backgrounds.
            int skipLines = 3;
            if ( ! doRowBg )
            {
                m_composer->line(
                    m_pageSize->m_marginLeft + s,           yPos + 3.5 * textHt,
                    m_pageSize->m_marginLeft + rowWd + s,   yPos + 3.5 * textHt );
                skipLines = 4;
            }
            // Display the output column headers.
            for ( col = 0;
                    col < tableCols();
                    col++ )
            {
                if ( pageAcross == colPage[col] )
                {
                    // Display the output column units.
                    m_composer->text(
                        colXPos[col] + s,   yPos + 2. * textHt,
                        colWd,              textHt,
                        Qt::AlignVCenter|Qt::AlignRight,
                        colText[col] );
                    // Display the output column underline.
                    if ( ! doRowBg )
                    {
                        m_composer->line(
                            colXPos[col] + s,           yPos + 3.5 * textHt,
                            colXPos[col] + colWd + s,   yPos + 3.5 * textHt );
                    }
                }
            }
            // Display a centered column variable name and units header.
            m_composer->text(
                leftEdge,                   yPos,
                ( rightEdge - leftEdge ),   textHt,
                Qt::AlignVCenter|Qt::AlignHCenter,
                *(colVar->m_label) );

            if ( colVar->isContinuous() )
            {
                m_composer->text(
                    leftEdge,                   yPos + textHt,
                    ( rightEdge - leftEdge ),   textHt,
                    Qt::AlignVCenter|Qt::AlignHCenter,
                    colVar->displayUnits() );
            }

            // If there are previous columns, display a visual cue.
            if ( pageAcross > 1 )
            {
                for ( i = 0;
                        i < 3;
                        i++ )
                {
                    m_composer->text(
                        0, ( yPos + i * textHt ),
                        ( m_pageSize->m_marginLeft + s - m_padWd ),   textHt,
                        Qt::AlignVCenter|Qt::AlignRight,
                        "<" );
                }
            }
            // If there are subsequent column pages, display a visual clue.
            if ( pageAcross < pagesWide )
            {
                for ( i = 0;
                        i < 3;
                        i++ )
                {
                    m_composer->text(
                        ( rightEdge + m_padWd ), ( yPos + i * textHt ),
                        ( m_pageSize->m_pageWd - rightEdge ), textHt,
                        Qt::AlignVCenter|Qt::AlignLeft,
                        ">" );
                }
            }
            // Set vertical start of rows.
            yPos += skipLines * textHt;

            // Determine the rows range to display on this page.
            int rowFrom = ( pageDown - 1 ) * rowsPerPage;
            int rowThru = pageDown * rowsPerPage - 1;
            if ( rowThru >= tableRows() )
            {
                rowThru = tableRows() - 1;
            }
            // Determine the columns range to display on this page.
            int colFrom = -1;
            int colThru = 0;
            for ( col = 0;
                    col < tableCols();
                    col++ )
            {
                if ( colPage[col] == pageAcross )
                {
                    if ( colFrom == -1 )
                    {
                        colFrom = col;
                    }
                    colThru = col;
                }
            }

            // Loop for each row on this page.
            bool doThisRowBg = false;
            for ( row = rowFrom;
                    row <= rowThru;
                    row++ )
            {
                // Display a colored row background?
                if ( doRowBg && doThisRowBg )
                {
                    m_composer->fill(
                        bgLeft,     yPos,
                        bgRight,    textHt,
                        rowBrush );
                }
                doThisRowBg = ! doThisRowBg;

                // Left-most (row variable) column value.
                if ( rowVar->isDiscrete() )
                {
                    iid = (int) tableRow( row );
                    qStr = rowVar->m_itemList->itemName( iid );
                }
                else if ( rowVar->isContinuous() )
                {
                    // CDB DECIMALS MOD
                    if ( false )
                    {
                        qStr.sprintf( "%1.*f", rowVar->m_displayDecimals, tableRow( row ) );
                    }
                    else
                    {
                        qStr.sprintf( "%1.*f", m_rowDecimals, tableRow( row ) );
                    }
                }
                m_composer->font( textFont );       // use tableTextFont
                m_composer->pen( textPen );         // use tableTextFontColor
                m_composer->text(
                    m_pageSize->m_marginLeft + s,   yPos,
                    rowWd,                          textHt,
                    Qt::AlignVCenter|Qt::AlignLeft,
                    qStr );

                // Loop for each column value on this page.
                m_composer->font( valueFont );      // use tableValueFont
                m_composer->pen( valuePen );        // use tableValueFontColor
                out = vid
                      + colFrom * tableVars()
                      + row * tableCols() * tableVars();
                for ( col = colFrom;
                        col <= colThru;
                        col++ )
                {
                    // Determine whether to hatch this cell
                    cell = col + row * tableCols();
                    bool hatch = doRx && ! tableInRx( cell );

                    // Discrete variables use their item name.
                    if ( outVar->isDiscrete() )
                    {
                        iid = (int) tableVal( out );
                        qStr = outVar->m_itemList->itemName( iid );
                    }
                    // Continuous variables use the current display units format.
                    else if ( outVar->isContinuous() )
                    {
                        qStr.sprintf( " %1.*f",
                                      outVar->m_displayDecimals, tableVal( out ) );
                    }
                    // Display the output value.
                    if ( hatch && doBlank )
                    {
                        // draw nothing
                    }
                    else
                    {
                        m_composer->text(
                            colXPos[col] + s,   yPos,
                            colWd,              textHt,
                            Qt::AlignVCenter|Qt::AlignRight,
                            qStr );
                    }
                    out += tableVars();
                    // RX hatching
                    if ( hatch && ! doBlank && ! outVar->isDiagram() )
                    {
                        x0 = colXPos[col] + s - m_padWd;
                        x1 = colXPos[col] + s + m_padWd + colWd;
                        m_composer->line( x0, yPos, x1, ( yPos + textHt ) );
                        m_composer->line( x0, ( yPos + textHt ), x1, yPos );
                    }
                } // Next table output variable.
                yPos += rowHt;
            } // Next table row.
        } // Next pageAcross.
    } // Next pageDown.

    // Be polite and stop the composer.
    m_composer->end();

    // Clean up and return.
    delete[] colPage;
    delete[] colXPos;
    delete[] colText;
    delete[] shift;
    return;
}
コード例 #8
0
void BpDocument::composeTable3Html( FILE *fptr, int vid,
                                    EqVar *rowVar, EqVar *colVar )
{
    EqVar *outVar = tableVar(vid);
    int iid;

    // Prescription shading?
    bool doRx = property()->boolean( "tableShading" );
    bool doBlank = property()->boolean( "tableShadingBlank" );

    QString text = "";
    if ( outVar->isContinuous() )
    {
        text = "(" + outVar->displayUnits() + ")";
    }
    fprintf( fptr,
             "<!-- Begin 2-Way Output Table for %s -->\n"
             "<p class=\"bp2\">\n"
             "  <h3 class=\"bp2\">Results for: %s %s</h3>\n"
             "  <table cellpadding=\"5\" cellspacing=\"2\" border=\"0\">\n",
             (*(outVar->m_label)).latin1(),
             (*(outVar->m_label)).latin1(),
             text.latin1()
           );

    // First column headers
    fprintf( fptr,
             "    <tr>\n"
             "      <td class=\"bp2hdr\" align=\"center\">\n"
             "        %s\n"
             "      </td>\n",
             (*(rowVar->m_hdr0)).latin1()
           );
    fprintf( fptr,
             "      <td class=\"bp2hdr\" colspan=\"%d\" align=\"center\">\n"
             "        %s\n"
             "      </td>\n"
             "    </tr>\n",
             tableCols(),
             (*(colVar->m_label)).latin1()
           );

    // Second column header
    fprintf( fptr,
             "    <tr>\n"
             "      <td class=\"bp2hdr\" align=\"center\">\n"
             "        %s\n"
             "      </td>\n",
             (*(rowVar->m_hdr1)).latin1()
           );
    text = "";
    if ( colVar->isContinuous() )
    {
        text = colVar->displayUnits();
    }
    fprintf( fptr,
             "      <td class=\"bp2hdr\" colspan=\"%d\" align=\"center\">\n"
             "        %s\n"
             "      </td>\n"
             "    </tr>\n",
             tableCols(),
             text.latin1()
           );

    // Third column header
    // Row variable's units
    text = "";
    if ( rowVar->isContinuous() )
    {
        text = rowVar->displayUnits();
    }
    fprintf( fptr,
             "    <tr>\n"
             "      <td class=\"bp2hdr\" align=\"center\">\n"
             "        %s\n"
             "      </td>\n",
             text.latin1()
           );
    // Column variable values
    int row, col;
    for ( col = 0; col < tableCols(); col++ )
    {
        if ( colVar->isDiscrete() )
        {
            iid = (int) tableCol( col );
            text = colVar->m_itemList->itemName( iid );
        }
        else if ( colVar->isContinuous() )
        {
            // CDB DECIMALS MOD
            if ( false )
            {
                text.sprintf( " %1.*f",	colVar->m_displayDecimals, tableCol( col ) );
            }
            else
            {
                text.sprintf( " %1.*f", m_colDecimals, tableCol( col ) );
            }
        }
        fprintf( fptr,
                 "      <td class=\"bp2hdr\" align=\"center\">\n"
                 "        %s\n"
                 "      </td>\n",
                 text.latin1()
               );
    }
    fprintf( fptr, "    </tr>\n" );

    // Table body
    int out = vid;
    for ( row = 0; row < tableRows(); row++ )
    {
        // Row value is in the first column
        if ( rowVar->isDiscrete() )
        {
            iid = (int) tableRow( row );
            text = rowVar->m_itemList->itemName( iid );
        }
        else if ( rowVar->isContinuous() )
        {
            // CDB DECIMALS MOD
            if ( false )
            {
                text.sprintf( "%1.*f", rowVar->m_displayDecimals, tableRow( row ) );
            }
            else
            {
                text.sprintf( "%1.*f", m_rowDecimals, tableRow( row ) );
            }
        }
        fprintf( fptr,
                 "    <tr>\n"
                 "      <td class=\"bp2hdr\" align=\"center\">\n"
                 "        %s\n"
                 "      </td>\n",
                 text.latin1()
               );

        // Remaining columns
        for ( col = 0; col < tableCols(); col++ )
        {
            if ( outVar->isDiscrete() )
            {
                iid = (int) tableVal( out );
                text = outVar->m_itemList->itemName( iid );
            }
            else if ( outVar->isContinuous() )
            {
                text.sprintf( "%1.*f",
                              outVar->m_displayDecimals, tableVal( out ) );
            }
            // Display the output value.
            if ( doRx )
            {
                int cell = col + row * tableCols();
                if ( tableInRx( cell ) )
                {
                    fprintf( fptr,
                             "      <td class=\"bp2row%din\" align=\"center\">\n"
                             "        %s\n"
                             "      </td>\n",
                             row%2, text.latin1()
                           );
                }
                else if ( doBlank )
                {
                    fprintf( fptr,
                             "      <td class=\"bp2row%dout\" align=\"center\">\n"
                             "        &nbsp;\n"
                             "      </td>\n",
                             row%2
                           );
                }
                else
                {
                    fprintf( fptr,
                             "      <td class=\"bp2row%dout\" align=\"center\">\n"
                             "        %s\n"
                             "      </td>\n",
                             row%2, text.latin1()
                           );
                }
            }
            else
            {
                fprintf( fptr,
                         "      <td  class=\"bp2row%d\" align=\"center\">\n"
                         "        %s\n"
                         "      </td>\n",
                         row%2, text.latin1()
                       );
            }
            out += tableVars();
        }   // Next table column
        fprintf( fptr, "    </tr>\n" );
    } // Next table row

    // End of the table for this variable
    fprintf( fptr,
             "  </table>\n"
             "</p>\n"
             "<!-- End 2-Way Output Table for %s -->\n\n",
             (*(outVar->m_label)).latin1()
           );
    return;
}
コード例 #9
0
void BpDocument::composeFireCharacteristicsDiagram( void )
{
    // Surface Module must be active and using fuel model inputs
    PropertyDict *prop = m_eqTree->m_propDict;
    if ( ! prop->boolean( "surfaceModuleActive" )
      || ! prop->boolean( "surfaceCalcFireCharacteristicsDiagram" ) )
    {
        return;
    }

    // Graph fonts.
    QFont  textFont( property()->string( "graphTextFontFamily" ),
                     property()->integer( "graphTextFontSize" ) );
    QColor textColor( property()->color( "graphTextFontColor" ) );
    QPen   textPen( textColor );
    QFont  subTitleFont( property()->string( "graphSubtitleFontFamily" ),
                    property()->integer( "graphSubtitleFontSize" ) );
    QColor subTitleColor( property()->color( "graphSubtitleFontColor" ) );

    // Open the result file
    QString resultFile = m_eqTree->m_resultFile;
    FILE *fptr = 0;
    if ( ! ( fptr = fopen( resultFile.latin1(), "r" ) ) )
    // This code block should never be executed!
    {
        QString text("");
        translate( text, "BpDocument:FireCharacteristicsDiagram:NoLogOpen",
            resultFile );
        error( text );
        return;
    }
    // Allocate ros and hpua data arrays
    int rows  = tableRows();
    int cols  = tableCols();
    int cells = rows * cols;
    double *hpua = new double[ cells ];
    checkmem( __FILE__, __LINE__, hpua, "double hpua", cells );
    double *ros = new double[ cells ];
    checkmem( __FILE__, __LINE__, ros, "double ros", cells );
    // Set the variable names we're looking for
    const char* hpuaName = "vSurfaceFireHeatPerUnitArea";
    const char* rosName = "vSurfaceFireSpreadAtHead";
    if ( prop->boolean( "surfaceConfSpreadDirInput" ) )
    {
        rosName = "vSurfaceFireSpreadAtVector";
    }
    // Read and store the ros and hpua values
    char   buffer[1024], varName[128], varUnits[128];
    int    row, col, cell;
    double value;
    double rosMax = 0.0;
    double hpuaMax = 0.0;
    while ( fgets( buffer, sizeof(buffer), fptr ) )
    {
        if ( strncmp( buffer, "CELL", 4 ) == 0 )
        {
            if ( strstr( buffer, hpuaName ) )
            {
                sscanf( buffer, "CELL %d %d %s cont %lf %s",
                    &row, &col, varName, &value, varUnits );
                cell = ( col - 1 ) + ( cols * ( row - 1) );
                if ( ( hpua[ cell ] = value ) > hpuaMax )
                {
                    hpuaMax = value;
                }
            }
            else if ( strstr( buffer, rosName ) )
            {
                sscanf( buffer, "CELL %d %d %s cont %lf %s",
                    &row, &col, varName, &value, varUnits );
                cell = ( col - 1 ) + ( cols * ( row - 1) );
                if ( ( ros[ cell ] = value ) > rosMax )
                {
                    rosMax = value;
                }
            }
        }
    }
    fclose( fptr );

    // Get variable pointers
    EqVar *hpuaVar = m_eqTree->m_varDict->find( "vSurfaceFireHeatPerUnitArea" );
    EqVar *rosVar = m_eqTree->m_varDict->find( "vSurfaceFireSpreadAtHead" );
    EqVar *fliVar = m_eqTree->m_varDict->find( "vSurfaceFireLineIntAtHead" );
    EqVar *flVar = m_eqTree->m_varDict->find( "vSurfaceFireFlameLengAtHead" );

    // Conversion factor
    double flFactor, fliFactor, rosFactor, hpuaFactor, offset;
    appSiUnits()->conversionFactorOffset(
        flVar->m_nativeUnits, flVar->m_displayUnits, &flFactor, &offset );
    appSiUnits()->conversionFactorOffset(
        fliVar->m_nativeUnits, fliVar->m_displayUnits, &fliFactor, &offset );
    appSiUnits()->conversionFactorOffset(
        hpuaVar->m_nativeUnits, hpuaVar->m_displayUnits, &hpuaFactor, &offset );
    appSiUnits()->conversionFactorOffset(
        rosVar->m_nativeUnits, rosVar->m_displayUnits, &rosFactor, &offset );

    // Determine which of four different chart scales to use
    static const int Scales = 4;
    static double RosScale[Scales] = { 100., 200., 400., 800. };        // ft/min
    static double HpuaScale[Scales] = { 2000., 4000., 8000., 16000. };  // Btu/ft2
    double rosScale = 0.;       // Max y-axis ros
    double hpuaScale = 0.;      // Max x-axis hpua
    int scale;
    for ( scale=0; scale<Scales; scale++ )
    {
        if ( rosMax < ( rosScale = RosScale[ scale ] ) )
        {
            break;
        }
    }
    for ( scale=0; scale<Scales; scale++ )
    {
        if ( hpuaMax < ( hpuaScale = HpuaScale[scale] ) )
        {
            break;
        }
    }
    // Set axis maximums to appropriate predefined scale in display units
    rosMax  = rosFactor * rosScale;
    hpuaMax = hpuaFactor * hpuaScale;
    double ratio = rosMax / hpuaMax;

    // Create the graph
    Graph  graph;
    GraphLine *graphLine;
    GraphMarker *graphMarker;
    static const int Points = 100;
    double l_x[Points];
    double l_y[Points];

    // Draw the four standard hauling chart fli-fl levels
    static const int Lines = 4;
    static const double Fli[Lines] = { 100., 500., 1000., 2000. };  // Btu/ft/s
    static const double Fl[Lines] = { 4., 8., 11., 15. };           // ft

    // Create the hauling chart lines
    // Put Fireline Int label 65% of the way along the HPUA axis (display units)
    double  xPosFli = 0.65 * hpuaMax;
    // Put Flame Length label 85% of the way along the HPUA axis (display units)
    double  xPosFl  = 0.85 * hpuaMax;
    // Fireline Int and Flame Length label Y positions (display units)
    double  yPosFl[Lines], yPosFli[Lines];
    // Icon locations (in display units)
    double xIcon[Lines+1], yIcon[Lines+1];
    double diff, minDiff;
    QString label;
    QPen    redPen( "red", 1 );
    QColor  blackColor( "black" );
    int     alignCenter = Qt::AlignHCenter | Qt::AlignVCenter;
    // Fireline intensity - flame length curves
    int     line, point;
    for ( line = 0; line < Lines; line++ )
    {
        minDiff = 999999999.;
        for ( point = 0; point < Points; point++ )
        {
            // Hpua value in native units (Btu/ft2)
            l_x[point] = ( (point+1) * hpuaScale ) / (double) Points;
            // Ros value in native units (ft/min)
            l_y[point] = 60. * Fli[line] / l_x[point];
            // Convert to display units
            l_x[point] *= hpuaFactor;
            l_y[point] *= rosFactor;
            // Check for curve inflection point (for icon placement)
            if ( ( diff = fabs( l_y[point]/l_x[point] - ratio ) ) < minDiff )
            {
                minDiff = diff;
                xIcon[line+1] = l_x[point];
                yIcon[line+1] = l_y[point];
            }
        }
        // Create a graph line (with its own copy of the data).
        graphLine = graph.addGraphLine( Points, l_x, l_y, redPen );

        // Fireline intensity label
        label = QString( "%1" ).arg( ( Fli[line] * fliFactor ), 0, 'f', 0 );
        yPosFli[line] = rosFactor * ( 60. * Fli[line] / ( xPosFli / hpuaFactor ) );
        graph.addGraphMarker( xPosFli, yPosFli[line], label, textFont,
            blackColor, alignCenter );

        // Flame length label
        label = QString( "%1" ).arg( ( Fl[line] * flFactor ), 0, 'f', 0 );
        yPosFl[line] = rosFactor * ( 60. * Fli[line] / ( xPosFl / hpuaFactor ) );
        graph.addGraphMarker( xPosFl, yPosFl[line], label, textFont,
            blackColor, alignCenter );
    } // Next line

    // Fireline intensity label and units
    translate( label, "BpDocument:FireCharacteristicsDiagram:FLI" );
    graph.addGraphMarker( xPosFli, ( yPosFli[Lines-1] + 0.10 * rosMax ),
        label, textFont, blackColor, alignCenter );
    graph.addGraphMarker( xPosFli, ( yPosFli[Lines-1] + 0.05 * rosMax ),
        fliVar->m_displayUnits, textFont, blackColor, alignCenter );

    // Flame length label and units
    translate( label, "BpDocument:FireCharacteristicsDiagram:FL" );
    graph.addGraphMarker( xPosFl, ( yPosFl[Lines-1] + 0.10 * rosMax ),
        label, textFont, blackColor, alignCenter );
    graph.addGraphMarker( xPosFl, ( yPosFl[Lines-1] + 0.05 * rosMax ),
        flVar->m_displayUnits, textFont, blackColor, alignCenter );

    // Add icons
    QPixmap pixmap[Lines];
    pixmap[0] = QPixmap( fireman_xpm );
    pixmap[1] = QPixmap( dozer_xpm );
    pixmap[2] = QPixmap( torchtree_xpm );
    pixmap[3] = QPixmap( mtnfire_xpm );
    xIcon[0] = yIcon[0] = 0.0;
    for ( line=0; line<Lines; line++ )
    {
        graphMarker = graph.addGraphMarker(
            xIcon[line] + ( 0.5 * ( xIcon[line+1] - xIcon[line] ) ),
            yIcon[line] + ( 0.5 * ( yIcon[line+1] - yIcon[line] ) ),
            "", textFont, blackColor, alignCenter );
        graphMarker->setGraphMarkerPixmap( pixmap[line] );
    }

    // Finally, add a marker for each output result
    QColor  bluePen( "blue" );
    for ( cell=0; cell<cells; cell++ )
    {
        //fprintf( stderr, "%02d: %3.2f  %3.2f\n", i, hpua[i], ros[i] );
        graph.addGraphMarker( hpua[cell], ros[cell],
            QString( "%1" ).arg( cell + 1 ), textFont, bluePen, alignCenter );
    }
    // Compose the graph
    EqVar *zVar = 0;
    GraphAxleParms xParms( 0.0, hpuaMax, 11 );
    GraphAxleParms yParms( 0.0, rosMax, 11 );
    composeGraphBasics( &graph, true, hpuaVar, rosVar, zVar, Lines,
        &xParms, &yParms );

    // Create a separate page for this graph.
    translate( label, "BpDocument:FireCharacteristicsDiagram:Caption" );
    graph.setSubTitle( label, subTitleFont, subTitleColor );
    startNewPage( label, TocHaulChart );

    // This is how we save the graph and its composer.
    m_composer->graph( graph,
        m_pageSize->m_marginLeft
            + m_pageSize->m_bodyWd * property()->real( "graphXOffset" ),
        m_pageSize->m_marginTop
            + m_pageSize->m_bodyHt * property()->real( "graphYOffset" ),
        m_pageSize->m_bodyWd * property()->real( "graphScaleWidth" ),
        m_pageSize->m_bodyHt * property()->real( "graphScaleHeight" )
    );
    // Be polite and stop the composer.
    m_composer->end();
    delete[] ros;   ros  = 0;
    delete[] hpua;  hpua = 0;
    return;
}
コード例 #10
0
TableStatistics::TableStatistics(ScriptingEnv *env, QWidget *parent, Table *base, Type t, QValueList<int> targets)
  : Table(env, 0, 0, "", parent, ""),
  d_base(base), d_type(t), d_targets(targets)
{
  worksheet->setReadOnly(true);
  setCaptionPolicy(myWidget::Both);
  if (d_type == row)
  {
    setName(QString(d_base->name())+"-"+tr("RowStats"));
    setWindowLabel(tr("Row Statistics of %1").arg(base->name()));
    resizeRows(d_targets.size());
    resizeCols(9);
    setColName(0, tr("Row"));
    setColName(1, tr("Cols"));
    setColName(2, tr("Mean"));
    setColName(3, tr("StandardDev"));
    setColName(4, tr("Variance"));
    setColName(5, tr("Sum"));
    setColName(6, tr("Max"));
    setColName(7, tr("Min"));
    setColName(8, "N");

    for (unsigned i=0; i < d_targets.size(); i++)
      setText(i, 0, QString::number(d_targets[i]+1));
    update(d_base, QString::null);
  }
  else if (d_type == column)
  {
    setName(QString(d_base->name())+"-"+tr("ColStats"));
    setWindowLabel(tr("Column Statistics of %1").arg(base->name()));
    resizeRows(d_targets.size());
    resizeCols(11);
    setColName(0, tr("Col"));
    setColName(1, tr("Rows"));
    setColName(2, tr("Mean"));
    setColName(3, tr("StandardDev"));
    setColName(4, tr("Variance"));
    setColName(5, tr("Sum"));
    setColName(6, tr("iMax"));
    setColName(7, tr("Max"));
    setColName(8, tr("iMin"));
    setColName(9, tr("Min"));
    setColName(10, "N");

    for (unsigned i=0; i < d_targets.size(); i++)
    {
      setText(i, 0, d_base->colLabel(d_targets[i]));
      update(d_base, d_base->colName(d_targets[i]));
    }
  }
  int w=9*(worksheet->horizontalHeader())->sectionSize(0);
  int h;
  if (tableRows()>11)
    h=11*(worksheet->verticalHeader())->sectionSize(0);
  else
    h=(tableRows()+1)*(worksheet->verticalHeader())->sectionSize(0);
  setGeometry(50,50,w + 45, h + 45);

  setColPlotDesignation(0, Table::X);
  setHeaderColType();
}