├── 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 | ![alt text](https://github.com/DavDag/MathPlotter/blob/master/images/1.PNG) 13 | ![alt text](https://github.com/DavDag/MathPlotter/blob/master/images/2.PNG) 14 | ![alt text](https://github.com/DavDag/MathPlotter/blob/master/images/3.PNG) 15 | ![alt text](https://github.com/DavDag/MathPlotter/blob/master/images/4.PNG) 16 | ![alt text](https://github.com/DavDag/MathPlotter/blob/master/images/5.PNG) 17 | ![alt text](https://github.com/DavDag/MathPlotter/blob/master/images/6.PNG) 18 | ![alt text](https://github.com/DavDag/MathPlotter/blob/master/images/7.PNG) 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 | --------------------------------------------------------------------------------