├── LICENSE
├── Math.exe
├── README.md
├── images
├── 1.PNG
├── 2.PNG
├── 3.PNG
├── 4.PNG
├── 5.PNG
├── 6.PNG
└── 7.PNG
└── main.cpp
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Math.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/Math.exe
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MathPlotter
2 | A function plotter written in C++ with only OpenGl / ImGui / mathExp libraries
3 |
4 | ### Guide to Use
5 | Add to **compiler** options:
6 | -DGLEW_STATIC -DNO_FREETYPE
7 | Add to **linker** options:
8 | -static-libgcc -lglew32 -lglfw3 -lopengl32 -lglu32 -lgdi32 -lwinmm
9 | _Or simply download the "Math.exe" file_
10 |
11 | # Some Images from the App
12 | 
13 | 
14 | 
15 | 
16 | 
17 | 
18 | 
19 |
--------------------------------------------------------------------------------
/images/1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/images/1.PNG
--------------------------------------------------------------------------------
/images/2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/images/2.PNG
--------------------------------------------------------------------------------
/images/3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/images/3.PNG
--------------------------------------------------------------------------------
/images/4.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/images/4.PNG
--------------------------------------------------------------------------------
/images/5.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/images/5.PNG
--------------------------------------------------------------------------------
/images/6.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/images/6.PNG
--------------------------------------------------------------------------------
/images/7.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavDag/MathPlotter/59b80ef0100e29b50656554c8d831d7da0cbfaaa/images/7.PNG
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "imgui/imgui.h"
7 | #include "imgui/imgui_impl_glfw.h"
8 | #include "imgui/imgui_impl_opengl3.h"
9 | #include "exp/mathexpr.h"
10 | #include
11 |
12 | #define CENTERED 0
13 | #define ALIGN_RIGHT 1
14 |
15 | const double pi = std::atan(1.0f) * 4;
16 | const double e = std::exp(1.0f);
17 | const double inf = std::numeric_limits::infinity();
18 |
19 | GLFWwindow *window;
20 | unsigned int vertexbuffer, axisbuffer, numbersbuffer, gridbuffer, deepgridbuffer, integratebuffer, guidelinesbuffer, parabolasbuffer;
21 |
22 | const int num_points = 1000, intervalError = 50000;
23 | double scale = 0.1f, xoffset = 0, yoffset = 0, stepstart = 0, stepend = 0, area = 0.0f, errore = 0.0f;
24 | int stepintegral = 1, stepforcheckinterval = 1000, parabolaprecision = 100, intervalMinMaxCheckPrecision = 1000;
25 | double points[num_points << 1];
26 | std::vector axis, numbers, grid, deepgrid, integrals, guidelines, parabolas;
27 | bool precision_scale = true, drag = false, integrable = false, check = false, updatefunction = true;
28 | int integrate = -1;
29 | bool breakable = false;
30 | double screenWidth = 1100.0f, screenHeight = 600.0f;
31 | std::pair lastMousePos = {0.0f, 0.0f}, currMousePos = {0.0f, 0.0f};
32 |
33 | char function[500] = "x";
34 | double funx;
35 | RVar *xvar;
36 | RVar* vararray[1];
37 | ROperation *op;
38 |
39 | void MousePosProc(GLFWwindow*, double, double);
40 | void MouseScrollProc(GLFWwindow*, double, double);
41 | void MouseButtonProc(GLFWwindow*, int, int, int);
42 | void KeyboardProc(GLFWwindow*, int, int, int, int);
43 | void APIENTRY ErrorProc(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, const void*);
44 | void Init(int, int, const std::string&);
45 | void Destroy();
46 | void Update();
47 | void DrawContent();
48 | void DrawGui();
49 | void ElaborateFunction();
50 | void CheckForInterval();
51 | void CalcError();
52 | void DrawParabola(double, double, double);
53 | void DrawIntegral();
54 | void DrawGrid(double, double, std::string);
55 | std::vector DrawNumber(double, double, unsigned int, double);
56 | double Func(double);
57 | double FirstDeriv(double);
58 | double SecondDeriv(double);
59 | double ThirdDeriv(double);
60 | double FourthDeriv(double);
61 |
62 | int main()
63 | {
64 | int scelta = 0;
65 | do
66 | {
67 | std::cout << "Insert Screen Size : ";
68 | std::cin >> screenWidth >> screenHeight;
69 | Init(screenWidth, screenHeight, "Grafi");
70 | while (true && !glfwWindowShouldClose(window))
71 | {
72 | Update();
73 | DrawContent();
74 | DrawGui();
75 | glfwSwapBuffers(window);
76 | glfwPollEvents();
77 | }
78 | Destroy();
79 | std::cout << "Premere 1 per continuare : ";
80 | std::cin >> scelta;
81 | } while(scelta == 1);
82 | return EXIT_SUCCESS;
83 | }
84 |
85 | double FirstDeriv(double x)
86 | {
87 | double h = 0.0001f;
88 | double x2 = x + h;
89 | double x1 = x - h;
90 | double f2 = Func(x2);
91 | double f1 = Func(x1);
92 | double approxDerivative = (f2 - f1) / (2.0 * h);
93 | return approxDerivative;
94 | }
95 |
96 | double SecondDeriv(double x)
97 | {
98 | double h = 0.0001f;
99 | double x2 = x + h;
100 | double x1 = x - h;
101 | double f2 = FirstDeriv(x2);
102 | double f1 = FirstDeriv(x1);
103 | double approxDerivative = (f2 - f1) / (2.0 * h);
104 | return approxDerivative;
105 | }
106 |
107 | double ThirdDeriv(double x)
108 | {
109 | double h = 0.0001f;
110 | double x2 = x + h;
111 | double x1 = x - h;
112 | double f2 = SecondDeriv(x2);
113 | double f1 = SecondDeriv(x1);
114 | double approxDerivative = (f2 - f1) / (2.0 * h);
115 | return approxDerivative;
116 | }
117 |
118 | double FourthDeriv(double x)
119 | {
120 | double h = 0.0001f;
121 | double x2 = x + h;
122 | double x1 = x - h;
123 | double f2 = ThirdDeriv(x2);
124 | double f1 = ThirdDeriv(x1);
125 | double approxDerivative = (f2 - f1) / (2.0 * h);
126 | return approxDerivative;
127 | }
128 |
129 | double Func(double x)
130 | {
131 | double y = 0;
132 | funx = x;
133 | y = op->Val();
134 | if(y == inf && breakable) integrable = false;
135 | return y;
136 | }
137 |
138 | void ElaborateFunction()
139 | {
140 | if(!updatefunction) return;
141 | updatefunction = false;
142 | xvar = new RVar("x", &funx);
143 | vararray[0] = xvar;
144 | op = new ROperation(function, 1, vararray);
145 | }
146 |
147 | void Update()
148 | {
149 | // Disegno la funzione
150 | ElaborateFunction();
151 | double x = (-screenWidth / 2 + xoffset / scale) * scale;
152 | double func_step = (screenWidth * scale) / ((double)num_points + 1);
153 | for(int i = 0; i < num_points; ++i)
154 | {
155 | points[i << 1] = (x - xoffset) / scale / (screenWidth / 2);
156 | points[(i << 1) + 1] = (Func(x) - yoffset) / scale / (screenHeight / 2);
157 | x += func_step;
158 | }
159 | // Disegno gli assi cartesiani
160 | axis = {
161 | 1.0f, -yoffset / scale / screenHeight * 2.0f,
162 | -1.0f, -yoffset / scale / screenHeight * 2.0f,
163 | -xoffset / scale / screenWidth * 2.0f, 1.0f,
164 | -xoffset / scale / screenWidth * 2.0f, -1.0f
165 | };
166 | // Disegno i numeri lungo gli assi
167 | numbers.clear();
168 | grid.clear();
169 | deepgrid.clear();
170 | double step = scale * 100;
171 | // Ascisse positive
172 | for(double x = -xoffset; x < screenWidth / 2 * scale; x += step)
173 | {
174 | std::vector num = DrawNumber(x + xoffset, 8.75f, CENTERED, scale);
175 | for(int i = 0; i < num.size(); i += 2) num[i] = (num[i] + x / scale) / (screenWidth / 2);
176 | for(int i = 1; i < num.size(); i += 2) num[i] = (num[i] - yoffset / scale) / (screenHeight / 2);
177 | for(auto el : num) numbers.push_back(el);
178 | // Disegno la griglia
179 | DrawGrid(x, x + step, "x");
180 | }
181 | // Ascisse negative
182 | DrawGrid(-xoffset, -xoffset - step, "x");
183 | for(double x = -xoffset - step; x > - screenWidth / 2 * scale; x -= step)
184 | {
185 | std::vector num = DrawNumber(x + xoffset, 8.75f, CENTERED, scale);
186 | for(int i = 0; i < num.size(); i += 2) num[i] = (num[i] + x / scale) / (screenWidth / 2);
187 | for(int i = 1; i < num.size(); i += 2) num[i] = (num[i] - yoffset / scale) / (screenHeight / 2);
188 | for(auto el : num) numbers.push_back(el);
189 | // Disegno la griglia
190 | DrawGrid(x, x - step, "x");
191 | }
192 | // Ordinate positive
193 | DrawGrid(-yoffset, -yoffset + step, "y");
194 | for(double y = -yoffset + step; y < screenHeight / 2 * scale; y += step)
195 | {
196 | std::vector num = DrawNumber(y + yoffset, 8.75f, ALIGN_RIGHT, scale);
197 | for(int i = 0; i < num.size(); i += 2) num[i] = (num[i] - xoffset / scale) / (screenWidth / 2);
198 | for(int i = 1; i < num.size(); i += 2) num[i] = (num[i] + y / scale) / (screenHeight / 2);
199 | for(auto el : num) numbers.push_back(el);
200 | // Disegno la griglia
201 | DrawGrid(y, y + step, "y");
202 | }
203 | // Ordinate negative
204 | DrawGrid(-yoffset, -yoffset - step, "y");
205 | for(double y = -yoffset - step; y > -screenHeight / 2 * scale; y -= step)
206 | {
207 | std::vector num = DrawNumber(y + yoffset, 8.75f, ALIGN_RIGHT, scale);
208 | for(int i = 0; i < num.size(); i += 2) num[i] = (num[i] - xoffset / scale) / (screenWidth / 2);
209 | for(int i = 1; i < num.size(); i += 2) num[i] = (num[i] + y / scale) / (screenHeight / 2);
210 | for(auto el : num) numbers.push_back(el);
211 | // Disegno la griglia
212 | DrawGrid(y, y - step, "y");
213 | }
214 | // Disegno x e F(x) con x = posizione del mouse
215 | x = (currMousePos.first - screenWidth / 2) * scale;
216 | double y = Func(x);
217 | axis.push_back((x) / scale / (screenWidth / 2));
218 | axis.push_back((-yoffset) / scale / (screenHeight / 2));
219 | axis.push_back((x) / scale / (screenWidth / 2));
220 | axis.push_back((Func(x + xoffset) - yoffset) / scale / (screenHeight / 2));
221 | axis.push_back((-xoffset) / scale / (screenWidth / 2));
222 | axis.push_back((Func(x + xoffset) - yoffset) / scale / (screenHeight / 2));
223 | axis.push_back((x) / scale / (screenWidth / 2));
224 | axis.push_back((Func(x + xoffset) - yoffset) / scale / (screenHeight / 2));
225 | // Disegno i numeri sopra il mouse
226 | /*x += xoffset;
227 | y -= yoffset;
228 | double xshift = 9 * std::log10(std::abs(x)) + 18, yshift = (y < 0) ? -10 : 10;
229 | x = (double)((int)(x * 100)) / 100.0f;
230 | y = (double)((int)(y * 100)) / 100.0f;
231 | std::vector num = drawNumber(x, 8.75f, CENTERED, scale);
232 | for(int i = 0; i < num.size(); i += 2) num[i] = (num[i] + x / scale - xshift) / (screenWidth / 2);
233 | for(int i = 1; i < num.size(); i += 2) num[i] = (num[i] + y / scale + yshift) / (screenHeight / 2);
234 | for(auto el : num) numbers.push_back(el);
235 | num = drawNumber(y, 8.75f, CENTERED, scale);
236 | for(int i = 0; i < num.size(); i += 2) num[i] = (num[i] + x / scale + xshift) / (screenWidth / 2);
237 | for(int i = 1; i < num.size(); i += 2) num[i] = (num[i] + y / scale + yshift) / (screenHeight / 2);
238 | for(auto el : num) numbers.push_back(el);*/
239 | // Disegno l'integrale
240 | breakable = true;
241 | DrawIntegral();
242 | breakable = false;
243 | }
244 |
245 | void CalcError()
246 | {
247 | errore = 0.0f;
248 | double step = (stepend - stepstart) / (double) intervalError;
249 | double M = 0.0f;
250 | for(double i = stepstart; i < stepend; i += step)
251 | {
252 | if(integrate == 0 || integrate == 1) M = std::max(M, std::abs(FirstDeriv(i)));
253 | else if(integrate == 2) M = std::max(M, std::abs(SecondDeriv(i)));
254 | else if(integrate == 3) M = std::max(M, std::abs(FourthDeriv(i)));
255 | }
256 | if(integrate == 0 || integrate == 1) errore = std::pow((stepend - stepstart), 2) / (2.0f * (double) stepintegral) * M;
257 | else if(integrate == 2) errore = std::pow((stepend - stepstart), 3) / (12.0f * std::pow((double) stepintegral, 2)) * M;
258 | else if(integrate == 3) errore = std::pow((stepend - stepstart), 5) / (2880.0f * std::pow((double) stepintegral, 4)) * M;
259 | }
260 |
261 | void CheckForInterval()
262 | {
263 | if(!check) return;
264 | check = false;
265 | double step = (stepend - stepstart) / (double)stepforcheckinterval;
266 | int sign = 0;
267 | bool allgood = true;
268 | for(double i = stepstart; i < stepend; i += step)
269 | {
270 | double y = Func(i);
271 | if(y == 0 || y == -0) continue;
272 | if(sign == 0) sign = (y > 0) ? 1 : -1;
273 | else if(sign == -1 && y < 0) continue;
274 | else if(sign == +1 && y > 0) continue;
275 | else
276 | {
277 | allgood = false;
278 | break;
279 | }
280 | }
281 | integrable = allgood;
282 | }
283 |
284 | void DrawParabola(double x1, double x2, double x3)
285 | {
286 | double y1 = Func(x1), y2 = Func(x2), y3 = Func(x3);
287 | // printf("[%f, %f], [%f, %f], [%f, %f]\n", x1, y1, x2, y2, x3, y3);
288 | // Per calcolare i coefficenti uso i "polinomi di Legendre"
289 | // credit http://www.francococca.com/gg/parabola_per_tre_punti.asp
290 | double a = (y1)/((x1-x2)*(x1-x3))+(y2)/((x2-x1)*(x2-x3))+(y3)/((x3-x1)*(x3-x2));
291 | double b = -(y1*(x2+x3)/((x1-x2)*(x1-x3))+y2*(x1+x3)/((x2-x1)*(x2-x3))+y3*(x1+x2)/((x3-x1)*(x3-x2)));
292 | double c = y1*x2*(x3)/((x1-x2)*(x1-x3))+y2*x1*(x3)/((x2-x1)*(x2-x3))+y3*x1*(x2)/((x3-x1)*(x3-x2));
293 | std::string str_func = std::to_string(a) + "x^2 + " + std::to_string(b) + "x + " + std::to_string(c);
294 | char temp_func[str_func.size() + 1];
295 | std::strcpy(temp_func, str_func.c_str());
296 | double temp_funx;
297 | RVar temp_xvar("x", &temp_funx);
298 | RVar* temp_vararray[1];
299 | temp_vararray[0] = &temp_xvar;
300 | ROperation temp_op(temp_func, 1, temp_vararray);
301 | // std::cout << temp_op.Expr() << "\n";
302 | double x = x1;
303 | double func_step = ((x3 - x1)) / ((double)parabolaprecision);
304 | for(int i = 0; i <= parabolaprecision; ++i)
305 | {
306 | temp_funx = x;
307 | parabolas.push_back((temp_funx - xoffset) / scale / (screenWidth / 2));
308 | parabolas.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
309 | x += func_step;
310 | }
311 | double delta = (x3 - x1) / (double) parabolaprecision;
312 | for(int i = 0; i <= parabolaprecision; ++i)
313 | {
314 | temp_funx = (x1 + delta * (i + 1));
315 | double massimo = temp_op.Val();
316 | temp_funx = (x1 + delta * i);
317 | double minimo = temp_op.Val();
318 | if(massimo < minimo) std::swap(minimo, massimo);
319 |
320 | integrals.push_back((x1 + delta * i - xoffset) / scale / (screenWidth / 2));
321 | integrals.push_back((-yoffset) / scale / (screenHeight / 2));
322 | integrals.push_back((x1 + delta * i - xoffset) / scale / (screenWidth / 2));
323 | temp_funx = (x1 + delta * i);
324 | integrals.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
325 | integrals.push_back((x1 + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
326 | temp_funx = (x1 + delta * (i + 1));
327 | integrals.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
328 |
329 | // guidelines.push_back((x1 + delta * i - xoffset) / scale / (screenWidth / 2));
330 | // guidelines.push_back((-yoffset) / scale / (screenHeight / 2));
331 | // guidelines.push_back((x1 + delta * i - xoffset) / scale / (screenWidth / 2));
332 | // temp_funx = (x1 + delta * i);
333 | // guidelines.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
334 |
335 | integrals.push_back((x1 + delta * i - xoffset) / scale / (screenWidth / 2));
336 | integrals.push_back((-yoffset) / scale / (screenHeight / 2));
337 | integrals.push_back((x1 + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
338 | temp_funx = (x1 + delta * (i + 1));
339 | integrals.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
340 | integrals.push_back((x1 + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
341 | integrals.push_back((-yoffset) / scale / (screenHeight / 2));
342 |
343 | // guidelines.push_back((x1 + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
344 | // guidelines.push_back((-yoffset) / scale / (screenHeight / 2));
345 | // guidelines.push_back((x1 + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
346 | // temp_funx = (x1 + delta * (i + 1));
347 | // guidelines.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
348 | }
349 | guidelines.push_back((x1 - xoffset) / scale / (screenWidth / 2));
350 | guidelines.push_back((-yoffset) / scale / (screenHeight / 2));
351 | guidelines.push_back((x1 - xoffset) / scale / (screenWidth / 2));
352 | temp_funx = x1;
353 | guidelines.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
354 | guidelines.push_back((x3 - xoffset) / scale / (screenWidth / 2));
355 | guidelines.push_back((-yoffset) / scale / (screenHeight / 2));
356 | guidelines.push_back((x3 - xoffset) / scale / (screenWidth / 2));
357 | temp_funx = x3;
358 | guidelines.push_back((temp_op.Val() - yoffset) / scale / (screenHeight / 2));
359 | }
360 |
361 | void DrawIntegral()
362 | {
363 | integrals.clear();
364 | guidelines.clear();
365 | parabolas.clear();
366 | area = 0.0f;
367 | if(stepstart == stepend || integrate == -1) return;
368 | CheckForInterval();
369 | if(!integrable) return;
370 | if(integrate == 0 || integrate == 1 || integrate == 2)
371 | {
372 | double delta = (stepend - stepstart) / (double) stepintegral;
373 | for(int i = 0; i < stepintegral; ++i)
374 | {
375 | double massimo = Func(stepstart + delta * (i + 1)), minimo = Func(stepstart + delta * i);
376 | double tempx = stepstart + delta * (i);
377 | double tempstep = (delta) / (double) intervalMinMaxCheckPrecision;
378 | if(massimo < minimo) std::swap(massimo, minimo);
379 | for(int j = 0; j < intervalMinMaxCheckPrecision && integrate != 2; ++j)
380 | {
381 | double tempy = Func(tempx + j * tempstep);
382 | if(tempy < minimo) minimo = tempy;
383 | if(tempy > massimo) massimo = tempy;
384 | }
385 |
386 | if(integrate == 0) area += minimo * delta;
387 | else if(integrate == 1) area += massimo * delta;
388 | else area += (minimo + massimo) / 2.0f * delta;
389 |
390 | integrals.push_back((stepstart + delta * i - xoffset) / scale / (screenWidth / 2));
391 | integrals.push_back((-yoffset) / scale / (screenHeight / 2));
392 | integrals.push_back((stepstart + delta * i - xoffset) / scale / (screenWidth / 2));
393 | if(integrate == 0) integrals.push_back((minimo - yoffset) / scale / (screenHeight / 2));
394 | else if(integrate == 1) integrals.push_back((massimo - yoffset) / scale / (screenHeight / 2));
395 | else integrals.push_back((Func(stepstart + delta * i) - yoffset) / scale / (screenHeight / 2));
396 | integrals.push_back((stepstart + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
397 | if(integrate == 0) integrals.push_back((minimo - yoffset) / scale / (screenHeight / 2));
398 | else if(integrate == 1) integrals.push_back((massimo - yoffset) / scale / (screenHeight / 2));
399 | else integrals.push_back((Func(stepstart + delta * (i + 1)) - yoffset) / scale / (screenHeight / 2));
400 |
401 | guidelines.push_back((stepstart + delta * i - xoffset) / scale / (screenWidth / 2));
402 | guidelines.push_back((-yoffset) / scale / (screenHeight / 2));
403 | guidelines.push_back((stepstart + delta * i - xoffset) / scale / (screenWidth / 2));
404 | if(integrate == 0) guidelines.push_back((minimo - yoffset) / scale / (screenHeight / 2));
405 | else if(integrate == 1) guidelines.push_back((massimo - yoffset) / scale / (screenHeight / 2));
406 | else guidelines.push_back((Func(stepstart + delta * i) - yoffset) / scale / (screenHeight / 2));
407 |
408 | integrals.push_back((stepstart + delta * i - xoffset) / scale / (screenWidth / 2));
409 | integrals.push_back((-yoffset) / scale / (screenHeight / 2));
410 | integrals.push_back((stepstart + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
411 | if(integrate == 0) integrals.push_back((minimo - yoffset) / scale / (screenHeight / 2));
412 | else if(integrate == 1) integrals.push_back((massimo - yoffset) / scale / (screenHeight / 2));
413 | else integrals.push_back((Func(stepstart + delta * (i + 1)) - yoffset) / scale / (screenHeight / 2));
414 | integrals.push_back((stepstart + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
415 | integrals.push_back((-yoffset) / scale / (screenHeight / 2));
416 |
417 | guidelines.push_back((stepstart + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
418 | guidelines.push_back((-yoffset) / scale / (screenHeight / 2));
419 | guidelines.push_back((stepstart + delta * (i + 1) - xoffset) / scale / (screenWidth / 2));
420 | if(integrate == 0) guidelines.push_back((minimo - yoffset) / scale / (screenHeight / 2));
421 | else if(integrate == 1) guidelines.push_back((massimo - yoffset) / scale / (screenHeight / 2));
422 | else guidelines.push_back((Func(stepstart + delta * (i + 1)) - yoffset) / scale / (screenHeight / 2));
423 | }
424 | }
425 | else if(integrate == 3)
426 | {
427 | double delta = (stepend - stepstart) / ((double) stepintegral);
428 | for(int i = 0; i < stepintegral; ++i)
429 | {
430 | double x1 = stepstart + delta * i;
431 | double x3 = stepstart + delta * (i + 1);
432 | DrawParabola(x1, (x1 + x3) / 2.0f, x3);
433 | area += (Func(x1) + Func(x3) + 4 * Func((x1 + x3) / 2.0f)) * (delta / 2.0f / 3.0f);
434 | }
435 | }
436 | }
437 |
438 | void DrawGrid(double val, double dval, std::string axe)
439 | {
440 | if(axe == "x")
441 | {
442 | double x = val;
443 | grid.push_back(x / scale / screenWidth * 2);
444 | grid.push_back(-1.0f);
445 | grid.push_back(x / scale / screenWidth * 2);
446 | grid.push_back(1.0f);
447 | for(int i = 1; i < 5; ++i)
448 | {
449 | x = (dval - val ) * i / 5.0f + val;
450 | deepgrid.push_back(x / scale / screenWidth * 2);
451 | deepgrid.push_back(-1.0f);
452 | deepgrid.push_back(x / scale / screenWidth * 2);
453 | deepgrid.push_back(1.0f);
454 | }
455 | }
456 | else if(axe == "y")
457 | {
458 | double y = val;
459 | grid.push_back(-1.0f);
460 | grid.push_back(y / scale / screenHeight * 2);
461 | grid.push_back(1.0f);
462 | grid.push_back(y / scale / screenHeight * 2);
463 | for(int i = 1; i < 5; ++i)
464 | {
465 | y = (dval - val ) * i / 5.0f + val;
466 | deepgrid.push_back(-1.0f);
467 | deepgrid.push_back(y / scale / screenHeight * 2);
468 | deepgrid.push_back(1.0f);
469 | deepgrid.push_back(y / scale / screenHeight * 2);
470 | }
471 | }
472 | }
473 |
474 | void DrawContent()
475 | {
476 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
477 | glClear(GL_COLOR_BUFFER_BIT);
478 |
479 | // Disegno la griglia ridotta
480 | glLineWidth(0.5f);
481 | glColor3f(0.9f, 0.9f, 0.9f);
482 | glBindBuffer(GL_ARRAY_BUFFER, deepgridbuffer);
483 | glBufferData(GL_ARRAY_BUFFER, deepgrid.size() * sizeof(double), deepgrid.data(), GL_STATIC_DRAW);
484 | glEnableVertexAttribArray(0);
485 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
486 | glDrawArrays(GL_LINES, 0, deepgrid.size() >> 1);
487 |
488 | // Disegno la griglia
489 | glLineWidth(0.5f);
490 | glColor3f(0.75f, 0.75f, 0.75f);
491 | glBindBuffer(GL_ARRAY_BUFFER, gridbuffer);
492 | glBufferData(GL_ARRAY_BUFFER, grid.size() * sizeof(double), grid.data(), GL_STATIC_DRAW);
493 | glEnableVertexAttribArray(0);
494 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
495 | glDrawArrays(GL_LINES, 0, grid.size() >> 1);
496 |
497 | // Disegno l'integrazione
498 | glColor3f(93.0f / 255.0f, 173.0f / 255.0f, 226.0f / 255.0f);
499 | glBindBuffer(GL_ARRAY_BUFFER, integratebuffer);
500 | glBufferData(GL_ARRAY_BUFFER, integrals.size() * sizeof(double), integrals.data(), GL_STATIC_DRAW);
501 | glEnableVertexAttribArray(0);
502 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
503 | glDrawArrays(GL_TRIANGLES, 0, integrals.size() >> 1);
504 |
505 | // Disegno la funzione
506 | glLineWidth(1.0f);
507 | glColor3f(0.2f, 0.0f, 1.0f);
508 | glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
509 | glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
510 | glEnableVertexAttribArray(0);
511 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
512 | glDrawArrays(GL_LINE_STRIP, 0, num_points);
513 |
514 | // Disegno le parabole
515 | glLineWidth(1.5f);
516 | glColor3f(1.0f, 0.0f, 0.0f);
517 | glBindBuffer(GL_ARRAY_BUFFER, parabolasbuffer);
518 | glBufferData(GL_ARRAY_BUFFER, parabolas.size() * sizeof(double), parabolas.data(), GL_STATIC_DRAW);
519 | glEnableVertexAttribArray(0);
520 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
521 | glDrawArrays(GL_LINE_STRIP, 0, parabolas.size() >> 1);
522 |
523 | // Disegno le linee guida
524 | glLineWidth(1.0f);
525 | glColor3f(91.0f / 255.0f, 84.0f / 255.0f, 111.0f / 255.0f);
526 | glBindBuffer(GL_ARRAY_BUFFER, guidelinesbuffer);
527 | glBufferData(GL_ARRAY_BUFFER, guidelines.size() * sizeof(double), guidelines.data(), GL_STATIC_DRAW);
528 | glEnableVertexAttribArray(0);
529 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
530 | glDrawArrays(GL_LINES, 0, guidelines.size() >> 1);
531 |
532 | // Disegno gli assi
533 | glLineWidth(1.0f);
534 | glColor3f(0.3f, 0.3f, 0.3f);
535 | glBindBuffer(GL_ARRAY_BUFFER, axisbuffer);
536 | glBufferData(GL_ARRAY_BUFFER, axis.size() * sizeof(double), axis.data(), GL_STATIC_DRAW);
537 | glEnableVertexAttribArray(0);
538 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
539 | glDrawArrays(GL_LINES, 0, axis.size() >> 1);
540 |
541 | // Disegno i valori numerici
542 | glLineWidth(0.5f);
543 | glColor3f(0.0f, 0.0f, 0.0f);
544 | glBindBuffer(GL_ARRAY_BUFFER, numbersbuffer);
545 | glBufferData(GL_ARRAY_BUFFER, numbers.size() * sizeof(double), numbers.data(), GL_STATIC_DRAW);
546 | glEnableVertexAttribArray(0);
547 | glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 2 * sizeof(double), 0);
548 | glDrawArrays(GL_LINES, 0, numbers.size() >> 1);
549 |
550 | glBindBuffer(GL_ARRAY_BUFFER, 0);
551 | }
552 |
553 | void DrawGui()
554 | {
555 | ImGui_ImplOpenGL3_NewFrame();
556 | ImGui_ImplGlfw_NewFrame();
557 | ImGui::NewFrame();
558 | ImGui::Begin("Integrazione Numerica");
559 | ImGui::Text("F(x): "); ImGui::SameLine();
560 | if(ImGui::InputText("", function, 500)) updatefunction = check = true;
561 | //ImGui::Text("Scala: %.3f", scale);
562 | if(!integrable) ImGui::Text("Inserire un intervallo in cui la\nfunzione e': \n -STRETTAMENTE CRESCENTE O DECRESCENTE \n -CONTINUA");
563 | if(ImGui::InputDouble(": a", &stepstart)) check = true;
564 | if(ImGui::InputDouble(": b", &stepend)) check = true;
565 | if(ImGui::InputInt(": n", &stepintegral)) if(stepintegral > 1) CalcError();
566 | if(integrable)
567 | {
568 | ImGui::Text("Area = %lf", ((area >= 0) ? area : -area));
569 | ImGui::Text("Errore = %lf", errore);
570 | }
571 | if(ImGui::RadioButton("Nessuna", &integrate, -1)) CalcError();
572 | if(ImGui::RadioButton("Rettangoli per Difetto", &integrate, 0)) CalcError();
573 | if(ImGui::RadioButton("Rettangoli per Eccesso", &integrate, 1)) CalcError();
574 | if(ImGui::RadioButton("Trapezi", &integrate, 2)) CalcError();
575 | if(ImGui::RadioButton("Parabole", &integrate, 3)) CalcError();
576 | ImGui::End();
577 | ImGui::Render();
578 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
579 | if(scale < 0.001f) scale = 0.001f;
580 | else if(scale > 1000.0f) scale = 1000.0f;
581 | if(stepend < stepstart) stepend = stepstart;
582 | if(stepintegral < 1) stepintegral = 1;
583 | if(stepintegral > 500) stepintegral = 500;
584 | }
585 |
586 | std::vector nums[] = {
587 | { // Zero
588 | 0.2, 0.2, 0.2, 0.8,
589 | 0.2, 0.8, 0.3, 0.95,
590 | 0.3, 0.95, 0.4, 1.0,
591 | 0.4, 1.0, 0.6, 1.0,
592 | 0.6, 1.0, 0.7, 0.95,
593 | 0.7, 0.95, 0.8, 0.8,
594 | 0.8, 0.8, 0.8, 0.2,
595 | 0.8, 0.2, 0.7, 0.05,
596 | 0.7, 0.05, 0.6, 0.0,
597 | 0.6, 0.0, 0.4, 0.0,
598 | 0.4, 0.0, 0.3, 0.05,
599 | 0.3, 0.05, 0.2, 0.2,
600 | },
601 | { // Uno
602 | 0.2, 0.7, 0.8, 1.0,
603 | 0.8, 1.0, 0.8, 0
604 | },
605 | { // Due
606 | 0.3, 0.6, 0.2, 0.8,
607 | 0.2, 0.8, 0.4, 1.0,
608 | 0.4, 1.0, 0.6, 1.0,
609 | 0.6, 1.0, 0.8, 0.8,
610 | 0.8, 0.8, 0.8, 0.6,
611 | 0.8, 0.6, 0.2, 0.0,
612 | 0.2, 0.0, 0.8, 0.0
613 | },
614 | { // Tre
615 | 0.2, 1.0, 0.8, 1.0,
616 | 0.8, 1.0, 0.5, 0.6,
617 | 0.5, 0.6, 0.7, 0.6,
618 | 0.7, 0.6, 0.8, 0.5,
619 | 0.8, 0.5, 0.8, 0.2,
620 | 0.8, 0.2, 0.6, 0.0,
621 | 0.6, 0.0, 0.3, 0.0,
622 | 0.3, 0.0, 0.2, 0.1
623 | },
624 | { // Quattro
625 | 0.6, 0.0, 0.6, 1.0,
626 | 0.6, 1.0, 0.2, 0.3,
627 | 0.2, 0.3, 0.8, 0.3
628 | },
629 | { // Cinque
630 | 0.2, 0.1, 0.4, 0.0,
631 | 0.4, 0.0, 0.6, 0.0,
632 | 0.6, 0.0, 0.8, 0.2,
633 | 0.8, 0.2, 0.8, 0.5,
634 | 0.8, 0.5, 0.6, 0.7,
635 | 0.6, 0.7, 0.4, 0.7,
636 | 0.4, 0.7, 0.2, 0.6,
637 | 0.2, 0.6, 0.2, 1.0,
638 | 0.2, 1.0, 0.8, 1.0
639 | },
640 | { // Sei
641 | 0.8, 1.0, 0.4, 0.9,
642 | 0.4, 0.9, 0.2, 0.6,
643 | 0.2, 0.6, 0.2, 0.2,
644 | 0.2, 0.2, 0.4, 0.0,
645 | 0.4, 0.0, 0.6, 0.0,
646 | 0.6, 0.0, 0.8, 0.2,
647 | 0.8, 0.2, 0.8, 0.4,
648 | 0.8, 0.4, 0.6, 0.5,
649 | 0.6, 0.5, 0.4, 0.5,
650 | 0.4, 0.5, 0.2, 0.4
651 | },
652 | { // Sette
653 | 0.2, 1.0, 0.8, 1.0,
654 | 0.8, 1.0, 0.2, 0.0
655 | },
656 | { // Otto
657 | 0.4, 0.0, 0.2, 0.15,
658 | 0.2, 0.15, 0.2, 0.4,
659 | 0.2, 0.4, 0.4, 0.5,
660 | 0.4, 0.5, 0.2, 0.6,
661 | 0.2, 0.6, 0.2, 0.85,
662 | 0.2, 0.85, 0.4, 1.0,
663 | 0.4, 1.0, 0.6, 1.0,
664 | 0.6, 1.0, 0.8, 0.85,
665 | 0.8, 0.85, 0.8, 0.6,
666 | 0.8, 0.6, 0.6, 0.5,
667 | 0.6, 0.5, 0.8, 0.4,
668 | 0.8, 0.4, 0.8, 0.15,
669 | 0.8, 0.15, 0.6, 0.0,
670 | 0.6, 0.0, 0.4, 0.0,
671 |
672 | 0.4, 0.5, 0.6, 0.5
673 | },
674 | { // Nove
675 | 0.2, 0.0, 0.6, 0.1,
676 | 0.6, 0.1, 0.8, 0.4,
677 | 0.8, 0.4, 0.8, 0.8,
678 | 0.8, 0.8, 0.6, 1.0,
679 | 0.6, 1.0, 0.4, 1.0,
680 | 0.4, 1.0, 0.2, 0.8,
681 | 0.2, 0.8, 0.2, 0.6,
682 | 0.2, 0.6, 0.4, 0.5,
683 | 0.4, 0.5, 0.6, 0.5,
684 | 0.6, 0.5, 0.8, 0.6
685 | },
686 | { // Virgola
687 | 0.5, 0.0, 0.2, -0.4
688 | },
689 | { // Meno
690 | 0.2, 0.5, 0.8, 0.5
691 | }
692 |
693 | };
694 |
695 | std::vector DrawNumber(double number, double scale, unsigned int option, double worldscale)
696 | {
697 | double PRECISION = 10.0f;
698 | std::vector num(1, 0);
699 | if(worldscale < 1.0f)
700 | {
701 | num.assign(3, 0);
702 | PRECISION = 1000.0f;
703 | }
704 | else if(worldscale < 5.0f)
705 | {
706 | num.assign(2, 0);
707 | PRECISION = 100.f;
708 | }
709 |
710 | bool neg = false;
711 | if(number < 0)
712 | {
713 | number *= -1;
714 | neg = true;
715 | }
716 | int tmp1 = (int) number;
717 | if(number != (int) number)
718 | {
719 | int tmp2 = ((int) (number * PRECISION)) - (((int) number) * PRECISION), cnt = 0;
720 | while(tmp2 > 9)
721 | {
722 | num[cnt++] = tmp2 % 10;
723 | tmp2 /= 10;
724 | }
725 | num[cnt++] = tmp2;
726 | }
727 | num.push_back(-1);
728 | while(tmp1 > 9)
729 | {
730 | num.push_back(tmp1 % 10);
731 | tmp1 /= 10;
732 | }
733 | num.push_back(tmp1);
734 | bool coda = true, decimal = true;
735 | std::vector v;
736 | for(int i = 0; i < num.size(); ++i)
737 | {
738 | if(num[i] == -1)
739 | {
740 | decimal = false;
741 | if(v.size() == 0) continue;
742 | for(int j = 0; j < nums[10].size(); ++j)
743 | {
744 | int el = nums[10][j] * scale;
745 | if(j % 2 == 0) el += scale * (num.size() - i - 1) + scale * 0.5;
746 | v.push_back(el);
747 | }
748 | continue;
749 | }
750 | if(num[i] == 0 && coda && decimal) continue;
751 | for(int j = 0; j < nums[num[i]].size(); ++j)
752 | {
753 | int el = nums[num[i]][j] * scale;
754 | if(j % 2 == 0) el += scale * (num.size() - i - 1) + ((decimal) ? 0 : scale * 0.5);
755 | v.push_back(el);
756 | }
757 | coda = false;
758 | }
759 | if(neg)
760 | {
761 | for(int j = 0; j < nums[11].size(); ++j)
762 | {
763 | int el = nums[11][j] * scale;
764 | if(j % 2 == 0) el -= scale / 2;
765 | v.push_back(el);
766 | }
767 | }
768 | if(option == ALIGN_RIGHT)
769 | {
770 | double M = 0;
771 | for(int i = 0; i < v.size(); i += 2) M = std::max(M, v[i]);
772 | for(int i = 0; i < v.size(); i += 2) v[i] -= M * 1.5f;
773 | for(int i = 1; i < v.size(); i += 2) v[i] -= scale / 2;
774 | }
775 | else if(option == CENTERED)
776 | {
777 | double M = 0;
778 | for(int i = 0; i < v.size(); i += 2) M = std::max(M, v[i]);
779 | for(int i = 0; i < v.size(); i += 2) v[i] -= M / 2;
780 | for(int i = 1; i < v.size(); i += 2) v[i] -= scale * 1.5f;
781 | }
782 | return v;
783 | }
784 |
785 | void Init(int width, int height, const std::string& title)
786 | {
787 | glfwInit();
788 | glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
789 | window = glfwCreateWindow(width, height, title.data(), NULL, NULL);
790 | glfwMakeContextCurrent(window);
791 | glfwSwapInterval(1);
792 | glewInit();
793 | ImGui::CreateContext();
794 | ImGui_ImplGlfw_InitForOpenGL(window, true);
795 | ImGui_ImplOpenGL3_Init("#version 330");
796 |
797 | glfwSetCursorPosCallback(window, MousePosProc);
798 | glfwSetScrollCallback(window, MouseScrollProc);
799 | glfwSetMouseButtonCallback(window, MouseButtonProc);
800 | // glfwSetKeyCallback(window, KeyboardProc);
801 | glDebugMessageCallback(ErrorProc, 0);
802 |
803 | glEnable(GL_LINE_SMOOTH);
804 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
805 |
806 | glGenBuffers(1, &vertexbuffer);
807 | glGenBuffers(1, &axisbuffer);
808 | glGenBuffers(1, &numbersbuffer);
809 | glGenBuffers(1, &deepgridbuffer);
810 | glGenBuffers(1, &gridbuffer);
811 | glGenBuffers(1, &integratebuffer);
812 | glGenBuffers(1, &guidelinesbuffer);
813 | glGenBuffers(1, ¶bolasbuffer);
814 | glBindBuffer(GL_ARRAY_BUFFER, 0);
815 | }
816 |
817 | void Destroy()
818 | {
819 | glDeleteBuffers(1, &vertexbuffer);
820 | glDeleteBuffers(1, &axisbuffer);
821 | glDeleteBuffers(1, &numbersbuffer);
822 | glDeleteBuffers(1, &gridbuffer);
823 | glDeleteBuffers(1, &deepgridbuffer);
824 | glDeleteBuffers(1, &integratebuffer);
825 | glDeleteBuffers(1, &guidelinesbuffer);
826 | glDeleteBuffers(1, ¶bolasbuffer);
827 | glfwTerminate();
828 | ImGui_ImplOpenGL3_Shutdown();
829 | ImGui_ImplGlfw_Shutdown();
830 | ImGui::DestroyContext();
831 | }
832 |
833 | void APIENTRY ErrorProc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
834 | {
835 | std::cout << "Error : " << message << "\n";
836 | if(severity == GL_DEBUG_SEVERITY_HIGH)
837 | {
838 | std::cout << "ABORTING ...";
839 | std::abort();
840 | }
841 | }
842 |
843 | void KeyboardProc(GLFWwindow* window, int key, int scancode, int action, int mods)
844 | {
845 |
846 | }
847 |
848 | void MousePosProc(GLFWwindow* window, double x, double y)
849 | {
850 | currMousePos = {x, y};
851 | if(drag)
852 | {
853 | xoffset += (lastMousePos.first - currMousePos.first) * scale;
854 | yoffset += (currMousePos.second - lastMousePos.second) * scale;
855 | lastMousePos = currMousePos;
856 | }
857 | }
858 |
859 | void MouseScrollProc(GLFWwindow* window, double xoff, double yoff)
860 | {
861 | double new_scale = scale * (1.0 + yoff / 10.0f);
862 | if(new_scale < 0.001f)
863 | new_scale = 0.001f;
864 |
865 | if(precision_scale && new_scale <= 1.0f)
866 | scale = new_scale;
867 | else if(!precision_scale && new_scale >= 1.0f)
868 | scale = new_scale;
869 | else
870 | scale = 1.0f;
871 | }
872 |
873 | void MouseButtonProc(GLFWwindow* window, int button, int action, int mods)
874 | {
875 | if(button == GLFW_MOUSE_BUTTON_MIDDLE)
876 | {
877 | if(action == GLFW_PRESS)
878 | {
879 | drag = true;
880 | lastMousePos = currMousePos;
881 | }
882 | else if(action == GLFW_RELEASE)
883 | {
884 | drag = false;
885 | }
886 | }
887 | }
888 |
889 |
--------------------------------------------------------------------------------