make the path view independent of type of connection
[mussa.git] / qui / PathScene.cpp
index 7040b6969fd71667e284357122ed4cfffefbc95a..43195f6cd5bb8cb4435b0e4d046560d10f8b16b1 100644 (file)
 
 using namespace std;
 
-PathScene::PathScene(Mussa* analysis, QWidget *parent) : 
-  QGLWidget(parent),
-  viewport_height(0),
-  viewport_width(0),
-  clipZ(30.0),
-  zoom(2),
-  maxOrtho2d(-50.0, -50, 3000000.0, 300.0),
-  curOrtho2d(maxOrtho2d),
-  viewport_center(((curOrtho2d.right()-curOrtho2d.left())/2)+curOrtho2d.left()),
-  selectedMode(false),
-  rubberBand(0),
-  drawingBand(false)
+PathScene::PathScene(QWidget *parent)
+  : QGLWidget(parent)
+    //selectedMode(false),
+    //rubberBand(0),
+    //drawingBand(false)
 { 
-  if (analysis == 0)
-  {
-    mussaAnalysis = new Mussa;
-  }
-  else
-  {
-    mussaAnalysis = analysis;
-  }
-  updateScene();
 }
 
 QSize PathScene::sizeHint() const
 {
-  return QSize(400, 400);
-}
-
-float PathScene::left()
-{
-  return maxOrtho2d.left();
-}
-
-float PathScene::right()
-{
-  return maxOrtho2d.right();
-}
-
-float PathScene::viewportLeft()
-{
-  return curOrtho2d.left();
-}
-
-float PathScene::viewportRight()
-{
-  return curOrtho2d.right();
+  return QSize(GlTracks::viewportHeight(), GlTracks::viewportWidth());
 }
 
-float PathScene::viewportCenter()
+void PathScene::setViewportCenter(float x)
 {
-  return viewport_center;
-}
+  const float epsilon = 1e-10;
+  float center = fabs(GlTracks::viewportCenter());
+  float abs_x = fabsf(x);
+  float difference = fabsf(abs_x - center);
 
-void PathScene::updateViewport(float center, int new_zoom)
-{
-  float max_width = maxOrtho2d.width();
-  if (new_zoom < 1) new_zoom = 1;
-  float new_max_width = max_width / new_zoom;
-  //curOrtho2d.setLeft(max(center-new_max_width, maxOrtho2d.left()));
-  //curOrtho2d.setRight(min(center+new_max_width, maxOrtho2d.right()));
-  curOrtho2d.setLeft(center-new_max_width);
-  curOrtho2d.setRight(center+new_max_width);
-  emit viewportChanged();
-}
-
-void PathScene::setViewportX(float x)
-{
   //hopefully this calculates a sufficiently reasonable == for a float
-  if (x != viewport_center )
+  if (difference < epsilon * abs_x or difference < epsilon * center)
   {
-    updateViewport(x, zoom);
-    viewport_center = x;
+    GlTracks::setViewportCenter(x);
     update();
   }
 }
 
 void PathScene::setZoom(int new_zoom)
 {
-  if (zoom != new_zoom) {
-    // try to figure out where we should be now?
-    updateViewport(viewport_center, new_zoom);
-    zoom = new_zoom;
+  if (new_zoom != GlTracks::zoom()) {
+    GlTracks::setZoom(new_zoom);
     update();
   }
 }
 
-void PathScene::setClipPlane(int newZ)
+void PathScene::setClipPlane(int )
 {
+/*
   if (clipZ != (double) newZ){
     clipZ = (double) newZ;
     update();
   }
-}
-
-void PathScene::loadMotifList()
-{
-  QString caption("Load a motif list");
-  QString filter("Motif list(*.txt *.mtl)");
-  QString path = QFileDialog::getOpenFileName(this,
-                                                   caption, 
-                                                   QDir::currentPath(),
-                                                   filter);
-  // user hit cancel?
-  if (path.isNull()) 
-    return;
-  // try to load safely
-  try {
-    mussaAnalysis->load_motifs(path.toStdString());
-    updateScene();
-  } catch (runtime_error e) {
-    QString msg("Unable to load ");
-    msg += path;
-    msg += "\n";
-    msg += e.what();
-    QMessageBox::warning(this, "Load Motifs", msg);
-  }
-  assert (mussaAnalysis != 0);
-}
-void PathScene::loadMupa()
-{
-  QString caption("Load a mussa parameter file");
-  QString filter("Mussa Parameters (*.mupa)");
-  QString mupa_path = QFileDialog::getOpenFileName(this,
-                                                   caption, 
-                                                   QDir::currentPath(),
-                                                   filter);
-  // user hit cancel?
-  if (mupa_path.isNull()) 
-    return;
-  // try to load safely
-  try {
-    Mussa *m = new Mussa;
-    m->load_mupa_file(mupa_path.toStdString());
-    m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
-    // only switch mussas if we loaded without error
-    delete mussaAnalysis;
-    mussaAnalysis = m;
-    updateScene();
-  } catch (mussa_load_error e) {
-    QString msg("Unable to load ");
-    msg += mupa_path;
-    msg += "\n";
-    msg += e.what();
-    QMessageBox::warning(this, "Load Parameter", msg);
-  }
-  assert (mussaAnalysis != 0);
-}
-
-void PathScene::loadSavedAnalysis()
-{
-  QString caption("Load a previously run analysis");
-  QString muway_dir = QFileDialog::getExistingDirectory(this,
-                                                        caption, 
-                                                        QDir::currentPath());
-  // user hit cancel?
-  if (muway_dir.isNull()) 
-    return;
-  // try to safely load
-  try {
-    Mussa *m = new Mussa;
-    m->load(muway_dir.toStdString());
-    // only switch mussas if we loaded without error
-    delete mussaAnalysis;
-    mussaAnalysis = m;
-    updateScene();
-  } catch (mussa_load_error e) {
-    QString msg("Unable to load ");
-    msg += muway_dir;
-    msg += "\n";
-    msg += e.what();
-    QMessageBox::warning(this, "Load Parameter", msg);
-  }
-  assert (mussaAnalysis != 0);
-}
-
-void PathScene::setSoftThreshold(int threshold)
-{
-  if (mussaAnalysis->get_threshold() != threshold) {
-    mussaAnalysis->set_soft_thres(threshold);
-    mussaAnalysis->nway();
-    update();
-  }
+*/
 }
 
 ////////////////////
 // Rendering code
 void PathScene::initializeGL()
 {
-  glEnable(GL_DEPTH_TEST);
-  glClearColor(1.0, 1.0, 1.0, 0.0);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  glShadeModel(GL_FLAT);
+  GlTracks::initializeGL();
 }
 
 void PathScene::resizeGL(int width, int height)
 {
-  viewport_width = width;
-  viewport_height = height;
-  assert (geometry().width() == width);
-  assert (geometry().height() == height);
-  glViewport(0, 0, (GLsizei)width, (GLsizei)height);
-  glMatrixMode(GL_PROJECTION);
-  glLoadIdentity();
-  // I'm abusing this as Qt and OpenGL disagree about the direction of the
-  // y axis
-  glOrtho(curOrtho2d.left(), curOrtho2d.right(), 
-          curOrtho2d.top(), curOrtho2d.bottom(), 
-          -50.0, clipZ);
+  GlTracks::resizeGL(width, height);
 }
 
 void PathScene::paintGL()
 {
-  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-
-  glPushMatrix();
-  glMatrixMode(GL_PROJECTION);
-  glLoadIdentity();
-  glOrtho(curOrtho2d.left(), curOrtho2d.right(), 
-          curOrtho2d.top(), curOrtho2d.bottom(), 
-          -50.0, clipZ);
-  glMatrixMode(GL_MODELVIEW);
-  mussaesque();
-  glEnable(GL_BLEND);
-  glDepthMask(GL_FALSE);
-  if (selectedMode && !drawingBand) {
-    glColor4f(0.6, 0.6, 0.6, 0.9);
-    glRectf(previousBand.x(), previousBand.y(),
-            previousBand.right(), previousBand.bottom());
-  }
-  glDepthMask(GL_TRUE);
-  glDisable(GL_BLEND);
-  glPopMatrix();
-  glFlush();
-}
-
-void PathScene::updateScene()
-{
-  // Delete old glsequences
-  // FIXME: does this actually free the memory from the new'ed GlSequences?
-  tracks.clear();
-
-  // save a reference to our GlSequences
-  GlSequence *gl_seq;
-  float y = mussaAnalysis->sequences().size() * 100 ;
-  float max_base_pairs = 0;
-  typedef vector<Sequence>::const_iterator seqs_itor_t;
-  for(seqs_itor_t seq_itor = mussaAnalysis->sequences().begin();
-      seq_itor != mussaAnalysis->sequences().end();
-      ++seq_itor)
-  {
-    y = y - 100;
-    gl_seq = new GlSequence(*seq_itor, mussaAnalysis->colorMapper());
-    gl_seq->setX(0);
-    gl_seq->setY(y);
-    if (gl_seq->length() > max_base_pairs ) max_base_pairs = gl_seq->length();
-    tracks.push_back( *gl_seq );
-  }
-  maxOrtho2d.setWidth(max_base_pairs + 100.0);
-  maxOrtho2d.setHeight((mussaAnalysis->sequences().size()) * 100 );
-  curOrtho2d = maxOrtho2d;
-  viewport_center = (curOrtho2d.right()-curOrtho2d.left())/2+curOrtho2d.left();
+  GlTracks::paintGL();
 }
 
+/*
 void PathScene::processSelection(GLuint hits, GLuint buffer[], GLuint bufsize)
 {
   const size_t pathz_count = mussaAnalysis->paths().refined_pathz.size();
@@ -408,122 +208,4 @@ void PathScene::mouseReleaseEvent( QMouseEvent *e)
 
   resizeGL(geometry().width(), geometry().height());
 }
-
-
-//////
-// openGl rendering code
-
-void PathScene::draw_tracks() const
-{
-  glPushMatrix();
-  glPushName(0);
-  for (vector<GlSequence>::size_type i = 0; i != tracks.size(); ++i )
-  {
-    glLoadName(i);
-    tracks[i].draw(curOrtho2d.left(), curOrtho2d.right());
-  }
-  glPopName();
-  glPopMatrix();
-}
-
-void PathScene::draw_lines() const
-{
-  GLfloat x;
-  GLfloat y;
-  GLuint pathid=0;
-  GLint objid=0;
-  bool reversed = false;
-  bool prevReversed = false;
-  const NwayPaths& nway = mussaAnalysis->paths();
-
-  glPushName(pathid);
-  glLineWidth(2);
-  vector<GlSequence>::const_iterator track_itor;
-  
-  typedef list<ExtendedConservedPath> conserved_paths;
-  typedef conserved_paths::const_iterator const_conserved_paths_itor;
-  for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
-      path_itor != nway.refined_pathz.end();
-      ++path_itor, ++objid)
-  {
-    track_itor = tracks.begin();
-    // since we were drawing to the start of a window, and opengl lines
-    // are centered around the two connecting points our lines were slightly
-    // offset. the idea of window_offset is to adjust them to the
-    // right for forward compliment or left for reverse compliment
-    // FIXME: figure out how to unit test these computations
-    GLfloat window_offset = (path_itor->window_size)/2.0;
-    
-    glBegin(GL_LINE_STRIP);
-    for (vector<int>::const_iterator sp_itor = path_itor->begin();
-         sp_itor != path_itor->end();
-         ++sp_itor, ++track_itor)
-    {
-      x = *sp_itor;
-      y = track_itor->y();
-      // at some point when we modify the pathz data structure to keep
-      // track of the score we can put grab the depth here.
-      //
-      // are we reverse complimented? 
-      if ( x>=0) {
-        reversed = false;
-      } else {
-        reversed = true;
-        x = -x; // make positive
-      }
-      if (!reversed)
-        x += window_offset; // move right for forward compliment
-      else
-        x -= window_offset; // move left for reverse compliment
-      // the following boolean implements logical xor
-      if ( (reversed || prevReversed) && (!reversed || !prevReversed)) { 
-        // we have a different orientation
-        if (not selectedMode or selectedPaths[objid] == true) {
-          // if we have nothing selected, or we're the highlight, be bright
-          glColor3f(0.0, 0.0, 1.0);
-        } else {
-          // else be dim
-          glColor3f(0.7, 0.7, 1.0);
-        }
-      } else {
-        // both current and previous path have the same orientation
-        if (not selectedMode or selectedPaths[objid] == true) {
-          glColor3f(1.0, 0.0, 0.0);
-        } else {
-          glColor3f(1.0, 0.7, 0.7);
-        }
-      }
-      prevReversed = reversed;
-      glVertex3f(x, y, -1.0);
-    }
-    glEnd();
-    glLoadName(++pathid);
-  }
-  glPopName();
-}
-
-GLuint PathScene::make_line_list()
-{
-  GLuint line_list = glGenLists(1);
-  glNewList(line_list, GL_COMPILE);
-
-  draw_lines();
-
-  glEndList();
-  return line_list;
-
-}
-
-void PathScene::mussaesque()
-{
-  //static GLuint theLines = make_line_list();
-
-  glInitNames();
-  glPushName(MussaPaths);
-  //glCallList(theLines);
-  draw_lines();
-  glLoadName(MussaTracks);
-  draw_tracks();
-  glPopName();
-}
-
+*/