Logo Search packages:      
Sourcecode: labplot version File versions

qwt3d_meshplot.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;


/////////////////////////////////////////////////////////////////////////////////
//
//     cell specific
//


void SurfacePlot::createDataC()
{           
      createFloorDataC();
  
  if (plotStyle() == NOPLOT)
    return;

  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);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      int idx = 0;
      if (plotStyle() != WIREFRAME)
      {
            glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);

            bool hl = (plotStyle() == HIDDENLINE);
            if (hl)
            {
                  RGBA col = backgroundRGBAColor();
                  glColor4d(col.r, col.g, col.b, col.a);
            }
            
            for (unsigned i=0; i!=actualDataC_->cells.size(); ++i)
            {
                  glBegin(GL_POLYGON);
                  for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j)
                  {
                        idx = actualDataC_->cells[i][j];
                        setColorFromVertexC(idx, hl);
                        glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, actualDataC_->nodes[idx].z );
                        glNormal3d( actualDataC_->normals[idx].x, actualDataC_->normals[idx].y, actualDataC_->normals[idx].z );
                  }
                  glEnd();
            }
      }

      if (plotStyle() == FILLEDMESH || plotStyle() == WIREFRAME || plotStyle() == HIDDENLINE)
      {
            glColor4d(meshColor().r, meshColor().g, meshColor().b, meshColor().a);
            {
                  for (unsigned i=0; i!=actualDataC_->cells.size(); ++i)
                  {
                        glBegin(GL_LINE_LOOP);
                        for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j)
                        {
                              idx = actualDataC_->cells[i][j];
                              glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, actualDataC_->nodes[idx].z );
                        }
                        glEnd();
                  }
            }
      }
}

// ci = cell index
// cv = vertex index in cell ci
void SurfacePlot::setColorFromVertexC(int node, bool skip)
{
      if (skip)
            return;

      RGBA col = (*datacolor_p)(
            actualDataC_->nodes[node].x, actualDataC_->nodes[node].y, actualDataC_->nodes[node].z);
            
      glColor4d(col.r, col.g, col.b, col.a);
}

void SurfacePlot::createFloorDataC()
{
      switch (floorStyle())
      {
      case FLOORDATA:
            Data2FloorC();
            break;
      case FLOORISO:
            Isolines2FloorC();
            break;
      default:
            break;
      }
}

void SurfacePlot::Data2FloorC()
{     
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      
      double zshift = actualDataC_->hull().minVertex.z;
      int idx;

      for (unsigned i = 0; i!=actualDataC_->cells.size(); ++i)
      {
            glBegin(GL_POLYGON);
            for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j)
            {
                  idx = actualDataC_->cells[i][j];
                  setColorFromVertexC(idx);
                  glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, zshift );
            }
            glEnd();
      }
}

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

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

      RGBA col;

      double zshift = actualData_p->hull().minVertex.z;
            
      TripleField nodes;
      TripleField intersection;
      
      double lambda = 0;
      
      GLStateBewarer sb2(GL_LINE_SMOOTH, false);

      for (int k = 0; k != isolines(); ++k) 
      {
            double val = zshift + k * step;           
                        
            for (unsigned i=0; i!=actualDataC_->cells.size(); ++i)
            {
                  nodes.clear();
                  unsigned cellnodes = actualDataC_->cells[i].size();
                  for (unsigned j=0; j!=cellnodes; ++j)
                  {
                        nodes.push_back(actualDataC_->nodes[actualDataC_->cells[i][j]]);
                  }
                  
                  double diff = 0;
                  for (unsigned m = 0; m!=cellnodes; ++m)
                  {
                        unsigned mm = (m+1)%cellnodes;
                        if ((val>=nodes[m].z && val<=nodes[mm].z) || (val>=nodes[mm].z && val<=nodes[m].z))
                        {
                              diff = nodes[mm].z - nodes[m].z;
                              
                              if (isPracticallyZero(diff)) // degenerated
                              {
                                    intersection.push_back(nodes[m]);
                                    intersection.push_back(nodes[mm]);
                                    continue;
                              }
                              
                              lambda =  (val - nodes[m].z) / diff;
                              intersection.push_back(Triple(nodes[m].x + lambda * (nodes[mm].x-nodes[m].x), nodes[m].y + lambda * (nodes[mm].y-nodes[m].y), val));
                        }
                  }

                  if (!intersection.empty())
                  {
                        col = (*datacolor_p)(nodes[0].x,nodes[0].y,nodes[0].z);
                  glColor4d(col.r, col.g, col.b, col.a);
                        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::createNormalsC()
{
      if (!normals() || actualData_p->empty())
            return;

      if (actualDataC_->nodes.size() != actualDataC_->normals.size())
            return;
  Arrow arrow;
  arrow.setQuality(normalQuality());

      Triple basev, topv, norm;     
            
      double diag = (actualData_p->hull().maxVertex-actualData_p->hull().minVertex).length() * normalLength();

  RGBA col;
  arrow.assign(*this);
  arrow.drawBegin();
      for (unsigned i = 0; i != actualDataC_->normals.size(); ++i) 
      {
            basev = actualDataC_->nodes[i];
            topv = basev + actualDataC_->normals[i];
            
                  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();
}

/*! 
      Convert user (non-rectangular) mesh based data to internal structure.
      See also Qwt3D::TripleField and Qwt3D::CellField
*/
00257 bool SurfacePlot::loadFromData(TripleField const& data, CellField const& poly)
{     
      actualDataG_->clear();
  actualData_p = actualDataC_;
            
      actualDataC_->nodes = data;
      actualDataC_->cells = poly;
      actualDataC_->normals = TripleField(actualDataC_->nodes.size());

      unsigned i;

//  normals for the moment
      Triple n, u, v;
      for ( i = 0; i < poly.size(); ++i) 
      {
            if (poly[i].size() < 3)
                  n = Triple(0,0,0);
            else
            {
                  for (unsigned j = 0; j < poly[i].size(); ++j) 
                  {
                        unsigned jj = (j+1) % poly[i].size(); 
                        unsigned pjj = (j) ? j-1 : poly[i].size()-1;
                        u = actualDataC_->nodes[poly[i][jj]]-actualDataC_->nodes[poly[i][j]];         
                        v = actualDataC_->nodes[poly[i][pjj]]-actualDataC_->nodes[poly[i][j]];
                        n = normalizedcross(u,v);
                        actualDataC_->normals[poly[i][j]] += n;
                  }
            }
      }
      for ( i = 0; i != actualDataC_->normals.size(); ++i) 
      {
            actualDataC_->normals[i].normalize();
      }  
      
      ParallelEpiped hull(Triple(DBL_MAX,DBL_MAX,DBL_MAX),Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX));

      for (i = 0; i!=data.size(); ++i)
      {
            if (data[i].x < hull.minVertex.x)
                  hull.minVertex.x = data[i].x;
            if (data[i].y < hull.minVertex.y)
                  hull.minVertex.y = data[i].y;
            if (data[i].z < hull.minVertex.z)
                  hull.minVertex.z = data[i].z;
            
            if (data[i].x > hull.maxVertex.x)
                  hull.maxVertex.x = data[i].x;
            if (data[i].y > hull.maxVertex.y)
                  hull.maxVertex.y = data[i].y;
            if (data[i].z > hull.maxVertex.z)
                  hull.maxVertex.z = data[i].z;
      }

      actualDataC_->setHull(hull);

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

      return true;
}     



Generated by  Doxygen 1.6.0   Back to index