1 #include "alg/glsequence.hpp"
9 GlSequence::GlSequence(boost::shared_ptr<Sequence> s,
10 boost::shared_ptr<AnnotationColors> cm)
17 drawColor(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::operator=(const GlSequence & s)
41 seq_height = s.seq_height;
42 color_mapper = s.color_mapper;
43 drawColor = s.drawColor;
44 assert(char_pix_per_world_unit == s.char_pix_per_world_unit);
49 boost::shared_ptr<Sequence> GlSequence::sequence()
54 void GlSequence::setX(GLfloat value)
59 GLfloat GlSequence::x() const
64 GLfloat GlSequence::right() const
69 void GlSequence::setY(GLfloat value)
74 GLfloat GlSequence::y() const
79 GLfloat GlSequence::height() const
84 GLfloat GlSequence::size() const
89 Sequence::size_type GlSequence::leftbase(GLfloat left) const
91 left = ceil(left - seq_x);
94 else if (left > seq->size() )
97 return (Sequence::size_type)left;
100 Sequence::size_type GlSequence::rightbase(GLfloat right) const
102 right = floor(right) - seq_x;
103 if (right > seq->size())
108 return (Sequence::size_type)right;
111 Sequence::const_iterator GlSequence::sequence_begin() const
116 Sequence::const_iterator GlSequence::sequence_end() const
121 Sequence::const_iterator
122 GlSequence::sequence_begin(GLfloat left, GLfloat right) const
124 if ( leftbase(left) > seq->size() or left > right )
127 return seq->begin() + leftbase(left);
130 Sequence::const_iterator
131 GlSequence::sequence_end(GLfloat left, GLfloat right) const
133 if ( rightbase(right) > seq->size() or left > right )
136 return seq->begin() + rightbase(right);
140 //! set default track draw color
141 void GlSequence::setColor(Color &c)
146 //! get default track draw color
147 Color GlSequence::color()
152 int GlSequence::get_viewport_width_in_pixels()
155 glGetIntegerv(GL_VIEWPORT, viewport);
156 return viewport[3]; // grab the viewport width
159 GLfloat GlSequence::get_pixel_width(GLfloat left, GLfloat right) const
161 return get_pixel_width(left, right, get_viewport_width_in_pixels());
165 GlSequence::get_pixel_width(GLfloat left, GLfloat right, int vp_width) const
167 return round((right-left)/vp_width);
170 bool GlSequence::is_sequence_renderable(GLfloat left, GLfloat right) const
172 return is_sequence_renderable(left, right, get_viewport_width_in_pixels());
175 bool GlSequence::is_sequence_renderable(GLfloat left,
177 int viewport_width) const
179 GLfloat world_width = right - left;
180 GLfloat pixels_needed = (char_pix_per_world_unit * world_width);
182 // if the number of pixels taken up by rendering the characters
183 // that'd show up in the current ortho width is less than the window
184 // width we can actually draw something
185 return pixels_needed < viewport_width;
189 void GlSequence::draw(GLfloat left, GLfloat right) const
191 if ( not is_sequence_renderable(left, right) ) {
192 draw_track(left, right);
194 draw_sequence(left, right);
196 draw_annotations(left, right);
199 void GlSequence::draw_box(GLfloat world_left, GLfloat world_right,
200 GLfloat left, GLfloat right,
201 GLfloat height, GLfloat z) const
203 GLfloat pixel_width = get_pixel_width(world_left, world_right);
204 GLfloat offset = height/2.0;
205 GLfloat top = seq_y + offset;
206 GLfloat bottom = seq_y - offset;
208 // make our box be at least 1 pixel
209 if ((right-left) < pixel_width) {
210 right = left + pixel_width;
213 glVertex3f(left, top, z);
214 glVertex3f(left, bottom, z);
215 glVertex3f(right, bottom, z);
216 glVertex3f(right, top, z);
220 void GlSequence::draw_track(GLfloat left, GLfloat right) const
222 glColor3fv(drawColor.get());
223 // draw main sequence track
224 draw_box(left, right, seq_x, seq_x+seq->size(), seq_height, 0.0);
227 void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
230 GLfloat annotation_z = seq_z + 10.0;
231 const std::list<annot>& annots = seq->annotations();
232 const std::list<motif>& motifs = seq->motifs();
233 for (std::list<annot>::const_iterator annot_itor = annots.begin();
234 annot_itor != annots.end();
237 glColor3f(0.0, 0.8, 0.0);
238 draw_box(left, right, seq_x+annot_itor->begin, seq_x+annot_itor->end,
239 seq_height, annotation_z);
242 for (std::list<motif>::const_iterator motifs_itor = motifs.begin();
243 motifs_itor != motifs.end();
246 glColor3fv(color_mapper->lookup("motif", motifs_itor->sequence).get());
247 draw_box(left, right, seq_x+motifs_itor->begin, seq_x+motifs_itor->end,
248 seq_height, annotation_z+1.0);
253 // this way of drawing characters, came from the red open gl book
255 const int STROKE = 2;
258 typedef struct charpoint {
264 {0, -5, PT}, {2.5, 5, PT}, {5, -5, STROKE},
265 {0.75, -2, PT}, {4.25, -2, END}
269 {2.5, -5, PT}, {2.5,5, STROKE}, {0, 5, PT}, {5, 5, END}
273 {5, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
274 {2, -5, PT}, {3, -5, PT}, {5, -3, STROKE},
275 {2.5, -1, PT}, {5, -1,PT}, {5, -5, END}
279 {4.9, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
280 {2, -5, PT}, {3, -5, PT}, {5, -3, END}
283 CP Xdata[] = {{ 0, 5, PT}, {5, -5,STROKE},{0,-5,PT},{5, 5, END}};
284 CP Ndata[] = {{ 0, -5, PT}, {0, 5, PT}, {5, -5, PT}, {5, 5, END}};
286 //! the maximum width used for a charcter glyph
287 const int max_glyph_width = 5; // unit ( glyph_coord )
289 static void drawLetter(CP *l, GLfloat z)
291 glBegin(GL_LINE_STRIP);
295 glVertex3f(l->x, l->y, z);
298 glVertex3f(l->x, l->y, z);
300 glBegin(GL_LINE_STRIP);
303 glVertex3f(l->x, l->y, z);
308 throw runtime_error("data structure failure");
314 void GlSequence::draw_sequence(GLfloat left, GLfloat right) const
316 // FIXME: basically this needs to be greater than the number of annotations
317 const GLfloat z = 30;
319 glColor3fv(drawColor.get());
321 Sequence::const_iterator seq_itor = sequence_begin(left, right);
322 Sequence::const_iterator seq_end = sequence_end(left, right);
323 Sequence::size_type basepair = 0;
324 const float bp_per_world = 1.0; //( world coord )
325 const float glyph_x_scale = 0.125; // unit = ( world coord / glyph coord )
326 // compute how much space there should be to either size of a letter
327 const float glyph_margin = (bp_per_world - glyph_x_scale * max_glyph_width)
330 assert(seq_end - seq_itor >= 0);
331 while(seq_itor != seq_end)
333 assert ( basepair < seq->size() );
335 glTranslatef( seq_x+leftbase(left) + basepair + glyph_margin, seq_y, 1.0 );
336 glScalef(glyph_x_scale, 1.0, 1.0);
339 drawLetter(Adata, z);
342 drawLetter(Tdata, z);
345 drawLetter(Gdata, z);
348 drawLetter(Cdata, z);
351 drawLetter(Ndata, z);
354 drawLetter(Xdata, z);
363 bool operator==(const GlSequence &left, const GlSequence &right)
365 return ( (left.seq_x == right.seq_x) and
366 (left.seq_y == right.seq_y) and
367 (left.seq_z == right.seq_z) and
368 (left.seq_height == right.seq_height) and
369 (left.drawColor == right.drawColor));