using Newtonsoft.Json; using REST_JSON_API; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; /// <summary> /// Point in 3D Space /// </summary> public class SquareFact : FactWrappedCRTP<SquareFact> { //used points public string PidA, PidB, PidC; public Vector3 A, B, C, D; public PointFact GetA {get => (PointFact)FactRecorder.AllFacts[PidA];} public PointFact GetB {get => (PointFact)FactRecorder.AllFacts[PidB];} public PointFact GetC {get => (PointFact)FactRecorder.AllFacts[PidC];} protected void calculate_vectors(){ A = ((PointFact)FactRecorder.AllFacts[PidA]).Point + Vector3.zero; B = ((PointFact)FactRecorder.AllFacts[PidB]).Point + Vector3.zero; C = ((PointFact)FactRecorder.AllFacts[PidC]).Point + Vector3.zero; D = (A - B) + C; Vector3 scale = new Vector3(Vector3.Distance(B, C), Vector3.Distance(A, B), 1.0F); LocalScale = scale * 0.5F; Position = B + 0.5F*((A-B) + (C-B)); //Vector3 normal = Vector3.Cross((A-B), (C-B)); s /* Vector3 arbitary_not_normal = normal == Vector3.forward ? Vector3.right : Vector3.forward; Vector3 forward = Vector3.Cross(arbitary_not_normal, normal); Rotation = Quaternion.LookRotation(forward, normal); */ /* //angle rotation around y axis Vector3 AB = A - B; Vector3 BC = C - B; // Calculate the angle between AB and BC around the Y-axis float yAxisRotation = Mathf.Atan2(AB.z, AB.x) * Mathf.Rad2Deg; float xAxisRotation = Mathf.Atan2(BC.z, BC.y) * Mathf.Rad2Deg; float zAxisRotation = Mathf.Atan2(AB.y, AB.x) * Mathf.Rad2Deg; Vector3 rotationVector = new Vector3(0, yAxisRotation, 0); */ //angle rotation around y axis /* float distABx = (A.x - B.x); float distABy = (A.y - B.y); float distABz = (A.z - B.z); float distBCx = (C.x - B.x); float distBCy = (C.y - B.y); float distBCz = (C.z - B.z); float ERROR = 1E-5F; float xAxisRotation = Mathf.Rad2Deg* - Mathf.Atan(distBCy / distBCz); float yAxisRotation = -(Mathf.Abs((distABx - distABz)) < ERROR ? 45.0F : Mathf.Rad2Deg*Mathf.Atan(distABx / distABz)); float zAxisRotation = Mathf.Rad2Deg*Mathf.Atan(distABy / distABx); Vector3 rotationVector = new Vector3(xAxisRotation, yAxisRotation, zAxisRotation); Rotation = Quaternion.Euler(rotationVector); */ /* Vector3 forward = (from + to).normalized; if (up.sqrMagnitude < Math3d.vectorPrecission) { //Angle is 180° (or 0°) Vector3 from_arbitary = from.normalized == Vector3.forward ? Vector3.right : Vector3.forward; up = Vector3.Cross(from_arbitary, to); forward = Vector3.Cross(up, to); } Vector3 upy0 = new Vector3(up.x, 0, up.z); Rotation = Quaternion.LookRotation(upy0, up); Vector3 from = (A - B).normalized; Vector3 to = (C - B).normalized; Vector3 up = Vector3.Cross(from, to); Rotation = Quaternion.LookRotation(up, new Vector3(0.0F, 0.0F, 1.0F)); Vector3 normal = Vector3.Cross((A-B), (B-C)); lookObject.transform.position = normal + Position; */ Rotation = Quaternion.LookRotation(Vector3.Cross((A-B), (C-B)), Vector3.up); //Rotation = Quaternion.LookRotation(forward, new Vector3(1.0F, 0.0F, 0.0F)); } public SquareFact() : base(){ this.PidA = null; this.PidB = null; this.PidC = null; } [JsonConstructor] public SquareFact( string PidA, string PidB, string PidC) : base() { this.PidA = PidA; this.PidB = PidB; this.PidC = PidC; calculate_vectors(); } /// <summary> /// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_. /// <see cref="Normal"/> set to <c>Vector3.up</c> /// </summary> /// <param name="Point">sets <see cref="Point"/></param> /// <param name="ServerDefinition">MMT URI as OMS</param> public SquareFact(string PidA, string PidB, string PidC, SOMDoc ServerDefinition) : base() { this.PidA = PidA; this.PidB = PidB; this.PidC = PidC; this.ServerDefinition = ServerDefinition; calculate_vectors(); } /// \copydoc Fact.parseFact(ScrollFact) public new static IEnumerator parseFact(List<Fact> ret, MMTFact fact) { if (((MMTGeneralFact)fact).defines is not OMA df) yield break; OMS pointA, pointB, pointC; pointA = (OMS)df.arguments[0]; pointB = (OMS)df.arguments[1]; pointC = (OMS)df.arguments[2]; string PidA = pointA.uri; string PidB = pointB.uri; string PidC = pointC.uri; ret.Add(new SquareFact(PidA, PidB, PidC, fact.@ref)); //ParsingDictionary.parseTermsToId.TryAdd(defines.ToString(), fact.@ref.uri); //ret.Add(new PointFact(SOMDoc.MakeVector3(defines), fact.@ref)); } /// \copydoc Fact.hasDependentFacts public override bool HasDependentFacts => true; /// \copydoc Fact.getDependentFactIds protected override string[] GetDependentFactIds() => new string[] { PidA, PidB, PidC}; /// \copydoc Fact.GetHashCode /* public override int GetHashCode() => this.Point.GetHashCode(); */ protected override void RecalculateTransform() { calculate_vectors(); } /// \copydoc Fact.Equivalent(Fact, Fact) protected override bool EquivalentWrapped(SquareFact f1, SquareFact f2){ return ( Math3d.IsApproximatelyEqual(f1.A, f2.A) && Math3d.IsApproximatelyEqual(f1.B, f2.B) && Math3d.IsApproximatelyEqual(f1.C, f2.C) && Math3d.IsApproximatelyEqual(f1.D, f2.D) ); } protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new){ return new SquareFact(this.PidA, this.PidB, this.PidC); } public override MMTFact MakeMMTDeclaration() { SOMDoc tp = new OMS(MMTConstants.SquareType); return new MMTGeneralFact(_LastLabel, tp, Defines()); } public override SOMDoc Defines() => new OMA( new OMS(MMTConstants.SquareCons), new[] { new OMS(PidA), new OMS(PidB), new OMS(PidC), } ); }