Click here to Skip to main content
15,885,757 members
Articles / Programming Languages / C#

Integration: Mechanics + Hydraulics + Navigation

Rate me:
Please Sign up or sign in to vote.
5.00/5 (46 votes)
3 Feb 2011CPOL21 min read 61.5K   6.1K   88  
Sample of integration of branches of engineering.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using BaseTypes;
using BaseTypes.Interfaces;
using BaseTypes.CSharp;
using FormulaEditor.CodeCreators;
using FormulaEditor.Interfaces;

namespace FormulaEditor.CSharp
{
    /// <summary>
    /// Creator of C# code
    /// </summary>
    public class CSharpCodeCreator : SeparatorCodeCreator, IOperationSeparatorCreator
    {
        #region Fields

        /// <summary>
        /// Singleton
        /// </summary>
        public static readonly ICodeCreator CodeCreator = new CSharpCodeCreator();

        /// <summary>
        /// Standard header of calculation class
        /// </summary>
        public const string StandardHeader = "using System;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\n\r\n";

        private static bool cycle = true;

        private static readonly ITypeCreator typeCreator =
            new CSTypeCreator();

        private static readonly Dictionary<string, string[]> elementary =
        new Dictionary<string, string[]> {
            {"s", new string[] {" = Math.Sin(", ");"}},
            {"c", new string[] {" = Math.Cos(", ");"}},
            {"l", new string[] {" = Math.Log(", ");"}},
            {"e", new string[] {" = Math.Exp(", ");"}},
            {"t", new string[] {" = Math.Tan(", ");"}},
            {"q", new string[] {" = Math.Tan( Math.PI / 2 - (", "));"}},
            {"a", new string[] {" = Math.Atan(", ");"}},
            {"b", new string[] {" = Math.PI / 2 - Math.Atan(", ");"}},
            {"j", new string[] {" = 1 / Math.Cos(", ");"}},
            {"k", new string[] {" = 1 / Math.Sin(", ");"}},
            {"f", new string[] {" = Math.Asin(", ");"}},
            {"g", new string[] {" = Math.Acos(", ");"}},
            {"?", new string[] {" = (", ");"}},
            {"-", new string[] {" = -(", ");"}},
        };

        private static readonly string[] squareRoot = new string[] { " = Math.Sqrt(", ");" };
        private static readonly string[] root = new string[] { " = Math.Pow(", ", 1 /(", "));" };

        private static readonly string[] atan2 = new string[] { " = Math.Atan2(", ", ", ");" };
            

        private static readonly string[] optionalSeparator = new string[] {" = (", ") ? (", ") : (", ");"};

        private static readonly string[] power = new string[] 
        { " = Math.Pow(", ", ", ");" };


        private static Dictionary<string, string[]> elementaryBinary = new Dictionary<string, string[]>()
        {
            {"+", new string[] {" = (", ") + (", ");"}},
            {"-", new string[] {" = (", ") - (", ");"}},
            {"*", new string[] {" = (", ") * (", ");"}},
        };

        private static readonly Dictionary<string, string[]> comparation = new Dictionary<string, string[]>()
        {
            {">", new string[] {" = (", ") > (", ");"}},
            {"<", new string[] {" = (", ") < (", ");"}},
            {"\u2260", new string[] {" != (", ") * (", ");"}},
            {"\u2264", new string[] {" >= (", ") * (", ");"}},
            {"\u2265", new string[] {" >= (", ") * (", ");"}},
        };

        private static readonly Dictionary<string, string[]> logicalOperation = new Dictionary<string, string[]>()
       {
            {"\u2216", new string[] {" = (", ") & (", ");"}},
            {"\u2217", new string[] {" = (", ") | (", ");"}}
       };



        private static string[] fraction = new string[] { " = (", ") / (", ");" };

        #endregion

        #region Ctor

        private CSharpCodeCreator()
            : this(null)
        {
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="trees">Trees</param>
        protected CSharpCodeCreator(ObjectFormulaTree[] trees)
            : base(trees)
        {
            separatorCreator = this; 
        }

        #endregion

        #region Overriden Members

        /// <summary>
        /// Creates Code from tree
        /// </summary>
        /// <param name="tree">The tree</param>
        /// <param name="ret">Return value</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="variables">Variables</param>
        /// <param name="initializers">Initializers</param>
        /// <returns>List of code</returns>
        public override IList<string> CreateCode(ObjectFormulaTree tree, string ret, string[] parameters, out IList<string> variables, out IList<string> initializers)
        {
            IList<string> l = base.CreateCode(tree, ret, parameters, out variables, out initializers);
            if (l != null)
            {
                return l;
            }
            l = CreateArraySingleCode(tree, ret, parameters, out variables, out initializers);
            if (l != null)
            {
                return l;
            }
            l = CreateArrayCode(tree, ret, parameters, out variables, out initializers);
            if (l != null)
            {
                return l;
            }
            return CreateTreeCode(tree, ret, parameters, out variables, out initializers);
        }

        /// <summary>
        /// Gets constant string representation of value of tree 
        /// </summary>
        /// <param name="tree">The tree</param>
        /// <returns>String representation</returns>
        public override string GetConstValue(ObjectFormulaTree tree)
        {
            IObjectOperation op = tree.Operation;
            if (op is ElementaryRealConstant)
            {
                ElementaryRealConstant co = op as ElementaryRealConstant;
               /* if (!consts.Contains(tree))
                {
                    consts.Add(tree);
                }*/
                return co.StringValue;
            }
            return null;
        }

        #endregion

        #region IOperationSeparatorCreator Members

        /// <summary>
        /// Separators
        /// </summary>
        /// <param name="tree">Tree</param>
        /// <returns>operation separators</returns>
        public new virtual string[] this[ObjectFormulaTree tree]
        {
            get
            {
                string[] ss = null;
                IObjectOperation op = tree.Operation;
                ss = GetMultiSeparator(tree.Operation);
                if (ss != null)
                {
                    return ss;
                }
                return null;
            }
        }

        /// <summary>
        /// Creates Creator
        /// </summary>
        /// <param name="trees">Trees</param>
        /// <returns>Creator</returns>
        public override ICodeCreator Create(ObjectFormulaTree[] trees)
        {
            return new CSharpCodeCreator(trees);
        }

        #endregion

        #region Members

        /// <summary>
        /// Creates code
        /// </summary>
        /// <param name="trees">Trees</param>
        /// <param name="creator">Code creator</param>
        /// <param name="local">Local code creator</param>
        /// <param name="variables">Variables</param>
        /// <param name="initializers">Initializers</param>
        /// <returns>List of code strings</returns>
        public static IList<string> CreateCode(ObjectFormulaTree[] trees, ICodeCreator creator, out ICodeCreator local,
             out IList<string> variables, out IList<string> initializers)
        {
            IList<string> l = StaticCodeCreator.CreateCode(trees, creator, out local,
                out variables, out initializers);
            variables.Add("ObjectFormulaTree currentTree = null;");
            variables.Add("object[] currentArray = null;");
            variables.Add("double doubleValue = 0;");
            variables.Add("ObjectFormulaTree[] trees = null;");
            ObjectFormulaTree[] lt = local.Trees;
            foreach (ObjectFormulaTree tree in lt)
            {
                object ret = tree.ReturnType;
                string s = typeCreator.GetType(ret) + " ";
                s += local[tree] + " = ";
                string cv = creator.GetConstValue(tree);
                if (cv == null)
                {
                    s += typeCreator.GetDefaultValue(ret);
                }
                else
                {
                    s += cv;
                }
                s += ";";
                variables.Add(s);
            }
            return l;
        }

        private static string GuidClass
        {
            get
            {
                string guid = Guid.NewGuid() + "";
                guid = guid.Replace('-', '_');
                string ss = "namespace Calculation";
               // ss += guid;
                ss += "\r\n{\r\n    public class Calculate ";
                return ss;
            }
        }

        private static string AddType(string s, Type type)
        {
            string so = s + "";
            if (so.Contains(":"))
            {
                so += ": ";
            }
            else
            {
                so += ", ";
            }
            so +=  type.FullName;
            return so;
        }

        /// <summary>
        /// Create Guid class name
        /// </summary>
        /// <param name="types">Types of variables</param>
        /// <returns>Class name</returns>
        public static string GetGuidClass(Type[] types)
        {
            string s = GuidClass;
            if (types != null)
            {
                if (types.Length > 0)
                {
                    s += ": ";
                    string ss = "";
                    foreach (Type t in types)
                    {
                        s += t.FullName + ss;
                        ss = ", ";
                    }
                }
            }
            s += "\r\n";
            s += "{\r\n";
            return s;
        }


        private string[] GetMultiSeparator(IObjectOperation op)
        {
          /*  if (op is OptionalOperation)
            {
                return optional;
            }*/
            if (op is ElementaryBinaryOperation)
            {
                ElementaryBinaryOperation eb = op as ElementaryBinaryOperation;
                string seb = eb.Symbol + "";
                if (elementaryBinary.ContainsKey(seb))
                {
                    return elementaryBinary[seb];
                }
            }
            if (op is ElementaryAtan2)
            {
                return atan2;
            }
            if (op is ElementaryFraction)
            {
                return fraction;
            }
            if (op is ElementaryRoot)
            {
                if (op.Arity == 1)
                {
                    return squareRoot;
                }
                return root;
            }
            if (op is ElementaryFunctionOperation)
            {
                ElementaryFunctionOperation o = op as ElementaryFunctionOperation;
                string key = o.Symbol + "";
                if (elementary.ContainsKey(key))
                {
                    return elementary[key];
                }
            }
            if (op is ComparationOperation)
            {
                ComparationOperation co = op as ComparationOperation;
                string cos = co.String;
                if (comparation.ContainsKey(cos))
                {
                    return comparation[cos];
                }
            }
            if (op is LogicalOperation)
            {
                LogicalOperation lo = op as LogicalOperation;
                string los = lo.Symbol + "";
                if (logicalOperation.ContainsKey(los))
                {
                    return logicalOperation[los];
                }
            }
            if (op is ElementaryPowerOperation)
            {
                return power;
            }
            return null;
                
        }

        /// <summary>
        /// Creates code for array operation
        /// </summary>
        /// <param name="tree">Tree</param>
        /// <param name="ret">Return</param>
        /// <param name="parameters">Parameters of tree</param>
        /// <param name="variables">Variables</param>
        /// <param name="initializers">Initializers</param>
        /// <returns>List of code strings</returns>
        protected IList<string> CreateArraySingleCode(ObjectFormulaTree tree, string ret, string[] parameters,
            out IList<string> variables, out IList<string> initializers)
        {
            variables = new List<string>();
            initializers = new List<string>();
            IObjectOperation op = tree.Operation;
            if (!(op is ArraySingleOperation))
            {
                return null;
            }
            ArraySingleOperation ars = op as ArraySingleOperation;
            string ops = (ars.Type == ArraySingleOperationType.Sum) ? " + " : " * ";
            ObjectFormulaTree t = tree[0];
            ArrayReturnType art = t.ReturnType as ArrayReturnType;
            int n = art.Dimension[0];
            string sp = "";
            if (art.IsObjectType)
            {
                sp = "(double)";
            }
            StringBuilder sb = new StringBuilder();
            sb.Append(ret);
            sb.Append(" = ");
            string par = sp + parameters[0] + "[";
            sb.Append(par + "0]");
            par = ops + par;
            for (int i = 1; i < n; i++)
            {
                sb.Append(par);
                sb.Append(i);
                sb.Append("]");
            }
            sb.Append(";");
            return new List<string> { { sb.ToString() } };
        }


        private string GetModifier(object type)
        {
            string s = "";
            if (type is ArrayReturnType)
            {
                ArrayReturnType art = type as ArrayReturnType;
                if (art.IsObjectType)
                {
                    s = "(" + typeCreator.GetType(art.ElementType) + ")";
                }
            }
            return s;
        }

        private int GetLength(object type)
        {
            if (!(type is ArrayReturnType))
            {
                return 0;
            }
            ArrayReturnType art = type as ArrayReturnType;
            return art.Dimension.Length;
        }

        private int GetMaxLength(object[] types)
        {
            int n = 0;
            foreach (object type in types)
            {
                int m = GetLength(type);
                if (m > n)
                {
                    n = m;
                }
            }
            return n;
        }

        /// <summary>
        /// Creates code from tree
        /// </summary>
        /// <param name="tree">The tree</param>
        /// <param name="ret">Return identifier</param>
        /// <param name="parameters">Parameters of tree</param>
        /// <param name="variables">Variables of tree</param>
        /// <param name="initializers">Initializers</param>
        /// <returns>List of code strings</returns>
        protected IList<string> CreateArrayCode(ObjectFormulaTree tree, string ret, string[] parameters,
            out IList<string> variables, out IList<string> initializers)
        {
            List<string> vari = new List<string>();
            List<string> init = new List<string>();
            variables = vari;
            initializers = init;
            IObjectOperation op = tree.Operation;
            if (!(op is ArrayOperation))
            {
                return null;
            }
            ArrayOperation ao = op as ArrayOperation;
            object[] types = ao.Types;
            string[] par = new string[parameters.Length];
            for (int i = 0; i < par.Length; i++)
            {
                par[i] = GetModifier(types[i]) + parameters[i];
            }
            ArrayReturnType art = ao.ReturnType as ArrayReturnType;
            List<ObjectFormulaTree> ch = new List<ObjectFormulaTree>();
            for (int i = 0; i < tree.Count; i++)
            {
                if (tree[i] != null)
                {
                    ch.Add(tree[i]);
                }
            }
            ObjectFormulaTree t = new ObjectFormulaTree(ao.SingleOperation, ch);
            List<string> list = new List<string>();
            bool success;
            if (cycle)
            {
                ProcessCycleArrayCode(0, tree, t, ret + "[", par, types, art, list, vari, init, out success);
            }
            else
            {
                ProcessArrayCode(0, tree, t, ret + "[", par, types, art, list, vari, init, out success);
            }
            if (!success)
            {
                return null;
            }
            return list;
        }

        /// <summary>
        /// Process cyclic array code
        /// </summary>
        /// <param name="level">Level</param>
        /// <param name="baseTree">Base tree</param>
        /// <param name="childTree">Child tree</param>
        /// <param name="ret">Rerurn</param>
        /// <param name="parameters">Parametres</param>
        /// <param name="types">Types of variables</param>
        /// <param name="retType">Type of return</param>
        /// <param name="list">List of code strings</param>
        /// <param name="variables">List of variables</param>
        /// <param name="initializers">List of initializers</param>
        /// <param name="success">The success sign</param>
        protected void ProcessCycleArrayCode(int level, ObjectFormulaTree baseTree, ObjectFormulaTree childTree,
            string ret, string[] parameters, object[] types, ArrayReturnType retType, List<string> list,
           List<string> variables, List<string> initializers, out bool success)
        {
            if (retType.Dimension.Length == 1)
            {
                int n = retType.Dimension[level];
                string[] par = new string[parameters.Length];
                list.Add("for (int i = 0; i < " + n + "; i++)");
                list.Add("{");
                string si = "i";
                string sf = si + "]";
                string retLocal = ret + sf;

                for (int j = 0; j < parameters.Length; j++)
                {
                    par[j] = parameters[j] + "";
                    int ll = GetLength(types[j]);
                    if (ll > 0)
                    {
                        if (ll == 1)
                        {
                            par[j] += "[";
                        }
                        par[j] += sf;
                    }
                }
                IList<string> vari;
                IList<string> init;
                IList<string> l = CreateCode(childTree, retLocal, par, out vari, out init);
                success = (l != null);
                if (!success)
                {
                    return;
                }
                list.AddRange(l);
                if (vari != null)
                {
                    variables.AddRange(vari);
                }
                if (init != null)
                {
                    initializers.AddRange(init);
                }
                list.Add("}");
                success = true;
                return;
            }
            if (level == retType.Dimension.Length - 1)
            {
                int n = retType.Dimension[level];
                string[] par = new string[parameters.Length];
                for (int i = 0; i < n; i++)
                {
                    string si = i + "";
                    string sf = si + "]";
                    string retLocal = ret + sf;

                    for (int j = 0; j < parameters.Length; j++)
                    {
                        par[j] = parameters[j] + "";
                        int ll = GetLength(types[j]);
                        if (ll > 0)
                        {
                            if (ll == 1)
                            {
                                par[j] += "[";
                            }
                            par[j] += sf;
                        }
                    }
                    IList<string> vari;
                    IList<string> init;
                    IList<string> l = CreateCode(childTree, retLocal, par, out vari, out init);
                    success = (l != null);
                    if (!success)
                    {
                        return;
                    }
                    list.AddRange(l);
                    if (vari != null)
                    {
                        variables.AddRange(vari);
                    }
                    if (init != null)
                    {
                        initializers.AddRange(init);
                    }
                }
                success = true;
                return;
            }
            string[] localPar = new string[parameters.Length];
            int k = retType.Dimension[level];
            int length = retType.Dimension.Length;
            for (int i = 0; i < k; i++)
            {
                string[] parlocal = new string[parameters.Length];
                string retLocal = ret + i + ",";
                for (int j = 0; j < parameters.Length; i++)
                {
                    int dim = GetLength(types[j]);
                    if (dim == 0)
                    {
                        continue;
                    }
                    if ((dim + level) <= length)
                    {
                        continue;
                    }
                    if ((dim + level) == length)
                    {
                        parlocal[i] += "[" + i + ", ";
                        continue;
                    }
                    parlocal[i] += i + ",";
                }
                ProcessArrayCode(level + 1, baseTree, childTree, retLocal, parlocal, types,
                    retType, list, variables, initializers, out success);
                if (!success)
                {
                    return;
                }
            }
            success = true;
        }


        /// <summary>
        /// Processes array code
        /// </summary>
        /// <param name="level">Level</param>
        /// <param name="baseTree">Base tree</param>
        /// <param name="childTree">Current tree</param>
        /// <param name="ret">Return</param>
        /// <param name="parameters">Parameters</param>
        /// <param name="types">Types of variables</param>
        /// <param name="retType">Return type</param>
        /// <param name="list">List of code strings</param>
        /// <param name="variables">Variables</param>
        /// <param name="initializers">Initializers</param>
        /// <param name="success">The "success" sign</param>
        protected void ProcessArrayCode(int level, ObjectFormulaTree baseTree, ObjectFormulaTree childTree,
            string ret, string[] parameters, object[] types, ArrayReturnType retType, List<string> list,
           List<string> variables, List<string> initializers, out bool success)
        {
            if (level == retType.Dimension.Length - 1)
            {
                int n = retType.Dimension[level];
                string[] par = new string[parameters.Length];
                for (int i = 0; i < n; i++)
                {
                    string si = i + "";
                    string sf = si + "]";
                    string retLocal = ret + sf;
                    
                    for (int j = 0; j < parameters.Length; j++)
                    {
                        par[j] = parameters[j] + "";
                        int ll = GetLength(types[j]);
                        if (ll > 0)
                        {
                            if (ll == 1)
                            {
                                par[j] += "[";
                            }
                            par[j] += sf;
                        }
                    }
                    IList<string> vari;
                    IList<string> init;
                    IList<string> l = CreateCode(childTree, retLocal, par, out vari, out init);
                    success = (l != null);
                    if (!success)
                    {
                        return;
                    }
                    list.AddRange(l);
                    if (vari != null)
                    {
                        variables.AddRange(vari);
                    }
                    if (init != null)
                    {
                        initializers.AddRange(init);
                    }
                }
                success = true;
                return;
            }
            string[] localPar = new string[parameters.Length];
            int k = retType.Dimension[level];
            int length = retType.Dimension.Length;
            for (int i = 0; i < k; i++)
            {
                string[] parlocal = new string[parameters.Length];
                string retLocal = ret + i + ",";
                for (int j = 0; j < parameters.Length; i++)
                {
                    int dim = GetLength(types[j]);
                    if (dim == 0)
                    {
                        continue;
                    }
                    if ((dim + level) <= length)
                    {
                        continue;
                    }
                    if ((dim + level) == length)
                    {
                        parlocal[i] += "[" + i + ", ";
                        continue;
                    }
                    parlocal[i] += i + ",";
                }
                ProcessArrayCode(level + 1, baseTree, childTree, retLocal, parlocal, types,
                    retType, list, variables, initializers, out success);
                if (!success)
                {
                    return;
                }
            }
            success = true;
        }



        /// <summary>
        /// Creates array code
        /// </summary>
        /// <param name="tree">Base tree</param>
        /// <param name="ret">Return</param>
        /// <param name="parameters">Variables</param>
        /// <param name="variables">Parameters</param>
        /// <param name="initializers">Initializers</param>
        /// <returns>List of code strings</returns>
        protected IList<string> CreateTreeCode(ObjectFormulaTree tree, string ret, string[] parameters,
            out IList<string> variables, out IList<string> initializers)
        {
            List<string> l = new List<string>();
            int n = StaticCodeCreator.GetNumber(this, tree);
            l.Add("\t\t\tcurrentTree = trees[" + n + "];");
            int count = tree.Count;
            List<string> vari = new List<string>();
            string ta = "treeArray_" + n;
            l.Add("\t\t\tcurrentArray = " + ta + ";");
            vari.Add("object[] " + ta + " = new object[" + count + "];");
            for (int i = 0; i < count; i++)
            {
                ObjectFormulaTree t = tree[i];
                if (t == null)
                {
                    continue;
                }
                string id = codeCreator[t];
                l.Add("currentArray[" + i + "] = " + id + ";"); 
            }
            string ss = "";
            string tt = typeCreator.GetType(tree.ReturnType);
            if (!tt.Equals("object"))
            {
                ss = "(" + tt + ")";
            }
            l.Add(ret + " = " + ss + "currentTree.Calculate(currentArray);");
            initializers = new List<string>();
            variables = vari; 
            return l;
        }

        #endregion

     }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Russian Federation Russian Federation
Ph. D. Petr Ivankov worked as scientific researcher at Russian Mission Control Centre since 1978 up to 2000. Now he is engaged by Aviation training simulators http://dinamika-avia.com/ . His additional interests are:

1) Noncommutative geometry

http://front.math.ucdavis.edu/author/P.Ivankov

2) Literary work (Russian only)

http://zhurnal.lib.ru/editors/3/3d_m/

3) Scientific articles
http://arxiv.org/find/all/1/au:+Ivankov_Petr/0/1/0/all/0/1

Comments and Discussions