Bridges-C++  3.4.5-dev1-6-g935685a
Bridges(C++ API)
Symbol.h
Go to the documentation of this file.
1 
2 #ifndef SYMBOL_H
3 
4 #define SYMBOL_H
5 
6 #include <string>
7 #include <vector>
8 #include <cmath>
9 
10 using namespace std;
11 
12 #include "DataStructure.h"
13 #include "Color.h"
14 
15 namespace bridges {
16  namespace datastructure {
31  class Symbol {
32 
33  private:
34 
35  static int ids;
36 
37  int identifier;
38 
39  string name = string();
40 
41  // maintain ids for symbols
42 
43  // symbol attributes
44 
45  Color *fillColor = nullptr;
46  Color *strokeColor = nullptr;
47  float *strokeWidth = nullptr;
48  int* strokeDash = nullptr;
49  float *opacity = nullptr;
50  int *layer = nullptr;
51 
52  // use this flag to refrain from putting it into the JSON
53  // as its the default
54  bool xform_flag = false;
55 
56  // 2D affine transform matrix for the symbol
57  float xform[3][3] = {
58  {1., 0., 0.},
59  {0., 1., 0.},
60  {0., 0., 1.}
61  };
62 
63  // matrix methods used for affine transformations on symbols
64  void matMult (float m1[][3], float m2[][3], float result[][3])
65  const {
66  for (int i = 0; i < 3; ++i) {
67  for (int j = 0; j < 3; ++j) {
68  result[i][j] = 0.;
69  for (int k = 0; k < 3; ++k) {
70  result[i][j] += m1[i][k] * m2[k][j];
71  }
72  }
73  }
74  }
75  void identity(float m[][3]) {
76  for (int i = 0; i < 3; ++i)
77  for (int j = 0; j < 3; ++j)
78  m[i][j] = (i == j) ? 1. : 0.;
79  }
80 
81  void copyMat(float m[][3], float copy[][3]) {
82  for (int i = 0; i < 3; ++i)
83  for (int j = 0; j < 3; ++j)
84  copy[i][j] = m[i][j];
85  }
86  void printMat(float m[][3]) {
87  for (int i = 0; i < 3; ++i) {
88  for (int j = 0; j < 3; ++j)
89  cout << m[i][j] << ", ";
90  cout << "\n";
91  }
92  }
93 
94  void clear_optional() {
95  if (fillColor) {
96  delete fillColor;
97  fillColor = nullptr;
98  }
99  if (strokeColor) {
100  delete strokeColor;
101  strokeColor = nullptr;
102  }
103  if (strokeWidth) {
104  delete strokeWidth;
105  strokeWidth = nullptr;
106  }
107  if (strokeDash) {
108  delete strokeDash;
109  strokeDash = nullptr;
110  }
111  if (opacity) {
112  delete opacity;
113  opacity = nullptr;
114  }
115  if (layer) {
116  delete layer;
117  layer = nullptr;
118  }
119  }
120 
121  public:
122 
126  Symbol() :
127  fillColor(nullptr),
128  strokeColor(nullptr),
129  strokeWidth(nullptr),
130  strokeDash(nullptr),
131  opacity(nullptr),
132  layer(nullptr) {
133 
134  identifier = ids;
135  xform_flag = false;
136 
137  // set id for symbol
138  ids++;
139  }
140 
141  Symbol(const Symbol& s)
142  : identifier(s.identifier), name(s.name), xform_flag (s.xform_flag) {
143  xform[0][0] = s.xform[0][0];
144  xform[0][1] = s.xform[0][1];
145  xform[0][2] = s.xform[0][2];
146  xform[1][0] = s.xform[1][0];
147  xform[1][1] = s.xform[1][1];
148  xform[1][2] = s.xform[1][2];
149  xform[2][0] = s.xform[2][0];
150  xform[2][1] = s.xform[2][1];
151  xform[2][2] = s.xform[2][2];
152 
153  if (s.fillColor)
154  this->fillColor = new Color(*(s.fillColor));
155  if (s.strokeColor)
156  this->strokeColor = new Color(*(s.strokeColor));
157  if (s.strokeWidth)
158  this->strokeWidth = new float(*(s.strokeWidth));
159  if (s.strokeDash)
160  this->strokeDash = new int(*(s.strokeDash));
161  if (s.opacity)
162  this->opacity = new float(*(s.opacity));
163  if (s.layer)
164  this->layer = new int(*(s.layer));
165 
166  }
167 
168  Symbol& operator= (const Symbol& s) {
169  clear_optional();
170 
171  this->identifier = s.identifier;
172  this->name = s.name;
173  this->xform_flag = s.xform_flag;
174  xform[0][0] = s.xform[0][0];
175  xform[0][1] = s.xform[0][1];
176  xform[0][2] = s.xform[0][2];
177  xform[1][0] = s.xform[1][0];
178  xform[1][1] = s.xform[1][1];
179  xform[1][2] = s.xform[1][2];
180  xform[2][0] = s.xform[2][0];
181  xform[2][1] = s.xform[2][1];
182  xform[2][2] = s.xform[2][2];
183 
184  if (s.fillColor)
185  this->fillColor = new Color(*(s.fillColor));
186  if (s.strokeColor)
187  this->strokeColor = new Color(*(s.strokeColor));
188  if (s.strokeWidth)
189  this->strokeWidth = new float(*(s.strokeWidth));
190  if (s.strokeDash)
191  this->strokeDash = new int(*(s.strokeDash));
192  if (s.opacity)
193  this->opacity = new float(*(s.opacity));
194  if (s.layer)
195  this->layer = new int(*(s.layer));
196 
197  return *this;
198  }
199 
201  clear_optional();
202  }
203 
207  virtual const string getSymbolRepresentation() const = 0;
208 
217  int getIdentifier() const {
218  return identifier;
219  }
220 
227  if (!fillColor)
228  fillColor = new Color;
229 
230  *fillColor = c;
231 
232  return *this;
233  }
239  Symbol& setFillColor(string c) {
240  if (!fillColor)
241  fillColor = new Color;
242 
243  *fillColor = Color(c);
244 
245  return *this;
246  }
252  Color getFillColor() const {
253  if (!fillColor)
254  throw "Fill color was not set!";
255  else
256  return *fillColor;
257  }
258 
265  if (!strokeColor)
266  strokeColor = new Color;
267 
268  *strokeColor = c;
269 
270  return *this;
271  }
272 
278  Symbol& setStrokeColor(string c) {
279  if (!strokeColor)
280  strokeColor = new Color;
281 
282  *strokeColor = Color(c);
283 
284  return *this;
285  }
286 
293  if (!strokeColor)
294  throw "Stroke color was not set!";
295  else
296  return *strokeColor;
297  }
298 
304  Symbol& setStrokeWidth(float strk_width) {
305  if (!strokeWidth)
306  strokeWidth = new float;
307 
308  if (strk_width < 0.0f)
309  throw "Stroke width must be positive or null";
310  else
311  *strokeWidth = strk_width;
312 
313  return *this;
314  }
315 
321  float getStrokeWidth() const {
322  if (!strokeWidth)
323  throw "Stroke width not set!";
324 
325  return *strokeWidth;
326  }
327 
333  Symbol& setOpacity(float op) {
334  if (!opacity)
335  opacity = new float;
336 
337  if (op < 0.0f || op > 1.0f)
338  throw "Opacity must be between 0 and 1";
339  else
340  *opacity = op;
341 
342  return *this;
343  }
344 
350  float getOpacity() const {
351  if (!opacity)
352  throw "Opacity not set!";
353 
354  return *opacity;
355  }
356 
362  Symbol& setStrokeDash(int dash) {
363  if (!strokeDash)
364  strokeDash = new int;
365 
366  if (dash < 0 || dash > 10)
367  throw "Dash must be between 0 and 10 (inclusive)";
368  else
369  *strokeDash = dash;
370 
371  return *this;
372  }
373 
379  int getStrokeDash() const {
380  if (!strokeDash)
381  throw "Stroke dash not set!";
382 
383  return *strokeDash;
384  }
385 
392  Symbol& setLayer(int l) {
393  if (!layer)
394  layer = new int;
395 
396  *layer = l;
397 
398  return *this;
399  }
400 
407  int getLayer() const {
408  return *layer;
409  }
410 
411  protected:
417  virtual string getShapeType() const = 0;
418 
419  public:
427  Symbol& translate (float tx, float ty) {
428  float result[3][3];
429  float transl[3][3] = {
430  {1., 0., tx}, {0., 1., ty}, {0., 0., 1.}
431  };
432 
433  // update current transform matrix
434  matMult (transl, xform, result);
435  copyMat (result, xform);
436 
437  xform_flag = true;
438 
439  return *this;
440  }
441 
448  Symbol& scale(float sx, float sy) {
449  float result[3][3];
450  float scale[3][3] = {
451  {sx, 0., 0.}, {0., sy, 0.}, {0., 0., 1.}
452  };
453 
454  // update current transform matrix
455  matMult (scale, xform, result);
456  copyMat (result, xform);
457 
458  xform_flag = true;
459 
460  return *this;
461  }
462 
469  Symbol& scale(float scalefactor) {
470  return scale(scalefactor, scalefactor);
471  }
472 
480  Symbol& rotate(float angle) {
481  // compute sin, cos
482  float angle_r = angle * M_PI / 180.;
483  float c = cos(angle_r);
484  float s = sin(angle_r);
485 
486  // form the rotation matrix
487  float result[3][3];
488  float rotation[3][3] = {
489  {c, -s, 0.}, {s, c, 0.}, {0., 0., 1.}
490  };
491 
492  // update current transform matrix
493  matMult (rotation, xform, result);
494  copyMat (result, xform);
495 
496  xform_flag = true;
497 
498  return *this;
499  }
500 
509  Symbol& scale(float sx, float sy, float px, float py) {
510  float result[3][3], result2[3][3];
511  float scale[3][3] = {
512  {sx, 0., 0.}, {0., sy, 0.}, {0., 0., 1.}
513  };
514  float transl1[3][3] =
515  { {1., 0., -px}, {0., 1., -py}, {0., 0., 1.} };
516  float transl2[3][3] =
517  { {1., 0., px}, {0., 1., py}, {0., 0., 1.} };
518 
519  // form the composite transform
520  matMult (scale, transl1, result);
521  matMult (transl2, result, result2);
522 
523  // update current transform matrix
524  matMult (result2, xform, result);
525  copyMat (result, xform);
526 
527  xform_flag = true;
528 
529  return *this;
530  }
531 
539  Symbol& rotate(float angle, float px, float py) {
540  // compute sin, cos
541  float angle_r = angle * M_PI / 180.;
542  float c = cos(angle_r);
543  float s = sin(angle_r);
544 
545  // form the rotation matrix
546  float result[3][3], result2[3][3];
547  float rotation[3][3] = {
548  {c, -s, 0.}, {s, c, 0.}, {0., 0., 1.}
549  };
550  float transl1[3][3] = {
551  {1., 0., -px}, {0., 1., -py}, {0., 0., 1.}
552  };
553  float transl2[3][3] = {
554  {1., 0., px}, {0., 1., py}, {0., 0., 1.}
555  };
556 
557  // form the composite transform
558  matMult (rotation, transl1, result);
559  matMult (transl2, result, result2);
560 
561  // update current transform matrix
562  matMult (result2, xform, result);
563  copyMat (result, xform);
564 
565  xform_flag = true;
566 
567  return *this;
568  }
575  Symbol& setTransform(float a, float b, float c,
576  float d, float e, float f) {
577  xform[0][0] = a;
578  xform[1][0] = b;
579  xform[0][1] = c;
580  xform[1][1] = d;
581  xform[0][2] = e;
582  xform[2][2] = f;
583  xform[2][0] = 0.0f;
584  xform[2][1] = 0.0f;
585  xform[2][2] = 1.0f;
586 
587  xform_flag = true;
588 
589  return *this;
590  }
591 
592  protected:
593 
602  const string getSymbolAttributeRepresentation() const {
603 
604  // first get all the non-geometric attributes
605 
607 
608  string symbol_attr_json = OPEN_CURLY;
609 
610  symbol_attr_json += QUOTE + "type" + QUOTE + COLON +
611  QUOTE + getShapeType() + QUOTE + COMMA +
612  QUOTE + "ID" + QUOTE + COLON +
613  QUOTE + to_string(identifier) + QUOTE + COMMA;
614 
615  // check transform, if it is not set, ignore
616  if (this->xform_flag) {
617  symbol_attr_json +=
618  QUOTE + "transform" + QUOTE + COLON +
619  OPEN_BOX +
620  JSONencode(this->xform[0][0]) + COMMA +
621  JSONencode(this->xform[1][0]) + COMMA +
622  JSONencode(this->xform[0][1]) + COMMA +
623  JSONencode(this->xform[1][1]) + COMMA +
624  JSONencode(this->xform[0][2]) + COMMA +
625  JSONencode(this->xform[1][2]) +
626  CLOSE_BOX + COMMA;
627  }
628  if (layer) {
629  symbol_attr_json += QUOTE + "layer" + QUOTE +
630  COLON + to_string(*layer) + COMMA;
631  }
632 
633  // the above attributes are all that is needed for 'group'
634  // type, rest also include the following
635  if (getShapeType() == "group") {
636  // remove the last comma
637  symbol_attr_json.erase (symbol_attr_json.size() - 1);
638  symbol_attr_json += CLOSE_CURLY;
639  }
640  else {
641 
642  if (fillColor) {
643  symbol_attr_json += QUOTE + "fill-color" +
644  QUOTE + COLON + fillColor->getCSSRepresentation()
645  + COMMA;
646  }
647 
648  if (opacity) {
649  symbol_attr_json += QUOTE + "opacity" + QUOTE + COLON +
650  to_string(*opacity) + COMMA;
651  }
652 
653  if (strokeColor) {
654  symbol_attr_json += QUOTE + "stroke-color" + QUOTE +
655  COLON + strokeColor->getCSSRepresentation() + COMMA;
656  }
657 
658  if (strokeWidth) {
659  symbol_attr_json += QUOTE + "stroke-width" + QUOTE +
660  COLON + to_string(*strokeWidth) + COMMA;
661  }
662 
663  if (strokeDash) {
664  symbol_attr_json += QUOTE + "stroke-dasharray" + QUOTE +
665  COLON + to_string(*strokeDash) + COMMA;
666  }
667  }
668 
669  return symbol_attr_json;
670  }
671  };
672 
673  // initialize the id to start at zero
674  int Symbol::ids = 0;
675  }
676 } // namespace bridges
677 
678 #endif
#define M_PI
Definition: OSMData.h:12
This class represents Color, and supports rgba, hexadecimal and named color values.
Definition: Color.h:50
const string getCSSRepresentation() const
Definition: Color.h:403
This is an abstract class for deriving a number of Symbol shape objects, for use in a SymbolCollectio...
Definition: Symbol.h:31
float getStrokeWidth() const
This method gets stroke width.
Definition: Symbol.h:321
Symbol & setStrokeColor(Color c)
Definition: Symbol.h:264
Symbol & setTransform(float a, float b, float c, float d, float e, float f)
Definition: Symbol.h:575
Symbol & setLayer(int l)
Definition: Symbol.h:392
int getStrokeDash() const
This method gets stroke dash level.
Definition: Symbol.h:379
virtual string getShapeType() const =0
float getOpacity() const
This method gets symbol opacity.
Definition: Symbol.h:350
Symbol & setFillColor(Color c)
Set the symbol fill color.
Definition: Symbol.h:226
Symbol & translate(float tx, float ty)
Translate a 2D point.
Definition: Symbol.h:427
Symbol & scale(float sx, float sy)
Scale a Symbol.
Definition: Symbol.h:448
int getLayer() const
Definition: Symbol.h:407
Symbol & scale(float scalefactor)
Scale a Symbol.
Definition: Symbol.h:469
int getIdentifier() const
return the symbol identifier.
Definition: Symbol.h:217
Symbol & setOpacity(float op)
This method sets the symbol opacity.
Definition: Symbol.h:333
Symbol()
default constructor
Definition: Symbol.h:126
Symbol & rotate(float angle, float px, float py)
Rotate a 2D point about an arbitrary point (px, py)
Definition: Symbol.h:539
Symbol & setStrokeColor(string c)
This method sets the symbol stroke color.
Definition: Symbol.h:278
~Symbol()
Definition: Symbol.h:200
Symbol & setStrokeWidth(float strk_width)
This method sets the symbol stroke width.
Definition: Symbol.h:304
virtual const string getSymbolRepresentation() const =0
Virtual method to get the JSON representation of the symbol.
Symbol & rotate(float angle)
Rotate a 2D point (about Z)
Definition: Symbol.h:480
Color getFillColor() const
This method gets fill color.
Definition: Symbol.h:252
Color getStrokeColor()
This method gets stroke color.
Definition: Symbol.h:292
Symbol(const Symbol &s)
Definition: Symbol.h:141
const string getSymbolAttributeRepresentation() const
Get the JSON of the symbol representation.
Definition: Symbol.h:602
Symbol & setFillColor(string c)
This method sets the symbol fill color.
Definition: Symbol.h:239
Symbol & setStrokeDash(int dash)
This method sets the stroke dash level.
Definition: Symbol.h:362
Symbol & scale(float sx, float sy, float px, float py)
Scale about an arbitrary point (px, py)
Definition: Symbol.h:509
std::string JSONencode(const T &d)
Definition: JSONutil.h:38
Support for drawing Bar charts.
Definition: alltypes.h:4
const string COLON
Definition: DataStructure.h:52
const string OPEN_BOX
Definition: DataStructure.h:55
const string COMMA
Definition: DataStructure.h:51
const string OPEN_CURLY
Definition: DataStructure.h:53
const string CLOSE_BOX
Definition: DataStructure.h:56
const string CLOSE_CURLY
Definition: DataStructure.h:54
const string QUOTE
Definition: DataStructure.h:50