NCBI C++ ToolKit
cross_panel_ir.cpp
Go to the documentation of this file.
00001 /*  $Id: cross_panel_ir.cpp 24562 2011-10-17 19:29:20Z wuliangs $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors:  Vlad Lebedev
00027  *
00028  */
00029 
00030 
00031 #include <ncbi_pch.hpp>
00032 #include <gui/widgets/aln_crossaln/cross_panel_ir.hpp>
00033 #include <objmgr/seq_vector.hpp>
00034 #include <gui/objutils/utils.hpp>
00035 #include <gui/opengl/glcolortable.hpp>
00036 #include <gui/utils/intersect.hpp>
00037 #include <corelib/ncbitime.hpp>
00038 
00039 BEGIN_NCBI_SCOPE
00040 USING_SCOPE(objects);
00041 USING_SCOPE(math);
00042 
00043 static const TModelUnit   kSeqMapBarHeight = 3.0f;
00044 static const int sc_StepK[] = { 2, 5, 10 };
00045 static const TModelUnit kClipMultiple = 5.0;
00046 
00047 
00048 CCrossPanelIR::CCrossPanelIR()
00049     : m_Font_Fixed12(CGlBitmapFont::eFixed12)
00050 {
00051 }
00052 
00053 
00054 CCrossPanelIR::~CCrossPanelIR()
00055 {
00056 }
00057 
00058 
00059 
00060 void CCrossPanelIR::SetLimits(TVPRect rcm1, TModelRect rcv1, TVPRect rcm2, TModelRect rcv2)
00061 {
00062     m_RCM1 = rcm1;
00063     m_RCV1 = rcv1;
00064     m_RCM2 = rcm2;
00065     m_RCV2 = rcv2;
00066 }
00067 
00068 
00069 
00070 void CCrossPanelIR::ColorBySegments()
00071 {
00072     m_ColorScoreId.Reset();
00073 }
00074 
00075 
00076 void CCrossPanelIR::ColorByScore(CConstRef<CObject_id> score_id)
00077 {
00078     /*m_ColorScoreId = score_id;
00079 
00080     if(m_DS) {
00081         m_Graph.AssignColorsByScore(score_id);
00082     }*/
00083 }
00084 
00085 
00086 void CCrossPanelIR::SetDataSource(ICrossAlnDataSource* ds)
00087 {
00088     m_DS = ds;
00089 
00090     m_Graph.DeleteGlyphs();
00091 
00092     if(m_DS)    {
00093         const CHitMatrixDataSource::THitAdapterCont& hits = ds->GetHits();
00094         ITERATE (CHitMatrixDataSource::THitAdapterCont, it, hits) {
00095             //const CDenseSegHit* hit = *it;
00096             //cout << "Q Start " << hit.GetQueryStart() << ", Subj Start " << hit.GetSubjectStart() << endl;
00097             m_Graph.CreateGlyph(**it);
00098         }
00099     }
00100     m_ColorScoreId.Reset();
00101 }
00102 
00103 
00104 void CCrossPanelIR::Render(CGlPane& pane)
00105 {
00106     pane.OpenOrtho();
00107 
00108     glDisable(GL_CULL_FACE);
00109     glDisable(GL_DEPTH_TEST);
00110     glDisable(GL_LIGHTING);
00111     glEnable(GL_BLEND);
00112     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00113     glEnable(GL_LINE_SMOOTH);
00114     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00115 
00116     glEnable(GL_POLYGON_SMOOTH);
00117     glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
00118 
00119     glLineWidth(1.5f);
00120 
00121     x_DrawCrossAlignment(pane);  // Draw our quads
00122 
00123     x_DrawSequence(pane);  // Draw some sequence letters
00124 
00125     glDisable(GL_BLEND);
00126     glDisable(GL_LINE_SMOOTH);
00127     glDisable(GL_POLYGON_SMOOTH);
00128     glLineWidth(1.0f);
00129 
00130     pane.Close();
00131 }
00132 
00133 
00134 TModelRect CCrossPanelIR::HitTest(CGlPane& pane, int x, int y, bool select)
00135 {
00136     const TModelRect& rcV = pane.GetVisibleRect();
00137 
00138     CRange<TModelUnit> rcv1(m_RCV1.Left(), m_RCV1.Right());
00139     CRange<TModelUnit> rcv2(m_RCV2.Left(), m_RCV2.Right());
00140 
00141     CRange<TModelUnit> rcv1_clip(rcv1.GetFrom() - rcv1.GetLength() * kClipMultiple,
00142                                     rcv1.GetTo() + rcv1.GetLength() * kClipMultiple);
00143     CRange<TModelUnit> rcv2_clip(rcv2.GetFrom() - rcv2.GetLength() * kClipMultiple,
00144                                     rcv2.GetTo() + rcv2.GetLength() * kClipMultiple);
00145 
00146     ITERATE(THitGlyphVector, it, m_Graph.GetGlyphs()) { // for each Hit
00147         const CHitGlyph::TElemGlyphCont& elems = (*it)->GetElems();
00148         const IHitElement& first_elem = elems.front().GetHitElem();
00149         const IHitElement& last_elem  = elems.back().GetHitElem();
00150 
00151         TSignedSeqPos from1 = first_elem.GetQueryStart();
00152         TSignedSeqPos from2 = first_elem.GetSubjectStart();
00153         TSignedSeqPos to1   = last_elem.GetQueryStart() + last_elem.GetQueryLength();
00154         TSignedSeqPos to2   = last_elem.GetSubjectStart() + last_elem.GetSubjectLength();
00155 
00156         if ( (to1 < m_RCV1.Left()     &&  to2 < m_RCV2.Left())  ||
00157              (from1 > m_RCV1.Right()  &&  from1 > m_RCV2.Right()) ) {
00158             continue;
00159         }
00160         if ( (to1 < rcv1_clip.GetFrom()  &&  from2 > rcv2_clip.GetTo())  ||
00161              (from1 > rcv1_clip.GetTo()  &&  to2 < rcv2_clip.GetFrom()) ) {
00162             continue;
00163         }
00164 
00165 
00166         /// some part of the range intersects the visible area
00167         /// now we start back with the first element
00168         ITERATE (CHitGlyph::TElemGlyphCont, itE, elems) {
00169             const IHitElement& elem = itE->GetHitElem();
00170 
00171             from1 = elem.GetQueryStart();
00172             from2 = elem.GetSubjectStart();
00173             if (from1 == -1  ||  from2 == -1) {
00174                 continue;
00175             }
00176 
00177             to1   = from1 + elem.GetQueryLength();
00178             to2   = from2 + elem.GetSubjectLength();
00179 
00180             /// perform our clipping again
00181             if ( (to1 < m_RCV1.Left()     &&  to2 < m_RCV2.Left())  ||
00182                  (from1 > m_RCV1.Right()  &&  from1 > m_RCV2.Right()) ) {
00183                 continue;
00184             }
00185             if ( (to1 < rcv1_clip.GetFrom()  &&  from2 > rcv2_clip.GetTo())  ||
00186                  (from1 > rcv1_clip.GetTo()  &&  to2 < rcv2_clip.GetFrom()) ) {
00187                 continue;
00188             }
00189 
00190             TModelUnit x_from1 = x_Seq2Lim1(from1);
00191             TModelUnit x_to1   = x_Seq2Lim1(to1);
00192             TModelUnit x_from2 = x_Seq2Lim2(from2);
00193             TModelUnit x_to2   = x_Seq2Lim2(to2);
00194 
00195             TModelUnit x_x     = pane.UnProjectX(x);
00196             TModelUnit x_y     = pane.UnProjectY(y);
00197 
00198             CVect3<TModelUnit> orig(x_x, x_y, 1.0);
00199             CVect3<TModelUnit> dir(0.0, 0.0, -2.0);
00200             CVect3<TModelUnit> vert0(x_from1, rcV.Top(), 0.0);
00201             CVect3<TModelUnit> vert1(x_to1, rcV.Top(), 0.0);
00202             CVect3<TModelUnit> vert2(x_to2, rcV.Bottom(), 0.0);
00203             CVect3<TModelUnit> vert3(x_from2, rcV.Bottom(), 0.0);
00204             CVect3<TModelUnit> pt;
00205 
00206             if (IntersectRayQuad(orig,dir,vert0, vert1, vert2, vert3, pt) == eIntersects) {
00207                 if (select) { // select the Glyph
00208                     //m_Graph.SelectGlyph(**it);
00209                     CHitElemGlyph& heg = const_cast<CHitElemGlyph&>(*itE);
00210                     heg.SetSelected(true);
00211                 }
00212                 return TModelRect(from1, from2, to1, to2);
00213             }
00214         }
00215     }
00216 
00217     return TModelRect(0, 0, 0, 0); // empty
00218 }
00219 
00220 
00221 
00222 void CCrossPanelIR::ResetObjectSelection()
00223 {
00224     m_Graph.ResetGlyphSelection();
00225     ITERATE(THitGlyphVector, it, m_Graph.GetGlyphs()) // for each Hit
00226     {
00227         const CHitGlyph::TElemGlyphCont& elems = (*it)->GetElems();
00228         ITERATE(CHitGlyph::TElemGlyphCont, itE, elems) { // for each Hit Element
00229             const CHitElemGlyph& gl_elem = *itE;
00230             if (gl_elem.IsSelected()) {
00231                 CHitElemGlyph& the_elem = *const_cast<CHitElemGlyph*>(&gl_elem);
00232                 the_elem.SetSelected(false);
00233             }
00234         }
00235     }
00236 }
00237 
00238 
00239 void CCrossPanelIR::GetObjectSelection(TConstObjects& objs) const
00240 {
00241     set<const CSeq_align*> aligns; // selected aligns
00242 
00243     const TElemGlyphSet& glyphs = m_Graph.GetSelectedGlyphs();
00244 
00245     // build a set of CSeq_aligns corresponding to selected glyphs
00246     ITERATE(TElemGlyphSet, it_G, glyphs)   {
00247         const IHitElement& elem = (*it_G)->GetHitElem();
00248         const IHit& hit = elem.GetHit();
00249         aligns.insert(hit.GetSeqAlign());
00250     }
00251 
00252     objs.reserve(aligns.size());
00253     ITERATE(set<const CSeq_align*>, it_align, aligns) {
00254         objs.push_back(CConstRef<CObject>(*it_align));
00255     }
00256 }
00257 
00258 void CCrossPanelIR::SetObjectSelection(const vector<const CSeq_align*> sel_aligns)
00259 {
00260     m_Graph.ResetGlyphSelection();
00261 
00262     typedef CHitMatrixGraph::THitGlyphVector TGlyphs;
00263     const TGlyphs& glyphs = m_Graph.GetGlyphs();
00264     ITERATE(TGlyphs, it_G, glyphs)  {
00265         const CHitGlyph& glyph = **it_G;
00266         const CSeq_align* align = glyph.GetHit().GetSeqAlign();
00267 
00268         if(std::find(sel_aligns.begin(), sel_aligns.end(), align)
00269                      != sel_aligns.end())   {
00270             m_Graph.SelectGlyph(glyph);
00271         }
00272     }
00273 }
00274 
00275 
00276 void CCrossPanelIR::x_DrawSequence(CGlPane& pane)
00277 {
00278     const TVPRect& rcP = pane.GetViewport();
00279 
00280     bool seq_fit1 = x_IsSeqLettersFit1();
00281     bool seq_fit2 = x_IsSeqLettersFit2();
00282 
00283     TVPUnit font_h = TVPUnit( m_Font_Fixed12.TextHeight() );
00284     TModelUnit y1 = pane.UnProjectY(rcP.Top() - font_h - 1);
00285     TModelUnit y2 = pane.UnProjectY(rcP.Bottom() + 3);
00286 
00287     char bases[2];
00288     bases[1] = '\0';
00289     string seq1, seq2;
00290 
00291     glColor3f(0.0f, 0.0f, 0.0f);
00292 
00293     if (seq_fit1  &&  m_DS->GetQueryHandle()) {  // sequence 1 fit
00294         TSeqPos l1 = TSeqPos( m_RCV1.Left () );
00295         TSeqPos r1 = TSeqPos( m_RCV1.Right() );
00296 
00297         x_GetSequence(m_DS->GetQueryHandle(), l1, r1, seq1);
00298 
00299         for (TSeqPos bp = 0;  bp != seq1.length();  bp++) {
00300             bases[0] = seq1[bp];
00301             TModelUnit x1 = (float) x_Seq2Lim1(l1 + bp + 0.25);
00302             m_Font_Fixed12.TextOut(x1, y1, bases);
00303         }
00304     }
00305 
00306     if (seq_fit2  &&  m_DS->GetSubjectHandle()) {  // sequence 2 fit
00307         TSeqPos l2 = TSeqPos( m_RCV2.Left () );
00308         TSeqPos r2 = TSeqPos( m_RCV2.Right() );
00309 
00310         x_GetSequence(m_DS->GetSubjectHandle(), l2, r2, seq2);
00311 
00312         for (TSeqPos bp = 0;  bp != seq2.length();  bp++) {
00313             bases[0] = seq2[bp];
00314             TModelUnit x2 = x_Seq2Lim2(l2 + bp + 0.25);
00315             m_Font_Fixed12.TextOut(x2, y2, bases);
00316         }
00317     }
00318 
00319     // 4) Highlight mismatches (and draw connection lines)
00320     if (seq_fit1  &&  seq_fit2  &&
00321         m_DS->GetQueryHandle()  &&  m_DS->GetSubjectHandle()) { // not yet
00322         TVPUnit value = TVPUnit(m_Font_Fixed12.TextHeight());
00323         TModelUnit font_height = pane.UnProjectHeight(value);
00324 
00325         CRange<TModelUnit> rcv1(m_RCV1.Left(), m_RCV1.Right());
00326         CRange<TModelUnit> rcv2(m_RCV2.Left(), m_RCV2.Right());
00327 
00328         CRange<TModelUnit> rcv1_clip(rcv1.GetFrom() - rcv1.GetLength() * kClipMultiple,
00329                                      rcv1.GetTo() + rcv1.GetLength() * kClipMultiple);
00330         CRange<TModelUnit> rcv2_clip(rcv2.GetFrom() - rcv2.GetLength() * kClipMultiple,
00331                                      rcv2.GetTo() + rcv2.GetLength() * kClipMultiple);
00332 
00333         ITERATE(THitGlyphVector, it, m_Graph.GetGlyphs()) { // for each Hit
00334             const CHitGlyph::TElemGlyphCont& elems = (*it)->GetElems();
00335             const IHitElement& first_elem = elems.front().GetHitElem();
00336             const IHitElement& last_elem  = elems.back().GetHitElem();
00337 
00338             TSignedSeqPos from1 = first_elem.GetQueryStart();
00339             TSignedSeqPos from2 = first_elem.GetSubjectStart();
00340             TSignedSeqPos to1   = last_elem.GetQueryStart() + last_elem.GetQueryLength();
00341             TSignedSeqPos to2   = last_elem.GetSubjectStart() + last_elem.GetSubjectLength();
00342 
00343             /// first test: clip for things entirely off screen
00344             if ( (to1 < m_RCV1.Left()     &&  to2 < m_RCV2.Left())  ||
00345                  (from1 > m_RCV1.Right()  &&  from1 > m_RCV2.Right()) ) {
00346                 continue;
00347             }
00348 
00349             /// second test: clip items that cross too obliquely
00350             if ( (to1 < rcv1_clip.GetFrom()  &&  from2 > rcv2_clip.GetTo())  ||
00351                  (from1 > rcv1_clip.GetTo()  &&  to2 < rcv2_clip.GetFrom()) ) {
00352                 continue;
00353             }
00354 
00355 
00356             /// some part of the range intersects the visible area
00357             /// now we start back with the first element
00358             ITERATE (CHitGlyph::TElemGlyphCont, itE, elems) {
00359                 const IHitElement& elem = itE->GetHitElem();
00360 
00361                 from1 = elem.GetQueryStart();
00362                 from2 = elem.GetSubjectStart();
00363 
00364                 if (from1 == -1  ||  from2 == -1) {
00365                     continue;
00366                 }
00367 
00368                 to1   = from1 + elem.GetQueryLength();
00369                 to2   = from2 + elem.GetSubjectLength();
00370 
00371                 /// perform our clipping again
00372                 if ( (to1 < m_RCV1.Left()     &&  to2 < m_RCV2.Left())  ||
00373                      (from1 > m_RCV1.Right()  &&  from1 > m_RCV2.Right()) ) {
00374                     continue;
00375                 }
00376                 if ( (to1 < rcv1_clip.GetFrom()  &&  from2 > rcv2_clip.GetTo())  ||
00377                      (from1 > rcv1_clip.GetTo()  &&  to2 < rcv2_clip.GetFrom()) ) {
00378                     continue;
00379                 }
00380 
00381                 seq1.erase();
00382                 seq2.erase();
00383                 x_GetSequence(m_DS->GetQueryHandle(),   from1, to1, seq1);
00384                 x_GetSequence(m_DS->GetSubjectHandle(), from2, to2, seq2);
00385 
00386                 TSeqPos bp = 0;
00387                 //TODO - Length on query and Subject can be different
00388                 for (TSeqPos pos = 0;  pos != elem.GetQueryLength();  pos++) {
00389                     //TModelUnit x1 = x_Seq2Lim1(from1 + pos + 0.25);
00390                     //TModelUnit x2 = x_Seq2Lim2(from2 + pos + 0.25);
00391 
00392                     // Draw lines to connect mismatches
00393                     glColor3f(0.0f, 0.0f, 0.0f);  // black
00394                     if (seq1[bp] != seq2[bp]  ||  (from1 + pos) % 10 == 0) {
00395                         TModelUnit lx1 = from1 + pos + 0.5; // centered
00396                         TModelUnit lx2 = from2 + pos + 0.5;
00397                         float alpha = 0.5f;
00398                         if (lx1 < m_RCV1.Left()  ||  lx1 > m_RCV1.Right() ||
00399                             lx2 < m_RCV2.Left()  ||  lx2 > m_RCV2.Right() )
00400                         {
00401                             alpha = 0.08f;
00402                         }
00403                         if (seq1[bp] != seq2[bp]) {
00404                             glColor4f(1.0f, 0.0f, 0.0f, alpha);
00405                         } else {
00406                             glColor4f(0.7f, 0.7f, 0.7f, alpha);
00407                         }
00408                         glBegin(GL_LINES);
00409                             glVertex2d(x_Seq2Lim1(lx1), y1);
00410                             glVertex2d(x_Seq2Lim2(lx2), y2 + font_height);
00411                         glEnd();
00412                     }
00413                     bp++;
00414                 } // for: pos
00415             }
00416         }
00417     }
00418 }
00419 
00420 
00421 void CCrossPanelIR::x_GetSequence(const CBioseq_Handle& handle,
00422             TSeqPos from, TSeqPos to, string& buffer) const
00423 {
00424     buffer.erase();
00425     CSeqVector s_vec =
00426         handle.GetSeqVector(CBioseq_Handle::eCoding_Iupac);
00427 
00428     s_vec.GetSeqData(from, to, buffer);
00429 }
00430 
00431 
00432 void CCrossPanelIR::x_DrawCrossedPanel(CGlPane& pane, const CRgbaColor& color,
00433                                        TModelUnit x_from1, TModelUnit x_to1,
00434                                        TModelUnit x_from2, TModelUnit x_to2)
00435 {
00436     const TModelRect& rcV = pane.GetVisibleRect();
00437     TModelUnit x_offs = pane.GetOffsetX();
00438     float alpha = 0.1f;
00439 
00440     glColor4f(color.GetRed(), color.GetGreen(), color.GetBlue(), alpha);
00441 
00442     /// gap is not too small
00443     /// render the previous element, save the current
00444     if (fabs(x_from1 - x_to1) < pane.GetScaleX()  &&
00445         fabs(x_from2 - x_to2) < pane.GetScaleX()) {
00446 
00447         glBegin(GL_LINES);
00448             glVertex2d(x_from1 - x_offs, rcV.Top());
00449             glVertex2d(x_from2 - x_offs, rcV.Bottom());
00450         glEnd();
00451     } else {
00452         glBegin(GL_TRIANGLE_STRIP);
00453             glVertex2d(x_from1 - x_offs, rcV.Top());
00454             glVertex2d(x_to1 - x_offs,   rcV.Top());
00455             glVertex2d(x_from2 - x_offs, rcV.Bottom());
00456             glVertex2d(x_to2 - x_offs,   rcV.Bottom());
00457         glEnd();
00458     }
00459 }
00460 
00461 
00462 void CCrossPanelIR::x_DrawCrossAlignment(CGlPane& pane)
00463 {
00464     glFlush();
00465     CStopWatch sw;
00466     sw.Start();
00467     //const TModelRect& rcV = pane.GetVisibleRect();
00468     CRgbaColorTable table(1, 0.5f, 0.75f);
00469 
00470     //TModelUnit rcv1_inv = 1.0f / m_RCV1.Width();
00471     //TModelUnit rcv2_inv = 1.0f / m_RCV2.Width();
00472 
00473     size_t clip_bounds = 0;
00474     size_t clip_cross  = 0;
00475     size_t elements_rendered = 0;
00476 
00477     ///
00478     /// this code makes use of CRange<> as a temporary storage for standardization
00479     ///
00480 
00481     /// we compute two ranges: the visible range and a related clip range
00482 
00483     /// first sequence ranges
00484     CRange<TModelUnit> rcv1(m_RCV1.Left(), m_RCV1.Right());
00485     CRange<TModelUnit> rcv1_clip
00486         (rcv1.GetFrom() - rcv1.GetLength() * kClipMultiple,
00487          rcv1.GetTo()   + rcv1.GetLength() * kClipMultiple);
00488 
00489     /// second sequence ranges
00490     CRange<TModelUnit> rcv2(m_RCV2.Left(), m_RCV2.Right());
00491     CRange<TModelUnit> rcv2_clip
00492         (rcv2.GetFrom() - rcv2.GetLength() * kClipMultiple,
00493          rcv2.GetTo()   + rcv2.GetLength() * kClipMultiple);
00494 
00495     CRgbaColor sel_color(0.0f, 0.0f, 1.0f);
00496     CRgbaColor plus_color(1.0f, 0.0f, 0.0f);
00497     CRgbaColor minus_color(1.0f, 0.8f, 0.0f);
00498 
00499     ITERATE(THitGlyphVector, it, m_Graph.GetGlyphs()) { // for each Hit
00500         const CHitGlyph::TElemGlyphCont& elems = (*it)->GetElems();
00501 
00502         const IHitElement& first_elem = elems.front().GetHitElem();
00503         const IHitElement& last_elem  = elems.back().GetHitElem();
00504         bool is_mixed =
00505             (first_elem.GetQueryStrand() != first_elem.GetSubjectStrand());
00506 
00507         /// we consider the entire range at first
00508         CRange<TModelUnit> range1(first_elem.GetQueryStart(),
00509                                   last_elem.GetQueryStart() + last_elem.GetQueryLength());
00510         CRange<TModelUnit> range2(first_elem.GetSubjectStart(),
00511                                   last_elem.GetSubjectStart() + last_elem.GetSubjectLength());
00512 
00513         /// clipping:
00514 
00515         /// first test:
00516         ///  - is the panel entirely off the screen (left or right)?
00517         if ( (range1.GetTo() < rcv1.GetFrom()  &&  range2.GetTo() < rcv2.GetFrom())  ||
00518              (range1.GetFrom() > rcv1.GetTo()  &&  range2.GetFrom() > rcv2.GetTo()) ) {
00519             /// off screen, not crossing
00520             ++clip_bounds;
00521             continue;
00522         }
00523 
00524         /// second test:
00525         ///  - does the panel cross left -> right or right -> left at
00526         ///    so steep an angle as to be worthless information?
00527         if ( !range1.IntersectingWith(rcv1_clip)  &&
00528              !range2.IntersectingWith(rcv2_clip)) {
00529             ++clip_cross;
00530             continue;
00531         }
00532 
00533         TModelUnit x_from1 = x_Seq2Lim1(range1.GetFrom());
00534         TModelUnit x_to1   = x_Seq2Lim1(range1.GetTo());
00535         TModelUnit x_from2 = x_Seq2Lim2(range2.GetFrom());
00536         TModelUnit x_to2   = x_Seq2Lim2(range2.GetTo());
00537 
00538         /// we will only iterate the elements in this hit if the entire hit
00539         /// occupies more than one pixel
00540         if (fabs(x_from1 - x_to1) > pane.GetScaleX()  ||
00541             fabs(x_from2 - x_to2) > pane.GetScaleX()) {
00542 
00543             /// some part of the range intersects the visible area
00544             /// now we start back with the first element
00545             CHitGlyph::TElemGlyphCont::const_iterator itE     = elems.begin();
00546             CHitGlyph::TElemGlyphCont::const_iterator itE_end = elems.end();
00547 
00548             range1.SetTo(itE->GetHitElem().GetQueryStart() +
00549                          itE->GetHitElem().GetQueryLength());
00550             range2.SetTo(itE->GetHitElem().GetSubjectStart() +
00551                          itE->GetHitElem().GetSubjectLength());
00552 
00553             x_to1 = x_Seq2Lim1(range1.GetTo());
00554             x_to2 = x_Seq2Lim2(range2.GetTo());
00555 
00556             for ( ;  itE != itE_end;  ++itE) {
00557                 const IHitElement& elem = itE->GetHitElem();
00558                 if (elem.GetQueryStart()   == -1  ||
00559                     elem.GetSubjectStart() == -1) {
00560                     continue;
00561                 }
00562 
00563                 ///
00564                 /// compute sequence and model coordinates for this element's
00565                 /// starting and ending coordinates
00566                 ///
00567 
00568                 //TODO - don't we need to subtract 1 from start + len?
00569                 CRange<TModelUnit> elem_range1(elem.GetQueryStart(),
00570                                                elem.GetQueryStart() + elem.GetQueryLength());
00571                 CRange<TModelUnit> elem_range2(elem.GetSubjectStart(),
00572                                                 elem.GetSubjectStart() + elem.GetSubjectLength());
00573 
00574                 /// check to see if the starting point of this element is
00575                 /// mergeable with the ending point of the previous element
00576                 TModelUnit x_elem1_start = x_Seq2Lim1(elem_range1.GetFrom());
00577                 TModelUnit x_elem1_stop  = x_Seq2Lim1(elem_range1.GetTo());
00578                 TModelUnit x_elem2_start = x_Seq2Lim2(elem_range2.GetFrom());
00579                 TModelUnit x_elem2_stop  = x_Seq2Lim2(elem_range2.GetTo());
00580 
00581                 /// merge this element if the gap space is too small
00582                 if (fabs(x_elem1_start - x_to1) < pane.GetScaleX()  &&
00583                     fabs(x_elem2_start - x_to2) < pane.GetScaleX()) {
00584                     range1 += elem_range1;
00585                     range2 += elem_range2;
00586 
00587                     x_to1 = x_elem1_stop;
00588                     x_to2 = x_elem2_stop;
00589                     continue;
00590                 }
00591 
00592                 ///
00593                 /// unmerged element
00594                 /// render it as a panel
00595                 ///
00596                 if (range1.IntersectingWith(rcv1_clip)  ||
00597                     range2.IntersectingWith(rcv2_clip)) {
00598                     CRgbaColor& clr = itE->IsSelected() ? sel_color :
00599                             (is_mixed ? minus_color : plus_color);
00600                     x_DrawCrossedPanel(pane, clr, x_elem1_start, x_elem1_stop,
00601                                                   x_elem2_start, x_elem2_stop);
00602                     ++elements_rendered;
00603                 }
00604 
00605                 range1 = elem_range1;
00606                 range2 = elem_range2;
00607 
00608                 x_from1 = x_elem1_start;
00609                 x_from2 = x_elem2_start;
00610                 x_to1   = x_elem1_stop;
00611                 x_to2   = x_elem2_stop;
00612             }
00613         }
00614 
00615         if (is_mixed) {
00616             x_DrawCrossedPanel(pane, minus_color,
00617                                x_from1, x_to1, x_from2, x_to2);
00618         } else {
00619             x_DrawCrossedPanel(pane, plus_color,
00620                                x_from1, x_to1, x_from2, x_to2);
00621         }
00622         ++elements_rendered;
00623     }
00624 
00625     glFlush();
00626     /**
00627     LOG_POST(Error << "CCrossPanelIR::x_DrawCrossAlignment(): finish: "
00628         << sw.Elapsed() << ": "
00629         << clip_bounds << " bound / "
00630         << clip_cross << " cross / "
00631         << elements_rendered << " rendered");
00632         **/
00633 }
00634 
00635 
00636 
00637 double CCrossPanelIR::x_SelectBaseStep(double MinV, double MaxV) const
00638 {
00639     double Range = MaxV - MinV;
00640     double logRange = log10(Range);
00641     logRange = ceil(logRange) - 1;
00642     double Step = pow(10.0, logRange);
00643 
00644     // selcting BaseStep as step divided by 1, 2 or 5
00645     double BaseStep = Step;
00646     double nTicks = Range / BaseStep;
00647     int i=0;
00648     while( nTicks < 8 )
00649     {
00650         BaseStep = Step / sc_StepK[i++];
00651         nTicks = Range / BaseStep;
00652     }
00653     return BaseStep;
00654 }
00655 
00656 
00657 
00658 // Convert sequence to limits
00659 TModelUnit CCrossPanelIR::x_Seq2Lim1(TModelUnit seq)
00660 {
00661     return (seq - m_RCV1.Left()) / m_RCV1.Width();
00662 }
00663 
00664 
00665 TModelUnit CCrossPanelIR::x_Seq2Lim2(TModelUnit seq)
00666 {
00667     return (seq - m_RCV2.Left()) / m_RCV2.Width();
00668 }
00669 
00670 
00671 // Convert limits to sequence
00672 TModelUnit CCrossPanelIR::x_Lim2Seq1(TModelUnit lim)
00673 {
00674     return lim;
00675 }
00676 
00677 
00678 TModelUnit CCrossPanelIR::x_Lim2Seq2(TModelUnit lim)
00679 {
00680     return lim;
00681 }
00682 
00683 
00684 bool CCrossPanelIR::x_IsSeqLettersFit1() const
00685 {
00686     return m_RCV1.Width() / m_RCM1.Width() <= 1.0f / 6.0f;
00687 }
00688 
00689 bool CCrossPanelIR::x_IsSeqLettersFit2() const
00690 {
00691     return m_RCV2.Width() / m_RCM2.Width() <= 1.0f / 6.0f;
00692 }
00693 
00694 
00695 END_NCBI_SCOPE
Modified on Wed May 23 13:19:28 2012 by modify_doxy.py rev. 337098