TBTK
Canvas.h
Go to the documentation of this file.
1 /* Copyright 2017 Kristofer Björnson
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
23 #ifndef COM_DAFER45_TBTK_CANVAS
24 #define COM_DAFER45_TBTK_CANVAS
25 
26 #include "Streams.h"
27 #include "TBTKMacros.h"
28 
29 #include <initializer_list>
30 
31 #include <opencv2/core/core.hpp>
32 #include <opencv2/highgui/highgui.hpp>
33 
34 namespace TBTK{
35 
36 template<typename CoordinateType>
37 class Canvas{
38 public:
39  class RGBA{
40  public:
42  RGBA(char r, char g, char b, char a = 0);
43  private:
45  char r, g, b, a;
46 
47  friend class Canvas;
48  };
49 
50  class Pixel{
51  public:
53  Pixel(unsigned int x, unsigned int y);
54 
56  unsigned int x, y;
57  };
58 
60  Canvas(unsigned int width, unsigned int height);
61 
63  ~Canvas();
64 
66  void setOrigin(CoordinateType x, CoordinateType y);
67 
69  void setBasisVectors(
70  std::initializer_list<std::initializer_list<CoordinateType>> basisVectors
71  );
72 
74  void drawPixel(const RGBA &rgba, CoordinateType x, CoordinateType y);
75 
77  void drawCircle(const RGBA &rgba, CoordinateType x, CoordinateType y, CoordinateType radius);
78 
80  void save(std::string filename) const;
81 private:
83  cv::Mat data;
84 
86  CoordinateType origin[2];
87 
89  CoordinateType basisVectors[2][2];
90 
92  double norms[2];
93 
95  Pixel getPixel(CoordinateType x, CoordinateType y);
96 
98  void calculateNorms();
99 };
100 
101 template<typename CoordinateType>
103 }
104 
105 template<typename CoordinateType>
106 void Canvas<CoordinateType>::setOrigin(CoordinateType x, CoordinateType y){
107  origin[0] = x;
108  origin[1] = y;
109 }
110 
111 template<>
113  const RGBA &rgba,
114  unsigned int x,
115  unsigned int y
116 ){
117  if(x < (unsigned int)data.cols && y < (unsigned int)data.rows){
118  data.at<cv::Vec3b>(y, x)[0] = rgba.b;
119  data.at<cv::Vec3b>(y, x)[1] = rgba.g;
120  data.at<cv::Vec3b>(y, x)[2] = rgba.r;
121  }
122 }
123 
124 template<>
125 inline void Canvas<double>::drawPixel(
126  const RGBA &rgba,
127  double x,
128  double y
129 ){
130  Pixel p = getPixel(x, y);
131  if(p.x >= 0
132  && p.x < (unsigned int)data.cols
133  && p.y >= 0
134  && p.y < (unsigned int)data.rows
135  ){
136  data.at<cv::Vec3b>(p.y, p.x)[0] = rgba.b;
137  data.at<cv::Vec3b>(p.y, p.x)[1] = rgba.g;
138  data.at<cv::Vec3b>(p.y, p.x)[2] = rgba.r;
139  }
140 }
141 
142 template<>
144  const RGBA &rgba,
145  unsigned int x,
146  unsigned int y,
147  unsigned int radius
148 ){
149 // if(x < (unsigned int)data.cols && y < (unsigned int)data.rows){
150  cv::circle(data, cv::Point(x, y), radius, cv::Scalar(rgba.r, rgba.g, rgba.b), CV_FILLED, 8, 0);
151 // }
152 }
153 
154 template<>
155 inline void Canvas<double>::drawCircle(
156  const RGBA &rgba,
157  double x,
158  double y,
159  double radius
160 ){
161  Pixel p = getPixel(x, y);
162 /* if(p.x >= 0
163  && p.x < (unsigned int)data.cols
164  && p.y >= 0
165  && p.y < (unsigned int)data.rows
166  ){*/
167  cv::circle(data, cv::Point(p.x, p.y), (int)radius, cv::Scalar(rgba.r, rgba.g, rgba.b));
168 // }
169 }
170 
171 template<typename CoordinateType>
173  CoordinateType x,
174  CoordinateType y
175 ){
176  double projections[2];
177  for(unsigned int n = 0; n < 2; n++){
178  projections[n]
179  = ((double)x - (double)origin[0])*((double)basisVectors[n][0])
180  + ((double)y - (double)origin[1])*((double)basisVectors[n][1]);
181  projections[n] /= norms[n]*norms[n];
182  }
183 
184  return Pixel(data.cols*projections[0], data.rows*projections[1]);
185 }
186 
187 template<typename CoordinateType>
189  std::initializer_list<std::initializer_list<CoordinateType>> basisVectors
190 ){
191  TBTKAssert(
192  basisVectors.size() == 2,
193  "Canvas::setBasisVectors()",
194  "'basisVectors' must contain two vectors.",
195  ""
196  );
197  for(unsigned int n = 0; n < 2; n++){
198  TBTKAssert(
199  (basisVectors.begin() + n)->size() == 2,
200  "Canvas::setBasisVectors",
201  "Each basis vector must have two components, but basis"
202  << " vector " << n << " has "
203  << (basisVectors.begin() + n)->size()
204  << " components.",
205  ""
206  );
207  }
208 
209  for(unsigned int n = 0; n < 2; n++)
210  for(unsigned int c = 0; c < 2; c++)
211  this->basisVectors[n][c] = *((basisVectors.begin() + n)->begin() + c);
212 
213  calculateNorms();
214 }
215 
216 template<typename CoordinateType>
217 inline void Canvas<CoordinateType>::save(std::string filename) const{
218  imwrite(filename, data);
219 }
220 
221 template<typename CoordinateType>
222 inline Canvas<CoordinateType>::RGBA::RGBA(char r, char g, char b, char a){
223  this->r = r;
224  this->g = g;
225  this->b = b;
226  this->a = a;
227 }
228 
229 template<typename CoordinateType>
230 inline Canvas<CoordinateType>::Pixel::Pixel(unsigned int x, unsigned int y){
231  this->x = x;
232  this->y = y;
233 }
234 
235 template<typename CoordinateType>
237  for(unsigned int n = 0; n < 2; n++){
238  norms[n] = 0;
239  for(unsigned int c = 0; c < 2; c++)
240  norms[n] += basisVectors[n][c]*basisVectors[n][c];
241  norms[n] = sqrt(norms[n]);
242  }
243 }
244 
245 }; //End namespace TBTK
246 
247 #endif
void setOrigin(CoordinateType x, CoordinateType y)
Definition: Canvas.h:106
Definition: Canvas.h:37
void drawPixel(const RGBA &rgba, CoordinateType x, CoordinateType y)
Definition: Canvas.h:50
Precompiler macros.
RGBA(char r, char g, char b, char a=0)
Definition: Canvas.h:222
Definition: Canvas.h:39
~Canvas()
Definition: Canvas.h:102
Definition: ModelFactory.h:35
void save(std::string filename) const
Definition: Canvas.h:217
void setBasisVectors(std::initializer_list< std::initializer_list< CoordinateType >> basisVectors)
Definition: Canvas.h:188
void drawCircle(const RGBA &rgba, CoordinateType x, CoordinateType y, CoordinateType radius)
unsigned int x
Definition: Canvas.h:56
Pixel(unsigned int x, unsigned int y)
Definition: Canvas.h:230
Streams for TBTK output.