factor out viewport to display scaling functions
[mussa.git] / alg / glseqbrowser.hpp
1 #ifndef _GLTRACKS_H_
2 #define _GLTRACKS_H_
3 #include <boost/shared_ptr.hpp>
4
5 #include <map>
6 #include <set>
7 #include <vector>
8
9 #include "alg/annotation_colors.hpp"
10 #include "alg/sequence.hpp"
11 #include "alg/glsequence.hpp"
12 #include "alg/sequence_location.hpp"
13 #include "alg/track_region.hpp"
14
15 //! Manage rendering a collection of glSequences
16 class GlSeqBrowser
17 {
18 public:
19   GlSeqBrowser();
20   GlSeqBrowser(const GlSeqBrowser&);
21
22   //! setup the opengl canvas
23   void initializeGL();
24   //! called when our screen canvas is resized
25   void resizeGL(int width, int height);
26   //! render our scene
27   void paintGL() const;
28
29   //! select a region (using canvas coordinates)
30   void selectRegion(int top, int left, int bottom, int right);
31   //! turn off selection
32   void clearSelection();
33
34   //! border size
35   float border() const;
36
37   //! max world left coordinate
38   float left() const;
39   //! max world right coordinate
40   float right() const;
41   // return how wide is a pixel in world coordinates?
42   float get_pixel_width() const;
43
44   void setViewportCenter(float x);
45   //! return world coordinate of the left side of the viewport
46   float viewportLeft() const;
47   //! return world coordinate of the center of the viewport
48   float viewportCenter() const;
49   //! return world coordinate of the right side of the viewport
50   float viewportRight() const;
51   //! return height of the viewport in world coordinates
52   float viewportHeight() const;
53   //! return width of the viewport in world coordinates
54   float viewportWidth() const;
55   
56   //! return viewport height in pixels
57   int viewportPixelHeight() const;
58   //! return viewport width in pixels
59   int viewportPixelWidth() const;
60   
61   //! convert x axis from display to world coordinates
62   float viewportXtoWorldX(int x);
63   //! convert y axis from display to world coordinates
64   float viewportYtoWorldY(int y);
65
66   //! zoom out far enough to show the full size of the sequence
67   double zoomOut();
68   //! zoom in to a reasonable sequence view
69   double zoomToSequence();
70   //! set the current zoom level in (base pairs / pix )
71   //! its a double as zoom levels of [0.01, 1.0] make nice sequence views
72   void setZoom(double zoom_level);
73   //! returns the current zoom level as basepairs per pixel
74   double zoom() const;
75   //! center the provided path in the current viewport
76   void centerOnPath(const std::vector<int>&);
77
78   void setColorMapper(boost::shared_ptr<AnnotationColors> cm);
79   const AnnotationColorsRef colorMapper();
80
81   //! clear our tracks and connections
82   void clear();
83   //! clear everything related to a selection
84   void clear_selection();
85
86   //! add a sequence to the back of our track container (makes copy of s)
87   void push_sequence(const Sequence& s);
88   //! add a sequence to the back of our track container
89   void push_sequence(boost::shared_ptr<Sequence> s);
90   //! add a glsequence to the back of our track container
91   void push_sequence(GlSequence s);
92   //! add a glsequence to the back of our track container
93   void push_sequence(boost::shared_ptr<GlSequence> gs);
94   //! return our track container
95   const std::vector<boost::shared_ptr<GlSequence> >& sequences() const;
96
97   //! clear all the line segments between all the sequences
98   void clear_links();
99   //! define a path
100   void link(const std::vector<int>& path, const std::vector<bool>& isRC, int length);
101   //! set selected paths (it'd be nice if this could be a templated function)
102   void setSelectedPaths(std::vector<int> c);
103   //! returns the index of pathids based on order added by link
104   const std::set<int>& selectedPaths() const;
105
106   //! set selected tracks (it'd be nice if this could be a templated function)
107   void appendSelectedTrack(GLuint track_index, int left, int right);
108
109   //! return list of selected tracks
110   std::list<TrackRegion> selectedTracks() const;
111
112   //! copy sequence from selected track using formating function
113   template<class Item>
114   size_t copySelectedTracks(std::list<Item>& result, 
115              Item (*format_track)(const Sequence& s, int left, int right));
116   //! copy sequence from selected tracks as FASTA sequences
117   /*! \return number of base pairs copied
118    */
119   size_t copySelectedTracksAsFasta(std::string& copy_buffer);
120   //! copy sequence from selected tracks as a list of sequences
121   /*! \return number of base pairs copied
122    */
123   size_t copySelectedTracksAsSequences(std::list<Sequence>& result);
124   //! copy sequence from selected tracks as plain sequences
125   /*! \return number of base pairs copied
126    */
127   size_t copySelectedTracksAsString(std::string& copy_buffer);
128
129   //! copy tracks as a sequence and its coordinates
130   size_t copySelectedTracksAsSeqLocation(std::list<SequenceLocation>& result);
131   
132   
133   //! Provide a logical name for a type discriminator for our glName stack
134   enum FeatureType { MussaTrack, MussaSegment };
135
136   //! a useful point class
137   template<class T> struct point {
138     T x;
139     T y;
140
141     point(T x_, T y_):x(x_), y(y_) {}
142   };
143
144   //! a useful rectangle, where 0,0 is in the lower left
145   template<class T> struct rect {
146     T top;
147     T left;
148     T bottom;
149     T right;
150
151     rect() {}
152     rect(T t, T l, T b, T r) : top(t), left(l), bottom(b), right(r) {}
153     T width() { return right - left; }
154     T height() { return top - bottom; }
155     void clear() { top=0; left=0; bottom=0; right=0; }
156   };
157
158   struct Segment
159   {
160     point<float> start;
161     point<float> end;
162     bool reversed;
163     int length;
164     // each integer represents an index into our list of paths
165     std::set<int> path_ids;
166
167     Segment() : start(0.0, 0.0), end(0.0, 0.0), reversed(false), length(0) {}
168     Segment(float x1, float y1, float x2, float y2, bool isRC, int length_) 
169       : start(x1, y1), end(x2, y2), reversed(isRC), length(length_) {}
170   };
171
172   //! data structure holding our line segments
173   /*! the vector is of size track_container.size()-1
174    *  it's indexed by the pair x1, x2 (the two x coordinates between
175    *  the two tracks
176    */
177   typedef std::pair<int, int> segment_key;  
178   typedef std::map<segment_key, Segment> pair_segment_map;
179   typedef std::vector<pair_segment_map> path_segment_map_vector;
180   path_segment_map_vector path_segments;
181
182 private:
183   //! recalculate the viewable world
184   /*! depending on the size of our canvas, our zoom level and
185    *  how far we've been offset
186    */
187   void update_viewport(float center, double new_zoom);
188
189   //! determine where all the tracks should be placed
190   void update_layout();
191
192   //! convert opengl selections into the list of paths we should highlight
193   void processSelection(GLuint hits, 
194                         GLuint buffer[], 
195                         GLuint bufsize, 
196                         const rect<float>& r);
197
198   //! master scene drawing function
199   /*! draw is broken out for the opengl selection code
200    */
201   void draw() const;
202   //! draw glsequence tracks
203   void draw_tracks() const;
204   //! draw line segments between tracks
205   void draw_segments() const;
206   //! draw selection box
207   void draw_selection() const;
208
209   //! number of pixels to reserve around the edges of our canvas
210   const int border_width;
211   //! the current viewable region (world coord)
212   rect<float> cur_ortho;
213   //! how many pixels our viewport is (screen coord)
214   point<int> viewport_size;
215   //! the center of our current viewport (world coord) (used for scrollbar)
216   float viewport_center;
217   double zoom_level;
218   AnnotationColorsRef color_mapper;
219   //! counter for each path added to us via connect
220   int pathid;
221
222 protected:
223   //! container of all the GlSequences loaded into our scene
224   std::vector<GlSequenceRef > track_container;
225   //! where to draw our box (world coordinates)
226   rect<float> selectedRegion;
227   //! true if we have a selection
228   bool selectedMode;
229   //! indicate which paths are selected
230   std::set<int> selected_paths;
231   //! which track is selected (it only makes sense to have one track selected).
232   std::list<TrackRegion> selected_tracks;
233   typedef std::list<TrackRegion>::iterator selected_track_iterator;
234 };
235
236 inline float GlSeqBrowser::viewportXtoWorldX(int x) {
237   GLfloat x_scale = cur_ortho.width()/((float)viewport_size.x);
238   return (cur_ortho.left + (x * x_scale));
239 }
240
241 inline float GlSeqBrowser::viewportYtoWorldY(int y) {
242   GLfloat y_scale = cur_ortho.height()/((float)viewport_size.y);
243   return cur_ortho.top-(y * y_scale);
244 }
245
246 #endif