-
Notifications
You must be signed in to change notification settings - Fork 1
/
Draw.h
260 lines (215 loc) · 9.52 KB
/
Draw.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
// (c) 2021 Nithisha Nantha Kumar
// This code is licensed under MIT license (see LICENSE.md for details)
#pragma once
#ifndef Draw_H
#define Draw_H
#include "Pattern.h"
#include <vector>
#include <map>
struct point {
double x;
double y;
};
// stores an equation in ax + by = c form
struct equation {
double a;
double b;
double c;
};
class draw {
private:
std::vector<point> vertices;
// Stores vertices of the current polygon to which
// other polygons have to be attached
std::vector<point> centerPolygon;
std::vector<point> centerPolygonVertices;
// Stores vertices of the polygon drawn in the center of
// the output (first polygon in tiling)
std::vector<point> originPolygon;
std::vector<point> originPolygonVertices;
std::vector<point> midpoints;
point center;
cairo_t* cr;
PF_LayerDef* output;
// Mode can take values of 1, 2, 3.
// When mode == 1, calculated vertices
// are stored in the vertices vector.
// Similarly, when mode == 2, calculated
// vertices are stored in centerPolygonVertices
// and when mode == 3, vertices are stored in
// originPolygonVertices.
int mode;
/*Parameter Values*/
double sideLength;
bool hideTiling;
PF_Pixel bgColor;
PF_Pixel patternColor;
double patternWidth;
int deltaMode;
double delta;
double angleInDegrees;
int numSidesCenterMode;
int outputMode;
int tilingChoice;
//REQUIRES: non-parallel, non-horizontal, non-vertical & non-collinear
// linear equations of 2 lines.
//EFFECTS: returns the intersection point of both lines by solving
// the equation using determinants.
point solve_equation(equation& eq1, equation& eq2);
//EFFECTS: returns an equation in ax + by = c form from
// the two points.
equation construct_equation_from_pts(point& pt1, point& pt2);
//REQUIRES: angle in radians
//EFFECTS: returns a point rotated about another point by the given angle.
point rotatePoint(point& original, point& rotateAbt, double angleInRadians);
//REQUIRES: 2 linear equations representing non-parallel lines.
//EFFECTS: returns true if the two lines are collinear & false otherwise.
bool isCollinear(equation& eq1, equation& eq2);
//EFFECTS: returns true if the line formed by 2 points is
// horizontal and false otherwise.
bool isHorizontal(equation& eq);
//EFFECTS: returns true if the line formed by 2 points is
// vertical and false otherwise.
bool isVertical(equation& eq);
//EFFECTS: returns midPoint moved by a distance delta
// along the line formed by v1 and v2.
point move_along_line(point& v1, point& v2,
point midPoint, double distance);
//REQUIRES: the lines formed by each of the two points
// should not be parallel.
//EFFECTS: returns the intersection point of two lines.
point findIntersection(point& eq1pt1, point& eq1pt2,
point& eq2pt1, point& eq2pt2);
//REQUIRES: numSides is an integer greater than 2.
//MODIFIES: vertices
//EFFECTS: calculates the coordinates of a polygon's vertices
// given the default center of the polygon & stores it
// in vertices.
void calculate_center_vertices(int numSides);
//REQUIRES: numSides is an integer greater than 2.
//MODIFIES: midpoints
//EFFECTS: calculates the midpoints of each of the sides
// of the polygon & stores it in midpoints.
void calculate_midpoints(int numSides);
//REQUIRES: numSides is an integer greater than 2.
//MODIFIES: cr, midpoints
//EFFECTS: implements the Hankin's polygons-in-contact algorithm.
// Refer to: https://dl.acm.org/doi/pdf/10.5555/1089508.1089538
// https://www.youtube.com/watch?v=ld4gpQnaziU
void draw_ngon_star(int numSides);
//REQUIRES: numSides >= 3
//MODIFIES: cr, vertices
//EFFECTS: calculates vertices of the polygon with the default center
// & draws it.
void draw_ngon(int numSides);
//MODIFIES: cr
//EFFECTS: draws a polygon in the current mode when tiling is not hidden.
void draw_shape();
//EFFECTS: returns the length of the polygon's apothem given the
// polygon's radius.
double findApothem(double radius);
//REQUIRES: numSides >= 3, numSidesCenter >= 3,
// 1 <= side <= numSidesCenter
//EFFECTS: returns the center of the polygon to be attached to another
// polygon which is referred to as the center polygon.
point findCenter(point& v0, point& v1, int numSides,
int numSidesCenter, int side);
//REQUIRES: numSides >= 3, numSidesCenter >= 3,
// 1 <= side <= numSidesCenter
//MODIFIES: vertices, centerPolygonVertices, originPolygonVertices
//EFFECTS: calculates the rest of the vertices of a polygon
// with 2 known vertices.
void calculate_vertices_known(point v0, point v1, int numSides,
int numSidesCenter, int side);
//MODIFIES: vertices, centerPolygonVertices, originPolygonVertices
//EFFECTS: sorts the vertices of the polygon in counter-clockwise order.
void sort_vertices();
//REQUIRES: numSidesShapeToAttach >= 3, numSidesCenter >= 3,
// 1 <= side <= numSidesCenter
//MODIFIES: vertices, centerPolygonVertices, originPolygonVertices, cr
//EFFECTS: attaches a polygon to the given side of another polygon
// which is referred to as the center polygon.
/**This function only works for sides of the center polygon whose apothem
is not vertical and not horizontal**/
bool attach_shape(int numSidesShapeToAttach, int numSidesCenter,
int side);
//EFFECTS: returns true if the given point is within the bounds of the output
// & false otherwise.
bool isWithinBounds(point& pt);
//EFFECTS: returns true if at least one point is within the bounds
// of the output in vertices, centerPolygonVertices, or
// originPolygonVertices & false otherwise.
bool areVerticesBounded();
//REQUIRES: valid index of point in centerPolygon (this point should
// be a vertex of the current polygon that is to be attached to
// the centerPolygon),
// centerPolygon to contain vertices of a polygon to which
// the current polygon is to be attached,
// centerPolygonVertices to contain vertices of a polygon already
// attached to the centerPolygon & located adjacent to the current
// polygon that is now to be attached to the centerPolygon.
//EFFECTS: returns the position of the next vertex (in counter-clockwise
// order) of the current polygon to be attached to the centerPolygon
// from centerPolygonVertices.
/**This function is useful to calculate the vertices of a polygon that is to
be attached to a side of the centerPolygon whose apothem is vertical
or horizontal. It finds vertices of the current polygon from the existing
vertices of its adjacent polygons.**/
int find_vertex_from_center_ngon(int index);
//REQUIRES: numSides = 4 || numSides = 6
//MODIFIES: cr, vertices, originPolygonVertices,
// originPolygon, centerPolygon,
// centerPolygonVertices, midpoints
//EFFECTS: implements Hankin's Polygons-in-contact algorithm in
// 4.4.4 or 6.6.6 tiling.
void regular_tiling(int numSides);
//MODIFIES: cr, vertices, originPolygonVertices,
// originPolygon, centerPolygon,
// centerPolygonVertices, midpoints
//EFFECTS: implements Hankin's Polygons-in-contact algorithm in 4.8.8 tiling.
void four_eight_eight();
//MODIFIES: cr, vertices, originPolygonVertices,
// originPolygon, centerPolygon,
// centerPolygonVertices, midpoints
//EFFECTS: executes an inner loop for implementing Hankin's
// polygons-in-contact algorithm in 4.6.12 tiling .
void four_six_twelve_inner_loop(bool left = true);
//MODIFIES: cr, vertices, originPolygonVertices,
// originPolygon, centerPolygon,
// centerPolygonVertices, midpoints
//EFFECTS: implements Hankin's Polygons-in-contact algorithm in 4.6.12 tiling.
void four_six_twelve();
//MODIFIES: cr, vertices, originPolygonVertices,
// originPolygon, centerPolygon,
// centerPolygonVertices, midpoints
//EFFECTS: implements Hankin's Polygons-in-contact algorithm in 3.12.12 tiling.
void three_twelve_twelve();
//MODIFIES: cr
//EFFECTS: sets pattern properties based on selected parameters.
void set_pattern_properties();
//MODIFIES: cr
//EFFECTS: sets the background color of the composition
// based on selected parameters.
void set_bg_color();
public:
draw(cairo_t* cr_in, PF_LayerDef* output_in, PF_ParamDef* params[])
: cr(cr_in), output(output_in) {
center.x = double(output->width) * 0.5;
center.y = double(output->height) * 0.5;
outputMode = params[Pattern_CHOOSEMODE]->u.pd.value;
tilingChoice = params[Pattern_CHOOSETILING]->u.pd.value;
sideLength = params[Pattern_SIDELENGTH]->u.fs_d.value;
hideTiling = params[Pattern_HIDETILINGCHKBOX]->u.bd.value;
bgColor = params[Pattern_BGCOLOR]->u.cd.value;
set_bg_color();
patternColor = params[Pattern_PATTERNCOLOR]->u.cd.value;
patternWidth = params[Pattern_PATTERNWIDTH]->u.fs_d.value;
deltaMode = params[Pattern_CHOOSEDELTA]->u.pd.value;
delta = params[DELTA_ID]->u.fs_d.value;
angleInDegrees = params[ANGLE_ID]->u.fs_d.value;
numSidesCenterMode = params[Pattern_NUMSIDES]->u.fs_d.value;
mode = 1;
}
void pattern();
};
#endif // Draw_H