-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path3d_lsystems.cpp
More file actions
118 lines (99 loc) · 3.77 KB
/
Copy path3d_lsystems.cpp
File metadata and controls
118 lines (99 loc) · 3.77 KB
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
//
// Created by kobedb on 20.05.22.
//
#include "3d_lsystems.h"
#include <iostream>
#include <stack>
#include <fstream>
#include "l_parser.h"
using namespace std;
namespace KDBRenderUtils {
struct PenState {
Vector3D pos;
Vector3D H; // look at
Vector3D L; // left
Vector3D U; // up
double angleDelta{};
PenState() : pos{Vector3D::point(0,0,0)}, H{Vector3D::point(1,0,0)}, L{Vector3D::point(0,1,0)}, U{Vector3D::point(0,0,1)} {}
};
void generate3DLSystemFigureRecursive(
int nrIterations,
const std::string& penInstructions,
Figure& fig,
const LParser::LSystem3D& lSystem,
PenState& curPenState,
stack<PenState>& penStateStack
)
{
for(char c : penInstructions) {
if(lSystem.get_alphabet().find(c) != lSystem.get_alphabet().end()) {
if(nrIterations <= 0) {
if(lSystem.draw(c)) {
auto next = curPenState.pos + curPenState.H;
fig.vertices.push_back(curPenState.pos); int prevPos_i = fig.vertices.size()-1;
fig.vertices.push_back(next); int next_i = fig.vertices.size()-1;
fig.faces.push_back(Face{{prevPos_i, next_i}});
curPenState.pos = next;
}
continue;
}
generate3DLSystemFigureRecursive(nrIterations-1, lSystem.get_replacement(c), fig, lSystem, curPenState, penStateStack);
continue;
}
if( c == '(') {
penStateStack.push(curPenState);
continue;
}
if(c == ')') {
curPenState = penStateStack.top();
penStateStack.pop();
continue;
}
double angle = curPenState.angleDelta;
if(c == '-' || c == '&' || c == '/') {
angle = -angle;
}
if(c == '+' || c == '-') {
auto H_new = curPenState.H * cos(angle) + curPenState.L * sin(angle);
auto L_new = -curPenState.H * sin(angle) + curPenState.L * cos(angle);
curPenState.H = H_new;
curPenState.L = L_new;
continue;
}
if(c == '^' || c == '&') {
auto H_new = (curPenState.H * cos(angle)) + (curPenState.U * sin(angle));
auto U_new = (-curPenState.H * sin(angle)) + (curPenState.U * cos(angle));
curPenState.H = H_new;
curPenState.U = U_new;
continue;
}
if(c == '\\' || c == '/') {
auto L_new = curPenState.L * cos(angle) - curPenState.U * sin(angle);
auto U_new = curPenState.L * sin(angle) + curPenState.U * cos(angle);
curPenState.L = L_new;
curPenState.U = U_new;
continue;
}
if(c == '|') {
angle = KDB_PI;
curPenState.H = -curPenState.H;
curPenState.L = -curPenState.L;
continue;
}
cerr << "Unhandled symbol in 3d lsystem\n";
}
}
Figure generate3DLSystemFigure(const std::string& inputFile)
{
std::stack<PenState> penStateStack{};
PenState curPenState{};
LParser::LSystem3D lSystem;
std::ifstream ifs{inputFile};
ifs >> lSystem;
if(!ifs) std::cerr << "Couldn't read l-system\n";
curPenState.angleDelta = rad(lSystem.get_angle());
Figure fig;
generate3DLSystemFigureRecursive(lSystem.get_nr_iterations(), lSystem.get_initiator(), fig, lSystem, curPenState, penStateStack);
return fig;
}
};