/*public static void AddRelator<A, B>(Func<A, B, RSpatialRelation> func) * { * relators.Register((object a, object b) => func((A)a, (B)b), typeof(A), typeof(B)); * * if (typeof(A) != typeof(B)) * relators.Register((object a, object b) => * { * RSpatialRelation r = func((A)b, (B)a); * if (r == RSpatialRelation.AInsideB) r = RSpatialRelation.BInsideA; * else if (r == RSpatialRelation.BInsideA) r = RSpatialRelation.AInsideB; * return r; * }, typeof(B), typeof(A)); * } * * static MultipleDispatcher<Func<object, object, RSpatialRelation>> relators = new MultipleDispatcher<Func<object, object, RSpatialRelation>>(); */ public static void AddRelator <A, B>(Func <A, B, RSpatialRelation> func) { if (!relators.ContainsKey(typeof(A))) { relators[typeof(A)] = new Dictionary <Type, Func <object, object, RSpatialRelation> >(); } if (!relators.ContainsKey(typeof(B))) { relators[typeof(B)] = new Dictionary <Type, Func <object, object, RSpatialRelation> >(); } relators[typeof(A)].Add(typeof(B), (object a, object b) => func((A)a, (B)b)); if (typeof(A) != typeof(B)) { relators[typeof(B)].Add(typeof(A), (object a, object b) => { RSpatialRelation r = func((A)b, (B)a); if (r == RSpatialRelation.AInsideB) { r = RSpatialRelation.BInsideA; } else if (r == RSpatialRelation.BInsideA) { r = RSpatialRelation.AInsideB; } return(r); }); } }
public static RSpatialRelation Relation(BoundingBox a, Bounding.Frustum b) { Vector3 min, max; RSpatialRelation rel = RSpatialRelation.AInsideB; for (int i = 0; i < b.planes.Length; i++) { if (b.planes[i].Normal.X > 0) { min.X = a.Minimum.X; max.X = a.Maximum.X; } else { min.X = a.Maximum.X; max.X = a.Minimum.X; } if (b.planes[i].Normal.Y > 0) { min.Y = a.Minimum.Y; max.Y = a.Maximum.Y; } else { min.Y = a.Maximum.Y; max.Y = a.Minimum.Y; } if (b.planes[i].Normal.Z > 0) { min.Z = a.Minimum.Z; max.Z = a.Maximum.Z; } else { min.Z = a.Maximum.Z; max.Z = a.Minimum.Z; } if (Vector3.Dot(b.planes[i].Normal, min) + b.planes[i].D > 0) { return(RSpatialRelation.Outside); } if (Vector3.Dot(b.planes[i].Normal, max) + b.planes[i].D >= 0) { rel = RSpatialRelation.Intersect; } } return(rel); }
// ---------------------------------------------------------------------------------------------- // -- Chain ------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------- public static RSpatialRelation Relation(Bounding.Chain a, object b) { if (a.Shallow) { return(Relation(a.Boundings[0], b)); } RSpatialRelation rel = RSpatialRelation.Outside; foreach (object o in a.Boundings) { rel = Relation(o, b); if (rel == RSpatialRelation.Outside) { return(RSpatialRelation.Outside); } else if (rel == RSpatialRelation.AInsideB) { return(RSpatialRelation.AInsideB); } } return(rel); }
public static RSpatialRelation Relation(BoundingBox a, Bounding.Cylinder b) { // NOTE: Not tested thoroughly! /* * This all is based on finding the intersections between the axises of the box * */ float m, n; float boxMinZ = a.Minimum.Z; float boxMaxZ = a.Maximum.Z; float cylMinZ = b.Position.Z; float cylMaxZ = cylMinZ + b.Height; RSpatialRelation verticalRelation = Relation1DLines(boxMinZ, boxMaxZ, cylMinZ, cylMaxZ); if (verticalRelation == RSpatialRelation.Outside) { return(RSpatialRelation.Outside); } // from this point on we know that the cylinder at least intersects the box on the vertical axis //X Axis, first find intersections CylP x1 = CylP.NotIntersecting; if (Math.CircleXAxisIntersection(b.Position, b.Radius, a.Minimum.Y, out m, out n)) { if (m > a.Maximum.X || n < a.Minimum.X) { x1 = CylP.Outside; } else if (m < a.Minimum.X && n > a.Maximum.X) { x1 = CylP.AInsideB; } else { return(RSpatialRelation.Intersect); } } CylP x2 = CylP.NotIntersecting; if (Math.CircleXAxisIntersection(b.Position, b.Radius, a.Maximum.Y, out m, out n)) { if (m > a.Maximum.X || n < a.Minimum.X) { x2 = CylP.Outside; } else if (m < a.Minimum.X && n > a.Maximum.X) { x2 = CylP.AInsideB; } else { return(RSpatialRelation.Intersect); } } //Y Axis, first find intersections CylP y1 = CylP.NotIntersecting; if (Math.CircleYAxisIntersection(b.Position, b.Radius, a.Minimum.X, out m, out n)) { if (m > a.Maximum.Y || n < a.Minimum.Y) { y1 = CylP.Outside; } else if (m < a.Minimum.Y && n > a.Maximum.Y) { y1 = CylP.AInsideB; } else { return(RSpatialRelation.Intersect); } } CylP y2 = CylP.NotIntersecting; if (Math.CircleYAxisIntersection(b.Position, b.Radius, a.Maximum.X, out m, out n)) { if (m > a.Maximum.Y || n < a.Minimum.Y) { y2 = CylP.Outside; } else if (m < a.Minimum.Y && n > a.Maximum.Y) { y2 = CylP.AInsideB; } else { return(RSpatialRelation.Intersect); } } if (x1 == CylP.AInsideB && x2 == CylP.AInsideB && y1 == CylP.AInsideB && y2 == CylP.AInsideB) { if (verticalRelation == RSpatialRelation.AInsideB) { return(RSpatialRelation.AInsideB); } return(RSpatialRelation.Intersect); } //var horizontalRelation = RectCircleRelation(new RectangleF(new PointF(a.Minimum.X, a.Minimum.Y), new SizeF(a.Maximum.X - a.Minimum.X, a.Maximum.Y - a.Minimum.Y)), b); //if (horizontalRelation == RSpatialRelation.Outside) // return RSpatialRelation.Outside; //else if (horizontalRelation == verticalRelation) // return horizontalRelation; //else // return RSpatialRelation.Intersect; if (x1 == CylP.NotIntersecting && x2 == CylP.NotIntersecting && y1 == CylP.NotIntersecting && y2 == CylP.NotIntersecting && Intersection.Intersect(a, Math.ToVector2(b.Position))) { if (verticalRelation == RSpatialRelation.BInsideA) { return(RSpatialRelation.BInsideA); } return(RSpatialRelation.Intersect); } else { return(RSpatialRelation.Outside); } #if false //We start by checking if the circle is so large it covers the whole rectangle bool intersects = false, ainsideb = true; if (p.CullPoint(position.X, position.Y) == ECull.Intersect) { intersects = true; } else { ainsideb = false; } if (p.CullPoint(position.X + size.X, position.Y) == ECull.Intersect) { intersects = true; } else { ainsideb = false; } if (p.CullPoint(position.X, position.Y + size.Y) == ECull.Intersect) { intersects = true; } else { ainsideb = false; } if (p.CullPoint(position.X + size.X, position.Y + size.Y) == ECull.Intersect) { intersects = true; } else { ainsideb = false; } if (ainsideb) { return(RSpatialRelation.AInsideB); } if (intersects) { return(RSpatialRelation.Intersect); } //The find the point on the circle which is closest to the center of the rectangle Vector3 k = center - p.Position; if (k.LengthSquared() == 0) { k.X = 1; } Vector3 d = Vector3.Normalize(k) * p.Radius; Vector3 a = p.Position + d; //And check if it is outside the rectangle if (CullPoint(a.X, a.Y) == ECull.Outside) { return(RSpatialRelation.Outside); } //The we take the point furthest away from the center Vector3 b = p.Position - d; if (CullPoint(b.X, b.Y) == ECull.Outside) { return(RSpatialRelation.Intersect); } return(RSpatialRelation.BInsideA); #endif }