Skip to content
Snippets Groups Projects
Fact.cs 117 KiB
Newer Older
  • Learn to ignore specific revisions
  •     /// \copydoc Fact.parseFact(Scroll.ScrollFact)
        public new static OnLineFact parseFact(Scroll.ScrollFact fact)
    
            string uri = fact.@ref.uri;
    
            string lineUri = "";
            string pointUri = "";
            
            if (((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[0] is OMS)
            {
                // standard case
                lineUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[0]).uri;
                pointUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).uri;
            }
            else {
                // case when line Uri has a projl on the line Argument 
                lineUri = ((OMS)((OMA)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[0]).arguments[0]).uri;
                pointUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).uri;
    
    
            }
    
            if (StageStatic.stage.factState.ContainsKey(pointUri)
             && StageStatic.stage.factState.ContainsKey(lineUri))
                return new OnLineFact(pointUri, lineUri, uri, StageStatic.stage.factState);
    
            //If dependent facts do not exist return null
            else
                return null;
    
        protected override string generateLabel()
        {
    
            return _Facts[Pid].Label + "∈" + _Facts[Rid].Label;
    
    BenniHome's avatar
    BenniHome committed
    
    
        public override Boolean hasDependentFacts()
        {
            return true;
        }
    
    
        /// \copydoc Fact.getDependentFactIds
    
        public override string[] getDependentFactIds()
    
            return new string[] { Pid, Rid };
    
        /// \copydoc Fact.instantiateDisplay(GameObject, Transform)
    
    John Schihada's avatar
    John Schihada committed
        public override GameObject instantiateDisplay(GameObject prefab, Transform transform)
    
    John Schihada's avatar
    John Schihada committed
        {
            var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform);
    
            obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid].Label;
            obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Rid].Label;
    
    John Schihada's avatar
    John Schihada committed
            obj.GetComponent<FactWrapper>().fact = this;
            return obj;
        }
    
    
            return this.Pid.GetHashCode() ^ this.Rid.GetHashCode();
    
    BenniHome's avatar
    BenniHome committed
    
    
        /// \copydoc Fact.Equivalent(Fact, Fact)
    
        protected override bool EquivalentWrapped(OnLineFact f1, OnLineFact f2)
    
            if (f1.Pid == f2.Pid && f1.Rid == f2.Rid)
                return true;
    
    
            PointFact pf1 = (PointFact)_Facts[f1.Pid];
            RayFact rf1 = (RayFact)_Facts[f1.Rid];
            PointFact pf2 = (PointFact)_Facts[f2.Pid];
            RayFact rf2 = (RayFact)_Facts[f2.Rid];
    
    
            return pf1.Equivalent(pf2) && rf1.Equivalent(rf2);
    
    /// <summary>
    /// Angle comprised of three <see cref="PointFact">PointFacts</see> [A,B,C]
    /// </summary>
    
    public class AngleFact : FactWrappedCRTP<AngleFact>
    
        /// @{ <summary>
        /// One <see cref="Fact.Id">Id</see> of three <see cref="PointFact">PointFacts</see> defining Angle [<see cref="Pid1"/>, <see cref="Pid2"/>, <see cref="Pid3"/>].
        /// </summary>
    
        public string Pid1, Pid2, Pid3;
    
        /// @}
    
        /// <summary> <see langword="true"/>, if AngleFact is approximately 90° or 270°</summary>
    
        public bool is_right_angle;
    
    
        /// <summary> \copydoc Fact.Fact </summary>
    
        public AngleFact() : base()
        {
            this.Pid1 = null;
            this.Pid2 = null;
            this.Pid3 = null;
            this.is_right_angle = false;
        }
    
    
        /// <summary>
        /// Copies <paramref name="fact"/> by initiating new MMT %Fact.
        /// </summary>
        /// <param name="fact">Fact to be copied</param>
        /// <param name="old_to_new"><c>Dictionary</c> mapping <paramref name="fact"/>.<see cref="getDependentFactIds"/> in <paramref name="fact"/>.<see cref="Fact._Facts"/> to corresponding <see cref="Fact.Id"/> in <paramref name="organizer"/> </param>
        /// <param name="organizer">sets <see cref="_Facts"/></param>
    
        public AngleFact(AngleFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer)
        {
            init(old_to_new[fact.Pid1], old_to_new[fact.Pid2], old_to_new[fact.Pid3]);
        }
    
    
        /// <summary>
        /// Standard Constructor
        /// </summary>
        /// <param name="pid1">sets <see cref="Pid1"/></param>
        /// <param name="pid2">sets <see cref="Pid2"/></param>
        /// <param name="pid3">sets <see cref="Pid3"/></param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
    
        public AngleFact(string pid1, string pid2, string pid3, FactOrganizer organizer) : base(organizer)
    
        /// <summary>
        /// Initiates <see cref="Pid1"/>, <see cref="Pid2"/>, <see cref="Pid3"/>, <see cref="is_right_angle"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
        /// </summary>
        /// <param name="pid1">sets <see cref="Pid1"/></param>
        /// <param name="pid2">sets <see cref="Pid2"/></param>
        /// <param name="pid3">sets <see cref="Pid3"/></param>
    
        private void init(string pid1, string pid2, string pid3)
    
            this.Pid1 = pid1;
            this.Pid2 = pid2;
            this.Pid3 = pid3;
    
            PointFact pf1 = _Facts[pid1] as PointFact;
            PointFact pf2 = _Facts[pid2] as PointFact;
            PointFact pf3 = _Facts[pid3] as PointFact;
    
            float v = GetAngle(); // sets is_right_angle
    
            if (Mathf.Abs(Mathf.Abs(v) - 90.0f) < 0.1)
            {
                // also generate a RightAngleFact 
                RightAngleFact rightAngle = new RightAngleFact(pid1, pid2, pid3, StageStatic.stage.factState);
                // I have no clue if this is actually necessary
                bool exists;
                StageStatic.stage.factState.Add(rightAngle, out exists, true);
            }
    
    
            string p1URI = pf1.Id;
            string p2URI = pf2.Id;
            string p3URI = pf3.Id;
    
           // if (is_right_angle)
           //     mmtDecl = generate90DegreeAngleDeclaration(v, p1URI, p2URI, p3URI);
           // else
              mmtDecl = generateNot90DegreeAngleDeclaration(v, p1URI, p2URI, p3URI);
    
            AddFactResponse.sendAdd(mmtDecl, out this._URI);
    
        /// <summary>
        /// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_.
        /// </summary>
        /// <param name="Pid1">sets <see cref="Pid1"/></param>
        /// <param name="Pid2">sets <see cref="Pid2"/></param>
        /// <param name="Pid3">sets <see cref="Pid3"/></param>
        /// <param name="backendURI">MMT URI</param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
    
        public AngleFact(string Pid1, string Pid2, string Pid3, string backendURI, FactOrganizer organizer) : base(organizer)
    
        {
            this.Pid1 = Pid1;
            this.Pid2 = Pid2;
            this.Pid3 = Pid3;
    
            float v = GetAngle();
    
            if (Mathf.Abs(Mathf.Abs(v) - 90.0f) < 0.1)
            {
                // also generate an orthogonal circle line fact
    
                RightAngleFact rightAngle = new RightAngleFact(Pid1, Pid2, Pid3, StageStatic.stage.factState);
                // is it necessary to make a boolean variable here?
                bool exists;
                StageStatic.stage.factState.Add(rightAngle, out exists, true);
            }
    
    
    
            this._URI = backendURI;
            _ = this.Label;
        }
    
        public AngleFact(string Pid1, string Pid2, string Pid3,float angle, string backendURI, FactOrganizer organizer) : base(organizer)
        {
            this.Pid1 = Pid1;
            this.Pid2 = Pid2;
            this.Pid3 = Pid3;
    
            if (Mathf.Abs(Mathf.Abs(angle) - 90.0f) < 0.1)
            {
                // also generate an orthogonal circle line fact
    
                RightAngleFact rightAngle = new RightAngleFact(Pid1, Pid2, Pid3, StageStatic.stage.factState);
                // I have no clue if this is actually necessary
                bool exists;
                StageStatic.stage.factState.Add(rightAngle, out exists, true);
            }
    
            this._URI = backendURI;
    
        /// \copydoc Fact.parseFact(Scroll.ScrollFact)
        public new static AngleFact parseFact(Scroll.ScrollFact fact)
    
            string uri = fact.@ref.uri;
            string
                pointAUri,
                pointBUri,
                pointCUri;
    
            //If angle is not a 90Degree-Angle
            if (fact.GetType().Equals(typeof(Scroll.ScrollValueFact)))
            {
    
                OMA df = (OMA)((Scroll.ScrollValueFact)fact).lhs;
    
                if (df == null)
                    return null;
    
          
    
                if (((Scroll.ScrollValueFact)fact).value != null)
                    angle = ((OMF)(((Scroll.ScrollValueFact)fact).value)).f;
    
    
    
                pointAUri = ((OMS)((OMA)((Scroll.ScrollValueFact)fact).lhs).arguments[0]).uri;
                pointBUri = ((OMS)((OMA)((Scroll.ScrollValueFact)fact).lhs).arguments[1]).uri;
                pointCUri = ((OMS)((OMA)((Scroll.ScrollValueFact)fact).lhs).arguments[2]).uri;
    
            // this should never happen anymore
    
            //If angle is a 90Degree-Angle
            else {
    
                Debug.Log("Angle 90 degrees parsed. This shouldn't happen anymore");
                
    
                pointAUri = ((OMS)((OMA)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).arguments[0]).uri;
                pointBUri = ((OMS)((OMA)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).arguments[1]).uri;
                pointCUri = ((OMS)((OMA)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).arguments[2]).uri;
            }
    
    
            if (StageStatic.stage.factState.ContainsKey(pointAUri)
             && StageStatic.stage.factState.ContainsKey(pointBUri)
             && StageStatic.stage.factState.ContainsKey(pointCUri))
    
            {
    //                return new AngleFact(pointAUri, pointBUri, pointCUri, uri, StageStatic.stage.factState);
                    return new AngleFact(pointAUri, pointBUri, pointCUri,angle, uri, StageStatic.stage.factState);
            }
            else
            {   //If dependent facts do not exist return null
    
        protected override string generateLabel()
        {
    
            return (is_right_angle ? "⊾" : "∠") + _Facts[Pid1].Label + _Facts[Pid2].Label + _Facts[Pid3].Label;
    
        /// <summary>
        /// Computes smallest angle and sets <see cref="is_right_angle"/>
        /// </summary>
        /// <returns>Smallets angle between [<see cref="Pid1"/>, <see cref="Pid2"/>] and [<see cref="Pid2"/>, <see cref="Pid3"/>]</returns>
    
        private float GetAngle()
        {
    
            PointFact pf1 = _Facts[Pid1] as PointFact;
            PointFact pf2 = _Facts[Pid2] as PointFact;
            PointFact pf3 = _Facts[Pid3] as PointFact;
    
    
            float v = Vector3.Angle((pf1.Point - pf2.Point), (pf3.Point - pf2.Point));
            this.is_right_angle = Mathf.Abs(v - 90.0f) < 0.01;
    
            return is_right_angle ? 90f : v;
        }
    
    
        /// <summary>
        /// Constructs struct for right-angled MMT %Fact <see cref="AddFactResponse"/>
        /// </summary>
        /// <param name="val">Angle == 90f, _not checked_</param>
        /// <param name="p1URI"><see cref="Pid1"/></param>
        /// <param name="p2URI"><see cref="Pid2"/></param>
        /// <param name="p3URI"><see cref="Pid3"/></param>
        /// <returns>struct for <see cref="AddFactResponse"/></returns>
    
        private MMTDeclaration generate90DegreeAngleDeclaration(float val, string p1URI, string p2URI, string p3URI) {
    
            MMTTerm argument = new OMA(
                new OMS(MMTURIs.Eq),
                new List<MMTTerm> {
                    new OMS(MMTURIs.RealLit),
                    new OMA(
                        new OMS(MMTURIs.Angle),
                        new List<MMTTerm> {
                            new OMS(p1URI),
                            new OMS(p2URI),
                            new OMS(p3URI)
                        }
                    ),
    
                    new OMF(val) // 90f
    
                }
            );
            
            MMTTerm tp = new OMA(new OMS(MMTURIs.Ded), new List<MMTTerm> {argument});
            MMTTerm df = null;
    
            return new MMTSymbolDeclaration(this.Label, tp, df);
        }
    
    
        /// <summary>
        /// Constructs struct for not-right-angled MMT %Fact <see cref="AddFactResponse"/>
        /// </summary>
        /// <param name="val">Angle != 90f, _not checked_</param>
        /// <param name="p1URI"><see cref="Pid1"/></param>
        /// <param name="p2URI"><see cref="Pid2"/></param>
        /// <param name="p3URI"><see cref="Pid3"/></param>
        /// <returns>struct for <see cref="AddFactResponse"/></returns>
    
        private MMTDeclaration generateNot90DegreeAngleDeclaration(float val, string p1URI, string p2URI, string p3URI)
        {
            MMTTerm lhs =
                new OMA(
                    new OMS(MMTURIs.Angle),
                    new List<MMTTerm> {
                        new OMS(p1URI),
                        new OMS(p2URI),
                        new OMS(p3URI)
                    }
                );
    
            MMTTerm valueTp = new OMS(MMTURIs.RealLit);
            MMTTerm value = new OMF(val);
            
            return new MMTValueDeclaration(this.Label, lhs, valueTp, value);
        }
    
        public override Boolean hasDependentFacts()
        {
            return true;
        }
    
    
        /// \copydoc Fact.getDependentFactIds
    
        public override string[] getDependentFactIds()
    
            return new string[] { Pid1, Pid2, Pid3 };
    
        /// \copydoc Fact.instantiateDisplay(GameObject, Transform)
    
    John Schihada's avatar
    John Schihada committed
        public override GameObject instantiateDisplay(GameObject prefab, Transform transform) {
    
    John Schihada's avatar
    John Schihada committed
            var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform);
    
            obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid1].Label;
            obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid2].Label;
            obj.transform.GetChild(2).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid3].Label;
    
    John Schihada's avatar
    John Schihada committed
            obj.GetComponent<FactWrapper>().fact = this;
            return obj;
        }
    
    
            return this.Pid1.GetHashCode() ^ this.Pid2.GetHashCode() ^ this.Pid3.GetHashCode();
    
        /// \copydoc Fact.Equivalent(Fact, Fact)
    
        protected override bool EquivalentWrapped(AngleFact f1, AngleFact f2)
    
            if ((f1.Pid1 == f2.Pid1 && f1.Pid2 == f2.Pid2 && f1.Pid3 == f2.Pid3))// || 
                //(f1.Pid1 == f2.Pid3 && f1.Pid2 == f2.Pid2 && f1.Pid3 == f2.Pid1))
                return true;
    
    
            PointFact p1f1 = (PointFact)_Facts[f1.Pid1];
            PointFact p2f1 = (PointFact)_Facts[f1.Pid2];
            PointFact p3f1 = (PointFact)_Facts[f1.Pid3];
            PointFact p1f2 = (PointFact)_Facts[f2.Pid1];
            PointFact p2f2 = (PointFact)_Facts[f2.Pid2];
            PointFact p3f2 = (PointFact)_Facts[f2.Pid3];
    
            return (p1f1.Equivalent(p1f2) && p2f1.Equivalent(p2f2) && p3f1.Equivalent(p3f2));
            //|| (p1f1.Equivalent(p3f2) && p2f1.Equivalent(p2f2) && p1f1.Equivalent(p3f2));
        }
    }
    
    
    /// TODO Work in Progress
    /// <summary>
    /// Two parallel Lines comprised of two <see cref="LineFact">LineFacts</see> 
    /// </summary>
    public class ParallelLineFact : FactWrappedCRTP<ParallelLineFact>
    {
        /// @{ <summary>
        /// One <see cref="Fact.Id">Id</see> of thwo <see cref="LineFact">PointFacts</see> defining Angle [<see cref="Lid1"/>, <see cref="Lid2"/>].
        /// </summary>
        public string Lid1, Lid2;
        /// @}
    
    
    
    
        /// <summary> \copydoc Fact.Fact </summary>
        public ParallelLineFact() : base()
        {
            this.Lid1 = null;
            this.Lid2 = null;
        }
    
        /// <summary>
        /// Copies <paramref name="fact"/> by initiating new MMT %Fact.
        /// </summary>
        /// <param name="fact">Fact to be copied</param>
        /// <param name="old_to_new"><c>Dictionary</c> mapping <paramref name="fact"/>.<see cref="getDependentFactIds"/> in <paramref name="fact"/>.<see cref="Fact._Facts"/> to corresponding <see cref="Fact.Id"/> in <paramref name="organizer"/> </param>
        /// <param name="organizer">sets <see cref="_Facts"/></param>
        public ParallelLineFact(ParallelLineFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer)
        {
            init(old_to_new[fact.Lid1], old_to_new[fact.Lid2]);
        }
    
        /// <summary>
        /// Standard Constructor
        /// </summary>
        /// <param name="lid1">sets <see cref="Lid1"/></param>
        /// <param name="lid2">sets <see cref="Lid2"/></param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
        public ParallelLineFact(string lid1, string lid2, FactOrganizer organizer) : base(organizer)
        {
            init(lid1, lid2);
        }
    
        /// <summary>
        /// Initiates <see cref="Lid1"/>, <see cref="Lid2"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
        /// </summary>
        /// <param name="lid1">sets <see cref="Lid1"/></param>
        /// <param name="lid2">sets <see cref="Lid2"/></param>
        private void init(string lid1, string lid2)
        {
            //TODO must be parallel lines 
            this.Lid1 = lid1;
            this.Lid2 = lid2;
    
            RayFact lf1 = _Facts[lid1] as RayFact;
            RayFact lf2 = _Facts[lid2] as RayFact;
    
            MMTDeclaration mmtDecl;
            string l1URI = lf1.Id;
            string l2URI = lf2.Id;
            mmtDecl = generateParallelLineDeclaration( l1URI, l2URI);
        
            AddFactResponse.sendAdd(mmtDecl, out this._URI);
        }
    
        /// <summary>
        /// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_.
        /// </summary>
        /// <param name="Lid1">sets <see cref="Lid1"/></param>
        /// <param name="Lid2">sets <see cref="Lid2"/></param>
        /// <param name="backendURI">MMT URI</param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
        public ParallelLineFact(string Lid1, string Lid2, string backendURI, FactOrganizer organizer) : base(organizer)
        {
            this.Lid1 = Lid1;
            this.Lid2 = Lid2;
    
            this._URI = backendURI;
            _ = this.Label;
        }
    
        /// \copydoc Fact.parseFact(Scroll.ScrollFact)
        public new static ParallelLineFact parseFact(Scroll.ScrollFact fact)
        {
            OMA tp = (OMA)((Scroll.ScrollSymbolFact)fact).tp;
            if (tp == null)
                return null;
    
            string lineAUri = "";
            string lineBUri = "";
    
            string uri = fact.@ref.uri;
            OMA proof_OMA = (OMA)((Scroll.ScrollSymbolFact)fact).tp; // proof DED
       
    
            OMA parallel_lines_OMA = (OMA) proof_OMA.arguments[0]; // parallel
    
            if (parallel_lines_OMA.arguments[0] is OMS) {
                // Normaler Fall 
                lineAUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[0]).uri;
                lineBUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).uri;
    
            }
            // Second case might be redundant by now
            else {
                OMA Projl_line_A_OMA = (OMA)parallel_lines_OMA.arguments[0]; // ProjectL
                lineAUri = ((OMS)Projl_line_A_OMA.arguments[0]).uri;
                OMA Projl_line_B_OMA = (OMA)parallel_lines_OMA.arguments[1]; // ProjectL
                lineBUri = ((OMS)Projl_line_B_OMA.arguments[0]).uri;
    
    
            }
    
    
            if (StageStatic.stage.factState.ContainsKey(lineAUri)
             && StageStatic.stage.factState.ContainsKey(lineBUri))
    
                return new ParallelLineFact(lineAUri,lineBUri, uri, StageStatic.stage.factState);
    
            else    //If dependent facts do not exist return null
                return null;
        }
    
        /// \copydoc Fact.generateLabel
        protected override string generateLabel()
        {
            return "||" + _Facts[Lid1].Label + _Facts[Lid2].Label;
        }
    
    
    
        /// <summary>
        /// Constructs struct for right-angled MMT %Fact <see cref="AddFactResponse"/>
        /// </summary>
        /// <param name="l1URI"><see cref="Lid1"/></param>
        /// <param name="l2URI"><see cref="Lid2"/></param>
        /// <returns>struct for <see cref="AddFactResponse"/></returns>
        private MMTDeclaration generateParallelLineDeclaration(string l1URI, string l2URI)
        {
            
            List<MMTTerm> innerArguments = new List<MMTTerm>
            {
                new OMS(l1URI),
                new OMS(l2URI)
            };
    
            List<MMTTerm> outerArguments = new List<MMTTerm>
            {
                new OMA(new OMS(MMTURIs.ParallelLine), innerArguments)
            };
    
            //OMS constructor generates full URI
            MMTTerm tp = new OMA(new OMS(MMTURIs.Ded), outerArguments);
            MMTTerm df = null;
    
            MMTSymbolDeclaration mmtDecl = new MMTSymbolDeclaration(this.Label, tp, df);
            AddFactResponse.sendAdd(mmtDecl, out this._URI);
    
    
            return mmtDecl;
        }
    
    
        /// \copydoc Fact.hasDependentFacts
        public override Boolean hasDependentFacts()
        {
            return true;
        }
    
        /// \copydoc Fact.getDependentFactIds
        public override string[] getDependentFactIds()
        {
            return new string[] { Lid1, Lid2 };
        }
    
        /// \copydoc Fact.instantiateDisplay(GameObject, Transform)
        public override GameObject instantiateDisplay(GameObject prefab, Transform transform)
        {
            var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform);
            obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Lid1].Label;
            obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Lid2].Label;
            obj.GetComponent<FactWrapper>().fact = this;
            return obj;
        }
    
        /// \copydoc Fact.GetHashCode
        public override int GetHashCode()
        {
            return this.Lid1.GetHashCode() ^ this.Lid2.GetHashCode() ;
        }
    
        /// \copydoc Fact.Equivalent(Fact, Fact)
        protected override bool EquivalentWrapped(ParallelLineFact f1, ParallelLineFact f2)
        {
            if ((f1.Lid1 == f2.Lid1 && f1.Lid2 == f2.Lid2))
                return true;
    
            RayFact r1f1 = (RayFact)_Facts[f1.Lid1];
            RayFact r2f1 = (RayFact)_Facts[f1.Lid2];
            RayFact r1f2 = (RayFact)_Facts[f2.Lid1];
            RayFact r2f2 = (RayFact)_Facts[f2.Lid2];
    
            return (r1f1.Equivalent(r1f2) && r2f1.Equivalent(r2f2)) ;
        }
    }
    
    
    
    
    //TODO big work in progress Circle Wrapper
    
    /// TODO Work in Progress
    /// <summary>
    /// A Circle that is made out of a middle point, a plane and a radius  
    /// </summary>
    public class CircleFact : FactWrappedCRTP<CircleFact>
    {
       
        /// <summary> defining the middle point of the circle  </summary>
        public string Pid1;
        /// <summary>  defining the base point of the circle plane </summary>
        public string Pid2;
        /// <summary>  radius of the circle </summary>
        public float radius;
        /// <summary> normal vector of the plane </summary>
        public Vector3 normal;
       
        /// <summary> \copydoc Fact.Fact </summary>
        public CircleFact() : base()
        {
            this.normal = Vector3.zero;
            this.Pid1 = null;
            this.Pid2 = null;
            this.radius = 0;
        }
    
        /// <summary>
        /// Copies <paramref name="fact"/> by initiating new MMT %Fact.
        /// </summary>
        /// <param name="fact">Fact to be copied</param>
        /// <param name="old_to_new"><c>Dictionary</c> mapping <paramref name="fact"/>.<see cref="getDependentFactIds"/> in <paramref name="fact"/>.<see cref="Fact._Facts"/> to corresponding <see cref="Fact.Id"/> in <paramref name="organizer"/> </param>
        /// <param name="organizer">sets <see cref="_Facts"/></param>
        public CircleFact(CircleFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer)
        {
            init(old_to_new[fact.Pid1], old_to_new[fact.Pid2], fact.radius, fact.normal);
    
    1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
    
        /// <summary>
        /// Standard Constructor
        /// </summary>
        /// <param name="pid1">sets <see cref="Pid1"/></param>
        /// <param name="pid2">sets <see cref="Pid2"/></param>
        /// <param name="radius">sets <see cref="radius"/></param>
        /// <param name="normal">sets <see cref="normal"/></param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
        public CircleFact(string pid1, string pid2, float radius, Vector3 normal, FactOrganizer organizer) : base(organizer)
        {
            init(pid1, pid2, radius, normal);
        }
    
        /// <summary>
        /// Initiates <see cref="Pid1"/>, <see cref="Pid2"/>, <see cref="radius"/>,<see cref="dir1"/>,<see cref="dir2"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
        /// </summary>
        /// <param name="pid1">sets <see cref="Pid1"/></param>
        /// <param name="pid2">sets <see cref="Pid2"/></param>
        /// <param name="radius">sets <see cref="radius"/></param>
        /// <param name="normal">sets <see cref="normal"/></param>
        private void init(string pid1, string pid2, float radius, Vector3 normal)
        {
            this.Pid1 = pid1;
            this.Pid2 = pid2;
    
            PointFact pf1 = _Facts[pid1] as PointFact;
            PointFact pf2 = _Facts[pid2] as PointFact;
    
    
            this.radius = radius;
            this.normal = normal;
    
            MMTDeclaration mmtDecl;
            string p1URI = pf1.Id;
            string p2URI = pf2.Id;
    
            mmtDecl = generateCircleFactDeclaration(p1URI, p2URI, radius, normal);
    
            AddFactResponse.sendAdd(mmtDecl, out this._URI);
        }
    
        /// <summary>
        /// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_.
        /// </summary>
        /// <param name="Pid1">sets <see cref="Pid1"/></param>
        /// <param name="Pid2">sets <see cref="Pid2"/></param>
        /// <param name="radius">sets <see cref="radius"/></param>
        /// <param name="normal">sets <see cref="normal"/></param>
        /// <param name="backendURI">MMT URI</param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
        public CircleFact(string Pid1, string Pid2, float radius, Vector3 normal, string backendURI, FactOrganizer organizer) : base(organizer)
        {
            this.Pid1 = Pid1;
            this.Pid2 = Pid2;
    
            this.radius = radius;
            this.normal = normal;
     
            this._URI = backendURI;
            _ = this.Label;
        }
    
        /// <summary>
        /// parses the Circlefact response of the MMT-Server
        /// </summary>
        /// \copydoc Fact.parseFact(Scroll.ScrollFact) 
        public new static CircleFact parseFact(Scroll.ScrollFact fact)
        {
            string uri = fact.@ref.uri;
    
            OMA df = (OMA)((Scroll.ScrollSymbolFact)fact).df;
    
            if (df == null)
                return null;
    
            Scroll.ScrollSymbolFact casted_fact = (Scroll.ScrollSymbolFact)fact;
    
    
            OMA planeOMA = (OMA) ((OMA)casted_fact.df).arguments[0];
            OMA pointAOMA = (OMA) planeOMA.arguments[0];
    
            OMA n = (OMA) planeOMA.arguments[1];
            Vector3 normal = new Vector3(((OMF)n.arguments[0]).f, ((OMF)n.arguments[1]).f, ((OMF)n.arguments[2]).f);
    
    
            // get the mid point uri
            string parse_id_M = ParsingDictionary.MMTermToString(((OMA)casted_fact.df).arguments[1]);
            string M_uri = ParsingDictionary.parseTermsToId[parse_id_M];
    
            string parse_id_A = ParsingDictionary.MMTermToString(planeOMA.arguments[0]);
            string A_uri = ParsingDictionary.parseTermsToId[parse_id_A];
    
            // get the radius
            float radius = ((OMF)((OMA)casted_fact.df).arguments[2]).f;
    
    
            if (StageStatic.stage.factState.ContainsKey(M_uri)
             && StageStatic.stage.factState.ContainsKey(A_uri))
                  return new CircleFact(M_uri,A_uri,radius,normal, uri, StageStatic.stage.factState);
    
            else    //If dependent facts do not exist return null
                return null;
        }
    
        /// \copydoc Fact.generateLabel
        protected override string generateLabel()
        {
    
            return  "○"+_Facts[Pid1].Label;
        }
    
    
    
        /// <summary>
        /// Constructs struct for right-angled MMT %Fact <see cref="AddFactResponse"/>
        /// </summary>
        /// <param name="p1URI"> <see cref="Pid1"/></param>
        /// <param name="p2URI"> <see cref="Pid2"/></param>
        /// <param name="radius"> <see cref="radius"/></param>
        /// <returns>struct for <see cref="AddFactResponse"/></returns>
        private MMTDeclaration generateCircleFactDeclaration( string p1URI, string p2URI, float radius, Vector3 normal)
        {
            PointFact p1 = _Facts[p1URI] as PointFact;
            PointFact p2 = _Facts[p2URI] as PointFact;
    
            List<MMTTerm> normalArgs = new List<MMTTerm>
            {
                new OMF(normal.x),
                new OMF(normal.y),
                new OMF(normal.z)
            };
            OMA NormalVector = new OMA(new OMS(MMTURIs.Tuple), normalArgs);
    
    
    
            List<MMTTerm> planeArgs = new List<MMTTerm>
            {
                new OMS(p2URI),
                NormalVector //n
            };
    
            OMA CirclePlane = new OMA(new OMS(MMTURIs.pointNormalPlane), planeArgs);
            OMS middlePoint = new OMS(p1URI);
            OMF Radius = new OMF(radius);
    
            List<MMTTerm> outerArguments = new List<MMTTerm>
            {
               CirclePlane,
               middlePoint,
               Radius
            };
    
            //OMS constructor generates full URI
            // Do i need this here? doubt 
            MMTTerm tp = new OMS(MMTURIs.CircleType3d);
            MMTTerm df = new OMA(new OMS(MMTURIs.MkCircle3d), outerArguments);
    
            MMTSymbolDeclaration mmtDecl = new MMTSymbolDeclaration(this.Label, tp, df);
            AddFactResponse.sendAdd(mmtDecl, out this._URI);
    
    
            return mmtDecl;
        }
    
    
        /// \copydoc Fact.hasDependentFacts
        public override Boolean hasDependentFacts()
        {
            return true;
        }
    
        public Vector3 getNormal() 
        {
            return normal;
        }
    
    
        /// \copydoc Fact.getDependentFactIds
        public override string[] getDependentFactIds()
        {
            return new string[] { Pid1,Pid2 };
        }
    
        /// \copydoc Fact.instantiateDisplay(GameObject, Transform)
        public override GameObject instantiateDisplay(GameObject prefab, Transform transform)
        {
            var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform);
            obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid1].Label;
     
            // obj.transform.GetChild(1).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Lid2].Label;
    
            obj.GetComponent<FactWrapper>().fact = this;
            return obj;
        }
    
        /// \copydoc Fact.GetHashCode
        public override int GetHashCode()
        {
            return  this.Pid1.GetHashCode() ^ this.Pid2.GetHashCode() ;
        }
    
        /// \copydoc Fact.Equivalent(Fact, Fact)
        protected override bool EquivalentWrapped(CircleFact f1, CircleFact f2)
        {
            if ( f1.Pid1 == f2.Pid1 && f1.normal == f2.normal && f1.radius == f2.radius)
                return true;
    
            PointFact p1f1 = (PointFact)_Facts[f1.Pid1];
            PointFact p1f2 = (PointFact)_Facts[f2.Pid1];
    
            return (p1f1.Equivalent(p1f2) && f1.normal == f2.normal && f1.radius == f2.radius);
        }
    }
    
    
    /// <summary>
    /// A <see cref="PointFact"/> on a <see cref="CircleFact"/>
    /// </summary>
    public class OnCircleFact : FactWrappedCRTP<OnCircleFact>
    {
        /// <summary> the point on the circle  </summary>
        public string Pid;
        /// <summary> the circle, which the point is on  </summary>
        public string Cid;
    
        /// <summary> \copydoc Fact.Fact </summary>
        public OnCircleFact() : base()
        {
            this.Pid = null;
            this.Cid = null;
        }
    
        /// <summary>
        /// Copies <paramref name="fact"/> by initiating new MMT %Fact.
        /// </summary>
        /// <param name="fact">Fact to be copied</param>
        /// <param name="old_to_new"><c>Dictionary</c> mapping <paramref name="fact"/>.<see cref="getDependentFactIds"/> in <paramref name="fact"/>.<see cref="Fact._Facts"/> to corresponding <see cref="Fact.Id"/> in <paramref name="organizer"/> </param>
        /// <param name="organizer">sets <see cref="_Facts"/></param>
        public OnCircleFact(OnCircleFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer)
        {
            init(old_to_new[fact.Pid], old_to_new[fact.Cid]);
        }
    
        /// <summary>
        /// Standard Constructor
        /// </summary>
        /// <param name="pid">sets <see cref="Pid"/></param>
        /// <param name="cid">sets <see cref="Cid"/></param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
        public OnCircleFact(string pid, string cid, FactOrganizer organizer) : base(organizer)
        {
            init(pid, cid);
        }
    
        /// <summary>
        /// Initiates <see cref="Pid"/>, <see cref="Rid"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
        /// </summary>
        /// <param name="pid">sets <see cref="Pid"/></param>
        /// <param name="cid">sets <see cref="Cid"/></param>
        private void init(string pid, string cid)
        {
            this.Pid = pid;
            this.Cid = cid;
    
            PointFact pf = _Facts[pid] as PointFact;
            CircleFact cf = _Facts[cid] as CircleFact;
            string pURI = pf.Id;
            string cURI = cf.Id;
    
            List<MMTTerm> innerArguments = new List<MMTTerm>
            {
                new OMS(cURI),
                new OMS(pURI)
            };
    
            List<MMTTerm> outerArguments = new List<MMTTerm>
            {
                new OMA(new OMS(MMTURIs.OnCircle), innerArguments)
            };
    
            //OMS constructor generates full URI
            MMTTerm tp = new OMA(new OMS(MMTURIs.Ded), outerArguments);
            MMTTerm df = null;
    
            MMTSymbolDeclaration mmtDecl = new MMTSymbolDeclaration(this.Label, tp, df);
            AddFactResponse.sendAdd(mmtDecl, out this._URI);
        }
    
        /// <summary>
        /// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_.
        /// </summary>
        /// <param name="pid">sets <see cref="Pid"/></param>
        /// <param name="cid">sets <see cref="Cid"/></param>
        /// <param name="uri">MMT URI</param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
        public OnCircleFact(string pid, string cid, string uri, FactOrganizer organizer) : base(organizer)
        {
            this.Pid = pid;
            this.Cid = cid;
            this._URI = uri;
            _ = this.Label;
        }
    
        /// \copydoc Fact.parseFact(Scroll.ScrollFact)
        public new static OnCircleFact parseFact(Scroll.ScrollFact fact)
        {
            string uri = fact.@ref.uri;
    
            OMA tp = (OMA)((Scroll.ScrollSymbolFact)fact).tp;
            if (tp == null)
                return null;
    
            string circleUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[0]).uri;
            string pointUri = ((OMS)((OMA)((OMA)((Scroll.ScrollSymbolFact)fact).tp).arguments[0]).arguments[1]).uri;
           
            if (StageStatic.stage.factState.ContainsKey(pointUri)
             && StageStatic.stage.factState.ContainsKey(circleUri))
                return new OnCircleFact(pointUri, circleUri, uri, StageStatic.stage.factState);
    
            //If dependent facts do not exist return null
            else
                return null;
        }
    
        /// \copydoc Fact.generateLabel
        protected override string generateLabel()
        {
            return _Facts[Pid].Label + "∈" + _Facts[Cid].Label;
        }
    
        /// \copydoc Fact.hasDependentFacts
        public override Boolean hasDependentFacts()
        {
            return true;
        }
    
        /// \copydoc Fact.getDependentFactIds
        public override string[] getDependentFactIds()
        {
            return new string[] { Pid, Cid };
        }
    
        /// \copydoc Fact.instantiateDisplay(GameObject, Transform)
        public override GameObject instantiateDisplay(GameObject prefab, Transform transform)
        {
            var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform);
            obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = _Facts[this.Pid].Label + "∈" + _Facts[this.Cid].Label;
            obj.GetComponent<FactWrapper>().fact = this;
    
            return obj;
        }
    
        /// \copydoc Fact.GetHashCode
        public override int GetHashCode()