Example #1
0
void TsPlotCurve::DarkenColour(int darkeningFactor)
{
   if (darkeningFactor < 1)
      darkeningFactor = 1;

   wxColour startColor = baseColor;
   unsigned char r,g,b;

   r = startColor.Red() / darkeningFactor;
   g = startColor.Green() / darkeningFactor;
   b = startColor.Blue() / darkeningFactor;

   wxColour theColor(r, g, b);
   SetColour(theColor, -1);
   baseColor = startColor;
}
Example #2
0
void trend::Tolder::grdDraw()
{
   glBegin(GL_POINTS);
   TNDR_GLDATAT* cpoint_array = new TNDR_GLDATAT [2*_num_grid_points];
   unsigned start = 0;
   unsigned stop = 0;
   for (VGrids::const_iterator VG = _grid_props.begin(); VG != _grid_props.end(); VG++)
   {
      layprop::tellRGB theColor(_drawprop->getColor((*VG)->color()));
      glColor4ub(theColor.red(), theColor.green(), theColor.blue(), theColor.alpha());
      stop = (*VG)->dump(cpoint_array, 2*start);
      for (unsigned i = start; i < stop; i++)
         glVertex2f(cpoint_array[2*i], cpoint_array[2*i+1]);
      start = stop;
   }
   assert(start <= (_num_grid_points));
   delete [] cpoint_array;
   glEnd();
}
Example #3
0
void TsPlotCurve::LightenColour(int lighteningFactor)
{
   if (lighteningFactor < 1)
      lighteningFactor = 1;

   wxColour startColor = baseColor;
   unsigned char r,g,b, rdiff, gdiff, bdiff;

   rdiff = 255 - startColor.Red();
   gdiff = 255 - startColor.Green();
   bdiff = 255 - startColor.Blue();

   r = startColor.Red() + (int)(rdiff * (1.0 - 1.0 / lighteningFactor));
   g = startColor.Green() + (int)(gdiff * (1.0 - 1.0 / lighteningFactor));
   b = startColor.Blue() + (int)(bdiff * (1.0 - 1.0 / lighteningFactor));

   wxColour theColor(r, g, b);
   SetColour(theColor, -1);
   baseColor = startColor;
}
void KDChartLinesPainter::specificPaintData( QPainter* painter,
                                             const QRect& /*ourClipRect*/,
                                             KDChartTableDataBase* data,
                                             KDChartDataRegionList* regions,
                                             const KDChartAxisParams* ordinatePara,
                                             bool /*bNormalMode*/,
                                             uint chart,
                                             double logWidth,
                                             double /*areaWidthP1000*/,
                                             double logHeight,
                                             double axisYOffset,
                                             double minColumnValue,
                                             double maxColumnValue,
                                             double columnValueDistance,
                                             uint /*chartDatasetStart*/,
                                             uint /*chartDatasetEnd*/,
                                             uint datasetStart,
                                             uint datasetEnd )
{
    if( !data ) return;


    abscissaInfos ai;
    ai.bCenterThePoints = mCenterThePoints;
    calculateAbscissaInfos( *params(), *data,
                            datasetStart, datasetEnd,
                            logWidth, _dataRect,
                            ai );
    mCenterThePoints = ai.bCenterThePoints;

    bool bOrdinateDecreasing = ordinatePara
        ? ordinatePara->axisValuesDecreasing()
        : false;
    bool bOrdinateIsLogarithmic
        = ordinatePara
        ? (KDChartAxisParams::AxisCalcLogarithmic == ordinatePara->axisCalcMode())
        : false;

    //const double ordinatePixelsPerUnit = logHeight / columnValueDistance;
    const double ordinatePixelsPerUnit
        = (    ordinatePara
               && (0.0 != ordinatePara->trueAxisDeltaPixels())
               && (0.0 != ordinatePara->trueAxisDelta()))
        ? ordinatePara->trueAxisDeltaPixels() / ordinatePara->trueAxisDelta()
        : logHeight / columnValueDistance;;
    //qDebug("ordinatePixelsPerUnit: %f",ordinatePixelsPerUnit);


    const bool showThreeDLines = !mIsArea && params()->threeDLines();

    enum { Normal, Stacked, Percent } mode = Normal;
    if (    (    ( mChartType                   == KDChartParams::Line )
                 && ( params()->lineChartSubType() == KDChartParams::LineNormal ) )
            || (    ( mChartType                   == KDChartParams::Area )
                    && ( params()->areaChartSubType() == KDChartParams::AreaNormal ) ) )
        mode = Normal;
    else if (    (    ( mChartType                   == KDChartParams::Line )
                      && ( params()->lineChartSubType() == KDChartParams::LineStacked ) )
                 || (    ( mChartType                   == KDChartParams::Area )
                         && ( params()->areaChartSubType() == KDChartParams::AreaStacked ) ) )
        mode = Stacked;
    else if (    (    ( mChartType                   == KDChartParams::Line )
                      && ( params()->lineChartSubType() == KDChartParams::LinePercent ) )
                 || (    ( mChartType                   == KDChartParams::Area )
                         && ( params()->areaChartSubType() == KDChartParams::AreaPercent ) ) )
        mode = Percent;
    else
        qDebug( "Internal error in KDChartLinesPainter::paintDataInternal(): Unknown subtype" );


    QMap < int, double > currentValueSums;
    if ( mode == Stacked || mode == Percent ) {
        // this array is only used for stacked and percent lines, no need
        // to waste time initializing it for normal types
        for ( int value = 0; value < ai.numValues; ++value )
            currentValueSums[ value ] = 0.0;
    }
    QMap < int, double > totalValueSums;

    // compute the position of the 0 axis
    double zeroXAxisI;
    if ( mode == Percent ) {
        if ( minColumnValue == 0.0 )
            zeroXAxisI = logHeight + axisYOffset;
        else if( maxColumnValue == 0.0 )
            zeroXAxisI = _dataRect.y() + axisYOffset;
        else
            zeroXAxisI = logHeight / 2.0 + _dataRect.y();
    } else
        zeroXAxisI = ordinatePara->axisZeroLineStartY() - _dataRect.y();


    // compute how to shift of the points in case we want them in the
    // middle of their respective columns
    int xShift = mCenterThePoints ? static_cast < int > ( ai.pointDist * 0.5 ) : 0;


    // calculate all points' positions
    // ===============================
    int arrayNumDatasets = 0;
    int arrayNumValues   = ai.bAbscissaHasTrueAxisDtValues
        ? data->cols()
        : ai.numValues;
    int dataset;
    for( dataset = datasetEnd;
         ( dataset >= static_cast < int > ( datasetStart ) && dataset >= 0 );
         --dataset )
        ++arrayNumDatasets;
#if COMPAT_QT_VERSION >= 0x030000
    QValueVector<MyPoint> allPoints(
#else
    QArray<MyPoint> allPoints(
#endif
                              arrayNumDatasets * arrayNumValues );
                                    
    KDChartPropertySet curPropSet;
    int curPropSetId = KDChartPropertySet::UndefinedID;
                                    
    for( dataset = datasetEnd; ( dataset >= (int)datasetStart && dataset >= 0 ); --dataset ) {
                                        
        int prevPointX = -1;
        int prevPointY = -1;
                                        
        const KDChartParams::LineMarkerStyle
            defaultMarkerStyle = params()->lineMarkerStyle( dataset );
        const QPen default2DPen(   params()->lineColor().isValid()
                                   ? params()->lineColor()
                                   : params()->dataColor( dataset ),
                                   params()->lineWidth(),
                                   params()->lineStyle( dataset ) );

        if( ai.bAbscissaHasTrueAxisDtValues )
            ai.numValues = data->cols();

        QVariant vValY;
        QVariant vValX;
        int cellPropID;
        for( int value = 0; value < ai.numValues; ++value ) {
            //if ( mode == Percent )
            //    valueTotal = data->colAbsSum( value );
            double valueTotal = 0.0; // Will only be used for Percent
            if( mode == Percent ) {
                valueTotal = 0.0;
                // iterate over datasets of this axis only:
                for ( uint dataset2  = datasetStart;
                      dataset2 <= datasetEnd;
                      ++dataset2 ) {
                    if( data->cellCoord( dataset2, value, vValY, 1 ) &&
                        QVariant::Double == vValY.type() )
                        valueTotal += vValY.toDouble();
                }
            }

            if( data->cellContent( dataset, value, vValY, vValX, cellPropID ) &&
                QVariant::Double == vValY.type() &&
                ( !ai.bCellsHaveSeveralCoordinates || QVariant::Invalid != vValX.type() ) ){
                //qDebug("a. cellPropID: %i",cellPropID);

                // calculate Ordinate axis value
                // -----------------------------
                double cellValue = vValY.toDouble();
                double drawValue = 0.0;
                // PENDING(kalle) This does not work for AreaPercent yet
                if ( mode == Stacked )
                    drawValue = ( cellValue + currentValueSums[ value ] ) * ordinatePixelsPerUnit;
                else if ( mode == Percent )
                    drawValue = ( ( cellValue + currentValueSums[ value ] ) / valueTotal ) * 100.0 * ordinatePixelsPerUnit;
                else {
                    // LineNormal or AreaNormal
                    if( bOrdinateIsLogarithmic ){
                        if( 0.0 < cellValue )
                            drawValue = log10( cellValue ) * ordinatePixelsPerUnit;
                        else
                            drawValue = -10250.0;
                        //qDebug("\nlogarithmic calc  -  cellValue: %f   drawValue: %f",
                        //        cellValue, drawValue );
                    }else{
                        drawValue = cellValue * ordinatePixelsPerUnit * (bOrdinateDecreasing ? -1.0 : 1.0);
                        //qDebug("\nlinear calc  -  cellValue: %f\n             -  drawValue: %f",
                        //        cellValue, drawValue );
                    }
                }


                // calculate Abscissa axis value
                // -----------------------------
                double xValue;
                bool skipMe = !calculateAbscissaAxisValue( vValX, ai, value,
                                                           xValue );


                // calculate and store the point and region / draw the marker
                // ----------------------------------------------------------
                if( !skipMe ){
                    // prevent the point from being toooo far
                    // below the bottom (or above the top, resp.)
                    // of the cliprect
                    double pY = QMIN( zeroXAxisI - drawValue,
                                      (logHeight + axisYOffset) * 3 );
                    pY = QMAX( pY, -(logHeight + axisYOffset) * 3 );
                    // specify the Point
                    int myPointX = static_cast < int > ( xValue ) + xShift;
                    int myPointY = static_cast < int > ( pY );

                    if( cellPropID == curPropSetId &&
                        myPointX == prevPointX &&
                        myPointY == prevPointY ){
                        allPoints[   static_cast < int > ( datasetEnd-dataset )
                                     * arrayNumValues + value ].setSkipThis( true );
                        skipMe = true;
                        //qDebug("skipped");
                    }else{
                        // use typecast to make it compile on windows using qt232
                        allPoints[   static_cast < int > ( datasetEnd-dataset )
                                     * arrayNumValues + value ].set( myPointX, myPointY, cellValue );
                        //qDebug("ok");
                    }
                    if( !skipMe ){
                        // --------------------------------------------------------
                        // determine any 'extra' properties assigned to this cell
                        // by traversing the property set chain (if necessary)
                        // --------------------------------------------------------
                        if( cellPropID != curPropSetId ){
                            //qDebug("b. ( curPropSetId: %i )",curPropSetId);
                            //qDebug("b. cellPropID: %i",cellPropID);
                            //qDebug(curPropSet.name().latin1());
                            if( cellPropID != KDChartPropertySet::UndefinedID &&
                                params()->calculateProperties( cellPropID,
                                                               curPropSet ) ){
                                curPropSetId = cellPropID;
                                //qDebug("c. curPropSetId: %i",curPropSetId);
                                //qDebug(curPropSet.name().latin1());
                            }else{
                                curPropSetId = KDChartPropertySet::UndefinedID;
                            }
                        }
                        // make sure any extra horiz. and/or vert. lines and/or markers
                        // are drawn *before* the data lines and/or markers are painted
                        if( mChartType == KDChartParams::Line ){
                            if( curPropSetId != KDChartPropertySet::UndefinedID ){
                                drawExtraLinesAndMarkers(
                                                         curPropSet,
                                                         default2DPen,
                                                         defaultMarkerStyle,
                                                         myPointX, myPointY,
                                                         painter,
                                                         ai.abscissaPara,
                                                         ordinatePara,
                                                         logWidth/1000.0,
                                                         logHeight/1000.0,
                                                         false );
                            }
                        }
                        prevPointX = myPointX;
                        prevPointY = myPointY;
                    }
                }
                // calculate running sum for stacked and percent
                if ( mode == Stacked || mode == Percent ) {
                    if( cellValue == KDCHART_POS_INFINITE )
                        currentValueSums[ value ] = KDCHART_POS_INFINITE;
                    else if( currentValueSums[ value ] != KDCHART_POS_INFINITE )
                        currentValueSums[ value ] += cellValue;
                }
            }
        }
    }



    QPointArray previousPoints; // no vector since only areas need it,
    // and these do not support 3d yet

    // Store some (dataset-independend) default values
    // to be used unless other properties
    // have been specified for the respective data cell:
    //
    const bool defaultDrawMarkers = mDrawMarkers;

    for ( dataset = datasetEnd; ( dataset >= (int)datasetStart && dataset >= 0 ); --dataset ) {

        // Store some (dataset-dependend) default values
        // to be used unless other properties
        // have been specified for the respective data cell:
        //
        const QPen default2DPen(   params()->lineColor().isValid()
                                   ? params()->lineColor()
                                   : params()->dataColor( dataset ),
                                   params()->lineWidth(),
                                   params()->lineStyle( dataset ) );
        bool currentDrawMarkers = defaultDrawMarkers;
        const KDChartParams::LineMarkerStyle markerStyle = params()->lineMarkerStyle( dataset );

        // the +2 is for the areas (if any)
        QPtrVector< QPointArray > points( 2 );
        points.setAutoDelete( true );
        /* Pending Michel - we need to keep track of the 
         * non rotated points for 3D lines
         */
        QPtrVector< QPointArray > oripoints( 2 );
        oripoints.setAutoDelete( true );
        
        int i = 0;
        for( i = 0; i < 2; ++i ) {
            points.insert( i, new QPointArray( ai.numValues + 2 ) );
            oripoints.insert( i, new QPointArray( ai.numValues + 2 ) );
        }

        if( ai.bAbscissaHasTrueAxisDtValues )
            ai.numValues = data->cols();

        int point = 0;

        for ( int value = 0; value < ai.numValues; ++value ) {

            // determine and store marker properties assigned to this cell
            // -----------------------------------------------------------
            currentDrawMarkers = defaultDrawMarkers;
            int cellPropID;
            if( data->cellProp( dataset, value, cellPropID ) &&
                cellPropID != curPropSetId ){
                if( cellPropID != KDChartPropertySet::UndefinedID &&
                    params()->calculateProperties( cellPropID,
                                                   curPropSet ) )
                    curPropSetId = cellPropID;
                else
                    curPropSetId = KDChartPropertySet::UndefinedID;
            }
            if( curPropSetId != KDChartPropertySet::UndefinedID ){
                // we can safely call the following functions and ignore their
                // return values since they will touch the parameters' values
                // if the propSet *contains* corresponding own values only.
                int iDummy;
                curPropSet.hasOwnShowMarker( iDummy, currentDrawMarkers );
            }


            int iVec = static_cast < int > ( datasetEnd-dataset ) * arrayNumValues + value;
            if( allPoints[ iVec ].bValid && !allPoints[ iVec ].bSkipThis ){
                const MyPoint& mp = allPoints[iVec];

                
                //qDebug("\np.x() %i        p.y() %i", p.x(), p.y() );
                // For 3D lines, we need two points (that lie
                // behind each other on the Z axis). For 2D lines and
                // areas, we need only one point.
                if( showThreeDLines ) {
                    points[0]->setPoint( point, project( mp.p.x(), mp.p.y(),
                                                         (datasetStart+dataset)*params()->threeDLineDepth() ) );
                    points[1]->setPoint( point, project( mp.p.x(), mp.p.y(),
                                                         (datasetStart+dataset + 1)*params()->threeDLineDepth() ) );
                    oripoints[0]->setPoint( point,  mp.p.x(), mp.p.y() );
                    oripoints[1]->setPoint( point,  mp.p.x() -  (datasetStart+dataset + 1)*params()->threeDLineDepth(), 
                                            mp.p.y() -  (datasetStart+dataset + 1)*params()->threeDLineDepth() );
		 
                } else
                    // 2D lines or areas
                    points[0]->setPoint( point, mp.p );
                ++point;

                int x = mp.p.x();
                int y = QMAX(QMIN(mp.p.y(),
                                  static_cast < int > (logHeight +axisYOffset)),
                             0);
                bool markerIsOutside = y != mp.p.y();
                // draw the marker and store the region
                if ( currentDrawMarkers ){
                    uint   theAlignment = Qt::AlignCenter;
                    bool   hasOwnSize = false;
                    int    theWidth  = 0;
                    int    theHeight = 0;
                    QColor theColor(params()->dataColor( dataset ));
                    int    theStyle = markerStyle;
                    if( curPropSetId != KDChartPropertySet::UndefinedID ){
                        // we can safely call the following functions and ignore their
                        // return values since they will touch the parameters' values
                        // if the propSet *contains* corresponding own values only.
                        int iDummy;
                        curPropSet.hasOwnMarkerAlign( iDummy, theAlignment );
                        curPropSet.hasOwnMarkerColor( iDummy, theColor );
                        curPropSet.hasOwnMarkerStyle( iDummy, theStyle );
                        QSize size(theWidth, theHeight);
                        hasOwnSize = curPropSet.hasOwnMarkerSize(iDummy, size);
                        if( hasOwnSize ){
                            theWidth  = size.width();
                            theHeight = size.height();
                        }
                    }

                    drawMarker( painter,
                                params(),
                                _areaWidthP1000, _areaHeightP1000,
                                _dataRect.x(),
                                _dataRect.y(),
                                markerIsOutside
                                ? KDChartParams::LineMarker1Pixel
                                : theStyle,
                                theColor,
                                QPoint(x,y),
                                dataset, value, chart, regions,
                                hasOwnSize ? &theWidth  : 0,
                                hasOwnSize ? &theHeight : 0,
                                theAlignment );

                }
                // store the region
                else if( regions ) {
                    QRect rect(
                        QPoint( x-params()->lineWidth()-1, y-params()->lineWidth()-1 ),
                        QPoint( x+params()->lineWidth()+1, y+params()->lineWidth()+1 )
                        );
                    rect.moveBy( _dataRect.x(), _dataRect.y() );
                    regions->append(
                                    new KDChartDataRegion(dataset, value, chart, rect) );
                }

            }
        }
        if ( point ) {
            bool bDrawLines = (0 != params()->lineWidth());
          
            if ( mIsArea ) {
                // first draw with the fill brush, no pen, with the
                // zero axis points or upper border points added for the first
                // dataset or with the previous points reversed for all other
                // datasets.
                painter->setPen( QPen( Qt::NoPen ) );
                const QBrush datasetBrush( params()->dataColor( dataset ), Qt::SolidPattern );
                painter->setBrush( datasetBrush );
                QBrush currentBrush( datasetBrush );

                if ( mode == Normal || dataset == (int)datasetEnd ) {
                    /// first dataset (or any dataset in normal mode, where
                    /// the datasets overwrite each other)

                    // no 3d handling for areas yet
                    QPoint lastPoint = points[0]->point( point - 1 );

                    // zeroXAxisI can be too far below the abscissa, but it's
                    // the only thing we have. Likewise can 0 be too far above
                    // the upper boundary, but again it's the only thing we
                    // have, at the rest is clipped anyway.
                    int yCoord;
                    if ( params()->areaLocation() == KDChartParams::AreaBelow ||
                         mode == Percent )
                        yCoord = static_cast<int>(zeroXAxisI);
                    else
                        yCoord = static_cast<int>(axisYOffset);

                    // old: draw the complete area in on go:
                    /*
                    // no 3d handling for areas yet
                    points[0]->setPoint( point, lastPoint.x(), yCoord );
                    point++;

                    QPoint firstPoint = points[0]->point( 0 );
                    points[0]->setPoint( point, firstPoint.x(), yCoord );
                    point++;

                    painter->drawPolygon( *points[0], false, 0, point );
                    */

                    // new: draw individual area segments:
                    curPropSetId = KDChartPropertySet::UndefinedID;
                    for( int value = 0; value < point-1; ++value ) {

                        int cellPropID;
                        if( data->cellProp( dataset, value, cellPropID ) &&
                            cellPropID != curPropSetId ){

                            if( cellPropID != KDChartPropertySet::UndefinedID &&
                                params()->calculateProperties( cellPropID,
                                                               curPropSet ) ){
                                curPropSetId = cellPropID;
                            }else{
                                curPropSetId = KDChartPropertySet::UndefinedID;
                            }
                            // preset with default value
                            QBrush theAreaBrush = datasetBrush;

                            if( curPropSetId != KDChartPropertySet::UndefinedID ){
                                // we can safely call the following functions and ignore their
                                // return values since they will touch the parameters' values
                                // if the propSet *contains* corresponding own values only.
                                int iDummy;
                                curPropSet.hasOwnAreaBrush( iDummy, theAreaBrush );
                            }
                            painter->setBrush( theAreaBrush );

                        }
                        QPointArray segment( 4 );
                        segment.setPoint( 0, points[0]->point( value                 ) );
                        segment.setPoint( 1, points[0]->point( value+1               ) );
                        segment.setPoint( 2, points[0]->point( value+1 ).x(), yCoord );
                        segment.setPoint( 3, points[0]->point( value   ).x(), yCoord );                        
                        painter->drawPolygon( segment );
                    }

                    // old: draw the complete area in on go:
                    /*
                    // remove the last two points added
                    point -= 2;
                    */
                    //qDebug("\n111");
                } //  if ( mode == Normal || dataset == (int)datasetEnd )
                else {
                    // don't mess around with the original array; we'll need
                    // that for the next time through.

                    //qDebug("222");
                    // no 3d handling for areas yet
                    QPointArray thisSection = points[0]->copy();

                    thisSection.resize( point + previousPoints.size() );
                    // append the previous array (there is guaranteed to be
                    // one because we are at least the second time through
                    // here) in reverse order
                    for ( unsigned int i = 0; i < previousPoints.size(); ++i ) {
                        thisSection.setPoint( point + i,
                                              previousPoints.point( previousPoints.size() - i - 1 ) );
                        //qDebug("\nx: %i",previousPoints.point( previousPoints.size() - i - 1 ).x());
                        //qDebug("y: %i",previousPoints.point( previousPoints.size() - i - 1 ).y());
                    }
                    painter->drawPolygon( thisSection );
                }
                // draw the line with no brush and outline color
                painter->setBrush( Qt::NoBrush );
                painter->setPen( QPen( params()->outlineDataColor(),
                                       params()->outlineDataLineWidth() ) );
            } else {
                // line
                if( showThreeDLines ) {
                    // This is a 3D line:
                    // We draw the line with the data color brush
                    //                   and the outline data pen.
                    painter->setBrush( params()->dataColor( dataset ) );
                    painter->setPen( QPen( params()->outlineDataColor(),
                                           params()->outlineDataLineWidth() ) );
                } else {
                    // This is a 2D line:
                    // We draw the line with the no brush
                    // and the data color if no special line color was specified.
                    painter->setBrush( Qt::NoBrush );
                    painter->setPen( default2DPen );
                }
            }

            // Neither draw the contour line if this is a pure Point chart
            // nor draw it for the last row of a percent area chart.
           
            if( bDrawLines &&
                ( (mode != Percent) || !mIsArea || (dataset != (int)datasetEnd) ) ){
                if( showThreeDLines ) {
		 
                    // A 3D line needs to be drawn piece-wise
                    for ( int value = 0; value < point-1; ++value ) {
                        //          if( data->cell( dataset, value ).hasValue() &&
                        //              data->cell( dataset, value+1 ).hasValue() ) {
                        //      qDebug( "Draw a segment in dataset %d from %d to %d", dataset, value, value+1 );
                
                        //store the rotated points ( see project() )
                        QPointArray rotatedSegment( 4 );                        
                        rotatedSegment.setPoint( 0, points[0]->point( value ));
                        rotatedSegment.setPoint( 1, points[0]->point( value+1 ) );
                        rotatedSegment.setPoint( 2, points[1]->point( value+1 ) );
                        rotatedSegment.setPoint( 3, points[1]->point( value ) );

                        //store the true points without rotation    
                        QPointArray trueSegment( 4 );			 
                        trueSegment.setPoint( 0, oripoints[0]->point( value ));
                        trueSegment.setPoint( 1, oripoints[0]->point( value+1 ) );
                        trueSegment.setPoint( 2, oripoints[1]->point( value+1 ) );
                        trueSegment.setPoint( 3, oripoints[1]->point( value ) );

                        // calculate the rotated points position relative to each other
                        // we will then be able to keep the rotation ( see: project () )
                        // by reporting this position relative to the true segment line 
                        //left side pt3 and pt0 
                        int dx30 = rotatedSegment.point(3).x() - rotatedSegment.point(0).x();
                        int dy30 = rotatedSegment.point(3).y() - rotatedSegment.point(0).y(); 
                        //right side pt1 and pt2
                        int dx12 = rotatedSegment.point(2).x() - rotatedSegment.point(1).x();
                        int dy12 = rotatedSegment.point(2).y() - rotatedSegment.point(1).y();

                        // store and paint the "3D" segment
                        QPointArray segment( 4 );
                        segment.setPoint( 0, trueSegment.point(0) );
                        segment.setPoint( 1, trueSegment.point(1) );
                        segment.setPoint( 2, trueSegment.point(1).x() + dx12, trueSegment.point(1).y() + dy12 );
                        segment.setPoint( 3, trueSegment.point(0).x() + dx30, trueSegment.point(0).y() + dy30);

		       
                        //PENDING Michel 3dlines drawing a segment with showThreeDLines                       
                        painter->drawPolygon( segment );
		       
                      			
                        //          } else
                        //              qDebug( "Can't draw a segment in dataset %d from %d to %d", dataset, value, value+1 );
                    }
                } else {
                    QPoint p1, p2;
                    // Note: If markers are drawn very near to each other
                    //       and tiny markers are used
                    //       we don't draw the connecting lines.
                    bool b4PMarkers = KDChartParams::LineMarker4Pixels == markerStyle;
                    bool bTinyMarkers =
                        KDChartParams::LineMarker1Pixel  == markerStyle || b4PMarkers;
                    curPropSetId = KDChartPropertySet::UndefinedID;
                    painter->setPen( default2DPen );
                    for ( int value = 0; value < point-1; ++value ) {
                        p1 = points[0]->point( value   );
                        p2 = points[0]->point( value+1 );

                        // Determine properties assigned to this cell
                        // and change the painter if necessarry:
                        currentDrawMarkers = defaultDrawMarkers;
                        int cellPropID;
                        if( data->cellProp( dataset, value, cellPropID ) &&
                            cellPropID != curPropSetId ){
                            if( cellPropID != KDChartPropertySet::UndefinedID &&
                                params()->calculateProperties( cellPropID,
                                                               curPropSet ) ){
                                curPropSetId = cellPropID;
                            }else{
                                curPropSetId = KDChartPropertySet::UndefinedID;
                            }
                            // preset with default values
                            int          theLineWidth = default2DPen.width();
                            QColor       theLineColor = default2DPen.color();
                            Qt::PenStyle theLineStyle = default2DPen.style();
                            if( curPropSetId != KDChartPropertySet::UndefinedID ){
                                // we can safely call the following functions and ignore their
                                // return values since they will touch the parameters' values
                                // if the propSet *contains* corresponding own values only.
                                int iDummy;
                                curPropSet.hasOwnLineWidth ( iDummy, theLineWidth );
                                curPropSet.hasOwnLineColor ( iDummy, theLineColor );
                                curPropSet.hasOwnLineStyle ( iDummy, theLineStyle );
                                curPropSet.hasOwnShowMarker( iDummy, currentDrawMarkers );
                            }
                            painter->setPen( QPen( theLineColor,
                                                   theLineWidth,
                                                   theLineStyle ) );
                        }

                        if( !currentDrawMarkers ){
                            //PENDING Michel: drawing a line - not currentMarkers
                            painter->drawLine( p1, p2 );
                        }else{
                            int dx = p2.x() - p1.x();
                            int dy = p2.y() - p1.y();
                            if( !bTinyMarkers || (abs(dx) > 4) || (abs(dy) > 4) ){
                                if( bTinyMarkers ) {
                                    double m  = !dx ? 100.0
                                        : !dy ? 0.01
                                        : ((double)dy / (double)dx);
                                    double am = fabs(m);
                                    int dxx;
                                    int dyy;
                                    if( 0.25 > am ){
                                        dxx = 3;
                                        dyy = 0;
                                    }else if( 0.67 > am ){
                                        dxx = 3;
                                        dyy = 1;
                                    }else if( 1.33 > am ){
                                        dxx = 2;
                                        dyy = 2;
                                    }else if( 4.0 > am ){
                                        dxx = 1;
                                        dyy = 3;
                                    }else{
                                        dxx = 0;
                                        dyy = 3;
                                    }
                                    if( 0 > dx )
                                        dxx *= -1;
                                    if( 0 > dy )
                                        dyy *= -1;
                                    if( b4PMarkers ){
                                        if( 0 < dx )
                                            ++p1.rx();
                                        else if( 0 > dx )
                                            ++p2.rx();
                                        if( 0 < dy )
                                            ++p1.ry();
                                        else if( 0 > dy )
                                            ++p2.ry();
                                    }
                                    p1.rx() += dxx; p1.ry() += dyy;
                                    p2.rx() -= dxx; p2.ry() -= dyy;
                                }
                                //PENDING Michel: drawing a line - currentMarkers
                                painter->drawLine( p1, p2 );
                            }
                        }
                    }
                }
            }
        }

        // Save point array for next way through (needed for e.g. stacked
        // areas), not for 3D currently
        points[0]->resize( point );
        previousPoints = points[0]->copy();
    }


    // Now draw any extra lines (and/or their markers, resp.) that
    // are to be printed IN FRONT of the normal lines:
    if( mChartType == KDChartParams::Line ){
        for( dataset = datasetEnd; ( dataset >= (int)datasetStart && dataset >= 0 ); --dataset ) {

            const KDChartParams::LineMarkerStyle
                defaultMarkerStyle = params()->lineMarkerStyle( dataset );
            const QPen default2DPen(   params()->lineColor().isValid()
                                       ? params()->lineColor()
                                       : params()->dataColor( dataset ),
                                       params()->lineWidth(),
                                       params()->lineStyle( dataset ) );

            if( ai.bAbscissaHasTrueAxisDtValues )
                ai.numValues = data->cols();

            for ( int value = 0; value < ai.numValues; ++value ) {
                int iVec = static_cast < int > ( datasetEnd-dataset ) * arrayNumValues + value;
                if( allPoints[ iVec ].bValid ){
                    const MyPoint& mp = allPoints[iVec];
                    //qDebug("\np.x() %i        p.y() %i", p.x(), p.y() );

                    // --------------------------------------------------------
                    // determine any 'extra' properties assigned to this cell
                    // by traversing the property set chain (if necessary)
                    // --------------------------------------------------------
                    int cellPropID;
                    if( data->cellProp( dataset, value, cellPropID ) &&
                        cellPropID != curPropSetId ){
                        if( cellPropID != KDChartPropertySet::UndefinedID &&
                            params()->calculateProperties( cellPropID,
                                                           curPropSet ) )
                            curPropSetId = cellPropID;
                        else
                            curPropSetId = KDChartPropertySet::UndefinedID;
                    }
                    if( curPropSetId != KDChartPropertySet::UndefinedID ){
                        drawExtraLinesAndMarkers(
                                                 curPropSet,
                                                 default2DPen,
                                                 defaultMarkerStyle,
                                                 mp.p.x(), mp.p.y(),
                                                 painter,
                                                 ai.abscissaPara,
                                                 ordinatePara,
                                                 logWidth/1000.0,
                                                 logHeight/1000.0,
                                                 true );
                    }
                }
            }
        }
    }
    //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_NORMAL_DATA )->name().latin1());
    //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_TRANSPARENT_DATA )->name().latin1());
    //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_HORI_LINE )->name().latin1());
    //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_VERT_LINE )->name().latin1());
    //qDebug("--");
    }
MStatus liqSurfaceNode::compute( const MPlug& plug, MDataBlock& block )
{
  // outColor or individual R, G, B channel
  if( (plug == aOutColor) || (plug.parent() == aOutColor) ||
	  (plug == aOutTransparency) || (plug.parent() == aOutTransparency)
  	) {

    //cout <<"compute... "<<endl;

    // init shader
    MStatus status;
    MFloatVector theColor( 0.0f, 0.0f, 0.0f );
    MFloatVector& cColor  = block.inputValue(aColor).asFloatVector();
    MFloatVector& cTrans  = block.inputValue(aOpacity).asFloatVector();
    MFloatVector& ctex    = block.inputValue(aGLPreviewTexture).asFloatVector();

    // exploit maya's free openGL preview
    if ( ctex != MFloatVector( -1.0, -1.0, -1.0 ) ) theColor = ctex;
    else theColor = cColor;

    MFloatVector resultColor( 0.0, 0.0, 0.0 );
    MFloatVector resultTrans( cTrans );



    // lambert calc -------------------
    bool&  ignoreLights = block.inputValue( aMayaIgnoreLights, &status ).asBool();
    float& Ka = block.inputValue( aMayaKa, &status ).asFloat();
    float& Kd = block.inputValue( aMayaKd, &status ).asFloat();

    // get surface normal
    MFloatVector& surfaceNormal = block.inputValue( aNormalCamera, &status ).asFloatVector();
    CHECK_MSTATUS( status );

    if ( ignoreLights ) {

      MFloatVector cam( 0.0, 0.0, 1.0 );
      float cosln = cam * surfaceNormal;
      if ( cosln > 0.0f ) {
        float diff = cosln * cosln * Kd + Ka;
        resultColor = diff * theColor;
      }

    } else {

      // Get light list
      MArrayDataHandle lightData = block.inputArrayValue( aLightData, &status );
      CHECK_MSTATUS( status );
      int numLights = lightData.elementCount( &status );
      CHECK_MSTATUS( status );

      // Iterate through light list and get ambient/diffuse values
      for( int count=1; count <= numLights; count++ )
      {
        // Get the current light out of the array
        MDataHandle currentLight = lightData.inputValue( &status );
        CHECK_MSTATUS( status );

        // Get the intensity of that light
        MFloatVector& lightIntensity = currentLight.child( aLightIntensity ).asFloatVector();

        // Find ambient component
        if ( currentLight.child( aLightAmbient ).asBool() ) {
          resultColor += lightIntensity;
        }

        // Find diffuse component
        if ( currentLight.child( aLightDiffuse ).asBool() ) {
          MFloatVector& lightDirection = currentLight.child( aLightDirection ).asFloatVector();
          float cosln = lightDirection * surfaceNormal;
          if ( cosln > 0.0f )  resultColor += lightIntensity * cosln * Kd ;
        }

        // Advance to the next light.
        if ( count < numLights ) {
          status = lightData.next();
          CHECK_MSTATUS( status );
        }
      }

      resultColor[0] *= theColor[0];
      resultColor[1] *= theColor[1];
      resultColor[2] *= theColor[2];

    }

    resultTrans[0] = ( 1 - resultTrans[0] );
    resultTrans[1] = ( 1 - resultTrans[1] );
    resultTrans[2] = ( 1 - resultTrans[2] );


    // set ouput color attribute
    MDataHandle outColorHandle = block.outputValue( aOutColor );
    MFloatVector& outColor = outColorHandle.asFloatVector();
    outColor = resultColor;
    outColorHandle.setClean();

    MDataHandle outTransHandle = block.outputValue( aOutTransparency );
    MFloatVector& outTrans = outTransHandle.asFloatVector();
    outTrans = resultTrans;
    outTransHandle.setClean();

  } else return MS::kUnknownParameter;


  return MS::kSuccess;
}