using System.Collections.Generic;
public static void Main()
List<Vector2> sampleSpikeObs = new List<Vector2> {
List<RTap.WallObstacle> sampleWallObs = new List<RTap.WallObstacle>() {
new RTap.WallObstacle(new Vector2(0, 5), new Vector2(0, 1)),
RTap r = new RTap(sampleSpikeObs, sampleWallObs);
BezierCurve b = new BezierCurve(new List<Vector2> {
r.DerivativePath = b.DervBezFunc;
Console.WriteLine(b.DervBezFunc(0));
Console.WriteLine(b.DervBezFunc(0.5f));
Console.WriteLine(b.DervBezFunc(1));
Console.WriteLine("PENALTY: " + r.Penalty());
public List<SpikeObstacle> spikeObstacles = new List<SpikeObstacle>();
private const float spikeConst = 50;
public bool includingWalls;
private const int wallCount = 4;
public List<WallObstacle> wallObstacles = new List<WallObstacle>();
public Func<float, Vector2> Path;
public Func<float, Vector2> DerivativePath;
private const float potentialPenaltyWeight = 1;
private const float motionPenaltyWeight = 2;
public RTap(List<Vector2> sO, List<WallObstacle> wO, bool iW = true) {
foreach (Vector2 v in sO) {
spikeObstacles.Add(new SpikeObstacle(v));
public RTap(List<SpikeObstacle> sO, List<WallObstacle> wO, bool iW = true) {
public float Potential(Vector2 pos) {
foreach (SpikeObstacle s in spikeObstacles) {
sum += spikeConst * MathF.Exp( -MathF.Pow((pos.X - s.Position.X), 2) - MathF.Pow((pos.Y - s.Position.Y), 2));
foreach (WallObstacle w in wallObstacles) {
sum += MathF.Exp(5 * Vector2.Dot(w.Direction, pos - w.Offset));
Func<float, float> integrandFromPotential = (float t) => { return potentialPenaltyWeight * Potential( Path(t) ); };
Func<float, float> integrandFromMotion = (float t) => { Vector2 tempPos = DerivativePath(t); return motionPenaltyWeight*MathF.Sqrt( MathF.Pow(tempPos.X, 2) + MathF.Pow(tempPos.Y, 2) ); };
float penaltyFromPotential = AuxiliaryMath.BruteDefIntegral(integrandFromPotential, 0, 1);
float penaltyFromMotion = AuxiliaryMath.BruteDefIntegral(integrandFromMotion, 0, 1);
return penaltyFromPotential + penaltyFromMotion;
public class SpikeObstacle {
public SpikeObstacle (Vector2 pos, float s = 50) {
public float ContributionPotential(Vector2 loc) {
return size * MathF.Exp( -MathF.Pow((loc.X - Position.X), 2) - MathF.Pow((loc.Y - Position.Y), 2));
public class WallObstacle {
public Vector2 Direction;
public WallObstacle(Vector2 o, Vector2 d) {
Direction = Vector2.Normalize(d);
public WallObstacle(float o, string d) {
string dir = d.Substring(0, 1).ToLower();
Direction = new Vector2(0, 1);
Direction = new Vector2(1, 0);
Direction = new Vector2(0, -1);
Direction = new Vector2(-1, 0);
Offset = off * Direction;
public static class AuxiliaryMath {
private const float d = 0.0001f;
public static float BruteDefIntegral(Func<float, float> expression, float min, float max) {
for (float i = min; i <= max; i += d) {
sum += expression(i) * d;
public static int Fact(int n) {
for (int i = n - 1; i > 1; i--) {
public class BezierCurve {
public List<Vector2> points;
public Func<float, Vector2> parametric;
public BezierCurve(List<Vector2> p) {
parametric = (float t) => { return BezFunc(t); };
private float BezFactor(int n, int k) {
return (float)AuxiliaryMath.Fact(n) / (float)( AuxiliaryMath.Fact(k) * AuxiliaryMath.Fact(n - k) );
private float BezComp(float t, int K, float v, int Nrep = -1) {
return BezFactor(N, K) * MathF.Pow((1 - t), (N - K)) * MathF.Pow(t, K) * v;
public Vector2 BezFunc(float t) {
Vector2 sum = new Vector2(0, 0);
for (int i = 0; i < degree; i++) {
sum += new Vector2( BezComp(t, i, points[i].X), BezComp(t, i, points[i].Y) );
public Vector2 DervBezFunc(float t) {
Vector2 sum = new Vector2(0, 0);
for (int i = 0; i < degree - 1; i++) {
BezComp(t, i, degree * (points[i + 1].X - points[i].X), degree - 2),
BezComp(t, i, degree * (points[i + 1].Y - points[i].Y), degree - 2)