|
NCBI C++ ToolKit
|
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
1.7.5.1
Modified on Wed May 23 13:19:28 2012 by modify_doxy.py rev. 337098