예제 #1
0
 //Note that basis conversion is the same as inverse rotation,
 //and basis deconversion is the same as rotation.
 public static tv2 ConvertBasis(ev2 source, ev2 basis1) => EEx.ResolveV2(source, basis1,
                                                                         // [ b1.x  -b1.y ]^T  [ x ]
                                                                         // [ b1.y   b1.x ]    [ y ]
                                                                         (s, b1) => ExUtils.V2(
                                                                             b1.x.Mul(s.x).Add(b1.y.Mul(s.y)),
                                                                             b1.x.Mul(s.y).Sub(b1.y.Mul(s.x))
                                                                             ));
예제 #2
0
파일: ExMV3.cs 프로젝트: Bagoum/danmokou
 /// <summary>
 /// Wrap a position equation around a cylinder.
 /// </summary>
 /// <param name="radius">Radius of the cylinder</param>
 /// <param name="ang0">Starting angle offset (radians) on the cylinder. 0 = z-axis</param>
 /// <param name="maxWrap">Maximum angle value (radians) of the wrap. After this, the function will continue along the tangent. Starting offset not included. Absolute value tested.</param>
 /// <param name="axisOff">Offset angle (radians) of the axis of the cylinder from the y-axis</param>
 /// <param name="position">Position equation</param>
 /// <returns></returns>
 public static tv3 CylinderWrap(efloat radius, efloat ang0, efloat maxWrap, efloat axisOff, ev2 position) =>
 EEx.Resolve(radius, ang0, axisOff, position, (r, a0, axis, _v2) => {
     var cs    = new TExV2();
     var xyd   = new TExV2();
     var v2    = new TExV2(_v2);
     var v3    = new TExV3();
     var a     = ExUtils.VFloat();
     var aRem  = ExUtils.VFloat();
     var aMax  = ExUtils.VFloat();
     var a_cs  = new TExV2();
     var a0_cs = new TExV2();
     return(Ex.Block(new[] { v3, cs, xyd, a, aRem, aMax, a_cs, a0_cs },
                     aMax.Is(maxWrap),
                     cs.Is(CosSin(axis)),
                     xyd.Is(ConvertBasis(v2, cs)),
                     a.Is(xyd.x.Div(r)),
                     aRem.Is(E0),
                     Ex.IfThen(Abs(a).GT(aMax), Ex.Block(
                                   Ex.IfThen(a.LT0(), MulAssign(aMax, EN1)),
                                   aRem.Is(a.Sub(aMax)),
                                   a.Is(aMax)
                                   )),
                     a0_cs.Is(CosSin(a0)),
                     a_cs.Is(CosSin(a.Add(a0))),
                     xyd.x.Is(r.Mul(a_cs.y.Sub(a0_cs.y).Add(aRem.Mul(a_cs.x)))),
                     v3.Is(TP3(DeconvertBasis(xyd, cs))),
                     v3.z.Is(r.Mul(a_cs.x.Sub(a0_cs.x).Sub(aRem.Mul(a_cs.y)))),
                     v3
                     ));
 });
예제 #3
0
파일: ExMMod.cs 프로젝트: Bagoum/danmokou
 /// <summary>
 /// Periodize a value,
 /// "bouncing off" the endpoint instead of wrapping around.
 /// </summary>
 /// <example>
 /// <c>
 /// FSoftMod(X(), 4)(3.95) = 3.95
 /// FSoftMod(X(), 4)(4.05) = 3.95
 /// FSoftMod(X(), 4)(4.15) = 3.85
 /// </c>
 /// </example>
 /// <param name="by">Period</param>
 /// <param name="x">Value</param>
 /// <returns></returns>
 public static tfloat SoftMod(efloat by, efloat x) => EEx.Resolve(by, _by => {
     var vd = VFloat();
     return(Ex.Block(new[] { vd },
                     vd.Is(Mod(E2.Mul(_by), x)),
                     Ex.Condition(vd.LT(_by), vd, E2.Mul(_by).Sub(vd))
                     ));
 });
예제 #4
0
파일: ExMMod.cs 프로젝트: Bagoum/danmokou
 /// <summary>
 /// Use Fermat's Little Theorem to reindex integers around a prime number mod, localized to the region
 /// [mod\*floor(index/mod), mod+mod\*floor(index/mod)].
 /// </summary>
 public static tfloat RemapIndexLoop(efloat mod, efloat index) => EEx.Resolve(mod, index, (m, i) => {
     var rem = VFloat();
     return(Ex.Block(new[] { rem },
                     rem.Is(Mod(m, i)),
                     i.Sub(rem).Add(RemapIndex(m, rem))
                     ));
 });
예제 #5
0
파일: ExMMod.cs 프로젝트: Bagoum/danmokou
 /// <summary>
 /// Use this to draw "wings" where both go in opposite directions.
 /// <br/>Odd by: 0 is the center, [1,by/2-0.5] are one wing, and [by/2+0.5,by) are the other.
 /// <br/>Even by: [0, by/2) are one wing, [by/2, by) are the other.
 /// </summary>
 /// <example>
 /// <c>
 /// HNMod(X(), 9)(0) = HNMod(X(), 9)(9) = 0
 /// HNMod(X(), 9)(1) = 1
 /// HNMod(X(), 9)(5) = -1
 /// HNMod(X(), 9)(8) = -4
 /// HNMod(X(), 8)(0) = HNMod(X(), 8)(8) = 0.5
 /// HNMod(X(), 8)(3) = 3.5
 /// HNMod(X(), 8)(4) = -0.5
 /// </c>
 /// </example>
 /// <param name="by">Period</param>
 /// <param name="x">Target function</param>
 /// <returns></returns>
 public static tfloat HNMod(tfloat by, tfloat x) => EEx.Resolve <float>(by.Div(E2), h => {
     var y = VFloat();
     return(Ex.Block(new[] { y },
                     y.Is(Mod(h.Mul(E2), x)),
                     Ex.Condition(y.LT(h), y.Add(Floor(h)).Add(E05).Sub(h), h.Sub(E05).Sub(y))
                     ));
 });
예제 #6
0
 /// <summary>
 /// Lerp between two functions. The controller is not clamped.
 /// </summary>
 /// <param name="zeroBound">Lower bound for lerp controller</param>
 /// <param name="oneBound">Upper bound for lerp controller</param>
 /// <param name="controller">Lerp controller</param>
 /// <param name="f1">First function</param>
 /// <param name="f2">Second function</param>
 /// <returns></returns>
 public static TEx <T> LerpU <T>(efloat zeroBound, efloat oneBound, efloat controller, TEx <T> f1, TEx <T> f2) =>
 EEx.Resolve(zeroBound, oneBound, controller, (z, o, c) => {
     var rc = VFloat();
     return(Ex.Block(new[] { rc },
                     rc.Is(c.Sub(z).Div(o.Sub(z))),
                     rc.Mul(f2).Add(rc.Complement().Mul(f1))
                     ));
 });
예제 #7
0
 /// <summary>
 /// Lerp between two functions with smoothing applied to the controller.
 /// </summary>
 public static TEx <T> LerpSmooth <T>([LookupMethod] Func <tfloat, tfloat> smoother,
                                      efloat zeroBound, efloat oneBound, efloat controller, TEx <T> f1, TEx <T> f2)
 => EEx.Resolve(zeroBound, oneBound, controller, (z, o, c) => {
     var rc = VFloat();
     return(Ex.Block(new[] { rc },
                     rc.Is(smoother(Clamp(z, o, c).Sub(z).Div(o.Sub(z)))),
                     rc.Mul(f2).Add(rc.Complement().Mul(f1))
                     ));
 });
예제 #8
0
 /// <summary>
 /// Note: requires that normalVec and planeVec are perpendicular.
 /// </summary>
 public static tv3 RotateInPlane(tfloat rot, tv3 normalVec, ev3 planeVec) => EEx.Resolve(planeVec, p => {
     var cs    = new TExV2();
     var cross = new TExV3();
     return(Ex.Block(new ParameterExpression[] { cs, cross },
                     cs.Is(CosSinDeg(rot)),
                     cross.Is(CrossProduct(normalVec, p)),
                     cs.x.Mul(p).Add(cs.y.Mul(v3Mag(p).Div(v3Mag(cross)).Mul(cross)))
                     ));
 });
예제 #9
0
 public static tv3 FromSphere(tfloat radius, ev2 sphere) => radius.Mul(EEx.ResolveV2(sphere, s => {
     var cst = new TExV2();
     var csp = new TExV2();
     return(Ex.Block(new ParameterExpression[] { cst, csp },
                     cst.Is(CosSinDeg(s.x)),
                     csp.Is(CosSinDeg(s.y)),
                     V3(cst.x.Mul(csp.y), cst.y.Mul(csp.y), csp.x)
                     ));
 }));
예제 #10
0
 /// <summary>
 /// Normalize a vector.
 /// </summary>
 public static tv3 Norm3(ev3 v3) => EEx.ResolveV3(v3, xyz => {
     var mag = VFloat();
     return(Ex.Block(new[] { mag },
                     mag.Is(v3Mag(xyz)),
                     Ex.Condition(mag.GT(ExC(M.MAG_ERR)),
                                  xyz.Mul(E1.Div(mag)),
                                  xyz
                                  )
                     ));
 });
예제 #11
0
 /// <summary>
 /// Normalize a vector.
 /// </summary>
 public static tv2 Norm(ev2 v2) => EEx.ResolveV2(v2, xy => {
     var mag = VFloat();
     return(Ex.Block(new[] { mag },
                     mag.Is(Mag(xy)),
                     Ex.Condition(mag.GT(ExC(M.MAG_ERR)),
                                  xy.Mul(E1.Div(mag)),
                                  xy
                                  )
                     ));
 });
예제 #12
0
 public static tfloat EBounce2(tfloat x) => EEx.Resolve <float>((Ex)x, c => {
     var c1 = VFloat();
     var c2 = VFloat();
     return(Ex.Block(new[] { c1, c2 },
                     c1.Is(Min(E05, c.Mul(ExC(0.95f)))),
                     c2.Is(Max(E0, c.Sub(E05))),
                     c1.Add(c2).Add(ExC(0.4f).Mul(
                                        Sin(tau.Mul(c1)).Add(Sin(tau.Mul(c2)))
                                        ))
                     ));
 }); //https://www.desmos.com/calculator/ix37mllnyp
예제 #13
0
 /// <summary>
 /// Move a value in the range [-540, 540] to the range [-180, 180] by adding or subtracting 360.
 /// </summary>
 /// <param name="ang_rad"></param>
 /// <returns></returns>
 public static tfloat DegIntoRange(efloat ang_rad) =>
 EEx.Resolve(ang_rad, a => Ex.Condition(a.GT(ExC(180f)),
                                        a.Sub(ExC(360f)),
                                        Ex.Condition(a.LT(ExC(-180f)),
                                                     a.Add(ExC(360f)),
                                                     a)));
예제 #14
0
 /// <summary>
 /// Move a value in the range [-2pi, 2pi] to the range [0,2pi] by adding tau.
 /// </summary>
 /// <param name="ang_rad"></param>
 /// <returns></returns>
 public static tfloat RadToPos(efloat ang_rad) => EEx.Resolve(ang_rad, a =>
                                                              Ex.Condition(a.LT0(), a.Add(tau), a));
예제 #15
0
 /// <summary>
 /// Move a value in the range [-2pi, 2pi] to the range [-2pi, 0] by subtracting tau.
 /// </summary>
 /// <param name="ang_rad"></param>
 /// <returns></returns>
 public static tfloat RadToNeg(efloat ang_rad) => EEx.Resolve(ang_rad, a =>
                                                              Ex.Condition(a.GT0(), a.Sub(tau), a));
예제 #16
0
 /// <summary>
 /// Move a value in the range [-3pi, 3pi] to the range [-pi, pi] by adding or subtracting tau.
 /// </summary>
 /// <param name="ang_rad"></param>
 /// <returns></returns>
 public static tfloat RadIntoRange(efloat ang_rad) =>
 EEx.Resolve(ang_rad, a => Ex.Condition(a.GT(pi),
                                        a.Sub(tau),
                                        Ex.Condition(a.LT(npi),
                                                     a.Add(tau),
                                                     a)));
예제 #17
0
 /// <summary>
 /// If x's absolute value is greater than by, then return 0 instead.
 /// </summary>
 public static tfloat HighCut(tfloat by, efloat x) =>
 EEx.Resolve(x, _x => Ex.Condition(Abs(_x).GT(by), E0, _x));
예제 #18
0
 /// <summary>
 /// Limit a value x to have absolute value leq by.
 /// </summary>
 /// <param name="by">Positive number for absolute value comparison</param>
 /// <param name="x">Number to be limited</param>
 /// <returns></returns>
 public static tfloat Limit(efloat by, efloat x) => EEx.Resolve(by, x, (_by, _x) =>
                                                                Ex.Condition(_x.GT0(), Min(_x, _by), Max(_x, Ex.Negate(_by))));
예제 #19
0
 /// <summary>
 /// Of two numbers, return the one with the larger absolute value.
 /// Not well-defined when x1 = -x2.
 /// </summary>
 public static tfloat MaxA(efloat x1, efloat x2) =>
 EEx.Resolve(x1, x2, (a, b) => Ex.Condition(Abs(a).GT(Abs(b)), a, b));
예제 #20
0
 /// <summary>
 /// = Floor(ex / block) * block
 /// </summary>
 public static tfloat BlockFloor(efloat block, tfloat ex) => EEx.Resolve(block,
                                                                         b => Floor(ex.Div(b)).Mul(b));
예제 #21
0
 /// <summary>
 /// = Round(ex / block) * block
 /// </summary>
 public static tfloat BlockRound(efloat block, tfloat ex) => EEx.Resolve(block,
                                                                         b => Round(ex.Div(b)).Mul(b));
예제 #22
0
 public static tfloat NPow(efloat bas, efloat exp) => EEx.Resolve(bas, exp, (x, y) =>
                                                                  Ex.Condition(Ex.LessThan(x, E0),
                                                                               Ex.Negate(Pow(Ex.Negate(x), y)),
                                                                               Pow(x, y)));
예제 #23
0
 /// <summary>
 /// Derive a V2RV2 from two vectors and a float.
 /// </summary>
 /// <param name="nrot">Nonrotational x,y</param>
 /// <param name="rot">Rotational x,y</param>
 /// <param name="angle">Rotational angle (degrees)</param>
 /// <returns></returns>
 public static trv2 V2V2F(ev2 nrot, ev2 rot, tfloat angle) => EEx.Resolve(nrot, rot, (_nr, _r) => {
     var nr = new TExV2(_nr);
     var r  = new TExV2(_r);
     return(VRV2(nr.x, nr.y, r.x, r.y, angle));
 });
예제 #24
0
 /// <summary>
 /// Return the angle in radians whose tangent is v2.y/v2.x.
 /// </summary>
 public static tfloat ATanR(ev2 f) => EEx.Resolve(f, v2 => {
     var tv2 = new TExV2(v2);
     return(_AtanYX.Of(tv2.y, tv2.x));
 });
예제 #25
0
 /// <summary>
 /// Returns the quantity x^2+y^2+z^2.
 /// </summary>
 public static tfloat SqrMag3(efloat x, efloat y, efloat z) => EEx.Resolve(x, y, z, (_x, _y, _z) =>
                                                                           _x.Mul(_x).Add(_y.Mul(_y).Add(_z.Mul(_z))));
예제 #26
0
 /// <summary>
 /// Returns the quantity x^2+y^2.
 /// </summary>
 public static tfloat SqrMag2(efloat x, efloat y) => EEx.Resolve(x, y, (_x, _y) => _x.Mul(_x).Add(_y.Mul(_y)));
예제 #27
0
 /// <summary>
 /// Derive a V2RV2 from a nonrotational vector and a rotational vector3.
 /// </summary>
 /// <param name="nrot">Nonrotational component</param>
 /// <param name="rot">Rotational component (x,y,angle)</param>
 /// <returns></returns>
 public static trv2 V2V3(ev2 nrot, ev3 rot) => EEx.Resolve(nrot, rot, (_nr, _r) => {
     var nr = new TExV2(_nr);
     var r  = new TExV3(_r);
     return(VRV2(nr.x, nr.y, r.x, r.y, r.z));
 });
예제 #28
0
 /// <summary>
 /// Get the square magnitude of a vector.
 /// </summary>
 public static tfloat SqrMag(ev2 v2) => EEx.ResolveV2(v2, xy => SqrMag2(xy.x, xy.y));
예제 #29
0
 /// <summary>
 /// Derive a color from a vector3 containing R, G, B components and an separate alpha component.
 /// </summary>
 public static tv4 TP3A(tfloat a, ev3 tp) => EEx.ResolveV3(tp, v3 => ExUtils.V4(v3.x, v3.y, v3.z, a));
예제 #30
0
 /// <summary>
 /// Get the square magnitude of a vector.
 /// </summary>
 public static tfloat v3SqrMag(ev3 v3) => EEx.ResolveV3(v3, xyz => SqrMag3(xyz.x, xyz.y, xyz.z));