/// <summary> /// result * other ~= Proj(this onto other) /// </summary> /// <param name="other"></param> /// <returns></returns> [Pure] public double ProjectOntoComponentD(IntVector2 other) { return(other.Dot(this) / (double)other.SquaredNorm2()); }
public bool Equals(IntVector2 other) => X == other.X && Y == other.Y;
[Pure] public long Dot(IntVector2 other) => (long)X * other.X + (long)Y * other.Y;
[Pure] public IntVector2 To(IntVector2 other) => other - this;
public bool Contains(ref IntVector2 q) => Contains(First, Second, q);
public static bool Contains(IntVector2 p1, IntVector2 p2, IntVector2 q) => Contains(ref p1, ref p2, ref q);
public bool Contains(IntVector2 q) => Contains(ref q);
public static IntLineSegment2 Create(IntVector2 first, IntVector2 second) { return(new IntLineSegment2(first, second)); }
public void Deconstruct(out IntVector2 first, out IntVector2 second) { first = First; second = Second; }
/// <summary> /// Note: Containment definition varies by hole vs terrain: Containment for holes /// does not include the hole edge, containment for terrain includes the terrain edge. /// This is important, else e.g. knockback + terrain push placing an entity on an edge /// would potentially infinite loop. /// </summary> public static void PickDeepestPolynodeGivenHoleShapePolytree(this PolyTree polyTree, IntVector2 query, out PolyNode result, out bool isHole) { polyTree.AssertIsContourlessRootHolePunchResult(); PolyNode current = polyTree; while (true) { // current is a hole of a hole's shape PolyNode match; // if we fail to find the first child land node border-inclusively containing the query point if (!current.Childs.TryFindFirst(child => Clipper.PointInPolygon(new IntVector2(query.X, query.Y), child.Contour) == PolygonContainmentResult.InPolygon, out match)) { result = current; isHole = true; return; } // next off, current is land of a hole's shape current = match; // If we fail to find a child hole border-excludingly containing the query point if (!current.Childs.TryFindFirst(child => Clipper.PointInPolygon(new IntVector2(query.X, query.Y), child.Contour) != PolygonContainmentResult.OutsidePolygon, out match)) { result = current; isHole = false; return; } // next off, current is a hole of a hole's shape current = match; } }
public static bool PointInPolytree(this PolyTree polyTree, IntVector2 query, out PolyNode deepestPolyNode) { PickDeepestPolynodeGivenHoleShapePolytree(polyTree, query, out deepestPolyNode, out var isHole); return(!isHole); }