1 #include "alg/glsequence.hpp"
9 GlSequence::GlSequence(const Sequence &s,
10 boost::shared_ptr<AnnotationColors> cm)
13 char_pix_per_world_unit(2.5)
15 seq->setDrawable(default_drawable());
18 GlSequence::GlSequence(const GlSequence &s)
20 color_mapper(s.color_mapper),
21 char_pix_per_world_unit(s.char_pix_per_world_unit)
23 seq->setDrawable(copy_drawable(s.seq->drawable()));
26 GlSequence::GlSequence(const GlSequence *s)
28 color_mapper(s->color_mapper),
29 char_pix_per_world_unit(s->char_pix_per_world_unit)
31 seq->setDrawable(copy_drawable(s->seq->drawable()));
34 GlSequence::GlSequence(const GlSequenceRef s)
35 : Sequence( (SequenceRef)s ),
36 color_mapper(s->color_mapper),
37 char_pix_per_world_unit(s->char_pix_per_world_unit)
39 seq->setDrawable(copy_drawable(s->seq->drawable()));
42 GlSequence &GlSequence::operator=(const GlSequence & s)
45 Sequence::operator=(s);
46 seq->setDrawable(copy_drawable(s.seq->drawable()));
47 color_mapper = s.color_mapper;
48 assert(char_pix_per_world_unit == s.char_pix_per_world_unit);
53 DrawableRef GlSequence::default_drawable()
55 ColorRef c(new Color(0.0, 0.0, 0.0));
56 DrawableRef d(new Drawable(0.0, 0.0, 1.0, 12.0, c));
60 DrawableRef GlSequence::copy_drawable(DrawableRef old_d)
62 ColorRef c(old_d->color());
63 DrawableRef d(new Drawable(old_d));
69 SeqSpanRef GlSequence::make_undefined_sequence_annotation(
70 Drawable::draw_func_ptr draw,
74 // create all the components of our annotation
75 // (should seq_i-start_i
76 SeqSpanRef empty_seq(seq->subseq(start, count));
77 AnnotationsRef empty_seq_annot(new Annotations("null"));
78 DrawableRef drawable(default_drawable());
79 // glue everything to gether
80 drawable->setDrawFunction(draw);
81 empty_seq->setAnnotations(empty_seq_annot);
82 empty_seq->setDrawable(drawable);
86 void GlSequence::add_annotations_for_undefined_sequence(Drawable::draw_func_ptr draw)
88 Sequence::const_iterator start_i = begin();
89 Sequence::const_iterator seq_i = begin();
90 Sequence::const_iterator end_i = end();
92 Sequence::const_iterator start_block_i = end();
94 for(; seq_i != end_i; ++seq_i)
96 // need a better set of characters to serch for
97 if (*seq_i == 'N' or *seq_i == 'n') {
98 if (start_block_i == end_i) {
99 start_block_i = seq_i;
102 if (start_block_i != end_i) {
104 size_type start = start_block_i - start_i;
105 size_type count = seq_i - start_block_i;
106 // add the annotation
107 add_annotation(make_undefined_sequence_annotation(draw, start, count));
108 // reset our counter...
109 start_block_i = end_i;
113 // catch stuff at the end
114 if( start_block_i != end_i ) {
115 size_type start = start_block_i - start_i;
116 size_type count = seq_i - start_block_i;
117 add_annotation(make_undefined_sequence_annotation(draw, start, count));
122 void GlSequence::setX(float value)
124 seq->drawable()->setX(value);
127 float GlSequence::x() const
129 return seq->drawable()->x();
132 void GlSequence::setY(GLfloat value)
134 seq->drawable()->setY(value);
137 float GlSequence::y() const
139 return seq->drawable()->y();
142 float GlSequence::z() const
144 return seq->drawable()->z();
147 float GlSequence::height() const
149 return seq->drawable()->height();
152 GLfloat GlSequence::right() const
157 GLfloat GlSequence::size() const
159 return Sequence::size();
162 Sequence::size_type GlSequence::leftbase(GLfloat left) const
164 left = ceil(left - x());
167 else if (left > Sequence::size() )
168 return Sequence::size();
170 return (Sequence::size_type)left;
173 Sequence::size_type GlSequence::rightbase(GLfloat right) const
175 right = floor(right) - x();
176 if (right > Sequence::size())
177 return Sequence::size();
181 return (Sequence::size_type)right;
184 Sequence::const_iterator
185 GlSequence::region_begin(GLfloat left, GLfloat right) const
187 if ( leftbase(left) > Sequence::size() or left > right )
188 return Sequence::end();
190 return Sequence::begin() + leftbase(left);
193 Sequence::const_iterator
194 GlSequence::region_end(GLfloat left, GLfloat right) const
196 if ( rightbase(right) > Sequence::size() or left > right )
197 return Sequence::end();
199 return Sequence::begin() + rightbase(right);
202 GlSequence GlSequence::subseq(size_type start, size_type count) const
204 GlSequence new_seq(*this);
205 new_seq.seq = seq->subseq(start, count);
206 // make sure our subseq has a drawable attached to it
207 // perhaps we should figure out correct x,y,z,h coords
208 DrawableRef d(default_drawable());
209 // and default to our current color
212 new_seq.seq->setDrawable(d);
213 copy_children(new_seq, start, count);
218 void GlSequence::setColor(ColorRef &c)
220 seq->drawable()->setColor(c);
223 ColorRef GlSequence::color()
225 return seq->drawable()->color();
228 const ColorRef GlSequence::color() const
230 return seq->drawable()->color();
233 int GlSequence::get_viewport_width_in_pixels()
236 glGetIntegerv(GL_VIEWPORT, viewport);
237 return viewport[3]; // grab the viewport width
240 GLfloat GlSequence::pixelWidth(GLfloat left, GLfloat right) const
242 return pixelWidth(left, right, get_viewport_width_in_pixels());
246 GlSequence::pixelWidth(GLfloat left, GLfloat right, int vp_width) const
248 return round((right-left)/vp_width);
251 bool GlSequence::is_sequence_renderable(GLfloat left, GLfloat right) const
253 return is_sequence_renderable(left, right, get_viewport_width_in_pixels());
256 bool GlSequence::is_sequence_renderable(GLfloat left,
258 int viewport_width) const
260 GLfloat world_width = right - left;
261 GLfloat pixels_needed = (char_pix_per_world_unit * world_width);
263 // if the number of pixels taken up by rendering the characters
264 // that'd show up in the current ortho width is less than the window
265 // width we can actually draw something
266 return pixels_needed < viewport_width;
270 void GlSequence::draw(GLfloat left, GLfloat right) const
272 if ( not is_sequence_renderable(left, right) ) {
273 draw_track(left, right);
275 draw_sequence(left, right);
277 draw_annotations(left, right);
280 void GlSequence::draw_box(GLfloat world_left, GLfloat world_right,
281 GLfloat left, GLfloat right,
282 GLfloat height, GLfloat z) const
284 GLfloat pixel_width = pixelWidth(world_left, world_right);
285 GLfloat offset = height/2.0;
286 GLfloat top = y() + offset;
287 GLfloat bottom = y() - offset;
289 // make our box be at least 1 pixel
290 if ((right-left) < pixel_width) {
291 right = left + pixel_width;
294 glVertex3f(left, top, z);
295 glVertex3f(left, bottom, z);
296 glVertex3f(right, bottom, z);
297 glVertex3f(right, top, z);
301 void GlSequence::draw_track(GLfloat left, GLfloat right) const
303 glColor3fv(color()->get());
304 // draw main sequence track
305 draw_box(left, right, x(), x()+Sequence::size(), height(), 0.0);
308 void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
311 GLfloat annotation_z = z() + 10.0;
312 const SeqSpanRefList& annots = Sequence::annotations();
313 const MotifList& motifs = Sequence::motifs();
314 for (SeqSpanRefList::const_iterator annot_itor = annots.begin();
315 annot_itor != annots.end();
318 glColor3f(0.0, 0.8, 0.0);
319 draw_box(left, right, x()+(*annot_itor)->start(), x()+(*annot_itor)->stop(),
320 height(), annotation_z);
323 for (MotifList::const_iterator motifs_itor = motifs.begin();
324 motifs_itor != motifs.end();
327 glColor3fv(color_mapper->lookup("motif", motifs_itor->sequence).get());
328 draw_box(left, right, x()+motifs_itor->begin, x()+motifs_itor->end,
329 height(), annotation_z+1.0);
333 // this way of drawing characters, came from the red open gl book
335 const int STROKE = 2;
338 typedef struct charpoint {
344 {0, -5, PT}, {2.5, 5, PT}, {5, -5, STROKE},
345 {0.75, -2, PT}, {4.25, -2, END}
349 {2.5, -5, PT}, {2.5,5, STROKE}, {0, 5, PT}, {5, 5, END}
353 {5, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
354 {2, -5, PT}, {3, -5, PT}, {5, -3, STROKE},
355 {2.5, -1, PT}, {5, -1,PT}, {5, -5, END}
359 {4.9, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
360 {2, -5, PT}, {3, -5, PT}, {5, -3, END}
363 CP Xdata[] = {{ 0, 5, PT}, {5, -5,STROKE},{0,-5,PT},{5, 5, END}};
364 CP Ndata[] = {{ 0, -5, PT}, {0, 5, PT}, {5, -5, PT}, {5, 5, END}};
366 //! the maximum width used for a charcter glyph
367 const int max_glyph_width = 5; // unit ( glyph_coord )
369 static void drawLetter(CP *l, GLfloat z)
371 glBegin(GL_LINE_STRIP);
375 glVertex3f(l->x, l->y, z);
378 glVertex3f(l->x, l->y, z);
380 glBegin(GL_LINE_STRIP);
383 glVertex3f(l->x, l->y, z);
388 throw runtime_error("data structure failure");
394 void GlSequence::draw_sequence(GLfloat left, GLfloat right) const
396 // FIXME: basically this needs to be greater than the number of annotations
397 const GLfloat z = 30;
399 glColor3fv(color()->get());
401 Sequence::const_iterator seq_itor = region_begin(left, right);
402 Sequence::const_iterator seq_end = region_end(left, right);
403 Sequence::size_type basepair = 0;
404 const float bp_per_world = 1.0; //( world coord )
405 const float glyph_x_scale = 0.125; // unit = ( world coord / glyph coord )
406 // compute how much space there should be to either size of a letter
407 const float glyph_margin = (bp_per_world - glyph_x_scale * max_glyph_width)
410 assert(seq_end - seq_itor >= 0);
411 while(seq_itor != seq_end)
413 assert ( basepair < Sequence::size() );
415 glTranslatef( x()+leftbase(left) + basepair + glyph_margin, y(), 1.0 );
416 glScalef(glyph_x_scale, 1.0, 1.0);
419 drawLetter(Adata, z);
422 drawLetter(Tdata, z);
425 drawLetter(Gdata, z);
428 drawLetter(Cdata, z);
431 drawLetter(Ndata, z);
434 drawLetter(Xdata, z);
443 bool operator==(const GlSequence &left, const GlSequence &right)
445 return ( (left.x() == right.x()) and
446 (left.y() == right.y()) and
447 (left.z() == right.z()) and
448 (left.height() == right.height()) and
449 (left.color() == right.color()));