Bridges-C++ 3.5.0-dev2-1-ge3e57bf
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
10using namespace std;
11
12#include "DataStructure.h"
13#include "Color.h"
14
15namespace 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
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
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 }
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
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
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:
428 Symbol& translate (float tx, float ty) {
429 float result[3][3];
430 float transl[3][3] = {
431 {1., 0., tx}, {0., 1., ty}, {0., 0., 1.}
432 };
433
434 // update current transform matrix
435 matMult (transl, xform, result);
436 copyMat (result, xform);
437
438 xform_flag = true;
439
440 return *this;
441 }
442
451 Symbol& scale(float sx, float sy) {
452 float result[3][3];
453 float scale[3][3] = {
454 {sx, 0., 0.}, {0., sy, 0.}, {0., 0., 1.}
455 };
456
457 // update current transform matrix
458 matMult (scale, xform, result);
459 copyMat (result, xform);
460
461 xform_flag = true;
462
463 return *this;
464 }
465
473 Symbol& scale(float scalefactor) {
474 return scale(scalefactor, scalefactor);
475 }
476
485 Symbol& rotate(float angle) {
486 // compute sin, cos
487 float angle_r = angle * M_PI / 180.;
488 float c = cos(angle_r);
489 float s = sin(angle_r);
490
491 // form the rotation matrix
492 float result[3][3];
493 float rotation[3][3] = {
494 {c, -s, 0.}, {s, c, 0.}, {0., 0., 1.}
495 };
496
497 // update current transform matrix
498 matMult (rotation, xform, result);
499 copyMat (result, xform);
500
501 xform_flag = true;
502
503 return *this;
504 }
505
516 Symbol& scale(float sx, float sy, float px, float py) {
517 float result[3][3], result2[3][3];
518 float scale[3][3] = {
519 {sx, 0., 0.}, {0., sy, 0.}, {0., 0., 1.}
520 };
521 float transl1[3][3] =
522 { {1., 0., -px}, {0., 1., -py}, {0., 0., 1.} };
523 float transl2[3][3] =
524 { {1., 0., px}, {0., 1., py}, {0., 0., 1.} };
525
526 // form the composite transform
527 matMult (scale, transl1, result);
528 matMult (transl2, result, result2);
529
530 // update current transform matrix
531 matMult (result2, xform, result);
532 copyMat (result, xform);
533
534 xform_flag = true;
535
536 return *this;
537 }
538
550 Symbol& rotate(float angle, float px, float py) {
551 // compute sin, cos
552 float angle_r = angle * M_PI / 180.;
553 float c = cos(angle_r);
554 float s = sin(angle_r);
555
556 // form the rotation matrix
557 float result[3][3], result2[3][3];
558 float rotation[3][3] = {
559 {c, -s, 0.}, {s, c, 0.}, {0., 0., 1.}
560 };
561 float transl1[3][3] = {
562 {1., 0., -px}, {0., 1., -py}, {0., 0., 1.}
563 };
564 float transl2[3][3] = {
565 {1., 0., px}, {0., 1., py}, {0., 0., 1.}
566 };
567
568 // form the composite transform
569 matMult (rotation, transl1, result);
570 matMult (transl2, result, result2);
571
572 // update current transform matrix
573 matMult (result2, xform, result);
574 copyMat (result, xform);
575
576 xform_flag = true;
577
578 return *this;
579 }
595 Symbol& setTransform(float a, float b, float c,
596 float d, float e, float f) {
597 xform[0][0] = a;
598 xform[1][0] = b;
599 xform[0][1] = c;
600 xform[1][1] = d;
601 xform[0][2] = e;
602 xform[2][2] = f;
603 xform[2][0] = 0.0f;
604 xform[2][1] = 0.0f;
605 xform[2][2] = 1.0f;
606
607 xform_flag = true;
608
609 return *this;
610 }
611
612 protected:
613
622 const string getSymbolAttributeRepresentation() const {
623
624 // first get all the non-geometric attributes
625
627
628 string symbol_attr_json = OPEN_CURLY;
629
630 symbol_attr_json += QUOTE + "type" + QUOTE + COLON +
631 QUOTE + getShapeType() + QUOTE + COMMA +
632 QUOTE + "ID" + QUOTE + COLON +
633 QUOTE + to_string(identifier) + QUOTE + COMMA;
634
635 // check transform, if it is not set, ignore
636 if (this->xform_flag) {
637 symbol_attr_json +=
638 QUOTE + "transform" + QUOTE + COLON +
639 OPEN_BOX +
640 JSONencode(this->xform[0][0]) + COMMA +
641 JSONencode(this->xform[1][0]) + COMMA +
642 JSONencode(this->xform[0][1]) + COMMA +
643 JSONencode(this->xform[1][1]) + COMMA +
644 JSONencode(this->xform[0][2]) + COMMA +
645 JSONencode(this->xform[1][2]) +
647 }
648 if (layer) {
649 symbol_attr_json += QUOTE + "layer" + QUOTE +
650 COLON + to_string(*layer) + COMMA;
651 }
652
653 // the above attributes are all that is needed for 'group'
654 // type, rest also include the following
655 if (getShapeType() == "group") {
656 // remove the last comma
657 symbol_attr_json.erase (symbol_attr_json.size() - 1);
658 symbol_attr_json += CLOSE_CURLY;
659 }
660 else {
661
662 if (fillColor) {
663 symbol_attr_json += QUOTE + "fill-color" +
664 QUOTE + COLON + fillColor->getCSSRepresentation()
665 + COMMA;
666 }
667
668 if (opacity) {
669 symbol_attr_json += QUOTE + "opacity" + QUOTE + COLON +
670 to_string(*opacity) + COMMA;
671 }
672
673 if (strokeColor) {
674 symbol_attr_json += QUOTE + "stroke-color" + QUOTE +
675 COLON + strokeColor->getCSSRepresentation() + COMMA;
676 }
677
678 if (strokeWidth) {
679 symbol_attr_json += QUOTE + "stroke-width" + QUOTE +
680 COLON + to_string(*strokeWidth) + COMMA;
681 }
682
683 if (strokeDash) {
684 symbol_attr_json += QUOTE + "stroke-dasharray" + QUOTE +
685 COLON + to_string(*strokeDash) + COMMA;
686 }
687 }
688
689 return symbol_attr_json;
690 }
691 };
692
693 // initialize the id to start at zero
694 int Symbol::ids = 0;
695 }
696} // namespace bridges
697
698#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 & setFillColor(string c)
This method sets the symbol fill color.
Definition: Symbol.h:239
Symbol & scale(float sx, float sy)
Scale a Symbol.
Definition: Symbol.h:451
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 & scale(float sx, float sy, float px, float py)
Scale about an arbitrary point (px, py)
Definition: Symbol.h:516
Symbol & rotate(float angle, float px, float py)
Rotate a 2D point about an arbitrary point (px, py)
Definition: Symbol.h:550
Symbol & scale(float scalefactor)
Scale a Symbol.
Definition: Symbol.h:473
int getLayer() const
Definition: Symbol.h:407
Symbol & setStrokeDash(int dash)
This method sets the stroke dash level.
Definition: Symbol.h:362
Symbol & setFillColor(Color c)
Set the symbol fill color.
Definition: Symbol.h:226
Symbol & setStrokeWidth(float strk_width)
This method sets the symbol stroke width.
Definition: Symbol.h:304
int getIdentifier() const
return the symbol identifier.
Definition: Symbol.h:217
Symbol()
default constructor
Definition: Symbol.h:126
Symbol & setTransform(float a, float b, float c, float d, float e, float f)
Definition: Symbol.h:595
Symbol & setStrokeColor(string c)
This method sets the symbol stroke color.
Definition: Symbol.h:278
~Symbol()
Definition: Symbol.h:200
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:485
Symbol & setStrokeColor(Color c)
Definition: Symbol.h:264
Symbol & operator=(const Symbol &s)
Definition: Symbol.h:168
Color getFillColor() const
This method gets fill color.
Definition: Symbol.h:252
Symbol & translate(float tx, float ty)
Translate by a vector.
Definition: Symbol.h:428
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:622
Symbol & setOpacity(float op)
This method sets the symbol opacity.
Definition: Symbol.h:333
Symbol & setLayer(int l)
Definition: Symbol.h:392
std::string JSONencode(const T &d)
Definition: JSONutil.h:38
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: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