/// <summary> /// See <see cref="IForce.ApplyToObject(TPhysicalObject)"/>. /// </summary> public void ApplyToObject(IBody <TShapeFigure> physicalObject) { ArgumentChecks.AssertNotNull(physicalObject, nameof(physicalObject)); // TODO: make this class "more generic", so it could be used for particles as well. Add a strategy to determine the "point to apply the force to". var pointClosestToBlastCenter = this._supportFunctions.GetFigureOutlinePointClosestToPosition( physicalObject.Shape.Current, this._position); // Is the object within reach of the blast? var offset = pointClosestToBlastCenter.GetOffsetFrom(this._position); if (offset.Magnitude() > this._currentBlastRadius) { return; } var forceVector = offset.Norm().Multiply(this._currentForce); physicalObject.ApplyForceAtPointInSpace(forceVector, pointClosestToBlastCenter); }
/// <summary> /// See <see cref="IForce{TPhysicalObject}.ApplyToObject(TPhysicalObject)"/>. /// </summary> public void ApplyToObject(IBody <TShapeFigure> physicalObject) { ArgumentChecks.AssertNotNull(physicalObject, nameof(physicalObject)); var velocity = physicalObject.CurrentState.Velocity; if (velocity.SquaredMagnitude() == 0) { return; } var forceDirection = velocity.Invert(); var supportPointLeft = this._supportFunctions.GetSupportPoint(physicalObject.Shape.Current, forceDirection.Get90DegreesLeft()); var supportPointRight = this._supportFunctions.GetSupportPoint(physicalObject.Shape.Current, forceDirection.Get90DegreesRight()); var intersectionWithPerpendicular = this._lineCalculationHelper.GetIntersectionWithPerpendicularThroughPoint( new Line(physicalObject.CurrentState.Position, physicalObject.CurrentState.Position.AddVector(forceDirection)), supportPointLeft); var pointOppositeLeftSupportPoint = this._lineCalculationHelper.GetIntersectionWithPerpendicularThroughPoint( new Line(supportPointLeft, intersectionWithPerpendicular), supportPointRight); var offset = pointOppositeLeftSupportPoint.GetOffsetFrom(supportPointLeft); // Determine the exposed "area". var exposedArea = offset.SquaredMagnitude(); // Determine force. var forceMagnitude = exposedArea * this._density * velocity.SquaredMagnitude() / 2; var forceVector = forceDirection.Norm().Multiply(forceMagnitude); // Determine the point to apply force to. var pointToApplyForceTo = supportPointLeft.AddVector(offset.Divide(2)); // Apply force. physicalObject.ApplyForceAtPointInSpace(forceVector, pointToApplyForceTo); }