public IEnumerable<ISide> GetSides(Direction direction, Range positionRange, Range boundsRange, bool ascending = true) { return _directionSidesMap[(int) direction] .Where(s => positionRange.Contains(s.Position) && boundsRange.IsIntersect(new Range(s.Begin, true, s.End, true))) .OrderBy(s => ascending ? s.Position : -s.Position); }
private IEnumerable<CollisionEvent> GetSideCollisions(IBody movingBody, Direction movingSideDirection, Vector2 path) { var axis = movingSideDirection.ToAxis(); var sidePosition = movingBody.GetBound(movingSideDirection); var counterDirection = movingSideDirection.AtBack(); var pathForward = path.GetComponent(movingSideDirection); if (pathForward == 0) return Enumerable.Empty<CollisionEvent>(); var pathStartInclusive = pathForward > 0; var pathEndInclusive = pathForward < 0; var pathLeft = path.GetComponent(movingSideDirection.AtLeft()); var sideStartInclusive = pathLeft < 0; var sideEndInclusive = pathLeft > 0; var pathAlong = path.GetComponent(axis); var pathAcross = path.GetComponent(axis.Orthogonal()); var collisionType = pathForward >= 0 ? CollisionType.Entering : CollisionType.Leaving; var incidenceTangent = pathLeft/pathForward; //todo maybe pathLeft negate.... var movedSidePositionRange = new Range(sidePosition, pathStartInclusive, sidePosition + pathAlong, pathEndInclusive); var movedSideRange = movingBody.GetBoundRange(movingSideDirection, sideStartInclusive, sideEndInclusive); var counterSides = _sideRepository.GetSides(counterDirection, movedSidePositionRange, movedSideRange, pathAlong > 0); return (from counterSide in counterSides //todo query bodyBounds more optimal!!! use special sorted structs where counterSide.Body != movingBody && movedSidePositionRange.Contains(counterSide.Position) let pathAlongToCounterSide = counterSide.Position - sidePosition let pathAcrossToCounterSide = pathAcross * pathAlongToCounterSide / pathAlong where movedSideRange.IsIntersect(new Range(counterSide.Begin, sideStartInclusive, counterSide.End, sideEndInclusive)) group counterSide.Body by pathAlongToCounterSide into g select new CollisionEvent { Collision = new Collision { Bodies = g.ToArray(), Type = collisionType, NormalDirection = counterDirection, IncidenceTangent = incidenceTangent }, Traversed = g.Key / pathAlong, }); }