Bridges-C++  3.4.2
Bridges(C++ API)
Symbol.h
Go to the documentation of this file.
1 
2 #ifndef SYMBOL_H
3 
4 #define SYMBOL_H
5 
6 
7 #include <string>
8 #include <vector>
9 #include <cmath>
10 
11 using namespace std;
12 
13 #include "DataStructure.h"
14 #include "Color.h"
15 
16 namespace bridges {
17  namespace datastructure {
32  class Symbol {
33 
34  private:
35 
36  static int ids;
37 
38  int identifier;
39 
40  string name = string();
41 
42  // maintain ids for symbols
43 
44  // symbol attributes
45 
46  Color *fillColor = nullptr;
47  Color *strokeColor = nullptr;
48  float *strokeWidth = nullptr;
49  int* strokeDash = nullptr;
50  float *opacity = nullptr;
51  int *layer = nullptr;
52 
53 
54  // use this flag to refrain from putting it into the JSON
55  // as its the default
56  bool xform_flag = false;
57 
58  // 2D affine transform matrix for the symbol
59  float xform[3][3] = {
60  {1., 0., 0.},
61  {0., 1., 0.},
62  {0., 0., 1.}
63  };
64 
65 
66 
67  // matrix methods used for affine transformations on symbols
68  void matMult (float m1[][3], float m2[][3], float result[][3])
69  const {
70  for (int i = 0; i < 3; ++i) {
71  for (int j = 0; j < 3; ++j) {
72  result[i][j] = 0.;
73  for (int k = 0; k < 3; ++k) {
74  result[i][j] += m1[i][k] * m2[k][j];
75  }
76  }
77  }
78  }
79  void identity(float m[][3]) {
80  for (int i = 0; i < 3; ++i)
81  for (int j = 0; j < 3; ++j)
82  m[i][j] = (i == j) ? 1. : 0.;
83  }
84 
85  void copyMat(float m[][3], float copy[][3]) {
86  for (int i = 0; i < 3; ++i)
87  for (int j = 0; j < 3; ++j)
88  copy[i][j] = m[i][j];
89  }
90  void printMat(float m[][3]) {
91  for (int i = 0; i < 3; ++i) {
92  for (int j = 0; j < 3; ++j)
93  cout << m[i][j] << ", ";
94  cout << "\n";
95  }
96  }
97 
98  void clear_optional() {
99  if (fillColor) {
100  delete fillColor;
101  fillColor = nullptr;
102  }
103  if (strokeColor) {
104  delete strokeColor;
105  strokeColor = nullptr;
106  }
107  if (strokeWidth) {
108  delete strokeWidth;
109  strokeWidth = nullptr;
110  }
111  if (strokeDash) {
112  delete strokeDash;
113  strokeDash = nullptr;
114  }
115  if (opacity) {
116  delete opacity;
117  opacity = nullptr;
118  }
119  if (layer) {
120  delete layer;
121  layer = nullptr;
122  }
123  }
124 
125  public:
126 
130  Symbol() :
131  fillColor(nullptr),
132  strokeColor(nullptr),
133  strokeWidth(nullptr),
134  strokeDash(nullptr),
135  opacity(nullptr),
136  layer(nullptr) {
137 
138  identifier = ids;
139  xform_flag = false;
140 
141  // set id for symbol
142  ids++;
143  }
144 
145  Symbol(const Symbol& s)
146  :identifier(s.identifier), name(s.name), xform_flag (s.xform_flag) {
147  xform[0][0] = s.xform[0][0]; xform[0][1] = s.xform[0][1]; xform[0][2] = s.xform[0][2];
148  xform[1][0] = s.xform[1][0]; xform[1][1] = s.xform[1][1]; xform[1][2] = s.xform[1][2];
149  xform[2][0] = s.xform[2][0]; xform[2][1] = s.xform[2][1]; xform[2][2] = s.xform[2][2];
150 
151  if (s.fillColor) this->fillColor = new Color(*(s.fillColor));
152  if (s.strokeColor) this->strokeColor = new Color(*(s.strokeColor));
153  if (s.strokeWidth) this->strokeWidth = new float(*(s.strokeWidth));
154  if (s.strokeDash) this->strokeDash = new int(*(s.strokeDash));
155  if (s.opacity) this->opacity = new float(*(s.opacity));
156  if (s.layer) this->layer = new int(*(s.layer));
157 
158  }
159 
160  Symbol& operator= (const Symbol& s) {
161  clear_optional();
162 
163  this->identifier = s.identifier;
164  this->name = s.name;
165  this->xform_flag = s.xform_flag;
166  xform[0][0] = s.xform[0][0]; xform[0][1] = s.xform[0][1]; xform[0][2] = s.xform[0][2];
167  xform[1][0] = s.xform[1][0]; xform[1][1] = s.xform[1][1]; xform[1][2] = s.xform[1][2];
168  xform[2][0] = s.xform[2][0]; xform[2][1] = s.xform[2][1]; xform[2][2] = s.xform[2][2];
169 
170  if (s.fillColor) this->fillColor = new Color(*(s.fillColor));
171  if (s.strokeColor) this->strokeColor = new Color(*(s.strokeColor));
172  if (s.strokeWidth) this->strokeWidth = new float(*(s.strokeWidth));
173  if (s.strokeDash) this->strokeDash = new int(*(s.strokeDash));
174  if (s.opacity) this->opacity = new float(*(s.opacity));
175  if (s.layer) this->layer = new int(*(s.layer));
176 
177  return *this;
178  }
179 
180 
181 
183  clear_optional();
184  }
185 
189  virtual const string getSymbolRepresentation() const = 0;
190 
199  int getIdentifier() const {
200  return identifier;
201  }
202 
209  if (!fillColor)
210  fillColor = new Color;
211 
212  *fillColor = c;
213 
214  return *this;
215  }
221  Symbol& setFillColor(string c) {
222  if (!fillColor)
223  fillColor = new Color;
224 
225  *fillColor = Color(c);
226 
227  return *this;
228  }
234  Color getFillColor() const {
235  if (!fillColor)
236  throw "Fill color was not set!";
237  else
238  return *fillColor;
239  }
240 
247  if (!strokeColor)
248  strokeColor = new Color;
249 
250  *strokeColor = c;
251 
252  return *this;
253  }
254 
260  Symbol& setStrokeColor(string c) {
261  if (!strokeColor)
262  strokeColor = new Color;
263 
264  *strokeColor = Color(c);
265 
266  return *this;
267  }
268 
275  if (!strokeColor)
276  throw "Stroke color was not set!";
277  else
278  return *strokeColor;
279  }
280 
286  Symbol& setStrokeWidth(float strk_width) {
287  if (!strokeWidth)
288  strokeWidth = new float;
289 
290  if (strk_width < 0.0f)
291  throw "Stroke width must be positive or null";
292  else
293  *strokeWidth = strk_width;
294 
295  return *this;
296  }
297 
303  float getStrokeWidth() const {
304  if (!strokeWidth)
305  throw "Stroke width not set!";
306 
307  return *strokeWidth;
308  }
309 
315  Symbol& setOpacity(float op) {
316  if (!opacity)
317  opacity = new float;
318 
319  if (op < 0.0f || op > 1.0f)
320  throw "Opacity must be between 0 and 1";
321  else
322  *opacity = op;
323 
324  return *this;
325  }
326 
332  float getOpacity() const {
333  if (!opacity)
334  throw "Opacity not set!";
335 
336  return *opacity;
337  }
338 
344  Symbol& setStrokeDash(int dash) {
345  if (!strokeDash)
346  strokeDash = new int;
347 
348  if (dash < 0 || dash > 10)
349  throw "Dash must be between 0 and 10 (inclusive)";
350  else
351  *strokeDash = dash;
352 
353  return *this;
354  }
355 
361  int getStrokeDash() const {
362  if (!strokeDash)
363  throw "Stroke dash not set!";
364 
365  return *strokeDash;
366  }
367 
374  Symbol& setLayer(int l) {
375  if (!layer)
376  layer = new int;
377 
378  *layer = l;
379 
380  return *this;
381  }
382 
389  int getLayer() const {
390  return *layer;
391  }
392 
393 
394 
395  protected:
401  virtual string getShapeType() const = 0;
402 
403  public:
411  Symbol& translate (float tx, float ty) {
412  float result[3][3];
413  float transl[3][3] = {
414  {1., 0., tx}, {0., 1., ty}, {0., 0., 1.}
415  };
416 
417  // update current transform matrix
418  matMult (xform, transl, result);
419  copyMat (result, xform);
420 
421  xform_flag = true;
422 
423  return *this;
424  }
425 
432  Symbol& scale(float sx, float sy) {
433  float result[3][3];
434  float scale[3][3] = {
435  {sx, 0., 0.}, {0., sy, 0.}, {0., 0., 1.}
436  };
437 
438  // update current transform matrix
439  matMult (xform, scale, result);
440  copyMat (result, xform);
441 
442  xform_flag = true;
443 
444  return *this;
445  }
446 
453  Symbol& scale(float scalefactor) {
454  return scale(scalefactor, scalefactor);
455  }
456 
457 
465  Symbol& rotate(float angle) {
466  // compute sin, cos
467  float angle_r = angle * M_PI / 180.;
468  float c = cos(angle_r);
469  float s = sin(angle_r);
470 
471  // form the rotation matrix
472  float result[3][3];
473  float rotation[3][3] = {
474  {c, -s, 0.}, {s, c, 0.}, {0., 0., 1.}
475  };
476 
477  // update current transform matrix
478  matMult (xform, rotation, result);
479  copyMat (result, xform);
480 
481  xform_flag = true;
482 
483  return *this;
484  }
485 
494  Symbol& scale(float sx, float sy, float px, float py) {
495  float result[3][3], result2[3][3];
496  float scale[3][3] = {
497  {sx, 0., 0.}, {0., sy, 0.}, {0., 0., 1.}
498  };
499  float transl1[3][3] =
500  { {1., 0., -px}, {0., 1., -py}, {0., 0., 1.} };
501  float transl2[3][3] =
502  { {1., 0., px}, {0., 1., py}, {0., 0., 1.} };
503 
504  // form the composite transform
505  matMult (scale, transl1, result);
506  matMult (transl2, result, result2);
507 
508  // update current transform matrix
509  matMult (xform, result2, result);
510  copyMat (result, xform);
511 
512  xform_flag = true;
513 
514  return *this;
515  }
516 
524  Symbol& rotate(float angle, float px, float py) {
525  // compute sin, cos
526  float angle_r = angle * M_PI / 180.;
527  float c = cos(angle_r);
528  float s = sin(angle_r);
529 
530  // form the rotation matrix
531  float result[3][3], result2[3][3];
532  float rotation[3][3] = {
533  {c, -s, 0.}, {s, c, 0.}, {0., 0., 1.}
534  };
535  float transl1[3][3] = {
536  {1., 0., -px}, {0., 1., -py}, {0., 0., 1.}
537  };
538  float transl2[3][3] = {
539  {1., 0., px}, {0., 1., py}, {0., 0., 1.}
540  };
541 
542  // form the composite transform
543  matMult (rotation, transl1, result);
544  matMult (transl2, result, result2);
545 
546  // update current transform matrix
547  matMult (xform, result2, result);
548  copyMat (result, xform);
549 
550  xform_flag = true;
551 
552  return *this;
553  }
560  Symbol& setTransform(float a, float b, float c,
561  float d, float e, float f) {
562  xform[0][0] = a; xform[1][0] = b;
563  xform[0][1] = c; xform[1][1] = d;
564  xform[0][2] = e; xform[2][2] = f;
565  xform[2][0] = 0.0f; xform[2][1] = 0.0f; xform[2][2] = 1.0f;
566 
567  xform_flag = true;
568 
569  return *this;
570  }
571 
572  protected:
573 
582  const string getSymbolAttributeRepresentation() const {
583 
584  // first get all the non-geometric attributes
585 
587 
588  string symbol_attr_json = OPEN_CURLY;
589 
590  symbol_attr_json += QUOTE + "type" + QUOTE + COLON +
591  QUOTE + getShapeType() + QUOTE + COMMA +
592  QUOTE + "ID" + QUOTE + COLON +
593  QUOTE + to_string(identifier) + QUOTE + COMMA;
594 
595  // check transform, if it is not set, ignore
596  if (this->xform_flag) {
597  symbol_attr_json +=
598  QUOTE + "transform" + QUOTE + COLON +
599  OPEN_BOX +
600  JSONencode(this->xform[0][0]) + COMMA +
601  JSONencode(this->xform[1][0]) + COMMA +
602  JSONencode(this->xform[0][1]) + COMMA +
603  JSONencode(this->xform[1][1]) + COMMA +
604  JSONencode(this->xform[0][2]) + COMMA +
605  JSONencode(this->xform[1][2]) +
606  CLOSE_BOX + COMMA;
607  }
608  if (layer) {
609  symbol_attr_json += QUOTE + "layer" + QUOTE +
610  COLON + to_string(*layer) + COMMA;
611  }
612 
613  // the above attributes are all that is needed for 'group'
614  // type, rest also include the following
615  if (getShapeType() == "group") {
616  // remove the last comma
617  symbol_attr_json.erase (symbol_attr_json.size() -1);
618  symbol_attr_json += CLOSE_CURLY;
619  }
620  else {
621 
622  if (fillColor) {
623  symbol_attr_json += QUOTE + "fill-color" +
624  QUOTE + COLON + fillColor->getCSSRepresentation()
625  + COMMA;
626  }
627 
628  if (opacity) {
629  symbol_attr_json += QUOTE + "opacity" + QUOTE + COLON +
630  to_string(*opacity) + COMMA;
631  }
632 
633  if (strokeColor) {
634  symbol_attr_json += QUOTE + "stroke-color" + QUOTE +
635  COLON + strokeColor->getCSSRepresentation() + COMMA;
636  }
637 
638  if (strokeWidth) {
639  symbol_attr_json += QUOTE + "stroke-width" + QUOTE +
640  COLON + to_string(*strokeWidth) + COMMA;
641  }
642 
643  if (strokeDash) {
644  symbol_attr_json += QUOTE + "stroke-dasharray" + QUOTE +
645  COLON + to_string(*strokeDash) + COMMA;
646  }
647  }
648 
649  return symbol_attr_json;
650  }
651  };
652 
653  // initialize the id to start at zero
654  int Symbol::ids = 0;
655  }
656 } // namespace bridges
657 
658 #endif
#define M_PI
Definition: OSMData.h:13
This class represents Color, and supports rgba, hexadecimal and named color values.
Definition: Color.h:51
const string getCSSRepresentation() const
Definition: Color.h:404
This is an abstract class for deriving a number of Symbol shape objects, for use in a SymbolCollectio...
Definition: Symbol.h:32
float getStrokeWidth() const
This method gets stroke width.
Definition: Symbol.h:303
Symbol & setStrokeColor(Color c)
Definition: Symbol.h:246
Symbol & setTransform(float a, float b, float c, float d, float e, float f)
Definition: Symbol.h:560
Symbol & setLayer(int l)
Definition: Symbol.h:374
int getStrokeDash() const
This method gets stroke dash level.
Definition: Symbol.h:361
virtual string getShapeType() const =0
float getOpacity() const
This method gets symbol opacity.
Definition: Symbol.h:332
Symbol & setFillColor(Color c)
Set the symbol fill color.
Definition: Symbol.h:208
Symbol & translate(float tx, float ty)
Translate a 2D point.
Definition: Symbol.h:411
Symbol & scale(float sx, float sy)
Scale a Symbol.
Definition: Symbol.h:432
int getLayer() const
Definition: Symbol.h:389
Symbol & scale(float scalefactor)
Scale a Symbol.
Definition: Symbol.h:453
int getIdentifier() const
return the symbol identifier.
Definition: Symbol.h:199
Symbol & setOpacity(float op)
This method sets the symbol opacity.
Definition: Symbol.h:315
Symbol()
default constructor
Definition: Symbol.h:130
Symbol & rotate(float angle, float px, float py)
Rotate a 2D point about an arbitrary point (px, py)
Definition: Symbol.h:524
Symbol & setStrokeColor(string c)
This method sets the symbol stroke color.
Definition: Symbol.h:260
~Symbol()
Definition: Symbol.h:182
Symbol & setStrokeWidth(float strk_width)
This method sets the symbol stroke width.
Definition: Symbol.h:286
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:465
Color getFillColor() const
This method gets fill color.
Definition: Symbol.h:234
Color getStrokeColor()
This method gets stroke color.
Definition: Symbol.h:274
Symbol(const Symbol &s)
Definition: Symbol.h:145
const string getSymbolAttributeRepresentation() const
Get the JSON of the symbol representation.
Definition: Symbol.h:582
Symbol & setFillColor(string c)
This method sets the symbol fill color.
Definition: Symbol.h:221
Symbol & setStrokeDash(int dash)
This method sets the stroke dash level.
Definition: Symbol.h:344
Symbol & scale(float sx, float sy, float px, float py)
Scale about an arbitrary point (px, py)
Definition: Symbol.h:494
std::string JSONencode(const T &d)
Definition: JSONutil.h:37
these methods convert byte arrays in to base64 codes and are used in BRIDGES to represent the color a...
Definition: alltypes.h:4
const string COLON
Definition: DataStructure.h:51
const string OPEN_BOX
Definition: DataStructure.h:54
const string COMMA
Definition: DataStructure.h:50
const string OPEN_CURLY
Definition: DataStructure.h:52
const string CLOSE_BOX
Definition: DataStructure.h:55
const string CLOSE_CURLY
Definition: DataStructure.h:53
const string QUOTE
Definition: DataStructure.h:49