Newer
Older
using System;
using System.Collections.Generic;
Marco Zimmer
committed
using JsonSubTypes;
using System.Drawing;
public static class ParsingDictionary
//TODO? get rid of this, use reflection? instead, if possible
//TODO: docu
public static Dictionary<string, Func<MMTFact, List<Fact>>> parseFactDictionary = new() {
PointFact.parseFact },
LineFact.parseFact },
AngleFact.parseFact },
RightAngleFact.parseFact },
RayFact.parseFact },
RayFact.parseFact },
OnLineFact.parseFact },
{ MMTConstants.ParallelLine,
ParallelLineFact.parseFact },
{ MMTConstants.CircleType3d,
CircleFact.parseFact },
OnCircleFact.parseFact },
{ MMTConstants.AnglePlaneLine,
AngleCircleLineFact.parseFact },
{ MMTConstants.RadiusCircleMetric,
RadiusFact.parseFact },
AreaCircleFact.parseFact },
{ MMTConstants.OrthoCircleLine,
OrthogonalCircleLineFact.parseFact },
ConeVolumeFact.parseFact },
{ MMTConstants.TruncatedVolumeCone,
TruncatedConeVolumeFact.parseFact },
{ MMTConstants.CylinderVolume,
CylinderVolumeFact.parseFact },
TestFact.parseFact },
{ MMTConstants.EqualityCircles,
EqualCirclesFact.parseFact },
{ MMTConstants.UnEqualityCircles,
MaZiFAU
committed
{ MMTConstants.CreateWall,
QuadFact.parseFact },
MaZiFAU
committed
{ MMTConstants.ListType,
DynamicListFact.parseFact },
MaZiFAU
committed
{ MMTConstants.Product,
DynamicTupleFact.parseFact },
MaZiFAU
committed
{ MMTConstants.FunctionFact,
FunctionFact.parseFact },
// TODO: get rid of this
public static Dictionary<string, string> parseTermsToId = new();
/// <summary>
/// %Fact representation of Unity; mostly mirrors Facts of MMT.
/// </summary>
Marco Zimmer
committed
[JsonConverter(typeof(JsonSubtypes), "s_type")]
[JsonSubtypes.KnownSubType(typeof(PointFact), nameof(PointFact))]
[JsonSubtypes.KnownSubType(typeof(LineFact), nameof(LineFact))]
[JsonSubtypes.KnownSubType(typeof(RayFact), nameof(RayFact))]
[JsonSubtypes.KnownSubType(typeof(OnLineFact), nameof(OnLineFact))]
[JsonSubtypes.KnownSubType(typeof(AngleFact), nameof(AngleFact))]
[JsonSubtypes.KnownSubType(typeof(CircleFact), nameof(CircleFact))]
[JsonSubtypes.KnownSubType(typeof(ParallelLineFact), nameof(ParallelLineFact))]
[JsonSubtypes.KnownSubType(typeof(OnCircleFact), nameof(OnCircleFact))]
[JsonSubtypes.KnownSubType(typeof(AngleCircleLineFact), nameof(AngleCircleLineFact))]
[JsonSubtypes.KnownSubType(typeof(OrthogonalCircleLineFact), nameof(OrthogonalCircleLineFact))]
[JsonSubtypes.KnownSubType(typeof(AreaCircleFact), nameof(AreaCircleFact))]
[JsonSubtypes.KnownSubType(typeof(RadiusFact), nameof(RadiusFact))]
[JsonSubtypes.KnownSubType(typeof(ConeVolumeFact), nameof(ConeVolumeFact))]
[JsonSubtypes.KnownSubType(typeof(TruncatedConeVolumeFact), nameof(TruncatedConeVolumeFact))]
[JsonSubtypes.KnownSubType(typeof(RightAngleFact), nameof(RightAngleFact))]
[JsonSubtypes.KnownSubType(typeof(CylinderVolumeFact), nameof(CylinderVolumeFact))]
[JsonSubtypes.KnownSubType(typeof(TestFact), nameof(TestFact))]
[JsonSubtypes.KnownSubType(typeof(EqualCirclesFact), nameof(EqualCirclesFact))]
[JsonSubtypes.KnownSubType(typeof(UnEqualCirclesFact), nameof(UnEqualCirclesFact))]
[JsonSubtypes.KnownSubType(typeof(FunctionFact), nameof(FunctionFact))]
[JsonSubtypes.KnownSubType(typeof(FunctionCallFact), nameof(FunctionCallFact))]
[JsonSubtypes.KnownSubType(typeof(ListFact), nameof(ListFact))]
[JsonSubtypes.KnownSubType(typeof(DynamicListFact), nameof(DynamicListFact))]
[JsonSubtypes.KnownSubType(typeof(DynamicTupleFact), nameof(DynamicTupleFact))]
[JsonSubtypes.KnownSubType(typeof(QuadFact), nameof(QuadFact))]
MaZiFAU
committed
[JsonSubtypes.KnownSubType(typeof(RealLitFact), nameof(RealLitFact))]
/// <summary>
/// Reference to <c>GameObject</c> that represents this Fact in the GameWorld.
/// </summary>
/// <summary>
/// Collection of <c>Type</c>s of *all* available <see cref="Fact"/>s to choose from.
/// </summary>
[JsonIgnore]
public static readonly Type[] Types = TypeExtensions<Fact>.UAssemblyInheritenceTypes;
Marco Zimmer
committed
/// <value>
/// [ClassName] for JSON de-/serialization.
/// Automatically set in <see cref="Fact()"/> for <b>NON-Generiy-Types</b>!
/// Also add JsonSubtypes.KnownSubType decorator for deserialization to Fact!
Marco Zimmer
committed
/// </value>
protected string s_type;
Marco Zimmer
committed
MaZiFAU
committed
/// <returns><see langword="true"/> if Fact depends on other \ref Fact "Facts"; equivalent to <see cref="getDependentFactIds"/> returns non empty array</returns>
[JsonIgnore]
public virtual bool HasDependentFacts => DependentFactIds.Length > 0;
MaZiFAU
committed
/// <returns> array of Fact <see cref="Id"> Ids </see> on which this Fact depends.</returns>
/// <example><see cref="AngleFact"/> needs 3 <see cref="PointFact"/>s to be defined.</example>
public string[] DependentFactIds => _DependentFactIds ??= GetDependentFactIds();
MaZiFAU
committed
private string[] _DependentFactIds;
/// <returns> array of Fact <see cref="Id"> Ids </see> on which this Fact depends.</returns>
/// <example><see cref="AngleFact"/> needs 3 <see cref="PointFact"/>s to be defined.</example>
protected abstract string[] GetDependentFactIds();
MaZiFAU
committed
/// <value>Unique Id. e.g.: MMT URI</value>
//while (FetchURICoroutine.MoveNext()) ; //active wait for server
return ServerDefinition.ToString();
//private IEnumerator FetchURICoroutine = IEnumeratorExtensions.yield_break;
/// <summary>AST which the Server understands. e.g.: OMS(MMT URI)</summary>
public SOMDoc ServerDefinition { get; protected set; }
Marco Zimmer
committed
/// <value>
/// <c>get</c> initiates and subsequently updates a human readable name. <remarks>Should be called once a constructor call to be initiated.</remarks>
/// <c>set</c> calls <see cref="rename(string)"/>
/// </value>
public string Label
{
get
{ // in case of renamed dependables
return _Facts == null // JsonSerialization toggle (_Facts.GetNumberOfFacts() == 0 && this is not PointFact) // JsonSerialization toggle && allow first (Point)Fact to be created
|| (hasCustomLabel && _CustomLabel != null)
Marco Zimmer
committed
? _CustomLabel
: generateLabel();
Marco Zimmer
committed
}
set
{
if (_Facts == null) // JsonSerialization toggle)
{
_CustomLabel = value;
LabelId = -LabelId;
return;
}
/// <value>
/// Is true if Fact has a custom <see cref="Label"/> which is not <c>null</c> or <c>""</c>.
/// </value>
public bool hasCustomLabel => LabelId < 0;
/// <summary>
/// Stores custom <see cref="Label"/> if set.
/// </summary>
Marco Zimmer
committed
protected string _CustomLabel = null;
/// <summary>
/// Counter to organize auto generated <see cref="Label"/>.
/// Set to negative, if custom \ref Label is assigned.
/// </summary>
// property for JSON to set AFTER Label => declare AFTER Label
public int LabelId { get; set; }
/// <summary>
/// Reference to <see cref="FactRecorder"/> in which this Fact and all its <see cref="getDependentFactIds">depending Facts</see> are beeing organized.
/// </summary>
/// <remarks>Now only relevant for Lables</remarks>
MaZiFAU
committed
[JsonIgnore]
public Vector3 Position
{
get
{
if (ForceRecalculateTransform)
RecalculateTransform();
return _Position;
}
protected set
{
ForceRecalculateTransform = false;
_Position = value;
}
}
[JsonIgnore]
public Quaternion Rotation
{
get
{
if (ForceRecalculateTransform)
RecalculateTransform();
return _Rotation;
}
protected set
{
ForceRecalculateTransform = false;
_Rotation = value;
}
}
private Quaternion _Rotation = Quaternion.identity;
public Vector3 LocalScale
{
get
{
if (ForceRecalculateTransform)
RecalculateTransform();
return _LocalScale;
}
protected set
{
ForceRecalculateTransform = false;
_LocalScale = value;
}
}
/// <summary>
/// Only being used by [JsonReader](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonReader.htm) to initiate empty \ref Fact "Facts".
MaZiFAU
committed
/// <seealso cref="SOMDocManager"/>
/// </summary>
protected Fact()
{
s_type = this.GetType().Name;
/// <summary>
/// Standard base-constructor.
/// </summary>
/// <param name="organizer"><see cref="_Facts"/></param>
{
this._Facts = organizer;
}
/// <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"><see cref="_Facts"/></param>
public Fact ReInitializeMe(Dictionary<string, string> old_to_new, FactRecorder organizer)
ret.LabelId = this.LabelId;
if (ret.hasCustomLabel)
ret._CustomLabel = this.Label;
return ret;
protected abstract Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactRecorder organizer);
/// <summary>
/// Assignes a custom <see cref="Label"/>, if <paramref name="newLabel"/> is not yet taken;
/// or clears custom <see cref="Label"/>.
/// </summary>
/// <param name="newLabel">To be new <see cref="Label"/>. To reset to auto-generation set to <c>null</c> or <c>""</c>.</param>
/// <returns></returns>
//TODO: notify about updated dependable Labelnames for UI
//TODO: check for colissions with not yet generated names
public bool rename(string newLabel)
// returns true if succeded
{
if (string.IsNullOrEmpty(newLabel) && _Facts.GetNumberOfFacts() != 0)
// switch back to autogenerated
{
generateLabel();
_CustomLabel = null;
return true;
}
else
// set CustomLabel if available
{
if (_Facts.ContainsLabel(newLabel))
return false;
freeAutoLabel();
_CustomLabel = newLabel;
Marco Zimmer
committed
public abstract MMTFact MakeMMTDeclaration();
/// <summary>
/// Frees ressources e.g. <see cref="Label"/> and will eventually delete %Fact Server-Side in far-near future when feature is supported.
/// </summary>
Marco Zimmer
committed
Marco Zimmer
committed
if (CommunicationEvents.VerboseURI)
Marco Zimmer
committed
Debug.Log("Server removed Fact:\n" + this.Id);
/// <summary>
/// Compares \ref Fact "this" against <paramref name="f2"/>.
/// </summary>
/// <param name="f2">Fact to compare to</param>
/// <returns><c>true</c> if <paramref name="f2"/> is semantical very similar to \ref Fact "this"</returns>
Marco Zimmer
committed
public abstract bool Equivalent(Fact f2);
/// <summary>
/// Compares <paramref name="f1"/> against <paramref name="f2"/>.
/// </summary>
/// <param name="f1">Fact to compare to</param>
/// <param name="f2">Fact to compare to</param>
/// <returns><c>true</c> if <paramref name="f2"/> is semantical very similar to <paramref name="f1"/></returns>
Marco Zimmer
committed
public abstract bool Equivalent(Fact f1, Fact f2);
/// <summary>
/// canonical
/// </summary>
/// <returns>unique-ish Hash</returns>
=> DependentFactIds
.Select(id => id.GetHashCode())
.Aggregate((hash1, hash2) => hash1 ^ hash2);
/// <summary>
/// auto-generates <see cref="Label"/> using generation variable(s) e.g. <see cref="LabelId"/>;
/// if custom <see cref="Label"/> is set, tries to restore original generated <see cref="Label"/> **without** resetting <see cref="_CustomLabel"/>. If original <see cref="Label"/> is already taken, a new one will be generated.
/// </summary>
/// <returns>auto-generated <see cref="Label"/></returns>
Marco Zimmer
committed
protected virtual string generateLabel()
{
LabelId = _Facts.UnusedLabelIds.Remove(-LabelId) ? -LabelId : 0;
Marco Zimmer
committed
if (LabelId == 0)
if (_Facts.UnusedLabelIds.Count == 0)
LabelId = ++_Facts.MaxLabelId;
Marco Zimmer
committed
else
{
LabelId = _Facts.UnusedLabelIds.Min;
_Facts.UnusedLabelIds.Remove(LabelId);
Marco Zimmer
committed
}
return ((char)(64 + LabelId)).ToString();
}
/// <summary>
/// Parses <see cref="MMTFact"/> to actual Fact
/// </summary>
/// <param name="fact">instance to be parsed</param>
/// <returns>parsed Fact</returns>
public static List<Fact> parseFact(MMTFact fact)
/// <summary>
/// Tells <see cref="_Facts"/> that \ref Fact "this" no longer uses auto-generated <see cref="Label"/>, but remembers current generation variable(s).
/// </summary>
// TODO? only get _Fact to freeLabel/
public /*protected internal*/ void freeAutoLabel()
{
if (LabelId > 0)
_Facts.UnusedLabelIds.Add(LabelId);
// store Label for name-persistance
Marco Zimmer
committed
LabelId = -LabelId;
}
protected SOMDoc SendToMMT()
=> ServerDefinition = SendToMMT(MakeMMTDeclaration());
/// <summary>
///
/// </summary>
/// <remarks>Asynchron version has proofen inefficent, since <see cref="Fact.Id"/> is usually called in close proximity.</remarks>
// Asynchron version in comments
public static SOMDoc SendToMMT(MMTFact mmtDecl)
//GlobalBehaviour.Instance.StartCoroutine(
// FetchURICoroutine =
MaZiFAU
committed
JsonConvert.SerializeObject(mmtDecl)
//void _SendURICallback(MMTDeclaration mmtDecl, string uri)
//{
// _URI = uri;
if (mmtDecl is MMTGeneralFact mMTSymbol && mMTSymbol.defines != null)
ParsingDictionary.parseTermsToId[mMTSymbol.defines.ToString()] = uri;// _URI;
//}
if (uri == null)
{
Debug.LogWarning("Server rejected MMTFact; Fallback engaged.");
return mmtDecl is MMTGeneralFact general ? general.defines
: mmtDecl is MMTValueFact value ? value.lhs
: throw new NotSupportedException($"{mmtDecl.GetType()}");
}
else
return new OMS(uri);
static string _SendAdd(string path, string body)//, Action<string> uriCallback)
{
if (!CommunicationEvents.ServerRunning)
{
Debug.LogWarning("Server not running");
//uriCallback(null);
return null; // yield break;
}
if (CommunicationEvents.VerboseURI)
Debug.Log("Sending to Server:\n" + body);
//Put constructor parses stringbody to byteArray internally (goofy workaround)
using UnityWebRequest www = UnityWebRequest.Put(path, body);
www.method = UnityWebRequest.kHttpVerbPOST;
www.SetRequestHeader("Content-Type", "application/json");
www.timeout = 1;
//yield return
UnityWebRequestAsyncOperation web =
www.SendWebRequest();
while (!web.isDone) ;
if (www.result == UnityWebRequest.Result.ConnectionError
|| www.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogWarning(www.error);
//uriCallback(null);
return null; // yield break;
while (!www.downloadHandler.isDone)
//yield return null
;
FactReference res = JsonUtility.FromJson<FactReference>(www.downloadHandler.text);
if (CommunicationEvents.VerboseURI)
Debug.Log("Server added Fact:\n" + res.uri);
//uriCallback(res.uri);
return res.uri; // yield break;
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
private static uint bypasscc = 0;
public static List<Fact> MakeFact(object payload, SOMDoc ServerDefinition, FactRecorder organizer, bool BypassServer)
{
Type type = payload.GetType();
if (BypassServer) bypasscc++;
SOMDoc BypassURI = new OMS($"{bypasscc}_{ServerDefinition}");
if (payload is Fact fact)
return new() { fact };
else
if (payload is float f)
return new() { BypassServer
? new RealLitFact(f, BypassURI, organizer)
: new RealLitFact(f, organizer) };
else
if (payload is Vector3 point)
return new() { BypassServer
? new PointFact(point, BypassURI, organizer)
: new PointFact(point, Vector3.up, organizer) };
else
if (FuncExtensions.IsFuncType(type, out _))
return new() { BypassServer
? new FunctionFact(ServerDefinition, BypassURI, organizer)
: new FunctionFact(ServerDefinition, organizer)};
else
if (TupleExtensions.IsTupleType(type, out _))
return BypassServer
? DynamicTupleFact.MMTFactory(payload, ServerDefinition, SOMDoc.SOMDocType(type), organizer, BypassURI)
: DynamicTupleFact.MMTFactory(payload, ServerDefinition, SOMDoc.SOMDocType(type), organizer);
else
if (type.IsGenericType
&& type.GetGenericTypeDefinition() == typeof(List<>))
return BypassServer
? DynamicListFact.MMTFactory((List<dynamic>)payload, ServerDefinition, SOMDoc.SOMDocType(type), organizer, BypassURI)
: DynamicListFact.MMTFactory((List<dynamic>)payload, ServerDefinition, SOMDoc.SOMDocType(type), organizer);
else
throw new NotImplementedException($"For Type {type}.");
}
protected class ApproximationComparer : EqualityComparer<object>
{
public override bool Equals(object x, object y)
{
if (x.Equals(y))
return true;
if (x.GetType() != y.GetType())
return false;
if (x is float fx)
return Mathf.Approximately(fx, (float)y);
if (x is Vector3 vx)
return Math3d.IsApproximatelyEqual(vx, (Vector3)y);
return false;
}
public override int GetHashCode(object obj)
{
if (obj is float)
return typeof(float).GetHashCode();
if (obj is Vector3)
return typeof(Vector3).GetHashCode();
return obj.GetHashCode();
}
}
}
public interface IUnpackable
{
public abstract List<Fact> UnpackMe(bool BypassServer);
/// <summary>
/// Implements CRTP for <see cref="Fact"/>; Escalates constructors;
/// </summary>
/// <typeparam name="T">class, which inherits from FactWrappedCRTP</typeparam>
public abstract class FactWrappedCRTP<T> : Fact where T : FactWrappedCRTP<T>
/// <summary>\copydoc Fact.Fact()</summary>
protected FactWrappedCRTP() : base() { }
/// <summary>\copydoc Fact.Fact(FactOrganizer)</summary>
protected FactWrappedCRTP(FactRecorder organizer) : base(organizer) { }
/// \copydoc Fact.Equivalent(Fact)
Marco Zimmer
committed
public override bool Equivalent(Fact f2)
Marco Zimmer
committed
/// \copydoc Fact.Equivalent(Fact, Fact)
Marco Zimmer
committed
public override bool Equivalent(Fact f1, Fact f2)
=> f1.GetType() == f2.GetType() && EquivalentWrapped((T)f1, (T)f2);
Marco Zimmer
committed
/// <summary>CRTP step of <see cref="Equivalent(Fact)"/> and <see cref="Equivalent(Fact, Fact)"/></summary>
Marco Zimmer
committed
protected abstract bool EquivalentWrapped(T f1, T f2);
=> f1.DependentFactIds
.Zip(f2.DependentFactIds,
|| FactRecorder.AllFacts[id1].Equivalent(FactRecorder.AllFacts[id2])
Marco Zimmer
committed
}
/// <summary>
/// Point in 3D Space
/// </summary>
Marco Zimmer
committed
public class PointFact : FactWrappedCRTP<PointFact>
/// <summary> Position </summary>
/// <summary> Orientation for <see cref="Fact.WorldRepresentation"/> </summary>
MaZiFAU
committed
[JsonProperty]
private Vector3 Normal;
/// <summary> \copydoc Fact.Fact </summary>
public PointFact() : base()
{
this.Point = Vector3.zero;
MaZiFAU
committed
this.Normal = Vector3.up;
/// <summary>
/// Standard Constructor:
/// Initiates <see cref="Point"/>, <see cref="Normal"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
/// </summary>
/// <param name="P">sets <see cref="Point"/></param>
/// <param name="N">sets <see cref="Normal"/></param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
public PointFact(Vector3 P, Vector3 N, FactRecorder organizer) : base(organizer)
this.Point = P;
this.Normal = N;
MaZiFAU
committed
{ // Rotation
Vector3 notNormal = Vector3.forward != Normal ? Vector3.forward : Vector3.up;
Rotation = Quaternion.LookRotation(
Vector3.Cross(Normal, notNormal),
Normal
);
}
/// <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="uri">MMT URI</param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
public PointFact(Vector3 point, SOMDoc _ServerDefinition, FactRecorder organizer) : base(organizer)
this.Point = point;
this.Normal = Vector3.up;
this.ServerDefinition = _ServerDefinition;
/// \copydoc Fact.parseFact(ScrollFact)
public new static List<Fact> parseFact(MMTFact fact)
if (((MMTGeneralFact)fact).defines is not OMA defines)
return new();
ParsingDictionary.parseTermsToId.TryAdd(defines.ToString(), fact.@ref.uri);
return new() { new PointFact(point, fact.@ref, StageStatic.stage.factState) };
/// \copydoc Fact.hasDependentFacts
MaZiFAU
committed
public override bool HasDependentFacts => false;
/// \copydoc Fact.getDependentFactIds
protected override string[] GetDependentFactIds()
=> new string[] { };
/// \copydoc Fact.GetHashCode
Marco Zimmer
committed
public override int GetHashCode()
MaZiFAU
committed
=> this.Point.GetHashCode();
/// \copydoc Fact.Equivalent(Fact, Fact)
Marco Zimmer
committed
protected override bool EquivalentWrapped(PointFact f1, PointFact f2)
=> Math3d.IsApproximatelyEqual(f1.Point, f2.Point);
protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactRecorder organizer)
=> new PointFact(this.Point, this.Normal, organizer);
public override MMTFact MakeMMTDeclaration()
SOMDoc tp = new OMS(MMTConstants.Point);
new OMS(MMTConstants.Tuple),
new OMF(Point.x),
new OMF(Point.y),
new OMF(Point.z),
}
);
return new MMTGeneralFact(Label, tp, df);
/// <summary>
/// A <see cref="PointFact"/> on a <see cref="AbstractLineFact"/>
/// </summary>
Marco Zimmer
committed
public class OnLineFact : FactWrappedCRTP<OnLineFact>
{
MaZiFAU
committed
/// <summary> <see cref="PointFact"/>.<see cref="Fact.Id">Id</see> </summary>
public string Pid;
[JsonIgnore]
public PointFact Point { get => (PointFact)FactRecorder.AllFacts[Pid]; }
MaZiFAU
committed
/// <summary> <see cref="AbstractLineFact"/>.<see cref="Fact.Id">Id</see> </summary>
public string Rid;
[JsonIgnore]
public AbstractLineFact Ray { get => (AbstractLineFact)FactRecorder.AllFacts[Rid]; }
/// <summary> \copydoc Fact.Fact </summary>
public OnLineFact() : base()
{
this.Pid = null;
this.Rid = null;
}
/// <summary>
/// Standard Constructor:
/// 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="rid">sets <see cref="Rid"/></param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
public OnLineFact(string pid, string rid, FactRecorder organizer) : base(organizer)
{
this.Pid = pid;
this.Rid = rid;
}
MaZiFAU
committed
Vector3 up = Point.Rotation * Vector3.up;
Vector3 forward = Ray.Dir;
if (Math3d.IsApproximatelyEqual(up, forward))
{
Vector3 arbitary = Math3d.IsApproximatelyEqual(forward, Vector3.forward)
? Vector3.right
: Vector3.forward;
up = Vector3.Cross(arbitary, forward);
}
Rotation = Quaternion.LookRotation(forward, up);
}
}
/// <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="rid">sets <see cref="Rid"/></param>
/// <param name="uri">MMT URI</param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
public OnLineFact(string pid, string rid, SOMDoc _ServerDefinition, FactRecorder organizer) : base(organizer)
this.Pid = pid;
this.Rid = rid;
this.ServerDefinition = _ServerDefinition;
}
/// \copydoc Fact.parseFact(ScrollFact)
public new static List<Fact> parseFact(MMTFact fact)
{
string pointUri = ((OMS)((OMA)((OMA)((MMTGeneralFact)fact).type).arguments[0]).arguments[1]).uri;
string lineUri = ((OMA)((OMA)((MMTGeneralFact)fact).type).arguments[0]).arguments[0] is OMS
? ((OMS)((OMA)((OMA)((MMTGeneralFact)fact).type).arguments[0]).arguments[0]).uri
// case when line Uri has a projl on the line Argument
: ((OMS)((OMA)((OMA)((OMA)((MMTGeneralFact)fact).type).arguments[0]).arguments[0]).arguments[0]).uri;
if (!FactRecorder.AllFacts.ContainsKey(pointUri)
|| !FactRecorder.AllFacts.ContainsKey(lineUri))
return new();
return new() { new OnLineFact(pointUri, lineUri, fact.@ref, StageStatic.stage.factState) };
}
/// \copydoc Fact.generateLabel
protected override string generateLabel()
/// \copydoc Fact.hasDependentFacts
MaZiFAU
committed
public override bool HasDependentFacts => true;
/// \copydoc Fact.getDependentFactIds
protected override string[] GetDependentFactIds()
=> new string[] { Pid, Rid };
Marco Zimmer
committed
protected override bool EquivalentWrapped(OnLineFact f1, OnLineFact f2)
protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactRecorder organizer)
=> new OnLineFact(old_to_new[this.Pid], old_to_new[this.Rid], organizer);
public override MMTFact MakeMMTDeclaration()
new OMS(MMTConstants.OnLine),
new OMS(Rid),
new OMS(Pid)
}),});
SOMDoc df = null;
return new MMTGeneralFact(this.Label, tp, df);
}
/// <summary>
/// Two parallel Lines comprised of two <see cref="LineFact">LineFacts</see>
/// </summary>
public class ParallelLineFact : FactWrappedCRTP<ParallelLineFact>
{
/// @{ <summary>
MaZiFAU
committed
/// One <see cref="Fact.Id">Id</see> of two <see cref="LineFact"/> that are parallel [<see cref="Lid1"/>, <see cref="Lid2"/>].
/// </summary>
public string Lid1, Lid2;
/// @}
MaZiFAU
committed
[JsonIgnore]
public AbstractLineFact Ray1 { get => (AbstractLineFact)FactRecorder.AllFacts[Lid1]; }
MaZiFAU
committed
[JsonIgnore]
public AbstractLineFact Ray2 { get => (AbstractLineFact)FactRecorder.AllFacts[Lid2]; }
/// <summary> \copydoc Fact.Fact </summary>
public ParallelLineFact() : base()
{
this.Lid1 = null;
this.Lid2 = null;
}
/// <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, FactRecorder organizer) : base(organizer)
{
this.Lid1 = lid1;
this.Lid2 = lid2;
/// <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, SOMDoc _ServerDefinition, FactRecorder organizer) : base(organizer)
{
this.Lid1 = Lid1;
this.Lid2 = Lid2;
this.ServerDefinition = _ServerDefinition;
_ = this.Label;
}
/// \copydoc Fact.parseFact(ScrollFact)
public new static List<Fact> parseFact(MMTFact fact)
if (((MMTGeneralFact)fact).type is not OMA type) // proof DED
return new();
OMA parallel_lines_OMA = (OMA)type.arguments[0]; // parallel
string lineAUri = ((OMS)parallel_lines_OMA.arguments[0]).uri;
string lineBUri = ((OMS)parallel_lines_OMA.arguments[1]).uri;
if (!FactRecorder.AllFacts.ContainsKey(lineAUri)
|| !FactRecorder.AllFacts.ContainsKey(lineBUri))
return new();
return new() { new ParallelLineFact(lineAUri, lineBUri, fact.@ref, StageStatic.stage.factState) };
}
/// \copydoc Fact.generateLabel
protected override string generateLabel()
public override MMTFact MakeMMTDeclaration()
MaZiFAU
committed
SOMDoc tp = new OMA(
new OMS(MMTConstants.ParallelLine),
new OMS(Lid1),
new OMS(Lid2),
MaZiFAU
committed
SOMDoc df = null;
return new MMTGeneralFact(this.Label, tp, df);
}
/// \copydoc Fact.hasDependentFacts
MaZiFAU
committed
public override bool HasDependentFacts => true;
/// \copydoc Fact.getDependentFactIds
protected override string[] GetDependentFactIds()
=> new string[] { Lid1, Lid2 };
/// \copydoc Fact.Equivalent(Fact, Fact)
protected override bool EquivalentWrapped(ParallelLineFact f1, ParallelLineFact f2)
protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactRecorder organizer)
=> new ParallelLineFact(old_to_new[this.Lid1], old_to_new[this.Lid2], organizer);
/// Used for BouncingScroll
public class QuadFact : FactWrappedCRTP<QuadFact>
/// <summary> Defining Corners; Order is Cyclic;
/// <see cref="PointFact"/>.<see cref="Fact.Id">Id</see> </summary>
public string[] Pids;
MaZiFAU
committed
[JsonIgnore]
public PointFact[] Points
{
get => _Points ??= Pids.Select(pid => (PointFact)FactRecorder.AllFacts[pid]).ToArray();
private PointFact[] _Points;
MaZiFAU
committed
[JsonIgnore]
MaZiFAU
committed
public Vector3 Normal, Tangents, AltTangents;
/// <summary> \copydoc Fact.Fact </summary>
public QuadFact() : base() { }
/// <summary>
/// Initiates <see cref="Pids"/> and creates MMT %Fact Server-Side
/// </summary>
/// <param name="pid_corners">sets <see cref="Pids"/></param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
public QuadFact(string[] pid_corners, FactRecorder organizer) : base(organizer)
Init(pid_corners);
}
/// <summary>
/// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_.
/// </summary>
/// <param name="pid_corners">sets <see cref="Pids"/></param>
/// <param name="uri">MMT URI</param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
public QuadFact(string[] pid_corners, SOMDoc _ServerDefinition, FactRecorder organizer) : base(organizer)
Init(pid_corners);
this.ServerDefinition = _ServerDefinition;
_ = this.Label;