├── .gitattributes ├── .gitignore ├── .gitmodules ├── CPlot.sln ├── CPlot.vcxproj ├── CPlot.vcxproj.filters ├── CPlot.vcxproj.user ├── Engine ├── Functions │ ├── Faddeeva.cc │ ├── Faddeeva.h │ ├── Functions.h │ ├── basic.cc │ ├── bithacks.cc │ ├── boost_wrappers.cc │ ├── boost_wrappers.h │ ├── comparison.cc │ ├── exp.cc │ ├── fractals.cc │ ├── gamma.cc │ ├── powerseries.cc │ ├── random.cc │ ├── statistics.cc │ └── wrappers.cc ├── Namespace │ ├── AliasVariable.cc │ ├── AliasVariable.h │ ├── BaseFunction.cc │ ├── BaseFunction.h │ ├── Constant.h │ ├── Element.cc │ ├── Element.h │ ├── Expression.cc │ ├── Expression.h │ ├── Function.cc │ ├── Function.h │ ├── Namespace.cc │ ├── Namespace.h │ ├── ObjectDB.cc │ ├── ObjectDB.h │ ├── Operator.h │ ├── Parameter.cc │ ├── Parameter.h │ ├── RootNamespace.cc │ ├── RootNamespace.h │ ├── UserFunction.cc │ ├── UserFunction.h │ ├── Variable.h │ └── all.h ├── Parser │ ├── BoundContext.cc │ ├── BoundContext.h │ ├── EvalContext.h │ ├── Evaluator.cc │ ├── Evaluator.h │ ├── ExecToken.cc │ ├── ExecToken.h │ ├── FPTR.h │ ├── OptimizingTree.cc │ ├── OptimizingTree.h │ ├── ParsingResult.cc │ ├── ParsingResult.h │ ├── ParsingTree.cc │ ├── ParsingTree.h │ ├── PreToken.cc │ ├── PreToken.h │ ├── RetainTree.h │ ├── Simplifier │ │ ├── Functions.cc │ │ ├── Normalize.cc │ │ ├── Pattern.cc │ │ ├── Pattern.h │ │ ├── Powers.cc │ │ ├── Products.cc │ │ ├── Rules.txt │ │ ├── Simplify.cc │ │ ├── Sums.cc │ │ └── Unary.cc │ ├── Token.cc │ ├── Token.h │ ├── Waypoint.h │ ├── WorkingTree.cc │ ├── WorkingTree.h │ ├── WorkingTreeDerivative.cc │ ├── WorkingTreePrinting.cc │ ├── readconst.cc │ ├── readconst.h │ ├── readnum.cc │ ├── readnum.h │ └── utf8 │ │ ├── ReleaseNotes.txt │ │ ├── utf8.h │ │ ├── utf8 │ │ ├── checked.h │ │ ├── core.h │ │ └── unchecked.h │ │ └── utf8cpp.html ├── cnum.cc └── cnum.h ├── Graphs ├── Geometry │ ├── Axis.cc │ ├── Axis.h │ ├── AxisIndex.h │ ├── Camera.cc │ ├── Camera.h │ ├── Matrix.h │ ├── Quaternion.h │ ├── RecursiveGrid.cc │ ├── RecursiveGrid.h │ ├── Rotation.cc │ ├── Rotation.h │ ├── Triangle.h │ └── Vector.h ├── Graph.cc ├── Graph.h ├── Graphics │ ├── AxisLabels.cc │ ├── AxisLabels.h │ ├── Edge.h │ ├── Face.h │ ├── GL_AreaGraph.cc │ ├── GL_AreaGraph.h │ ├── GL_AreaGraph_no_subdivision.cc │ ├── GL_Axis.cc │ ├── GL_Axis.h │ ├── GL_ColorGraph.cc │ ├── GL_ColorGraph.h │ ├── GL_Graph.cc │ ├── GL_Graph.h │ ├── GL_Histogram.cc │ ├── GL_Histogram.h │ ├── GL_HistogramPointGraph.cc │ ├── GL_HistogramPointGraph.h │ ├── GL_ImplicitAreaGraph.cc │ ├── GL_ImplicitAreaGraph.h │ ├── GL_ImplicitAreaGraphTables.cc │ ├── GL_ImplicitLineGraph.cc │ ├── GL_ImplicitLineGraph.h │ ├── GL_LineGraph.cc │ ├── GL_LineGraph.h │ ├── GL_PointGraph.cc │ ├── GL_PointGraph.h │ ├── GL_RiemannColorGraph.cc │ ├── GL_RiemannColorGraph.h │ ├── GL_RiemannHistogram.cc │ ├── GL_RiemannHistogram.h │ ├── GL_RiemannHistogramPointGraph.cc │ ├── GL_RiemannHistogramPointGraph.h │ ├── Info.cc │ ├── Info.h │ ├── ThreadStorage.h │ ├── Vertex2D.h │ └── VisibilityFlags.h ├── OpenGL │ ├── GL_AAMode.h │ ├── GL_BlendMode.cc │ ├── GL_BlendMode.h │ ├── GL_ClippingPlane.cc │ ├── GL_ClippingPlane.h │ ├── GL_Color.cc │ ├── GL_Color.h │ ├── GL_Context.h │ ├── GL_Dots.cc │ ├── GL_Dots.h │ ├── GL_FBO.cc │ ├── GL_FBO.h │ ├── GL_Font.cc │ ├── GL_Font.h │ ├── GL_Image.cc │ ├── GL_Image.h │ ├── GL_Light.cc │ ├── GL_Light.h │ ├── GL_Lines.cc │ ├── GL_Lines.h │ ├── GL_Mask.cc │ ├── GL_Mask.h │ ├── GL_Mesh.cc │ ├── GL_Mesh.h │ ├── GL_RM.cc │ ├── GL_RM.h │ ├── GL_String.cc │ ├── GL_String.h │ ├── GL_StringCache.cc │ ├── GL_StringCache.h │ ├── GL_Util.cc │ └── GL_Util.h ├── Plot.cc ├── Plot.h └── Threading │ ├── ThreadInfo.h │ ├── ThreadMap.cc │ └── ThreadMap.h ├── LICENSE ├── Linux ├── Document.cc ├── Document.h ├── GUI.cc ├── GUI.h ├── GUI_defs.cc ├── GUI_edit.cc ├── GUI_file.cc ├── GUI_graphs.cc ├── GUI_help.cc ├── GUI_msg.cc ├── GUI_params.cc ├── GUI_prefs.cc ├── GUI_side_panel.cc ├── GUI_top_panel.cc ├── GUI_view.cc ├── Hack-Regular.ttf ├── ImFileDialog │ ├── ImFileDialog.cpp │ └── ImFileDialog.h ├── PlotWindow.cc ├── PlotWindow.h ├── Undo.h ├── main.cc └── screenshot.png ├── Persistence ├── ByteReader.cc ├── ByteReader.h ├── ErrorHandling.h ├── FileVersions.h ├── Serializer.cc └── Serializer.h ├── Plot Examples ├── 2D Supershape.cplot ├── Bessel.cplot ├── Breather.cplot ├── Color Mode 1.cplot ├── Color Mode 2.cplot ├── Harmonograph.cplot ├── Implicit Animation.cplot ├── Inequality.cplot ├── Julia Set.cplot ├── Klein Bottle.cplot ├── Knobs.cplot ├── Limpet Torus.cplot ├── Menger Cube.cplot ├── PhaseField.cplot ├── Riemann Histogram.cplot ├── Singularity.cplot ├── Snail Shell.cplot ├── Spherical Product.cplot ├── Tangent.cplot ├── Trefoil.cplot └── Waves & Interference.cplot ├── Profiler.psess ├── README.md ├── Utility ├── FPSCounter.h ├── MemoryPool.cc ├── MemoryPool.h ├── Mutex.h ├── Preferences.cc ├── Preferences.cpp ├── Preferences.h ├── StringFormatting.cc ├── StringFormatting.h ├── Timer.cc ├── Timer.cpp └── Timer.h ├── Windows ├── CPlotApp.cpp ├── CPlotApp.h ├── Controls │ ├── DefinitionView.cpp │ ├── DefinitionView.h │ ├── DeltaSlider.cpp │ ├── DeltaSlider.h │ ├── FocusEdit.cpp │ ├── FocusEdit.h │ ├── GraphView.cpp │ ├── GraphView.h │ ├── HeaderControl.cpp │ ├── HeaderControl.h │ ├── NumericEdit.cpp │ ├── NumericEdit.h │ ├── ParameterView.cpp │ ├── ParameterView.h │ ├── SideSection.cpp │ ├── SideSection.h │ ├── SideSectionAxis.cpp │ ├── SideSectionAxis.h │ ├── SideSectionDefs.cpp │ ├── SideSectionDefs.h │ ├── SideSectionGraphs.cpp │ ├── SideSectionGraphs.h │ ├── SideSectionParams.cpp │ ├── SideSectionParams.h │ ├── SideSectionSettings.cpp │ ├── SideSectionSettings.h │ ├── SideSectionStyle.cpp │ ├── SideSectionStyle.h │ ├── SplitterWnd.cpp │ ├── SplitterWnd.h │ ├── TextureControl.cpp │ ├── TextureControl.h │ ├── ViewUtil.cpp │ └── ViewUtil.h ├── Conversions.cpp ├── Conversions.h ├── DefinitionController.cpp ├── DefinitionController.h ├── Document.cpp ├── Document.h ├── Help │ ├── Media │ │ ├── CPlot128.png │ │ ├── CPlot128@2x.png │ │ ├── CPlot64.png │ │ ├── CPlot64@2x.png │ │ ├── Color_Riemann.png │ │ ├── Color_Tiled.png │ │ ├── Complex1.png │ │ ├── Complex2.png │ │ ├── DM_Flatshaded.png │ │ ├── DM_Hiddenline.png │ │ ├── DM_Points.png │ │ ├── DM_Smooth.png │ │ ├── DM_Wireframe.png │ │ ├── DS_Colors.png │ │ ├── DS_CombinedTextures.png │ │ ├── DS_CustomClipping.png │ │ ├── DS_Disco_Off.png │ │ ├── DS_Disco_On.png │ │ ├── DS_Fog_Off.png │ │ ├── DS_Fog_On.png │ │ ├── DS_Grid_On.png │ │ ├── DS_Mask.png │ │ ├── DS_Polar_Grid.png │ │ ├── DS_Reflection.png │ │ ├── DS_Shine_Off.png │ │ ├── DS_Shine_On.png │ │ ├── DS_Texture.png │ │ ├── DS_Transparency.png │ │ ├── Definitions.png │ │ ├── GammaPhaseField.png │ │ ├── Graph1.png │ │ ├── Graph2.png │ │ ├── Histogram.png │ │ ├── ImageMode.png │ │ ├── Implicit.png │ │ ├── Implicit2d.png │ │ ├── MultiArea.png │ │ ├── MultiLine.png │ │ ├── Parametric1.png │ │ ├── Parametric2.png │ │ ├── Spherical.png │ │ ├── Vectorfield1.png │ │ ├── Vectorfield2.png │ │ └── help.css │ ├── Topics │ │ ├── Controls.html │ │ ├── Functions.html │ │ ├── Graphs.html │ │ ├── Parameters.html │ │ ├── Preferences.html │ │ ├── ReleaseNotes.html │ │ ├── Settings.html │ │ └── Tips.html │ └── index.html ├── MainView.cpp ├── MainView.h ├── MainWindow.cpp ├── MainWindow.h ├── ParameterController.cpp ├── ParameterController.h ├── PlotView.cpp ├── PlotView.h ├── PreferencesDialog.cpp ├── PreferencesDialog.h ├── SideView.cpp ├── SideView.h ├── Util │ ├── DropHandler.cpp │ ├── DropHandler.h │ ├── Layout.cpp │ └── Layout.h ├── glew │ ├── LICENSE.txt │ ├── bin │ │ ├── Win32 │ │ │ ├── glew32.dll │ │ │ ├── glewinfo.exe │ │ │ ├── glewinfo.txt │ │ │ └── visualinfo.exe │ │ └── x64 │ │ │ ├── glew32.dll │ │ │ ├── glewinfo.exe │ │ │ └── visualinfo.exe │ ├── doc │ │ ├── advanced.html │ │ ├── basic.html │ │ ├── build.html │ │ ├── credits.html │ │ ├── github.png │ │ ├── glew.css │ │ ├── glew.html │ │ ├── glew.png │ │ ├── glew.txt │ │ ├── glxew.html │ │ ├── gpl.txt │ │ ├── index.html │ │ ├── install.html │ │ ├── khronos.txt │ │ ├── log.html │ │ ├── mesa.txt │ │ ├── new.png │ │ ├── ogl_sm.jpg │ │ ├── travis.png │ │ └── wglew.html │ ├── eglew.h │ ├── glew.h │ ├── glxew.h │ ├── lib │ │ ├── Win32 │ │ │ ├── glew32.lib │ │ │ └── glew32s.lib │ │ └── x64 │ │ │ ├── glew32.lib │ │ │ └── glew32s.lib │ └── wglew.h ├── res │ ├── CPlot.ico │ ├── CPlot.rc │ ├── CPlot.reg │ ├── CPlotDoc.ico │ └── Resource.h ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── zlib │ ├── Win32 │ ├── zlib.lib │ └── zlib.pdb │ ├── x64 │ ├── zlib.lib │ └── zlib.pdb │ ├── zconf.h │ └── zlib.h ├── build ├── gen_pkgbuild ├── leaks ├── pch.h ├── test.cplot └── version.h /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.txt text 3 | *.c text 4 | *.cc text 5 | *.cpp text 6 | *.h text 7 | *.hh text 8 | *.rc text 9 | *.ico binary 10 | *.h linguist-language=C++ 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ####### Linux build ####### 2 | /build_*/ 3 | /build.ninja 4 | /PKGBUILD 5 | /AUR/ 6 | /cplot 7 | /gmon.out 8 | 9 | ###### Windows build ###### 10 | Windows/boost/* 11 | Windows/Build/* 12 | Windows/zlib/sln/ 13 | 14 | ########## Misc ########### 15 | /TODO 16 | /stuff/ 17 | /homepage/ 18 | *.swp 19 | *.cc_ 20 | *.h_ 21 | *~ 22 | 23 | ###### Visual Studio ###### 24 | *.suo 25 | *.user 26 | *.userosscache 27 | *.sln.docstates 28 | *.userprefs 29 | .vs/ 30 | [Tt]est[Rr]esult*/ 31 | [Bb]uild[Ll]og.* 32 | *.VisualState.xml 33 | TestResult.xml 34 | *.ilk 35 | *.meta 36 | *.obj 37 | *.pch 38 | *.pgc 39 | *.pgd 40 | *.rsp 41 | *.sbr 42 | *.tlb 43 | *.tli 44 | *.tlh 45 | *.tmp 46 | *.tmp_proj 47 | *.log 48 | *.vspscc 49 | *.vssscc 50 | *.pidb 51 | *.svclog 52 | *.scc 53 | ipch/ 54 | *.aps 55 | *.ncb 56 | *.opendb 57 | *.opensdf 58 | *.sdf 59 | *.cachefile 60 | *.VC.db 61 | *.psess 62 | *.vsp 63 | *.vspx 64 | *.sap 65 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Linux/imgui"] 2 | path = Linux/imgui 3 | url = https://github.com/ocornut/imgui.git 4 | [submodule "Linux/ImFileDialog/orig"] 5 | path = Linux/ImFileDialog/orig 6 | url = https://github.com/dfranx/ImFileDialog.git 7 | [submodule "Linux/stb"] 8 | path = Linux/stb 9 | url = https://github.com/nothings/stb.git 10 | -------------------------------------------------------------------------------- /CPlot.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPlot", "CPlot.vcxproj", "{D83136BA-C18C-4407-A26F-8631F2244291}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7CFA3F74-819C-494F-B883-C5F4E95F3B3D}" 9 | ProjectSection(SolutionItems) = preProject 10 | Profiler.psess = Profiler.psess 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|32-bit = Debug|32-bit 16 | Debug|64-bit = Debug|64-bit 17 | Release|32-bit = Release|32-bit 18 | Release|64-bit = Release|64-bit 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {D83136BA-C18C-4407-A26F-8631F2244291}.Debug|32-bit.ActiveCfg = Debug|Win32 22 | {D83136BA-C18C-4407-A26F-8631F2244291}.Debug|32-bit.Build.0 = Debug|Win32 23 | {D83136BA-C18C-4407-A26F-8631F2244291}.Debug|64-bit.ActiveCfg = Debug|x64 24 | {D83136BA-C18C-4407-A26F-8631F2244291}.Debug|64-bit.Build.0 = Debug|x64 25 | {D83136BA-C18C-4407-A26F-8631F2244291}.Release|32-bit.ActiveCfg = Release|Win32 26 | {D83136BA-C18C-4407-A26F-8631F2244291}.Release|32-bit.Build.0 = Release|Win32 27 | {D83136BA-C18C-4407-A26F-8631F2244291}.Release|64-bit.ActiveCfg = Release|x64 28 | {D83136BA-C18C-4407-A26F-8631F2244291}.Release|64-bit.Build.0 = Release|x64 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /CPlot.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | Windows\res\CPlot.rc 6 | 7 | 8 | test.cplot 9 | WindowsLocalDebugger 10 | 11 | 12 | test.cplot 13 | WindowsLocalDebugger 14 | 15 | -------------------------------------------------------------------------------- /Engine/Functions/boost_wrappers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../cnum.h" 3 | 4 | /** 5 | * @addtogroup cnum 6 | * @{ 7 | */ 8 | 9 | #define BESSEL(NAME, FUNC) \ 10 | void NAME(const cnum &n, const cnum &z, cnum &r);\ 11 | double NAME(const cnum &n, const cnum &z);\ 12 | double NAME(double n, double z); 13 | BESSEL(bessel_J, cyl_bessel_j) 14 | BESSEL(bessel_Y, cyl_neumann) 15 | BESSEL(bessel_I, cyl_bessel_i) 16 | BESSEL(bessel_K, cyl_bessel_k) 17 | #undef BESSEL 18 | 19 | void expint_i(const cnum &z, cnum &r); 20 | double expint_i(const cnum &z); 21 | double expint_i(double z); 22 | 23 | void expint_n(const cnum &n, const cnum &z, cnum &r); 24 | double expint_n(const cnum &n, const cnum &z); 25 | double expint_n(double n, double z); 26 | 27 | #define AIRY(NAME, FUNC) \ 28 | void NAME(const cnum &z, cnum &r);\ 29 | double NAME(const cnum &z);\ 30 | double NAME(double z); 31 | AIRY(airy_ai, airy_ai) 32 | AIRY(airy_bi, airy_bi) 33 | AIRY(airy_ai_prime, airy_ai_prime) 34 | AIRY(airy_bi_prime, airy_bi_prime) 35 | #undef AIRY 36 | 37 | /** @} */ 38 | -------------------------------------------------------------------------------- /Engine/Functions/fractals.cc: -------------------------------------------------------------------------------- 1 | #include "Functions.h" 2 | 3 | #define M 150 /* iteration limit */ 4 | using std::log; 5 | 6 | const static double scale = 1.0/log(1.0+M); 7 | 8 | void mandel(const cnum &c, cnum &ret) 9 | { 10 | cnum z = c; 11 | int i = 0; 12 | 13 | do{ z *= z; z += c; }while (++i < M && absq(z) < 4.0); 14 | 15 | ret = log(i) * scale; 16 | } 17 | 18 | void julia(const cnum &z0, const cnum &c, cnum &ret) 19 | { 20 | cnum z = z0; 21 | int i = 0; 22 | 23 | do{ z *= z; z += c; }while (++i < M && absq(z) < 4.0); 24 | 25 | ret = log(i) * scale; 26 | } 27 | -------------------------------------------------------------------------------- /Engine/Functions/powerseries.cc: -------------------------------------------------------------------------------- 1 | #include "Functions.h" 2 | 3 | /* 4 | void besselJ(const cnum &z0, const cnum &nu0, cnum &ret) 5 | { 6 | cnum w = 1.0, z = z0; 7 | z *= z; z /= -4.0; 8 | cnum nu = nu0; nu += 1.0; 9 | cnum t; gamma(nu, t); w /= t; 10 | t = z0; t *= 0.5; cpow(t, nu0, t); w *= t; 11 | ret = w; 12 | for (int k = 1; k < 2800; ++k) 13 | { 14 | w *= z; w /= k; w /= nu; 15 | nu += 1.0; 16 | ret += w; 17 | if (absq(w) < 1e-30) return; 18 | } 19 | } 20 | */ 21 | 22 | #define G2 11.8170450080771157683163372834325820874206975794306966442 23 | #define G3 0 24 | #define N 50 25 | #define EPS 1e-40 26 | 27 | void weierp(const cnum &z0, cnum &ret) 28 | { 29 | cnum z(z0.real()-2.0*((int)z0.real()/2), z0.imag()-2.0*((int)z0.imag()/2)); 30 | // reduce to z \in [-1,1]x[-i,i] 31 | //z=z0; 32 | //while(z.r<-1) z.r+=2; while(z.r>1) z.r-=2; 33 | //while(z.i<-1) z.i+=2; while(z.i>1) z.i-=2; 34 | if (z.real() < -1.0) z += 2.0; if(z.real() > 1.0) z -= 2.0; 35 | if (z.imag() < -1.0) z.imag(z.imag() + 2.0); if(z.imag() > 1.0) z.imag(z.imag() - 2.0); 36 | 37 | int NN = (int)((absq(z)/2)*N) + 20; 38 | if (NN > N) NN = N; 39 | 40 | z *= z; 41 | cnum pz, t; 42 | ret = z; invert(ret); 43 | double c[N]; 44 | c[2] = G2*0.05; 45 | c[3] = 0.0; // = G3/28 46 | pz = z; t = pz; t *= c[2]; ret += t; 47 | pz *= z; t = pz; t *= c[3]; ret += t; 48 | for (int k = 4; k < NN; ++k) 49 | { 50 | c[k] = 0; 51 | for (int m = 2; m <= k-2; ++m) c[k] += c[m] * c[k-m]; 52 | c[k] *= 3.0 / ((2*k+1)*(k-3)); 53 | pz *= z; t = pz; t *= c[k]; ret += t; 54 | //if(RSQ(t) 7 | #include 8 | static std::mt19937 seed_rng; // TODO: lock this 9 | static thread_local std::mt19937 rng(seed_rng()); 10 | static std::uniform_real_distribution<> udist(-1.0, 1.0); 11 | 12 | #define URND (udist(rng)) 13 | 14 | #else 15 | 16 | #include 17 | static double rnd() 18 | { 19 | return (double)arc4random_uniform(std::numeric_limits::max()) / std::numeric_limits::max(); 20 | } 21 | // URND: [-1,1] 22 | #define URND (2.0*rnd()-1.0) 23 | 24 | #endif 25 | 26 | double real_rand() 27 | { 28 | // [-1,1] 29 | return URND; 30 | } 31 | void real_rand(cnum &z) 32 | { 33 | // re(z) in [-1,1], im(z) = 0 34 | // should always be optimized to the real version above 35 | z.real(URND); 36 | z.imag(0.0); 37 | } 38 | 39 | double normal_rand() 40 | { 41 | // (0,1)-normal variate (Marsaglia polar) 42 | double r; 43 | cnum z; 44 | do{ 45 | z.real(URND); 46 | z.imag(URND); 47 | r = absq(z); 48 | }while(r >= 1.0); 49 | return z.real() * sqrt(-2.0*log(r) / r); 50 | } 51 | void normal_rand(cnum &z) 52 | { 53 | // normal re(z), im(z) = 0 54 | // should always be optimized to the real version above 55 | double r; 56 | do{ 57 | z.real(URND); 58 | z.imag(URND); 59 | r = absq(z); 60 | }while(r >= 1.0); 61 | z.real(z.real() * sqrt(-2.0*log(r) / r)); 62 | z.imag(0.0); 63 | } 64 | 65 | void normal_z_rand(cnum &z) 66 | { 67 | // normal real and imag parts 68 | double r; 69 | do{ 70 | z.real(URND); 71 | z.imag(URND); 72 | r = absq(z); 73 | }while(r >= 1.0); 74 | z *= sqrt(-2.0*log(r) / r); 75 | } 76 | 77 | void riemann_rand(cnum &z) 78 | { 79 | // uniform distribution on riemann sphere 80 | P3d v; double d; 81 | do{ 82 | v.x = URND; 83 | v.y = URND; 84 | d = v.x*v.x + v.y*v.y; 85 | }while(d >= 1.0); 86 | 87 | v.z = 1.0 - 2.0*d; 88 | d = 2.0*sqrt(1.0-d); 89 | v.x *= d; 90 | v.y *= d; 91 | riemann(v, z); 92 | } 93 | 94 | void disk_rand(cnum &z) 95 | { 96 | // uniform distibution on the unit disk 97 | do{ 98 | z.real(URND); 99 | z.imag(URND); 100 | }while(absq(z) >= 1.0); 101 | } 102 | 103 | -------------------------------------------------------------------------------- /Engine/Functions/statistics.cc: -------------------------------------------------------------------------------- 1 | #include "Functions.h" 2 | 3 | void pdf_normal(const cnum &z, cnum &ret) // 1/sqrt(2pi) exp(- z^2 / 2) 4 | { 5 | ret = std::exp(-0.5 * z * z); 6 | ret *= M_2_SQRTPI * M_SQRT1_2 * 0.5; // 2/sqrt(pi) * sqrt(1/2) * 1/2 = sqrt(1/2pi) 7 | } 8 | 9 | #if 1 10 | 11 | #include "Faddeeva.h" 12 | void erf_ (const cnum &z, cnum &ret){ ret = Faddeeva::erf (z, 1e-6); } 13 | void erfc_(const cnum &z, cnum &ret){ ret = Faddeeva::erfc(z, 1e-6); } 14 | double erf_ (double x){ return Faddeeva::erf (x); } 15 | double erfc_(double x){ return Faddeeva::erfc(x); } 16 | 17 | #else 18 | 19 | void erfc_(const cnum &x, cnum &ret) 20 | { 21 | double pv=9.03777677, ph=4.76888839, p0=.392213346, p1=.149181256, p2=.0215823157, p3=1.18760964e-3, 22 | p4=2.48565745e-5, p5=1.97879468e-7, q0=.120830487, q1=1.08747438, q2=3.02076217, q3=5.92069385, 23 | q4=9.78726942, q5=14.6204889, r0=.221293361, r1=.272957057, r2=6.40298026e-02, r3=5.71296931e-3, 24 | r4=1.93880223e-4, r5=2.50263215e-6, r6=1.22871857e-8, s1=.483321947, s2=1.93328779, s3=4.34989752, 25 | s4=7.73315115, s5=12.0830487, s6=17.3995901; 26 | 27 | cnum y = x * x; 28 | 29 | if (fabs(x.real()) + fabs(x.imag()) < ph) 30 | { 31 | cnum z = std::exp(pv*x); 32 | ret = std::exp(-y); ret *= x; 33 | if (z.real() >= 0.0) 34 | { 35 | ret *= (p5/(y+q5) + p4/(y+q4) + p3/(y+q3) + p2/(y+q2) + p1/(y+q1) + p0/(y+q0)); 36 | ret += 2.0 / (1.0+z); 37 | } 38 | else 39 | { 40 | ret *= (r6/(y+s6) + r5/(y+s5) + r4/(y+s4) + r3/(y+s3) + r2/(y+s2) + r1/(y+s1) + r0/y); 41 | ret += 2.0 / (1.0-z); 42 | } 43 | } 44 | else 45 | { 46 | ret = std::exp(-y); ret *= x; 47 | ret *= (p5/(y+q5) + p4/(y+q4) + p3/(y+q3) + p2/(y+q2) + p1/(y+q1) + p0/(y+q0)); 48 | if (x.real()<0) ret += 2.0; 49 | } 50 | } 51 | 52 | void erf_(const cnum &x, cnum &ret) 53 | { 54 | double p0=1.12837917, p1=-.376126389, p2=.112837917, p3=-2.68661706e-02; 55 | if (fabs(x.real()) + fabs(x.imag()) > 0.125) 56 | { 57 | if(x.real()>=0) 58 | { 59 | erfc(x, ret); 60 | ret = 1.0 - ret; 61 | } 62 | else 63 | { 64 | erfc(-x, ret); 65 | ret -= 1.0; 66 | } 67 | } 68 | else 69 | { 70 | cnum y = x * x; 71 | ret = (((p3*y+p2)*y+p1)*y+p0)*x; 72 | } 73 | } 74 | #endif 75 | -------------------------------------------------------------------------------- /Engine/Functions/wrappers.cc: -------------------------------------------------------------------------------- 1 | #include "Functions.h" 2 | 3 | void add(const cnum &z, const cnum &w, cnum &ret){ ret = z; ret += w; } 4 | void sub(const cnum &z, const cnum &w, cnum &ret){ ret = z; ret -= w; } 5 | void mul(const cnum &z, const cnum &w, cnum &ret){ ret = z; ret *= w; } 6 | void cdiv(const cnum &z, const cnum &w, cnum &ret){ ret = z; ret /= w; } 7 | double add(double z, double w){ return z + w; } 8 | double sub(double z, double w){ return z - w; } 9 | double mul(double z, double w){ return z * w; } 10 | double div(double z, double w){ return z / w; } 11 | 12 | static inline double FMOD(double x,double y){ return x - y*floor(x/y); } 13 | 14 | void cmod(const cnum &x, const cnum &y, cnum &ret) 15 | { 16 | ret = (is_real(x) && is_real(y)) ? FMOD(x.real(), y.real()) : UNDEFINED; 17 | } 18 | double crmod(const cnum &z, const cnum &w) 19 | { 20 | return (is_real(z) && is_real(w)) ? FMOD(z.real(), w.real()) : UNDEFINED; 21 | } 22 | double mod(double z, double w){ return FMOD(z,w); } 23 | 24 | void negate(const cnum &z, cnum &ret){ ret = -z; } 25 | void invert(const cnum &z, cnum &ret){ double r = absq(z); ret.real(z.real()/r); ret.imag(-z.imag()/r); } 26 | 27 | double negate(double z){return -z; } 28 | double invert(double z){return 1.0/z; } 29 | 30 | void construct(double re, double im, cnum &r){ r.real(re); r.imag(im); } 31 | void construct(const cnum &a, const cnum &b, cnum &r) // a + ib 32 | { 33 | r.real(a.real() - b.imag()); 34 | r.imag(a.imag() + b.real()); 35 | } 36 | -------------------------------------------------------------------------------- /Engine/Namespace/AliasVariable.cc: -------------------------------------------------------------------------------- 1 | #include "AliasVariable.h" 2 | #include "Variable.h" 3 | #include "Expression.h" 4 | #include "RootNamespace.h" 5 | #include "../Parser/WorkingTree.h" 6 | 7 | AliasVariable::AliasVariable(const std::string &n, Variable *re) 8 | : Element(n), m_replacement(re) 9 | { 10 | assert(re); 11 | } 12 | 13 | AliasVariable::AliasVariable(const std::string &n, Variable *re, Variable *im) 14 | : Element(n), m_replacement(re->root_container()->Combine, WorkingTree(re), WorkingTree(im)) 15 | { 16 | assert(re && im); 17 | } 18 | 19 | AliasVariable::AliasVariable(const std::string &n, const Expression &ex) 20 | : Element(n), m_replacement(*ex.wt0()) 21 | { 22 | assert(ex.wt0()); 23 | } 24 | 25 | AliasVariable::AliasVariable(const std::string &n, AliasVariable *x) 26 | : Element(n), m_replacement(x->m_replacement) 27 | { 28 | } 29 | -------------------------------------------------------------------------------- /Engine/Namespace/AliasVariable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Namespace.h" 4 | #include "../Parser/WorkingTree.h" 5 | 6 | #include 7 | 8 | class Variable; 9 | class Expression; 10 | 11 | /** 12 | * @addtogroup Namespace 13 | * @{ 14 | */ 15 | 16 | 17 | /** 18 | * Dependent variable. All occurrences of it will be replaced by some replacement. 19 | */ 20 | 21 | class AliasVariable : public Element 22 | { 23 | public: 24 | AliasVariable(const std::string &n, Variable *re); ///< Replacement is another variable 25 | AliasVariable(const std::string &n, Variable *re, Variable *im); ///< Replace with re + i*im 26 | AliasVariable(const std::string &n, const Expression &ex); ///< Replace with expression 27 | AliasVariable(const std::string &n, AliasVariable *x); ///< Replacement is another alias 28 | 29 | virtual bool isAlias() const{ return true; } 30 | virtual bool builtin() const{ return true; } 31 | virtual int arity() const{ return -1; } 32 | 33 | const WorkingTree &replacement() const{ return m_replacement; } 34 | 35 | #ifdef DEBUG 36 | virtual void dump(std::ostream &o) const{ o << "AliasVariable " << name(); } 37 | #endif 38 | 39 | protected: 40 | virtual Element *copy() const{ return NULL; } 41 | 42 | private: 43 | WorkingTree m_replacement; 44 | }; 45 | 46 | /** @} */ 47 | 48 | -------------------------------------------------------------------------------- /Engine/Namespace/Constant.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Namespace.h" 4 | 5 | /** 6 | * @addtogroup Namespace 7 | * @{ 8 | */ 9 | 10 | 11 | /** 12 | * Symbol with a fixed value. Always live in the root namespace as builtins. 13 | * These are not user-creatable (unlike Parameters). 14 | */ 15 | 16 | class Constant : public Element 17 | { 18 | public: 19 | Constant(const std::string &n, const cnum &v) : Element(n), v(v) { }; 20 | 21 | virtual bool isConstant() const{ return true; } 22 | virtual bool builtin() const{ return true; } 23 | virtual int arity() const{ return -1; } 24 | 25 | bool real () const{ return is_real(v); } 26 | const cnum &value() const{ return v; } 27 | 28 | inline Range range() const{ return ::range(v); } 29 | 30 | #ifdef DEBUG 31 | virtual void dump(std::ostream &o) const{ o << "Constant " << name() << " = " << v; } 32 | #endif 33 | 34 | protected: 35 | const cnum v; 36 | 37 | virtual Element *copy() const{ return NULL; } 38 | }; 39 | 40 | /** @} */ 41 | 42 | -------------------------------------------------------------------------------- /Engine/Namespace/Element.cc: -------------------------------------------------------------------------------- 1 | #include "Element.h" 2 | #include "Namespace.h" 3 | #include "RootNamespace.h" 4 | #include 5 | 6 | //---------------------------------------------------------------------------------------------------------------------- 7 | // Element 8 | //---------------------------------------------------------------------------------------------------------------------- 9 | 10 | Element::~Element() 11 | { 12 | if (ns) ns->remove(this); 13 | } 14 | 15 | void Element::save(Serializer &s) const 16 | { 17 | s.string_(nm); 18 | } 19 | void Element::load(Deserializer &s) 20 | { 21 | s.string_(nm); 22 | } 23 | 24 | std::string Element::displayName(PrintingStyle ds) const 25 | { 26 | auto i = dn.find(ds); if (i != dn.end()) return i->second; 27 | switch (ds) 28 | { 29 | case PS_Debug: 30 | case PS_Function: 31 | case PS_Console: return name(); 32 | 33 | case PS_Input: 34 | case PS_Head: 35 | case PS_HTML: 36 | case PS_LaTeX: 37 | case PS_Mathematica: ds = PS_Console; break; // try again 38 | } 39 | i = dn.find(ds); return i != dn.end() ? i->second : name(); 40 | } 41 | 42 | RootNamespace *Element::root_container() const 43 | { 44 | for (Namespace *ns = container(); ns; ns = ns->container()) 45 | { 46 | if (ns->isRoot()) return (RootNamespace*)ns; 47 | } 48 | assert(isNamespace() && ((Namespace*)this)->isRoot()); 49 | return NULL; 50 | } 51 | 52 | bool Element::rename(const std::string &new_name) 53 | { 54 | if (nm == new_name) return true; 55 | 56 | if (!ns) 57 | { 58 | nm = new_name; 59 | return true; 60 | } 61 | else 62 | { 63 | return ns->rename(this, new_name); 64 | } 65 | } 66 | 67 | Element *Element::copy(Namespace &other) const 68 | { 69 | if (&other == container()) return NULL; 70 | 71 | Element *e = copy(); if (!e) return NULL; 72 | 73 | assert(e->name() == name()); 74 | 75 | try 76 | { 77 | other.add(e); 78 | } 79 | catch(...) 80 | { 81 | delete e; 82 | throw; 83 | } 84 | return e; 85 | } 86 | -------------------------------------------------------------------------------- /Engine/Namespace/ObjectDB.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #ifdef DEBUG 5 | #include 6 | #endif 7 | 8 | /** 9 | * Utility class to handle undo cases like modify -> delete -> undo delete -> undo modify 10 | * where the object is deleted and recreated, which would crash the undo modify if it passed the pointer. 11 | */ 12 | 13 | class IDCarrier 14 | { 15 | public: 16 | typedef uint64_t OID; ///< Object ID, will be unique over the runtime of the program 17 | 18 | static IDCarrier *find(OID oid); ///< @return The object with the oid or NULL if it does not or no longer exist. 19 | 20 | IDCarrier(); ///< Assigns a unique ID 21 | ~IDCarrier(); ///< Marks the ID as deleted (nonvirtual, so never delete an IDCarrier*) 22 | 23 | void restore(OID old_id); ///< Restores the OID after undoing deletion for an object. 24 | OID oid() const{ return m_oid; } 25 | 26 | #ifdef DEBUG 27 | virtual void dump(std::ostream &o) const = 0; 28 | #endif 29 | 30 | private: 31 | OID m_oid; 32 | friend class ObjectDB; 33 | }; 34 | -------------------------------------------------------------------------------- /Engine/Namespace/Operator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseFunction.h" 4 | 5 | /** 6 | * @addtogroup Namespace 7 | * @{ 8 | */ 9 | 10 | 11 | class Operator : public BaseFunction 12 | { 13 | public: 14 | Operator(const std::string &name, bfunc *fcc, bfuncRR *frr = NULL, bfuncCR *fcr = NULL, bfuncRC *frc = NULL, 15 | bool deterministic = true) 16 | : BaseFunction(name, fcc, frr, fcr, frc, deterministic) { } 17 | 18 | Operator(const std::string &name, ufunc *fcc, ufuncRR *frr = NULL, ufuncCR *fcr = NULL, ufuncRC *frc = NULL, 19 | bool deterministic = true) 20 | : BaseFunction(name, fcc, frr, fcr, frc, deterministic) { } 21 | 22 | virtual bool isFunction () const{ return false; } 23 | virtual bool isOperator () const{ return true; } 24 | 25 | virtual bool unary() const = 0; 26 | bool binary() const{ return !unary(); } 27 | virtual bool prefix() const{ return false; } 28 | virtual bool postfix() const{ return false; } 29 | virtual int arity() const{ return unary() ? 1 : 2; } 30 | }; 31 | 32 | class UnaryOperator : public Operator 33 | { 34 | public: 35 | UnaryOperator(const std::string &n, bool prefix, 36 | ufunc *fcc, ufuncRR *frr = NULL, ufuncCR *fcr = NULL, ufuncRC *frc = NULL, 37 | bool deterministic = true) 38 | : Operator(n, fcc, frr, fcr, frc, deterministic), pre(prefix) { } 39 | 40 | virtual bool unary() const{ return true; } 41 | virtual bool prefix() const{ return pre; } 42 | virtual bool postfix() const{ return !pre; } 43 | 44 | private: 45 | const bool pre; 46 | }; 47 | 48 | class BinaryOperator : public Operator 49 | { 50 | public: 51 | BinaryOperator(const std::string &name, int precedence, bool logical, 52 | bool associative, bool commutative, bool rightbinding, 53 | bfunc *fcc, bfuncRR *frr = NULL, bfuncCR *fcr = NULL, bfuncRC *frc = NULL, 54 | bool deterministic = true) 55 | : Operator(name, fcc, frr, fcr, frc, deterministic), 56 | m_precedence(precedence), m_logical(logical), m_associative(associative), 57 | m_commutative(commutative), m_rightbinding(rightbinding) { } 58 | 59 | virtual bool unary() const{ return false; } 60 | bool logical() const{ return m_logical; } ///< Result is always 0 or 1 61 | bool associative() const{ return m_associative; } ///< A∘(B∘C) = (A∘B)∘C 62 | bool commutative() const{ return m_commutative; } ///< A∘B = B∘A 63 | bool rightbinding() const{ return m_rightbinding; } ///< True if (A∘B∘C) should be (A∘(B∘C)) 64 | int precedence() const{ return m_precedence; } 65 | 66 | private: 67 | const bool m_logical, m_associative, m_commutative, m_rightbinding; 68 | const int m_precedence; 69 | }; 70 | 71 | /** @} */ 72 | 73 | -------------------------------------------------------------------------------- /Engine/Namespace/Variable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Namespace.h" 4 | 5 | /** 6 | * @addtogroup Namespace 7 | * @{ 8 | */ 9 | 10 | 11 | /** 12 | * Symbol with no fixed value. Can be real or complex. 13 | */ 14 | 15 | class Variable : public Element 16 | { 17 | public: 18 | Variable(const std::string &name, bool is_real) : Element(name), is_real(is_real){ } 19 | 20 | virtual bool isVariable () const{ return true; } 21 | virtual bool builtin() const{ return false; } 22 | virtual int arity() const{ return -1; } 23 | 24 | bool real() const{ return is_real; } 25 | inline Range range() const 26 | { 27 | return is_real ? R_Real : R_Complex; 28 | } 29 | 30 | #ifdef DEBUG 31 | virtual void dump(std::ostream &o) const{ o << "Variable " << name(); } 32 | #endif 33 | 34 | protected: 35 | bool is_real; 36 | 37 | virtual Element *copy() const 38 | { 39 | return new Variable(name(), is_real); 40 | } 41 | }; 42 | 43 | /** @} */ 44 | 45 | -------------------------------------------------------------------------------- /Engine/Namespace/all.h: -------------------------------------------------------------------------------- 1 | #include "AliasVariable.h" 2 | #include "BaseFunction.h" 3 | #include "Constant.h" 4 | #include "Element.h" 5 | #include "Expression.h" 6 | #include "Function.h" 7 | #include "Namespace.h" 8 | #include "ObjectDB.h" 9 | #include "Operator.h" 10 | #include "Parameter.h" 11 | #include "RootNamespace.h" 12 | #include "UserFunction.h" 13 | #include "Variable.h" 14 | -------------------------------------------------------------------------------- /Engine/Parser/BoundContext.cc: -------------------------------------------------------------------------------- 1 | #include "BoundContext.h" 2 | #include 3 | 4 | BoundContext::BoundContext(const Evaluator &e) 5 | : stack(new cnum[e.ctx->size]), last_change(e.ctx->last_change) 6 | , nin(e.ctx->nin), nout(e.ctx->nout) 7 | , start(new int[e.ctx->nin+1]) 8 | { 9 | memcpy(stack, e.ctx->stack, e.ctx->size*sizeof(cnum)); 10 | memcpy(start, e.start, (nin+1)*sizeof(int)); 11 | 12 | int nf = 0; 13 | for (CP_PARSER::ExecToken **F = e.funcs; *F; ++F) ++nf; 14 | 15 | #ifdef DEBUG 16 | for (int i = 0; i <= nin; ++i) assert(start[i] >= 0 && start[i] <= nf); 17 | #endif 18 | 19 | funcs = new FCall[nf+1]; 20 | funcs[nf].function = NULL; 21 | 22 | assert(sizeof(cnum) == 2*sizeof(double)); 23 | 24 | for (int i = 0; i < nf; ++i) 25 | { 26 | CP_PARSER::ExecToken &F = *e.funcs[i]; 27 | FCall &f = funcs[i]; 28 | 29 | assert(F.result_index >= nin && F.result_index < e.ctx->size); 30 | f.result = stack + F.result_index; 31 | f.param[0] = F.param_index[0] < 0 ? NULL : stack + F.param_index[0]; assert(F.param_index[0] < e.ctx->size); 32 | f.param[1] = F.param_index[1] < 0 ? NULL : stack + F.param_index[1]; assert(F.param_index[1] < e.ctx->size); 33 | f.param[2] = F.param_index[2] < 0 ? NULL : stack + F.param_index[2]; assert(F.param_index[2] < e.ctx->size); 34 | f.param[3] = F.param_index[3] < 0 ? NULL : stack + F.param_index[3]; assert(F.param_index[3] < e.ctx->size); 35 | f.function = F.function(); 36 | f.type = F.type(); 37 | assert(f.function); 38 | 39 | #define RR const_cast(f.result) ->imag(0.0); assert(f.result ->imag() == 0.0) 40 | #define R(i) const_cast(f.param[i])->imag(0.0); assert(f.param[i]->imag() == 0.0) 41 | using CP_PARSER::ExecToken; 42 | switch (f.type) 43 | { 44 | case ExecToken::Exec_2RC: R(1); // fallthrough 45 | case ExecToken::Exec_1RC: R(0); break; 46 | case ExecToken::Exec_3RR: R(2); // fallthrough 47 | case ExecToken::Exec_2RR: R(1); // fallthrough 48 | case ExecToken::Exec_1RR: R(0); // fallthrough 49 | case ExecToken::Exec_0R: 50 | case ExecToken::Exec_1CR: 51 | case ExecToken::Exec_2CR: RR; break; 52 | default: break; 53 | } 54 | #undef RR 55 | #undef R 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Engine/Parser/ExecToken.cc: -------------------------------------------------------------------------------- 1 | #include "ExecToken.h" 2 | #include "OptimizingTree.h" 3 | #include "../../Utility/StringFormatting.h" 4 | 5 | #include 6 | 7 | namespace CP_PARSER 8 | { 9 | 10 | ExecToken *ExecToken::convert(const OptimizingTree *node, const std::map &result_index) 11 | { 12 | const BaseFunction *f = node->function; 13 | assert(node->type == OptimizingTree::OT_Function && f != NULL); 14 | 15 | // get node's result index 16 | auto i = result_index.find(node); 17 | assert(i != result_index.end()); if(i == result_index.end()) return NULL; 18 | long ret = i->second; 19 | 20 | // parameter indexes are result indexes of node's children 21 | long P[4]; 22 | int nc = node->num_children(); 23 | assert(nc <= 4); if (nc > 4) return NULL; 24 | for (int k = 0; k < nc; ++k) 25 | { 26 | i = result_index.find(node->child(k)); 27 | assert(i != result_index.end()); if(i == result_index.end()) return NULL; 28 | P[k] = i->second; 29 | } 30 | 31 | switch(nc) 32 | { 33 | case 0: 34 | if (f->vfr) return new ExecToken_0R(f->vfr, ret); 35 | if (f->vfc) return new ExecToken_0C(f->vfc, ret); 36 | break; 37 | 38 | case 1: 39 | if (node->has_real_children()) 40 | { 41 | if (f->ufrr) return new ExecToken_1RR(f->ufrr, ret, P[0]); 42 | if (f->ufrc) return new ExecToken_1RC(f->ufrc, ret, P[0]); 43 | } 44 | if (f->ufcr) return new ExecToken_1CR(f->ufcr, ret, P[0]); 45 | if (f->ufcc) return new ExecToken_1CC(f->ufcc, ret, P[0]); 46 | break; 47 | 48 | case 2: 49 | if (node->has_real_children()) 50 | { 51 | if (f->bfrr) return new ExecToken_2RR(f->bfrr, ret, P[0], P[1]); 52 | if (f->bfrc) return new ExecToken_2RC(f->bfrc, ret, P[0], P[1]); 53 | } 54 | if (f->bfcr) return new ExecToken_2CR(f->bfcr, ret, P[0], P[1]); 55 | if (f->bfcc) return new ExecToken_2CC(f->bfcc, ret, P[0], P[1]); 56 | break; 57 | 58 | case 3: 59 | if (node->has_real_children()) 60 | { 61 | if (f->tfrr) return new ExecToken_3RR(f->tfrr, ret, P[0], P[1], P[2]); 62 | } 63 | if (f->tfcc) return new ExecToken_3CC(f->tfcc, ret, P[0], P[1], P[2]); 64 | break; 65 | 66 | case 4: if (f->qfcc) return new ExecToken_4CC(f->qfcc, ret, P[0], P[1], P[2], P[3]); break; 67 | } 68 | return NULL; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /Engine/Parser/FPTR.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef void (*FPTR)(); 4 | 5 | -------------------------------------------------------------------------------- /Engine/Parser/OptimizingTree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RetainTree.h" 4 | #include "ParsingResult.h" 5 | #include "../Namespace/RootNamespace.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class WorkingTree; 15 | 16 | /** 17 | * A simplified version of ParsingTree which can be optimized more easily. 18 | */ 19 | class OptimizingTree : public RetainTree 20 | { 21 | public: 22 | typedef RetainTree Super; 23 | 24 | explicit OptimizingTree(const WorkingTree *wt, ParsingResult &result); 25 | static OptimizingTree *copier(OptimizingTree *tree_to_copy, const RootNamespace &rns); 26 | ~OptimizingTree(); // only ever delete the root! 27 | 28 | void optimize() 29 | { 30 | /// @todo support associativity and commutativity while merging 31 | /// @todo support associativity in calculate optimization 32 | 33 | update_deterministic(); 34 | calculate(); 35 | merge(); 36 | } 37 | 38 | bool root() const{ return type == OT_Function && function == NULL; } 39 | bool has_real_children() const{ for (auto c : children) if (!c->real) return false; return true; } 40 | void update_real(); /// Figure out which nodes are real and which are complex. 41 | 42 | enum OTType 43 | { 44 | OT_Constant, 45 | OT_Function, 46 | OT_Variable 47 | }; 48 | 49 | OTType type; 50 | 51 | bool deterministic; 52 | bool real; 53 | 54 | union 55 | { 56 | const cnum *value; 57 | const BaseFunction *function; 58 | const Element *variable; // Parameter or Variable 59 | }; 60 | 61 | void set_child(int i, OptimizingTree *c) 62 | { 63 | Super::child(i, c); 64 | } 65 | 66 | private: 67 | void update_deterministic(); 68 | void calculate(); 69 | void merge(); 70 | 71 | OptimizingTree(); 72 | 73 | bool equals(OptimizingTree *other); 74 | 75 | struct cnum_hash{ size_t operator()(const cnum &z) const 76 | { 77 | return std::hash()(z.real()) ^ std::hash()(z.imag()); } 78 | }; 79 | void merge_const(std::unordered_map &nums, 80 | std::map &vars); 81 | 82 | friend void merge_funcs(OptimizingTree *tree, std::set &visited); 83 | }; 84 | 85 | std::ostream &operator<<(std::ostream &out, const OptimizingTree &tree); 86 | -------------------------------------------------------------------------------- /Engine/Parser/ParsingResult.cc: -------------------------------------------------------------------------------- 1 | #include "ParsingResult.h" 2 | #include "../Namespace/Expression.h" 3 | 4 | void ParsingResult::print(const Expression &ex) const 5 | { 6 | printf("%s. At this point:\n", info.c_str()); 7 | auto F = ex.strings(); 8 | if (index >= F.size()) 9 | { 10 | assert(false); 11 | printf("Invalid error source index (This should not happen!)\n"); 12 | return; 13 | } 14 | printf("%s\n%*s", F[index].c_str(), (int)pos, ""); 15 | if (len == 0) 16 | { 17 | printf("^--\n"); 18 | } 19 | else 20 | { 21 | for (size_t i = 0; i < len; ++i) putchar('~'); 22 | putchar('\n'); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Engine/Parser/ParsingResult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | class Expression; 5 | 6 | struct ParsingResult 7 | { 8 | ParsingResult() : ok(true), index(0), pos(0), len(0) { } 9 | 10 | bool ok; ///< if ok is false, the other fields will be set 11 | std::string info; ///< displayable error message 12 | size_t index; ///< index of the input string in the list 13 | size_t pos, len; ///< position of error in the input string 14 | 15 | void error(const std::string &info_, size_t pos_, size_t len_) 16 | { 17 | ok = false; 18 | info = info_; 19 | pos = pos_; 20 | len = len_; 21 | } 22 | 23 | void reset(bool reset_index = false) 24 | { 25 | ok = true; 26 | info.clear(); 27 | pos = len = 0; 28 | if (reset_index) index = 0; 29 | } 30 | 31 | void print(const Expression &ex) const; 32 | }; 33 | -------------------------------------------------------------------------------- /Engine/Parser/ParsingTree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RetainTree.h" 3 | #include "ParsingResult.h" 4 | #include "PreToken.h" 5 | #include "Token.h" 6 | #include "../cnum.h" 7 | #ifdef verify 8 | #undef verify 9 | #endif 10 | 11 | class Token; 12 | 13 | class ParsingTree : public RetainTree 14 | { 15 | public: 16 | typedef RetainTree Super; 17 | 18 | static ParsingTree *parse(const std::string &s, const Namespace &ns, ParsingResult &info); 19 | 20 | ParsingTree() : head(NULL){ } // creates a union/root node 21 | explicit ParsingTree(Token *head) : head(head){ assert(head); } 22 | ~ParsingTree(){ delete head; } 23 | 24 | virtual void reset() // delete head, clear children 25 | { 26 | delete head; head = NULL; 27 | Super::reset(); 28 | } 29 | 30 | Token *head; 31 | 32 | bool verify(ParsingResult &info); // catches internal screwups, wrong number of arguments 33 | 34 | ParsingTree *extract_child(int i = 0) 35 | { 36 | assert(retainCount() <= 1); 37 | assert(i >= 0 && i < num_children()); 38 | ParsingTree *c = child(i); 39 | children.erase(children.begin()+i); 40 | c->release_dont_delete(); 41 | return c; 42 | } 43 | 44 | private: 45 | static ParsingTree *parse(Token *token, ParsingResult &info, const RootNamespace &rns); 46 | static bool parenthesize(Token *&tokens, Token *begin, Token *end, ParsingResult &info, const RootNamespace &rns); 47 | 48 | static ParsingTree *parse(const std::string &str, PreTokens &T0, ParsingResult &info, const Namespace &ns); 49 | // Parses a token list and returns the root of the parsing tree or NULL on error 50 | // like this: sin((x+y)*z) --> sin 51 | // | 52 | // mul 53 | // / \ . 54 | // add z . 55 | // / \ . 56 | // x y 57 | // 58 | // All PreToken::TT_List must already have been converted to TT_Tree! 59 | }; 60 | 61 | std::ostream &operator<<(std::ostream &out, const ParsingTree &tree); 62 | -------------------------------------------------------------------------------- /Engine/Parser/RetainTree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef DEBUG 7 | //#define PARSER_DEBUG 8 | #endif 9 | 10 | template class RetainTree // T is the derived class to avoid typecasting all the time 11 | { 12 | public: 13 | RetainTree() : retain_count(0){ } // creates an empty tree 14 | 15 | virtual ~RetainTree() 16 | { 17 | assert(retain_count == 0); 18 | for (T *c : children) c->release(); 19 | } 20 | 21 | virtual void reset() // clear children 22 | { 23 | assert(retain_count <= 1); 24 | for (T *c : children) c->release(); 25 | children.clear(); 26 | } 27 | 28 | inline T *retain(){ ++retain_count; return (T*)this; } 29 | inline void release(){ assert(retain_count > 0); if (--retain_count == 0) delete this; } 30 | inline void release_dont_delete(bool exact = true){ --retain_count; assert(!exact || retain_count == 0); } 31 | inline void collect(){ if (retain_count == 0) delete this; } // same as retain+release 32 | 33 | int retainCount() const{ return retain_count; } 34 | 35 | #ifdef DEBUG 36 | bool check_retained(bool exact) const 37 | { 38 | assert(exact ? retain_count == 1 : retain_count >= 1); 39 | for (const T *c : children) if (!c->check_retained(exact)) return false; 40 | return (exact ? retain_count == 1 : retain_count >= 1); 41 | } 42 | #endif 43 | 44 | void add_child(T *c){ children.push_back(c->retain()); } 45 | int num_children() const{ return (int)children.size(); } 46 | T *child(int i){ assert(i >= 0 && (size_t)i < children.size()); return children[i]; } 47 | const T *child(int i) const{ assert(i >= 0 && (size_t)i < children.size()); return children[i]; } 48 | 49 | typedef typename std::vector::const_iterator const_iterator; 50 | inline const_iterator begin() const{ return children.begin(); } 51 | inline const_iterator end() const{ return children.end(); } 52 | 53 | protected: 54 | int retain_count; 55 | std::vector children; 56 | 57 | void child(int i, T *c) 58 | { 59 | assert(i >= 0 && i < num_children()); 60 | assert(c); 61 | T *c0 = children[i]; 62 | children[i] = c->retain(); 63 | c0->release(); 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /Engine/Parser/Simplifier/Pattern.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../RetainTree.h" 3 | #include "../../cnum.h" 4 | #include 5 | #include 6 | #include 7 | class Element; 8 | class Function; 9 | class Constant; 10 | class Variable; 11 | class WorkingTree; 12 | class RootNamespace; 13 | 14 | class Rule 15 | { 16 | struct Pattern : public RetainTree 17 | { 18 | enum Type 19 | { 20 | TT_Constant, 21 | TT_Number, 22 | TT_Wildcard, 23 | TT_Function, 24 | TT_Sum, 25 | TT_Product 26 | }; 27 | 28 | Type type; 29 | 30 | union 31 | { 32 | const Function *function; 33 | const Constant *constant; 34 | cnum number; 35 | Range range; // for TT_Wildcard 36 | }; 37 | 38 | #pragma warning(suppress:4582) // number's c'tor is not called, but that's ok 39 | Pattern(Type t) : type(t){} 40 | 41 | typedef std::map Bindings; 42 | bool matches(const WorkingTree &t, Bindings &bindings) const; 43 | 44 | WorkingTree apply(const Bindings &bindings, const RootNamespace &rns) const; 45 | 46 | void collect_elements(std::set &e, const RootNamespace &rns) const; 47 | Function *head(const RootNamespace &rns) const; 48 | 49 | static Pattern *load(bool replacement, const WorkingTree &t, 50 | const std::map &types, 51 | std::map &vars); 52 | }; 53 | 54 | const RootNamespace &rns; 55 | Pattern *pattern, *replacement; 56 | 57 | public: 58 | ~Rule(){ if (pattern) pattern->release(); if (replacement) replacement->release(); } 59 | 60 | Rule(RootNamespace &rns, const std::string &s); 61 | Rule(Rule &&r) : pattern(r.pattern), replacement(r.replacement), rns(r.rns) 62 | { 63 | r.pattern = r.replacement = NULL; 64 | } 65 | Rule(const Rule &r) : pattern(r.pattern), replacement(r.replacement), rns(r.rns) 66 | { 67 | if (pattern) pattern->retain(); 68 | if (replacement) replacement->retain(); 69 | } 70 | 71 | bool transform(WorkingTree &t) const; 72 | 73 | inline Function *head() const{ return pattern->head(rns); } 74 | 75 | void collect_elements(std::set &e, const RootNamespace &rns) const; 76 | 77 | inline std::set elements() const 78 | { 79 | return es; 80 | } 81 | 82 | private: 83 | std::set es; 84 | }; 85 | 86 | void load(const std::string &path, std::vector &rules, RootNamespace &rns); 87 | -------------------------------------------------------------------------------- /Engine/Parser/Simplifier/Rules.txt: -------------------------------------------------------------------------------- 1 | 2 | ################################################# 3 | # addition 4 | ################################################# 5 | 6 | z-z = 0 7 | 8 | ################################################# 9 | # multiplication, powers 10 | ################################################# 11 | 12 | z/z = 1 13 | 14 | ################################################# 15 | # re, im, complex, conjugation 16 | ################################################# 17 | 18 | ~x = x 19 | re(x) = x 20 | im(x) = 0 21 | re(y) = 0, y imag 22 | im(y) = y, y imag 23 | re(complex(x,y)) = x 24 | im(complex(x,y)) = y 25 | re(i*z) = -im(z) 26 | im(i*z) = re(z) 27 | re(exp(i*x)) = cos(x) 28 | im(exp(i*x)) = sin(x) 29 | re(z)+i*im(z) = z 30 | complex(re(z),im(z)) = z 31 | re(~z) = re(z) 32 | im(~z) = -im(z) 33 | 34 | ################################################# 35 | # trig 36 | ################################################# 37 | 38 | tan(z)*cos(z) = sin(z) 39 | sin(z)/cos(z) = tan(z) 40 | sin(z)/tan(z) = cos(z) 41 | sin(z)^k/cos(z)^k = tan(z)^k 42 | 43 | sin(arcsin(z)) = z 44 | cos(arccos(z)) = z 45 | -------------------------------------------------------------------------------- /Engine/Parser/Simplifier/Unary.cc: -------------------------------------------------------------------------------- 1 | #include "../WorkingTree.h" 2 | #include "../../Namespace/Function.h" 3 | 4 | void WorkingTree::simplify_unary(bool &change) 5 | { 6 | for (auto &c : children) c.simplify_unary(change); 7 | if (children.empty()) return; 8 | 9 | const RootNamespace &rns = ns(); 10 | 11 | if (is_operator(rns.Pow) && child(0).type == TT_Product && child(1).is_constant(true)) 12 | { 13 | auto &b = child(0), &e = child(1); 14 | for (auto &c : b.children) 15 | { 16 | c.pack(rns.Pow, true); 17 | c.children.emplace_back(e); 18 | } 19 | pull(0); 20 | change = true; 21 | return; 22 | } 23 | 24 | if (!(type == TT_Operator || type == TT_Function && function->base())) return; 25 | 26 | const Function *f = function; 27 | if (f->arity() != 1) return; 28 | 29 | WorkingTree *t = &child(0); 30 | int redo = 0; 31 | while (true) 32 | { 33 | // thread into sums and products so flatten and cancelling work better 34 | if (t->type == TT_Sum && f->additive() || t->type == TT_Product && f->multiplicative()) 35 | { 36 | if (f->involution()) 37 | { 38 | for (auto &c : t->children) c.flip_involution(f); 39 | } 40 | else 41 | { 42 | for (auto &c : t->children) c.pack(f); 43 | } 44 | pull(0); 45 | change = true; 46 | redo = -1; 47 | break; 48 | } 49 | 50 | if (!(t->type == TT_Operator || t->type == TT_Function && t->function->base())) break; 51 | 52 | const Function *g = t->function; 53 | bool done = false; 54 | switch(rns.combine(f, g)) 55 | { 56 | case RootNamespace::Nothing: done = true; break; 57 | case RootNamespace::Commutes: assert(t->num_children() == 1); t = &t->child(0); break; 58 | case RootNamespace::Zero: 59 | change = true; 60 | if (g == f){ *this = 0.0; return; }else{ *t = 0.0; done = true; break; } 61 | case RootNamespace::One: 62 | change = true; 63 | if (g == f){ *this = 1.0; return; }else{ *t = 1.0; done = true; break; } 64 | case RootNamespace::First: 65 | change = true; 66 | assert(t->num_children() == 1); 67 | t->pull(0); 68 | if (t != &child(0)) redo = 1; 69 | break; 70 | case RootNamespace::Second: change = true; pull(0); return; 71 | case RootNamespace::Collapses: 72 | assert(t->num_children() == 1); 73 | change = true; 74 | t->pull(0); pull(0); 75 | if (t != &child(0)) redo = -1; 76 | done = true; 77 | break; 78 | } 79 | if (done) break; 80 | } 81 | 82 | if (redo == -1) return simplify_unary(change); 83 | if (redo == 1) for (auto &c : children) c.simplify_unary(change); 84 | } 85 | -------------------------------------------------------------------------------- /Engine/Parser/Waypoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Token.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class Element; 9 | 10 | struct WayPoint // for backtracking 11 | { 12 | WayPoint() : fresh(true), base(NULL){ } 13 | 14 | bool empty() const{ return points.empty(); } 15 | 16 | bool fresh; // parsing stops on an empty, non-fresh waypoint 17 | Token *base; // start of waypointed token chain - must not be changed before the last pushed token 18 | 19 | void push(size_t i, size_t j, Token *t, const std::vector &c) 20 | { 21 | assert(t != NULL); 22 | 23 | if (fresh) 24 | { 25 | fresh = false; 26 | base = t->first(); 27 | } 28 | 29 | assert(!t->prev || base == t->first()); 30 | assert(points.empty() || i > points.top().i || i == points.top().i && j > points.top().j); 31 | assert(std::set(c.begin(), c.end()).size() == c.size()); 32 | 33 | // when bars get pushed, a closing bar will be tried as an opening one next 34 | // in that case c should contain a single NULL 35 | assert(!c.empty()); 36 | 37 | points.emplace(i, j, t, c); 38 | } 39 | 40 | inline void pop(size_t &i, size_t &j, Token *&t, Element *&e) 41 | { 42 | assert(!empty()); 43 | auto &p = points.top(); 44 | assert(!p.candidates.empty()); 45 | i = p.i; 46 | j = p.j; 47 | t = p.token; 48 | e = p.candidates.back(); 49 | assert(base == t->first()); 50 | 51 | p.candidates.pop_back(); 52 | if (p.candidates.empty()) points.pop(); 53 | } 54 | 55 | private: 56 | struct InsertionPoint 57 | { 58 | InsertionPoint(size_t i, size_t j, Token *t, const std::vector &c) 59 | : i(i), j(j), token(t), candidates(c){ } 60 | 61 | size_t i; // PreToken index 62 | size_t j; // position in substring (preTokens[i].i + j is the position in the parsed string) 63 | Token *token; // current token at (i,pos), to be modified after pop(...) 64 | std::vector candidates; // last element will be tried next, then removed 65 | }; 66 | 67 | std::stack points; 68 | }; 69 | -------------------------------------------------------------------------------- /Engine/Parser/readconst.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /** 6 | * Read a constant from a substring. 7 | * Format is const() or const_ 8 | * 9 | * @param s The entire string 10 | * @param i0 Start of substring 11 | * @param i1 End of substring (non-inclusive, i.e. i1==i0 is the empty string) 12 | * @param x The constant's value if any 13 | * 14 | * @return Length of the read constant or 0 if none found. 15 | */ 16 | 17 | size_t readconst(const std::string &s, size_t i0, size_t i1, double &x); // read from s[i0..i1) 18 | 19 | /** 20 | * Find the name of a constant. 21 | * Inverse of readconst. 22 | * 23 | * @param value The number to look up 24 | * 25 | * @return Its name (without the "const_" part) or the empty string if not found. 26 | */ 27 | 28 | std::string const_name(double value); 29 | -------------------------------------------------------------------------------- /Engine/Parser/readnum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /** 6 | * Read a double from a substring. 7 | * Format is [0x | 0b]nnn[.nnn][e[+-]nnn] with 0x for hex and 0b for binary. For hex numbers 8 | * the "e[+-]nnn" must be "q[+-]nnn" since 'e' is already used as a digit. 9 | * Note that this only reads nonnegative numbers (the '-' is read separately). 10 | * 11 | * @param s The entire string 12 | * @param i0 Start of substring 13 | * @param i1 End of substring (non-inclusive, i.e. i1==i0 is the empty string) 14 | * @param x The result if any 15 | * 16 | * @return Length of the read number or 0 if s[i0, ...] is not a numeric string. 17 | */ 18 | 19 | size_t readnum(const std::string &s, size_t i0, size_t i1, double &x); // read from s[i0..i1) 20 | 21 | /** 22 | * Read a complex/integer exponent from a substring. 23 | * Format is [+-]([i]nnn | nnn[i]) ... in superscript unicode, no spaces 24 | * 25 | * @param s The entire string 26 | * @param i0 Start of substring 27 | * @param i1 End of substring (non-inclusive, i.e. i1==i0 is the empty string) 28 | * @param real_part,imag_part The result if any 29 | * 30 | * @return Length of the read number or 0 if s[i0, ...] is not a valid exponent. 31 | */ 32 | 33 | size_t readexp(const std::string &s, size_t i0, size_t i1, int &real_part, int &imag_part); 34 | 35 | 36 | /** 37 | * Formats an exponent in superscript unicode. 38 | * Inverse of readexp. 39 | */ 40 | 41 | std::string format_exponent(int real_part, int imag_part = 0); 42 | 43 | std::string format_subscript(int re); 44 | -------------------------------------------------------------------------------- /Engine/Parser/utf8/ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | utf8 cpp library 2 | Release 2.3.4 3 | 4 | A minor bug fix release. Thanks to all who reported bugs. 5 | 6 | Note: Version 2.3.3 contained a regression, and therefore was removed. 7 | 8 | Changes from version 2.3.2 9 | - Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';' 10 | - Bug fix [36]: replace_invalid() only works with back_inserter 11 | 12 | Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes 13 | -------------------------------------------------------------------------------- /Engine/Parser/utf8/utf8.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Nemanja Trifunovic 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person or organization 5 | obtaining a copy of the software and accompanying documentation covered by 6 | this license (the "Software") to use, reproduce, display, distribute, 7 | execute, and transmit the Software, and to prepare derivative works of the 8 | Software, and to permit third-parties to whom the Software is furnished to 9 | do so, all subject to the following: 10 | 11 | The copyright notices in the Software and this entire statement, including 12 | the above license grant, this restriction and the following disclaimer, 13 | must be included in all copies of the Software, in whole or in part, and 14 | all derivative works of the Software, unless such copies or derivative 15 | works are solely in the form of machine-executable object code generated by 16 | a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | 28 | #ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 29 | #define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 30 | 31 | #include "utf8/checked.h" 32 | #include "utf8/unchecked.h" 33 | 34 | #endif // header guard 35 | -------------------------------------------------------------------------------- /Graphs/Geometry/AxisIndex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum AxisIndex 4 | { 5 | X_AXIS = 1, 6 | Y_AXIS = 2, 7 | Z_AXIS = 3 8 | }; 9 | -------------------------------------------------------------------------------- /Graphs/Geometry/Rotation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Matrix.h" 4 | #include "Quaternion.h" 5 | #include "../../Persistence/Serializer.h" 6 | 7 | class Rotation : public Serializable 8 | { 9 | public: 10 | Rotation(); // starts as identity 11 | 12 | void save(Serializer &s) const; 13 | void load(Deserializer &s); 14 | 15 | void rotate(double rx, double ry, double rz, bool concat=true); 16 | void rotate(const Rotation &other); 17 | void rotate(const P3d &axis, double angle); 18 | 19 | P3d operator() (const P3d &v) const{ return m * v; } ///< Image of v (double version) 20 | P3f operator() (const P3f &v) const{ return mf * v; } ///< Image of v (float version) 21 | P3d operator[] (const P3d &v) const{ return mi * v; } ///< Preimage of v 22 | 23 | double axis_angle(P3d &axis) const; ///< Get axis-angle representation 24 | 25 | void set(double phi, double psi, double theta); ///< Set from Euler angles 26 | void get(double &phi, double &psi, double &theta) const; ///< Get Euler angles 27 | 28 | Quaternion quat() const { return a; } 29 | void quat(const Quaternion &q) { a = q; update(); } 30 | 31 | private: 32 | Quaternion a; ///< Primary storage 33 | 34 | mutable M3d m; ///< a as a rotation matrix 35 | mutable M3d mi; ///< m transposed/inverted 36 | mutable M3f mf; ///< mf = (M3f)m 37 | 38 | void update(); ///< Sync m, mi and mf to new value of a 39 | }; 40 | -------------------------------------------------------------------------------- /Graphs/Geometry/Triangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Vector.h" 3 | 4 | class Triangle 5 | { 6 | public: 7 | Triangle(const P2d &A, const P2d &B, const P2d &C) : A(A), B(B), C(C) 8 | { 9 | m.a11 = A.x-C.x; m.a12 = B.x-C.x; 10 | m.a21 = A.y-C.y; m.a22 = B.y-C.y; 11 | D = m.det(); 12 | } 13 | inline bool contains(double x, double y) 14 | { 15 | // aA+bB+cC = (x,y), a+b+c = 1 --> 16 | // x - C.x = a*(A.x-C.x) + b*(B.x-C.x); 17 | // y - C.y = a*(A.y-C.y) + b*(B.y-C.y); 18 | // --> a,b in [0..1] 19 | double Da = (x-C.x)*m.a22 - (y-C.y)*m.a12; 20 | double Db = (y-C.y)*m.a11 - (x-C.x)*m.a21; 21 | return D >= 0.0 ? (Da >= 0.0 && Db >= 0.0 && Da+Db <= D) : (Da <= 0.0 && Db <= 0.0 && Da+Db >= D); 22 | } 23 | private: 24 | P2d A, B, C; 25 | M2d m; 26 | double D; 27 | }; 28 | -------------------------------------------------------------------------------- /Graphs/Graphics/AxisLabels.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | class GridIterator; 6 | class LabelIterator; 7 | 8 | class AxisLabels 9 | { 10 | public: 11 | AxisLabels(double pixel, double range); 12 | bool valid() const{ return !invalid; } 13 | 14 | private: 15 | friend class GridIterator; 16 | friend class LabelIterator; 17 | 18 | double major, minor, label; 19 | int subdiv; // number of minor ticks between major ones + 1 20 | bool invalid; 21 | }; 22 | 23 | class GridIterator 24 | { 25 | public: 26 | GridIterator(const AxisLabels &a, double min, double max); 27 | bool done() const{ return i >= n; } 28 | void operator++( ){ ++i; assert(i <= n); } 29 | void operator++(int){ ++i; assert(i <= n); } 30 | double x() const{ return x0 + a.minor * i; } 31 | bool is_minor() const{ return (i+sub) % a.subdiv != 0; } 32 | 33 | private: 34 | const AxisLabels &a; 35 | int i, n, sub; // i = current index, n = total, sub = subdivision index for #0 (see minor()) 36 | double x0; // first grid line 37 | }; 38 | 39 | class LabelIterator 40 | { 41 | public: 42 | LabelIterator(const AxisLabels &a, double min, double max, double char_size); // char_size should be 0 for vertically stacked text 43 | bool done() const{ return i >= n || n > 100; } 44 | void operator++( ){ ++i; assert(i <= n); } 45 | void operator++(int){ ++i; assert(i <= n); } 46 | double x() const{ return x0 + a.label * i; } 47 | std::string label() const; // will be empty for left out places (which should still get a tick but no text) 48 | bool skipped() const{ return (i+sub) % skip != 0; } 49 | int max_len() const{ return max_label_len; } 50 | 51 | private: 52 | const AxisLabels &a; 53 | int i, n, sub, skip; // i = current index, n = total, sub = skipping index for #0 54 | double x0; // first label 55 | int max_label_len; 56 | }; 57 | -------------------------------------------------------------------------------- /Graphs/Graphics/Face.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Edge.h" 3 | 4 | //---------------------------------------------------------------------------------------------------------------------- 5 | // Face 6 | //---------------------------------------------------------------------------------------------------------------------- 7 | 8 | struct Face 9 | { 10 | POOL_ITEM(Face); 11 | 12 | Edge *e; 13 | bool forward; // direction on the initial edge 14 | 15 | Face(Edge *e, bool forward) : e(e), forward(forward) 16 | { 17 | assert(e); 18 | assert(forward ? e->lb : e->la); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_AreaGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_Graph.h" 3 | #include "../OpenGL/GL_Mesh.h" 4 | #include "../OpenGL/GL_Mask.h" 5 | #include "../Graph.h" 6 | 7 | class GL_AreaGraph : public GL_Graph 8 | { 9 | public: 10 | GL_AreaGraph(Graph &graph) : GL_Graph(graph){ } 11 | 12 | virtual void update(int n_threads, double quality); 13 | virtual void draw(GL_RM &rm) const; 14 | 15 | virtual Opacity opacity() const; 16 | 17 | virtual bool needs_depth_sort() const; 18 | 19 | virtual void depth_sort(const P3f &view_vector) 20 | { 21 | if (!needs_depth_sort()) return; 22 | mesh.depth_sort(view_vector); 23 | } 24 | 25 | virtual bool has_unit_normals() const{ return graph.options.shading_mode == Shading_Flat; } 26 | 27 | protected: 28 | GL_Mesh mesh; 29 | GL_MaskScale mask_scale; 30 | 31 | private: 32 | void update_without_subdivision(int n_threads, std::vector &info); 33 | //void update_with_subdivision(int n_threads, int depth, std::vector &info); 34 | }; 35 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_Axis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Geometry/Axis.h" 3 | #include "../Geometry/Camera.h" 4 | #include 5 | #include 6 | #include "../OpenGL/GL_String.h" 7 | #include "../OpenGL/GL_StringCache.h" 8 | struct Plot; 9 | 10 | class GL_Axis 11 | { 12 | public: 13 | GL_Axis(Axis &axis, Camera &camera) : axis(axis), camera(camera){ } 14 | void draw(const Plot &plot) const; 15 | 16 | private: 17 | Axis &axis; 18 | Camera &camera; 19 | mutable GL_StringCache labelCache; 20 | 21 | void draw2D() const; 22 | void draw3D() const; 23 | void draw3D_cross() const; 24 | void drawSphere() const; 25 | }; 26 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_ColorGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_Graph.h" 3 | #include "../Plot.h" 4 | #include "../Geometry/Vector.h" 5 | #include "../OpenGL/GL_Image.h" 6 | 7 | class GL_ColorGraph : public GL_Graph 8 | { 9 | public: 10 | GL_ColorGraph(Graph &graph) : GL_Graph(graph){ } 11 | 12 | virtual void update(int n_threads, double quality); 13 | virtual void draw(GL_RM &rm) const; 14 | 15 | virtual bool needs_depth_sort() const{ return false; } 16 | virtual void depth_sort(const P3f &v){ (void)v; } 17 | 18 | virtual Opacity opacity() const; 19 | 20 | virtual bool has_unit_normals() const{ return true; } // has no normals 21 | 22 | private: 23 | GL_Image im; 24 | float xr, yr, zr; 25 | }; 26 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_Graph.cc: -------------------------------------------------------------------------------- 1 | #include "GL_Graph.h" 2 | #include "../Graph.h" 3 | #include "../Plot.h" 4 | #include "../Geometry/Axis.h" 5 | #include "../OpenGL/GL_Context.h" 6 | 7 | static inline int max_planes() 8 | { 9 | static int N = 0; 10 | if (!N) glGetIntegerv(GL_MAX_CLIP_PLANES, &N); 11 | assert(N >= 6); // 6 should be minimum 12 | return N; 13 | } 14 | 15 | static inline bool clip(const Graph &graph, int &first_plane_id) 16 | { 17 | if (!graph.clipping()) return false; 18 | bool ccp = graph.plot.options.clip.on(); 19 | if (ccp && max_planes() <= 6) return false; 20 | first_plane_id = GL_CLIP_PLANE0 + ccp; 21 | return true; 22 | } 23 | 24 | void GL_Graph::start_drawing() const 25 | { 26 | GL_CHECK; 27 | 28 | int P = -1; 29 | const Axis &axis = graph.plot.axis; 30 | if (axis.type() == Axis::Box && clip(graph, P)) 31 | { 32 | assert(P >= GL_CLIP_PLANE0); 33 | P4d cf; 34 | double r; 35 | 36 | r = fabs(axis.range(2) / axis.range(0)) + 1e-4; 37 | cf.set(0, 0, -1, r); glClipPlane(P, cf); glEnable(P++); 38 | cf.set(0, 0, 1, r); glClipPlane(P, cf); glEnable(P++); 39 | 40 | if (!graph.isGraph()) 41 | { 42 | r = 1.0 + 1e-4; // +1e-4 saves the outermost grid lines of a graph from being clipped 43 | cf.set(-1, 0, 0, r); glClipPlane(P, cf); glEnable(P++); 44 | cf.set( 1, 0, 0, r); glClipPlane(P, cf); glEnable(P++); 45 | 46 | r = fabs(axis.range(1) / axis.range(0)) + 1e-4; 47 | cf.set(0, -1, 0, r); glClipPlane(P, cf); glEnable(P++); 48 | cf.set(0, 1, 0, r); glClipPlane(P, cf); glEnable(P++); 49 | } 50 | } 51 | 52 | GL_CHECK; 53 | } 54 | 55 | void GL_Graph::finish_drawing() const 56 | { 57 | GL_CHECK; 58 | 59 | int P = -1; 60 | if (graph.plot.axis.type() == Axis::Box && clip(graph, P)) 61 | { 62 | assert(P >= GL_CLIP_PLANE0); 63 | for (int i = 0; i < 6; ++i) glDisable(P+i); 64 | } 65 | 66 | glDepthMask(GL_TRUE); 67 | 68 | GL_CHECK; 69 | } 70 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_Graph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Geometry/Vector.h" 3 | class Graph; 4 | struct Plot; 5 | class GL_RM; 6 | 7 | enum Opacity 8 | { 9 | OPAQUE = 0, // alpha is always 0 or 255 10 | ANTIALIASED = 1, // opaque if aa != AA_LINES, otherwise transparent 11 | TRANSPARENT = 2 // has transparency 12 | }; 13 | 14 | class GL_Graph 15 | { 16 | public: 17 | GL_Graph(Graph &graph) : graph(graph){ } 18 | virtual ~GL_Graph(){ } 19 | 20 | virtual void draw(GL_RM &rm) const = 0; 21 | virtual void update(int n_threads, double quality) = 0; 22 | virtual bool needs_depth_sort() const = 0; 23 | virtual void depth_sort(const P3f &view_vector) = 0; // should use needs_depth_sort! 24 | 25 | virtual Opacity opacity() const = 0; 26 | virtual bool has_unit_normals() const = 0; 27 | virtual bool wants_backface_culling() const{ return false; } 28 | 29 | protected: 30 | Graph &graph; 31 | 32 | void start_drawing() const; // handles clipping 33 | void finish_drawing() const; 34 | }; 35 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_Histogram.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_AreaGraph.h" 3 | 4 | class GL_Histogram : public GL_AreaGraph 5 | { 6 | public: 7 | GL_Histogram(Graph &graph) : GL_AreaGraph(graph){ } 8 | 9 | virtual bool has_unit_normals() const{ return true; } 10 | virtual bool wants_backface_culling() const{ return true; } 11 | 12 | virtual void update(int n_threads, double quality); 13 | }; 14 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_HistogramPointGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_PointGraph.h" 3 | 4 | //---------------------------------------------------------------------------------------------------------------------- 5 | // GL_HistogramPointGraph 6 | //---------------------------------------------------------------------------------------------------------------------- 7 | 8 | class GL_HistogramPointGraph : public GL_PointGraph 9 | { 10 | public: 11 | GL_HistogramPointGraph(Graph &graph) : GL_PointGraph(graph){ } 12 | 13 | virtual bool has_unit_normals() const{ return true; } 14 | 15 | virtual void update(int n_threads, double quality); 16 | }; 17 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_ImplicitAreaGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_AreaGraph.h" 3 | 4 | class GL_ImplicitAreaGraph : public GL_AreaGraph 5 | { 6 | public: 7 | GL_ImplicitAreaGraph(Graph &graph) : GL_AreaGraph(graph){ } 8 | 9 | virtual bool has_unit_normals() const{ return false; } 10 | 11 | virtual void update(int n_threads, double quality); 12 | }; 13 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_ImplicitLineGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../OpenGL/GL_Dots.h" 4 | #include "../OpenGL/GL_Lines.h" 5 | #include "GL_LineGraph.h" 6 | 7 | class GL_ImplicitLineGraph : public GL_LineGraph 8 | { 9 | public: 10 | GL_ImplicitLineGraph(Graph &graph) : GL_LineGraph(graph){ } 11 | 12 | virtual bool has_unit_normals() const{ return true; } // has no normals 13 | 14 | virtual void update(int n_threads, double quality); 15 | }; 16 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_LineGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../OpenGL/GL_Dots.h" 4 | #include "../OpenGL/GL_Lines.h" 5 | #include "GL_Graph.h" 6 | 7 | class GL_LineGraph : public GL_Graph 8 | { 9 | public: 10 | GL_LineGraph(Graph &graph) : GL_Graph(graph){ } 11 | 12 | virtual void update(int n_threads, double quality); 13 | virtual void draw(GL_RM &rm) const; 14 | 15 | virtual Opacity opacity() const; 16 | 17 | virtual bool needs_depth_sort() const; 18 | 19 | virtual void depth_sort(const P3f &view_vector) 20 | { 21 | if (!needs_depth_sort()) return; 22 | lines.depth_sort(view_vector); 23 | dots.depth_sort(view_vector); 24 | } 25 | 26 | virtual bool has_unit_normals() const{ return true; } // has no normals 27 | 28 | protected: 29 | GL_Lines lines; 30 | GL_Dots dots; 31 | }; 32 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_PointGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_Graph.h" 3 | #include "../Geometry/Vector.h" 4 | #include 5 | 6 | //---------------------------------------------------------------------------------------------------------------------- 7 | // GL_PointGraph 8 | //---------------------------------------------------------------------------------------------------------------------- 9 | 10 | class GL_PointGraph : public GL_Graph 11 | { 12 | public: 13 | GL_PointGraph(Graph &graph) : GL_Graph(graph), nvertexes(0){} 14 | 15 | virtual void update(int n_threads, double quality); 16 | virtual void draw(GL_RM &rm) const; 17 | 18 | virtual Opacity opacity() const; 19 | 20 | virtual void depth_sort(const P3f &view_vector); 21 | virtual bool needs_depth_sort() const; 22 | 23 | virtual bool has_unit_normals() const{ return true; } // has no normals 24 | 25 | protected: 26 | std::unique_ptr pau; // base points 27 | std::unique_ptr vau; // vectors (for vector fields) 28 | size_t nvertexes; 29 | 30 | private: 31 | float max_len; // for scaling vector fields (as is gridsize) 32 | float gridsize; // distance between neighbouring grid points in any direction and in GL coordinates 33 | }; 34 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_RiemannColorGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_AreaGraph.h" 3 | 4 | class GL_RiemannColorGraph : public GL_AreaGraph 5 | { 6 | public: 7 | GL_RiemannColorGraph(Graph &graph) : GL_AreaGraph(graph){ } 8 | 9 | virtual void update(int n_threads, double quality); 10 | 11 | virtual bool has_unit_normals() const{ return true; } 12 | 13 | private: 14 | void update(int n_threads, std::vector &info); 15 | }; 16 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_RiemannHistogram.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_AreaGraph.h" 3 | 4 | class GL_RiemannHistogram : public GL_AreaGraph 5 | { 6 | public: 7 | GL_RiemannHistogram(Graph &graph) : GL_AreaGraph(graph){ } 8 | 9 | virtual bool has_unit_normals() const{ return true; } 10 | virtual bool wants_backface_culling() const{ return true; } 11 | 12 | virtual void update(int n_threads, double quality); 13 | }; 14 | -------------------------------------------------------------------------------- /Graphs/Graphics/GL_RiemannHistogramPointGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_PointGraph.h" 3 | 4 | //---------------------------------------------------------------------------------------------------------------------- 5 | // GL_RiemannHistogramPointGraph 6 | //---------------------------------------------------------------------------------------------------------------------- 7 | 8 | class GL_RiemannHistogramPointGraph : public GL_PointGraph 9 | { 10 | public: 11 | GL_RiemannHistogramPointGraph(Graph &graph) : GL_PointGraph(graph){ } 12 | 13 | virtual bool has_unit_normals() const{ return true; } 14 | 15 | virtual void update(int n_threads, double quality); 16 | }; 17 | -------------------------------------------------------------------------------- /Graphs/Graphics/ThreadStorage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template struct ThreadStorage 4 | { 5 | size_t vertex_count; // number of vertexes in our vertex pool 6 | size_t face_count; // number of faces in our face pool 7 | size_t vertex_offset; // for transfer: where do the vertices for this thread start 8 | size_t face_offset; // same for faces 9 | 10 | MemoryPool faces; // must be separate so we can iterate them 11 | RawMemoryPool pool; 12 | 13 | char padding[128-4*8-sizeof(RawMemoryPool)-sizeof(MemoryPool)]; 14 | 15 | ThreadStorage() : face_count(0), vertex_count(0), faces(128*64), pool(512*1024, 64) 16 | { 17 | } 18 | 19 | ThreadStorage(const ThreadStorage &) = delete; 20 | ThreadStorage &operator=(const ThreadStorage &) = delete; 21 | 22 | /*void *face_block(size_t n) 23 | { 24 | face_count += n; 25 | return faces.alloc(n*sizeof(Face)); 26 | }*/ 27 | 28 | /*/ perform the actual splitting 29 | void subdivide_finish() 30 | { 31 | PoolIterator fi(faces, sizeof(Face)); 32 | size_t n = face_count; 33 | active_faces = 0; 34 | // if this stays 0, does not mean that this group is finished! neighbour groups can divide our faces too 35 | // divide_start could then be skipped though 36 | for (size_t i = 0; i < n; ++i, ++fi) 37 | { 38 | assert(fi); 39 | Face *f = (Face*)*fi; 40 | if (!f->done) 41 | { 42 | f->divide_finish(*this); 43 | if (!f->done) ++active_faces; 44 | } 45 | } 46 | }*/ 47 | }; 48 | -------------------------------------------------------------------------------- /Graphs/Graphics/Vertex2D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "VisibilityFlags.h" 3 | #include "Vector.h" 4 | #include 5 | #include "MemoryPool.h" 6 | #include "ThreadInfo.h" 7 | #include 8 | 9 | //---------------------------------------------------------------------------------------------------------------------- 10 | // Vertex 11 | //---------------------------------------------------------------------------------------------------------------------- 12 | 13 | struct Vertex2D 14 | { 15 | POOL_ITEM(Vertex2D); 16 | 17 | double u, v; // variable values 18 | P3f p; // axis-mapped, in [-1,1] coordinates 19 | P3f normal; // vertex normal 20 | P2f texture; // texture coordinates 21 | unsigned gl_index; // index in the gl display list during drawing 22 | bool exists; // point could be calculated / function is defined 23 | bool uglued, vglued; // one of the points where S1 x S1 is glued together? 24 | //#ifdef DEBUG 25 | //void *marker; // remember who counted this, so we can be sure it's the same thread that copies it to the GL array 26 | //#endif 27 | 28 | VisibilityFlags vis; 29 | 30 | char padding[2]; // to 64 bits 31 | 32 | static const unsigned npos = 0xFFFFFFFF; 33 | static const unsigned counted = 0xFFFFFFFE; 34 | 35 | Vertex2D(double u, double v, ThreadInfo &ti) : gl_index(npos), uglued(false), vglued(false), u(u), v(v) 36 | { 37 | memset(normal, 0, sizeof(P3f)); 38 | calc(ti); 39 | if (ti.ic.texture && exists) ti.ia.map_texture(u, v, texture); 40 | } 41 | 42 | // create a midpoint 43 | Vertex2D(const Vertex2D &a, const Vertex2D &b, ThreadInfo &ti) : gl_index(npos), uglued(a.uglued && b.uglued), vglued(a.vglued && b.vglued) 44 | { 45 | u = 0.5 * (a.u + b.u); 46 | v = 0.5 * (a.v + b.v); 47 | if (a.uglued != b.uglued && fabs(a.u - b.u) > M_PI) u += M_PI; 48 | if (a.vglued != b.vglued && fabs(a.v - b.v) > M_PI) v += M_PI; 49 | memset(normal, 0, sizeof(P3f)); 50 | calc(ti); 51 | } 52 | 53 | private: 54 | void calc(ThreadInfo &ti, bool same_u = false, bool same_v = false) 55 | { 56 | assert(gl_index == npos); 57 | ti.eval(u, v, p, exists, same_u, same_v); 58 | if (exists) 59 | { 60 | vis.set(ti.ia, p); 61 | ti.ia.map_texture(u, v, texture); 62 | } 63 | else 64 | { 65 | vis.set_invalid(); 66 | } 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /Graphs/Graphics/VisibilityFlags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Info.h" 3 | 4 | struct VisibilityFlags 5 | { 6 | VisibilityFlags() : all(0) { } 7 | 8 | inline void set(const DI_Axis &ia, const P3f &p) 9 | { 10 | all = 0; 11 | if (ia.clipping) 12 | { 13 | x_min = (p.x < -1.0); 14 | x_max = (p.x > 1.0); 15 | y_min = (p.y < -ia.yh); 16 | y_max = (p.y > ia.yh); 17 | z_min = (p.z < -ia.zh); 18 | z_max = (p.z > ia.zh); 19 | } 20 | } 21 | 22 | inline void set_invalid(){ all = -1; } 23 | inline bool valid() const{ return all != -1; } 24 | 25 | inline bool operator*(VisibilityFlags b) const{ return (all & b.all) != 0; } 26 | 27 | static inline bool visible(VisibilityFlags a, VisibilityFlags b) 28 | { 29 | return !a.invalid && !b.invalid && !(a.all & b.all); 30 | } 31 | static inline bool visible(VisibilityFlags a, VisibilityFlags b, VisibilityFlags c) 32 | { 33 | return !a.invalid && !b.invalid && !c.invalid && !(a.all & b.all & c.all); 34 | } 35 | 36 | private: 37 | 38 | union 39 | { 40 | char all; // if non-0, point is invisible, if a.all & b.all != 0, then the connecting line is invisible 41 | struct 42 | { 43 | bool x_min : 1; // true if point is outside of range to the left 44 | bool x_max : 1; // right 45 | bool y_min : 1; // front 46 | bool y_max : 1; // back 47 | bool z_min : 1; // bottom 48 | bool z_max : 1; // top 49 | bool invalid : 1; // !exists 50 | }; 51 | }; 52 | }; 53 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_AAMode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum AntialiasMode 4 | { 5 | AA_Off = 0, 6 | AA_Lines = 1, 7 | AA_4x = 2, 8 | AA_8x = 3, 9 | AA_4x_Acc = 4, 10 | AA_8x_Acc = 5 11 | }; 12 | 13 | inline AntialiasMode translate(AntialiasMode m, bool accum_ok) 14 | { 15 | if (!accum_ok) 16 | { 17 | if (m == AA_4x_Acc) return AA_4x; 18 | if (m == AA_8x_Acc) return AA_8x; 19 | } 20 | return m; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_BlendMode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../Persistence/Serializer.h" 3 | #include "GL_Color.h" 4 | 5 | struct GL_BlendMode : public Serializable 6 | { 7 | GL_BlendMode(); 8 | 9 | virtual void save(Serializer &s) const; 10 | virtual void load(Deserializer &s); 11 | 12 | void set() const; 13 | 14 | int fA, fB; 15 | GL_Color C; 16 | bool off; 17 | 18 | bool usesConstColor() const; // false if only const alpha is used! but if true, usesConstAlpha is true too 19 | bool usesConstAlpha() const; 20 | bool symmetric() const{ return symmetric(NULL); } 21 | std::string symmetry_info() const; 22 | bool forces_transparency() const; // will the background come through even if alpha=1? 23 | 24 | bool operator== (const GL_BlendMode &m) const 25 | { 26 | if (off && m.off) return true; 27 | if (off != m.off) return false; 28 | assert(!off && !m.off); 29 | if (fA != m.fA || fB != m.fB) return false; 30 | if (usesConstColor()) return C == m.C; 31 | if (usesConstAlpha()) return fabsf(C.a-m.C.a) < 1e-12f; 32 | return true; 33 | } 34 | bool operator!= (const GL_BlendMode &m) const 35 | { 36 | return !operator==(m); 37 | } 38 | 39 | private: 40 | bool symmetric(std::ostream *os) const; 41 | }; 42 | 43 | struct GL_DefaultBlendMode 44 | { 45 | std::string name; 46 | GL_BlendMode mode; 47 | }; 48 | 49 | const std::vector &DefaultBlendModes(); 50 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_ClippingPlane.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../Persistence/Serializer.h" 3 | #include "../Geometry/Vector.h" 4 | #include 5 | #include 6 | class Axis; 7 | 8 | class GL_ClippingPlane : public Serializable 9 | { 10 | public: 11 | GL_ClippingPlane() : m_normal(0.0f, 1.0f, 0.0f), m_distance(0.0f), m_locked(false), m_enabled(false), m_id(0){ } 12 | 13 | virtual void save(Serializer &s) const; 14 | virtual void load(Deserializer &s); 15 | 16 | bool on() const{ return m_enabled; } 17 | void on(bool f){ m_enabled = f; } 18 | 19 | void set(const Axis &axis, GLenum plane_ID = GL_CLIP_PLANE0) const; 20 | void unset() const; 21 | 22 | void draw(const Axis &axis) const; // draws the intersections with the axis box 23 | 24 | float distance() const{ return m_distance; } 25 | void distance(float d){ assert(d >= -2.0f && d <= 2.0f); m_distance = d; } 26 | 27 | const P3f &normal() const{ return m_normal; } 28 | void normal(const P3f &n){ assert(n.absq() > 0.0f); m_normal = n; m_normal.to_unit(); } 29 | 30 | bool locked() const{ return m_locked; } 31 | void locked(bool l){ m_locked = l; } 32 | 33 | private: 34 | bool m_enabled; 35 | P3f m_normal; 36 | float m_distance; // in +-√3, 0 = center of axis box 37 | bool m_locked; // don't follow camera rotation? 38 | mutable GLenum m_id; // last set plane_ID 39 | }; 40 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Color.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../Persistence/Serializer.h" 3 | #include 4 | #include 5 | #include 6 | #ifdef _WINDOWS 7 | #include 8 | #endif 9 | 10 | struct GL_Color : public Serializable 11 | { 12 | GL_Color(float r, float g, float b, float a = 1.0f) : r(r), g(g), b(b), a(a){ } 13 | GL_Color(float y = 1.0f, float a = 1.0f) : r(y), g(y), b(y), a(a){ } 14 | GL_Color(const GL_Color &) = default; 15 | 16 | virtual void save(Serializer &s) const; 17 | virtual void load(Deserializer &s); 18 | 19 | bool visible() const{ return a >= 1e-8f; } 20 | bool opaque() const{ return a >= 1.0f-1e-8f; } 21 | float lightness() const{ return 0.299f*r + 0.587f*g + 0.114f*b; } 22 | 23 | union 24 | { 25 | struct{ float r, g, b, a; }; 26 | float v[4]; 27 | }; 28 | 29 | #ifdef _WINDOWS 30 | operator COLORREF() const { return RGB(int(r*255.0f), int(g*255.0f), int(b*255.0f)); } 31 | 32 | Gdiplus::Color convert() const 33 | { 34 | return Gdiplus::Color(BYTE(a*255.0f), BYTE(r*255.0f), BYTE(g*255.0f), BYTE(b*255.0f)); 35 | } 36 | 37 | GL_Color &operator= (COLORREF c) 38 | { 39 | r = GetRValue(c) / 255.0f; 40 | g = GetGValue(c) / 255.0f; 41 | b = GetBValue(c) / 255.0f; 42 | // alpha is not changed! 43 | return *this; 44 | } 45 | int GetAlpha() const { return int(a*255.0f); } 46 | void SetAlpha(int a_) { a = a_ / 255.0f; } 47 | #endif 48 | 49 | void clamp() 50 | { 51 | if (r < 0.0f) r = 0.0f; if (r > 1.0f) r = 1.0f; 52 | if (g < 0.0f) g = 0.0f; if (g > 1.0f) g = 1.0f; 53 | if (b < 0.0f) b = 0.0f; if (b > 1.0f) b = 1.0f; 54 | if (a < 0.0f) a = 0.0f; if (a > 1.0f) a = 1.0f; 55 | } 56 | 57 | void set() const; 58 | void set_clear() const; 59 | 60 | bool operator== (const GL_Color &c) const{ return fabsf(r-c.r) < 1e-8f && fabsf(g-c.g) < 1e-8f && fabsf(b-c.b) < 1e-8f && fabsf(a-c.a) < 1e-8f; } 61 | bool operator!= (const GL_Color &c) const{ return !operator==(c); } 62 | 63 | GL_Color operator* (float alpha) const{ assert(alpha >= 0.0f && alpha <= 1.0f); return GL_Color(r, g, b, a * alpha); } 64 | 65 | std::string to_string() const; 66 | GL_Color &operator= (const std::string &s); // throws if parsing fails 67 | void hsl(double h, double s, double l); // leaves a as is 68 | 69 | static const std::map named_colors(); // red, green, ... 70 | }; 71 | 72 | std::ostream &operator<<(std::ostream &os, const GL_Color &c); 73 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #ifdef DEBUG 6 | #include 7 | #include 8 | 9 | #define GL_CHECK do{\ 10 | GLenum err = glGetError();\ 11 | if (err) std::cerr << "glERROR: " << gluErrorString(err) << std::endl;\ 12 | assert(err == GL_NO_ERROR);\ 13 | }while(0) 14 | 15 | #else 16 | #define GL_CHECK 17 | #endif 18 | 19 | 20 | class GL_Context 21 | { 22 | public: 23 | explicit GL_Context(void *c) : ctx(c){ } 24 | explicit operator void* () const{ return ctx; } 25 | operator bool() const{ return ctx != NULL; } 26 | bool operator== (const void *c) const{ return ctx == c; } 27 | inline void delete_texture(GLuint &texture) 28 | { 29 | if (ctx && texture) glDeleteTextures(1, &texture); 30 | texture = 0; 31 | } 32 | 33 | private: 34 | void *ctx; 35 | }; 36 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Dots.cc: -------------------------------------------------------------------------------- 1 | #include "GL_Dots.h" 2 | #include 3 | #include 4 | 5 | void GL_Dots::resize(size_t np) 6 | { 7 | if (n_points != np) 8 | { 9 | n_points = 0; 10 | p.reset(nullptr); 11 | p.reset(new P3f[np]); 12 | n_points = np; 13 | } 14 | } 15 | 16 | void GL_Dots::draw() const 17 | { 18 | glEnableClientState(GL_VERTEX_ARRAY); 19 | glVertexPointer(3, GL_FLOAT, 0, p.get()); 20 | glDrawArrays(GL_POINTS, (GLint)0, (GLsizei)n_points); 21 | glDisableClientState(GL_VERTEX_ARRAY); 22 | } 23 | 24 | void GL_Dots::depth_sort(const P3f &view) 25 | { 26 | if (!n_points) return; 27 | P3f *p = points(); 28 | std::sort(p, p + n_points, [&view](const P3f &a, const P3f &b)->bool 29 | { 30 | return a*view > b*view; 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Dots.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Geometry/Vector.h" 3 | #include 4 | 5 | /** 6 | * GL_Dots is a collection of isolated points. 7 | */ 8 | 9 | class GL_Dots 10 | { 11 | public: 12 | GL_Dots() : n_points(0){ } 13 | 14 | GL_Dots(const GL_Dots &m) = delete; 15 | GL_Dots &operator=(const GL_Dots &) = delete; 16 | 17 | void resize(size_t n_points); 18 | 19 | void draw() const; 20 | void depth_sort(const P3f &view); 21 | 22 | P3f *points() { return p.get(); } 23 | const P3f *points () const{ return p.get(); } 24 | 25 | private: 26 | std::unique_ptr p; 27 | size_t n_points; 28 | }; 29 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_FBO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_Context.h" 3 | 4 | class GL_FBO 5 | { 6 | public: 7 | GL_FBO() : fbo(0), texture(0), depth(0), w(0), h(0){ } 8 | 9 | bool init(GL_Context context, unsigned w, unsigned h, int bpp, bool depth_buffer); 10 | bool clear(GL_Context context){ return init(context, 0, 0, 0, false); } 11 | 12 | void bind() const; // makes OpenGL output go into this buffer 13 | void draw(bool blend, float alpha = 1.0f) const; // blend=false, alpha<1 scales the copied pixels 14 | 15 | void acc_load(const GL_FBO &fbo, float alpha = 1.0f); 16 | void acc_add (const GL_FBO &fbo, float alpha = 1.0f); 17 | 18 | private: 19 | GLuint fbo, texture, depth; 20 | unsigned w, h; // size of texture 21 | }; 22 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Font.cc: -------------------------------------------------------------------------------- 1 | #include "GL_Font.h" 2 | #include "../../Utility/StringFormatting.h" 3 | 4 | void GL_Font::save(Serializer &s) const 5 | { 6 | s.string_(name); 7 | s.float_(size); 8 | color.save(s); 9 | } 10 | void GL_Font::load(Deserializer &s) 11 | { 12 | s.string_(name); 13 | s.float_(size); 14 | color.load(s); 15 | } 16 | 17 | std::ostream &operator<<(std::ostream &os, const GL_Font &f) 18 | { 19 | os << '(' << f.name << ", " << f.size << "pt, " << f.color << ')'; 20 | return os; 21 | } 22 | 23 | std::string GL_Font::to_string() const 24 | { 25 | return name + format(" %d", (int)round(size)); 26 | } 27 | 28 | GL_Font& GL_Font::operator= (const std::string &s) 29 | { 30 | size_t n = s.length(); 31 | if (!n) 32 | { 33 | // TODO: set some default font? 34 | throw error("Not a valid font", s); 35 | } 36 | 37 | // split into name and size 38 | size_t i = n; 39 | while (i > 0 && isdigit(s[i-1])) --i; 40 | if (i < n && i > 0 && (s[i-1]=='+' || s[i-1]=='-')) --i; 41 | if (i < n) 42 | { 43 | int k; is_int(s.c_str()+i, k); 44 | size = (float)k; 45 | while (i > 0 && isspace(s[i-1])) --i; 46 | if (i > 0) name = s.substr(0, i); 47 | } 48 | else 49 | { 50 | name = s; 51 | } 52 | // TODO: if name = "bold" and such, modify current font 53 | return *this; 54 | } 55 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Font.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "GL_Color.h" 5 | 6 | struct GL_Font : public Serializable 7 | { 8 | GL_Font(const std::string &name, float size) : name(name), size(size), color(0,0,0,1){} 9 | 10 | std::string name; 11 | float size; 12 | GL_Color color; 13 | 14 | virtual void save(Serializer &s) const; 15 | virtual void load(Deserializer &s); 16 | bool visible() const{ return color.visible() && size > 1e-12f; } 17 | bool operator== (const GL_Font &f) const{ return name==f.name && color==f.color && fabs(size-f.size) < 1e-12f; } 18 | 19 | std::string to_string() const; 20 | GL_Font& operator= (const std::string &s); 21 | }; 22 | 23 | std::ostream &operator<<(std::ostream &os, const GL_Font &f); 24 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Light.cc: -------------------------------------------------------------------------------- 1 | #include "GL_Light.h" 2 | #include 3 | 4 | GL_Light::GL_Light() : v(-1, 1, 2, 0) 5 | { 6 | } 7 | 8 | void GL_Light::setup(bool enable) const 9 | { 10 | enabled = enable; 11 | if (enabled) 12 | { 13 | glEnable(GL_LIGHT0); 14 | glMatrixMode(GL_MODELVIEW); 15 | glPushMatrix(); 16 | glLoadIdentity(); 17 | 18 | glLightfv(GL_LIGHT0, GL_POSITION, v); 19 | 20 | glPopMatrix(); 21 | glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 22 | } 23 | else 24 | { 25 | glDisable(GL_LIGHTING); 26 | } 27 | } 28 | 29 | void GL_Light::on(float shinyness) const 30 | { 31 | if (!enabled) return; 32 | 33 | glEnable(GL_LIGHTING); 34 | 35 | if (shinyness > 1e-8f) 36 | { 37 | P4f specular(0.25f*shinyness); specular.w = 1.0f; 38 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); 39 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64.0f*shinyness); 40 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); 41 | } 42 | else 43 | { 44 | P4f specular(0.0f); specular.w = 1.0f; 45 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); 46 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); 47 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); 48 | } 49 | } 50 | 51 | void GL_Light::off() const 52 | { 53 | glDisable(GL_LIGHTING); 54 | } 55 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Light.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Geometry/Vector.h" 3 | 4 | class GL_Light 5 | { 6 | public: 7 | GL_Light(); 8 | 9 | void setup(bool enable) const; // setup position, but do not turn lighting on 10 | 11 | void on(float shinyness) const; 12 | void off() const; 13 | 14 | void direction(const P3f &w){ v.set(w, 0.0f); } 15 | void position (const P3f &w){ v.set(w, 1.0f); } 16 | 17 | private: 18 | P4f v; // position or direction 19 | mutable bool enabled; // if false, on() does nothing 20 | }; 21 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Lines.cc: -------------------------------------------------------------------------------- 1 | #include "GL_Lines.h" 2 | #include 3 | #include 4 | #include 5 | 6 | void GL_Lines::resize(size_t np, const std::vector &segments) 7 | { 8 | s = segments; 9 | if (n_points != np) 10 | { 11 | n_points = 0; 12 | p.reset(nullptr); 13 | p.reset(new P3f[np]); 14 | n_points = np; 15 | } 16 | 17 | #ifdef DEBUG 18 | size_t N = 0; 19 | for (size_t n : s) N += n; 20 | assert(N == np); 21 | #endif 22 | } 23 | 24 | void GL_Lines::resize(size_t np) 25 | { 26 | s.clear(); 27 | if (n_points != np) 28 | { 29 | n_points = 0; 30 | p.reset(nullptr); 31 | p.reset(new P3f[np]); 32 | n_points = np; 33 | } 34 | assert(np % 2 == 0); 35 | } 36 | 37 | void GL_Lines::draw() const 38 | { 39 | if (!n_points) return; 40 | glEnableClientState(GL_VERTEX_ARRAY); 41 | glVertexPointer(3, GL_FLOAT, 0, p.get()); 42 | 43 | if (s.empty()) 44 | { 45 | glDrawArrays(GL_LINES, 0, (GLsizei)n_points); 46 | } 47 | else 48 | { 49 | size_t i = 0; 50 | for (size_t n : s) 51 | { 52 | glDrawArrays(GL_LINE_STRIP, (GLint)i, (GLsizei)n); 53 | i += n; 54 | } 55 | } 56 | glDisableClientState(GL_VERTEX_ARRAY); 57 | } 58 | 59 | void GL_Lines::draw_dots() const 60 | { 61 | if (!n_points) return; 62 | glEnableClientState(GL_VERTEX_ARRAY); 63 | glVertexPointer(3, GL_FLOAT, 0, p.get()); 64 | 65 | if (s.empty()) 66 | { 67 | glDrawArrays(GL_POINTS, 0, (GLsizei)n_points); 68 | } 69 | else 70 | { 71 | glDrawArrays(GL_POINTS, 0, (GLsizei)std::accumulate(s.begin(), s.end(), 0ULL)); 72 | } 73 | 74 | glDisableClientState(GL_VERTEX_ARRAY); 75 | } 76 | 77 | void GL_Lines::depth_sort(const P3f &view) 78 | { 79 | if (!n_points || !s.empty()) return; 80 | 81 | struct Seg{ P3f A,B; }; 82 | Seg *p = (Seg*)points(); 83 | 84 | std::sort(p, p + n_points/2, [&view](const Seg &a, const Seg &b)->bool 85 | { 86 | return (a.A+a.B)*view > (b.A+b.B)*view; 87 | }); 88 | } 89 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Lines.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Geometry/Vector.h" 3 | #include 4 | #include 5 | 6 | /** 7 | * GL_Lines is a collection of line strips. 8 | */ 9 | 10 | class GL_Lines 11 | { 12 | public: 13 | GL_Lines() : n_points(0){ } 14 | 15 | GL_Lines(const GL_Lines &m) = delete; 16 | GL_Lines &operator=(const GL_Lines &) = delete; 17 | 18 | void resize(size_t n_points, const std::vector &segments); // --> GL_LINE_STRIP 19 | void resize(size_t n_points); // series of lines (p0-p1 p2-p3 p4-p5 ...) --> GL_LINES 20 | 21 | void draw() const; 22 | void draw_dots() const; 23 | void depth_sort(const P3f &view); // only for GL_LINES, not for GL_LINE_STRIP 24 | 25 | P3f *points() { return p.get(); } 26 | const P3f *points () const{ return p.get(); } 27 | 28 | private: 29 | // p[0..s0-1], p[s0..s1-1], ... p[s[n-2], s[n-1]-1] are the line segments unless 30 | // s is empty, which makes p[0..1], p[2..3], ... p[n-2..n-1] the line segments 31 | std::vector s; 32 | 33 | std::unique_ptr p; // points 34 | size_t n_points; // size of p 35 | }; 36 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Geometry/Vector.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | class GL_Mesh 10 | { 11 | public: 12 | enum class NormalMode 13 | { 14 | Vertex, 15 | Face, 16 | None 17 | }; 18 | 19 | GL_Mesh() : n_points(0), n_faces(0), n_normals(0), n_gridlines(0), max_index(0) 20 | { } 21 | 22 | GL_Mesh(const GL_Mesh &m) = delete; 23 | GL_Mesh &operator=(const GL_Mesh &) = delete; 24 | 25 | void resize(size_t n_points, size_t n_faces, NormalMode n, bool textured); 26 | void clear(); 27 | 28 | void draw(bool normals_are_unit) const; //!< caller must set up the texture arrays if needed! 29 | void draw_grid(bool full=false) const; 30 | void draw_normals() const; // for debugging 31 | 32 | void depth_sort(const P3f &view); 33 | 34 | GLuint *faces (){ return f.get(); } 35 | P3f *points (){ return p.get(); } 36 | P3f *normals(){ return n.get(); } 37 | P2f *texture(){ return t.get(); } 38 | GLuint *edges (){ return e.get(); } //!< Two indexes into points per edge. @see close_gaps 39 | 40 | const GLuint *faces () const{ return f.get(); } 41 | const P3f *points () const{ return p.get(); } 42 | const P3f *normals() const{ return n.get(); } 43 | const P2f *texture() const{ return t.get(); } 44 | const GLuint *edges () const{ return e.get(); } 45 | 46 | void set_grid(bool *edge_flags, bool remove_duplicates = true); 47 | void close_gaps(size_t total_per_chunk, const std::vector &skipped, bool *edge_flags); 48 | 49 | private: 50 | std::unique_ptr p; //!< vertex coordinates 51 | std::unique_ptr n; //!< normals; NULL, one per point, or one per face, depending on NormalMode 52 | std::unique_ptr t; //!< texture coordinates, one per point 53 | std::unique_ptr f; //!< faces, n_faces*3 indexes into the other arrays 54 | std::unique_ptr e; //!< edges 55 | 56 | size_t n_points, n_faces, n_normals, n_gridlines; 57 | size_t max_index; // in faces/grid index array 58 | NormalMode nmode; 59 | 60 | void gen_vertex_normals(); // turn face- into vertex-normals 61 | void gen_normals(bool per_vertex = true, int n_threads = -1); // -1 = n_cores 62 | }; 63 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_String.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_Font.h" 3 | #include "GL_Context.h" 4 | #include "../Geometry/Axis.h" 5 | #include 6 | #include 7 | 8 | enum VerticalPosition { TOP = -1, VCENTER = 0, BOTTOM = 1 }; 9 | enum HorizontalPosition{ LEFT = -1, HCENTER = 0, RIGHT = 1 }; 10 | 11 | class GL_String 12 | { 13 | public: 14 | GL_String(const std::string &s, const GL_Font &f); 15 | ~GL_String(); 16 | 17 | GL_String(const GL_String &) = delete; 18 | GL_String &operator=(const GL_String &) = delete; 19 | 20 | void draw(float x, float y, float w, float h); // GL-coordinates (x,y=0,z) 21 | void draw2d(float x, float y, float w, float h); // GL-coordinates (x,y,z=0) 22 | void draw(const P3f &top_left, const P3f &dx, const P3f &dy); 23 | 24 | void draw(const P3d &p, HorizontalPosition hp, VerticalPosition vp, const Axis &axis, double scale); // axis-coordinates 25 | void draw(const P3d &p, const P3d &dx, const P3d &dy, HorizontalPosition hp, VerticalPosition vp, const Axis &axis, double scale); // dx and dy must be unit vectors 26 | void draw_fixed(const P3d &p, const P3d &dx, const P3d &dy, HorizontalPosition hp, VerticalPosition vp, double scale); // dx and dy must be unit vectors 27 | 28 | float w() const{ return frame_w; } 29 | float h() const{ return frame_h; } 30 | 31 | private: 32 | GL_Context context; // context that contains the texture 33 | GLuint texName; 34 | GLfloat tex_w, tex_h; // size of the texture 35 | float frame_w, frame_h; // size of the string 36 | }; 37 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_StringCache.cc: -------------------------------------------------------------------------------- 1 | #include "GL_StringCache.h" 2 | 3 | void GL_StringCache::clear() 4 | { 5 | for (auto &i : cache) delete i.second; 6 | cache.clear(); 7 | unused.clear(); 8 | } 9 | 10 | void GL_StringCache::fonts(std::vector &&F) 11 | { 12 | if (F == _fonts) return; 13 | clear(); 14 | _fonts = F; 15 | assert(!_fonts.empty()); 16 | cf = 0; 17 | } 18 | void GL_StringCache::font(const GL_Font &F) 19 | { 20 | if (_fonts.size() == 1 && _fonts[0] == F) return; 21 | clear(); 22 | _fonts.clear(); 23 | _fonts.push_back(F); 24 | cf = 0; 25 | } 26 | 27 | void GL_StringCache::start() 28 | { 29 | for (auto &i : cache) unused.insert(i.first); 30 | } 31 | GL_String *GL_StringCache::get(const std::string &s) 32 | { 33 | if (cf < 0 || (size_t)cf >= _fonts.size()){ assert(false); return NULL; } 34 | Key k = std::make_pair(s, cf); 35 | if (cache.count(k)) 36 | { 37 | unused.erase(k); 38 | return cache[k]; 39 | } 40 | GL_String *gls = new GL_String(s, _fonts[cf]); 41 | cache[k] = gls; 42 | return gls; 43 | } 44 | void GL_StringCache::finish() 45 | { 46 | for (auto &k : unused) 47 | { 48 | delete cache[k]; 49 | cache.erase(k); 50 | } 51 | unused.clear(); 52 | } 53 | GL_StringCache::~GL_StringCache() 54 | { 55 | for (auto &i : cache) delete i.second; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_StringCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GL_String.h" 3 | #include 4 | #include 5 | #include 6 | 7 | class GL_StringCache 8 | { 9 | public: 10 | GL_StringCache() : cf(-1){ } 11 | ~GL_StringCache(); 12 | 13 | GL_StringCache(const GL_StringCache &) = delete; 14 | GL_StringCache &operator=(const GL_StringCache &) = delete; 15 | 16 | void start(); 17 | void finish(); 18 | GL_String *get(const std::string &s); 19 | 20 | void font(int i) { assert(i >= 0 && (size_t)i < _fonts.size()); cf = i; } 21 | void fonts(std::vector &&F); 22 | void font(const GL_Font &F); 23 | 24 | private: 25 | typedef std::pair Key; 26 | std::map cache; 27 | std::set unused; 28 | int cf; // current_font 29 | std::vector _fonts; 30 | 31 | void clear(); 32 | }; 33 | -------------------------------------------------------------------------------- /Graphs/OpenGL/GL_Util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Geometry/Vector.h" 3 | #include "../Geometry/Axis.h" 4 | #include 5 | 6 | void draw_arrow(const P3d &p, const P3d &u, double max_tip_length, const Axis &axis); // arrow from p to p+u 7 | void draw_arrow(const P2d &p, const P2d &u, double max_tip_length, const Axis &axis); 8 | 9 | void draw_arrow3d(const P3f &p, const P3f &u, float max_tip_length); // arrow from p to p+u 10 | void draw_arrow2d(const P3f &p, const P3f &u, float max_tip_length); 11 | 12 | 13 | inline void vertex(const P3d &p, const Axis &axis) 14 | { 15 | P3f q; 16 | axis.map(p, q); 17 | glVertex3fv(q); 18 | } 19 | inline void vertex(double x, double y, double z, const Axis &axis) 20 | { 21 | P3f q; 22 | axis.map(P3d(x,y,z), q); 23 | glVertex3fv(q); 24 | } 25 | 26 | inline void vertex2d(const P2d &p, const Axis &axis) 27 | { 28 | P3f q; 29 | axis.map(P3d(p.x, p.y, 0.0), q); 30 | glVertex3fv(q); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Torsten Hilgenberg 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Linux/GUI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "imgui/imgui.h" 4 | class PlotWindow; 5 | class GUI; 6 | 7 | struct GUI_Menu 8 | { 9 | GUI_Menu(GUI &gui) : gui(gui) {} 10 | virtual ~GUI_Menu() {} 11 | virtual void operator()() = 0; // update/draw, called every frame that the gui is visible 12 | virtual bool handle(const SDL_Event &event) { return false; } 13 | GUI &gui; 14 | }; 15 | struct GUI_Panel 16 | { 17 | GUI_Panel(GUI &gui) : gui(gui) {} 18 | virtual ~GUI_Panel() {} 19 | virtual void operator()() = 0; 20 | virtual bool handle(const SDL_Event &event) { return false; } 21 | GUI &gui; 22 | }; 23 | 24 | struct EnableGuard 25 | { 26 | EnableGuard() : enabled(true) {} 27 | ~EnableGuard() { if (!enabled) ImGui::EndDisabled(); } 28 | void operator()(bool e) 29 | { 30 | if (e) { if (!enabled) ImGui::EndDisabled(); } 31 | else { if ( enabled) ImGui::BeginDisabled(); } 32 | enabled = e; 33 | } 34 | [[nodiscard]] operator bool() const { return enabled; } 35 | private: 36 | bool enabled; 37 | }; 38 | 39 | class GUI 40 | { 41 | public: 42 | friend struct GUI_ViewMenu; 43 | friend struct GUI_FileMenu; 44 | 45 | GUI(SDL_Window* window, SDL_GLContext context, PlotWindow &w); 46 | ~GUI(); 47 | 48 | void show() { if (!visible) redraw(); visible = true; } 49 | void redraw(int n_frames = 3){ need_redraw = std::max(n_frames, need_redraw); } 50 | bool needs_redraw() const{ return visible && need_redraw > 0; } 51 | 52 | bool handle_event(const SDL_Event &event); 53 | void update(); // call this first (before waiting for the next frame) 54 | void draw(); // call this second 55 | 56 | void error(const std::string &msg); 57 | void confirm(bool need_confirmation, const std::string &msg, std::function action); 58 | 59 | PlotWindow &w; 60 | 61 | private: 62 | bool visible; 63 | int need_redraw; // imgui assumes a continuous render loop, but we only draw if 64 | // we have to, so this is some number of frames and not a single 65 | // bool to allow it to run its animations 66 | 67 | bool show_top_panel = true, show_side_panel = true; 68 | bool show_prefs_panel = false, show_help_panel = false; 69 | #ifdef DEBUG 70 | bool show_demo_window = false; 71 | #endif 72 | float top_panel_height = 0.0f; 73 | 74 | std::vector> menus; 75 | //std::vector> panels; 76 | 77 | void top_panel(), side_panel(), prefs_panel(), help_panel(); 78 | 79 | void error_panel(); 80 | std::string error_msg; 81 | 82 | void confirmation_panel(); 83 | std::string confirm_msg; 84 | std::function confirm_action; 85 | }; 86 | -------------------------------------------------------------------------------- /Linux/GUI_edit.cc: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | #include "imgui/imgui.h" 3 | #include "PlotWindow.h" 4 | 5 | struct GUI_EditMenu : public GUI_Menu 6 | { 7 | GUI_EditMenu(GUI &gui) : GUI_Menu(gui) {} 8 | 9 | void operator()() 10 | { 11 | if (!ImGui::BeginMenu("Edit")) return; 12 | 13 | std::string name("Undo"); bool on = gui.w.ut.can_undo(name); 14 | name += "###UndoItem"; 15 | if (ImGui::MenuItem(name.c_str(), "CTRL+Z", false, on)) gui.w.ut.undo(); 16 | 17 | name = "Redo"; on = gui.w.ut.can_redo(name); 18 | name += "###RedoItem"; 19 | if (ImGui::MenuItem(name.c_str(), "CTRL+Y", false, on)) gui.w.ut.redo(); 20 | 21 | ImGui::Separator(); 22 | if (ImGui::MenuItem("Cut", "CTRL+X")) {} 23 | if (ImGui::MenuItem("Copy", "CTRL+C")) {} 24 | if (ImGui::MenuItem("Paste", "CTRL+V")) {} 25 | ImGui::EndMenu(); 26 | } 27 | 28 | bool handle(const SDL_Event &event) 29 | { 30 | if (event.type != SDL_KEYDOWN) return false; 31 | 32 | auto key = event.key.keysym.sym; 33 | auto m = event.key.keysym.mod; 34 | constexpr int SHIFT = 1, CTRL = 2, ALT = 4; 35 | const int shift = (m & (KMOD_LSHIFT|KMOD_RSHIFT)) ? SHIFT : 0; 36 | const int ctrl = (m & (KMOD_LCTRL|KMOD_RCTRL)) ? CTRL : 0; 37 | const int alt = (m & (KMOD_LALT|KMOD_RALT)) ? ALT : 0; 38 | const int mods = shift + ctrl + alt; 39 | 40 | switch (key) 41 | { 42 | case SDLK_z: 43 | if (mods == CTRL) { gui.w.ut.undo(); gui.w.redraw(); return true; } 44 | break; 45 | case SDLK_y: 46 | if (mods == CTRL) { gui.w.ut.redo(); gui.w.redraw(); return true; } 47 | break; 48 | } 49 | return false; 50 | } 51 | }; 52 | GUI_Menu *new_edit_menu(GUI &gui) { return new GUI_EditMenu(gui); } 53 | -------------------------------------------------------------------------------- /Linux/GUI_graphs.cc: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | #include "imgui/imgui.h" 3 | #include "PlotWindow.h" 4 | 5 | struct GUI_GraphsMenu : public GUI_Menu 6 | { 7 | GUI_GraphsMenu(GUI &gui) : GUI_Menu(gui) {} 8 | 9 | void operator()() 10 | { 11 | if (!ImGui::BeginMenu("Graphs")) return; 12 | const Plot &plot = gui.w.plot; 13 | const Graph *g0 = plot.current_graph(); 14 | const int n = plot.number_of_graphs(); 15 | for (int i = 0; i < n; ++i) 16 | { 17 | Graph *g = plot.graph(i); 18 | ImGui::PushID(g); 19 | bool sel = (g == g0); 20 | std::string desc = g->description_line(); 21 | if (g->options.hidden) desc += " (hidden)"; 22 | if (ImGui::MenuItem(desc.c_str(), NULL, sel)) gui.w.selectGraph(i); 23 | ImGui::PopID(); 24 | } 25 | if (n > 0) ImGui::Separator(); 26 | 27 | if (ImGui::MenuItem("Add Graph")) gui.w.addGraph(); 28 | if (ImGui::MenuItem("Delete Selected Graph", NULL, false, g0 != NULL)) gui.w.deleteGraph(g0->oid()); 29 | if (ImGui::MenuItem((g0 && g0->options.hidden) ? "Show Selected Graph" : "Hide Selected Graph", 30 | NULL, false, g0 != NULL)) gui.w.toggleGraphVisibility(); 31 | ImGui::EndMenu(); 32 | } 33 | }; 34 | GUI_Menu *new_graphs_menu(GUI &gui) { return new GUI_GraphsMenu(gui); } 35 | -------------------------------------------------------------------------------- /Linux/GUI_msg.cc: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | 3 | void GUI::error_panel() 4 | { 5 | static bool showing = false; 6 | if (error_msg.empty()) return; 7 | if (!showing) 8 | { 9 | visible = true; 10 | showing = true; 11 | ImGui::OpenPopup("Error"); 12 | need_redraw = 20; // imgui wants to animate dimming the background 13 | } 14 | // Always center this window when appearing 15 | ImVec2 center = ImGui::GetMainViewport()->GetCenter(); 16 | ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); 17 | if (!ImGui::BeginPopupModal("Error", NULL, ImGuiWindowFlags_AlwaysAutoResize)) return; 18 | ImGui::TextWrapped(error_msg.c_str()); 19 | ImGui::Separator(); 20 | bool close = false; 21 | if (ImGui::Button("OK", ImVec2(120, 0))) 22 | close = true; 23 | if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && 24 | (ImGui::IsKeyPressed(ImGuiKey_Escape) || ImGui::IsKeyPressed(ImGuiKey_Enter))) 25 | close = true; 26 | 27 | if (close) 28 | { 29 | error_msg.clear(); 30 | ImGui::CloseCurrentPopup(); 31 | showing = false; 32 | } 33 | ImGui::EndPopup(); 34 | } 35 | 36 | void GUI::confirmation_panel() 37 | { 38 | static bool showing = false; 39 | if (!confirm_action) return; 40 | if (!showing) 41 | { 42 | visible = true; 43 | showing = true; 44 | ImGui::OpenPopup("Confirmation"); 45 | need_redraw = 20; // imgui wants to animate dimming the background 46 | } 47 | // Always center this window when appearing 48 | ImVec2 center = ImGui::GetMainViewport()->GetCenter(); 49 | ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); 50 | if (!ImGui::BeginPopupModal("Confirmation", NULL, ImGuiWindowFlags_AlwaysAutoResize)) return; 51 | ImGui::TextWrapped(confirm_msg.c_str()); 52 | ImGui::Separator(); 53 | bool confirm = false, close = false; 54 | if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImGui::IsKeyPressed(ImGuiKey_Escape)) 55 | close = true; 56 | if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImGui::IsKeyPressed(ImGuiKey_Enter)) 57 | confirm = close = true; 58 | if (ImGui::Button("Cancel", ImVec2(120, 0))) close = true; 59 | ImGui::SameLine(); 60 | if (ImGui::Button("OK", ImVec2(120, 0))) confirm = close = true; 61 | 62 | if (confirm) 63 | { 64 | try 65 | { 66 | confirm_action(); 67 | } 68 | catch (std::exception &e) 69 | { 70 | error(e.what()); 71 | } 72 | close = true; 73 | } 74 | if (close) 75 | { 76 | confirm_msg.clear(); 77 | confirm_action = nullptr; 78 | ImGui::CloseCurrentPopup(); 79 | showing = false; 80 | } 81 | ImGui::EndPopup(); 82 | } 83 | -------------------------------------------------------------------------------- /Linux/GUI_prefs.cc: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | #include "imgui/imgui.h" 3 | #include "../Utility/Preferences.h" 4 | 5 | void GUI::prefs_panel() 6 | { 7 | if (!show_prefs_panel) return; 8 | 9 | ImGui::Begin("Preferences", &show_prefs_panel); 10 | bool b0, b; int i0, i; 11 | 12 | ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); 13 | 14 | b0 = Preferences::drawNormals(); b = b0; 15 | ImGui::Checkbox("Draw Normals", &b); 16 | if (b != b0) { Preferences::drawNormals(b); redraw(); } 17 | 18 | b0 = Preferences::showFPS(); b = b0; 19 | ImGui::Checkbox("Show FPS", &b); 20 | if (b != b0) { Preferences::showFPS(b); redraw(); } 21 | 22 | ImGui::Text("Animation FPS limit (-1 for none)"); 23 | i0 = Preferences::fps(); i = i0; 24 | ImGui::InputInt("##fps", &i, 1, 0); 25 | if (i != i0) Preferences::fps(i); 26 | 27 | b0 = Preferences::vsync(); b = b0; 28 | ImGui::Checkbox("VSync", &b); 29 | if (b != b0) { 30 | SDL_GL_SetSwapInterval(b); 31 | Preferences::vsync(b); redraw(); 32 | } 33 | 34 | b0 = Preferences::dynamic(); b = b0; 35 | ImGui::Checkbox("Reduce Quality During Animation", &b); 36 | if (b != b0) { Preferences::dynamic(b); redraw(); } 37 | 38 | b0 = Preferences::depthSort(); b = b0; 39 | ImGui::Checkbox("Depth Sorting", &b); 40 | if (b != b0) { Preferences::depthSort(b); redraw(); } 41 | 42 | ImGui::Spacing(); 43 | ImGui::Spacing(); 44 | ImGui::Spacing(); 45 | ImGui::Text("Number of Threads (-1 for default = %d)", n_cores); 46 | i0 = Preferences::threads(false); i = i0; 47 | ImGui::InputInt("##threads", &i, 1, 0); 48 | if (i != i0) Preferences::threads(i); 49 | 50 | ImGui::PopItemWidth(); 51 | ImGui::Spacing(); 52 | ImGui::Spacing(); 53 | ImGui::Spacing(); 54 | if (ImGui::Button("Done")) show_prefs_panel = false; 55 | 56 | ImGui::End(); 57 | } 58 | -------------------------------------------------------------------------------- /Linux/Hack-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Linux/Hack-Regular.ttf -------------------------------------------------------------------------------- /Linux/PlotWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Document.h" 3 | #include "../Graphs/OpenGL/GL_RM.h" 4 | #include "../Graphs/OpenGL/GL_StringCache.h" 5 | #include "../Engine/Namespace/Parameter.h" 6 | #include "../Utility/FPSCounter.h" 7 | #include 8 | #include 9 | 10 | class PlotWindow : public Document 11 | { 12 | public: 13 | PlotWindow(SDL_Window* window, GL_Context &context); 14 | virtual ~PlotWindow(); 15 | void load(const std::string &path) override { Document::load(path); redraw(); } 16 | 17 | bool needs_redraw() const{ return need_redraw; } 18 | bool animating() const{ return tnf > 0.0; } 19 | 20 | void animate(); 21 | void draw(); 22 | void waiting() { fps.pause(); } 23 | //void redraw(){ need_redraw = true; } --> moved to base class 24 | 25 | void reshape(int w, int h); 26 | bool handle_event(const SDL_Event &event); 27 | bool handle_key(SDL_Keysym key, bool release); 28 | 29 | int accum_size() const { return accum; } 30 | float status_height() const { return current_status_height; } 31 | 32 | void start_animations(); // call after Parameter::anim_start() 33 | 34 | protected: 35 | SDL_Window *window; 36 | int w, h; 37 | int accum; // accumulation buffer size 38 | 39 | double tnf; // scheduled time for next frame 40 | double last_frame; // time of last animate() call 41 | GL_RM rm; 42 | FPSCounter fps; 43 | 44 | std::map ikeys; // pressed key -> inertia 45 | std::set keys; // pressed keys 46 | 47 | enum Zoom{ Axis, Camera, Inrange }; 48 | void translate(double dx, double dy, double dz, Zoom what, int mx = -1, int my = -1); 49 | void change_parameter(int i, cnum delta); 50 | 51 | void status(); // draw status bar 52 | float current_status_height = 0.0f; 53 | mutable GL_StringCache labelCache; 54 | struct StatusField { double x0, x1, y0, y1; }; 55 | std::vector status_fields; // for matching clicks in status bar to parameters 56 | int dragged_param = 0; 57 | }; 58 | 59 | -------------------------------------------------------------------------------- /Linux/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Linux/screenshot.png -------------------------------------------------------------------------------- /Persistence/ByteReader.cc: -------------------------------------------------------------------------------- 1 | #include "ByteReader.h" 2 | #include 3 | #include 4 | #include 5 | 6 | //---------------------------------------------------------------------------------------------------------------------- 7 | 8 | #ifdef _WINDOWS 9 | 10 | FileReader::FileReader(FileReaderFile *f) : f(f), i(0) 11 | { 12 | assert(f); 13 | n = (size_t)f->GetLength(); 14 | assert(f->GetPosition() == 0); 15 | } 16 | 17 | void FileReader::read(void *buffer, size_t len) 18 | { 19 | if (i + len > n) 20 | { 21 | throw std::runtime_error("Trying to read beyond end of file. This file seems to be truncated or corrupted."); 22 | } 23 | 24 | while (len) 25 | { 26 | UINT k = (len > UINT_MAX ? UINT_MAX : (UINT)len); 27 | if (f->Read(buffer, k) != k) 28 | { 29 | throw std::runtime_error("Error reading from file."); 30 | } 31 | len -= k; 32 | i += k; 33 | } 34 | } 35 | 36 | void FileWriter::write(const void *buffer, size_t len) 37 | { 38 | while (len) 39 | { 40 | UINT k = (len > UINT_MAX ? UINT_MAX : (UINT)len); 41 | f->Write(buffer, k); 42 | len -= k; 43 | } 44 | } 45 | 46 | #else 47 | 48 | FileReader::FileReader(FILE *f) : f(f), i(0) 49 | { 50 | assert(f); 51 | long p0 = ftell(f); // in case f has already been read from 52 | fseek(f, 0L, SEEK_END); 53 | n = ftell(f) - p0; 54 | fseek(f, p0, SEEK_SET); 55 | } 56 | 57 | void FileReader::read(void *buffer, size_t len) 58 | { 59 | if (i+len > n) 60 | { 61 | throw std::runtime_error("Trying to read beyond end of file. This file seems to be truncated or corrupted."); 62 | } 63 | 64 | if (fread(buffer, len, 1, f) != 1) 65 | { 66 | throw std::runtime_error("Error reading from file."); 67 | } 68 | 69 | i += len; 70 | } 71 | 72 | void FileWriter::write(const void *buffer, size_t len) 73 | { 74 | if (fwrite(buffer, len, 1, f) != 1) 75 | { 76 | throw std::runtime_error("Error writing to file."); 77 | } 78 | } 79 | 80 | #endif 81 | 82 | //---------------------------------------------------------------------------------------------------------------------- 83 | 84 | void ArrayReader::read(void *buffer, size_t len) 85 | { 86 | if (i+len > n) 87 | { 88 | throw std::runtime_error("Trying to read beyond end of data"); 89 | } 90 | memcpy(buffer, bytes+i, len); 91 | i += len; 92 | } 93 | 94 | void ArrayWriter::write(const void *buffer, size_t len) 95 | { 96 | d.insert(d.end(), (char*)buffer, (char*)buffer+len); 97 | } 98 | 99 | -------------------------------------------------------------------------------- /Persistence/ErrorHandling.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "FileVersions.h" 4 | #include "../Utility/StringFormatting.h" 5 | 6 | #define NEEDS_VERSION(v, thing) throw std::runtime_error(format("Cannot save " thing " prior to version %s", version_string(v))) 7 | #define CHECK_VERSION(v, thing) if (s.version() < v) throw std::runtime_error(format("Cannot save " thing " prior to version %s", version_string(v))) 8 | 9 | #define INCONSISTENCY(desc) do{ assert(false); throw std::logic_error(desc); }while(0) 10 | #define CHECK_CONSISTENCY(what, desc) do{ assert(what); if (!(what)) throw std::logic_error(desc); }while(0) 11 | -------------------------------------------------------------------------------- /Persistence/FileVersions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // All released versions as major<<16 + minor 4 | 5 | #define FILE_VERSION_1_0 0x00010000U 6 | #define FILE_VERSION_1_2 0x00010002U 7 | #define FILE_VERSION_1_3 0x00010003U 8 | #define FILE_VERSION_1_4 0x00010004U 9 | #define FILE_VERSION_1_5 0x00010005U 10 | #define FILE_VERSION_1_6 0x00010006U 11 | #define FILE_VERSION_1_7 0x00010007U 12 | #define FILE_VERSION_1_8 0x00010008U 13 | #define FILE_VERSION_1_9 0x00010009U 14 | #define FILE_VERSION_1_10 0x0001000AU 15 | #define FILE_VERSION_1_11 0x0001000BU 16 | #define CURRENT_VERSION FILE_VERSION_1_10 17 | 18 | inline const char *version_string(unsigned v) 19 | { 20 | static char buf[32]; 21 | #pragma warning(suppress: 6031) // return of snprintf ignored 22 | snprintf(buf, 31, "%u.%u", v >> 16, v & 0xFFFF); 23 | return buf; 24 | } 25 | -------------------------------------------------------------------------------- /Plot Examples/2D Supershape.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/2D Supershape.cplot -------------------------------------------------------------------------------- /Plot Examples/Bessel.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Bessel.cplot -------------------------------------------------------------------------------- /Plot Examples/Breather.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Breather.cplot -------------------------------------------------------------------------------- /Plot Examples/Color Mode 1.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Color Mode 1.cplot -------------------------------------------------------------------------------- /Plot Examples/Color Mode 2.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Color Mode 2.cplot -------------------------------------------------------------------------------- /Plot Examples/Harmonograph.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Harmonograph.cplot -------------------------------------------------------------------------------- /Plot Examples/Implicit Animation.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Implicit Animation.cplot -------------------------------------------------------------------------------- /Plot Examples/Inequality.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Inequality.cplot -------------------------------------------------------------------------------- /Plot Examples/Julia Set.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Julia Set.cplot -------------------------------------------------------------------------------- /Plot Examples/Klein Bottle.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Klein Bottle.cplot -------------------------------------------------------------------------------- /Plot Examples/Knobs.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Knobs.cplot -------------------------------------------------------------------------------- /Plot Examples/Limpet Torus.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Limpet Torus.cplot -------------------------------------------------------------------------------- /Plot Examples/Menger Cube.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Menger Cube.cplot -------------------------------------------------------------------------------- /Plot Examples/PhaseField.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/PhaseField.cplot -------------------------------------------------------------------------------- /Plot Examples/Riemann Histogram.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Riemann Histogram.cplot -------------------------------------------------------------------------------- /Plot Examples/Singularity.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Singularity.cplot -------------------------------------------------------------------------------- /Plot Examples/Snail Shell.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Snail Shell.cplot -------------------------------------------------------------------------------- /Plot Examples/Spherical Product.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Spherical Product.cplot -------------------------------------------------------------------------------- /Plot Examples/Tangent.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Tangent.cplot -------------------------------------------------------------------------------- /Plot Examples/Trefoil.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Trefoil.cplot -------------------------------------------------------------------------------- /Plot Examples/Waves & Interference.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Plot Examples/Waves & Interference.cplot -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## CPlot 2 | 3 | Linux (formerly Windows, formerly Mac) function plotter. Screenshots and Windows binaries are on the [homepage](http://zoon.cc/cplot/). 4 | 5 |

interface

6 | 7 | Supports various projection modes and function types, natural expression syntax (sin xy instead of Sin[x*y] f.e.), blending between functions (identity and your target function for example), realtime parameter variation (where parameters are things like a mass or spring constant, order of a pole, etc), ... 8 | 9 | ### Linux build: 10 | 11 | On Arch: `sudo pacman -S --needed git python ninja boost zlib sdl2 libgl glu glew pango cairo`.
12 | On Debian: `sudo apt install git python3 ninja-build libboost-dev libz-dev libsdl2-dev libgl-dev libglu-dev libglew-dev libpango-1.0-dev libcairo2-dev`. 13 | 14 | Then build with: 15 | ```Shell 16 | git clone https://github.com/hilgenberg/cplot 17 | cd cplot 18 | git submodule update --init --recursive 19 | ./build 20 | ./cplot test.cplot 21 | ``` 22 | 23 | Press Escape to show/hide the GUI. 24 | Documentation is available from the menu under View > Show Help. 25 | Some demo files are in the "Plot Examples" directory. 26 | 27 | ### Windows build: 28 | 29 | (Somewhat defunct because I have no Windows box at the moment - the 1.10 tag should still work.) 30 | Copy boost headers to Windows/boost/, open CPlot.sln in Visual Studio 2017, and it should just build. 31 | -------------------------------------------------------------------------------- /Utility/FPSCounter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Timer.h" 3 | 4 | class FPSCounter 5 | { 6 | public: 7 | void frame() 8 | { 9 | double t = now(); 10 | if (last > 0.0) 11 | { 12 | double dt = t - last; assert(dt >= 0.0); 13 | if (n >= N) n = N-1; 14 | 15 | // Keep a running average. Because vsync only kicks in after the second draw() 16 | // call, weigh the first frame less strongly than times after the framerate had 17 | // a chance to stabilize (normally one would use f = n/(n+1) or some such - our 18 | // f goes from 0 to N-1 / N, so it ends up at the same value) 19 | double f = (double)n / (double)((N-n)*N); 20 | avg = f*avg + (1.0-f)*dt; 21 | 22 | ++n; 23 | } 24 | last = t; 25 | } 26 | void pause() { last = -1.0; avg = -1.0; n = 0; } 27 | 28 | double fps() const { return avg > 0.0 ? 1.0 / avg : 0.0; } 29 | 30 | private: 31 | double last = -1.0; 32 | double avg = -1.0; 33 | int n = 0; 34 | static constexpr int N = 10; 35 | }; -------------------------------------------------------------------------------- /Utility/MemoryPool.cc: -------------------------------------------------------------------------------- 1 | #include "MemoryPool.h" 2 | #include 3 | #include 4 | 5 | RawMemoryPool::RawMemoryPool(size_t chunkSize_, size_t align) 6 | : chunkSize(chunkSize_), c0(NULL), cn(NULL), alignment(align) 7 | { 8 | assert(!(align & (align-1))); // must be 2^k 9 | assert(chunkSize > 64); 10 | 11 | #ifdef MP_THREADSAFE 12 | int err = pthread_mutex_init(&mutex, NULL); 13 | if(err != 0) throw std::runtime_error("Creating mutex failed"); 14 | #endif 15 | } 16 | 17 | void RawMemoryPool::clear() 18 | { 19 | while (c0) 20 | { 21 | Chunk *c1 = c0->next; 22 | assert(c1 || c0 == cn); 23 | delete c0; 24 | c0 = c1; 25 | } 26 | cn = NULL; 27 | } 28 | 29 | 30 | char *RawMemoryPool::alloc(size_t size) 31 | { 32 | #ifdef MP_THREADSAFE 33 | Lock lock(mutex); 34 | #endif 35 | size = align(size); 36 | 37 | if (!cn || cn->avail < size) 38 | { 39 | Chunk *c = new Chunk(*this, size <= chunkSize ? chunkSize : size); 40 | if (cn) 41 | { 42 | cn->next = c; 43 | cn = c; 44 | } 45 | else 46 | { 47 | c0 = cn = c; 48 | } 49 | } 50 | char *ret = cn->mem + cn->size - cn->avail; 51 | cn->avail -= size; 52 | assert(ret == align(ret)); 53 | return ret; 54 | } 55 | 56 | //---------------------------------------------------------------------------------------------------------------------- 57 | // RawMemoryPool::Chunk 58 | //---------------------------------------------------------------------------------------------------------------------- 59 | 60 | RawMemoryPool::Chunk::Chunk(RawMemoryPool &pool, size_t n) 61 | : size(n + pool.alignment), 62 | mem0(new char[n + pool.alignment]), next(NULL) 63 | { 64 | mem = pool.align(mem0); 65 | size_t ds = mem - mem0; assert(ds < pool.alignment); 66 | size -= ds; 67 | avail = size; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /Utility/Mutex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef USE_PTHREADS 4 | #include 5 | 6 | class Mutex 7 | { 8 | public: 9 | Mutex (){ pthread_mutex_init(&mutex, NULL); } 10 | ~Mutex(){ pthread_mutex_destroy(&mutex); } 11 | 12 | Mutex(const Mutex &) = delete; 13 | Mutex &operator=(const Mutex &) = delete; 14 | 15 | void lock() { pthread_mutex_lock(&mutex); } 16 | void unlock() { pthread_mutex_unlock(&mutex); } 17 | bool try_lock() { return 0 == pthread_mutex_trylock(&mutex); } 18 | 19 | private: 20 | friend class Lock; 21 | pthread_mutex_t mutex; 22 | }; 23 | 24 | #else 25 | 26 | #include 27 | 28 | class Mutex 29 | { 30 | public: 31 | Mutex() { } 32 | ~Mutex() { } 33 | 34 | Mutex(const Mutex &) = delete; 35 | Mutex &operator=(const Mutex &) = delete; 36 | 37 | void lock() { mutex.lock(); } 38 | void unlock() { mutex.unlock(); } 39 | bool try_lock() { return mutex.try_lock(); } 40 | 41 | private: 42 | std::mutex mutex; 43 | }; 44 | 45 | #endif 46 | 47 | class Lock 48 | { 49 | public: 50 | Lock(Mutex &m) : mutex(m) 51 | { 52 | mutex.lock(); 53 | } 54 | 55 | ~Lock() 56 | { 57 | mutex.unlock(); 58 | } 59 | 60 | Lock(const Lock &) = delete; 61 | Lock &operator=(const Lock &) = delete; 62 | 63 | private: 64 | Mutex &mutex; 65 | }; 66 | 67 | -------------------------------------------------------------------------------- /Utility/Preferences.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * For getting and setting user preferences. 6 | * The getters must be threadsafe. 7 | * Setters should be persistent. 8 | */ 9 | 10 | extern const int n_cores; 11 | 12 | namespace Preferences 13 | { 14 | bool flush(); // store changes into registry/ini file 15 | bool reset(); // reread from registry/disk 16 | 17 | bool dynamic(); // reduce quality during animation? 18 | void dynamic(bool value); 19 | 20 | #ifdef _WIN32 21 | bool slideback(); // delta sliders animate their return to center? 22 | void slideback(bool value); 23 | #endif 24 | 25 | #ifdef __linux__ 26 | std::filesystem::path directory(); 27 | 28 | bool showFPS(); 29 | void showFPS(bool value); 30 | 31 | int fps(); 32 | void fps(int value); 33 | 34 | bool vsync(); 35 | void vsync(bool value); 36 | #endif 37 | 38 | bool drawNormals(); // debugging 39 | void drawNormals(bool value); 40 | 41 | bool depthSort(); 42 | void depthSort(bool value); 43 | 44 | int threads(bool effective = true); // number of threads, -1 for num threads = num cores 45 | void threads(int n); 46 | }; 47 | -------------------------------------------------------------------------------- /Utility/StringFormatting.cc: -------------------------------------------------------------------------------- 1 | #include "StringFormatting.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | std::string format(const char *fmt, ...) 9 | { 10 | va_list ap; 11 | va_start(ap, fmt); 12 | 13 | char buf1[512]; // avoid heap allocation most of the time 14 | std::vector buf2; // use this if buf1 is too small 15 | size_t size = sizeof(buf1); 16 | char *buf = buf1; 17 | int n; 18 | 19 | while (true) 20 | { 21 | n = vsnprintf(buf, size, fmt, ap); 22 | if (n >= 0 && (size_t)n <= size) break; 23 | 24 | size = n > 0 ? (size_t)n+1 : size*2; 25 | buf2.resize(size); 26 | buf = buf2.data(); 27 | } 28 | 29 | va_end (ap); 30 | 31 | return std::string(buf, (size_t)n); 32 | } 33 | 34 | std::string spaces(int n) 35 | { 36 | assert(n >= 0); 37 | if (n <= 0) return std::string(); 38 | return std::string(n, ' '); 39 | } 40 | 41 | bool is_int(const char *s, int &v_) 42 | { 43 | int v = 0, sign = 1; 44 | if (*s == '-'){ ++s; sign = -1; } 45 | else if (*s == '+'){ ++s; } 46 | if (!*s) return false; 47 | 48 | for (; *s; ++s) 49 | { 50 | char c = *s; 51 | if (!isdigit(c)) return false; 52 | v *= 10; v += c - '0'; 53 | } 54 | v_ = sign * v; 55 | return true; 56 | } 57 | 58 | bool is_int(const std::string &s, int &v_) 59 | { 60 | int v = 0, sign = 1; 61 | size_t i = 0, n = s.length(); 62 | if (!n) return false; 63 | if (s[0] == '-'){ ++i; sign = -1; } 64 | else if (s[0] == '+'){ ++i; } 65 | if (i >= n) return false; 66 | 67 | for (; i < n; ++i) 68 | { 69 | char c = s[i]; 70 | if (!isdigit(c)) return false; 71 | v *= 10; v += c - '0'; 72 | } 73 | v_ = sign * v; 74 | return true; 75 | } 76 | 77 | bool has_prefix(const char *s, const char *p, bool ignore_case) 78 | { 79 | size_t l = strlen(p); 80 | if (strlen(s) < l) return false; 81 | auto cmp = ignore_case ? strncasecmp : strncmp; 82 | return cmp(s, p, l) == 0; 83 | } 84 | 85 | bool has_prefix(const std::string &s, const char *p, bool ignore_case) 86 | { 87 | size_t l = strlen(p); 88 | if (s.length() < l) return false; 89 | auto cmp = ignore_case ? strncasecmp : strncmp; 90 | return cmp(s.c_str(), p, l) == 0; 91 | } 92 | -------------------------------------------------------------------------------- /Utility/StringFormatting.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * Like sprintf for std::string. 9 | * @param fmt Passed to vsnprintf, so it supports all the usual % escapes. 10 | * @return The formatted string. 11 | */ 12 | std::string format(const char *fmt, ...); 13 | 14 | std::string spaces(int n); 15 | 16 | inline std::exception error(const char *what, const std::string &who, bool stupid=false) 17 | { 18 | std::string w = format("%s: \"%s\"", what, who.c_str()); 19 | 20 | if (!stupid) throw std::runtime_error(w); 21 | 22 | assert(false); 23 | throw std::logic_error(w); 24 | 25 | // we never return anything, but this way we can write 26 | // throw error(...) to make things a little more transparent 27 | } 28 | 29 | // returns true if s =~ [+-]?\d+ 30 | // value is not modified if it returs false, otherwise 31 | // it will be the numeric value of s. 32 | // TODO: Does not handle overflow/underflow 33 | // TODO: There's probably a faster library function for this 34 | bool is_int(const std::string &s, int &value); 35 | bool is_int(const char *s, int &value); 36 | 37 | bool has_prefix(const std::string &s, const char *prefix, bool ignore_case); 38 | bool has_prefix(const char *s, const char *prefix, bool ignore_case); 39 | 40 | -------------------------------------------------------------------------------- /Utility/Timer.cc: -------------------------------------------------------------------------------- 1 | #include "Timer.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | double now() 11 | { 12 | #if 1 13 | auto now = std::chrono::high_resolution_clock::now(); 14 | auto duration = now.time_since_epoch(); 15 | using sec = std::chrono::duration>; 16 | return std::chrono::duration_cast(duration).count(); 17 | #else 18 | timeval t; 19 | gettimeofday(&t, NULL); 20 | return t.tv_sec + t.tv_usec * 1e-6; 21 | #endif 22 | } 23 | 24 | void sleep(double t) 25 | { 26 | if (t <= 0.0) return; 27 | double s; t = modf(t, &s); 28 | timespec ts; 29 | ts.tv_sec = (time_t)s; 30 | ts.tv_nsec = (long)(t * 1e9); 31 | nanosleep (&ts, NULL); 32 | } 33 | -------------------------------------------------------------------------------- /Utility/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include "Timer.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | double now() 8 | { 9 | auto now = std::chrono::high_resolution_clock::now(); 10 | auto duration = now.time_since_epoch(); 11 | using sec = std::chrono::duration>; 12 | return std::chrono::duration_cast(duration).count(); 13 | } 14 | 15 | void sleep(double t) 16 | { 17 | if (t <= 0.0) return; 18 | Sleep((DWORD)(t*1000.0)); 19 | } 20 | 21 | static void CALLBACK TimerCallback(void *timer_, BOOLEAN TimerOrWaitFired) 22 | { 23 | assert(timer_); 24 | Timer &t = *((Timer*)timer_); 25 | if (t.callback) t.callback(); 26 | } 27 | 28 | Timer::Timer(double dt) : dt_(dt), timer(0) 29 | { 30 | } 31 | 32 | Timer::~Timer() 33 | { 34 | stop(); 35 | } 36 | 37 | void Timer::start() 38 | { 39 | if (timer) return; 40 | if (!CreateTimerQueueTimer(&timer, NULL, ::TimerCallback, this, 41 | (DWORD)(dt_*1000.0), 42 | (DWORD)(dt_*1000.0), 43 | WT_EXECUTEINTIMERTHREAD)) 44 | { 45 | assert(false); 46 | timer = 0; 47 | } 48 | } 49 | 50 | void Timer::stop() 51 | { 52 | if (!timer) return; 53 | 54 | if (!DeleteTimerQueueTimer(NULL, timer, NULL)) 55 | { 56 | if (GetLastError() != ERROR_IO_PENDING) 57 | { 58 | assert(false); 59 | return; 60 | } 61 | } 62 | timer = 0; 63 | } 64 | 65 | bool Timer::running() const 66 | { 67 | return timer != 0; 68 | } 69 | -------------------------------------------------------------------------------- /Utility/Timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | double now(); ///< Must be in seconds since some reference date. Higher resolution is better. 4 | 5 | void sleep(double dt); 6 | 7 | #ifdef _WINDOWS 8 | class Timer 9 | { 10 | public: 11 | Timer(double dt); 12 | ~Timer(); 13 | void start(); 14 | void stop(); 15 | bool running() const; 16 | double dt() const { return dt_; } 17 | std::function callback; 18 | 19 | private: 20 | #ifdef _WINDOWS 21 | HANDLE timer; 22 | #endif 23 | double dt_; 24 | }; 25 | #endif 26 | -------------------------------------------------------------------------------- /Windows/CPlotApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CPlotApp : public CWinAppEx 4 | { 5 | public: 6 | CPlotApp(); 7 | 8 | BOOL InitInstance() override; 9 | int ExitInstance() override; 10 | 11 | void OnPreferences(); 12 | void OnAppAbout(); 13 | void OnViewProperties(); 14 | void OnUpdateViewProperties(CCmdUI *mi); 15 | 16 | private: 17 | ULONG_PTR gdiplusToken; 18 | 19 | DECLARE_MESSAGE_MAP() 20 | }; 21 | 22 | extern CPlotApp theApp; 23 | -------------------------------------------------------------------------------- /Windows/Controls/DefinitionView.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | #include "DefinitionView.h" 3 | #include "../Document.h" 4 | #include "../res/resource.h" 5 | #include "ViewUtil.h" 6 | #include "SideSectionDefs.h" 7 | #include "../MainWindow.h" 8 | #include "../MainView.h" 9 | #include "../CPlotApp.h" 10 | 11 | #ifdef _DEBUG 12 | #define new DEBUG_NEW 13 | #endif 14 | 15 | enum 16 | { 17 | ID_def = 2000 18 | }; 19 | 20 | IMPLEMENT_DYNAMIC(DefinitionView, CWnd) 21 | BEGIN_MESSAGE_MAP(DefinitionView, CWnd) 22 | ON_WM_CREATE() 23 | ON_WM_SIZE() 24 | ON_BN_CLICKED(ID_def, OnEdit) 25 | END_MESSAGE_MAP() 26 | 27 | DefinitionView::DefinitionView(SideSectionDefs &parent, UserFunction &f) 28 | : parent(parent), f_id(f.oid()) 29 | { 30 | } 31 | 32 | BOOL DefinitionView::PreCreateWindow(CREATESTRUCT &cs) 33 | { 34 | cs.style |= WS_CHILD; 35 | cs.dwExStyle |= WS_EX_CONTROLPARENT | WS_EX_TRANSPARENT; 36 | return CWnd::PreCreateWindow(cs); 37 | } 38 | 39 | BOOL DefinitionView::Create(const RECT &rect, CWnd *parent, UINT ID) 40 | { 41 | static bool init = false; 42 | if (!init) 43 | { 44 | WNDCLASS wndcls; memset(&wndcls, 0, sizeof(WNDCLASS)); 45 | wndcls.style = CS_DBLCLKS; 46 | wndcls.lpfnWndProc = ::DefWindowProc; 47 | wndcls.hInstance = AfxGetInstanceHandle(); 48 | wndcls.hCursor = theApp.LoadStandardCursor(IDC_ARROW); 49 | wndcls.lpszMenuName = NULL; 50 | wndcls.lpszClassName = _T("DefinitionView"); 51 | wndcls.hbrBackground = NULL; 52 | if (!AfxRegisterClass(&wndcls)) throw std::runtime_error("AfxRegisterClass(DefinitionView) failed"); 53 | init = true; 54 | } 55 | 56 | return CWnd::Create(_T("DefinitionView"), NULL, WS_CHILD | WS_TABSTOP, rect, parent, ID); 57 | } 58 | 59 | int DefinitionView::OnCreate(LPCREATESTRUCT cs) 60 | { 61 | if (CWnd::OnCreate(cs) < 0) return -1; 62 | EnableScrollBarCtrl(SB_BOTH, FALSE); 63 | 64 | START_CREATE; 65 | BUTTONLABEL(def); 66 | 67 | return 0; 68 | } 69 | 70 | void DefinitionView::Update(bool full) 71 | { 72 | CRect bounds; GetClientRect(bounds); 73 | UserFunction *f = function(); 74 | if (!f) return; 75 | 76 | def.SetWindowText(Convert(f->formula())); 77 | 78 | if (!full) return; 79 | 80 | Layout layout(*this, 0, 20); SET(-1); USE(&def); 81 | } 82 | 83 | void DefinitionView::OnInitialUpdate() 84 | { 85 | Update(true); 86 | } 87 | 88 | void DefinitionView::OnSize(UINT type, int w, int h) 89 | { 90 | CWnd::OnSize(type, w, h); 91 | EnableScrollBarCtrl(SB_BOTH, FALSE); 92 | Update(true); 93 | } 94 | 95 | void DefinitionView::OnEdit() 96 | { 97 | auto *f = function(); if (!f) return; 98 | parent.OnEdit(f); 99 | } 100 | -------------------------------------------------------------------------------- /Windows/Controls/DefinitionView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "../../Engine/Namespace/UserFunction.h" 4 | #include "NumericEdit.h" 5 | #include "DeltaSlider.h" 6 | class SideSectionDefs; 7 | 8 | class DefinitionView : public CWnd 9 | { 10 | public: 11 | DefinitionView(SideSectionDefs &parent, UserFunction &f); 12 | UserFunction *function() const { return (UserFunction*)IDCarrier::find(f_id); } 13 | 14 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 15 | BOOL Create(const RECT &rect, CWnd *parent, UINT ID); 16 | int OnCreate(LPCREATESTRUCT cs); 17 | void OnSize(UINT type, int w, int h); 18 | void OnInitialUpdate(); 19 | 20 | void Update(bool full); 21 | void OnEdit(); 22 | 23 | private: 24 | SideSectionDefs &parent; 25 | IDCarrier::OID f_id; 26 | 27 | CMFCButton def; 28 | 29 | DECLARE_DYNAMIC(DefinitionView) 30 | DECLARE_MESSAGE_MAP() 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /Windows/Controls/DeltaSlider.cpp: -------------------------------------------------------------------------------- 1 | #include "DeltaSlider.h" 2 | #include "../../Utility/Preferences.h" 3 | 4 | #define M 32000 5 | 6 | BEGIN_MESSAGE_MAP(DeltaSlider, CSliderCtrl) 7 | ON_WM_CREATE() 8 | ON_WM_HSCROLL_REFLECT() 9 | ON_WM_TIMER() 10 | END_MESSAGE_MAP() 11 | 12 | DeltaSlider::DeltaSlider() : active_(false), slideback_(false) 13 | { 14 | } 15 | 16 | int DeltaSlider::OnCreate(LPCREATESTRUCT cs) 17 | { 18 | if (CSliderCtrl::OnCreate(cs) < 0) return -1; 19 | SetRange(-M, M); 20 | SetPos(0); 21 | SetLineSize(M / 3); 22 | SetPageSize(M / 3); 23 | return 0; 24 | } 25 | 26 | void DeltaSlider::HScroll(UINT code, UINT pos) 27 | { 28 | //CString s; s.Format(_T("hscroll %u %u\n"), code, pos); 29 | //OutputDebugString(s); 30 | 31 | switch (code) 32 | { 33 | case SB_THUMBTRACK: 34 | active(true, false); 35 | break; 36 | default: 37 | active(true, true); 38 | break; 39 | } 40 | } 41 | 42 | double DeltaSlider::evolve(double t) 43 | { 44 | if (!active()) return 0.0; 45 | 46 | int x = GetPos(); 47 | 48 | double dt = t - t0; 49 | constexpr double dt0 = 1.0 / 60.0; 50 | t0 = t; 51 | double scale = dt > 0 ? std::min(dt / dt0, 5.0) : 1.0; 52 | 53 | if (slideback()) 54 | { 55 | v -= (double)x / (double)M * 0.02 * scale; 56 | const int eps = M / 20; 57 | 58 | if (!Preferences::slideback()) 59 | { 60 | x = 0; 61 | } 62 | else if (x > 0) 63 | { 64 | x += (int)(v * M * scale); 65 | if (x < eps) x = 0; 66 | } 67 | else if (x < 0) 68 | { 69 | x += (int)(v * M * scale); 70 | if (x > -eps) x = 0; 71 | } 72 | SetPos(x); 73 | } 74 | 75 | if (x == 0) 76 | { 77 | active(false); 78 | return 0.0; 79 | } 80 | 81 | double r = x / (double)M; 82 | return r * fabs(r) * scale; 83 | } 84 | -------------------------------------------------------------------------------- /Windows/Controls/DeltaSlider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxcmn.h" 3 | 4 | class DeltaSlider: public CSliderCtrl 5 | { 6 | public: 7 | DeltaSlider(); 8 | 9 | std::function stateChange; 10 | 11 | int OnCreate(LPCREATESTRUCT cs); 12 | void HScroll(UINT code, UINT pos); 13 | 14 | bool active() const { return active_; } 15 | double evolve(double t); // t is current time, returns current dx 16 | 17 | private: 18 | void active(bool f, bool slide = false) 19 | { 20 | if (f != active_) 21 | { 22 | active_ = f; 23 | v = 0.0; 24 | if (stateChange) stateChange(f); 25 | } 26 | if (slide != slideback_) 27 | { 28 | slideback_ = slide; 29 | if (slide) v = 0.0; 30 | } 31 | } 32 | bool slideback() const 33 | { 34 | return slideback_; 35 | } 36 | bool active_, slideback_; 37 | double v; // slideback velocity 38 | double t0; 39 | 40 | DECLARE_MESSAGE_MAP() 41 | }; 42 | -------------------------------------------------------------------------------- /Windows/Controls/FocusEdit.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | #include "FocusEdit.h" 3 | 4 | BEGIN_MESSAGE_MAP(FocusEdit, CEdit) 5 | ON_CONTROL_REFLECT_EX(EN_KILLFOCUS, OnKillFocus) 6 | 7 | ON_COMMAND(ID_EDIT_CUT, OnEditCut) 8 | ON_COMMAND(ID_EDIT_COPY, OnEditCopy) 9 | ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) 10 | ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCopy) // sic 11 | ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy) 12 | ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) 13 | END_MESSAGE_MAP() 14 | 15 | BOOL FocusEdit::PreTranslateMessage(MSG *m) 16 | { 17 | if (m->message == WM_KEYDOWN && m->wParam == VK_RETURN) 18 | { 19 | assert(OnChange); // should always have a handler 20 | if (OnChange) OnChange(); 21 | return TRUE; 22 | } 23 | 24 | return CEdit::PreTranslateMessage(m); 25 | } 26 | 27 | BOOL FocusEdit::OnKillFocus() 28 | { 29 | assert(OnChange); // should always have a handler 30 | if (OnChange) OnChange(); 31 | return FALSE; // pass on to CEdit 32 | } 33 | -------------------------------------------------------------------------------- /Windows/Controls/FocusEdit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include 4 | 5 | class FocusEdit: public CEdit 6 | { 7 | public: 8 | std::function OnChange; 9 | 10 | void OnUpdateEditCopy(CCmdUI *cmd) { int a, b; GetSel(a, b); cmd->Enable(a < b); } 11 | void OnUpdateEditPaste(CCmdUI *cmd) 12 | { 13 | if (!OpenClipboard()) { cmd->Enable(false); return; } 14 | cmd->Enable(GetClipboardData(CF_TEXT) != NULL); 15 | CloseClipboard(); 16 | } 17 | void OnEditCut() { Cut(); } 18 | void OnEditCopy() { Copy(); } 19 | void OnEditPaste() { Paste(); } 20 | 21 | private: 22 | BOOL PreTranslateMessage(MSG *m) override; 23 | BOOL OnKillFocus(); 24 | DECLARE_MESSAGE_MAP() 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /Windows/Controls/GraphView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "../../Graphs/Graph.h" 4 | #include "NumericEdit.h" 5 | #include "DeltaSlider.h" 6 | class SideSectionGraphs; 7 | 8 | class GraphView : public CWnd 9 | { 10 | public: 11 | GraphView(SideSectionGraphs &parent, Graph &g); 12 | Graph *graph() const { return (Graph*)IDCarrier::find(g_id); } 13 | 14 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 15 | BOOL Create(const RECT &rect, CWnd *parent, UINT ID); 16 | int OnCreate(LPCREATESTRUCT cs); 17 | void OnSize(UINT type, int w, int h); 18 | void OnInitialUpdate(); 19 | void OnVisible(); 20 | void OnSelect(); 21 | 22 | void Update(bool full); 23 | 24 | private: 25 | SideSectionGraphs &parent; 26 | IDCarrier::OID g_id; 27 | 28 | CMFCButton desc; 29 | CButton visible; 30 | 31 | DECLARE_DYNAMIC(GraphView) 32 | DECLARE_MESSAGE_MAP() 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /Windows/Controls/HeaderControl.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Controls/HeaderControl.cpp -------------------------------------------------------------------------------- /Windows/Controls/HeaderControl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | 4 | class HeaderControl : public CButton 5 | { 6 | public: 7 | HeaderControl() : canAdd(Hidden), canRemove(Hidden) {} 8 | 9 | enum State{Hidden, Inactive, Active}; 10 | 11 | void SetCanAdd (State s) { if (canAdd == s) return; canAdd = s; Invalidate(); } 12 | void SetCanRemove(State s) { if (canRemove == s) return; canRemove = s; Invalidate(); } 13 | 14 | void OnPaint(); 15 | void OnLButtonDown(UINT flags, CPoint p); 16 | 17 | private: 18 | State canAdd, canRemove; 19 | 20 | DECLARE_MESSAGE_MAP() 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /Windows/Controls/NumericEdit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include 4 | #include "../../Engine/cnum.h" 5 | 6 | class NumericEdit: public CEdit 7 | { 8 | public: 9 | NumericEdit() : real(true), value(UNDEFINED), text(_T("")) { } 10 | 11 | std::function OnChange; 12 | 13 | double GetDouble() const; // these also set the mode to Real 14 | void SetDouble(double x); 15 | cnum GetComplex() const; // these also set the mode to Complex 16 | void SetComplex(cnum z); 17 | 18 | void OnUpdateEditCopy(CCmdUI *cmd) { int a, b; GetSel(a, b); cmd->Enable(a < b); } 19 | void OnUpdateEditPaste(CCmdUI *cmd) 20 | { 21 | if (!OpenClipboard()) { cmd->Enable(false); return; } 22 | cmd->Enable(GetClipboardData(CF_TEXT) != NULL); 23 | CloseClipboard(); 24 | } 25 | void OnEditCut() { Cut(); } 26 | void OnEditCopy() { Copy(); } 27 | void OnEditPaste() { Paste(); } 28 | 29 | private: 30 | mutable bool real; 31 | mutable cnum value; 32 | mutable CString text; 33 | Namespace *find_namespace() const; 34 | 35 | BOOL PreTranslateMessage(MSG *m) override; 36 | BOOL OnKillFocus(); 37 | DECLARE_MESSAGE_MAP() 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /Windows/Controls/ParameterView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "../../Engine/Namespace/Parameter.h" 4 | #include "NumericEdit.h" 5 | #include "DeltaSlider.h" 6 | class SideSectionParams; 7 | 8 | class ParameterView : public CWnd 9 | { 10 | public: 11 | ParameterView(SideSectionParams &parent, Parameter &p); 12 | Parameter *parameter() const { return (Parameter*)IDCarrier::find(p_id); } 13 | 14 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 15 | BOOL Create(const RECT &rect, CWnd *parent, UINT ID); 16 | int OnCreate(LPCREATESTRUCT cs); 17 | void OnSize(UINT type, int w, int h); 18 | void OnInitialUpdate(); 19 | BOOL OnEraseBkgnd(CDC *dc); 20 | 21 | void Update(bool full); 22 | 23 | void OnValueChange(); 24 | void OnEdit(); 25 | void OnPlus(); 26 | void OnMinus(); 27 | void OnAnimate(); 28 | void Animate(double t); 29 | void Change(cnum delta); 30 | void StopAnimation(); 31 | 32 | private: 33 | friend class SideSectionParams; 34 | SideSectionParams &parent; 35 | IDCarrier::OID p_id; 36 | 37 | CMFCButton name; 38 | CStatic eq; 39 | NumericEdit value; 40 | DeltaSlider delta; 41 | CButton anim; 42 | CButton plus, minus; // for integer params 43 | 44 | DECLARE_DYNAMIC(ParameterView) 45 | DECLARE_MESSAGE_MAP() 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /Windows/Controls/SideSection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "HeaderControl.h" 4 | class SideView; 5 | class MainWindow; 6 | struct Plot; 7 | class Graph; 8 | class Document; 9 | 10 | class SideSection : public CWnd 11 | { 12 | public: 13 | virtual BOOL Create(SideView *parent, UINT ID); 14 | 15 | MainWindow *window() const { return (MainWindow*)GetParentFrame(); } 16 | SideView &parent() const { return *(SideView*)GetParent(); } 17 | Document &document() const; 18 | Plot &GetPlot() const; 19 | Graph *GetGraph() const; 20 | 21 | // full updates position and (un)hide child view 22 | // non-full updates only set child state (text, checked, greyed, ...) 23 | virtual void Update(bool full); 24 | 25 | void Position(int &y) 26 | { 27 | CRect r; GetWindowRect(r); 28 | r.MoveToXY(0, y); 29 | MoveWindow(r, false); 30 | y += r.Height(); 31 | } 32 | void Width(int w) 33 | { 34 | CRect r; GetWindowRect(r); 35 | MoveWindow(CRect(r.left, r.top, r.left + w, r.bottom), false); 36 | } 37 | void Show() 38 | { 39 | header.SetCheck(true); 40 | } 41 | 42 | void Redraw(); // the graph, not this! 43 | void Recalc(Plot &plot); 44 | void Recalc(Graph *g); 45 | 46 | int OnCreate(LPCREATESTRUCT cs); 47 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 48 | BOOL OnEraseBkgnd(CDC *dc); 49 | void OnHeader(); 50 | virtual CString headerString() = 0; 51 | virtual CString wndClassName() = 0; 52 | 53 | virtual void OnAdd() {} 54 | virtual void OnRemove() {} 55 | 56 | HeaderControl header; 57 | 58 | DECLARE_MESSAGE_MAP() 59 | }; 60 | 61 | -------------------------------------------------------------------------------- /Windows/Controls/SideSectionAxis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "SideSection.h" 4 | #include "DeltaSlider.h" 5 | #include "NumericEdit.h" 6 | #include "../../Graphs/Geometry/Vector.h" 7 | 8 | class SideSectionAxis : public SideSection 9 | { 10 | public: 11 | CString headerString() override { return _T("Axis"); } 12 | CString wndClassName() override { return _T("SideSectionAxis"); } 13 | void Update(bool full) override; 14 | 15 | int OnCreate(LPCREATESTRUCT cs); 16 | 17 | void Animate(double t); 18 | 19 | CStatic centerLabel, rangeLabel; 20 | CStatic xLabel; NumericEdit xCenter, xRange; DeltaSlider xDelta; 21 | CStatic yLabel; NumericEdit yCenter, yRange; DeltaSlider yDelta; 22 | CStatic zLabel; NumericEdit zCenter, zRange; DeltaSlider zDelta; 23 | DeltaSlider xyzDelta; 24 | CStatic uLabel; NumericEdit uCenter, uRange; DeltaSlider uDelta; 25 | CStatic vLabel; NumericEdit vCenter, vRange; DeltaSlider vDelta; 26 | DeltaSlider uvDelta; 27 | CStatic phiLabel, psiLabel, thetaLabel; 28 | NumericEdit phi, psi, theta; 29 | DeltaSlider phiDelta, psiDelta, thetaDelta; 30 | CStatic distLabel; NumericEdit dist; DeltaSlider distDelta; 31 | CButton center, top, front; 32 | void OnCenterAxis(); 33 | void OnEqualRanges(); 34 | void OnAxisRange(int i, NumericEdit &e); 35 | void OnAxisCenter(int i, NumericEdit &e); 36 | void OnAxisAngle(int i, NumericEdit &e); 37 | void OnDistance(); 38 | void ChangeView(const P3d &v); 39 | void OnTopView() { ChangeView(P3d(0.0, 90.0, 0.0)); } 40 | void OnFrontView() { ChangeView(P3d(0.0, 0.3, 0.0)); } 41 | void OnLeftView() { ChangeView(P3d(90.0, 0.3, 0.0)); } 42 | void OnRightView() { ChangeView(P3d(-90.0, 0.3, 0.0)); } 43 | void OnBackView() { ChangeView(P3d(180.0, 0.3, 0.0)); } 44 | void OnBottomView() { ChangeView(P3d(0.0, -90.0, 0.0)); } 45 | 46 | DECLARE_MESSAGE_MAP() 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /Windows/Controls/SideSectionDefs.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | #include "SideSectionDefs.h" 3 | #include "ViewUtil.h" 4 | #include "../res/resource.h" 5 | #include "../DefinitionController.h" 6 | #include "DefinitionView.h" 7 | #include "../../Graphs/Plot.h" 8 | #include "../SideView.h" 9 | 10 | BEGIN_MESSAGE_MAP(SideSectionDefs, SideSection) 11 | ON_WM_CREATE() 12 | END_MESSAGE_MAP() 13 | 14 | enum 15 | { 16 | ID_header = 2000 17 | }; 18 | 19 | SideSectionDefs::~SideSectionDefs() 20 | { 21 | for (auto *d : defs) delete d; 22 | } 23 | 24 | void SideSectionDefs::OnEdit(UserFunction *f) 25 | { 26 | DefinitionController pc(*this, f); 27 | if (pc.DoModal() == IDOK) 28 | { 29 | Redraw(); 30 | parent().Update(true); 31 | } 32 | } 33 | 34 | int SideSectionDefs::OnCreate(LPCREATESTRUCT cs) 35 | { 36 | if (SideSection::OnCreate(cs) < 0) return -1; 37 | 38 | header.SetCanAdd(HeaderControl::Active); 39 | 40 | return 0; 41 | } 42 | 43 | void SideSectionDefs::Update(bool full) 44 | { 45 | SideSection::Update(full); 46 | 47 | if (!full) 48 | { 49 | for (auto *q : defs) 50 | { 51 | q->Update(false); 52 | } 53 | } 54 | 55 | Layout layout(*this, 22, 22); SET(-1); 56 | const Plot &plot = GetPlot(); 57 | 58 | if (!header.GetCheck()) 59 | { 60 | for (auto *d : defs) HIDE(*d); 61 | } 62 | else 63 | { 64 | // add new parameters, remove deleted ones, sort by name 65 | std::map> 66 | m([](const UserFunction *a, const UserFunction *b) { return a->formula() < b->formula(); }); 67 | for (auto *q : defs) 68 | { 69 | auto *f = q->function(); 70 | if (!f) 71 | { 72 | delete q; 73 | } 74 | else 75 | { 76 | m.insert(std::make_pair(f, q)); 77 | } 78 | } 79 | DS0; 80 | for (UserFunction *f : plot.ns.all_functions(true)) 81 | { 82 | if (m.count(f)) continue; 83 | DefinitionView *q = new DefinitionView(*this, *f); 84 | m.insert(std::make_pair(f, q)); 85 | q->Create(CRect(0, 0, DS(20), DS(22)), this, 3000 + (UINT)f->oid()); 86 | } 87 | defs.clear(); defs.reserve(m.size()); 88 | for (auto i : m) defs.push_back(i.second); 89 | 90 | // place the controls 91 | for (auto *q : defs) 92 | { 93 | USE(q); 94 | q->Update(true); 95 | } 96 | if (!defs.empty()) layout.skip(); 97 | } 98 | 99 | if (full) MoveWindow(0, 0, layout.W, layout.y); 100 | } 101 | -------------------------------------------------------------------------------- /Windows/Controls/SideSectionDefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "SideSection.h" 4 | class DefinitionView; 5 | class UserFunction; 6 | 7 | class SideSectionDefs : public SideSection 8 | { 9 | public: 10 | ~SideSectionDefs(); 11 | CString headerString() override { return _T("Definitions"); } 12 | CString wndClassName() override { return _T("SideSectionDefs"); } 13 | void Update(bool full) override; 14 | 15 | int OnCreate(LPCREATESTRUCT cs); 16 | 17 | void OnAdd() { OnEdit(NULL); } 18 | void OnEdit(UserFunction *p); 19 | 20 | protected: 21 | std::vector defs; 22 | 23 | DECLARE_MESSAGE_MAP() 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /Windows/Controls/SideSectionGraphs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "SideSection.h" 4 | class GraphView; 5 | 6 | class SideSectionGraphs : public SideSection 7 | { 8 | public: 9 | ~SideSectionGraphs(); 10 | CString headerString() override { return _T("Graphs"); } 11 | CString wndClassName() override { return _T("SideSectionGraphs"); } 12 | void Update(bool full) override; 13 | 14 | int OnCreate(LPCREATESTRUCT cs); 15 | 16 | void OnAdd(); 17 | void OnRemove(); 18 | 19 | protected: 20 | std::vector defs; 21 | 22 | DECLARE_MESSAGE_MAP() 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /Windows/Controls/SideSectionParams.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "SideSection.h" 4 | #include "../../Engine/cnum.h" 5 | class Parameter; 6 | class ParameterView; 7 | 8 | class SideSectionParams : public SideSection 9 | { 10 | public: 11 | ~SideSectionParams(); 12 | CString headerString() override { return _T("Parameters"); } 13 | CString wndClassName() override { return _T("SideSectionParams"); } 14 | void Update(bool full) override; 15 | 16 | int OnCreate(LPCREATESTRUCT cs); 17 | 18 | void OnAdd() { OnEdit(NULL); } 19 | void OnEdit(Parameter *p); 20 | void Animate(double t); 21 | void Change(int i, cnum delta); 22 | void ToggleAnimation(int i); 23 | void StopAllAnimation(); 24 | 25 | protected: 26 | std::vector params; 27 | 28 | DECLARE_MESSAGE_MAP() 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /Windows/Controls/SideSectionSettings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "SideSection.h" 4 | #include "TextureControl.h" 5 | #include "NumericEdit.h" 6 | 7 | class SideSectionSettings : public SideSection 8 | { 9 | public: 10 | CString headerString() override { return _T("Settings"); } 11 | CString wndClassName() override { return _T("SideSectionSettings"); } 12 | void Update(bool full) override; 13 | 14 | int OnCreate(LPCREATESTRUCT cs); 15 | 16 | CStatic qualityLabel; CSliderCtrl quality; 17 | void OnHScroll(UINT code, UINT pos, CScrollBar *sb); 18 | 19 | CStatic discoLabel; CButton disco; 20 | void OnDisco(); 21 | 22 | CStatic displayModeLabel; CComboBox displayMode, vfMode; 23 | void OnDisplayMode(); 24 | void OnVFMode(); 25 | void OnCycleVFMode(int d); 26 | CStatic histoModeLabel; CComboBox histoMode; 27 | CStatic histoScaleLabel; NumericEdit histoScale; CSliderCtrl histoScaleSlider; 28 | void OnHistoMode(); 29 | void OnHistoScale(); 30 | 31 | CStatic gridModeLabel, meshModeLabel; 32 | CComboBox gridMode, meshMode; 33 | CSliderCtrl gridDensity, meshDensity; 34 | void OnGridMode(); 35 | void OnMeshMode(); 36 | void OnToggleGrid(); // for PlotView 37 | 38 | CButton drawAxis; 39 | void OnDrawAxis(); 40 | CStatic axisModeLabel; 41 | CButton clip; 42 | void OnClip(); 43 | CComboBox axisMode; 44 | void OnAxisMode(); 45 | 46 | CButton clipCustom, clipLock, clipReset; 47 | CSliderCtrl clipDistance; 48 | void OnClipCustom(); 49 | void OnClipLock(); 50 | void OnClipReset(); 51 | 52 | DECLARE_MESSAGE_MAP() 53 | }; 54 | 55 | -------------------------------------------------------------------------------- /Windows/Controls/SideSectionStyle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "SideSection.h" 4 | #include "TextureControl.h" 5 | #include "NumericEdit.h" 6 | 7 | class SideSectionStyle : public SideSection 8 | { 9 | public: 10 | CString headerString() override { return _T("Style"); } 11 | CString wndClassName() override { return _T("SideSectionStyle"); } 12 | void Update(bool full) override; 13 | 14 | int OnCreate(LPCREATESTRUCT cs); 15 | 16 | void OnHScroll(UINT code, UINT pos, CScrollBar *sb); 17 | 18 | CStatic aaModeLabel; CComboBox aaMode; 19 | void OnAAMode(); 20 | 21 | CStatic transparencyModeLabel; CComboBox transparencyMode; 22 | void OnTransparencyMode(); 23 | 24 | CStatic fogLabel; CSliderCtrl fog; 25 | CStatic lineWidthLabel; CSliderCtrl lineWidth; 26 | CStatic shinynessLabel; CSliderCtrl shinyness; 27 | 28 | CStatic bgLabel, fillLabel, axisLabel, gridLabel; 29 | CMFCColorButton bgColor, fillColor, axisColor, gridColor; 30 | CSliderCtrl bgAlpha, fillAlpha, axisAlpha, gridAlpha; 31 | void OnBgColor(); 32 | void OnFillColor(); 33 | void OnAxisColor(); 34 | void OnGridColor(); 35 | CStatic fontLabel; 36 | CButton font; 37 | void OnFont(); 38 | 39 | CStatic textureLabel, reflectionLabel; 40 | TextureControl texture, reflection; 41 | void OnChangeTexture(int i); 42 | CSliderCtrl textureStrength, reflectionStrength; 43 | void OnVScroll(UINT code, UINT pos, CScrollBar *sb); 44 | CComboBox textureMode; 45 | void OnTextureMode(); 46 | void OnCycleTextureMode(int d); 47 | 48 | DECLARE_MESSAGE_MAP() 49 | }; 50 | 51 | -------------------------------------------------------------------------------- /Windows/Controls/SplitterWnd.cpp: -------------------------------------------------------------------------------- 1 | #include "SplitterWnd.h" 2 | 3 | #ifdef _DEBUG 4 | #define new DEBUG_NEW 5 | #endif 6 | 7 | BEGIN_MESSAGE_MAP(SplitterWnd, CSplitterWnd) 8 | ON_WM_ERASEBKGND() 9 | END_MESSAGE_MAP() 10 | 11 | SplitterWnd::SplitterWnd() 12 | : hidden(false) 13 | { 14 | } 15 | 16 | BOOL SplitterWnd::PreCreateWindow(CREATESTRUCT &cs) 17 | { 18 | if (!CSplitterWnd::PreCreateWindow(cs)) return FALSE; 19 | 20 | cs.style &= ~WS_BORDER; 21 | cs.style |= WS_CHILD; 22 | cs.dwExStyle |= WS_EX_CONTROLPARENT | WS_EX_TRANSPARENT; 23 | 24 | return TRUE; 25 | } 26 | 27 | BOOL SplitterWnd::OnEraseBkgnd(CDC *dc) 28 | { 29 | return FALSE; 30 | } 31 | 32 | void SplitterWnd::Show() 33 | { 34 | if (!hidden) return; 35 | assert(m_nCols == 1); 36 | 37 | ++m_nCols; 38 | 39 | CWnd *p = GetDlgItem(AFX_IDW_PANE_FIRST + 2); 40 | p->ShowWindow(SW_SHOWNA); 41 | GetPane(0, 0)->SetDlgCtrlID(IdFromRowCol(0, 1)); 42 | p->SetDlgCtrlID(IdFromRowCol(0, 0)); 43 | 44 | m_pColInfo[1].nIdealSize = m_pColInfo[0].nCurSize; 45 | m_pColInfo[0].nIdealSize = m_pColInfo[1].nCurSize; 46 | 47 | hidden = false; 48 | RecalcLayout(); 49 | } 50 | 51 | void SplitterWnd::Hide() 52 | { 53 | if (hidden) return; 54 | assert(m_nCols == 2); 55 | 56 | SetActivePane(0, 1); 57 | 58 | CWnd *p = GetPane(0, 0); 59 | p->ShowWindow(SW_HIDE); 60 | p->SetDlgCtrlID(AFX_IDW_PANE_FIRST + 2); 61 | GetPane(0, 1)->SetDlgCtrlID(IdFromRowCol(0, 0)); 62 | 63 | m_pColInfo[1].nCurSize = m_pColInfo[0].nCurSize; 64 | 65 | --m_nCols; 66 | hidden = true; 67 | RecalcLayout(); 68 | } 69 | -------------------------------------------------------------------------------- /Windows/Controls/SplitterWnd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class SplitterWnd : public CSplitterWnd 4 | { 5 | public: 6 | SplitterWnd(); 7 | 8 | void Show(); 9 | void Hide(); 10 | void Toggle() { if (hidden) Show(); else Hide(); } 11 | bool Hidden() { return hidden; } 12 | 13 | BOOL OnEraseBkgnd(CDC *dc); 14 | BOOL PreCreateWindow(CREATESTRUCT &cs); 15 | 16 | private: 17 | bool hidden; 18 | 19 | DECLARE_MESSAGE_MAP() 20 | }; 21 | -------------------------------------------------------------------------------- /Windows/Controls/TextureControl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "../Util/DropHandler.h" 4 | #include 5 | struct GL_Image; 6 | 7 | class TextureControl: public CWnd 8 | { 9 | public: 10 | TextureControl(); 11 | BOOL Create(DWORD style, const RECT &rect, CWnd *parent, UINT ID); 12 | 13 | std::function OnChange; 14 | void SetImage(GL_Image *im); // NULL to clear 15 | 16 | int OnCreate(LPCREATESTRUCT cs); 17 | void OnPaint(); 18 | void OnRButtonUp(UINT flags, CPoint p); 19 | void OnContextItem(UINT which); 20 | bool load(const CString &imageFile); 21 | 22 | private: 23 | GL_Image *im; 24 | size_t im_state; // im->state_counter from last update 25 | CBitmap bmp; 26 | CMenu cm; // context menu 27 | DropHandler drop; 28 | 29 | DECLARE_MESSAGE_MAP() 30 | }; 31 | -------------------------------------------------------------------------------- /Windows/Controls/ViewUtil.cpp: -------------------------------------------------------------------------------- 1 | 2 | CFont &controlFont(bool bold) 3 | { 4 | static CFont font, boldFont; 5 | 6 | if (!font.GetSafeHandle()) 7 | { 8 | font.CreatePointFont(80, _T("MS Shell Dlg")); 9 | 10 | LOGFONT lf; 11 | font.GetLogFont(&lf); 12 | lf.lfWeight = FW_SEMIBOLD; 13 | boldFont.CreateFontIndirect(&lf); 14 | } 15 | 16 | return bold ? boldFont : font; 17 | } 18 | -------------------------------------------------------------------------------- /Windows/Conversions.cpp: -------------------------------------------------------------------------------- 1 | #include "Conversions.h" 2 | 3 | #ifdef UNICODE 4 | CStringW Convert(const std::string &s) 5 | { 6 | const int n = (int)s.length(); if (!n) return L""; 7 | CStringW t; 8 | const int m = MultiByteToWideChar(CP_UTF8, 0, s.data(), n, NULL, 0); 9 | if (m > 0) 10 | { 11 | wchar_t *buf = t.GetBuffer(m); 12 | if (buf) MultiByteToWideChar(CP_UTF8, 0, s.data(), n, buf, m); 13 | t.ReleaseBuffer(); 14 | } 15 | return t; 16 | } 17 | #else 18 | CStringA Convert(const std::string &s) 19 | { 20 | CStringA ret; ret = s.c_str(); 21 | return ret; 22 | } 23 | #endif 24 | 25 | std::string Convert(const CStringW &s) 26 | { 27 | const int n = (int)s.GetLength(); if (!n) return std::string(); 28 | const wchar_t *ss = s.GetString(); 29 | const int m = WideCharToMultiByte(CP_UTF8, 0, ss, n, NULL, 0, NULL, NULL); 30 | std::string t(m, 0); 31 | WideCharToMultiByte(CP_UTF8, 0, ss, n, t._Myptr(), m, NULL, NULL); 32 | return t; 33 | } 34 | 35 | std::string Convert(const CStringA &s) 36 | { 37 | return std::string((const char*)s); 38 | } 39 | -------------------------------------------------------------------------------- /Windows/Conversions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | CString Convert(const std::string &s); 5 | std::string Convert(const CStringW &s); 6 | std::string Convert(const CStringA &s); 7 | -------------------------------------------------------------------------------- /Windows/DefinitionController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "res/Resource.h" 4 | #include "../Engine/Namespace/Parameter.h" 5 | #include "Controls/SideSectionDefs.h" 6 | 7 | class DefinitionController : public CDialogEx 8 | { 9 | DECLARE_DYNAMIC(DefinitionController) 10 | 11 | public: 12 | DefinitionController(SideSectionDefs &parent, UserFunction *f); // f == NULL adds a new def 13 | 14 | private: 15 | virtual void DoDataExchange(CDataExchange* pDX); 16 | BOOL OnInitDialog() override; 17 | 18 | void OnOk(); 19 | void OnCancel(); 20 | void OnDelete(); 21 | CEdit def; 22 | CButton del; 23 | 24 | UserFunction *f; 25 | SideSectionDefs &sv; 26 | 27 | DECLARE_MESSAGE_MAP() 28 | }; 29 | -------------------------------------------------------------------------------- /Windows/Document.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CPlotApp.h" 3 | #include "Document.h" 4 | #include "../Persistence/Serializer.h" 5 | #include "MainWindow.h" 6 | #include "SideView.h" 7 | #include 8 | #ifdef _DEBUG 9 | #define new DEBUG_NEW 10 | #endif 11 | 12 | IMPLEMENT_DYNCREATE(Document, CDocument) 13 | 14 | BOOL Document::OnNewDocument() 15 | { 16 | if (!CDocument::OnNewDocument()) return FALSE; 17 | 18 | plot.clear(); 19 | rns.clear(); 20 | plot.add_graph(); 21 | 22 | MainWindow* w = (MainWindow*)AfxGetMainWnd(); 23 | SideView *sv = w ? &w->GetSideView() : NULL; 24 | if (sv) 25 | { 26 | sv->UpdateAll(); 27 | sv->Redraw(); 28 | w->OnFocusEdit(); 29 | } 30 | 31 | return TRUE; 32 | } 33 | 34 | void Document::Serialize(CArchive &ar) 35 | { 36 | MainWindow* w = (MainWindow*)AfxGetMainWnd(); 37 | SideView *sv = w ? &w->GetSideView() : NULL; 38 | 39 | try 40 | { 41 | if (ar.IsStoring()) 42 | { 43 | FileWriter fw(ar.GetFile()); 44 | Serializer w(fw); 45 | rns.save(w); 46 | plot.save(w); 47 | BoxState b; b.all = (unsigned)-1; 48 | if (sv) b = sv->GetBoxState(); 49 | if (w.version() >= FILE_VERSION_1_8) w.uint32_(b.all); 50 | w.marker_("EOF."); 51 | } 52 | else 53 | { 54 | if (w) w->OnFocusGraph(); 55 | FileReader fr(ar.GetFile()); 56 | Deserializer s(fr); 57 | plot.clear(); // TODO: don't modify on fail 58 | rns.clear(); 59 | rns.load(s); 60 | plot.load(s); 61 | BoxState b; b.all = (unsigned)-1; 62 | if (s.version() >= FILE_VERSION_1_8) s.uint32_(b.all); 63 | if (s.version() < FILE_VERSION_1_11) b.style = b.settings; 64 | b.style = false; // avoid CMFCColorButton problem 65 | s.marker_("EOF."); 66 | assert(s.done()); 67 | if (sv) 68 | { 69 | sv->SetBoxState(b); 70 | sv->UpdateAll(); 71 | sv->Redraw(); 72 | } 73 | } 74 | } 75 | catch (const std::exception &ex) 76 | { 77 | MessageBox(NULL, CString(ex.what()), _T("Error"), MB_OK | MB_ICONERROR); 78 | THROW(new CArchiveException); 79 | } 80 | catch (...) 81 | { 82 | MessageBox(NULL, _T("Unexpected exception"), _T("Error"), MB_OK | MB_ICONERROR); 83 | THROW(new CArchiveException); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Windows/Document.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Engine/Namespace/RootNamespace.h" 3 | #include "../Graphs/Plot.h" 4 | 5 | class Document : public CDocument 6 | { 7 | public: 8 | Document() : plot(rns) {} 9 | 10 | BOOL OnNewDocument() override; 11 | void Serialize(CArchive& ar) override; 12 | 13 | RootNamespace rns; 14 | Plot plot; 15 | 16 | DECLARE_DYNCREATE(Document) 17 | }; 18 | -------------------------------------------------------------------------------- /Windows/Help/Media/CPlot128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/CPlot128.png -------------------------------------------------------------------------------- /Windows/Help/Media/CPlot128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/CPlot128@2x.png -------------------------------------------------------------------------------- /Windows/Help/Media/CPlot64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/CPlot64.png -------------------------------------------------------------------------------- /Windows/Help/Media/CPlot64@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/CPlot64@2x.png -------------------------------------------------------------------------------- /Windows/Help/Media/Color_Riemann.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Color_Riemann.png -------------------------------------------------------------------------------- /Windows/Help/Media/Color_Tiled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Color_Tiled.png -------------------------------------------------------------------------------- /Windows/Help/Media/Complex1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Complex1.png -------------------------------------------------------------------------------- /Windows/Help/Media/Complex2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Complex2.png -------------------------------------------------------------------------------- /Windows/Help/Media/DM_Flatshaded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DM_Flatshaded.png -------------------------------------------------------------------------------- /Windows/Help/Media/DM_Hiddenline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DM_Hiddenline.png -------------------------------------------------------------------------------- /Windows/Help/Media/DM_Points.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DM_Points.png -------------------------------------------------------------------------------- /Windows/Help/Media/DM_Smooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DM_Smooth.png -------------------------------------------------------------------------------- /Windows/Help/Media/DM_Wireframe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DM_Wireframe.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Colors.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_CombinedTextures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_CombinedTextures.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_CustomClipping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_CustomClipping.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Disco_Off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Disco_Off.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Disco_On.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Disco_On.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Fog_Off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Fog_Off.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Fog_On.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Fog_On.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Grid_On.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Grid_On.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Mask.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Polar_Grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Polar_Grid.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Reflection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Reflection.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Shine_Off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Shine_Off.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Shine_On.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Shine_On.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Texture.png -------------------------------------------------------------------------------- /Windows/Help/Media/DS_Transparency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/DS_Transparency.png -------------------------------------------------------------------------------- /Windows/Help/Media/Definitions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Definitions.png -------------------------------------------------------------------------------- /Windows/Help/Media/GammaPhaseField.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/GammaPhaseField.png -------------------------------------------------------------------------------- /Windows/Help/Media/Graph1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Graph1.png -------------------------------------------------------------------------------- /Windows/Help/Media/Graph2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Graph2.png -------------------------------------------------------------------------------- /Windows/Help/Media/Histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Histogram.png -------------------------------------------------------------------------------- /Windows/Help/Media/ImageMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/ImageMode.png -------------------------------------------------------------------------------- /Windows/Help/Media/Implicit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Implicit.png -------------------------------------------------------------------------------- /Windows/Help/Media/Implicit2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Implicit2d.png -------------------------------------------------------------------------------- /Windows/Help/Media/MultiArea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/MultiArea.png -------------------------------------------------------------------------------- /Windows/Help/Media/MultiLine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/MultiLine.png -------------------------------------------------------------------------------- /Windows/Help/Media/Parametric1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Parametric1.png -------------------------------------------------------------------------------- /Windows/Help/Media/Parametric2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Parametric2.png -------------------------------------------------------------------------------- /Windows/Help/Media/Spherical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Spherical.png -------------------------------------------------------------------------------- /Windows/Help/Media/Vectorfield1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Vectorfield1.png -------------------------------------------------------------------------------- /Windows/Help/Media/Vectorfield2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/Help/Media/Vectorfield2.png -------------------------------------------------------------------------------- /Windows/Help/Media/help.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background: white; 4 | font: 14px "Lucida Grande", "Lucida Sans Unicode", Verdana, Lucida, Helvetica, sans-serif; 5 | margin: 30px; 6 | //max-width: 60em; 7 | //margin: auto; 8 | } 9 | p { 10 | max-width: 50em; 11 | margin: auto; 12 | } 13 | ul,ol { 14 | max-width: 50em; 15 | margin: auto; 16 | } 17 | table { 18 | border: 0; 19 | margin: 30px auto; 20 | border-collapse:collapse; 21 | } 22 | td { 23 | vertical-align:top; 24 | border:1px solid #ccc; 25 | padding: 8px 16px; 26 | } 27 | th { 28 | border:1px solid #ccc; 29 | padding: 4px 8px; 30 | font-weight: bold; 31 | margin: 30px; 32 | } 33 | th.origin 34 | { 35 | border:0; 36 | 37 | } 38 | .key { 39 | font: 14px "Courier", fixed; 40 | border:1px solid #ccc; 41 | padding:1px 5px; 42 | } 43 | 44 | div.figures 45 | { 46 | text-align: center; 47 | } 48 | div.figure 49 | { 50 | display: inline-block; 51 | padding: 0; 52 | width: 35em; 53 | margin: 2em 1em; 54 | } 55 | div.figure img 56 | { 57 | display: block; 58 | margin: auto auto 0 auto; 59 | text-align: center; 60 | } 61 | div.figure p 62 | { 63 | width: 100%; 64 | text-align: center; 65 | color: #999; 66 | margin-top: 1em; 67 | } 68 | .right 69 | { 70 | float:right; 71 | margin-left:2em; 72 | } 73 | 74 | h1 { 75 | padding-bottom: 30px; 76 | font-size: 26; 77 | text-align: center; 78 | } 79 | 80 | h2 { 81 | padding: 30px auto 15px; 82 | font-size: 16; 83 | text-align: center; 84 | } 85 | 86 | h3 { 87 | padding: 30px auto 15px; 88 | font-size: 14; 89 | text-align: center; 90 | } 91 | 92 | a { 93 | color: #3f7dd5; 94 | text-decoration: none; 95 | } 96 | a:hover { 97 | text-decoration: underline; 98 | } 99 | 100 | li { 101 | margin-bottom: 6px; 102 | margin-top: 6px; 103 | } 104 | -------------------------------------------------------------------------------- /Windows/Help/Topics/Parameters.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Parameters 7 | 8 | 9 |

Parameter Types

10 |

CPlot supports these types of parameters:

11 |
    12 |
  • Integer, optionally with a lower and/or upper limit
  • 13 |
  • Real, optionally with a lower and/or upper limit
  • 14 |
  • Complex, can have limits on the real and/or imaginary parts, or a maximum on the absolute value
  • 15 |
  • Angles are either real or complex: 16 |
      17 |
    • Real radians: [0, 2π]
    • 18 |
    • Real degrees: [0, 360] (use like sin(a°) in a function that uses radians).
    • 19 |
    • Complex: {exp(it) for t in [0, 2π]}
    • 20 |
    21 | The difference to real/complex is the fixed range and (TODO) that they display a rotary knob instead of a slider to modifiy their value. 22 |
  • 23 |
24 | 25 |

Defining and Changing Parameters

26 |

To create: Use the + button in the Parameters box.

27 |

To edit: Click on the name. At the bottom of the dialog is also a delete button.

28 |

To set the parameter's value, use either the sliders or enter any value into the matching text field. The text field will parse any 29 | entered formula but the parameter stores only the current value, so if a parameter is set to sin(a), it will not update when the value of a changes. 30 | Computed parameters can be defined as custom functions with no arguments.

31 | 32 | 33 | -------------------------------------------------------------------------------- /Windows/Help/Topics/Tips.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Tips and Tricks 6 | 7 | 8 | 9 |

Tips and Tricks

10 |
    11 |
  • Almost all text fields parse formulas (which can include user-defined parameters and definitions).
  • 12 |
  • Setting unused textures to any of the builtin textures saves smaller files (saves only a 4-byte ID, not the image data).
  • 13 |
  • The highest quality setting is almost always overkill (it draws up to 1,000,000 triangles) and should be avoided if you want smooth 14 | parameter animation.
  • 15 |
  • Complex values in real plot modes are considered undefined. If imprecisions yield imaginary parts in functions that 16 | should be real, plotting re(f) instead can help.
  • 17 |
  • Adding a real parameter t and plotting cblend(z, f(z), t) makes t animate between the identity and f. This can be helpful in understanding 18 | how f works. Especially in image mode.
  • 19 |
  • To visualize a set of the form {(x,y) with f(x,y) > 0} plot "f(x,y) > 0" in ℝ² → ℝ graph mode. 20 | More complex logical formulas can be mapped like this: For two logical values (0/1 for false/true) p and q, pq is "p and q", 1-p is "not p" 21 | and 1-(1-p)(1-q) = p+q-pq is "p or q". This last one can also be written as mix(1, p, q) = q∙1 + (1-q)∙p = p+q-pq.
  • 22 |
  • Real textures tend to look a lot better than the builtins. The gallery files use the builtins mainly to keep the file size down.
  • 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /Windows/Help/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | CPlot Help 9 | 20 | 21 | 22 | 23 |
24 | 25 |
26 | 27 |
CPlot
28 |
version 1.10
29 | 31 |
32 | 33 |
34 |

Documentation

35 | 44 | 45 |

Release Notes

46 | 50 |
51 |
52 | 53 | 54 | -------------------------------------------------------------------------------- /Windows/MainView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "PlotView.h" 3 | #include "SideView.h" 4 | #include "MainWindow.h" 5 | #include "Controls/FocusEdit.h" 6 | class Document; 7 | 8 | class BGStatic: public CStatic 9 | { 10 | public: 11 | BOOL Create(CWnd *parent, int h, UINT ID, DWORD style); 12 | BOOL OnEraseBkgnd(CDC *dc); 13 | COLORREF bg; // background color 14 | DECLARE_MESSAGE_MAP() 15 | }; 16 | 17 | class MainView : public CView 18 | { 19 | public: 20 | inline Document& GetDocument() const { return *((MainWindow*)GetParentFrame())->doc; } 21 | inline PlotView& GetPlotView() const { return const_cast(plotView); } 22 | inline SideView& GetSideView() const { return ((MainWindow*)GetParentFrame())->GetSideView(); } 23 | FocusEdit* GetEditView(int i) const; 24 | 25 | void RedrawHeader(); 26 | 27 | BOOL OnEraseBkgnd(CDC *dc); 28 | void OnDraw(CDC *dc); 29 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 30 | int OnCreate(LPCREATESTRUCT cs); 31 | HBRUSH OnCtlColor(CDC *dc, CWnd *wnd, UINT ctrl); 32 | void OnSize(UINT type, int w, int h); 33 | void OnInitialUpdate(); 34 | void Update(); 35 | void OnChangeF1(); 36 | void OnChangeF2(); 37 | void OnChangeF3(); 38 | void OnChangeF(int i, const CString &s); 39 | void OnDomainChange(); 40 | void OnCoordChange(); 41 | void OnModeChange(); 42 | 43 | private: 44 | CRect headerRect() const; 45 | 46 | CComboBox domain, coord, mode; 47 | FocusEdit f [3]; 48 | BGStatic fs[3]; 49 | PlotView plotView; 50 | BGStatic error; 51 | 52 | DECLARE_DYNCREATE(MainView) 53 | DECLARE_MESSAGE_MAP() 54 | }; 55 | 56 | 57 | -------------------------------------------------------------------------------- /Windows/MainWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Controls/SplitterWnd.h" 3 | #include "res/resource.h" 4 | #include "CPlotApp.h" 5 | class MainView; 6 | class SideView; 7 | class Document; 8 | 9 | class MainForm: public CFormView 10 | { 11 | public: 12 | MainForm() : CFormView(IDD_MAINVIEW) {} 13 | 14 | int OnCreate(LPCREATESTRUCT cs); 15 | void OnSize(UINT type, int w, int h); 16 | BOOL PreCreateWindow(CREATESTRUCT &cs); 17 | void OnInitialUpdate() override; 18 | BOOL OnEraseBkgnd(CDC *dc); 19 | 20 | SplitterWnd splitter; 21 | 22 | DECLARE_DYNCREATE(MainForm) 23 | DECLARE_MESSAGE_MAP() 24 | }; 25 | 26 | class MainWindow : public CFrameWndEx 27 | { 28 | public: 29 | MainWindow() : doc(NULL) {} 30 | 31 | MainView &GetMainView() { assert(mainView); return *mainView; } 32 | SideView &GetSideView() { assert(sideView); return *sideView; } 33 | SplitterWnd &GetSplitter() { assert(splitter); return *splitter; } 34 | void Focus(CWnd *who); 35 | 36 | BOOL OnCreateClient(LPCREATESTRUCT cs, CCreateContext *ctx) override; 37 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 38 | int OnCreate(LPCREATESTRUCT cs); 39 | BOOL OnEraseBkgnd(CDC *dc); 40 | void OnFocusGraph(); 41 | void OnFocusEdit(); 42 | 43 | BOOL OnCmdMsg(UINT id, int code, void *extra, AFX_CMDHANDLERINFO *handler) override; 44 | 45 | Document *doc; 46 | 47 | private: 48 | SplitterWnd *splitter; 49 | MainView *mainView; 50 | SideView *sideView; 51 | 52 | DECLARE_DYNCREATE(MainWindow) 53 | DECLARE_MESSAGE_MAP() 54 | }; 55 | 56 | 57 | -------------------------------------------------------------------------------- /Windows/ParameterController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "../Engine/Namespace/Parameter.h" 4 | class SideSectionParams; 5 | 6 | class ParameterController : public CDialogEx 7 | { 8 | DECLARE_DYNAMIC(ParameterController) 9 | 10 | public: 11 | ParameterController(SideSectionParams &parent, Parameter *p); // p == NULL adds a new parameter 12 | 13 | private: 14 | virtual void DoDataExchange(CDataExchange* pDX); 15 | BOOL OnInitDialog() override; 16 | 17 | void OnOk(); 18 | void OnCancel(); 19 | void OnDelete(); 20 | void OnTypeChange(); 21 | CEdit name, rmin, rmax, imin, imax, amax; 22 | CButton t_r, t_c, t_a, t_s, t_i; 23 | CButton rad; 24 | CButton del; 25 | 26 | ParameterType type() const; // selected radio button 27 | void type(ParameterType t); // select matching radio button 28 | 29 | Parameter *p; 30 | SideSectionParams &sv; 31 | 32 | DECLARE_MESSAGE_MAP() 33 | }; 34 | -------------------------------------------------------------------------------- /Windows/PreferencesDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "res/Resource.h" 3 | #include "PreferencesDialog.h" 4 | #include "afxdialogex.h" 5 | #include "../Utility/System.h" 6 | 7 | IMPLEMENT_DYNAMIC(PreferencesDialog, CDialogEx) 8 | BEGIN_MESSAGE_MAP(PreferencesDialog, CDialogEx) 9 | ON_BN_CLICKED(IDC_DYNAMIC, OnBnClickedDynamic) 10 | ON_BN_CLICKED(IDC_SLIDEBACK, OnBnClickedSlideback) 11 | ON_BN_CLICKED(IDC_DEPTHSORT, OnBnClickedDepthsort) 12 | ON_BN_CLICKED(IDC_NORMALS, OnBnClickedNormals) 13 | END_MESSAGE_MAP() 14 | 15 | PreferencesDialog::PreferencesDialog(CWnd* pParent) 16 | : CDialogEx(IDD_PREFERENCES, pParent) 17 | { 18 | } 19 | 20 | void PreferencesDialog::DoDataExchange(CDataExchange* pDX) 21 | { 22 | CDialogEx::DoDataExchange(pDX); 23 | DDX_Control(pDX, IDC_DYNAMIC, dynamic); 24 | DDX_Control(pDX, IDC_SLIDEBACK, slideback); 25 | DDX_Control(pDX, IDC_DEPTHSORT, depthsort); 26 | DDX_Control(pDX, IDC_NORMALS, normals); 27 | DDX_Control(pDX, IDC_THREADS, threads); 28 | DDX_Control(pDX, IDC_THREADS_INFO, threads_info); 29 | } 30 | 31 | BOOL PreferencesDialog::OnInitDialog() 32 | { 33 | CDialogEx::OnInitDialog(); 34 | 35 | dynamic.SetCheck(Preferences::dynamic()); 36 | slideback.SetCheck(Preferences::slideback()); 37 | depthsort.SetCheck(Preferences::depthSort()); 38 | normals.SetCheck(Preferences::drawNormals()); 39 | CString s; s.Format(_T("%d"), Preferences::threads()); 40 | threads.SetWindowText(s); 41 | s.Format(_T("(<= 0 for num cores = %d)"), n_cores); 42 | threads_info.SetWindowText(s); 43 | return TRUE; 44 | } 45 | 46 | void PreferencesDialog::OnBnClickedDynamic() 47 | { 48 | Preferences::dynamic(!Preferences::dynamic()); 49 | dynamic.SetCheck(Preferences::dynamic()); 50 | } 51 | 52 | void PreferencesDialog::OnBnClickedSlideback() 53 | { 54 | Preferences::slideback(!Preferences::slideback()); 55 | slideback.SetCheck(Preferences::slideback()); 56 | } 57 | 58 | void PreferencesDialog::OnBnClickedDepthsort() 59 | { 60 | Preferences::depthSort(!Preferences::depthSort()); 61 | depthsort.SetCheck(Preferences::depthSort()); 62 | } 63 | 64 | void PreferencesDialog::OnBnClickedNormals() 65 | { 66 | Preferences::drawNormals(!Preferences::drawNormals()); 67 | normals.SetCheck(Preferences::drawNormals()); 68 | } 69 | 70 | void PreferencesDialog::OnOK() 71 | { 72 | CString s; threads.GetWindowText(s); 73 | Preferences::threads(_ttoi(s)); 74 | 75 | CDialogEx::OnOK(); 76 | } -------------------------------------------------------------------------------- /Windows/PreferencesDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | 4 | class PreferencesDialog : public CDialogEx 5 | { 6 | public: 7 | PreferencesDialog(CWnd* pParent = NULL); 8 | 9 | private: 10 | virtual void DoDataExchange(CDataExchange* pDX); 11 | 12 | virtual BOOL OnInitDialog(); 13 | virtual void OnOK(); 14 | afx_msg void OnBnClickedDynamic(); 15 | afx_msg void OnBnClickedSlideback(); 16 | afx_msg void OnBnClickedDepthsort(); 17 | afx_msg void OnBnClickedNormals(); 18 | 19 | CButton dynamic; 20 | CButton slideback; 21 | CButton depthsort; 22 | CButton normals; 23 | CEdit threads; 24 | CStatic threads_info; 25 | 26 | DECLARE_DYNAMIC(PreferencesDialog) 27 | DECLARE_MESSAGE_MAP() 28 | }; 29 | -------------------------------------------------------------------------------- /Windows/SideView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include "Controls/HeaderControl.h" 4 | #include "Controls/SideSectionParams.h" 5 | #include "Controls/SideSectionDefs.h" 6 | #include "Controls/SideSectionGraphs.h" 7 | #include "Controls/SideSectionSettings.h" 8 | #include "Controls/SideSectionStyle.h" 9 | #include "Controls/SideSectionAxis.h" 10 | class Document; 11 | class Graph; 12 | struct Plot; 13 | 14 | union BoxState 15 | { 16 | struct 17 | { 18 | bool params : 1; 19 | bool defs : 1; 20 | bool graphs : 1; 21 | bool settings : 1; 22 | bool axis : 1; 23 | bool style : 1; 24 | }; 25 | uint32_t all; 26 | }; 27 | 28 | class SideView : public CScrollView 29 | { 30 | public: 31 | SideView(); 32 | 33 | Document &document() const; 34 | BoxState GetBoxState() const; 35 | void SetBoxState(BoxState b); 36 | 37 | void Redraw(); 38 | void Recalc(Plot &plot); 39 | void Recalc(Graph *g); 40 | void Update(bool full); 41 | 42 | void UpdateParams(bool full) { params.Update(full); if (full) Update(false); } 43 | void UpdateDefs(bool full) { defs.Update(full); if (full) Update(false); } 44 | void UpdateGraphs(bool full) { graphs.Update(full); if (full) Update(false); } 45 | void UpdateSettings(bool full) { settings.Update(full); if (full) Update(false); } 46 | void UpdateStyle(bool full) { style.Update(full); if (full) Update(false); } 47 | void UpdateAxis(bool full) { axis.Update(full); if (full) Update(false); } 48 | void UpdateAll(); 49 | 50 | bool Animating() const; 51 | void Animate(); 52 | 53 | int OnCreate(LPCREATESTRUCT cs); 54 | BOOL PreCreateWindow(CREATESTRUCT &cs) override; 55 | BOOL OnEraseBkgnd(CDC *dc); 56 | void OnSize(UINT type, int w, int h); 57 | void OnInitialUpdate(); 58 | BOOL OnMouseWheel(UINT flags, short dz, CPoint p); 59 | void OnDraw(CDC *dc) override; 60 | 61 | private: 62 | int active_anims; 63 | void AnimStateChanged(bool active); 64 | 65 | int update_w; // bounds.width in last Update call (to optimize OnSize) 66 | 67 | friend class PlotView; // access to OnXxx methods 68 | friend class ParameterView; // access to AnimStateChanged 69 | friend class SideSectionAxis; // access to AnimStateChanged 70 | 71 | SideSectionParams params; 72 | SideSectionDefs defs; 73 | SideSectionGraphs graphs; 74 | SideSectionSettings settings; 75 | SideSectionStyle style; 76 | SideSectionAxis axis; 77 | 78 | DECLARE_DYNCREATE(SideView) 79 | DECLARE_MESSAGE_MAP() 80 | }; 81 | 82 | -------------------------------------------------------------------------------- /Windows/Util/DropHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DropHandler.h" 2 | 3 | DROPEFFECT DropHandler::OnDragEnter(CWnd *w, COleDataObject *data, DWORD keyState, CPoint point) 4 | { 5 | state = DROPEFFECT_NONE; 6 | 7 | HGLOBAL hg = data->GetGlobalData(CF_HDROP); 8 | if (!hg) return false; 9 | HDROP hdrop = (HDROP)GlobalLock(hg); 10 | if (!hdrop) { GlobalUnlock(hg); return false; } 11 | 12 | // Get the number of files dropped 13 | if (DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0) == 1) 14 | { 15 | auto bufsize = 1 + DragQueryFile(hdrop, 0, NULL, 0); 16 | DragQueryFile(hdrop, 0, file.GetBuffer(bufsize), bufsize); 17 | file.ReleaseBuffer(); 18 | 19 | int pos = file.ReverseFind('.'); 20 | if (pos > 0) 21 | { 22 | CString ext = file.Right(file.GetLength() - pos - 1).MakeLower(); 23 | switch (type) 24 | { 25 | case DropHandler::IMAGE: 26 | if (ext == _T("png") || ext == _T("jpg") || ext == _T("jpeg") || 27 | ext == _T("gif") || ext == _T("bmp")) 28 | state = DROPEFFECT_COPY; 29 | break; 30 | case DropHandler::CPLOT: 31 | if (ext == _T("cplot")) 32 | state = DROPEFFECT_COPY; 33 | break; 34 | } 35 | } 36 | } 37 | 38 | GlobalUnlock(hg); 39 | 40 | return state; 41 | } 42 | DROPEFFECT DropHandler::OnDragOver(CWnd *w, COleDataObject* data, DWORD keyState, CPoint point) 43 | { 44 | return state; 45 | } 46 | BOOL DropHandler::OnDrop(CWnd *w, COleDataObject *data, DROPEFFECT dropEffect, CPoint point) 47 | { 48 | return state == DROPEFFECT_NONE ? false : callback(file); 49 | } 50 | void DropHandler::OnDragLeave(CWnd *w) 51 | { 52 | } 53 | -------------------------------------------------------------------------------- /Windows/Util/DropHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | #include 4 | 5 | class DropHandler: public COleDropTarget 6 | { 7 | public: 8 | enum Type 9 | { 10 | IMAGE, 11 | CPLOT 12 | }; 13 | 14 | DropHandler(Type t, std::function callback) 15 | : type(t), callback(callback) 16 | { 17 | assert(callback); 18 | } 19 | 20 | DROPEFFECT OnDragEnter(CWnd *w, COleDataObject *data, DWORD keyState, CPoint point); 21 | DROPEFFECT OnDragOver(CWnd *w, COleDataObject* data, DWORD keyState, CPoint point); 22 | BOOL OnDrop(CWnd *w, COleDataObject *data, DROPEFFECT dropEffect, CPoint point); 23 | void OnDragLeave(CWnd *w); 24 | 25 | protected: 26 | DROPEFFECT state; 27 | CString file; 28 | Type type; 29 | std::function callback; // path -> success 30 | }; 31 | -------------------------------------------------------------------------------- /Windows/Util/Layout.cpp: -------------------------------------------------------------------------------- 1 | #include "Layout.h" 2 | 3 | #define DS(x) MulDiv(x, dpi, 96) 4 | 5 | Layout::Layout(CWnd &c, int y0, int h_row, int space) 6 | { 7 | #ifdef WIN10 8 | dpi = ::GetDpiForWindow(c.GetSafeHwnd()); 9 | #else 10 | HDC tmp_hdc = ::GetDC(c.GetSafeHwnd()); 11 | dpi = ::GetDeviceCaps(tmp_hdc, LOGPIXELSX); 12 | ::ReleaseDC(NULL, tmp_hdc); 13 | #endif 14 | 15 | spc = DS(space); 16 | h = DS(h_row); 17 | y = DS(y0); 18 | 19 | CRect rc; c.GetWindowRect(rc); 20 | W = rc.Width(); 21 | } 22 | 23 | void Layout::operator<< (const std::vector &widths) 24 | { 25 | w = widths; 26 | int rest = W - spc * (int)(w.size()+1), t = 0; 27 | for (int &k : w) 28 | { 29 | if (k < 0) 30 | { 31 | t += k; 32 | } 33 | else 34 | { 35 | k = DS(k); 36 | rest -= k; 37 | } 38 | } 39 | for (int &k : w) if (k < 0) k = rest*k/t; 40 | } 41 | 42 | void Layout::use(const std::vector &C, int h0) 43 | { 44 | int dh = h0 <= 0 ? h : h0; 45 | assert(C.size() == w.size()); 46 | int x = spc; 47 | for (int i = 0, n = (int)C.size(); i < n; ++i) 48 | { 49 | if (!C[i]) 50 | { 51 | x += spc + w[i]; 52 | continue; 53 | } 54 | 55 | CWnd &c = *C[i]; 56 | int cw = w[i]; 57 | while (i + 1 < n && C[i + 1] == &c) 58 | { 59 | cw += spc + w[++i]; 60 | } 61 | 62 | if (cw <= 0) 63 | { 64 | c.ShowWindow(SW_HIDE); 65 | } 66 | else if (h0 > 0) 67 | { 68 | CRect rc(x, y, x + cw, y + dh); 69 | c.MoveWindow(rc); 70 | c.ShowWindow(SW_SHOW); 71 | } 72 | else 73 | { 74 | CRect rc; c.GetWindowRect(rc); 75 | rc.right = rc.left + cw; 76 | rc.MoveToXY(x, y + (h - rc.Height()) / 2); 77 | c.MoveWindow(rc); 78 | c.ShowWindow(SW_SHOW); 79 | } 80 | 81 | x += cw + spc; 82 | 83 | } 84 | y += dh; 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Windows/Util/Layout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "afxwin.h" 3 | 4 | class Layout 5 | { 6 | public: 7 | Layout(CWnd &w, int y0 = 5, int h_row = 24, int space = 5); 8 | void operator<< (const std::vector &widths); 9 | void use(const std::vector &controls, int h = -1); 10 | void height(int h_row) { h = h_row; } 11 | int height() const { return h; } 12 | int operator[](int i) { assert(i < (int)w.size()); return w[i]; } 13 | int y; 14 | int W; 15 | void skip(int n=1) { y += n*spc; } 16 | 17 | private: 18 | UINT dpi; 19 | std::vector w; 20 | int spc; 21 | int h; 22 | }; 23 | 24 | #define SET(...) { auto l = std::vector{__VA_ARGS__}; layout << l; } 25 | #define USE(...) layout.use(std::vector{__VA_ARGS__}) 26 | #define USEH(h, ...) layout.use(std::vector{__VA_ARGS__}, h) 27 | -------------------------------------------------------------------------------- /Windows/glew/bin/Win32/glew32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/bin/Win32/glew32.dll -------------------------------------------------------------------------------- /Windows/glew/bin/Win32/glewinfo.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/bin/Win32/glewinfo.exe -------------------------------------------------------------------------------- /Windows/glew/bin/Win32/visualinfo.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/bin/Win32/visualinfo.exe -------------------------------------------------------------------------------- /Windows/glew/bin/x64/glew32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/bin/x64/glew32.dll -------------------------------------------------------------------------------- /Windows/glew/bin/x64/glewinfo.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/bin/x64/glewinfo.exe -------------------------------------------------------------------------------- /Windows/glew/bin/x64/visualinfo.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/bin/x64/visualinfo.exe -------------------------------------------------------------------------------- /Windows/glew/doc/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/doc/github.png -------------------------------------------------------------------------------- /Windows/glew/doc/glew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/doc/glew.png -------------------------------------------------------------------------------- /Windows/glew/doc/glew.txt: -------------------------------------------------------------------------------- 1 | The OpenGL Extension Wrangler Library 2 | Copyright (C) 2008-2016, Nigel Stewart 3 | Copyright (C) 2002-2008, Milan Ikits 4 | Copyright (C) 2002-2008, Marcelo E. Magallon 5 | Copyright (C) 2002, Lev Povalahev 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | * The name of the author may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Windows/glew/doc/khronos.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007 The Khronos Group Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and/or associated documentation files (the 5 | "Materials"), to deal in the Materials without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Materials, and to 8 | permit persons to whom the Materials are furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Materials. 13 | 14 | THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | -------------------------------------------------------------------------------- /Windows/glew/doc/mesa.txt: -------------------------------------------------------------------------------- 1 | Mesa 3-D graphics library 2 | Version: 7.0 3 | 4 | Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a 7 | copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Windows/glew/doc/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/doc/new.png -------------------------------------------------------------------------------- /Windows/glew/doc/ogl_sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/doc/ogl_sm.jpg -------------------------------------------------------------------------------- /Windows/glew/doc/travis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/doc/travis.png -------------------------------------------------------------------------------- /Windows/glew/lib/Win32/glew32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/lib/Win32/glew32.lib -------------------------------------------------------------------------------- /Windows/glew/lib/Win32/glew32s.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/lib/Win32/glew32s.lib -------------------------------------------------------------------------------- /Windows/glew/lib/x64/glew32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/lib/x64/glew32.lib -------------------------------------------------------------------------------- /Windows/glew/lib/x64/glew32s.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/glew/lib/x64/glew32s.lib -------------------------------------------------------------------------------- /Windows/res/CPlot.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/res/CPlot.ico -------------------------------------------------------------------------------- /Windows/res/CPlot.reg: -------------------------------------------------------------------------------- 1 | REGEDIT 2 | ; This .REG file may be used by your SETUP program. 3 | ; If a SETUP program is not available, the entries below will be 4 | ; registered in your InitInstance automatically with a call to 5 | ; CWinApp::RegisterShellFileTypes and COleObjectFactory::UpdateRegistryAll. 6 | 7 | HKEY_CLASSES_ROOT\.cplot = CPlot.Document 8 | HKEY_CLASSES_ROOT\CPlot.Document\shell\open\command = CPlot.EXE %1 9 | HKEY_CLASSES_ROOT\CPlot.Document\shell\open\ddeexec = [open("%1")] 10 | HKEY_CLASSES_ROOT\CPlot.Document\shell\open\ddeexec\application = CPlot 11 | ; note: the application is optional 12 | ; (it defaults to the app name in "command") 13 | 14 | HKEY_CLASSES_ROOT\CPlot.Document = CPlot.Document 15 | 16 | -------------------------------------------------------------------------------- /Windows/res/CPlotDoc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/res/CPlotDoc.ico -------------------------------------------------------------------------------- /Windows/res/Resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by CPlot.rc 4 | // 5 | #define IDDELETE 3 6 | #define IDD_ABOUTBOX 100 7 | #define IDR_POPUP_EDIT 119 8 | #define IDR_MAINFRAME 128 9 | #define IDR_CPlotTYPE 130 10 | #define IDS_EDIT_MENU 306 11 | #define IDD_PARAMETER 310 12 | #define IDD_MAINVIEW 311 13 | #define IDD_DEFINITION 312 14 | #define IDR_HELP_MENU 322 15 | #define IDD_PREFERENCES 323 16 | #define IDC_PARAM_RADIANS 1002 17 | #define IDC_PARAM_NAME 1014 18 | #define IDC_PARAM_T_REAL 1015 19 | #define IDC_PARAM_T_COMPLEX 1016 20 | #define IDC_PARAM_T_ANGLE 1017 21 | #define IDC_PARAM_T_INT 1018 22 | #define IDC_PARAM_T_CANGLE 1019 23 | #define IDC_PARAM_RMIN 1020 24 | #define IDC_PARAM_RMAX 1021 25 | #define IDC_PARAM_IMIN 1022 26 | #define IDC_PARAM_IMAX 1023 27 | #define IDC_PARAM_ABSMAX 1024 28 | #define IDC_DEF_FORMULA 1025 29 | #define IDC_DYNAMIC 1026 30 | #define IDC_SLIDEBACK 1027 31 | #define IDC_DEPTHSORT 1028 32 | #define IDC_THREADS 1029 33 | #define IDC_THREADS_INFO 1030 34 | #define IDC_NORMALS 1031 35 | #define ID_VIEW_PROPERTIES 32777 36 | #define ID_VIEW_GRAPH 32784 37 | #define ID_VIEW_FORMULA 32785 38 | #define ID_VIEW_PREFERENCES 32789 39 | 40 | // Next default values for new objects 41 | // 42 | #ifdef APSTUDIO_INVOKED 43 | #ifndef APSTUDIO_READONLY_SYMBOLS 44 | #define _APS_NEXT_RESOURCE_VALUE 325 45 | #define _APS_NEXT_COMMAND_VALUE 32796 46 | #define _APS_NEXT_CONTROL_VALUE 1031 47 | #define _APS_NEXT_SYMED_VALUE 310 48 | #endif 49 | #endif 50 | -------------------------------------------------------------------------------- /Windows/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /Windows/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(disable:4800) /* disable the idiotic performance warnings for bool casts*/ 4 | #pragma warning(disable:4100) /* unreferenced function arguments are ok */ 5 | 6 | #include "../pch.h" 7 | 8 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 9 | 10 | #include "targetver.h" 11 | 12 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 13 | 14 | #define _AFX_ALL_WARNINGS 15 | 16 | #include // MFC core and standard components 17 | #include // MFC extensions 18 | #include // MFC Automation classes 19 | 20 | #ifndef _AFX_NO_OLE_SUPPORT 21 | #include // MFC support for Internet Explorer 4 Common Controls 22 | #endif 23 | #ifndef _AFX_NO_AFXCMN_SUPPORT 24 | #include // MFC support for Windows Common Controls 25 | #endif // _AFX_NO_AFXCMN_SUPPORT 26 | 27 | #include // MFC support for ribbons and control bars 28 | 29 | #ifdef _UNICODE 30 | #if defined _M_IX86 31 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 32 | #elif defined _M_X64 33 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 34 | #else 35 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 36 | #endif 37 | #endif 38 | 39 | #undef min 40 | #undef max 41 | #undef near 42 | #undef far 43 | #undef FAR 44 | #undef NEAR 45 | 46 | inline COLORREF GREY(BYTE y) { return RGB(y, y, y); } 47 | 48 | #undef TRANSPARENT 49 | #undef OPAQUE 50 | #define MFC_TRANSPARENT 1 51 | #define MFC_OPAQUE 2 52 | 53 | #define strncasecmp _strnicmp 54 | #undef ERROR 55 | 56 | #define GLEW_STATIC 57 | #include 58 | #include 59 | 60 | #include "Conversions.h" 61 | -------------------------------------------------------------------------------- /Windows/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /Windows/zlib/Win32/zlib.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/zlib/Win32/zlib.lib -------------------------------------------------------------------------------- /Windows/zlib/Win32/zlib.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/zlib/Win32/zlib.pdb -------------------------------------------------------------------------------- /Windows/zlib/x64/zlib.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/zlib/x64/zlib.lib -------------------------------------------------------------------------------- /Windows/zlib/x64/zlib.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/Windows/zlib/x64/zlib.pdb -------------------------------------------------------------------------------- /gen_pkgbuild: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # usage: pass any arguments to print to stdout, otherwise this will 3 | # create or overwrite PKGBUILD in current directory 4 | use strict; 5 | use warnings; 6 | 7 | chomp(my $commit = `git rev-parse HEAD`); 8 | chomp(my $version = `git describe --tags --abbrev=0 --match 'v*.*'`); 9 | chomp(my $tag_commit = `git rev-parse '$version'`); 10 | my $tagged = ($commit eq $tag_commit); 11 | $version =~ s/^v//; 12 | die "invalid version tag!" unless $version =~ /^\d+(\.\d+)+(\.?[a-zA-Z0-9]+)?$/; 13 | 14 | my $source = "commit=$commit"; 15 | my $suffix = ""; 16 | if (!$tagged) { 17 | $suffix = "-git\nprovides=('cplot')\nconflicts=('cplot')"; 18 | $source = "branch=master"; 19 | $version = "0"; 20 | } 21 | 22 | my $F; 23 | if (@ARGV) { 24 | $F = *STDOUT; 25 | } else { 26 | open($F,'>','PKGBUILD') or die $!; 27 | } 28 | 29 | print $F "# Maintainer: Torsten Hilgenberg 30 | 31 | pkgname=cplot$suffix 32 | pkgver=$version 33 | pkgrel=1 34 | pkgdesc='Function plotter for real and complex mathematical functions' 35 | url='https://zoon.cc/cplot/' 36 | license=('MIT') 37 | arch=('x86_64') 38 | 39 | depends=('zlib' 'sdl2' 'libgl' 'glu' 'glew' 'glibc' 'pango' 'cairo') 40 | makedepends=('git' 'python>=3.0.0' 'ninja' 'boost') 41 | source=('git+https://github.com/hilgenberg/cplot#$source') 42 | sha256sums=('SKIP') 43 | "; 44 | 45 | print $F q! 46 | pkgver() { 47 | cd "$srcdir/cplot/" 48 | git describe --long --tags --match 'v*.*' | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' 49 | } 50 | ! unless $tagged; 51 | 52 | print $F ' 53 | prepare() { 54 | cd "$srcdir/cplot/" 55 | git submodule update --init --recursive --depth 1 56 | } 57 | 58 | build() { 59 | cd "$srcdir/cplot/" 60 | ./build release 61 | } 62 | 63 | package() { 64 | cd "$srcdir/cplot/" 65 | install -Dm755 -t "$pkgdir/usr/bin/" build_release/cplot 66 | install -Dm644 -t "$pkgdir/usr/share/cplot/" Plot\ Examples/*.cplot 67 | install -Dm644 -t "$pkgdir/usr/share/licenses/cplot/" LICENSE 68 | } 69 | '; 70 | 71 | close($F); 72 | -------------------------------------------------------------------------------- /leaks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | valgrind --tool=memcheck --leak-check=yes ./cplot "$@" 4 | -------------------------------------------------------------------------------- /pch.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define _USE_MATH_DEFINES 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #ifndef _WINDOWS 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #endif 34 | 35 | #include "Utility/StringFormatting.h" 36 | 37 | using std::isnan; 38 | using std::isinf; 39 | using std::isfinite; 40 | 41 | -------------------------------------------------------------------------------- /test.cplot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hilgenberg/cplot/4f8475e428bc936977bdc3481b9231a95c698d58/test.cplot -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | VERSION="2.1.dev" --------------------------------------------------------------------------------