TBTK
Need a break? Support the development by playing Polarity Puzzles
Canvas.h
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 
17 
24 #ifndef COM_DAFER45_TBTK_CANVAS
25 #define COM_DAFER45_TBTK_CANVAS
26 
27 #include "Streams.h"
28 #include "TBTKMacros.h"
29 
30 #include <initializer_list>
31 
32 #include <opencv2/core/core.hpp>
33 #include <opencv2/highgui/highgui.hpp>
34 
35 namespace TBTK{
36 
37 template<typename CoordinateType>
38 class Canvas{
39 public:
40  class RGBA{
41  public:
43  RGBA(char r, char g, char b, char a = 0);
44  private:
46  char r, g, b, a;
47 
48  friend class Canvas;
49  };
50 
51  class Pixel{
52  public:
54  Pixel(unsigned int x, unsigned int y);
55 
57  unsigned int x, y;
58  };
59 
61  Canvas(unsigned int width, unsigned int height);
62 
64  ~Canvas();
65 
67  void setOrigin(CoordinateType x, CoordinateType y);
68 
70  void setBasisVectors(
71  std::initializer_list<std::initializer_list<CoordinateType>> basisVectors
72  );
73 
75  void drawPixel(const RGBA &rgba, CoordinateType x, CoordinateType y);
76 
78  void drawCircle(const RGBA &rgba, CoordinateType x, CoordinateType y, CoordinateType radius);
79 
81  void save(std::string filename) const;
82 private:
84  cv::Mat data;
85 
87  CoordinateType origin[2];
88 
90  CoordinateType basisVectors[2][2];
91 
93  double norms[2];
94 
96  Pixel getPixel(CoordinateType x, CoordinateType y);
97 
99  void calculateNorms();
100 };
101 
102 template<typename CoordinateType>
103 Canvas<CoordinateType>::~Canvas(){
104 }
105 
106 template<typename CoordinateType>
107 void Canvas<CoordinateType>::setOrigin(CoordinateType x, CoordinateType y){
108  origin[0] = x;
109  origin[1] = y;
110 }
111 
112 template<>
113 inline void Canvas<unsigned int>::drawPixel(
114  const RGBA &rgba,
115  unsigned int x,
116  unsigned int y
117 ){
118  if(x < (unsigned int)data.cols && y < (unsigned int)data.rows){
119  data.at<cv::Vec3b>(y, x)[0] = rgba.b;
120  data.at<cv::Vec3b>(y, x)[1] = rgba.g;
121  data.at<cv::Vec3b>(y, x)[2] = rgba.r;
122  }
123 }
124 
125 template<>
126 inline void Canvas<double>::drawPixel(
127  const RGBA &rgba,
128  double x,
129  double y
130 ){
131  Pixel p = getPixel(x, y);
132  if(p.x >= 0
133  && p.x < (unsigned int)data.cols
134  && p.y >= 0
135  && p.y < (unsigned int)data.rows
136  ){
137  data.at<cv::Vec3b>(p.y, p.x)[0] = rgba.b;
138  data.at<cv::Vec3b>(p.y, p.x)[1] = rgba.g;
139  data.at<cv::Vec3b>(p.y, p.x)[2] = rgba.r;
140  }
141 }
142 
143 template<>
144 inline void Canvas<unsigned int>::drawCircle(
145  const RGBA &rgba,
146  unsigned int x,
147  unsigned int y,
148  unsigned int radius
149 ){
150 // if(x < (unsigned int)data.cols && y < (unsigned int)data.rows){
151  cv::circle(data, cv::Point(x, y), radius, cv::Scalar(rgba.r, rgba.g, rgba.b), CV_FILLED, 8, 0);
152 // }
153 }
154 
155 template<>
156 inline void Canvas<double>::drawCircle(
157  const RGBA &rgba,
158  double x,
159  double y,
160  double radius
161 ){
162  Pixel p = getPixel(x, y);
163 /* if(p.x >= 0
164  && p.x < (unsigned int)data.cols
165  && p.y >= 0
166  && p.y < (unsigned int)data.rows
167  ){*/
168  cv::circle(data, cv::Point(p.x, p.y), (int)radius, cv::Scalar(rgba.r, rgba.g, rgba.b));
169 // }
170 }
171 
172 template<typename CoordinateType>
173 inline typename Canvas<CoordinateType>::Pixel Canvas<CoordinateType>::getPixel(
174  CoordinateType x,
175  CoordinateType y
176 ){
177  double projections[2];
178  for(unsigned int n = 0; n < 2; n++){
179  projections[n]
180  = ((double)x - (double)origin[0])*((double)basisVectors[n][0])
181  + ((double)y - (double)origin[1])*((double)basisVectors[n][1]);
182  projections[n] /= norms[n]*norms[n];
183  }
184 
185  return Pixel(data.cols*projections[0], data.rows*projections[1]);
186 }
187 
188 template<typename CoordinateType>
189 inline void Canvas<CoordinateType>::setBasisVectors(
190  std::initializer_list<std::initializer_list<CoordinateType>> basisVectors
191 ){
192  TBTKAssert(
193  basisVectors.size() == 2,
194  "Canvas::setBasisVectors()",
195  "'basisVectors' must contain two vectors.",
196  ""
197  );
198  for(unsigned int n = 0; n < 2; n++){
199  TBTKAssert(
200  (basisVectors.begin() + n)->size() == 2,
201  "Canvas::setBasisVectors",
202  "Each basis vector must have two components, but basis"
203  << " vector " << n << " has "
204  << (basisVectors.begin() + n)->size()
205  << " components.",
206  ""
207  );
208  }
209 
210  for(unsigned int n = 0; n < 2; n++)
211  for(unsigned int c = 0; c < 2; c++)
212  this->basisVectors[n][c] = *((basisVectors.begin() + n)->begin() + c);
213 
214  calculateNorms();
215 }
216 
217 template<typename CoordinateType>
218 inline void Canvas<CoordinateType>::save(std::string filename) const{
219  imwrite(filename, data);
220 }
221 
222 template<typename CoordinateType>
223 inline Canvas<CoordinateType>::RGBA::RGBA(char r, char g, char b, char a){
224  this->r = r;
225  this->g = g;
226  this->b = b;
227  this->a = a;
228 }
229 
230 template<typename CoordinateType>
231 inline Canvas<CoordinateType>::Pixel::Pixel(unsigned int x, unsigned int y){
232  this->x = x;
233  this->y = y;
234 }
235 
236 template<typename CoordinateType>
237 inline void Canvas<CoordinateType>::calculateNorms(){
238  for(unsigned int n = 0; n < 2; n++){
239  norms[n] = 0;
240  for(unsigned int c = 0; c < 2; c++)
241  norms[n] += basisVectors[n][c]*basisVectors[n][c];
242  norms[n] = sqrt(norms[n]);
243  }
244 }
245 
246 }; //End namespace TBTK
247 
248 #endif
249 
Precompiler macros.
Definition: Boolean.h:32
Streams for TBTK output.
Array< DataType > sqrt(const Array< DataType > &array)
Definition: ArrayAlgorithms.h:831