Logo Search packages:      
Sourcecode: magics++ version File versions  Download package

QtDriver.cc

Go to the documentation of this file.
/******************************** LICENSE ********************************


 Copyright 2007 European Centre for Medium-Range Weather Forecasts (ECMWF)
 
 Licensed under the Apache License, Version 2.0 (the "License"); 
 you may not use this file except in compliance with the License. 
 You may obtain a copy of the License at 
 
      http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software 
 distributed under the License is distributed on an "AS IS" BASIS, 
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 See the License for the specific language governing permissions and 
 limitations under the License.


 ******************************** LICENSE ********************************/

/*! \file QtDriver.cc
    \brief Implementation of QtDriver.
    \author Graphics Section, ECMWF

    Started: Mon Jan  4 20:28:15 2010

*/

#include <QtDriver.h>
#include <Polyline.h>
#include <Text.h>
#include <Image.h>
#include <Layer.h>
#include <AnimationRules.h>
#include <Flag.h>
#include <Symbol.h>

#include <QDebug>
#include <QGraphicsItem>
#include <QPainter>

#include "MgQPlotScene.h"

#include "MgQAnimation.h"
#include "MgQLayerNode.h"
#include "MgQLayoutNode.h"
#include "MgQStepNode.h"
#include "MgQSymbol.h"
#include "MgQPathItem.h"
#include "MgQPixmapItem.h"
#include "MgQTextItem.h"

using namespace magics;

/*!
  \brief Constructor
*/
00058 QtDriver::QtDriver() 
{
      //scene_ = 0;
      initialized_=false;
      symbolManager_=0;
      magnifierIsBeingRedisplayed_=false;
      magnifierZoomFactor_=1.;

      //lineWidthFactor_=0.67;
      //lineWidthFactor_=0.6;
      lineWidthFactor_=0.55;
}

/*!
  \brief Destructor
*/
00074 QtDriver::~QtDriver() 
{
}

/*!
  \brief Opening the driver
*/
00081 void QtDriver::open()
{
      MgQPlotScene *scene = static_cast<MgQPlotScene*>(scene_);

      //If the driver is already initialized
      if(initialized_) 
      {                                                                 
            //Re- the tree
            scene->clearBeforeNewRequest();

            MgQBaseNode *rootNode=new MgQBaseNode("root");
            currentNode_=rootNode;
            scene->addItem(rootNode);
            scene->setRootNode(rootNode);

            //Delete layout node stack
            while(!layoutNodeStack_.empty())
            {
                  layoutNodeStack_.pop();
            }

            //Initialise layout node stack
            layoutNodeStack_.push(0);


            //Delete layer node stack
            while(!layerNodeStack_.empty())
            {
                  layerNodeStack_.pop();
            }

            //Initialise layer node stack
            layerNodeStack_.push(0);

            //Clear the display
            //glClear(GL_COLOR_BUFFER_BIT);
            
            return;
      }

      //We do it for 75 dpi
      //if(QX11Info::appDpiX() > 0)

      setCMscale(75.*1./2.54);// cm -> pixel

      dimensionX_ = floorf(convertCM(getXDeviceLength()));
      dimensionY_ = floorf(convertCM(getYDeviceLength()));

      scene->setSceneRect(0,0,dimensionX_,dimensionY_);
            
      currentNode_=0;
      animationNode_=0;
      
      MgQBaseNode *rootNode=new MgQBaseNode("root");
      currentNode_=rootNode;
      scene->addItem(rootNode);
      scene->setRootNode(rootNode);
      rootNode->setEnabled(false);

      //Initialise layout node stack
      layoutNodeStack_.push(0);

      //Scaling factors have to be stored for 
      //symbol plotting and for rotations in an unscaled co-ordinate system
      coordRatioX_=1.;
      coordRatioY_=1;

      //Set initialization flag
      initialized_=true;

}

/*!
  \brief Closing the driver
*/
00156 void QtDriver::close()
{     
      MgQPlotScene *scene = static_cast<MgQPlotScene*>(scene_);
      scene->selectCurrentStepForAnimation();


      //Render the whole graphical tree, indicating thet it is anew tree!
      renderTree(stepToRender_,true);

      //endPage();
      currentPage_ = 0;
}

/*!
  \brief starting a new page

  This method has to take care that previous pages are closed and that
  for formats with multiple output files a new file is set up.
*/
00175 MAGICS_NO_EXPORT void QtDriver::startPage() const
{
      if(currentPage_ > 0) endPage();

      Log::debug() << "QtDriver::startPage needs implementing." <<endl;
      
      currentPage_++;
      newPage_ = true;
}

/*!
  \brief ending a page
 
  This method has to take care that for formats with multiple output 
  files are closed.
*/
00191 MAGICS_NO_EXPORT void QtDriver::endPage() const
{
      Log::debug() << "QtDriver::endPage needs implementing." <<endl;
}
/*!
  \brief project to a new Layout

  This method will update the offset and scale according to the new Layout given.

  \sa Layout
*/

00203 MAGICS_NO_EXPORT void QtDriver::project(const magics::Layout& layout) const
{
      //Create a new Layout Node
      string name=layout.name();
      MgQLayoutNode *node = new MgQLayoutNode(name.c_str(),layout);
      node->setData(0,QVariant("Layout"));
      project(node);                
}

/*!
  \brief project to a new Layout

  This method will update the offset and scale according to the new PreviewLayout given.

  \sa Layout
*/

00220 MAGICS_NO_EXPORT void QtDriver::project(const magics::PreviewLayout& layout) const
{
      //Create a new PreviewLayoutNode
      string name=layout.name();
      MgQPreviewLayoutNode *node = new MgQPreviewLayoutNode(name.c_str(),layout);
      node->setData(0,QVariant("PreviewLayout"));
      node->hide();
      project(node);
}

/*!
  \brief project to a new Layout

  This method will update the offset and scale according to the new MagnifierLayout given.

  \sa Layout
*/

00238 MAGICS_NO_EXPORT void QtDriver::project(const magics::MagnifierLayout& layout) const
{
      //Create a new MagnifierLayoutNode
      string name=layout.name();
      MgQMagnifierLayoutNode *node = new MgQMagnifierLayoutNode(name.c_str(),layout);
      node->setData(0,QVariant("MagnifierLayout"));
      //node->hide();
      project(node);
}

/*!
  \brief project to a new Layout

  This method will update the offset and scale according to the new Layout given.

  \sa Layout
*/
00255 MAGICS_NO_EXPORT void QtDriver::project(MgQLayoutNode *node) const
{
      const Layout& layout = node->layout();
      
      if(layout.isZoomable())
      {
            node->setData(1,QVariant("Zoomable"));
      }


      Log::debug() << "---> (Qt) PROJECT " << layout.name() <<  endl;

      //Get layout geometry
      const float width    = layout.width()  * 0.01 * dimensionX_;
      const float height   = layout.height() * 0.01 * dimensionY_;
      const float x        = layout.x() * 0.01 * dimensionX_;
      const float y        = layout.y() * 0.01 * dimensionY_;
      
      //Get layout coordinate range
      const float minX = layout.minX();
      const float maxX = layout.maxX();
      const float minY = layout.minY();
      const float maxY = layout.maxY();
      const float rangeX = maxX - minX;
      const float rangeY = maxY - minY;

      //Set dimensions
      dimensionStack_.push(dimensionX_);
      dimensionStack_.push(dimensionY_);  
      dimensionX_ = width;
      dimensionY_ = height;
      node->dimensionX(dimensionX_);
      node->dimensionY(dimensionY_);
      
      //Add to parent
      MgQBaseNode *parentNode=currentNode_;     
      node->setParentItem(parentNode);
      node->setParentItemInMainScene(parentNode);

      //--------------------------------------------  
      // Define the coordinate system translation
      // (in parent coordinates!) 
      //--------------------------------------------

      QTransform tr;

      //Here we have to compensate the translation by project(-XMin) etc. in the 
      //parent layout node!
      MgQLayoutNode *parentLayoutNode=layoutNodeStack_.top();
      if(parentLayoutNode)
      {
            tr.translate(parentLayoutNode->projectedMinX(),
                         parentLayoutNode->projectedMinY());
            
            Log::dev() << "Translate redo: " << parentLayoutNode->projectedMinX()  << " " 
                        << parentLayoutNode->projectedMinY() << endl;   
      }


      //Translate the origo
      tr.translate(x,y);
      Log::dev() << "Translate: " << x << " " << y << endl;  

      //Set the scaling factor
      //projectX and, projectY depend on coordRatio[X,Y]_ !!!           
      const float xx = width/rangeX;
      const float yy = height/rangeY;

      scalesX_.push(coordRatioX_);
      scalesY_.push(coordRatioY_);
      coordRatioX_ = xx;
      coordRatioY_ = yy;
      
      node->coordRatioX(coordRatioX_);
      node->coordRatioY(coordRatioY_);

      //Translate the origo
      tr.translate(projectX(-minX),projectY(-minY));

      //Save the projected minX, minY
      node->projectedMinX(projectX(minX));
      node->projectedMinY(projectY(minY));
      node->projectedMaxX(projectX(maxX));
      node->projectedMaxY(projectY(maxY));

      Log::dev() << "Translate: " << projectX(-minX) << " " << projectY(-minY) << endl;    

      //Set thr transformation for the layout node
      node->setTransform(tr);

#if 0
      if(layout.name() == "drawing" || layout.name() == "left" || layout.name() == "top")
      {
            QGraphicsRectItem *r=new QGraphicsRectItem(projectX(minX),projectY(minY),projectX(rangeX),projectY(rangeY));
            Log::debug() << projectX(minX) << "  " << projectY(minY) << " " << projectX(rangeX) << " " << projectY(rangeY) << endl;

            if(layout.name() != "drawing")
                  r->setBrush(Qt::cyan);
            else
                  r->setBrush(Qt::red);   
            //r->setTransform(tr);
            //scene_->addItem(r);
            //group->addToGroup(r);
            r->setParentItem(layoutItem);
      }
#endif

      //Update node history
      currentNode_=node;
      layoutNodeStack_.push(node);

      //Add animaton
      if(layout.animationRules() && !layout.animationRules()->empty())
      {           
            MgQAnimation *an= new MgQAnimation(layout.animationRules(),*this);
            MgQPlotScene *scene = static_cast<MgQPlotScene*>(scene_);
            scene->addAnimation(node,an);
      }
}

/*!
  \brief reproject out of the last Layout

  This method will update the offset and scale to the state they were before the
  last Layout was received.

*/
00382 MAGICS_NO_EXPORT void QtDriver::unproject() const
{
      MgQLayoutNode *qln=layoutNodeStack_.top();

      if(qln)
            Log::debug() << "---> (Qt) UNPROJECT " <<  qln->layout().name() << endl;
      else
            Log::debug() << "---> (Qt) UNPROJECT 0x000000" << endl;


      //If layout node is zero returns
      if(!qln) return;

      //Set current node to the layouts parent
      if(qln->parentItem() != 0)
            currentNode_=static_cast<MgQBaseNode*>(qln->parentItem());
      else
            currentNode_=0;

      //Pop layout from the stack
      layoutNodeStack_.pop();

      //Verify dimension stack
      if(dimensionStack_.empty())
      {
            Log::error() << "--->UNPROJECT (" <<
                        ") Dimension stack error!" << endl;
            assert(dimensionStack_.empty() == false);
      }

      coordRatioX_= scalesX_.top();
      coordRatioY_= scalesY_.top();
      scalesX_.pop();
      scalesY_.pop();

      //Verify dimension stack
      dimensionY_ = dimensionStack_.top();
      dimensionStack_.pop();
      dimensionX_ = dimensionStack_.top();
      dimensionStack_.pop();
}

/*!
  \brief setup a new layer

  This method will setup a new layer. Layers enable overlays of entities
  of information.

  \sa PhysicalLayer
*/
00432 MAGICS_NO_EXPORT void QtDriver::newLayer(const Layer& layer) const
{
      QString name(layer.id().c_str());

      MgQLayoutNode *parentLayout=layoutNodeStack_.top();

      MgQLayerNode* qln =  new MgQLayerNode(name, layer, parentLayout); 
      qln->setParentItem(currentNode_);
      qln->setData(0,QVariant("Layer"));
            
      layerNodeStack_.push(qln);
      currentNode_=qln->rootNode();
}

/*!
  \brief close the current layer

  This method will close an existing layer. This includes resets of existing boxes. 

  \sa UnPhysicalLayer PhysicalLayer
*/
00453 MAGICS_NO_EXPORT void QtDriver::closeLayer(const Layer& layer) const
{     
      //Get current layer node
      MgQLayerNode *qln=layerNodeStack_.top();

      if(qln)
            Log::debug() << "---> (Qt) CLOSE LAYER" <<  qln->layer().name() << endl;
      else
            Log::debug() << "---> (Qt) CLOSE LAYER 0x000000" << endl;

      //If layer node is zero returns
      if(!qln) return;

      //Get current layer node
      assert(qln->layer().id() == layer.id()); 

      //Pop layer node from the stack
      layerNodeStack_.pop();

      //Set current node to the layer parent
      if(qln->parentItem() != 0)
            currentNode_=static_cast<MgQBaseNode*>(qln->parentItem());
      else
            currentNode_=0;
}


/*!
  \brief sets a new colour

  This colour stays the default drawing colour until the painting in the 
  current box is finished.

  \sa Colour
*/
00488 MAGICS_NO_EXPORT void QtDriver::setNewColour(const Colour &colour) const
{
      if(currentColour_ == colour) return;
      currentColour_ = colour;
      //Log::debug() << "QtDriver::setNewColour needs checking." <<endl;
}

/*!
  \brief sets a new line width

  This line width stays the default width until the painting in the 
  current box is finished.

  \sa setLineParameters()
*/
00503 MAGICS_NO_EXPORT void QtDriver::setNewLineWidth(const float width) const
{
      currentLineWidth_ = width*lineWidthFactor_;
      //Log::debug() << "QtDriver::setNewColour needs checking." <<endl;
}

/*!
  \brief sets new properties of how lines are drawn

  These properties stay the default until the painting in the 
  current box is finished.

  \sa LineStyle

  \param linestyle Object describing the line style
  \param w width of the line

*/
00521 MAGICS_NO_EXPORT int QtDriver::setLineParameters(const LineStyle linestyle, const float w) const
{
      setNewLineWidth(w);

      //Log::debug() << "QtDriver::setLineParameters needs implementing." <<endl;
      return 0;
}

/*!
  \brief renders polylines

  This method renders a polyline given as two float arrays. The two 
  arrays given as X and Y values have to be at least the length of
  <i>n</i>. All values beyond <i>n</i> will be ignored. The style is
  determined by what is described in the current LineStyle.

  \sa setLineParameters()
  \param n number of points
  \param x array of x values
  \param y array of y values
*/
00542 MAGICS_NO_EXPORT void QtDriver::renderPolyline(const int n, float *x, float *y) const
{
      QVector<QPointF> pp;
      for(int i = 0; i<n; i++)
      {
            pp << QPointF(projectX(x[i]),projectY(y[i]));
      }

      QPainterPath path;
      path.addPolygon(pp);
      QGraphicsPathItem *item=new QGraphicsPathItem(path);
      item->setParentItem(currentNode_);
      QPen pen(QPen(QColor::fromRgbF(currentColour_.red(),
                                currentColour_.green(),
                                currentColour_.blue())));
      pen.setWidthF(currentLineWidth_);
      pen.setCosmetic(true);
      item->setPen(pen);
}

/*!
  \brief renders a single line

  This method renders a polyline with two points.The style is
  determined by what is described in the current LineStyle.

  \sa setLineParameters()
  \param n number of points
  \param x array of x values
  \param y array of y values
*/
00573 MAGICS_NO_EXPORT void QtDriver::renderPolyline2(const int n, float* x, float* y) const
{
      if(n != 2) return;

      QLineF pp(x[0],y[0],x[1],y[1]);

      QGraphicsLineItem *item=new QGraphicsLineItem(pp);
      item->setParentItem(currentNode_);
      QPen pen(QPen(QColor::fromRgbF(currentColour_.red(),
                                currentColour_.green(),
                                currentColour_.blue())));
      pen.setWidthF(currentLineWidth_);
      pen.setCosmetic(true);
      item->setPen(pen);
      
}

/*!
  \brief renders a filled polygon

  This method renders a filled polygon. The style is
  determined by what is described in the current LineStyle.

  \sa setLineParameters()
  \param n number of points
  \param x array of x values
  \param y array of y values
*/
00601 MAGICS_NO_EXPORT void QtDriver::renderSimplePolygon(const int n, float* x, float* y) const
{
      QVector<QPointF> pp;
      for(int i = 0; i<n; i++)
      {
            pp << QPointF(projectX(x[i]),projectY(y[i]));
      }
      QGraphicsPolygonItem *item=new QGraphicsPolygonItem(pp);
      item->setParentItem(currentNode_);
      item->setPen(QPen(Qt::red));
      item->setBrush(QColor::fromRgbF(currentColour_.red(),
                                currentColour_.green(),
                                currentColour_.blue()));
}

/*!
  \brief renders text strings

  This method renders given text strings.

  \note As of version 2.0 there are two forms of describing text in Text.

  \sa Text
  \param text object containing the strings and their description
*/
00626 MAGICS_NO_EXPORT void QtDriver::renderText(const Text& text) const
{
      if(text.empty()) return;

      //Check if nicetext available
      const vector<NiceText>& niceT = text.getNiceText();
      if(niceT.empty()) return;
      
      const enum Justification horizontal = text.getJustification();
      const enum VerticalAlign vertical   = text.getVerticalAlign();

      string textString;                                    
        float pheight;
      
      //Loop for the indidual text items
      for(vector<NiceText>::const_iterator niceText=text.textBegin(); niceText != text.textEnd(); niceText++)                               
      {                             
            const MagFont magfont = niceText->font();

                const std::set<string>& styles = magfont.styles();

            //pheight = 72.*convertCM(magfont.size())/75.; //height in points 
            pheight = 72.*magfont.size()/2.54; //height in points
            pheight*=1.2;
      
                QFont font(QString::fromStdString(magfont.name()), pheight);
            font.setPointSizeF(pheight);
                if (styles.find("underlined") != styles.end()) font.setUnderline(true);
                if(styles.find("bold") != styles.end())        font.setBold(true);
                if(styles.find("italic") != styles.end())      font.setItalic(true);

            QString str;
            textToUnicode((*niceText).text(),str);
            //QString str = QString::fromStdString((*niceText).text());

                QFontMetrics fm(font);
                int width  = fm.width(str);
                int height = fm.height();

                float x = 0;
                if(horizontal == MCENTRE)     x = width*.5;
                else if(horizontal == MRIGHT) x = width;

                float y = 0.;
                if (vertical==MBASE)        { y = height;}
                else if (vertical==MTOP)    { y = 0.;}
                else if (vertical==MHALF)   { y = height*.5;}
                else if (vertical==MBOTTOM) { y = height;}

            unsigned int noTexts = text.size();
            for(unsigned int nT=0;nT<noTexts;nT++)  // for all string CO-ORDINATES
            {           
                  const float x0 = projectX(text[nT].x());
                  const float y0 = projectY(text[nT].y());
                  const float an = text.getAngle()*57.29577951;
 
                  //Create the item
                  MgQTextItem *item= new MgQTextItem(str);
                  item->setParentItem(currentNode_);
                  item->setFont(font);
                  //item->setPen(QPen());
                  item->setTextBlanking(text.getBlanking());
                  item->setBrush(QColor::fromRgbF(magfont.colour().red(),
                               magfont.colour().green(),
                                       magfont.colour().blue()));

                  if(magnifierIsBeingRedisplayed_==true)
                  {
                        item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
                  }
      
                        item->setPos(x0,y0);
                  QTransform tr;
                  tr.scale(1.,-1.);
                  tr.translate(-x,-y);
                  item->setTransform(tr);

                  if(an !=0 &&  an != 360)      
                        item->rotate(an);
            }
      }
}


 // \brief Convert std::string to unicode QString     
 void QtDriver::textToUnicode(const string &str,QString &ustr) const
 {        
      const int len = str.length()+1;
      char pp[len];
      strcpy(pp, str.c_str());
      unsigned char *p = (unsigned char*)pp;          
      bool specialChar = false;           
      std::ostringstream special;                     
      int ucode;
            
      //HTML 4 entities &#...; decimal form
      
      while(*p)
      {
            if(specialChar)
            {
                  if( *p == ';')
                  {                       
                        std::istringstream buf(special.str());
                        buf >> ucode;
                        ustr+=QChar(ucode);
                        specialChar=false;
                  }
                  else
                  {
                        special << *p;
                  }
            }
            else if ( *p == '&')    
            {
                  p++;
                    if(*p)
                  {
                        if(*p=='#')
                        {                                                           
                              specialChar=true;
                        }
                        else 
                        {
                         ustr+=QChar('&');                                                 
                         ustr+=QChar(*p);
                        } 
                  } 
                  //else tmp<<"&";
            }
              
            //Handle 1 byte UTF-8 characters between 0x01 and 0x7F. These are
            //representing themselves. 
            //else if(*p < 0xC0)
            else          
            {
                  ustr+=QChar(*p);
            }

            p++;
      }             

}

/*!
  \brief drawing a circle

  This method renders given text strings.

  The meaning of the last parameter <i>s</i> is as follows:
     - 0-8 determines how many quarters of the circle are filled. Starting from the top clock-wise.
     - 9 fills the whole circle but leaves a vertical bar empty in the middle of the circle.

  \param x X Position
  \param y Y Position
  \param r Radius of circle
  \param s Style which determines how the circle is shaded
*/
00784 MAGICS_NO_EXPORT void QtDriver::circle(const float x, const float y, const float r, const int s) const
{
      Log::debug() << "QtDriver::circle needs implementing." <<endl;
}

/*!
  \brief render pixmaps

  This method renders pixmaps. These are used for cell shading and raster input (GIFs and PNGs).

  \sa renderCellArray()

  \param x0 x of lower corner
  \param y0 y of lower corner
  \param x1 x of higher corner
  \param y1 y of higher corner
  \param w width of pixmap
  \param h height of pixmap
  \param pixmap contents
  \param landscape says if contents is landscape

*/
00806 MAGICS_NO_EXPORT bool QtDriver::renderPixmap(float x0,float y0,float x1,float y1,
                                            int w,int h,unsigned char* pixmap,int landscape, bool hasAlpha) const
{
      Log::debug() << "renderPixmap: " << x0 << " " << y0 << " " << x1 << " " << y1 << endl; 


      QImage img=QImage(w,h,QImage::Format_ARGB32);

      //uchar *data = new uchar[w*h*4];
      int srcPos;
      int pixel;

      if(hasAlpha)
      {
            for(int j=0; j< h; j++)
            {
                  for(int i=0; i < w; i++)
                  {                 
                        srcPos=((h-j-1)*w+i)*4;
                        pixel=qRgba(pixmap[srcPos+1],pixmap[srcPos+2],pixmap[srcPos+3],pixmap[srcPos]);           
                        img.setPixel(i,j,pixel);
                  }
            }
      }
      else
      {
            for(int j=0; j< h; j++)
            {
                  for(int i=0; i < w; i++)
                  {                 
                        srcPos=((h-j-1)*w+i)*3;
                        pixel=qRgba(pixmap[srcPos],pixmap[srcPos+1],pixmap[srcPos+2],0xff);                 
                        img.setPixel(i,j,pixel);
                  }
            }

            /*int srcPos=(h-1)*w*3;
            int targetPos=0;
            for(int j=0; j< h; j++)
            {
                  for(int i=0; i < w; i++)
                  {     
                        data[targetPos]=pixmap[srcPos+2];
                        data[targetPos+1]=pixmap[srcPos+1];
                        data[targetPos+2]=pixmap[srcPos];
                        data[targetPos+3]=0xff;

                        srcPos+=3;
                        targetPos+=4;
                  }
                  srcPos-=w*3;
            }
            img=QImage(data,w,h,QImage::Format_ARGB32);*/   
      }


      MgQPixmapItem *item=new MgQPixmapItem(QPixmap::fromImage(img));
      
      item->setParentItem(currentNode_);
      item->setTargetRect(QRectF(x0,y0,x1-x0,y1-y0));       
      item->setPos(x0,y0);    

      //MgQLayoutNode layoutParent=layoutNodeStack_.top();
      //QRectF r=layoutparent->sceneBoundingRect();


      //delete data;

      return true;
}

/*!
  \brief render cell arrays

  This method renders cell arrays, also called images in Magics language. These are 
  mainly used for satellite data.

  \sa renderPixmap()

  \param image Object containing an image
*/
00887 MAGICS_NO_EXPORT bool QtDriver::renderCellArray(const Image& image) const
{
      ColourTable &lt = image.getColourTable(); 
      const int width  = image.getNumberOfColumns();
      const int height = image.getNumberOfRows();
      const float x0 = projectX(image.getOrigin().x());
      const float y0 = projectY(image.getOrigin().y());
      const float x1 = projectX(image.getOrigin().x()+image.getWidth());
      const float y1 = projectY(image.getOrigin().y()+image.getHeight());
      
      //Converts colour table into qRGb
      QList<QRgb> cols;
      for(int i=0 ; i < lt.size(); i++)
      {
            cols << QColor::fromRgbF(lt[i].red(),lt[i].green(),lt[i].blue()).rgb();
      }
      
      //Create an image
      QImage img(width,height,QImage::Format_ARGB32);
      img.fill(0x00ffffff);

      for (int i=0; i < height;i++)
      {
            for(int j=0;j< width; j++)
            {
              const int in = width*i+j;    
              const short c = image[in];

              if(!(lt[c]=="none"))
              {               
                  img.setPixel(j,height-i-1,cols[c]); 
                                
              }
            }
      }
      //          
      MgQPixmapItem *item=new MgQPixmapItem(QPixmap::fromImage(img));
      item->setParentItem(currentNode_);
      item->setTargetRect(QRectF(x0,y0-(y1-y0),x1-x0,y1-y0));           
      item->setPos(x0,y0-(y1-y0));  

      return true;
}


00932 void QtDriver::generateSymbolPath(MgQSymbolItem *qSym,svgSymbol sym) const
{
      //setCoordRatio(1.,1.);

      //Symbol size in pixels!!!
      float symbolSize=qSym->size();

      const unsigned int si = sym.elements.size();

      //setNewLineWidth(1.);
      //const float pX = 1. / coordRatioX_;
      //const float pY = 1. / coordRatioY_;

      const float scaling=symbolSize; ///convertCM(1.);
      
      QPainterPath path;

      for(unsigned int i=0;i<si;i++)  // for all elements in the symbol description
      {

            if(sym.elements[i].name == "circle")
            {
                  const float r  = atof(sym.elements[i].attributes["r"].c_str())  * scaling;
                  const float cx = atof(sym.elements[i].attributes["cx"].c_str()) * scaling;
                  const float cy = atof(sym.elements[i].attributes["cy"].c_str()) * scaling;
                  const int s = atoi(sym.elements[i].attributes["fill"].c_str());
                  //circle(cx,cy,r,s);
            }
            else if(sym.elements[i].name == "snowflake")
            {
                  const float r = atof(sym.elements[i].attributes["r"].c_str()) * scaling;
                  const float cx = atof(sym.elements[i].attributes["cx"].c_str()) * scaling;
                  const float cy = atof(sym.elements[i].attributes["cy"].c_str()) * scaling;                
                  //snowflake(cx,cy,r);
            }
            else if(sym.elements[i].name == "drizzle")
            {
                  const float r = atof(sym.elements[i].attributes["r"].c_str()) * scaling;
                  const float cx = atof(sym.elements[i].attributes["cx"].c_str()) * scaling;
                  const float cy = atof(sym.elements[i].attributes["cy"].c_str()) * scaling;
                  //drizzle(cx,cy,r);
            }
            else if(sym.elements[i].name == "triangle")
            {
                  const float r = atof(sym.elements[i].attributes["r"].c_str()) * scaling;
                  const int s = atoi(sym.elements[i].attributes["fill"].c_str());
                  const float cx = atof(sym.elements[i].attributes["cx"].c_str()) * scaling;
                  const float cy = atof(sym.elements[i].attributes["cy"].c_str()) * scaling;
                  const int li = atoi(sym.elements[i].attributes["line"].c_str());
                  //triangle(cx,cy,r,s,li);
            }
            else if(sym.elements[i].name == "lightning")
            {
                  const float r = atof(sym.elements[i].attributes["r"].c_str()) * scaling;
                  const float cx = atof(sym.elements[i].attributes["cx"].c_str()) * scaling;
                  const float cy = atof(sym.elements[i].attributes["cy"].c_str()) * scaling;
                  //lightning(cx,cy,r);
            }

            else if(sym.elements[i].name == "polyline")
            {                 
                  vector<PaperPoint> vPP;
                  parsePoints(vPP, sym.elements[i].attributes["points"]);
                                    
                  for(int s=0;s<vPP.size();s++)
                  {
                        vPP[s].x( vPP[s].x() * scaling);
                        vPP[s].y( vPP[s].y() * scaling);
                   }    
                  
                  QVector<QPointF> pp;
                  for(int j = 0; j< vPP.size(); j++)
                  {
                        //pp << QPointF(projectX(vPP[j].x()),projectY(vPP[j].y()));
                        pp << QPointF(vPP[j].x(),vPP[j].y());
                  }

                  path.addPolygon(pp);

                  if(magCompare("none",sym.elements[i].attributes["fill"]) )
                  {
                        //createPolylinePath(vPP);
                  }
                  else 
                  {
                        //createSimplePolygonPath(vPP);
                  }
                  
            }
      }// endfor 

      qSym->setPath(path);

      //resetCoordRatio();
}


01029 MAGICS_NO_EXPORT void QtDriver::renderSymbols(const Symbol& symbol) const
{     
      //setLineParameters(M_SOLID, 1.); // reset line

      // if still empty
      loadSymbols();
      
      if(sym_.size() == 0 ) 
      {
            Log::error() << "QtDriver::renderSymbols() --> NO symbols available!" << endl;
            return;
      }

      Log::dev() << "Number of symbols: " << symbol.size() << endl;

      const int noSymbols = sym_.size();
      svgSymbol sym;

      int ii=0;
      for(;ii<noSymbols;ii++)
      {
            sym = sym_[ii];
            if(sym.id==symbol.getSymbol()) break;
      }

      if(ii==noSymbols) sym = sym_[0];

      //Find out symbol size in pixels!!!!!!!
      float symbolSize = convertCM(symbol.getHeight());

      //Magnifier data mode
      //if(glLayoutStack_.top()->classType() == "OpenGLMagnifierLayoutNode")
      //{
      //    symbolSize/=magnifierZoom_;
      //}

      //Create symbolmanager if needed
      if(!symbolManager_)
      {
            symbolManager_ =  new MgQSymbolManager;
      }

      //If needed compile a display list for the symbol
      //The size of this symbol is "1 cm"
      MgQSymbolItem *actSymbol;
      QString id(QString::fromStdString(sym.id));
      if((actSymbol=symbolManager_->getSymbol(id,symbolSize)) == 0 )
      {
            actSymbol=symbolManager_->addSymbol(id,symbolSize);
            generateSymbolPath(actSymbol,sym);
      }

      //Set colour
      setNewColour(symbol.getColour());   
      
      for(unsigned int i=0;i<symbol.size();i++)
//    for(unsigned int i=0;i<1000;i++)
      { 
            MgQPathItem *item=new MgQPathItem(actSymbol->path());
            item->setParentItem(currentNode_);
            item->setPen(QColor::fromRgbF(currentColour_.red(),
                                currentColour_.green(),
                                currentColour_.blue()));
            item->setPos(projectX(symbol[i].x()),projectY(symbol[i].y()));    
            
            item->setBoundingRectSize(symbolSize);

            if(magnifierIsBeingRedisplayed_ == true)
            {
                  item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
            }
      }
}


void QtDriver::renderTree(int stepNo,bool newGlTree)
{
}     

01108 MAGICS_NO_EXPORT void QtDriver::redisplay(const StepRenderer& stepRenderer) const
{
      //Current layout
      MgQLayoutNode* qln=layoutNodeStack_.top();

      MgQAnimation *animation;
      MgQPlotScene *scene = static_cast<MgQPlotScene*>(scene_);
      if((animation = scene->animation()) ==0)
            return;
      
      for(int i=0; i < animation->count(); i++) 
      {
            //Log::debug() <<"step: " << step->label() << endl;
            std::ostringstream out;
            out  << i;
            string name= "step_" + out.str();                           

            MgQStepNode *qsn=new MgQStepNode(name.c_str(),qln);         
            qsn->setParentItem(currentNode_);

            //currentNode_=qsn;

            animation->step(i)->addNode(qsn);
            //animation->step(i)->stepObject()->execute(*this,qln->layout());

            //currentNode_=qln;
      }
}

MAGICS_NO_EXPORT void QtDriver::executeStep(const MgQAnimationStep& step,MgQStepNode *node) const
{
      MgQBaseNode *prevNode=currentNode_;
      MgQLayoutNode *parent=node->parentLayoutNode();
      layoutNodeStack_.push(parent);

      dimensionStack_.push(dimensionX_);
      dimensionStack_.push(dimensionY_);
      dimensionX_=parent->dimensionX();
      dimensionY_=parent->dimensionY();

      currentNode_=node;
      step.stepObject()->execute(*this,node->parentLayoutNode()->layout());

      currentNode_=prevNode;
      layoutNodeStack_.pop();

      dimensionY_  = dimensionStack_.top();
      dimensionStack_.pop();  
      dimensionX_  = dimensionStack_.top();
      dimensionStack_.pop();
}

MAGICS_NO_EXPORT void QtDriver::redisplayMagnifier(MgQMagnifierLayoutNode* node) const
{
      MgQBaseNode *prevNode=currentNode_;
      layoutNodeStack_.push(node);

      dimensionStack_.push(dimensionX_);
      dimensionStack_.push(dimensionY_);
      dimensionX_=node->dimensionX();
      dimensionY_=node->dimensionY();

      scalesX_.push(coordRatioX_);
      scalesY_.push(coordRatioY_);
      coordRatioX_ = node->coordRatioX();
      coordRatioY_ = node->coordRatioY();

      vector<PaperPoint> pp;
      for(int i=0; i < node->area().count();i++)
      {
            pp.push_back(PaperPoint(node->area()[i].x(),
                       node->area()[i].y()));
      }

      magnifierZoomFactor_=node->zoomFactor();
      magnifierIsBeingRedisplayed_=true;

      //MgQBaseNode *rootNode=new MgQBaseNode("MagnifierRoot");
      //node->setRootNode(rootNode);
      //rootNode->setParentItem(node);

      currentNode_=node;

      node->layout().redisplay(*this,node->step(),
                  pp,node->resolutionX(),node->resolutionY());

      magnifierZoomFactor_=1.;
      magnifierIsBeingRedisplayed_=false;

      currentNode_=prevNode;
      layoutNodeStack_.pop();

      dimensionY_  = dimensionStack_.top();
      dimensionStack_.pop();  
      dimensionX_  = dimensionStack_.top();
      dimensionStack_.pop();

      coordRatioX_ = scalesX_.top();
      coordRatioY_ = scalesY_.top();
      scalesX_.pop();
      scalesY_.pop();
}



01213 MAGICS_NO_EXPORT void QtDriver::redisplay(const Layer& layer) const 
{
      newLayer(layer);
      layer.visit(*this);
      closeLayer(layer);
}


MAGICS_NO_EXPORT void QtDriver::redisplay(const PreviewLayout& layout) const 
{
      project(layout);
      layout.visit(*this);  // visit this ROOT layout! 
      unproject();
}

MAGICS_NO_EXPORT void QtDriver::redisplay(const MagnifierLayout& layout) const 
{
      project(layout);
      layout.visit(*this);  // visit this ROOT layout! 
      unproject();
}
  
 
/*!
  \brief prints debug output

  When Magics++ is compiled in debug mode these extra strings are printed.

  \note This can increase file and log file sizes if you run Magics++ in debug mode!

  \param s string to be printed
*/
MAGICS_NO_EXPORT void QtDriver::debugOutput(const std::string &s) const
{
      Log::debug() << s << endl;
}

/*!
  \brief class information are given to the output-stream
*/
01253 void QtDriver::print(ostream& out)  const
{
      out << "QtDriver[";
      out << "]";
}

static SimpleObjectMaker<QtDriver, BaseDriver> Qt_driver("Qt");

Generated by  Doxygen 1.6.0   Back to index