Select Git revision
KineticFactBehaviour.cs.meta
AbstractLineFact.cs 13.43 KiB
using Newtonsoft.Json;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using static SOMDocManager;
/// <summary>
/// Base-class for 1D-Facts
/// </summary>
public abstract class AbstractLineFact : FactWrappedCRTP<AbstractLineFact>
{
/// @{ <summary>
/// One <see cref="Fact.Id">Id</see> of two <see cref="PointFact"/> defining <see cref="Dir"/>.
/// </summary>
public string Pid1, Pid2;
/// @}
[JsonIgnore]
public PointFact Point1 { get => (PointFact)_Facts[Pid1]; }
[JsonIgnore]
public PointFact Point2 { get => (PointFact)_Facts[Pid2]; }
/// <summary> Distance between <see cref="AbstractLineFact.Pid1"/> and <see cref="AbstractLineFact.Pid2"/></summary>
[JsonIgnore]
public float Distance;
/// <summary>
/// Normalized Direction from <see cref="Pid1"/> to <see cref="Pid2"/>.
/// </summary>
public Vector3 Dir;
/// <summary>
/// \copydoc Fact.Fact()
/// </summary>
protected AbstractLineFact() : base()
{
Pid1 = null;
Pid2 = null;
Dir = Vector3.zero;
}
/// <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>
protected AbstractLineFact(AbstractLineFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer)
{
set_public_members(old_to_new[fact.Pid1], old_to_new[fact.Pid2]);
}
/// <summary>
/// Standard Constructor
/// </summary>
/// <param name="pid1">sets <see cref="AbstractLineFact.Pid1"/></param>
/// <param name="pid2">sets <see cref="AbstractLineFact.Pid2"/></param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
protected AbstractLineFact(string pid1, string pid2, FactOrganizer organizer) : base(organizer)
{
set_public_members(pid1, pid2);
}
/// <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="backendURI">MMT URI</param>
/// <param name="organizer">sets <see cref="Fact._Facts"/></param>
protected AbstractLineFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(organizer)
{
set_public_members(pid1, pid2);
this._URI = backendURI;
}
/// <summary>
/// Initiates <see cref="Pid1"/>, <see cref="Pid2"/>, <see cref="Dir"/>
/// </summary>
/// <param name="pid1">sets <see cref="Pid1"/></param>
/// <param name="pid2">sets <see cref="Pid2"/></param>
private void set_public_members(string pid1, string pid2)
{
this.Pid1 = pid1;
this.Pid2 = pid2;
Vector3 diff = (Point1.Point - Point2.Point);
this.Dir = diff.normalized;
this.Distance = diff.magnitude;
RecalulateTransform();
}
protected override void RecalulateTransform()
{
Position = Vector3.Lerp(Point1.Point, Point2.Point, 0.5f);
Rotation = Quaternion.LookRotation(Dir, Vector3.up);
LocalScale = new Vector3(1, 1, Distance);
}
/// \copydoc Fact.hasDependentFacts
public override bool hasDependentFacts()
{
return true;
}
/// \copydoc Fact.getDependentFactIds
public override string[] getDependentFactIds()
{
return new string[] { Pid1, Pid2 };
}
/// \copydoc Fact.GetHashCode
public override int GetHashCode()
{
return this.Pid1.GetHashCode() ^ this.Pid2.GetHashCode();
}
}
/// <summary>
/// Implements CRTP for <see cref="AbstractLineFact"/>; Escalates constructors;
/// </summary>
/// <typeparam name="T">class, which inherits from AbstractLineFactWrappedCRTP</typeparam>
public abstract class AbstractLineFactWrappedCRTP<T> : AbstractLineFact where T : AbstractLineFactWrappedCRTP<T>
{
/// <summary>\copydoc Fact.Fact</summary>
protected AbstractLineFactWrappedCRTP() : base() { }
/// <summary>\copydoc AbstractLineFact.AbstractLineFact(AbstractLineFact, Dictionary{string, string}, FactOrganizer)</summary>
protected AbstractLineFactWrappedCRTP(AbstractLineFactWrappedCRTP<T> fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer) { }
/// <summary>\copydoc AbstractLineFact.AbstractLineFact(string, string, FactOrganizer)</summary>
protected AbstractLineFactWrappedCRTP(string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer) { }
/// <summary>\copydoc AbstractLineFact.AbstractLineFact(string, string, string, FactOrganizer)</summary>
protected AbstractLineFactWrappedCRTP(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer) { }
/// \copydoc Fact.Equivalent(Fact, Fact)
protected override bool EquivalentWrapped(AbstractLineFact f1, AbstractLineFact f2)
=> EquivalentWrapped((T)f1, (T)f2);
/// <summary>CRTP step of <see cref="EquivalentWrapped(AbstractLineFact, AbstractLineFact)"/></summary>
protected abstract bool EquivalentWrapped(T f1, T f2);
}
/// <summary>
/// Line within 3D Space of finite length
/// </summary>
public class LineFact : AbstractLineFactWrappedCRTP<LineFact>
{
/// \copydoc Fact.s_type
[JsonProperty]
protected static new string s_type = "LineFact";
/// <summary> \copydoc Fact.Fact </summary>
public LineFact() : base() { }
/// <summary> \copydoc AbstractLineFact.AbstractLineFact(AbstractLineFact, Dictionary<string, string>, FactOrganizer) </summary>
public LineFact(LineFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer)
=> init(old_to_new[fact.Pid1], old_to_new[fact.Pid2]);
/// <summary> \copydoc AbstractLineFact.AbstractLineFact(string, string, string, FactOrganizer) </summary>
public LineFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer)
=> _ = this.Label;
/// <summary> \copydoc AbstractLineFact.AbstractLineFact(string, string, FactOrganizer) </summary>
public LineFact(string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer)
=> init(pid1, pid2);
/// <summary>
/// Initiates <see cref="AbstractLineFact.Pid1"/>, <see cref="AbstractLineFact.Pid2"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
/// </summary>
/// <param name="pid1">sets <see cref="AbstractLineFact.Pid1"/></param>
/// <param name="pid2">sets <see cref="AbstractLineFact.Pid2"/></param>
private void init(string pid1, string pid2)
{
SOMDoc lhs =
new OMA(
new OMS(MMT_OMS_URI.Metric),
new List<SOMDoc> {
new OMS(pid1),
new OMS(pid2)
}
);
SOMDoc valueTp = new OMS(MMT_OMS_URI.RealLit);
SOMDoc value = new OMF(Distance);
MMTValueDeclaration mmtDecl = new(this.Label, lhs, valueTp, value);
AddFactResponse.sendAdd(mmtDecl, out this._URI);
}
/// \copydoc Fact.parseFact(Scroll.ScrollFact)
public new static LineFact parseFact(Scroll.ScrollFact fact)
{
string uri = fact.@ref.uri;
string pointAUri = ((OMS)((OMA)((Scroll.ScrollValueFact)fact).lhs).arguments[0]).uri;
string pointBUri = ((OMS)((OMA)((Scroll.ScrollValueFact)fact).lhs).arguments[1]).uri;
if (StageStatic.stage.factState.ContainsKey(pointAUri)
&& StageStatic.stage.factState.ContainsKey(pointBUri))
return new LineFact(pointAUri, pointBUri, uri, StageStatic.stage.factState);
//If dependent facts do not exist return null
else return null;
}
/// \copydoc Fact.generateLabel
protected override string generateLabel()
=> "[" + _Facts[Pid1].Label + _Facts[Pid2].Label + "]";
/// \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.Pid2].Label;
obj.GetComponent<FactWrapper>().fact = this;
return obj;
}
/// \copydoc Fact.Equivalent(Fact, Fact)
protected override bool EquivalentWrapped(LineFact f1, LineFact f2)
{
if ((f1.Pid1 == f2.Pid1 && f1.Pid2 == f2.Pid2))// ||
//(f1.Pid1 == f2.Pid2 && f1.Pid2 == f2.Pid1))
return true;
PointFact p1f1 = (PointFact)_Facts[f1.Pid1];
PointFact p2f1 = (PointFact)_Facts[f1.Pid2];
PointFact p1f2 = (PointFact)_Facts[f2.Pid1];
PointFact p2f2 = (PointFact)_Facts[f2.Pid2];
return (p1f1.Equivalent(p1f2) && p2f1.Equivalent(p2f2))
;//|| (p1f1.Equivalent(p2f2) && p2f1.Equivalent(p1f2));
}
}
/// <summary>
/// Ray within 3D Space of infinite length
/// </summary>
public class RayFact : AbstractLineFactWrappedCRTP<RayFact>
{
/// \copydoc Fact.s_type
[JsonProperty]
protected static new string s_type = "RayFact";
/// <summary> \copydoc Fact.Fact </summary>
public RayFact() : base() { }
/// <summary> \copydoc AbstractLineFact.AbstractLineFact(AbstractLineFact, Dictionary<string, string>, FactOrganizer) </summary>
public RayFact(RayFact fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer)
=> init(old_to_new[fact.Pid1], old_to_new[fact.Pid2]);
/// <summary> \copydoc AbstractLineFact.AbstractLineFact(string, string, string, FactOrganizer) </summary>
public RayFact(string pid1, string pid2, string backendURI, FactOrganizer organizer) : base(pid1, pid2, backendURI, organizer)
{
_ = this.Label;
RecalulateTransform();
}
/// <summary> \copydoc AbstractLineFact.AbstractLineFact(string, string, FactOrganizer) </summary>
public RayFact(string pid1, string pid2, FactOrganizer organizer) : base(pid1, pid2, organizer)
=> init(pid1, pid2);
/// <summary>
/// Initiates <see cref="AbstractLineFact.Pid1"/>, <see cref="AbstractLineFact.Pid2"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
/// </summary>
/// <param name="pid1">sets <see cref="AbstractLineFact.Pid1"/></param>
/// <param name="pid2">sets <see cref="AbstractLineFact.Pid2"/></param>
private void init(string pid1, string pid2)
{
RecalulateTransform();
SOMDoc tp = new OMS(MMT_OMS_URI.LineType);
SOMDoc df = new OMA(
new OMS(MMT_OMS_URI.LineOf),
new List<SOMDoc> {
new OMS(pid1),
new OMS(pid2)
});
AddFactResponse.sendAdd(new MMTSymbolDeclaration(this.Label, tp, df), out this._URI);
ParsingDictionary.parseTermsToId[df.ToString()] = this._URI;
}
protected override void RecalulateTransform()
{
base.RecalulateTransform();
LocalScale = new Vector3(1, 1, 2048);
}
/// \copydoc Fact.parseFact(Scroll.ScrollFact)
public new static RayFact parseFact(Scroll.ScrollFact fact)
{
string uri = fact.@ref.uri;
if ((OMA)((Scroll.ScrollSymbolFact)fact).df == null)
return null;
string pointAUri = ((OMS)((OMA)((Scroll.ScrollSymbolFact)fact).df).arguments[0]).uri;
string pointBUri = ((OMS)((OMA)((Scroll.ScrollSymbolFact)fact).df).arguments[1]).uri;
if (StageStatic.stage.factState.ContainsKey(pointAUri)
&& StageStatic.stage.factState.ContainsKey(pointBUri))
return new RayFact(pointAUri, pointBUri, uri, StageStatic.stage.factState);
//If dependent facts do not exist return null
else return null;
}
/// \copydoc Fact.generateLabel
protected override string generateLabel()
{
// TODO this string is too large to properly depict on scrolls.
// return "]" + _Facts[Pid1].Label + _Facts[Pid2].Label + "[";
return _Facts[Pid1].Label + _Facts[Pid2].Label;
}
/// \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 = this.Label;
obj.GetComponent<FactWrapper>().fact = this;
return obj;
}
/// \copydoc Fact.Equivalent(Fact, Fact)
protected override bool EquivalentWrapped(RayFact f1, RayFact f2)
{
if (!Math3d.IsApproximatelyParallel(f1.Dir, f2.Dir))
return false;
PointFact p1f1 = (PointFact)_Facts[f1.Pid1];
PointFact p1f2 = (PointFact)_Facts[f2.Pid1];
PointFact p2f2 = (PointFact)_Facts[f2.Pid2];
return Math3d.IsPointApproximatelyOnLine(p1f1.Point, f1.Dir, p1f2.Point)
&& Math3d.IsPointApproximatelyOnLine(p1f1.Point, f1.Dir, p2f2.Point);
}
}