1 #include "alg/glsequence.hpp"
9 GlSequence::GlSequence(const Sequence &s,
10 boost::shared_ptr<AnnotationColors> cm)
17 drawColor(new Color(0.0, 0.0, 0.0)),
18 char_pix_per_world_unit(2.5)
22 GlSequence::GlSequence(const GlSequence &s)
27 seq_height(s.seq_height),
28 color_mapper(s.color_mapper),
29 drawColor(s.drawColor),
30 char_pix_per_world_unit(s.char_pix_per_world_unit)
34 GlSequence::GlSequence(const GlSequence *s)
39 seq_height(s->seq_height),
40 color_mapper(s->color_mapper),
41 drawColor(s->drawColor),
42 char_pix_per_world_unit(s->char_pix_per_world_unit)
46 GlSequence &GlSequence::operator=(const GlSequence & s)
49 Sequence::operator=(s);
53 seq_height = s.seq_height;
54 color_mapper = s.color_mapper;
55 drawColor = s.drawColor;
56 assert(char_pix_per_world_unit == s.char_pix_per_world_unit);
61 void GlSequence::setX(GLfloat value)
66 GLfloat GlSequence::x() const
71 GLfloat GlSequence::right() const
76 void GlSequence::setY(GLfloat value)
81 GLfloat GlSequence::y() const
86 GLfloat GlSequence::height() const
91 GLfloat GlSequence::size() const
93 return Sequence::size();
96 Sequence::size_type GlSequence::leftbase(GLfloat left) const
98 left = ceil(left - seq_x);
101 else if (left > Sequence::size() )
102 return Sequence::size();
104 return (Sequence::size_type)left;
107 Sequence::size_type GlSequence::rightbase(GLfloat right) const
109 right = floor(right) - seq_x;
110 if (right > Sequence::size())
111 return Sequence::size();
115 return (Sequence::size_type)right;
118 Sequence::const_iterator
119 GlSequence::region_begin(GLfloat left, GLfloat right) const
121 if ( leftbase(left) > Sequence::size() or left > right )
122 return Sequence::end();
124 return Sequence::begin() + leftbase(left);
127 Sequence::const_iterator
128 GlSequence::region_end(GLfloat left, GLfloat right) const
130 if ( rightbase(right) > Sequence::size() or left > right )
131 return Sequence::end();
133 return Sequence::begin() + rightbase(right);
136 GlSequence GlSequence::subseq(size_type start, size_type count) const
138 GlSequence new_seq(*this);
139 new_seq.seq = seq->subseq(start, count);
140 copy_children(new_seq, start, count);
145 //! set default track draw color
146 void GlSequence::setColor(boost::shared_ptr<Color> &c)
151 //! get default track draw color
152 boost::shared_ptr<Color> GlSequence::color()
157 int GlSequence::get_viewport_width_in_pixels()
160 glGetIntegerv(GL_VIEWPORT, viewport);
161 return viewport[3]; // grab the viewport width
164 GLfloat GlSequence::pixelWidth(GLfloat left, GLfloat right) const
166 return pixelWidth(left, right, get_viewport_width_in_pixels());
170 GlSequence::pixelWidth(GLfloat left, GLfloat right, int vp_width) const
172 return round((right-left)/vp_width);
175 bool GlSequence::is_sequence_renderable(GLfloat left, GLfloat right) const
177 return is_sequence_renderable(left, right, get_viewport_width_in_pixels());
180 bool GlSequence::is_sequence_renderable(GLfloat left,
182 int viewport_width) const
184 GLfloat world_width = right - left;
185 GLfloat pixels_needed = (char_pix_per_world_unit * world_width);
187 // if the number of pixels taken up by rendering the characters
188 // that'd show up in the current ortho width is less than the window
189 // width we can actually draw something
190 return pixels_needed < viewport_width;
194 void GlSequence::draw(GLfloat left, GLfloat right) const
196 if ( not is_sequence_renderable(left, right) ) {
197 draw_track(left, right);
199 draw_sequence(left, right);
201 draw_annotations(left, right);
204 void GlSequence::draw_box(GLfloat world_left, GLfloat world_right,
205 GLfloat left, GLfloat right,
206 GLfloat height, GLfloat z) const
208 GLfloat pixel_width = pixelWidth(world_left, world_right);
209 GLfloat offset = height/2.0;
210 GLfloat top = seq_y + offset;
211 GLfloat bottom = seq_y - offset;
213 // make our box be at least 1 pixel
214 if ((right-left) < pixel_width) {
215 right = left + pixel_width;
218 glVertex3f(left, top, z);
219 glVertex3f(left, bottom, z);
220 glVertex3f(right, bottom, z);
221 glVertex3f(right, top, z);
225 void GlSequence::draw_track(GLfloat left, GLfloat right) const
227 glColor3fv(drawColor->get());
228 // draw main sequence track
229 draw_box(left, right, seq_x, seq_x+Sequence::size(), seq_height, 0.0);
232 void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
235 GLfloat annotation_z = seq_z + 10.0;
236 const std::list<annot>& annots = Sequence::annotations();
237 const std::list<motif>& motifs = Sequence::motifs();
238 for (std::list<annot>::const_iterator annot_itor = annots.begin();
239 annot_itor != annots.end();
242 glColor3f(0.0, 0.8, 0.0);
243 draw_box(left, right, seq_x+annot_itor->begin, seq_x+annot_itor->end,
244 seq_height, annotation_z);
247 for (std::list<motif>::const_iterator motifs_itor = motifs.begin();
248 motifs_itor != motifs.end();
251 glColor3fv(color_mapper->lookup("motif", motifs_itor->sequence).get());
252 draw_box(left, right, seq_x+motifs_itor->begin, seq_x+motifs_itor->end,
253 seq_height, annotation_z+1.0);
258 // this way of drawing characters, came from the red open gl book
260 const int STROKE = 2;
263 typedef struct charpoint {
269 {0, -5, PT}, {2.5, 5, PT}, {5, -5, STROKE},
270 {0.75, -2, PT}, {4.25, -2, END}
274 {2.5, -5, PT}, {2.5,5, STROKE}, {0, 5, PT}, {5, 5, END}
278 {5, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
279 {2, -5, PT}, {3, -5, PT}, {5, -3, STROKE},
280 {2.5, -1, PT}, {5, -1,PT}, {5, -5, END}
284 {4.9, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
285 {2, -5, PT}, {3, -5, PT}, {5, -3, END}
288 CP Xdata[] = {{ 0, 5, PT}, {5, -5,STROKE},{0,-5,PT},{5, 5, END}};
289 CP Ndata[] = {{ 0, -5, PT}, {0, 5, PT}, {5, -5, PT}, {5, 5, END}};
291 //! the maximum width used for a charcter glyph
292 const int max_glyph_width = 5; // unit ( glyph_coord )
294 static void drawLetter(CP *l, GLfloat z)
296 glBegin(GL_LINE_STRIP);
300 glVertex3f(l->x, l->y, z);
303 glVertex3f(l->x, l->y, z);
305 glBegin(GL_LINE_STRIP);
308 glVertex3f(l->x, l->y, z);
313 throw runtime_error("data structure failure");
319 void GlSequence::draw_sequence(GLfloat left, GLfloat right) const
321 // FIXME: basically this needs to be greater than the number of annotations
322 const GLfloat z = 30;
324 glColor3fv(drawColor->get());
326 Sequence::const_iterator seq_itor = region_begin(left, right);
327 Sequence::const_iterator seq_end = region_end(left, right);
328 Sequence::size_type basepair = 0;
329 const float bp_per_world = 1.0; //( world coord )
330 const float glyph_x_scale = 0.125; // unit = ( world coord / glyph coord )
331 // compute how much space there should be to either size of a letter
332 const float glyph_margin = (bp_per_world - glyph_x_scale * max_glyph_width)
335 assert(seq_end - seq_itor >= 0);
336 while(seq_itor != seq_end)
338 assert ( basepair < Sequence::size() );
340 glTranslatef( seq_x+leftbase(left) + basepair + glyph_margin, seq_y, 1.0 );
341 glScalef(glyph_x_scale, 1.0, 1.0);
344 drawLetter(Adata, z);
347 drawLetter(Tdata, z);
350 drawLetter(Gdata, z);
353 drawLetter(Cdata, z);
356 drawLetter(Ndata, z);
359 drawLetter(Xdata, z);
368 bool operator==(const GlSequence &left, const GlSequence &right)
370 return ( (left.seq_x == right.seq_x) and
371 (left.seq_y == right.seq_y) and
372 (left.seq_z == right.seq_z) and
373 (left.seq_height == right.seq_height) and
374 (left.drawColor == right.drawColor));