Logo Search packages:      
Sourcecode: labplot version File versions

qwt3d_gridplot.cpp

#if defined(_MSC_VER) /* MSVC Compiler */
#pragma warning ( disable : 4305 )
#pragma warning ( disable : 4786 )
#endif

#include "qwt3d_surfaceplot.h"
#include "qwt3d_enrichment_std.h"

using namespace std;
using namespace Qwt3D;



void SurfacePlot::createDataG()
{
  createFloorData();
  
  if (plotStyle() == NOPLOT)
            return;

      int i, j;
      RGBA col;
      int step = resolution();

  if (plotStyle() == Qwt3D::SPOINTS)
  {
    createPoints();
    return;
  }
  else if (plotStyle() == Qwt3D::USER)
  {
    if (userplotstyle_p)
      createEnrichment(*userplotstyle_p);
    return;
  }

      setDeviceLineWidth(meshLineWidth());
  
  GLStateBewarer sb(GL_POLYGON_OFFSET_FILL,true);
      setDevicePolygonOffset(polygonOffset(),1.0);

      GLStateBewarer sb2(GL_LINE_SMOOTH, smoothDataMesh());
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


  int lastcol =  actualDataG_->columns();
  int lastrow =  actualDataG_->rows(); 
 
      if (plotStyle() != WIREFRAME)
      {
            glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
            
            bool hl = (plotStyle() == HIDDENLINE);
            if (hl)
            {
                  col = backgroundRGBAColor();
                  glColor4d(col.r, col.g, col.b, col.a);
            }

            for (i = 0; i < lastcol - step; i += step) 
            {
              glBegin(GL_TRIANGLE_STRIP);
                        setColorFromVertexG(i, 0, hl);
                        glNormal3dv(actualDataG_->normals[i][0]);
                        glVertex3dv(actualDataG_->vertices[i][0]);
                              
                        setColorFromVertexG(i+step, 0, hl);
                        glNormal3dv(actualDataG_->normals[i+step][0]);
                        glVertex3dv(actualDataG_->vertices[i+step][0]);

                        for (j = 0; j < lastrow - step; j += step) 
                        {                       
                              setColorFromVertexG(i,j+step, hl);
                              glNormal3dv(actualDataG_->normals[i][j+step]);
                              glVertex3dv(actualDataG_->vertices[i][j+step]);

                              setColorFromVertexG(i+step, j+step, hl);
                              glNormal3dv(actualDataG_->normals[i+step][j+step]);
                              glVertex3dv(actualDataG_->vertices[i+step][j+step]);
                        }
                  glEnd();
            }
  }

      if (plotStyle() == FILLEDMESH || plotStyle() == WIREFRAME || plotStyle() == HIDDENLINE)
      {
            glColor4d(meshColor().r, meshColor().g, meshColor().b, meshColor().a);        

            if (step < actualDataG_->columns() && step < actualDataG_->rows())
            {
                  glBegin(GL_LINE_LOOP);
                        for (i = 0; i < actualDataG_->columns() - step; i += step) 
                              glVertex3dv(actualDataG_->vertices[i][0]);            
                        for (j = 0; j < actualDataG_->rows() - step; j += step) 
                              glVertex3dv(actualDataG_->vertices[i][j]);                                    
                        for (; i >= 0; i -= step) 
                              glVertex3dv(actualDataG_->vertices[i][j]);                  
                        for (; j >= 0; j -= step) 
                              glVertex3dv(actualDataG_->vertices[0][j]);                  
                  glEnd();
            }

            // weaving
            for (i = step; i < actualDataG_->columns() - step; i += step) 
            {           
                  glBegin(GL_LINE_STRIP);
                        for (j = 0; j < actualDataG_->rows(); j += step) 
                              glVertex3dv(actualDataG_->vertices[i][j]);                  
                  glEnd();
            }
            for (j = step; j < actualDataG_->rows() - step; j += step) 
            {           
                  glBegin(GL_LINE_STRIP);
                        for (i = 0; i < actualDataG_->columns(); i += step) 
                              glVertex3dv(actualDataG_->vertices[i][j]);                  
                  glEnd();
            }
      }
}

void SurfacePlot::setColorFromVertexG(int ix, int iy, bool skip)
{
      if (skip)
            return;

      RGBA col = (*datacolor_p)(
            actualDataG_->vertices[ix][iy][0],
            actualDataG_->vertices[ix][iy][1],
            actualDataG_->vertices[ix][iy][2]);
            
      glColor4d(col.r, col.g, col.b, col.a);
}


void SurfacePlot::createNormalsG()
{
      if (!normals() || actualDataG_->empty())
            return;

  Arrow arrow;
  arrow.setQuality(normalQuality());

      Triple basev, topv, norm;     
      
      int step = resolution();

      double diag = (actualDataG_->hull().maxVertex-actualDataG_->hull().minVertex).length() * normalLength();

  arrow.assign(*this);
  arrow.drawBegin();
      for (int i = 0; i <= actualDataG_->columns() - step; i += step) 
      {
            for (int j = 0; j <= actualDataG_->rows() - step; j += step) 
            {
                  basev = Triple(actualDataG_->vertices[i][j][0],actualDataG_->vertices[i][j][1],actualDataG_->vertices[i][j][2]);
                  topv = Triple(actualDataG_->vertices[i][j][0]+actualDataG_->normals[i][j][0],
                                           actualDataG_->vertices[i][j][1]+actualDataG_->normals[i][j][1],
                                           actualDataG_->vertices[i][j][2]+actualDataG_->normals[i][j][2]); 
                  
                  norm = topv-basev;
                  norm.normalize();
                  norm  *= diag;

      arrow.setTop(basev+norm);
      arrow.setColor((*datacolor_p)(basev.x,basev.y,basev.z));
      arrow.draw(basev);
            }
      }
  arrow.drawEnd();
}

void SurfacePlot::readIn(GridData& gdata, Triple** data, unsigned int columns, unsigned int rows)
{
      gdata.setSize(columns,rows);
      
  ParallelEpiped range(Triple(DBL_MAX,DBL_MAX,DBL_MAX),Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX));

      /* fill out the vertex array for the mesh. */
      for (unsigned i = 0; i != columns; ++i) 
      {
            for (unsigned j = 0; j != rows; ++j) 
            {
                  gdata.vertices[i][j][0] = data[i][j].x; 
                  gdata.vertices[i][j][1] = data[i][j].y;
                  gdata.vertices[i][j][2] = data[i][j].z;

                  if (data[i][j].x > range.maxVertex.x)
                        range.maxVertex.x = data[i][j].x;
                  if (data[i][j].y > range.maxVertex.y)
                        range.maxVertex.y = data[i][j].y;
                  if (data[i][j].z > range.maxVertex.z)
                        range.maxVertex.z = data[i][j].z;
                  if (data[i][j].x < range.minVertex.x)
                        range.minVertex.x = data[i][j].x;
                  if (data[i][j].y < range.minVertex.y)
                        range.minVertex.y = data[i][j].y;
                  if (data[i][j].z < range.minVertex.z)
                        range.minVertex.z = data[i][j].z;
            }
      }
  gdata.setHull(range);
}


void SurfacePlot::readIn(GridData& gdata, double** data, unsigned int columns, unsigned int rows
            , double minx, double maxx, double miny, double maxy)
{
  gdata.setPeriodic(false,false);
      gdata.setSize(columns,rows);
      
      double dx = (maxx - minx) / (gdata.columns() - 1);
      double dy = (maxy - miny) / (gdata.rows() - 1);

      double tmin = DBL_MAX;
      double tmax = -DBL_MAX;

      /* fill out the vertex array for the mesh. */
      for (unsigned i = 0; i != columns; ++i) 
      {
            for (unsigned j = 0; j != rows; ++j) 
            {
                  gdata.vertices[i][j][0] = minx + i*dx;
                  gdata.vertices[i][j][1] = miny + j*dy;
                  gdata.vertices[i][j][2] = data[i][j];

                  if (data[i][j] > tmax)
                        tmax = data[i][j];
                  if (data[i][j] < tmin)
                        tmin = data[i][j];
            }
      }
      ParallelEpiped hull = 
  ParallelEpiped(
                                                            Triple(     
                                                                                    gdata.vertices[0][0][0], 
                                                                                    gdata.vertices[0][0][1], 
                                                                                    tmin
                                                                              ), 
                                                            Triple(
                                                                                    gdata.vertices[gdata.columns()-1][gdata.rows()-1][0], 
                                                                                    gdata.vertices[gdata.columns()-1][gdata.rows()-1][1], 
                                                                                    tmax
                                                                              )
                                                      );

      gdata.setHull(hull);
}


void SurfacePlot::calcNormals(GridData& gdata)
{
      
  unsigned int rows = gdata.rows();
  unsigned int columns = gdata.columns();
  
  // normals
        
      Triple u, v, n;  // for cross product

      for (unsigned i = 0; i != columns; ++i) 
      {
            for (unsigned j = 0; j != rows; ++j) 
            {
                  n = Triple(0,0,0);
      
      
      if (i<columns-1 && j<rows-1) 
      {
        /*  get two vectors to cross */      
        u = Triple(
                                                        gdata.vertices[i+1][j][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i+1][j][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i+1][j][2] - gdata.vertices[i][j][2]
                                                  );

        v = Triple(
                                                        gdata.vertices[i][j+1][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i][j+1][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i][j+1][2] - gdata.vertices[i][j][2]
                                                  );
        /* get the normalized cross product */ 
        n += normalizedcross(u,v); // right hand system here !
      }

      if (i>0 && j<rows-1) 
      {
        u = Triple(
                                                        gdata.vertices[i][j+1][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i][j+1][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i][j+1][2] - gdata.vertices[i][j][2]
                                                  );
                    v = Triple(
                                                        gdata.vertices[i-1][j][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i-1][j][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i-1][j][2] - gdata.vertices[i][j][2]
                                                  );
        n += normalizedcross(u,v); 
      }

      if (i>0 && j>0) 
      {
        u = Triple(
                                                        gdata.vertices[i-1][j][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i-1][j][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i-1][j][2] - gdata.vertices[i][j][2]
                                                  );

        v = Triple(
                                                        gdata.vertices[i][j-1][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i][j-1][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i][j-1][2] - gdata.vertices[i][j][2]
                                                  );
        n += normalizedcross(u,v); 
      }

      if (i<columns-1 && j>0) 
      {
        u = Triple(
                                                        gdata.vertices[i][j-1][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i][j-1][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i][j-1][2] - gdata.vertices[i][j][2]
                                                  );

        v = Triple(
                                                        gdata.vertices[i+1][j][0] - gdata.vertices[i][j][0],
                                                        gdata.vertices[i+1][j][1] - gdata.vertices[i][j][1],
                                                        gdata.vertices[i+1][j][2] - gdata.vertices[i][j][2]
                                                  );
        n += normalizedcross(u,v);
      }
      n.normalize();

                  gdata.normals[i][j][0] = n.x;
                  gdata.normals[i][j][1] = n.y;
                  gdata.normals[i][j][2] = n.z;
            }    
      } 
}


void SurfacePlot::sewPeriodic(GridData& gdata)
{
  // sewing 
   
  Triple n;
  
  unsigned int columns = gdata.columns();
  unsigned int rows = gdata.rows();
  
  if (gdata.uperiodic())
  {
    for (unsigned i = 0; i != columns; ++i) 
    {
      n = Triple(
                                                      gdata.normals[i][0][0] + gdata.normals[i][rows-1][0],
                                                      gdata.normals[i][0][1] + gdata.normals[i][rows-1][1],
                                                      gdata.normals[i][0][2] + gdata.normals[i][rows-1][2]
                                                );

      n.normalize();        
                  gdata.normals[i][0][0] = gdata.normals[i][rows-1][0] = n.x;
                  gdata.normals[i][0][1] = gdata.normals[i][rows-1][1] = n.y;
                  gdata.normals[i][0][2] = gdata.normals[i][rows-1][2] = n.z;
    }
  }
  if (gdata.vperiodic())
  {
    for (unsigned j = 0; j != rows; ++j) 
    {
      n = Triple(
                                                      gdata.normals[0][j][0] + gdata.normals[columns-1][j][0],
                                                      gdata.normals[0][j][1] + gdata.normals[columns-1][j][1],
                                                      gdata.normals[0][j][2] + gdata.normals[columns-1][j][2]
                                                );

      n.normalize();        
                  gdata.normals[0][j][0] = gdata.normals[columns-1][j][0] = n.x;
                  gdata.normals[0][j][1] = gdata.normals[columns-1][j][1] = n.y;
                  gdata.normals[0][j][2] = gdata.normals[columns-1][j][2] = n.z;
    }
  }
}

/*!
      Convert user grid data to internal vertex structure.
      See also NativeReader::read() and Function::create()
*/
00388 bool SurfacePlot::loadFromData(Triple** data, unsigned int columns, unsigned int rows, bool uperiodic, bool vperiodic)
{
  actualDataC_->clear();
  actualData_p = actualDataG_;

  readIn(*actualDataG_, data, columns, rows);
  calcNormals(*actualDataG_);
  actualDataG_->setPeriodic(uperiodic,vperiodic);
      sewPeriodic(*actualDataG_);

      updateData();
      updateNormals();
      createCoordinateSystem();

      return true;
}     

/*! 
      Convert user grid data to internal vertex structure.
      See also NativeReader::read() and Function::create()
*/
00409 bool SurfacePlot::loadFromData(double** data, unsigned int columns, unsigned int rows
                                                                                                                        , double minx, double maxx, double miny, double maxy)
{     
  actualDataC_->clear();
  actualData_p = actualDataG_;
  
  actualDataG_->setPeriodic(false,false);
      actualDataG_->setSize(columns,rows);
      readIn(*actualDataG_,data,columns,rows,minx,maxx,miny,maxy);
  calcNormals(*actualDataG_);  
      
      updateData();
      updateNormals();
      createCoordinateSystem();

      return true;
}     


void SurfacePlot::createFloorDataG()
{
      switch (floorStyle())
      {
      case FLOORDATA:
            Data2FloorG();
            break;
      case FLOORISO:
            Isolines2FloorG();
            break;
      default:
            break;
      }
}

void SurfacePlot::Data2FloorG()
{
      if (actualData_p->empty())
            return;
      
      int step = resolution();

      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
      
      double zshift = actualData_p->hull().minVertex.z;
      for (int i = 0; i < actualDataG_->columns() - step; i += step) 
      {
            glBegin(GL_TRIANGLE_STRIP);
            setColorFromVertexG(i, 0);
                  glVertex3d(actualDataG_->vertices[i][0][0], actualDataG_->vertices[i][0][1], zshift);
                  
                  setColorFromVertexG(i+step, 0);
                  glVertex3d(actualDataG_->vertices[i+step][0][0],actualDataG_->vertices[i+step][0][1], zshift);
                  for (int j = 0; j < actualDataG_->rows() - step; j += step) 
                  {
                        setColorFromVertexG(i, j+step);
                        glVertex3d(actualDataG_->vertices[i][j+step][0],actualDataG_->vertices[i][j+step][1], zshift);
                        
                        setColorFromVertexG(i+step, j+step);
                        glVertex3d(actualDataG_->vertices[i+step][j+step][0],actualDataG_->vertices[i+step][j+step][1], zshift);                      
                  }
            glEnd();
      }
}

void SurfacePlot::Isolines2FloorG()
{
      if (isolines() <= 0 || actualData_p->empty())
            return;

      double count = (actualData_p->hull().maxVertex.z - actualData_p->hull().minVertex.z) / isolines();          

      RGBA col;

  int step = resolution();

      double zshift = actualData_p->hull().minVertex.z;
      
      int cols = actualDataG_->columns();
      int rows = actualDataG_->rows();
      
      Triple t[4];
      vector<Triple> intersection;
      
      double lambda = 0;
      
      GLStateBewarer sb2(GL_LINE_SMOOTH, false);

      for (int k = 0; k != isolines(); ++k) 
      {
            double val = zshift + k * count;          
                        
            for (int i = 0; i < cols-step; i += step) 
            {
                  for (int j = 0; j < rows-step; j += step) 
                  {
                        t[0] =  Triple(   actualDataG_->vertices[i][j][0],
                                                                        actualDataG_->vertices[i][j][1],
                                                                        actualDataG_->vertices[i][j][2]);

                        col = (*datacolor_p)(t[0].x,t[0].y,t[0].z);
                  glColor4d(col.r, col.g, col.b, col.a);
//                glColor4d(0,0,0,1);
                        
                        t[1] =  Triple(   actualDataG_->vertices[i+step][j][0],
                                                                        actualDataG_->vertices[i+step][j][1],
                                                                        actualDataG_->vertices[i+step][j][2]);
                        t[2] =  Triple(   actualDataG_->vertices[i+step][j+step][0],
                                                                        actualDataG_->vertices[i+step][j+step][1],
                                                                        actualDataG_->vertices[i+step][j+step][2]);
                        t[3] =  Triple(   actualDataG_->vertices[i][j+step][0],
                                                                        actualDataG_->vertices[i][j+step][1],
                                                                        actualDataG_->vertices[i][j+step][2]);

                        double diff = 0;
                        for (int m = 0; m!=4; ++m)
                        {
                              int mm = (m+1)%4;
                              if ((val>=t[m].z && val<=t[mm].z) || (val>=t[mm].z && val<=t[m].z))
                              {
                                    diff = t[mm].z - t[m].z;
                                    
                                    if (isPracticallyZero(diff)) // degenerated
                                    {
                                          intersection.push_back(t[m]);
                                          intersection.push_back(t[mm]);
                                          continue;
                                    }
                                    
                                    lambda =  (val - t[m].z) / diff;
                                    intersection.push_back(Triple(t[m].x + lambda * (t[mm].x-t[m].x), t[m].y + lambda * (t[mm].y-t[m].y), val));
                              }
                        }
                        
                        if (!intersection.empty())
                        {
                              if (intersection.size()>2)
                              {
                                    glBegin(GL_LINE_STRIP);
                                    for (unsigned dd = 0; dd!=intersection.size(); ++dd)
                                    {
                                          glVertex3d(intersection[dd].x, intersection[dd].y, zshift);
                                    }
                                    glEnd();
                                    glBegin(GL_POINTS);
                                          glVertex3d(intersection[0].x,intersection[0].y,zshift);
                                    glEnd();
                              }
                              else if (intersection.size() == 2)
                              {
                                    glBegin(GL_LINES);
                                          glVertex3d(intersection[0].x,intersection[0].y,zshift);
                                          glVertex3d(intersection[1].x,intersection[1].y,zshift);
                                          
                                          // small pixel gap problem (see OpenGL spec.)
                                          glVertex3d(intersection[1].x,intersection[1].y,zshift);
                                          glVertex3d(intersection[0].x,intersection[0].y,zshift);
                                    glEnd();
                              }
                              
                              intersection.clear();
                        }
                  }
            }
      }
}



/*
void SurfacePlot::calcLowResolution()
{
  if (!actualDataG_)
    return;

  int res = resolution();
  if (res == 1)
  {
    lowresData_p = *actualDataG_;
    return;
  }
  
  GridData const& src = *actualDataG_;
  result.clear();
  
  
}*/


Generated by  Doxygen 1.6.0   Back to index