├── .gitignore ├── FunctionParser.sln ├── FunctionParser ├── FunctionParser.cs ├── FunctionParser.csproj └── Properties │ └── AssemblyInfo.cs ├── FunctionParserAndPlotterTester ├── App.config ├── Form1.Designer.cs ├── Form1.cs ├── Form1.resx ├── FunctionParserAndPlotterTester.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── frm_AddFunction.Designer.cs ├── frm_AddFunction.cs └── frm_AddFunction.resx ├── FunctionParserWindowsFormTester ├── AddIDForm.Designer.cs ├── AddIDForm.cs ├── AddIDForm.resx ├── App.config ├── Form1.Designer.cs ├── Form1.cs ├── Form1.resx ├── Form_ID.Designer.cs ├── Form_ID.cs ├── Form_ID.resx ├── FunctionParserWindowsFormTester.csproj ├── Program.cs └── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── FunctionPlotter ├── FunctionPlotter.csproj ├── Plotter.cs └── Properties │ └── AssemblyInfo.cs ├── LICENSE ├── README.md └── docs └── images ├── example_1.png └── record.gif /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | 56 | # StyleCop 57 | StyleCopReport.xml 58 | 59 | # Files built by Visual Studio 60 | *_i.c 61 | *_p.c 62 | *_h.h 63 | *.ilk 64 | *.meta 65 | *.obj 66 | *.iobj 67 | *.pch 68 | *.pdb 69 | *.ipdb 70 | *.pgc 71 | *.pgd 72 | *.rsp 73 | *.sbr 74 | *.tlb 75 | *.tli 76 | *.tlh 77 | *.tmp 78 | *.tmp_proj 79 | *.log 80 | *.vspscc 81 | *.vssscc 82 | .builds 83 | *.pidb 84 | *.svclog 85 | *.scc 86 | 87 | # Chutzpah Test files 88 | _Chutzpah* 89 | 90 | # Visual C++ cache files 91 | ipch/ 92 | *.aps 93 | *.ncb 94 | *.opendb 95 | *.opensdf 96 | *.sdf 97 | *.cachefile 98 | *.VC.db 99 | *.VC.VC.opendb 100 | 101 | # Visual Studio profiler 102 | *.psess 103 | *.vsp 104 | *.vspx 105 | *.sap 106 | 107 | # Visual Studio Trace Files 108 | *.e2e 109 | 110 | # TFS 2012 Local Workspace 111 | $tf/ 112 | 113 | # Guidance Automation Toolkit 114 | *.gpState 115 | 116 | # ReSharper is a .NET coding add-in 117 | _ReSharper*/ 118 | *.[Rr]e[Ss]harper 119 | *.DotSettings.user 120 | 121 | # JustCode is a .NET coding add-in 122 | .JustCode 123 | 124 | # TeamCity is a build add-in 125 | _TeamCity* 126 | 127 | # DotCover is a Code Coverage Tool 128 | *.dotCover 129 | 130 | # AxoCover is a Code Coverage Tool 131 | .axoCover/* 132 | !.axoCover/settings.json 133 | 134 | # Visual Studio code coverage results 135 | *.coverage 136 | *.coveragexml 137 | 138 | # NCrunch 139 | _NCrunch_* 140 | .*crunch*.local.xml 141 | nCrunchTemp_* 142 | 143 | # MightyMoose 144 | *.mm.* 145 | AutoTest.Net/ 146 | 147 | # Web workbench (sass) 148 | .sass-cache/ 149 | 150 | # Installshield output folder 151 | [Ee]xpress/ 152 | 153 | # DocProject is a documentation generator add-in 154 | DocProject/buildhelp/ 155 | DocProject/Help/*.HxT 156 | DocProject/Help/*.HxC 157 | DocProject/Help/*.hhc 158 | DocProject/Help/*.hhk 159 | DocProject/Help/*.hhp 160 | DocProject/Help/Html2 161 | DocProject/Help/html 162 | 163 | # Click-Once directory 164 | publish/ 165 | 166 | # Publish Web Output 167 | *.[Pp]ublish.xml 168 | *.azurePubxml 169 | # Note: Comment the next line if you want to checkin your web deploy settings, 170 | # but database connection strings (with potential passwords) will be unencrypted 171 | *.pubxml 172 | *.publishproj 173 | 174 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 175 | # checkin your Azure Web App publish settings, but sensitive information contained 176 | # in these scripts will be unencrypted 177 | PublishScripts/ 178 | 179 | # NuGet Packages 180 | *.nupkg 181 | # The packages folder can be ignored because of Package Restore 182 | **/[Pp]ackages/* 183 | # except build/, which is used as an MSBuild target. 184 | !**/[Pp]ackages/build/ 185 | # Uncomment if necessary however generally it will be regenerated when needed 186 | #!**/[Pp]ackages/repositories.config 187 | # NuGet v3's project.json files produces more ignorable files 188 | *.nuget.props 189 | *.nuget.targets 190 | 191 | # Microsoft Azure Build Output 192 | csx/ 193 | *.build.csdef 194 | 195 | # Microsoft Azure Emulator 196 | ecf/ 197 | rcf/ 198 | 199 | # Windows Store app package directories and files 200 | AppPackages/ 201 | BundleArtifacts/ 202 | Package.StoreAssociation.xml 203 | _pkginfo.txt 204 | *.appx 205 | 206 | # Visual Studio cache files 207 | # files ending in .cache can be ignored 208 | *.[Cc]ache 209 | # but keep track of directories ending in .cache 210 | !*.[Cc]ache/ 211 | 212 | # Others 213 | ClientBin/ 214 | ~$* 215 | *~ 216 | *.dbmdl 217 | *.dbproj.schemaview 218 | *.jfm 219 | *.pfx 220 | *.publishsettings 221 | orleans.codegen.cs 222 | 223 | # Including strong name files can present a security risk 224 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 225 | #*.snk 226 | 227 | # Since there are multiple workflows, uncomment next line to ignore bower_components 228 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 229 | #bower_components/ 230 | 231 | # RIA/Silverlight projects 232 | Generated_Code/ 233 | 234 | # Backup & report files from converting an old project file 235 | # to a newer Visual Studio version. Backup files are not needed, 236 | # because we have git ;-) 237 | _UpgradeReport_Files/ 238 | Backup*/ 239 | UpgradeLog*.XML 240 | UpgradeLog*.htm 241 | ServiceFabricBackup/ 242 | *.rptproj.bak 243 | 244 | # SQL Server files 245 | *.mdf 246 | *.ldf 247 | *.ndf 248 | 249 | # Business Intelligence projects 250 | *.rdl.data 251 | *.bim.layout 252 | *.bim_*.settings 253 | *.rptproj.rsuser 254 | 255 | # Microsoft Fakes 256 | FakesAssemblies/ 257 | 258 | # GhostDoc plugin setting file 259 | *.GhostDoc.xml 260 | 261 | # Node.js Tools for Visual Studio 262 | .ntvs_analysis.dat 263 | node_modules/ 264 | 265 | # Visual Studio 6 build log 266 | *.plg 267 | 268 | # Visual Studio 6 workspace options file 269 | *.opt 270 | 271 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 272 | *.vbw 273 | 274 | # Visual Studio LightSwitch build output 275 | **/*.HTMLClient/GeneratedArtifacts 276 | **/*.DesktopClient/GeneratedArtifacts 277 | **/*.DesktopClient/ModelManifest.xml 278 | **/*.Server/GeneratedArtifacts 279 | **/*.Server/ModelManifest.xml 280 | _Pvt_Extensions 281 | 282 | # Paket dependency manager 283 | .paket/paket.exe 284 | paket-files/ 285 | 286 | # FAKE - F# Make 287 | .fake/ 288 | 289 | # JetBrains Rider 290 | .idea/ 291 | *.sln.iml 292 | 293 | # CodeRush 294 | .cr/ 295 | 296 | # Python Tools for Visual Studio (PTVS) 297 | __pycache__/ 298 | *.pyc 299 | 300 | # Cake - Uncomment if you are using it 301 | # tools/** 302 | # !tools/packages.config 303 | 304 | # Tabs Studio 305 | *.tss 306 | 307 | # Telerik's JustMock configuration file 308 | *.jmconfig 309 | 310 | # BizTalk build output 311 | *.btp.cs 312 | *.btm.cs 313 | *.odx.cs 314 | *.xsd.cs 315 | 316 | # OpenCover UI analysis results 317 | OpenCover/ 318 | 319 | # Azure Stream Analytics local run output 320 | ASALocalRun/ 321 | 322 | # MSBuild Binary and Structured Log 323 | *.binlog 324 | 325 | # NVidia Nsight GPU debugger configuration file 326 | *.nvuser 327 | 328 | # MFractors (Xamarin productivity tool) working folder 329 | .mfractor/ 330 | 331 | # Local History for Visual Studio 332 | .localhistory/ -------------------------------------------------------------------------------- /FunctionParser.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionParser", "FunctionParser\FunctionParser.csproj", "{4BEC9A15-40FE-44DE-BC77-2F243D180772}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionParserWindowsFormTester", "FunctionParserWindowsFormTester\FunctionParserWindowsFormTester.csproj", "{3F4D032D-2548-4E36-AD17-0BA72215A9AD}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionPlotter", "FunctionPlotter\FunctionPlotter.csproj", "{2D5FA28F-AFFB-4A6E-9CE2-A61DBC6BB245}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionParserAndPlotterTester", "FunctionParserAndPlotterTester\FunctionParserAndPlotterTester.csproj", "{E3082C48-B7BF-4A22-AF1A-DA9C20C734D2}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {4BEC9A15-40FE-44DE-BC77-2F243D180772}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {4BEC9A15-40FE-44DE-BC77-2F243D180772}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {4BEC9A15-40FE-44DE-BC77-2F243D180772}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {4BEC9A15-40FE-44DE-BC77-2F243D180772}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {3F4D032D-2548-4E36-AD17-0BA72215A9AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {3F4D032D-2548-4E36-AD17-0BA72215A9AD}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {3F4D032D-2548-4E36-AD17-0BA72215A9AD}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {3F4D032D-2548-4E36-AD17-0BA72215A9AD}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {2D5FA28F-AFFB-4A6E-9CE2-A61DBC6BB245}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {2D5FA28F-AFFB-4A6E-9CE2-A61DBC6BB245}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {2D5FA28F-AFFB-4A6E-9CE2-A61DBC6BB245}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {2D5FA28F-AFFB-4A6E-9CE2-A61DBC6BB245}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {E3082C48-B7BF-4A22-AF1A-DA9C20C734D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {E3082C48-B7BF-4A22-AF1A-DA9C20C734D2}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {E3082C48-B7BF-4A22-AF1A-DA9C20C734D2}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {E3082C48-B7BF-4A22-AF1A-DA9C20C734D2}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /FunctionParser/FunctionParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace FunctionParser 8 | { 9 | public class Function : ParsTreeNode 10 | { 11 | public enum FunctionEnum 12 | { 13 | Sinh, Sin, Cosh, Cos, Tanh, Tan, Coth, Cot, Sich, Sic, Csch, Csc, E, Log, Ln 14 | } 15 | public static bool IsFunction(string function, string[] ids) 16 | { 17 | foreach (string func in Enum.GetNames(typeof(FunctionEnum))) 18 | { 19 | if (function.ToLower().StartsWith(func.ToLower())) 20 | { 21 | return Term.IsTerm(function.Substring(func.Length), ids); 22 | } 23 | } 24 | return false; 25 | } 26 | public FunctionEnum Func { get; set; } 27 | public Term Term; 28 | 29 | public Function(string function, string[] ids, ParsTreeNode parent) 30 | : base(function, ids, parent) 31 | { 32 | 33 | foreach (string func in Enum.GetNames(typeof(FunctionEnum))) 34 | { 35 | if (function.ToLower().StartsWith(func.ToLower())) 36 | { 37 | 38 | Func = (FunctionEnum)Enum.Parse(typeof(FunctionEnum), func); 39 | this.Term = new Term(function.Substring(func.Length), ids, this); 40 | break; 41 | } 42 | } 43 | } 44 | public override double CalculateValue(double[] idsValue) 45 | { 46 | double termValue = this.Term.CalculateValue(idsValue); 47 | double ret = 0; 48 | switch (Func) 49 | { 50 | case FunctionEnum.Sin: 51 | ret = Math.Sin(termValue * Math.PI / 180); 52 | break; 53 | case FunctionEnum.Cos: 54 | ret = Math.Sin(termValue * Math.PI / 180); 55 | break; 56 | case FunctionEnum.Tan: 57 | ret = Math.Tan(termValue * Math.PI / 180); 58 | break; 59 | case FunctionEnum.Sinh: 60 | ret = Math.Sinh(termValue * Math.PI / 180); 61 | break; 62 | case FunctionEnum.Cosh: 63 | ret = Math.Cosh(termValue * Math.PI / 180); 64 | break; 65 | case FunctionEnum.Tanh: 66 | ret = Math.Tanh(termValue * Math.PI / 180); 67 | break; 68 | case FunctionEnum.Csc: 69 | ret = (1 / Math.Sin(termValue * Math.PI / 180)); 70 | break; 71 | case FunctionEnum.Sic: 72 | ret = (1 / Math.Cos(termValue * Math.PI / 180)); 73 | break; 74 | case FunctionEnum.Cot: 75 | ret = (1 / Math.Tan(termValue * Math.PI / 180)); 76 | break; 77 | case FunctionEnum.Csch: 78 | ret = (1 / Math.Sinh(termValue * Math.PI / 180)); 79 | break; 80 | case FunctionEnum.Sich: 81 | ret = (1 / Math.Cosh(termValue * Math.PI / 180)); 82 | break; 83 | case FunctionEnum.Coth: 84 | ret = (1 / Math.Tanh(termValue * Math.PI / 180)); 85 | break; 86 | case FunctionEnum.E: 87 | ret = (Math.Exp(termValue)); 88 | break; 89 | case FunctionEnum.Log: 90 | ret = (Math.Log10(termValue)); 91 | break; 92 | case FunctionEnum.Ln: 93 | ret = (Math.Log(termValue, Math.E)); 94 | break; 95 | } 96 | return ret; 97 | 98 | } 99 | public override double[] CalculateValue(string[] ids, double[][] idsValues) 100 | { 101 | double[] termValue = this.Term.CalculateValue(ids, idsValues); 102 | double[] ret = new double[termValue.Length]; 103 | switch (Func) 104 | { 105 | case FunctionEnum.Sin: 106 | for (int i = 0; i < ret.Length; i++) 107 | ret[i] = Math.Sin(termValue[i] * Math.PI / 180); 108 | break; 109 | case FunctionEnum.Cos: 110 | for (int i = 0; i < ret.Length; i++) 111 | ret[i] = Math.Cos(termValue[i] * Math.PI / 180); 112 | break; 113 | case FunctionEnum.Tan: 114 | for (int i = 0; i < ret.Length; i++) 115 | ret[i] = Math.Tanh(termValue[i] * Math.PI / 180); 116 | break; 117 | case FunctionEnum.Sinh: 118 | for (int i = 0; i < ret.Length; i++) 119 | ret[i] = Math.Sinh(termValue[i] * Math.PI / 180); 120 | break; 121 | case FunctionEnum.Cosh: 122 | for (int i = 0; i < ret.Length; i++) 123 | ret[i] = Math.Cosh(termValue[i] * Math.PI / 180); 124 | break; 125 | case FunctionEnum.Tanh: 126 | for (int i = 0; i < ret.Length; i++) 127 | ret[i] = Math.Tanh(termValue[i] * Math.PI / 180); 128 | break; 129 | case FunctionEnum.Csc: 130 | for (int i = 0; i < ret.Length; i++) 131 | ret[i] = (1 / Math.Sin(termValue[i] * Math.PI / 180)); 132 | break; 133 | case FunctionEnum.Sic: 134 | for (int i = 0; i < ret.Length; i++) 135 | ret[i] = (1 / Math.Cos(termValue[i] * Math.PI / 180)); 136 | break; 137 | case FunctionEnum.Cot: 138 | for (int i = 0; i < ret.Length; i++) 139 | ret[i] = (1 / Math.Tan(termValue[i] * Math.PI / 180)); 140 | break; 141 | case FunctionEnum.Csch: 142 | for (int i = 0; i < ret.Length; i++) 143 | ret[i] = (1 / Math.Sinh(termValue[i] * Math.PI / 180)); 144 | break; 145 | case FunctionEnum.Sich: 146 | for (int i = 0; i < ret.Length; i++) 147 | ret[i] = (1 / Math.Cosh(termValue[i] * Math.PI / 180)); 148 | break; 149 | case FunctionEnum.Coth: 150 | for (int i = 0; i < ret.Length; i++) 151 | ret[i] = (1 / Math.Tanh(termValue[i] * Math.PI / 180)); 152 | break; 153 | case FunctionEnum.E: 154 | for (int i = 0; i < ret.Length; i++) 155 | ret[i] = (Math.Exp(termValue[i])); 156 | break; 157 | case FunctionEnum.Log: 158 | for (int i = 0; i < ret.Length; i++) 159 | ret[i] = (Math.Log10(termValue[i])); 160 | break; 161 | case FunctionEnum.Ln: 162 | for (int i = 0; i < ret.Length; i++) 163 | ret[i] = (Math.Log(Math.E, termValue[i])); 164 | break; 165 | } 166 | return ret; 167 | 168 | } 169 | } 170 | public class Factor : ParsTreeNode 171 | { 172 | public enum FactorExpansion 173 | { 174 | Number,//1,2,3,etc 175 | Function,//sin,cos,etc 176 | MinuFactor,//-x,-15,-sin,-(x+1),etc 177 | WrappedExpression,//(expression) 178 | ID//x 179 | } 180 | public static bool IsFactor(string factor, string[] ids) 181 | { 182 | double tst; 183 | if (double.TryParse(factor, out tst)) 184 | return true; 185 | else if (factor.StartsWith("(") && factor.EndsWith(")") && Expression.IsExpression(factor.Substring(1, factor.Length - 2), ids)) 186 | return true; 187 | else if (factor.StartsWith("-") && Factor.IsFactor(factor.Substring(1, factor.Length - 1), ids)) 188 | return true; 189 | else if (FunctionParser.Function.IsFunction(factor, ids)) 190 | return true; 191 | else if (IsID(factor, ids)) 192 | return true; 193 | else { return false; } 194 | } 195 | private static bool IsID(string id, string[] ids) 196 | { 197 | foreach (string s in ids) 198 | { 199 | if (id == s) 200 | { 201 | return true; 202 | } 203 | 204 | } 205 | return false; 206 | } 207 | public FactorExpansion Expansion { get; set; } 208 | public Function Function { get; set; } 209 | public Expression WrappedExpression { get; set; } 210 | public Factor InnerFactor; 211 | public Factor(string factor, string[] ids, ParsTreeNode parent) 212 | : base(factor, ids, parent) 213 | { 214 | 215 | this.Value = factor; 216 | double value; 217 | if (double.TryParse(factor, out value)) 218 | { 219 | 220 | this.Expansion = FactorExpansion.Number; 221 | } 222 | else 223 | { 224 | if (factor.StartsWith("(") && factor.EndsWith(")")) 225 | { 226 | this.Expansion = FactorExpansion.WrappedExpression; 227 | this.WrappedExpression = new Expression(factor.Substring(1, factor.Length - 2), ids, this); 228 | } 229 | else if (Function.IsFunction(factor, ids)) 230 | { 231 | this.Expansion = FactorExpansion.Function; 232 | this.Function = new Function(factor, ids, this); 233 | 234 | } 235 | else if(factor.StartsWith("-")) 236 | { 237 | this.Expansion = FactorExpansion.MinuFactor; 238 | this.InnerFactor = new Factor(factor.Substring(1, factor.Length - 1), ids, this); 239 | } 240 | else 241 | { 242 | this.Expansion = FactorExpansion.ID; 243 | } 244 | } 245 | 246 | } 247 | public override double CalculateValue(double[] idsValue) 248 | { 249 | if (Expansion == FactorExpansion.Number) 250 | { 251 | return (double.Parse(this.Value)); 252 | } 253 | else if (Expansion == FactorExpansion.WrappedExpression) 254 | { 255 | return (WrappedExpression.CalculateValue(idsValue)); 256 | } 257 | else if (Expansion == FactorExpansion.Function) 258 | { 259 | return (this.Function.CalculateValue(idsValue)); 260 | } 261 | else if(Expansion== FactorExpansion.MinuFactor) 262 | { 263 | return -this.InnerFactor.CalculateValue(idsValue); 264 | } 265 | else 266 | { 267 | //ID 268 | int idIndex = -1; 269 | for (int i = 0; i < IDs.Length; i++) 270 | if (IDs[i] == this.Value) 271 | { 272 | idIndex = i; 273 | break; 274 | } 275 | return idsValue[idIndex]; 276 | 277 | } 278 | } 279 | public override double[] CalculateValue(string[] ids, double[][] idsValues) 280 | { 281 | if (Expansion == FactorExpansion.Number) 282 | { 283 | double[] ret = new double[idsValues.Length]; 284 | double value = double.Parse(this.Value); 285 | for (int i = 0; i < ret.Length; i++) 286 | ret[i] = value; 287 | return ret; 288 | } 289 | else if (Expansion == FactorExpansion.WrappedExpression) 290 | { 291 | return (WrappedExpression.CalculateValue(ids, idsValues)); 292 | } 293 | else if (Expansion == FactorExpansion.Function) 294 | { 295 | return (this.Function.CalculateValue(ids, idsValues)); 296 | } 297 | else if(Expansion== FactorExpansion.MinuFactor) 298 | { 299 | double[] result = this.InnerFactor.CalculateValue(ids, idsValues); 300 | for (int i = 0; i < result.Length; i++) 301 | result[i] = -result[i]; 302 | return result; 303 | } 304 | else 305 | { 306 | //ID 307 | int idIndex = -1; 308 | for (int i = 0; i < ids.Length; i++) 309 | if (ids[i] == this.Value) 310 | { 311 | idIndex = i; 312 | break; 313 | } 314 | return idsValues[idIndex]; 315 | } 316 | } 317 | } 318 | public class Term : ParsTreeNode 319 | { 320 | public enum TermExpansion 321 | { 322 | TermMulFactor, 323 | TermDivFactor, 324 | TermPowFactor, 325 | Factor 326 | } 327 | public static bool IsTerm(string term, string[] ids) 328 | { 329 | int oprIndx = -1; 330 | int brackets = 0; 331 | for (int i = term.Length - 1; i > 0; i--) 332 | { 333 | if ((term[i] == '*' || term[i] == '/' || term[i] == '^') && (brackets == 0)) 334 | { 335 | oprIndx = i; 336 | break; 337 | } 338 | else if (term[i] == ')') brackets++; 339 | else if (term[i] == '(') brackets--; 340 | } 341 | if (oprIndx > 0) 342 | { 343 | 344 | string subterm, factor; 345 | subterm = term.Substring(0, oprIndx); 346 | factor = term.Substring(oprIndx + 1); 347 | return Term.IsTerm(subterm, ids) && Factor.IsFactor(factor, ids); 348 | } 349 | else 350 | { 351 | return FunctionParser.Factor.IsFactor(term, ids); 352 | } 353 | 354 | } 355 | public TermExpansion Expansion { get; set; } 356 | public Term SubTerm { get; set; } 357 | public Factor Factor { get; set; } 358 | public Term(string term, string[] ids, ParsTreeNode parent) 359 | : base(term, ids, parent) 360 | { 361 | 362 | this.Value = term; 363 | int oprIndx = -1; 364 | int brackets = 0; 365 | for (int i = term.Length - 1; i > 0; i--) 366 | { 367 | if ((term[i] == '*' || term[i] == '/' || term[i] == '^') && (brackets == 0)) 368 | { 369 | oprIndx = i; 370 | break; 371 | } 372 | else if (term[i] == ')') brackets++; 373 | else if (term[i] == '(') brackets--; 374 | } 375 | if (oprIndx > 0) 376 | { 377 | 378 | string subterm, factor; 379 | char opr = term[oprIndx]; 380 | subterm = term.Substring(0, oprIndx); 381 | factor = term.Substring(oprIndx + 1); 382 | this.Factor = new Factor(factor, ids, this); 383 | this.SubTerm = new Term(subterm, ids, this); 384 | if (opr == '*') 385 | { 386 | this.Expansion = TermExpansion.TermMulFactor; 387 | } 388 | else if (opr == '/') 389 | { 390 | this.Expansion = TermExpansion.TermDivFactor; 391 | } 392 | else 393 | { 394 | this.Expansion = TermExpansion.TermPowFactor; 395 | } 396 | } 397 | else 398 | { 399 | this.Expansion = TermExpansion.Factor; 400 | this.Factor = new Factor(term, ids, this); 401 | } 402 | 403 | } 404 | public override double CalculateValue(double[] idsValue) 405 | { 406 | if (Expansion == TermExpansion.TermDivFactor) 407 | { 408 | return (this.SubTerm.CalculateValue(idsValue) / this.Factor.CalculateValue(idsValue)); 409 | } 410 | else if (Expansion == TermExpansion.TermMulFactor) 411 | { 412 | return (this.SubTerm.CalculateValue(idsValue) * this.Factor.CalculateValue(idsValue)); 413 | } 414 | else if (Expansion == TermExpansion.TermPowFactor) 415 | { 416 | return (Math.Pow(this.SubTerm.CalculateValue(idsValue), this.Factor.CalculateValue(idsValue))); 417 | } 418 | else 419 | return (this.Factor.CalculateValue(idsValue)); 420 | } 421 | public override double[] CalculateValue(string[] ids, double[][] idsValues) 422 | { 423 | double[] ret = new double[idsValues.Length]; 424 | if (Expansion == TermExpansion.TermDivFactor) 425 | { 426 | double[] subtermValues = this.SubTerm.CalculateValue(ids, idsValues); 427 | double[] factorValues = this.Factor.CalculateValue(ids, idsValues); 428 | for (int i = 0; i < ret.Length; i++) 429 | ret[i] = subtermValues[i] / factorValues[i]; 430 | return ret; 431 | } 432 | else if (Expansion == TermExpansion.TermMulFactor) 433 | { 434 | double[] subtermValues = this.SubTerm.CalculateValue(ids, idsValues); 435 | double[] factorValues = this.Factor.CalculateValue(ids, idsValues); 436 | for (int i = 0; i < ret.Length; i++) 437 | ret[i] = subtermValues[i] * factorValues[i]; 438 | return ret; 439 | } 440 | else if (Expansion == TermExpansion.TermPowFactor) 441 | { 442 | double[] subtermValues = this.SubTerm.CalculateValue(ids, idsValues); 443 | double[] factorValues = this.Factor.CalculateValue(ids, idsValues); 444 | for (int i = 0; i < ret.Length; i++) 445 | ret[i] = Math.Pow(subtermValues[i], factorValues[i]); 446 | return ret; 447 | } 448 | else 449 | return (this.Factor.CalculateValue(ids, idsValues)); 450 | } 451 | } 452 | public class Expression : ParsTreeNode 453 | { 454 | public enum ExpressionExpansion 455 | { 456 | ExpressionPlusTerm, 457 | ExpressionMinusTerm, 458 | Term 459 | } 460 | public static bool IsExpression(string expr, string[] ids) 461 | { 462 | expr = expr.Replace(" ", ""); 463 | int oprIndx = -1; 464 | int brackets = 0; 465 | for (int i = expr.Length - 1; i > 0; i--) 466 | { 467 | if (((expr[i] == '-'&&!IsOperator(expr[i-1])) 468 | || expr[i] == '+') && (brackets == 0)) 469 | { 470 | oprIndx = i; 471 | break; 472 | } 473 | else if (expr[i] == ')') brackets++; 474 | else if (expr[i] == '(') brackets--; 475 | } 476 | if (oprIndx > 0) 477 | { 478 | string subExpr, term; 479 | subExpr = expr.Substring(0, oprIndx); 480 | term = expr.Substring(oprIndx + 1); 481 | return (FunctionParser.Term.IsTerm(term, ids) && IsExpression(subExpr, ids)); 482 | } 483 | else 484 | { 485 | return FunctionParser.Term.IsTerm(expr, ids); 486 | } 487 | } 488 | static bool IsOperator(char c) 489 | { 490 | return c == '-' || c == '+' || c == '*' || c == '/' || c == '^'; 491 | } 492 | public ExpressionExpansion Expansion { get; set; } 493 | public Term Term { get; set; } 494 | public Expression SubExpression { get; set; } 495 | public Expression(string expr, string[] ids, ParsTreeNode parent) 496 | : base(expr, ids, parent) 497 | { 498 | expr=expr.Replace(" ", ""); 499 | int oprIndx = -1; 500 | int brackets = 0; 501 | for (int i = expr.Length - 1; i > 0; i--) 502 | { 503 | if (((expr[i] == '-' && !IsOperator(expr[i - 1])) 504 | || expr[i] == '+') && (brackets == 0)) 505 | { 506 | oprIndx = i; 507 | break; 508 | } 509 | else if (expr[i] == ')') brackets++; 510 | else if (expr[i] == '(') brackets--; 511 | } 512 | if (oprIndx > 0) 513 | { 514 | string subExpr, term; 515 | char opr; 516 | subExpr = expr.Substring(0, oprIndx); 517 | term = expr.Substring(oprIndx + 1); 518 | opr = expr[oprIndx]; 519 | this.Term = new Term(term, ids, this); 520 | this.SubExpression = new Expression(subExpr, ids, this); 521 | if (opr == '-') 522 | { 523 | Expansion = ExpressionExpansion.ExpressionMinusTerm; 524 | } 525 | else 526 | { 527 | Expansion = ExpressionExpansion.ExpressionPlusTerm; 528 | } 529 | } 530 | else 531 | { 532 | Expansion = ExpressionExpansion.Term; 533 | this.Term = new Term(expr, ids, this); 534 | } 535 | } 536 | public override double CalculateValue(double[] idsValue) 537 | { 538 | if (Expansion == ExpressionExpansion.ExpressionMinusTerm) 539 | { 540 | return (this.SubExpression.CalculateValue(idsValue) - this.Term.CalculateValue(idsValue)); 541 | } 542 | else if (Expansion == ExpressionExpansion.ExpressionPlusTerm) 543 | { 544 | return (this.SubExpression.CalculateValue(idsValue) + this.Term.CalculateValue(idsValue)); 545 | } 546 | else 547 | return (this.Term.CalculateValue(idsValue)); 548 | } 549 | public override double[] CalculateValue(string[] ids, double[][] idsValues) 550 | { 551 | double[] ret = new double[idsValues.Length]; 552 | if (Expansion == ExpressionExpansion.ExpressionMinusTerm) 553 | { 554 | double[] subExprValues = this.SubExpression.CalculateValue(ids, idsValues); 555 | double[] termValues = this.Term.CalculateValue(ids, idsValues); 556 | for (int i = 0; i < ret.Length; i++) 557 | ret[i] = subExprValues[i] - termValues[i]; 558 | return ret; 559 | } 560 | else if (Expansion == ExpressionExpansion.ExpressionPlusTerm) 561 | { 562 | double[] subExprValues = this.SubExpression.CalculateValue(ids, idsValues); 563 | double[] termValues = this.Term.CalculateValue(ids, idsValues); 564 | for (int i = 0; i < ret.Length; i++) 565 | ret[i] = subExprValues[i] + termValues[i]; 566 | return ret; 567 | } 568 | else 569 | return (this.Term.CalculateValue(ids, idsValues)); 570 | } 571 | 572 | } 573 | public abstract class ParsTreeNode 574 | { 575 | public string Value { get; set; } 576 | public abstract double CalculateValue(double[] idsValue); 577 | public abstract double[] CalculateValue(string[] ids, double[][] idsValues); 578 | public ParsTreeNode Parent { get; set; } 579 | public string[] IDs { get; set; } 580 | protected ParsTreeNode(string value, string[] ids, ParsTreeNode parnet) 581 | { 582 | this.Value = value.Replace(" ",""); 583 | this.Parent = parnet; 584 | this.IDs = ids; 585 | } 586 | } 587 | } 588 | -------------------------------------------------------------------------------- /FunctionParser/FunctionParser.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4BEC9A15-40FE-44DE-BC77-2F243D180772} 8 | Library 9 | Properties 10 | FunctionParser 11 | FunctionParser 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 54 | -------------------------------------------------------------------------------- /FunctionParser/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FunctionParser")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FunctionParser")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4bec9a15-40fe-44de-bc77-2f243d180772")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Form1.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FunctionParserAndPlotterTester 2 | { 3 | partial class Form1 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.picBox_graph = new System.Windows.Forms.PictureBox(); 32 | this.splitContainer1 = new System.Windows.Forms.SplitContainer(); 33 | this.btn_AddFunction = new System.Windows.Forms.Button(); 34 | this.lst_functions = new System.Windows.Forms.ListView(); 35 | this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 36 | ((System.ComponentModel.ISupportInitialize)(this.picBox_graph)).BeginInit(); 37 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); 38 | this.splitContainer1.Panel1.SuspendLayout(); 39 | this.splitContainer1.Panel2.SuspendLayout(); 40 | this.splitContainer1.SuspendLayout(); 41 | this.SuspendLayout(); 42 | // 43 | // picBox_graph 44 | // 45 | this.picBox_graph.BackColor = System.Drawing.Color.White; 46 | this.picBox_graph.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 47 | this.picBox_graph.Dock = System.Windows.Forms.DockStyle.Fill; 48 | this.picBox_graph.Location = new System.Drawing.Point(0, 0); 49 | this.picBox_graph.Name = "picBox_graph"; 50 | this.picBox_graph.Size = new System.Drawing.Size(695, 674); 51 | this.picBox_graph.TabIndex = 0; 52 | this.picBox_graph.TabStop = false; 53 | this.picBox_graph.Paint += new System.Windows.Forms.PaintEventHandler(this.picBox_graph_Paint); 54 | this.picBox_graph.MouseDown += new System.Windows.Forms.MouseEventHandler(this.picBox_graph_MouseDown); 55 | this.picBox_graph.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picBox_graph_MouseMove); 56 | this.picBox_graph.MouseUp += new System.Windows.Forms.MouseEventHandler(this.picBox_graph_MouseUp); 57 | // 58 | // splitContainer1 59 | // 60 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; 61 | this.splitContainer1.Location = new System.Drawing.Point(0, 0); 62 | this.splitContainer1.Name = "splitContainer1"; 63 | // 64 | // splitContainer1.Panel1 65 | // 66 | this.splitContainer1.Panel1.Controls.Add(this.btn_AddFunction); 67 | this.splitContainer1.Panel1.Controls.Add(this.lst_functions); 68 | // 69 | // splitContainer1.Panel2 70 | // 71 | this.splitContainer1.Panel2.Controls.Add(this.picBox_graph); 72 | this.splitContainer1.Size = new System.Drawing.Size(952, 674); 73 | this.splitContainer1.SplitterDistance = 253; 74 | this.splitContainer1.TabIndex = 2; 75 | // 76 | // btn_AddFunction 77 | // 78 | this.btn_AddFunction.Dock = System.Windows.Forms.DockStyle.Bottom; 79 | this.btn_AddFunction.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 80 | this.btn_AddFunction.Location = new System.Drawing.Point(0, 615); 81 | this.btn_AddFunction.Name = "btn_AddFunction"; 82 | this.btn_AddFunction.Size = new System.Drawing.Size(253, 59); 83 | this.btn_AddFunction.TabIndex = 1; 84 | this.btn_AddFunction.Text = "Add Function"; 85 | this.btn_AddFunction.UseVisualStyleBackColor = true; 86 | this.btn_AddFunction.Click += new System.EventHandler(this.btn_AddFunction_Click); 87 | // 88 | // lst_functions 89 | // 90 | this.lst_functions.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 91 | | System.Windows.Forms.AnchorStyles.Left) 92 | | System.Windows.Forms.AnchorStyles.Right))); 93 | this.lst_functions.CheckBoxes = true; 94 | this.lst_functions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { 95 | this.columnHeader1}); 96 | this.lst_functions.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 97 | this.lst_functions.FullRowSelect = true; 98 | this.lst_functions.GridLines = true; 99 | this.lst_functions.Location = new System.Drawing.Point(3, 3); 100 | this.lst_functions.Name = "lst_functions"; 101 | this.lst_functions.Size = new System.Drawing.Size(250, 616); 102 | this.lst_functions.TabIndex = 0; 103 | this.lst_functions.UseCompatibleStateImageBehavior = false; 104 | this.lst_functions.View = System.Windows.Forms.View.Details; 105 | this.lst_functions.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.lst_functions_ItemChecked); 106 | // 107 | // columnHeader1 108 | // 109 | this.columnHeader1.Text = "Functions"; 110 | this.columnHeader1.Width = 238; 111 | // 112 | // Form1 113 | // 114 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 115 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 116 | this.ClientSize = new System.Drawing.Size(952, 674); 117 | this.Controls.Add(this.splitContainer1); 118 | this.Name = "Form1"; 119 | this.Text = "Plotter"; 120 | ((System.ComponentModel.ISupportInitialize)(this.picBox_graph)).EndInit(); 121 | this.splitContainer1.Panel1.ResumeLayout(false); 122 | this.splitContainer1.Panel2.ResumeLayout(false); 123 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); 124 | this.splitContainer1.ResumeLayout(false); 125 | this.ResumeLayout(false); 126 | 127 | } 128 | 129 | #endregion 130 | 131 | private System.Windows.Forms.PictureBox picBox_graph; 132 | private System.Windows.Forms.SplitContainer splitContainer1; 133 | private System.Windows.Forms.ListView lst_functions; 134 | private System.Windows.Forms.ColumnHeader columnHeader1; 135 | private System.Windows.Forms.Button btn_AddFunction; 136 | } 137 | } 138 | 139 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Form1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | using FunctionPlotter; 6 | using FunctionParser; 7 | 8 | namespace FunctionParserAndPlotterTester 9 | { 10 | public partial class Form1 : Form 11 | { 12 | Plotter plotter; 13 | 14 | //variables for mouse panning 15 | private bool isDown; 16 | private Point lastPoint; 17 | private Point currPoint; 18 | 19 | List graphs = new List(); 20 | 21 | public Form1() 22 | { 23 | InitializeComponent(); 24 | plotter = new Plotter(60, 60, new Point(50, picBox_graph.Height - 50)); 25 | plotter.GridColor = Color.FromArgb(200, 200, 200); 26 | plotter.GridWidth = 1; 27 | plotter.XAxisSubDashesPerUnit = 1; 28 | UpdateGraphs(); 29 | picBox_graph.MouseWheel += PicBox_graph_MouseWheel; 30 | } 31 | 32 | private void PicBox_graph_MouseWheel(object sender, MouseEventArgs e) 33 | { 34 | if (e.Delta > 0) 35 | { 36 | plotter.XPixelsPerUnit *= 2; 37 | plotter.YPixelsPerUnit *= 2; 38 | } 39 | else 40 | { 41 | if (plotter.XPixelsPerUnit > 2) 42 | plotter.XPixelsPerUnit /= 2; 43 | if (plotter.YPixelsPerUnit > 2) 44 | plotter.YPixelsPerUnit /= 2; 45 | } 46 | UpdateGraphs(); 47 | picBox_graph.Invalidate(); 48 | } 49 | 50 | void UpdateGraphs() 51 | { 52 | plotter.Curves.Clear(); 53 | for (int i = 0; i < graphs.Count; i++) 54 | { 55 | if (graphs[i].Shown) 56 | { 57 | graphs[i].Curve.Points.Clear(); 58 | plotter.Curves.Add(graphs[i].Curve); 59 | float resolution = graphs[i].Resolution > 0 ? graphs[i].Resolution : plotter.XResolution; 60 | for (float x = 0; x >= plotter.GetMinX(); x -= resolution) 61 | { 62 | PointF point = new PointF(x, (float)graphs[i].Expression.CalculateValue(new double[] { x })); 63 | graphs[i].Curve.Points.Add(point); 64 | } 65 | graphs[i].Curve.Points.Reverse(); 66 | for (float x = resolution; x <= plotter.GetMaxX(picBox_graph.Width); x += resolution) 67 | { 68 | graphs[i].Curve.Points.Add(new PointF(x, (float)graphs[i].Expression.CalculateValue(new double[] { x }))); 69 | } 70 | } 71 | } 72 | } 73 | private void FilterHiddenGraphs() 74 | { 75 | plotter.Curves.Clear(); 76 | for (int i = 0; i < graphs.Count; i++) 77 | { 78 | if (graphs[i].Shown) 79 | { 80 | plotter.Curves.Add(graphs[i].Curve); 81 | } 82 | } 83 | } 84 | private void picBox_graph_Paint(object sender, PaintEventArgs e) 85 | { 86 | plotter.DrawGridandAxes(e.Graphics, picBox_graph.Width, picBox_graph.Height); 87 | plotter.DrawCurves(e.Graphics); 88 | } 89 | private void picBox_graph_MouseDown(object sender, MouseEventArgs e) 90 | { 91 | isDown = true; 92 | lastPoint = e.Location; 93 | } 94 | private void picBox_graph_MouseMove(object sender, MouseEventArgs e) 95 | { 96 | if (isDown) 97 | { 98 | currPoint = e.Location; 99 | int deltaX = currPoint.X - lastPoint.X; 100 | int deltaY = currPoint.Y - lastPoint.Y; 101 | plotter.Center = new Point(plotter.Center.X + deltaX, plotter.Center.Y + deltaY); 102 | lastPoint = currPoint; 103 | UpdateGraphs(); 104 | picBox_graph.Invalidate(); 105 | } 106 | } 107 | private void picBox_graph_MouseUp(object sender, MouseEventArgs e) 108 | { 109 | isDown = false; 110 | } 111 | 112 | private void lst_functions_ItemChecked(object sender, ItemCheckedEventArgs e) 113 | { 114 | graphs[e.Item.Index].Shown = e.Item.Checked; 115 | FilterHiddenGraphs(); 116 | picBox_graph.Invalidate(); 117 | } 118 | 119 | private void btn_AddFunction_Click(object sender, EventArgs e) 120 | { 121 | frm_AddFunction addFuncForm = new frm_AddFunction(); 122 | if(addFuncForm.ShowDialog()== DialogResult.OK) 123 | { 124 | addFuncForm.ExpressionGraph.Shown = true; 125 | graphs.Add(addFuncForm.ExpressionGraph); 126 | UpdateGraphs(); 127 | picBox_graph.Invalidate(); 128 | ListViewItem func = new ListViewItem(addFuncForm.ExpressionGraph.Expression.Value); 129 | func.ForeColor = addFuncForm.ExpressionGraph.Curve.CurveColor; 130 | func.Checked = true; 131 | lst_functions.Items.Add(func); 132 | } 133 | } 134 | } 135 | public class ExpressionGraphData 136 | { 137 | public Expression Expression { get; set; } 138 | public float Resolution { get; set; } 139 | public Curve Curve { get; set; } 140 | public bool Shown { get; set; } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Form1.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/FunctionParserAndPlotterTester.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E3082C48-B7BF-4A22-AF1A-DA9C20C734D2} 8 | WinExe 9 | Properties 10 | FunctionParserAndPlotterTester 11 | FunctionParserAndPlotterTester 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Form 51 | 52 | 53 | Form1.cs 54 | 55 | 56 | Form 57 | 58 | 59 | frm_AddFunction.cs 60 | 61 | 62 | 63 | 64 | Form1.cs 65 | 66 | 67 | frm_AddFunction.cs 68 | 69 | 70 | ResXFileCodeGenerator 71 | Resources.Designer.cs 72 | Designer 73 | 74 | 75 | True 76 | Resources.resx 77 | 78 | 79 | SettingsSingleFileGenerator 80 | Settings.Designer.cs 81 | 82 | 83 | True 84 | Settings.settings 85 | True 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | {4bec9a15-40fe-44de-bc77-2f243d180772} 94 | FunctionParser 95 | 96 | 97 | {2d5fa28f-affb-4a6e-9ce2-a61dbc6bb245} 98 | FunctionPlotter 99 | 100 | 101 | 102 | 109 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace FunctionParserAndPlotterTester 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new Form1()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FunctionParserAndPlotterTester")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FunctionParserAndPlotterTester")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e3082c48-b7bf-4a22-af1a-da9c20c734d2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FunctionParserAndPlotterTester.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FunctionParserAndPlotterTester.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FunctionParserAndPlotterTester.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/frm_AddFunction.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FunctionParserAndPlotterTester 2 | { 3 | partial class frm_AddFunction 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label1 = new System.Windows.Forms.Label(); 32 | this.txt_expression = new System.Windows.Forms.TextBox(); 33 | this.label2 = new System.Windows.Forms.Label(); 34 | this.btn_graphColor = new System.Windows.Forms.Button(); 35 | this.label3 = new System.Windows.Forms.Label(); 36 | this.cmbo_dashStyle = new System.Windows.Forms.ComboBox(); 37 | this.cmbo_lineWidth = new System.Windows.Forms.ComboBox(); 38 | this.label4 = new System.Windows.Forms.Label(); 39 | this.cmbo_pointSize = new System.Windows.Forms.ComboBox(); 40 | this.label5 = new System.Windows.Forms.Label(); 41 | this.label6 = new System.Windows.Forms.Label(); 42 | this.btn_Ok = new System.Windows.Forms.Button(); 43 | this.btn_Cancel = new System.Windows.Forms.Button(); 44 | this.lst_plottingType = new System.Windows.Forms.CheckedListBox(); 45 | this.txt_resolution = new System.Windows.Forms.TextBox(); 46 | this.label7 = new System.Windows.Forms.Label(); 47 | this.SuspendLayout(); 48 | // 49 | // label1 50 | // 51 | this.label1.AutoSize = true; 52 | this.label1.Location = new System.Drawing.Point(27, 32); 53 | this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 54 | this.label1.Name = "label1"; 55 | this.label1.Size = new System.Drawing.Size(53, 20); 56 | this.label1.TabIndex = 0; 57 | this.label1.Text = "F(x) = "; 58 | // 59 | // txt_expression 60 | // 61 | this.txt_expression.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 62 | | System.Windows.Forms.AnchorStyles.Right))); 63 | this.txt_expression.Location = new System.Drawing.Point(137, 26); 64 | this.txt_expression.Name = "txt_expression"; 65 | this.txt_expression.Size = new System.Drawing.Size(260, 26); 66 | this.txt_expression.TabIndex = 1; 67 | this.txt_expression.Text = "x"; 68 | // 69 | // label2 70 | // 71 | this.label2.AutoSize = true; 72 | this.label2.Location = new System.Drawing.Point(27, 89); 73 | this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 74 | this.label2.Name = "label2"; 75 | this.label2.Size = new System.Drawing.Size(50, 20); 76 | this.label2.TabIndex = 2; 77 | this.label2.Text = "Color:"; 78 | // 79 | // btn_graphColor 80 | // 81 | this.btn_graphColor.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 82 | | System.Windows.Forms.AnchorStyles.Right))); 83 | this.btn_graphColor.BackColor = System.Drawing.Color.Black; 84 | this.btn_graphColor.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 85 | this.btn_graphColor.Location = new System.Drawing.Point(137, 81); 86 | this.btn_graphColor.Name = "btn_graphColor"; 87 | this.btn_graphColor.Size = new System.Drawing.Size(256, 28); 88 | this.btn_graphColor.TabIndex = 3; 89 | this.btn_graphColor.UseVisualStyleBackColor = false; 90 | this.btn_graphColor.Click += new System.EventHandler(this.btn_graphColor_Click); 91 | // 92 | // label3 93 | // 94 | this.label3.AutoSize = true; 95 | this.label3.Location = new System.Drawing.Point(27, 145); 96 | this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 97 | this.label3.Name = "label3"; 98 | this.label3.Size = new System.Drawing.Size(90, 20); 99 | this.label3.TabIndex = 4; 100 | this.label3.Text = "Dash Style:"; 101 | // 102 | // cmbo_dashStyle 103 | // 104 | this.cmbo_dashStyle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 105 | | System.Windows.Forms.AnchorStyles.Right))); 106 | this.cmbo_dashStyle.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; 107 | this.cmbo_dashStyle.FormattingEnabled = true; 108 | this.cmbo_dashStyle.Items.AddRange(new object[] { 109 | "0", 110 | "1", 111 | "2", 112 | "3", 113 | "4"}); 114 | this.cmbo_dashStyle.Location = new System.Drawing.Point(137, 137); 115 | this.cmbo_dashStyle.Name = "cmbo_dashStyle"; 116 | this.cmbo_dashStyle.Size = new System.Drawing.Size(260, 27); 117 | this.cmbo_dashStyle.TabIndex = 5; 118 | this.cmbo_dashStyle.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.cmbo_dashStyle_DrawItem); 119 | this.cmbo_dashStyle.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.cmbo_dashStyle_MeasureItem); 120 | // 121 | // cmbo_lineWidth 122 | // 123 | this.cmbo_lineWidth.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 124 | | System.Windows.Forms.AnchorStyles.Right))); 125 | this.cmbo_lineWidth.FormattingEnabled = true; 126 | this.cmbo_lineWidth.Items.AddRange(new object[] { 127 | "1", 128 | "2", 129 | "3", 130 | "4", 131 | "5", 132 | "6", 133 | "7", 134 | "8", 135 | "9", 136 | "10"}); 137 | this.cmbo_lineWidth.Location = new System.Drawing.Point(137, 188); 138 | this.cmbo_lineWidth.Name = "cmbo_lineWidth"; 139 | this.cmbo_lineWidth.Size = new System.Drawing.Size(260, 28); 140 | this.cmbo_lineWidth.TabIndex = 7; 141 | // 142 | // label4 143 | // 144 | this.label4.AutoSize = true; 145 | this.label4.Location = new System.Drawing.Point(27, 196); 146 | this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 147 | this.label4.Name = "label4"; 148 | this.label4.Size = new System.Drawing.Size(88, 20); 149 | this.label4.TabIndex = 6; 150 | this.label4.Text = "Line Width:"; 151 | // 152 | // cmbo_pointSize 153 | // 154 | this.cmbo_pointSize.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 155 | | System.Windows.Forms.AnchorStyles.Right))); 156 | this.cmbo_pointSize.FormattingEnabled = true; 157 | this.cmbo_pointSize.Items.AddRange(new object[] { 158 | "2", 159 | "3", 160 | "4", 161 | "5", 162 | "6", 163 | "7", 164 | "8", 165 | "9", 166 | "10", 167 | "12", 168 | "15", 169 | "20"}); 170 | this.cmbo_pointSize.Location = new System.Drawing.Point(137, 236); 171 | this.cmbo_pointSize.Name = "cmbo_pointSize"; 172 | this.cmbo_pointSize.Size = new System.Drawing.Size(260, 28); 173 | this.cmbo_pointSize.TabIndex = 9; 174 | // 175 | // label5 176 | // 177 | this.label5.AutoSize = true; 178 | this.label5.Location = new System.Drawing.Point(27, 244); 179 | this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 180 | this.label5.Name = "label5"; 181 | this.label5.Size = new System.Drawing.Size(84, 20); 182 | this.label5.TabIndex = 8; 183 | this.label5.Text = "Point Size:"; 184 | // 185 | // label6 186 | // 187 | this.label6.AutoSize = true; 188 | this.label6.Location = new System.Drawing.Point(27, 293); 189 | this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 190 | this.label6.Name = "label6"; 191 | this.label6.Size = new System.Drawing.Size(104, 20); 192 | this.label6.TabIndex = 10; 193 | this.label6.Text = "Plotting Type:"; 194 | // 195 | // btn_Ok 196 | // 197 | this.btn_Ok.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 198 | this.btn_Ok.DialogResult = System.Windows.Forms.DialogResult.OK; 199 | this.btn_Ok.Location = new System.Drawing.Point(309, 440); 200 | this.btn_Ok.Name = "btn_Ok"; 201 | this.btn_Ok.Size = new System.Drawing.Size(88, 31); 202 | this.btn_Ok.TabIndex = 12; 203 | this.btn_Ok.Text = "OK"; 204 | this.btn_Ok.UseVisualStyleBackColor = true; 205 | this.btn_Ok.Click += new System.EventHandler(this.btn_Ok_Click); 206 | // 207 | // btn_Cancel 208 | // 209 | this.btn_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 210 | this.btn_Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 211 | this.btn_Cancel.Location = new System.Drawing.Point(200, 440); 212 | this.btn_Cancel.Name = "btn_Cancel"; 213 | this.btn_Cancel.Size = new System.Drawing.Size(88, 31); 214 | this.btn_Cancel.TabIndex = 13; 215 | this.btn_Cancel.Text = "Cancel"; 216 | this.btn_Cancel.UseVisualStyleBackColor = true; 217 | // 218 | // lst_plottingType 219 | // 220 | this.lst_plottingType.CheckOnClick = true; 221 | this.lst_plottingType.FormattingEnabled = true; 222 | this.lst_plottingType.Items.AddRange(new object[] { 223 | "Continuous Graph", 224 | "Points", 225 | "Impulses"}); 226 | this.lst_plottingType.Location = new System.Drawing.Point(137, 283); 227 | this.lst_plottingType.Name = "lst_plottingType"; 228 | this.lst_plottingType.Size = new System.Drawing.Size(260, 67); 229 | this.lst_plottingType.TabIndex = 14; 230 | this.lst_plottingType.SelectedIndexChanged += new System.EventHandler(this.lst_plottingType_SelectedIndexChanged); 231 | // 232 | // txt_resolution 233 | // 234 | this.txt_resolution.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 235 | | System.Windows.Forms.AnchorStyles.Right))); 236 | this.txt_resolution.Location = new System.Drawing.Point(137, 370); 237 | this.txt_resolution.Name = "txt_resolution"; 238 | this.txt_resolution.Size = new System.Drawing.Size(260, 26); 239 | this.txt_resolution.TabIndex = 16; 240 | this.txt_resolution.Text = "0"; 241 | // 242 | // label7 243 | // 244 | this.label7.AutoSize = true; 245 | this.label7.Location = new System.Drawing.Point(27, 376); 246 | this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 247 | this.label7.Name = "label7"; 248 | this.label7.Size = new System.Drawing.Size(85, 20); 249 | this.label7.TabIndex = 15; 250 | this.label7.Text = "Resolution"; 251 | // 252 | // frm_AddFunction 253 | // 254 | this.AcceptButton = this.btn_Ok; 255 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); 256 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 257 | this.CancelButton = this.btn_Cancel; 258 | this.ClientSize = new System.Drawing.Size(409, 483); 259 | this.Controls.Add(this.txt_resolution); 260 | this.Controls.Add(this.label7); 261 | this.Controls.Add(this.lst_plottingType); 262 | this.Controls.Add(this.btn_Cancel); 263 | this.Controls.Add(this.btn_Ok); 264 | this.Controls.Add(this.label6); 265 | this.Controls.Add(this.cmbo_pointSize); 266 | this.Controls.Add(this.label5); 267 | this.Controls.Add(this.cmbo_lineWidth); 268 | this.Controls.Add(this.label4); 269 | this.Controls.Add(this.cmbo_dashStyle); 270 | this.Controls.Add(this.label3); 271 | this.Controls.Add(this.btn_graphColor); 272 | this.Controls.Add(this.label2); 273 | this.Controls.Add(this.txt_expression); 274 | this.Controls.Add(this.label1); 275 | this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 276 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 277 | this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 278 | this.MaximizeBox = false; 279 | this.MinimizeBox = false; 280 | this.Name = "frm_AddFunction"; 281 | this.Text = "Add Function"; 282 | this.ResumeLayout(false); 283 | this.PerformLayout(); 284 | 285 | } 286 | 287 | #endregion 288 | 289 | private System.Windows.Forms.Label label1; 290 | private System.Windows.Forms.TextBox txt_expression; 291 | private System.Windows.Forms.Label label2; 292 | private System.Windows.Forms.Button btn_graphColor; 293 | private System.Windows.Forms.Label label3; 294 | private System.Windows.Forms.ComboBox cmbo_dashStyle; 295 | private System.Windows.Forms.ComboBox cmbo_lineWidth; 296 | private System.Windows.Forms.Label label4; 297 | private System.Windows.Forms.ComboBox cmbo_pointSize; 298 | private System.Windows.Forms.Label label5; 299 | private System.Windows.Forms.Label label6; 300 | private System.Windows.Forms.Button btn_Ok; 301 | private System.Windows.Forms.Button btn_Cancel; 302 | private System.Windows.Forms.CheckedListBox lst_plottingType; 303 | private System.Windows.Forms.TextBox txt_resolution; 304 | private System.Windows.Forms.Label label7; 305 | } 306 | } -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/frm_AddFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using FunctionParser; 4 | using System.Drawing.Drawing2D; 5 | using System.Drawing; 6 | 7 | namespace FunctionParserAndPlotterTester 8 | { 9 | public partial class frm_AddFunction : Form 10 | { 11 | public ExpressionGraphData ExpressionGraph { get; set; } 12 | public frm_AddFunction() 13 | { 14 | InitializeComponent(); 15 | SetInitialValues(); 16 | } 17 | 18 | private void SetInitialValues() 19 | { 20 | cmbo_lineWidth.SelectedIndex = 0; 21 | cmbo_pointSize.SelectedIndex = 0; 22 | cmbo_dashStyle.SelectedIndex = 0; 23 | lst_plottingType.SetItemChecked(0, true); 24 | ExpressionGraph = new ExpressionGraphData(); 25 | ExpressionGraph.Curve = new FunctionPlotter.Curve(System.Drawing.Color.Black, FunctionPlotter.PlotType.ContineuosCurve); 26 | 27 | } 28 | 29 | private void btn_graphColor_Click(object sender, EventArgs e) 30 | { 31 | ColorDialog colorDialog = new ColorDialog(); 32 | if(colorDialog.ShowDialog()== DialogResult.OK) 33 | { 34 | btn_graphColor.BackColor = colorDialog.Color; 35 | ExpressionGraph.Curve.CurveColor= colorDialog.Color; 36 | } 37 | } 38 | 39 | private void btn_Ok_Click(object sender, EventArgs e) 40 | { 41 | ExpressionGraph.Expression =new Expression( txt_expression.Text,new string[] { "x" },null); 42 | ExpressionGraph.Curve.CurveColor = btn_graphColor.BackColor; 43 | ExpressionGraph.Curve.LineWidth = int.Parse(cmbo_lineWidth.SelectedItem.ToString()); 44 | ExpressionGraph.Curve.PointSize = int.Parse(cmbo_pointSize.SelectedItem.ToString()); 45 | ExpressionGraph.Curve.DashStyle = (DashStyle)cmbo_dashStyle.SelectedIndex ; 46 | ExpressionGraph.Resolution = float.Parse(txt_resolution.Text); 47 | for(int i=0;i< lst_plottingType.CheckedIndices.Count;i++) 48 | { 49 | int checkedIndex = lst_plottingType.CheckedIndices[i]; 50 | ExpressionGraph.Curve.PlottingType |= (FunctionPlotter.PlotType)(1 << checkedIndex); 51 | } 52 | 53 | } 54 | 55 | private void lst_plottingType_SelectedIndexChanged(object sender, EventArgs e) 56 | { 57 | 58 | } 59 | 60 | private void cmbo_dashStyle_DrawItem(object sender, DrawItemEventArgs e) 61 | { 62 | DashStyle style = (DashStyle)e.Index; 63 | using (Pen p = new Pen(Color.Black, 2)) 64 | { 65 | e.DrawBackground(); 66 | p.DashStyle = style; 67 | Point start = new Point(e.Bounds.X,e.Bounds.Top+e.Bounds.Height / 2); 68 | Point end = new Point(e.Bounds.X + e.Bounds.Width, e.Bounds.Top + e.Bounds.Height / 2); 69 | e.Graphics.DrawLine(p, start,end); 70 | e.DrawFocusRectangle(); 71 | } 72 | } 73 | 74 | private void cmbo_dashStyle_MeasureItem(object sender, MeasureItemEventArgs e) 75 | { 76 | e.ItemWidth = 350; 77 | e.ItemHeight = 25; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /FunctionParserAndPlotterTester/frm_AddFunction.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/AddIDForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FunctionParserWindowsFormTester 2 | { 3 | partial class AddIDForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // AddIDForm 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.ClientSize = new System.Drawing.Size(284, 261); 38 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 39 | this.Name = "AddIDForm"; 40 | this.Text = "Add ID"; 41 | this.ResumeLayout(false); 42 | 43 | } 44 | 45 | #endregion 46 | } 47 | } -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/AddIDForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace FunctionParserWindowsFormTester 12 | { 13 | public partial class AddIDForm : Form 14 | { 15 | public AddIDForm() 16 | { 17 | InitializeComponent(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/AddIDForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Form1.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FunctionParserWindowsFormTester 2 | { 3 | partial class Form1 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.txt_expr = new System.Windows.Forms.TextBox(); 32 | this.trvw_ParseTree = new System.Windows.Forms.TreeView(); 33 | this.lst_ids = new System.Windows.Forms.ListView(); 34 | this.id_name = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 35 | this.id_value = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); 36 | this.btn_addID = new System.Windows.Forms.Button(); 37 | this.lbl_result = new System.Windows.Forms.Label(); 38 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 39 | this.groupBox2 = new System.Windows.Forms.GroupBox(); 40 | this.groupBox1.SuspendLayout(); 41 | this.groupBox2.SuspendLayout(); 42 | this.SuspendLayout(); 43 | // 44 | // txt_expr 45 | // 46 | this.txt_expr.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 47 | this.txt_expr.Location = new System.Drawing.Point(6, 27); 48 | this.txt_expr.Name = "txt_expr"; 49 | this.txt_expr.Size = new System.Drawing.Size(465, 26); 50 | this.txt_expr.TabIndex = 0; 51 | this.txt_expr.TextChanged += new System.EventHandler(this.txt_expr_TextChanged); 52 | // 53 | // trvw_ParseTree 54 | // 55 | this.trvw_ParseTree.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 56 | | System.Windows.Forms.AnchorStyles.Left) 57 | | System.Windows.Forms.AnchorStyles.Right))); 58 | this.trvw_ParseTree.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 59 | this.trvw_ParseTree.FullRowSelect = true; 60 | this.trvw_ParseTree.Location = new System.Drawing.Point(12, 249); 61 | this.trvw_ParseTree.Name = "trvw_ParseTree"; 62 | this.trvw_ParseTree.Size = new System.Drawing.Size(614, 433); 63 | this.trvw_ParseTree.TabIndex = 1; 64 | // 65 | // lst_ids 66 | // 67 | this.lst_ids.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { 68 | this.id_name, 69 | this.id_value}); 70 | this.lst_ids.FullRowSelect = true; 71 | this.lst_ids.GridLines = true; 72 | this.lst_ids.Location = new System.Drawing.Point(6, 19); 73 | this.lst_ids.Name = "lst_ids"; 74 | this.lst_ids.Size = new System.Drawing.Size(598, 85); 75 | this.lst_ids.TabIndex = 3; 76 | this.lst_ids.UseCompatibleStateImageBehavior = false; 77 | this.lst_ids.View = System.Windows.Forms.View.Details; 78 | this.lst_ids.KeyDown += new System.Windows.Forms.KeyEventHandler(this.lst_ids_KeyDown); 79 | // 80 | // id_name 81 | // 82 | this.id_name.Text = "Name"; 83 | this.id_name.Width = 266; 84 | // 85 | // id_value 86 | // 87 | this.id_value.Text = "Value"; 88 | this.id_value.Width = 325; 89 | // 90 | // btn_addID 91 | // 92 | this.btn_addID.Location = new System.Drawing.Point(6, 110); 93 | this.btn_addID.Name = "btn_addID"; 94 | this.btn_addID.Size = new System.Drawing.Size(75, 23); 95 | this.btn_addID.TabIndex = 4; 96 | this.btn_addID.Text = "Add ID"; 97 | this.btn_addID.UseVisualStyleBackColor = true; 98 | this.btn_addID.Click += new System.EventHandler(this.btn_addID_Click); 99 | // 100 | // lbl_result 101 | // 102 | this.lbl_result.AutoSize = true; 103 | this.lbl_result.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 104 | this.lbl_result.Location = new System.Drawing.Point(488, 30); 105 | this.lbl_result.Name = "lbl_result"; 106 | this.lbl_result.Size = new System.Drawing.Size(31, 20); 107 | this.lbl_result.TabIndex = 5; 108 | this.lbl_result.Text = "= 0"; 109 | // 110 | // groupBox1 111 | // 112 | this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 113 | | System.Windows.Forms.AnchorStyles.Right))); 114 | this.groupBox1.Controls.Add(this.lst_ids); 115 | this.groupBox1.Controls.Add(this.btn_addID); 116 | this.groupBox1.Location = new System.Drawing.Point(12, 12); 117 | this.groupBox1.Name = "groupBox1"; 118 | this.groupBox1.Size = new System.Drawing.Size(614, 142); 119 | this.groupBox1.TabIndex = 6; 120 | this.groupBox1.TabStop = false; 121 | this.groupBox1.Text = "Function IDs (Variables)"; 122 | // 123 | // groupBox2 124 | // 125 | this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 126 | | System.Windows.Forms.AnchorStyles.Right))); 127 | this.groupBox2.Controls.Add(this.txt_expr); 128 | this.groupBox2.Controls.Add(this.lbl_result); 129 | this.groupBox2.Location = new System.Drawing.Point(12, 165); 130 | this.groupBox2.Name = "groupBox2"; 131 | this.groupBox2.Size = new System.Drawing.Size(614, 78); 132 | this.groupBox2.TabIndex = 7; 133 | this.groupBox2.TabStop = false; 134 | this.groupBox2.Text = "Function"; 135 | // 136 | // Form1 137 | // 138 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 139 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 140 | this.ClientSize = new System.Drawing.Size(638, 694); 141 | this.Controls.Add(this.groupBox2); 142 | this.Controls.Add(this.groupBox1); 143 | this.Controls.Add(this.trvw_ParseTree); 144 | this.Name = "Form1"; 145 | this.Text = "Function Evaluator"; 146 | this.Load += new System.EventHandler(this.Form1_Load); 147 | this.groupBox1.ResumeLayout(false); 148 | this.groupBox2.ResumeLayout(false); 149 | this.groupBox2.PerformLayout(); 150 | this.ResumeLayout(false); 151 | 152 | } 153 | 154 | #endregion 155 | 156 | private System.Windows.Forms.TextBox txt_expr; 157 | private System.Windows.Forms.TreeView trvw_ParseTree; 158 | private System.Windows.Forms.ListView lst_ids; 159 | private System.Windows.Forms.ColumnHeader id_name; 160 | private System.Windows.Forms.ColumnHeader id_value; 161 | private System.Windows.Forms.Button btn_addID; 162 | private System.Windows.Forms.Label lbl_result; 163 | private System.Windows.Forms.GroupBox groupBox1; 164 | private System.Windows.Forms.GroupBox groupBox2; 165 | } 166 | } 167 | 168 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Form1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | using FunctionParser; 5 | namespace FunctionParserWindowsFormTester 6 | { 7 | public partial class Form1 : Form 8 | { 9 | string[] idsNames=new string[] { }; 10 | double[] idsValues = new double[] { }; 11 | public Form1() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | private void Form1_Load(object sender, EventArgs e) 17 | { 18 | 19 | } 20 | private void CreateTreeNodes(ParsTreeNode parseNode, TreeNode treeViewNode) 21 | { 22 | if (parseNode is Expression) 23 | { 24 | Expression expr = parseNode as Expression; 25 | switch (expr.Expansion) 26 | { 27 | case Expression.ExpressionExpansion.ExpressionMinusTerm: 28 | TreeNode subExpr = new TreeNode("Expression: " + expr.SubExpression.Value); 29 | subExpr.Tag = expr.SubExpression; 30 | CreateTreeNodes(expr.SubExpression, subExpr); 31 | treeViewNode.Nodes.Add(subExpr); 32 | treeViewNode.Nodes.Add("-"); 33 | TreeNode termNode = new TreeNode("Term: " + expr.Term.Value); 34 | termNode.Tag = expr.Term; 35 | CreateTreeNodes(expr.Term, termNode); 36 | treeViewNode.Nodes.Add(termNode); 37 | break; 38 | case Expression.ExpressionExpansion.ExpressionPlusTerm: 39 | TreeNode subExpr2 = new TreeNode("Expression: " + expr.SubExpression.Value); 40 | subExpr2.Tag = expr.SubExpression; 41 | CreateTreeNodes(expr.SubExpression, subExpr2); 42 | TreeNode termNode2 = new TreeNode("Term: " + expr.Term.Value); 43 | termNode2.Tag = expr.Term; 44 | CreateTreeNodes(expr.Term, termNode2); 45 | 46 | treeViewNode.Nodes.Add(subExpr2); 47 | treeViewNode.Nodes.Add("+"); 48 | treeViewNode.Nodes.Add(termNode2); 49 | 50 | break; 51 | case Expression.ExpressionExpansion.Term: 52 | TreeNode termNode3 = new TreeNode("Term: " + expr.Value); 53 | termNode3.Tag = expr; 54 | CreateTreeNodes(expr.Term, termNode3); 55 | treeViewNode.Nodes.Add(termNode3); 56 | break; 57 | } 58 | } 59 | else if (parseNode is Term) 60 | { 61 | Term term = parseNode as Term; 62 | switch (term.Expansion) 63 | { 64 | case Term.TermExpansion.TermMulFactor: 65 | TreeNode subTerm = new TreeNode("Term: " + term.SubTerm.Value); 66 | subTerm.Tag = term.SubTerm; 67 | CreateTreeNodes(term.SubTerm, subTerm); 68 | TreeNode factor = new TreeNode("Factor: " + term.Factor.Value); 69 | factor.Tag = term.Factor; 70 | CreateTreeNodes(term.Factor, factor); 71 | 72 | treeViewNode.Nodes.Add(subTerm); 73 | treeViewNode.Nodes.Add("*"); 74 | treeViewNode.Nodes.Add(factor); 75 | 76 | break; 77 | 78 | case Term.TermExpansion.TermDivFactor: 79 | TreeNode subTerm2 = new TreeNode("Term: " + term.SubTerm.Value); 80 | subTerm2.Tag = term.SubTerm; 81 | CreateTreeNodes(term.SubTerm, subTerm2); 82 | TreeNode factor2 = new TreeNode("Factor: " + term.Factor.Value); 83 | factor2.Tag = term.Factor; 84 | CreateTreeNodes(term.Factor, factor2); 85 | 86 | treeViewNode.Nodes.Add(subTerm2); 87 | treeViewNode.Nodes.Add("/"); 88 | treeViewNode.Nodes.Add(factor2); 89 | break; 90 | 91 | case Term.TermExpansion.TermPowFactor: 92 | TreeNode subTerm3 = new TreeNode("Term: " + term.SubTerm.Value); 93 | subTerm3.Tag = term.SubTerm; 94 | CreateTreeNodes(term.SubTerm, subTerm3); 95 | TreeNode factor3 = new TreeNode("Factor: " + term.Factor.Value); 96 | factor3.Tag = term.Factor; 97 | CreateTreeNodes(term.Factor, factor3); 98 | 99 | treeViewNode.Nodes.Add(subTerm3); 100 | treeViewNode.Nodes.Add("^"); 101 | treeViewNode.Nodes.Add(factor3); 102 | break; 103 | case Term.TermExpansion.Factor: 104 | TreeNode factor4 = new TreeNode("Factor: " + term.Factor.Value); 105 | factor4.Tag = term.Factor; 106 | CreateTreeNodes(term.Factor, factor4); 107 | treeViewNode.Nodes.Add(factor4); 108 | break; 109 | } 110 | } 111 | else if (parseNode is Factor) 112 | { 113 | Factor factor = parseNode as Factor; 114 | switch (factor.Expansion) 115 | { 116 | case Factor.FactorExpansion.Number: 117 | TreeNode number = new TreeNode("Number: " + factor.Value); 118 | treeViewNode.Nodes.Add(number); 119 | break; 120 | case Factor.FactorExpansion.ID: 121 | TreeNode id = new TreeNode("ID: " + factor.Value); 122 | treeViewNode.Nodes.Add(id); 123 | break; 124 | case Factor.FactorExpansion.WrappedExpression: 125 | treeViewNode.Nodes.Add("("); 126 | TreeNode expr = new TreeNode("Expression:" + factor.WrappedExpression.Value); 127 | expr.Tag = factor.WrappedExpression; 128 | CreateTreeNodes(factor.WrappedExpression, expr); 129 | treeViewNode.Nodes.Add(expr); 130 | treeViewNode.Nodes.Add(")"); 131 | break; 132 | case Factor.FactorExpansion.Function: 133 | treeViewNode.Nodes.Add("Function: " + factor.Function.Func.ToString()); 134 | TreeNode term = new TreeNode("Term: " + factor.Function.Term.Value); 135 | term.Tag = factor.Function.Term; 136 | CreateTreeNodes(factor.Function.Term, term); 137 | treeViewNode.Nodes.Add(term); 138 | break; 139 | } 140 | } 141 | } 142 | 143 | private void txt_expr_TextChanged(object sender, EventArgs e) 144 | { 145 | if (Expression.IsExpression(txt_expr.Text, idsNames)) 146 | { 147 | txt_expr.ForeColor = Color.Black; 148 | Expression expression = new Expression(txt_expr.Text, idsNames, null); 149 | TreeNode expr = new TreeNode(txt_expr.Text); 150 | CreateTreeNodes(expression, expr); 151 | trvw_ParseTree.Nodes.Clear(); 152 | trvw_ParseTree.Nodes.Add(expr); 153 | trvw_ParseTree.ExpandAll(); 154 | double result = expression.CalculateValue(idsValues); 155 | lbl_result.Text = string.Format("= {0:f3}", result); 156 | } 157 | else 158 | { 159 | txt_expr.ForeColor = Color.Red; 160 | } 161 | } 162 | 163 | private void lst_ids_KeyDown(object sender, KeyEventArgs e) 164 | { 165 | //delete character 166 | if (e.KeyCode== Keys.Delete) 167 | { 168 | if (lst_ids.SelectedItems.Count > 0) 169 | { 170 | for (int i = 0; i < lst_ids.SelectedItems.Count; i++) 171 | lst_ids.Items.Remove(lst_ids.SelectedItems[i]); 172 | } 173 | } 174 | UpdateIDs(); 175 | 176 | } 177 | 178 | private void btn_addID_Click(object sender, EventArgs e) 179 | { 180 | Form_ID frmID = new Form_ID(); 181 | if( frmID.ShowDialog()== DialogResult.OK) 182 | { 183 | lst_ids.Items.Add(frmID.ID_Name).SubItems.Add(frmID.ID_Value); 184 | } 185 | UpdateIDs(); 186 | } 187 | 188 | public void UpdateIDs() 189 | { 190 | idsNames = new string[lst_ids.Items.Count]; 191 | idsValues = new double[lst_ids.Items.Count]; 192 | for(int i=0;i 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Form_ID.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FunctionParserWindowsFormTester 2 | { 3 | partial class Form_ID 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.btn_cancel = new System.Windows.Forms.Button(); 32 | this.btn_OK = new System.Windows.Forms.Button(); 33 | this.label1 = new System.Windows.Forms.Label(); 34 | this.txt_idName = new System.Windows.Forms.TextBox(); 35 | this.txt_idValue = new System.Windows.Forms.TextBox(); 36 | this.label2 = new System.Windows.Forms.Label(); 37 | this.SuspendLayout(); 38 | // 39 | // btn_cancel 40 | // 41 | this.btn_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 42 | this.btn_cancel.Location = new System.Drawing.Point(104, 136); 43 | this.btn_cancel.Name = "btn_cancel"; 44 | this.btn_cancel.Size = new System.Drawing.Size(75, 23); 45 | this.btn_cancel.TabIndex = 0; 46 | this.btn_cancel.Text = "Cancel"; 47 | this.btn_cancel.UseVisualStyleBackColor = true; 48 | // 49 | // btn_OK 50 | // 51 | this.btn_OK.DialogResult = System.Windows.Forms.DialogResult.OK; 52 | this.btn_OK.Location = new System.Drawing.Point(197, 136); 53 | this.btn_OK.Name = "btn_OK"; 54 | this.btn_OK.Size = new System.Drawing.Size(75, 23); 55 | this.btn_OK.TabIndex = 1; 56 | this.btn_OK.Text = "OK"; 57 | this.btn_OK.UseVisualStyleBackColor = true; 58 | // 59 | // label1 60 | // 61 | this.label1.AutoSize = true; 62 | this.label1.Location = new System.Drawing.Point(26, 46); 63 | this.label1.Name = "label1"; 64 | this.label1.Size = new System.Drawing.Size(50, 13); 65 | this.label1.TabIndex = 2; 66 | this.label1.Text = "ID name:"; 67 | // 68 | // txt_idName 69 | // 70 | this.txt_idName.Location = new System.Drawing.Point(104, 39); 71 | this.txt_idName.Name = "txt_idName"; 72 | this.txt_idName.Size = new System.Drawing.Size(100, 20); 73 | this.txt_idName.TabIndex = 3; 74 | // 75 | // txt_idValue 76 | // 77 | this.txt_idValue.Location = new System.Drawing.Point(104, 80); 78 | this.txt_idValue.Name = "txt_idValue"; 79 | this.txt_idValue.Size = new System.Drawing.Size(100, 20); 80 | this.txt_idValue.TabIndex = 5; 81 | // 82 | // label2 83 | // 84 | this.label2.AutoSize = true; 85 | this.label2.Location = new System.Drawing.Point(26, 87); 86 | this.label2.Name = "label2"; 87 | this.label2.Size = new System.Drawing.Size(37, 13); 88 | this.label2.TabIndex = 4; 89 | this.label2.Text = "Value:"; 90 | // 91 | // Form_ID 92 | // 93 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 94 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 95 | this.ClientSize = new System.Drawing.Size(284, 174); 96 | this.Controls.Add(this.txt_idValue); 97 | this.Controls.Add(this.label2); 98 | this.Controls.Add(this.txt_idName); 99 | this.Controls.Add(this.label1); 100 | this.Controls.Add(this.btn_OK); 101 | this.Controls.Add(this.btn_cancel); 102 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 103 | this.MaximizeBox = false; 104 | this.MinimizeBox = false; 105 | this.Name = "Form_ID"; 106 | this.Text = "Add ID"; 107 | this.ResumeLayout(false); 108 | this.PerformLayout(); 109 | 110 | } 111 | 112 | #endregion 113 | 114 | private System.Windows.Forms.Button btn_cancel; 115 | private System.Windows.Forms.Button btn_OK; 116 | private System.Windows.Forms.Label label1; 117 | private System.Windows.Forms.TextBox txt_idName; 118 | private System.Windows.Forms.TextBox txt_idValue; 119 | private System.Windows.Forms.Label label2; 120 | } 121 | } -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Form_ID.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace FunctionParserWindowsFormTester 12 | { 13 | public partial class Form_ID : Form 14 | { 15 | public string ID_Name { get { return txt_idName.Text; } } 16 | public string ID_Value { get { return txt_idValue.Text; } } 17 | public Form_ID() 18 | { 19 | InitializeComponent(); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Form_ID.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/FunctionParserWindowsFormTester.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3F4D032D-2548-4E36-AD17-0BA72215A9AD} 8 | WinExe 9 | Properties 10 | FunctionParserWindowsFormTester 11 | FunctionParserWindowsFormTester 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Form 51 | 52 | 53 | Form1.cs 54 | 55 | 56 | Form 57 | 58 | 59 | Form_ID.cs 60 | 61 | 62 | 63 | 64 | Form1.cs 65 | 66 | 67 | Form_ID.cs 68 | 69 | 70 | ResXFileCodeGenerator 71 | Resources.Designer.cs 72 | Designer 73 | 74 | 75 | True 76 | Resources.resx 77 | 78 | 79 | SettingsSingleFileGenerator 80 | Settings.Designer.cs 81 | 82 | 83 | True 84 | Settings.settings 85 | True 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | {4bec9a15-40fe-44de-bc77-2f243d180772} 94 | FunctionParser 95 | 96 | 97 | 98 | 105 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace FunctionParserWindowsFormTester 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new Form1()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FunctionParserWindowsFormTester")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FunctionParserWindowsFormTester")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3f4d032d-2548-4e36-ad17-0ba72215a9ad")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FunctionParserWindowsFormTester.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FunctionParserWindowsFormTester.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FunctionParserWindowsFormTester.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /FunctionParserWindowsFormTester/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FunctionPlotter/FunctionPlotter.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2D5FA28F-AFFB-4A6E-9CE2-A61DBC6BB245} 8 | Library 9 | Properties 10 | FunctionPlotter 11 | FunctionPlotter 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 55 | -------------------------------------------------------------------------------- /FunctionPlotter/Plotter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Drawing.Drawing2D; 5 | 6 | namespace FunctionPlotter 7 | { 8 | public class Plotter 9 | { 10 | 11 | List curves = new List(); 12 | /// 13 | /// List of curves that will be plotted by this plotter 14 | /// 15 | public List Curves { get { return curves; } } 16 | 17 | /// 18 | /// The size of x unit in pixels 19 | /// 20 | public float XPixelsPerUnit { get; set; } 21 | /// 22 | /// The size of y unit in pixels 23 | /// 24 | public float YPixelsPerUnit { get; set; } 25 | 26 | /// 27 | /// Axes center position in drawing canvas 28 | /// 29 | public Point Center { get; set; } 30 | 31 | /// 32 | /// The dash style of the x and y axes 33 | /// 34 | public DashStyle AxesStyle { get; set; } 35 | /// 36 | /// The line width of the Axes 37 | /// 38 | public float AxesWidth { get; set; } 39 | 40 | /// 41 | /// Number of units per grid square in x axes 42 | /// 43 | public int XGridUnitsPerSquare { get; set; } 44 | /// 45 | /// Number of units per grid square in y axis 46 | /// 47 | public int YGridUnitsPerSquare { get; set; } 48 | 49 | /// 50 | /// The dash style of grid lines 51 | /// 52 | public DashStyle GridStyle { get; set; } 53 | /// 54 | /// Line width of the grid 55 | /// 56 | public float GridWidth { get; set; } 57 | /// 58 | /// Color of grid lines 59 | /// 60 | public Color GridColor { get; set; } 61 | /// 62 | /// Enable grid drawing 63 | /// 64 | public bool GridEnabled { get; set; } 65 | 66 | // X-Axis properties 67 | /// 68 | /// The color of x axis 69 | /// 70 | public Color XAxisColor { get; set; } 71 | 72 | /// 73 | /// Enable dashes that represent the unit location on x axis 74 | /// 75 | public bool XAxisDashEnable { get; set; } 76 | /// 77 | /// Color of the x axis dashes 78 | /// 79 | public Color XAxisDashColor { get; set; } 80 | /// 81 | /// Width of x axis dashes 82 | /// 83 | public float XAxisDashWidth { get; set; } 84 | /// 85 | /// Height of x axis dashes 86 | /// 87 | public float XAxisDashHeight { get; set; } 88 | 89 | /// 90 | /// Enable small dashes on x axis 91 | /// 92 | public bool XAxisSubDashEnable { get; set; } 93 | /// 94 | /// Number of small dashes per unit on x axis 95 | /// 96 | public int XAxisSubDashesPerUnit { get; set; } 97 | /// 98 | /// The color of x axis unit dashes 99 | /// 100 | public Color XAxisSubDashColor { get; set; } 101 | /// 102 | /// Width of x axis unit dashes 103 | /// 104 | public float XAxisSubDashWidth { get; set; } 105 | /// 106 | /// Height of x axis unit dashes 107 | /// 108 | public float XAxisSubDashHeight { get; set; } 109 | 110 | 111 | // Y-Axis properties 112 | public Color YAxisColor { get; set; } 113 | 114 | public bool YAxisDashEnable { get; set; } 115 | public Color YAxisDashColor { get; set; } 116 | public float YAxisDashWidth { get; set; } 117 | public float YAxisDashHeight { get; set; } 118 | 119 | public bool YAxisSubDashEnable { get; set; } 120 | public int YAxisSubDashesPerUnit { get; set; } 121 | public Color YAxisSubDashColor { get; set; } 122 | public float YAxisSubDashWidth { get; set; } 123 | public float YAxisSubDashHeight { get; set; } 124 | 125 | public float XResolution 126 | { 127 | get { return 1 / XPixelsPerUnit; } 128 | } 129 | 130 | public Plotter(float xPixelsPerUnit, float yPixelsPerUnit, Point center, Color axesColor) 131 | { 132 | this.XPixelsPerUnit = xPixelsPerUnit; 133 | this.YPixelsPerUnit = yPixelsPerUnit; 134 | this.Center = center; 135 | 136 | this.XAxisSubDashesPerUnit = 0; 137 | this.YAxisSubDashesPerUnit = 0; 138 | 139 | AxesWidth = 1; 140 | XAxisColor = YAxisColor = XAxisDashColor = YAxisDashColor = XAxisSubDashColor = YAxisSubDashColor = axesColor; 141 | 142 | XGridUnitsPerSquare = YGridUnitsPerSquare = 1; 143 | 144 | GridWidth = 1; 145 | GridColor = Color.Black; 146 | GridEnabled = true; 147 | 148 | XAxisDashWidth = 1; 149 | XAxisDashHeight = 5; 150 | XAxisDashEnable = true; 151 | 152 | YAxisDashWidth = 1; 153 | YAxisDashHeight = 5; 154 | YAxisDashEnable = true; 155 | 156 | 157 | XAxisSubDashWidth = 1; 158 | XAxisSubDashHeight = 3; 159 | XAxisSubDashEnable = true; 160 | 161 | YAxisSubDashWidth = 1; 162 | YAxisSubDashHeight = 3; 163 | YAxisSubDashEnable = true; 164 | 165 | 166 | } 167 | public Plotter(float xPixelsPerUnit, float yPixelsPerUnit, Point center) : this(xPixelsPerUnit, yPixelsPerUnit, center, Color.Black) 168 | { 169 | 170 | } 171 | public void DrawGridandAxes(Graphics g, int width, int height) 172 | { 173 | //Draw Grid 174 | #region Draw Grid 175 | if (GridEnabled) 176 | { 177 | using (Pen gridPen = new Pen(GridColor)) 178 | { 179 | gridPen.Width = GridWidth; 180 | gridPen.DashStyle = GridStyle; 181 | int seed = (int)Math.Round(YGridUnitsPerSquare * YPixelsPerUnit); 182 | int i = Center.Y - seed; 183 | for (; i > 0; i -= seed) 184 | { 185 | 186 | g.DrawLine(gridPen, 0, i, width, i);//draw the upper horizontal half 187 | } 188 | for (i = Center.Y + seed; i < height; i += seed) 189 | { 190 | g.DrawLine(gridPen, 0, i, width, i);//draw the lower half 191 | } 192 | seed = (int)Math.Round(XGridUnitsPerSquare * XPixelsPerUnit); 193 | i = Center.X - seed; 194 | for (; i > 0; i -= seed) 195 | { 196 | 197 | g.DrawLine(gridPen, i, 0, i, height);//draw the left vertical half 198 | } 199 | for (i = Center.X + seed; i < width; i += seed) 200 | { 201 | g.DrawLine(gridPen, i, 0, i, height);//draw the right half 202 | } 203 | } 204 | 205 | } 206 | #endregion 207 | //Draw Axes 208 | #region Draw Axes 209 | using (Pen p = new Pen(XAxisColor)) 210 | { 211 | p.Width = AxesWidth; 212 | p.DashStyle = AxesStyle; 213 | g.DrawLine(p, Center.X, Center.Y, width, Center.Y); 214 | g.DrawLine(p, Center.X, Center.Y, 0, Center.Y); 215 | } 216 | using (Pen p = new Pen(YAxisColor)) 217 | { 218 | p.Width = AxesWidth; 219 | p.DashStyle = AxesStyle; 220 | g.DrawLine(p, Center.X, Center.Y, Center.X, 0); 221 | g.DrawLine(p, Center.X, Center.Y, Center.X, height ); 222 | } 223 | #endregion 224 | //Draw Axes Dashes 225 | #region Draw Axes dashes 226 | 227 | //draw subDashes X-axis 228 | if (XAxisSubDashEnable & (XAxisSubDashesPerUnit > 0)) 229 | { 230 | using (Pen xDashPen = new Pen(XAxisSubDashColor)) 231 | { 232 | xDashPen.Width = XAxisSubDashWidth; 233 | int xSegment = (int)Math.Round((XPixelsPerUnit)); 234 | 235 | int subDashStart = (Center.Y - (int)(AxesWidth / 2) - (int)((XAxisSubDashHeight - AxesWidth) / 2));//the segment of the dash right and lift the axis 236 | int subDashEnd = subDashStart + (int)XAxisSubDashHeight - 1; 237 | int subDashSeed = xSegment / (XAxisSubDashesPerUnit+1); 238 | int i = Center.X - subDashSeed; 239 | for (; i > 0; i -= subDashSeed) 240 | { 241 | if ((i - Center.X) % xSegment == 0) continue; 242 | g.DrawLine(xDashPen, i, subDashStart, i, subDashEnd);//draw the upper y-axis half 243 | } 244 | for (i = Center.X + subDashSeed; i < width; i += subDashSeed) 245 | { 246 | if ((i - Center.X) % xSegment == 0) continue; 247 | g.DrawLine(xDashPen, i, subDashStart, i, subDashEnd);//draw the lower y-axis half 248 | } 249 | } 250 | } 251 | if (YAxisSubDashEnable & (YAxisSubDashesPerUnit > 0)) 252 | { 253 | using (Pen yDashPen = new Pen(YAxisSubDashColor)) 254 | { 255 | yDashPen.Width = YAxisSubDashWidth; 256 | 257 | int ySegment = (int)Math.Round(YPixelsPerUnit); 258 | 259 | int subDashStart = (Center.X - (int)(AxesWidth / 2) - (int)((YAxisSubDashHeight - AxesWidth) / 2));//the segment of the dash right and lift the axis 260 | int subDashEnd = subDashStart + (int)YAxisSubDashHeight - 1; 261 | int subDashSeed = ySegment / (YAxisSubDashesPerUnit+1); 262 | 263 | int i = Center.Y - subDashSeed; 264 | 265 | for (; i > 0; i -= subDashSeed) 266 | { 267 | if ((i - Center.Y) % ySegment == 0) continue; 268 | g.DrawLine(yDashPen, subDashEnd, i, subDashStart, i);//draw the upper y-axis half 269 | } 270 | for (i = Center.Y + subDashSeed; i < height; i += subDashSeed) 271 | { 272 | if ((i - Center.Y) % ySegment == 0) continue; 273 | g.DrawLine(yDashPen, subDashStart, i, subDashEnd, i);//draw the lower y-axis half 274 | } 275 | } 276 | } 277 | if (XAxisDashEnable) 278 | { 279 | using (Pen xDashPen = new Pen(XAxisDashColor)) 280 | { 281 | xDashPen.Width = XAxisDashWidth; 282 | 283 | int seed = (int)Math.Round((XPixelsPerUnit)); 284 | int i = Center.X - seed; 285 | int dashStart = (Center.Y - (int)(AxesWidth / 2) - (int)((XAxisDashHeight - AxesWidth) / 2));//the segment of the dash right and lift the axis 286 | int dashEnd = dashStart + (int)XAxisDashHeight - 1; 287 | for (; i > 0; i -= seed) 288 | { 289 | g.DrawLine(xDashPen, i, dashStart, i, dashEnd);//draw the upper y-axis half 290 | } 291 | 292 | for (i = Center.X + seed; i < width; i += seed) 293 | { 294 | g.DrawLine(xDashPen, i, dashStart, i, dashEnd);//draw the lower y-axis half 295 | } 296 | } 297 | } 298 | if (YAxisDashEnable) 299 | { 300 | using (Pen yDashPen = new Pen(YAxisDashColor)) 301 | { 302 | yDashPen.Width = YAxisDashWidth; 303 | 304 | int seed = (int)Math.Round(YPixelsPerUnit); 305 | int i = Center.Y - seed; 306 | int dashStart = (int)(Center.X - (int)(AxesWidth / 2) - ((YAxisDashHeight - AxesWidth) / 2));//the segment of the dash right and lift the axis 307 | int dashEnd = dashStart + (int)YAxisDashHeight - 1; 308 | for (; i > 0; i -= seed) 309 | { 310 | g.DrawLine(yDashPen, dashStart, i, dashEnd, i);//draw the upper y-axis half 311 | } 312 | for (i = Center.Y + seed; i < height; i += seed) 313 | { 314 | g.DrawLine(yDashPen, dashStart, i, dashEnd, i);//draw the lower y-axis half 315 | } 316 | } 317 | } 318 | 319 | #endregion 320 | 321 | } 322 | public void DrawCurves(Graphics g) 323 | { 324 | g.TranslateTransform(Center.X, Center.Y); 325 | g.ScaleTransform(1, -1); 326 | foreach (Curve curve in curves) 327 | { 328 | if ((curve.PlottingType & PlotType.ContineuosCurve) == PlotType.ContineuosCurve) 329 | DrawConCurve(g, curve); 330 | if ((curve.PlottingType & PlotType.DiscretePoints) == PlotType.DiscretePoints) 331 | DrawPoints(g, curve); 332 | if ((curve.PlottingType & PlotType.Impulses) == PlotType.Impulses) 333 | DrawImpulse(g, curve); 334 | } 335 | g.ResetTransform(); 336 | } 337 | private void DrawImpulse(Graphics g, Curve curve) 338 | { 339 | using (Pen p = new Pen(curve.CurveColor)) 340 | { 341 | p.Width = curve.LineWidth; 342 | p.DashStyle = curve.DashStyle; 343 | for (int i = 0; i < curve.Points.Count; i++) 344 | { 345 | g.DrawLine(p, curve[i].X * XPixelsPerUnit, curve[i].Y * YPixelsPerUnit, curve[i].X * XPixelsPerUnit, 0);//0 because we have transform the coordinate 346 | } 347 | } 348 | } 349 | private void DrawPoints(Graphics g, Curve curve) 350 | { 351 | SmoothingMode currentMode = g.SmoothingMode; 352 | g.SmoothingMode = SmoothingMode.AntiAlias; 353 | using (Brush b = new SolidBrush(curve.CurveColor)) 354 | { 355 | float halfPointSize = curve.PointSize / 2; 356 | for (int i = 0; i < curve.Points.Count; i++) 357 | { 358 | g.FillEllipse(b, (curve[i].X * XPixelsPerUnit)- halfPointSize, (curve[i].Y * YPixelsPerUnit) - halfPointSize, curve.PointSize, curve.PointSize); 359 | } 360 | } 361 | g.SmoothingMode = currentMode; 362 | } 363 | private void DrawConCurve(Graphics g, Curve curve) 364 | { 365 | using (Pen p = new Pen(curve.CurveColor)) 366 | { 367 | p.DashStyle = curve.DashStyle; 368 | p.Width = curve.LineWidth; 369 | SmoothingMode mode = g.SmoothingMode; 370 | g.SmoothingMode = SmoothingMode.AntiAlias; 371 | for (int i = 0; i < curve.Points.Count - 1; i++) 372 | { 373 | try 374 | { 375 | g.DrawLine(p, curve[i].X * XPixelsPerUnit, curve[i].Y * YPixelsPerUnit, curve[i + 1].X * XPixelsPerUnit, curve[i + 1].Y * YPixelsPerUnit); 376 | } 377 | catch (Exception ex) 378 | { 379 | //if the point is out of drawable range just ignore it 380 | } 381 | } 382 | 383 | //this should be more efficient, but we need to handle the NAN and infinity values 384 | //g.DrawLines(p, curve.GetScaledPoints(XPixelsPerUnit, YPixelsPerUnit)); 385 | 386 | g.SmoothingMode = mode; 387 | } 388 | } 389 | public PointF GetActualPoint(Point p) 390 | { 391 | //return the actual human interface point using the representational point in the canvas 392 | PointF res = new PointF((p.X - Center.X) * XPixelsPerUnit, (Center.Y - p.Y) * YPixelsPerUnit); 393 | return res; 394 | } 395 | public PointF GetRepresentaionalPoint(PointF p) 396 | { 397 | //return the position of (drawer point) on the canvas 398 | PointF res = new PointF(p.X / XPixelsPerUnit + Center.X, Center.Y - p.Y / YPixelsPerUnit); 399 | return res; 400 | } 401 | public float GetMinX() 402 | { 403 | return (0 - Center.X) / XPixelsPerUnit; 404 | } 405 | public float GetMaxX(float canvasWidth) 406 | { 407 | return (canvasWidth - Center.X) / XPixelsPerUnit; 408 | } 409 | 410 | 411 | } 412 | [Flags] 413 | public enum PlotType 414 | { 415 | ContineuosCurve = 1, 416 | DiscretePoints = 2, 417 | Impulses = 4, 418 | 419 | } 420 | public class Curve 421 | { 422 | public Color CurveColor { get; set; } 423 | public List Points { get; set; } 424 | public DashStyle DashStyle { get; set; } 425 | public float LineWidth { get; set; } 426 | public PlotType PlottingType { get; set; } 427 | public float PointSize { get; set; } 428 | public Curve(Color color,PlotType plottingType) 429 | { 430 | CurveColor = color; 431 | PlottingType = plottingType; 432 | LineWidth = 1.0f; 433 | PointSize = 2.0f; 434 | Points = new List(800); 435 | } 436 | public PointF this[int index] { get { return Points[index]; } } 437 | public PointF[] GetScaledPoints(float xs,float ys) 438 | { 439 | PointF[] points = new PointF[Points.Count]; 440 | for(int i=0;i