align_row.cpp
来自「ncbi源码」· C++ 代码 · 共 1,105 行 · 第 1/3 页
CPP
1,105 行
s_tip += ", on Sequence "; s_tip += FormatRange(seq_r.GetFrom(), seq_r.GetTo() + 1); s_tip += " : "; s_tip += seq; } else if(type == 0) { // generate string for gap s_tip += "\nGap "; s_tip += FormatRange(aln_r.GetFrom() + 1, aln_r.GetTo() + 1); s_tip += ", on Sequence "; s_tip += FormatRange(seq_r.GetFrom() + 1, seq_r.GetTo() + 1); } } } return s_tip;}void CAlnVecRow::x_OnClickExpandBtn(){ fl_cursor(FL_CURSOR_WAIT); Expand(! IsExpanded()); fl_cursor(FL_CURSOR_DEFAULT);}/// Renders graphical part of the rowvoid CAlnVecRow::x_RenderAlign(CGlPane& pane){ _ASSERT(m_pStyle); pane.OpenOrtho(); TModelUnit offset_x = pane.GetOffsetX(); TModelUnit offset_y = pane.GetOffsetY(); TModelRect rc_lim = pane.GetModelLimitsRect(); TModelRect rc_model = pane.GetVisibleRect(); TModelUnit y2 = rc_lim.Top() + kAlignSpace - offset_y; TModelUnit y1 = rc_lim.Top() + m_BaseHeight -1 - kAlignSpace - offset_y; TSeqPos row_start = m_Handle.GetSeqAlnStart(); TSeqPos row_stop = m_Handle.GetSeqAlnStop(); glLineWidth(1.0f); glColorC(m_pStyle->GetAlignColor()); // now render segments actually present unsigned Left = (unsigned) floor(rc_model.Left()); unsigned Right = (unsigned) ceil(rc_model.Right()); CAlnMap::TSignedRange Range(Left, Right); // render aligned segments CRef<CAlnVec::CAlnChunkVec> vAlnChunks = m_Handle.GetAlnChunks(Range, CAlnVec::fSkipInserts); if(m_pCache) { // render parts of chunks accordingly to scores pane.Close(); x_RenderAlignScores(pane, vAlnChunks); pane.OpenOrtho(); } else { // scores are not available - render all chunks with a default color // render a single line for all possible gaps TModelUnit Yc = (y2 + y1) / 2; glBegin(GL_LINES); glLined(row_start - offset_x, Yc, row_stop - offset_x, Yc); glEnd(); x_RenderAlignSegments(pane, vAlnChunks, (int) y1, (int) y2); } // render inserts CRef<CAlnVec::CAlnChunkVec> vChunks = m_Handle.GetAlnChunks(Range, CAlnVec::fInsertsOnly); glColor3d(0, 0, 0.5); glBegin(GL_LINES); for (int i = 0; i < vChunks->size(); i++) { CConstRef<CAlnMap::CAlnChunk> chunk = (*vChunks)[i]; _ASSERT(chunk->GetType() & CAlnMap::fSeq); _ASSERT(chunk->GetType() & CAlnMap::fNotAlignedToSeqOnAnchor); TModelUnit ins_pos = chunk->GetAlnRange().GetFrom() - offset_x; TModelUnit len = chunk->GetRange().GetLength(); TModelUnit x1 = ins_pos - len / 2; TModelUnit x2 = x1 + len; // assuming glBegin(GL_LINES) glLined(ins_pos, y1, ins_pos, y2); glLined(x1, y1, x2, y1); glLined(x1, y2, x2, y2); } glEnd(); // render sequence if its visible if(x_CanRenderSeq(pane)) { double H = m_pStyle->GetSeqFont().TextHeight(); double y = floor((y1 + y2 + H) / 2); x_RenderSequence(pane, y, Left, Right); } pane.Close(); x_RenderGraph(pane, vAlnChunks);}void CAlnVecRow::x_RenderAlignSegments(CGlPane& pane, TRefChunks& chunks, int top_y, int bottom_y){ glColorC(m_pStyle->GetAlignColor()); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); TModelUnit offset_x = pane.GetOffsetX(); for (int i = 0; i < chunks->size(); i++) { CConstRef<CAlnMap::CAlnChunk> chunk = (*chunks)[i]; if((chunk->GetType() & CAlnMap::fSeq)) { _ASSERT((chunk->GetType() & CAlnMap::fNotAlignedToSeqOnAnchor) == 0); const TSignedSeqRange& R = chunk->GetAlnRange(); glRectd(R.GetFrom() - offset_x, top_y, R.GetToOpen() - offset_x, bottom_y); } }}/// Renders alignment (graphical) part of the row according to scores./// Score intervals are rendered differently depending on their size./// Long intervals ("long" meaning covering more than one full pixel) are rendered in/// "vector" mode - the series of pixels corresponding to a single interval/// is drawn as a single rectangle with color defined by the intreval's score./// Short intervals are rendered in "raster" mode - algorithm iterates by intervals/// and calculates average and maximal scores corresponding to a particular pixel,/// then each pixel is drawn with its individual color.void CAlnVecRow::x_RenderAlignScores(CGlPane& pane, TRefChunks& chunks){ pane.OpenPixels(); const TVPRect& rc_vp = pane.GetViewport(); const TModelRect rc_vis = pane.GetVisibleRect(); glTranslated(0.0, rc_vp.Top(), 0.0); // to make the display list "scrollable" vertically // if horz projection has changed - invalidate display list if(m_PixLeft != rc_vp.Left() || m_PixRight != rc_vp.Right() || m_ModelLeft != rc_vis.Left() || m_ModelRight != rc_vis.Right()) { m_DList.Invalidate(); m_PixLeft = rc_vp.Left(); m_PixRight = rc_vp.Right(); m_ModelLeft = rc_vis.Left(); m_ModelRight = rc_vis.Right(); } if(m_DList.IsValid()) { m_DList.Call(); } else { // need to create a new one m_DList.Begin(GL_COMPILE_AND_EXECUTE); TModelUnit left = rc_vis.Left(); TModelUnit scale_x = pane.GetScaleX(); int range_pix_start = rc_vp.Left(); int range_pix_end = rc_vp.Right(); // visible alignment range in seq coords int range_from = (int) (floor(left)); // int range_to_open = (int) (ceil(pane.GetVisibleRect().Right())); int top_y = - kAlignSpace; int bottom_y = - m_BaseHeight + kAlignSpace; int off_y = 0, extr_off_y = 0; // obtain Score Collection and setup iterators const CScoreCache::TScoreColl& ScoreColl = m_pCache->GetScores(m_Handle.GetRowNum()); CScoreCache::TScoreColl::const_iterator it = ScoreColl.begin(); const CScoreCache::TScoreColl::const_iterator it_end = ScoreColl.end(); it = ScoreColl.find(it, it_end, range_from); double int_score; double pix_start, pix_end; double score_sum = 0, score_min = 0, score_len = 0; bool b_first = true; // "true" if pixel is being processed for the first time bool b_new_interval = true; bool b_lines = true; glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBegin(GL_LINES); int i_prev_chunk = -1, i_chunk = 0, n_chunks = chunks->size(); CConstRef<CAlnMap::CAlnChunk> chunk; // [pos_start, pos_end) defines range being processed int pos_start = -1, pos_end = range_from; bool b_skip = false; // iterate by pixels, score intervals and chunks for( int pix = range_pix_start; pix <= range_pix_end && it != it_end && i_chunk < n_chunks; ) { if(i_prev_chunk != i_chunk) { chunk = (*chunks)[i_chunk]; int type = chunk->GetType(); b_skip = false; if(type & CAlnMap::fSeq) { // aligned segment off_y = 0; extr_off_y = kExtremeArea; } else if(type & (CAlnVec::fNoSeqOnRight | CAlnVec::fNoSeqOnLeft)) { // empty space - do not draw anything b_skip = true; } else { // gap off_y = kGapOffset ; extr_off_y = kGapOffset + kGapExtremeArea; } } if(b_new_interval) { // new range int_score = it->GetAttr(); } if(i_chunk != i_prev_chunk || b_new_interval) { // [pos_start, pos_end) is defined as intersection of current score interval // and current chunk pos_start = pos_end; pos_end = min((int) chunk->GetAlnRange().GetToOpen(), (int) it->GetToOpen()); // transform from seq. coords to pixels pix_start = range_pix_start + ((double) (pos_start - left)) / scale_x; pix_end = range_pix_start + ((double) (pos_end - left)) / scale_x; i_prev_chunk = i_chunk; b_new_interval = false; } if(b_skip && (pix_start <= pix && pix_end >= pix + 1)) { int strip_end = (int) ceil(pix_end) - 1; if(! b_skip) { if(b_lines) { glEnd(); b_lines = false; } // interval covers current pixel and may be consequent pixels // draw them in one iteration glColorC(m_pCache->GetColorForScore(int_score)); glRectd(pix, top_y - off_y, strip_end, bottom_y + off_y); } pix = strip_end; b_first = true; } //[start, end] specify part of the pixel covered by current score interval double start = max((double) pix, pix_start); double end = min((double) pix + 1, pix_end); double len = end - start; _ASSERT(len >= 0.0 && len <= 1.0); double d_score = len * int_score; if(b_first) { // new pixel - reset assign values to accumulators score_min = int_score; score_sum = d_score; score_len = len; b_first = false; } else { // accumulate score_min = min(score_min, int_score); score_sum += d_score; score_len += len; } if(pix_end < pix + 1) { // current range ends before current pixel if(it->GetToOpen() <= pos_end) { // advance score interval it++; b_new_interval = true; } if(chunk->GetAlnRange().GetToOpen() <= pos_end) { // advance chunk i_chunk++; } } else { // pixel is fully covered with current range - draw the pixel if(! b_lines) { glBegin(GL_LINES); b_lines = true; } double sc = score_sum / score_len; bool b_diff = (score_min != sc); glColorC(m_pCache->GetColorForScore(b_diff ? score_min : sc)); glLined(pix, top_y - off_y, pix, bottom_y + off_y); if(b_diff) { glColorC(m_pCache->GetColorForScore(sc)); glLined(pix, top_y - extr_off_y, pix, bottom_y + extr_off_y); } pix++; b_first = true; } } if(b_lines) { glEnd(); } m_DList.End(); } glTranslated(0.0, -rc_vp.Top(), 0.0); pane.Close();}#define SEQ_OFF_VERT 0#define SEQ_OFF_HORZ 0/// Checks if sequence can be drawn.bool CAlnVecRow::x_CanRenderSeq(CGlPane& pane){ if(m_pStyle) { double min_w = 1.0 / m_pStyle->GetSeqFont().GetMetric(CGlBitmapFont::eMetric_MaxCharWidth); double scale_x = pane.GetScaleX(); return min_w >= scale_x; } else return false;}// renders a row of seq symbols in the range [Start, Stop]void CAlnVecRow::x_RenderSequence(CGlPane& pane, float y, int start, int stop){ _ASSERT(m_pStyle); string seq; m_Handle.GetAlnSeqString(seq, CAlnVec::TSignedRange(start, stop)); replace(seq.begin(), seq.end(), '-', ' '); glColorC(m_pStyle->GetAlignTextColor()); float x = start + 0.5 - pane.GetOffsetX(); m_pStyle->GetSeqFont().ArrayTextOut(x, y, 1.0f, 0.0f, seq.c_str(), (float) pane.GetScaleX(), 0.0f);}static const int kTextOffsetY = 0;static const int kTextOffsetX = 2;static const int kPosOffsetX = 4;void CAlnVecRow::x_RenderDescr(CGlPane& pane, int state){ _ASSERT(m_pStyle); pane.OpenPixels(); TVPRect rc_vp = pane.GetViewport(); bool b_wid_focused = (state & fWidgetFocused) != 0; //draw background if(state & fItemSelected) { if(b_wid_focused) { glColorC(m_pStyle->GetSelBackFocusedColor()); } else { glColorC(m_pStyle->GetSelBackColor()); } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glRectd(rc_vp.Left(), rc_vp.Bottom() - 1, rc_vp.Right(), rc_vp.Top()); } // draw text label glColorC((state & fItemSelected) != 0 ? m_pStyle->GetSelTextColor() : m_pStyle->GetTextColor()); int x = rc_vp.Left() + kTextOffsetX; int w = rc_vp.Width() - kTextOffsetX;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?