/// <summary> /// Adds a data point. /// </summary> /// <param name="p">Data point to add.</param> /// <returns>True if the spline was modified.</returns> public bool Add(VECTOR p) { CurveBuilder.AddPointResult res = _builder.AddPoint(p); if (!res.WasChanged) return false; // update spline ReadOnlyCollection<CubicBezier> curves = _builder.Curves; if (res.WasAdded && curves.Count == 1) { // first curve Debug.Assert(_spline.Curves.Count == 0); _spline.Add(curves[0]); } else if (res.WasAdded) { // split _spline.Update(_spline.Curves.Count - 1, curves[res.FirstChangedIndex]); for (int i = res.FirstChangedIndex + 1; i < curves.Count; i++) _spline.Add(curves[i]); } else { // last curve updated Debug.Assert(res.FirstChangedIndex == curves.Count - 1); _spline.Update(_spline.Curves.Count - 1, curves[curves.Count - 1]); } return true; }
/// <summary> /// Tries to fit single Bezier curve to the points in [first ... last]. Destroys anything in <see cref="_u"/> in the process. /// Assumes there are at least two points to fit. /// </summary> /// <param name="first">Index of first point to consider.</param> /// <param name="last">Index of last point to consider (inclusive).</param> /// <param name="tanL">Tangent at teh start of the curve ("left").</param> /// <param name="tanR">Tangent on the end of the curve ("right").</param> /// <param name="curve">The fitted curve.</param> /// <param name="split">Point at which to split if this method returns false.</param> /// <returns>true if the fit was within error tolerence, false if the curve should be split. Even if this returns false, curve will contain /// a curve that somewhat fits the points; it's just outside error tolerance.</returns> protected bool FitCurve(int first, int last, VECTOR tanL, VECTOR tanR, out CubicBezier curve, out int split) { List<VECTOR> pts = _pts; int nPts = last - first + 1; if (nPts < 2) { throw new InvalidOperationException("INTERNAL ERROR: Should always have at least 2 points here"); } else if (nPts == 2) { // if we only have 2 points left, estimate the curve using Wu/Barsky VECTOR p0 = pts[first]; VECTOR p3 = pts[last]; FLOAT alpha = VectorHelper.Distance(p0, p3) / 3; VECTOR p1 = (tanL * alpha) + p0; VECTOR p2 = (tanR * alpha) + p3; curve = new CubicBezier(p0, p1, p2, p3); split = 0; return true; } else { split = 0; ArcLengthParamaterize(first, last); // initially start u with a simple chord-length paramaterization curve = default(CubicBezier); for (int i = 0; i < MAX_ITERS + 1; i++) { if (i != 0) Reparameterize(first, last, curve); // use newton's method to find better parameters (except on first run, since we don't have a curve yet) curve = GenerateBezier(first, last, tanL, tanR); // generate the curve itself FLOAT error = FindMaxSquaredError(first, last, curve, out split); // calculate error and get split point (point of max error) if (error < _squaredError) return true; // if we're within error tolerance, awesome! } return false; } }
public static bool IsInsideAngle(Point vectorOriginPoint, System.Windows.Vector v1, System.Windows.Vector v2, Point p) { var center = vectorOriginPoint; //make angle with 2 vectors var angle = System.Windows.Vector.AngleBetween(v1, v2); var halfAngle = angle / 2; v1.Normalize(); v2.Normalize(); //vector that bisects angle between v1 and v2 var bisector = v1 + v2; bisector.Normalize(); var vectorToPoint = new System.Windows.Vector(p.X - center.X, p.Y - center.Y); vectorToPoint.Normalize(); var AngleBetweenBisectorAndVectorToPoint = Math.Abs(System.Windows.Vector.AngleBetween(bisector, vectorToPoint)); //if angle between bisector and vector to point p is less than half of angle v1v2 then point lies inside the angle return AngleBetweenBisectorAndVectorToPoint <= halfAngle; }
private PointF[] profileNaca(PointF p1, PointF p2) { double d = (GetDistanceBetween(p1, p2) / Double.Parse(tb_real_length.Text.Replace(".", ","))) * 100; int distance = (int)d; System.Windows.Vector v1 = new System.Windows.Vector(p2.X - p1.X, p2.Y - p1.Y); System.Windows.Vector v2 = new System.Windows.Vector(1, 0); double angleBetween = System.Windows.Vector.AngleBetween(v1, v2); angleBetween = angleBetween * Math.PI / 180; float sin = (float)Math.Sin(angleBetween); float cos = (float)Math.Cos(angleBetween); double xTmp, yTmp; float xMiddleBtwnAB =0; float yMiddleBtwnAB =0; cal_A = A; cal_B = B; if (!(A == null || B == null)) { xTmp = A.X * cos + A.Y * sin; //rotating yTmp = -A.X * sin + A.Y * cos; xTmp = xTmp * d + p1.X; // mooving and scaling yTmp = yTmp * d + p1.Y; cal_A.X = (float)xTmp; cal_A.Y = (float)yTmp; xTmp = B.X * cos + B.Y * sin; //rotating yTmp = -B.X * sin + B.Y * cos; xTmp = xTmp * d + p1.X; // mooving and scaling yTmp = yTmp * d + p1.Y; cal_B.X = (float)xTmp; cal_B.Y = (float)yTmp; xMiddleBtwnAB = B.X * cos + ((A.Y - B.Y) / 2 + B.Y) * sin; //rotating yMiddleBtwnAB = -B.X * sin + ((A.Y - B.Y) / 2 + B.Y) * cos; xMiddleBtwnAB = (float)(xMiddleBtwnAB * d + p1.X); // mooving and scaling yMiddleBtwnAB = (float)(yMiddleBtwnAB * d + p1.Y); } List<PointF> testList = new List<PointF>(); bool flagIfOverRealLenght = false; foreach (PointF p in nacaProfile) { if (p.X > A.X) { if (!flagIfOverRealLenght) { testList.Add(cal_A); testList.Add(new PointF(xMiddleBtwnAB, yMiddleBtwnAB)); testList.Add(new PointF(p1.X, p1.Y)); flagIfOverRealLenght = true; } continue; } xTmp = p.X * cos + p.Y * sin; //rotating yTmp = -p.X * sin + p.Y * cos; xTmp = xTmp * d + p1.X; // mooving and scaling yTmp = yTmp * d + p1.Y; testList.Add(new PointF((float)xTmp, (float)yTmp)); } testList.Add(cal_B); testList.Add(new PointF(xMiddleBtwnAB, yMiddleBtwnAB)); return testList.ToArray(); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT DistanceSquared(VECTOR a, VECTOR b) { return((a - b).LengthSquared); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static VECTOR Normalize(VECTOR v) { return VECTOR.Normalize(v); }
public static VECTOR Lerp(VECTOR a, VECTOR b, FLOAT amount) { return(VECTOR.Lerp(a, b, amount)); }
public static VECTOR Normalize(VECTOR v) { return VECTOR.Normalize(v); }
public static FLOAT GetX(VECTOR v) { return v.X; }
public static FLOAT Distance(VECTOR a, VECTOR b) { return VECTOR.Distance(a, b); }
public static FLOAT LengthSquared(VECTOR v) { return v.sqrMagnitude; }
public static bool EqualsOrClose(VECTOR v1, VECTOR v2) { return(DistanceSquared(v1, v2) < EPSILON); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT DistanceSquared(VECTOR a, VECTOR b) { return (a - b).LengthSquared; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static VECTOR Lerp(VECTOR a, VECTOR b, FLOAT amount) { return(VECTOR.Lerp(a, b, amount)); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT Dot(VECTOR a, VECTOR b) { return(VECTOR.Dot(a, b)); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT DistanceSquared(VECTOR a, VECTOR b) { return(VECTOR.DistanceSquared(a, b)); }
public static FLOAT GetY(VECTOR v) { return(v.Y); }
public static FLOAT GetX(VECTOR v) { return(v.X); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static VECTOR Normalize(VECTOR v) { v.Normalize(); return v; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT Dot(VECTOR a, VECTOR b) { return(a.X * b.X + a.Y * b.Y); }
public static VECTOR Normalize(VECTOR v) { v.Normalize(); return v; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static VECTOR Normalize(VECTOR v) { v.Normalize(); return(v); }
public static FLOAT DistanceSquared(VECTOR a, VECTOR b) { return (a - b).LengthSquared; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT LengthSquared(VECTOR v) { return(v.LengthSquared); }
public static FLOAT LengthSquared(VECTOR v) { return v.LengthSquared; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static VECTOR Lerp(VECTOR a, VECTOR b, FLOAT amount) { return(new VECTOR(a.X + ((b.X - a.X) * amount), a.Y + ((b.Y - a.Y) * amount))); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT DistanceSquared(VECTOR a, VECTOR b) { return VECTOR.DistanceSquared(a, b); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT GetY(VECTOR v) { return(v.Y); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static VECTOR Lerp(VECTOR a, VECTOR b, FLOAT amount) { return VECTOR.Lerp(a, b, amount); }
public static FLOAT Distance(VECTOR a, VECTOR b) { return(VECTOR.Distance(a, b)); }
public static VECTOR Normalize(VECTOR v) { v.Normalize(); return(v); }
/// <summary>Converts a BCL Vector to a Loyc point.</summary> public static Vector <double> AsLoyc(this System.Windows.Vector p) { return(new Vector <double>(p.X, p.Y)); }
private void UpdateInfo() { if (tabControl1.SelectedTab.Equals(tabAnalyze) && !images.getActual().point1.IsEmpty() && !images.getActual().point2.IsEmpty()) { //vertical shift images.getActual().plunge = (float)(Math.Round(((imageBox.Image.Size.Height - GetElasticAxis().location.Y) - MeasureParameters.w0), 2)); l_plunge.Text = px2mm(images.getActual().plunge).ToString(); //pitch System.Windows.Vector v1 = new System.Windows.Vector(images.getActual().point2.Point.X - images.getActual().point1.Point.X, images.getActual().point2.Point.Y - images.getActual().point1.Point.Y); System.Windows.Vector v2 = new System.Windows.Vector(1, 0); double angleBetween = System.Windows.Vector.AngleBetween(v1, v2); angleBetween *= -1; images.getActual().pitch = (float)Math.Round(angleBetween, 2); l_pitch.Text = Math.Round(images.getActual().pitch,3).ToString() + "°"; if (images.getPosition() > 1) { images.getActual().vel_plunge = (images.getActual().plunge - images.get(images.pointer - 1).plunge) / MeasureParameters.dTau; images.getActual().vel_pitch = (images.getActual().pitch - images.get(images.pointer - 1).pitch) / MeasureParameters.dTau; l_plunge_vel.Text = px2mm(images.getActual().vel_plunge).ToString(CultureInfo.CreateSpecificCulture("en-GB")); l_pitch_vel.Text = Math.Round(images.getActual().vel_pitch, 3).ToString(CultureInfo.CreateSpecificCulture("en-GB")); } else { l_plunge_vel.Text = "NaN"; l_pitch_vel.Text = "NaN"; } } else { l_plunge_vel.Text = l_pitch_vel.Text = l_pitch.Text = l_plunge.Text = "-"; } tb_description.Text = images.getActual().description; }
public override void onAttach() { base.onAttach(); clickPoint = new Vector(0, 0); direction = new Vector(0, 0); }
public static bool EqualsOrClose(VECTOR v1, VECTOR v2) { return DistanceSquared(v1, v2) < EPSILON; }
private void OnPositionChanged(Vector newPos) { direction = newPos - startPosWorld; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT Dot(VECTOR a, VECTOR b) { return a.X * b.X + a.Y * b.Y; }
public static double Dot(this System.Windows.Vector start, System.Windows.Vector end) { return(start.X * end.Y - start.Y * end.X); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static VECTOR Lerp(VECTOR a, VECTOR b, FLOAT amount) { return new VECTOR(a.X + ((b.X - a.X) * amount), a.Y + ((b.Y - a.Y) * amount)); }
public RotateItemOperation(SceneEditorViewModel sceneEditor, EditorItem editorItem, Vector initialMousePosition) : base(editorItem, initialMousePosition) { _sceneEditor = sceneEditor; var initialMouseFromCenter = initialMousePosition - editorItem.GetPositionInScreenSpace(); _initialAngle = editorItem.Transformation.LocalRotation; _initialMouseAngle = (float)Math.Atan2(-initialMouseFromCenter.Y, initialMouseFromCenter.X); _rotationTracker = new RotationTracker(_initialMouseAngle, _initialAngle); }
public static FLOAT DistanceSquared(VECTOR a, VECTOR b) { float dx = a.x - b.x; float dy = a.y - b.y; return dx*dx + dy*dy; }
public Sphere(Vector position, Vector speed, int radius) { this.position = position; this.speed = speed; this.radius = radius; }
public static FLOAT Length(VECTOR v) { return v.magnitude; }
public Kamopis(PointF pos, Vector speed, float t, float vt, SizeF size) : this(pos.X, pos.Y, (float)speed.X, (float)speed.Y, t, vt, size.Width, size.Height) { }
public static FLOAT Distance(VECTOR a, VECTOR b) { return (a - b).Length; }
protected void ClickAt(Vector point, Action callback) { MouseOperations.Click(point.ToPoint(), callback); }
public static FLOAT Dot(VECTOR a, VECTOR b) { return VECTOR.Dot(a, b); }
protected void ClickAt(Vector point, Action callback, EClickType clickType) { MouseOperations.Click(point.ToPoint(), callback, clickType); }
public static FLOAT Length(VECTOR v) { return v.Length; }
public static Vector2 FromWpfVector(System.Windows.Vector vector) { return(new Vector2( (float)vector.X, (float)vector.Y)); }
public static VECTOR Lerp(VECTOR a, VECTOR b, FLOAT amount) { return VECTOR.Lerp(a, b, amount); }
/// <summary> /// Runs the main car logic. Needs to be subscribed to the MainLoop. /// </summary> public void Update() { // If we're not initialized, initialize! if (!initialized) { Init(); } // Update the passenger count. Car.PassengerCount = Car.Passengers.Count; // Update the current road with the road at our location. Car.CurrentRoad = GPSSystem.GetRoad(Car.Location); Car.CurrentIntersection = GPSSystem.FindIntersection(Car.Location); if (Car.CurrentRoad == null && Car.CurrentIntersection == null) { if (!resetTarget) { resetTarget = true; var closestRoad = GPSSystem.NearestRoad(Car.Location); if (closestRoad != null && Car != null) { Car.CurrentTarget = MathUtil.Distance(closestRoad.End, Car.Location) > MathUtil.Distance(closestRoad.Start, Car.Location) ? closestRoad.Start : closestRoad.End; App.Console.Print($"[C{Car.Id}] Lost road, trying to get back on, targeting {Car.CurrentTarget}", Colors.Blue); } ; } } else if (resetTarget) { App.Console.Print($"[C{Car.Id}] Road found again", Colors.Blue); resetTarget = false; } // Calculate the distance to the local target (usually the next intersection). var distanceToTarget = MathUtil.Distance(Car.Location, Car.CurrentTarget); // Calculate the distance to the destination. var distanceToDestination = MathUtil.Distance(Car.Location, Car.Destination.Location); // Calculate the relative yaw (in degrees). var yaw = MathUtil.VectorToAngle(Car.Rotation, Car.Direction); // Get the current velocity of the car. var velocity = Car.Velocity; // Create a variable to store the added rotation in this update call. var addedRotation = 0.0; var closeToDestination = CloseToDestination(); // Check if we're close to our target but not the destination. if (distanceToTarget < 20 && !closeToDestination && !resetTarget) { // Check if we've not obtained a new target yet. if (!obtainedNewTarget) { // Find the nearest intersection. var intersection = GPSSystem.FindIntersection(GetClosestRoadPoint(Car.Location)); if (intersection == null) { return; } App.Console.Print($"[C{Car.Id}] Requesting new target from intersection {intersection.Location}...", Colors.Blue); // Request the next target from the GPSSystem. var target = GPSSystem.GetDirection(Car, intersection); // Update our target. newTarget = target.Location; obtainedNewTarget = true; var distance = Math.Round(MathUtil.Distance(newTarget, Car.Location)); App.Console.Print($"[C{Car.Id}] Obtained a new target {newTarget} ({distance}m away)", Colors.Blue); } } else { obtainedNewTarget = false; } // Check if we are turning. if (turning > 0) { turning--; // Check if we locked on the new target yet. if (newTarget.X > -1) { // Lock on the new target and reset newTarget. Car.CurrentTarget = newTarget; newTarget = new Vector(-1, -1); App.Console.Print($"[C{Car.Id}] Locked on to target", Colors.Blue); } // Call the handle function to turn. HandleTurn(ref velocity, ref yaw, ref addedRotation); } // Check if we're still turning around. else if (flipping) { // Stop turning around. flipping = false; App.Console.Print($"[C{Car.Id}] Turn-around done", Colors.Blue); } // Check if we're on an intersection. if (Car.CurrentIntersection != null) { // Reset our turn timer. turning = 20; } else { // Check if we're not close to the destination. if (!closeToDestination) { // If we're still approaching, stop approaching. if (approach) { approach = false; App.Console.Print($"[C{Car.Id}] Approach done", Colors.Blue); } // Call the handle functions to stay in the lane and accelerate/deccelerate. HandleStayInLane(ref velocity, ref yaw, ref addedRotation); HandleAccelerate(ref velocity, ref distanceToTarget); } else { // If we're not approaching, start approaching. if (!approach) { approach = true; App.Console.Print($"[C{Car.Id}] Initiating approach", Colors.Blue); } // Call the handle function to approach the target. HandleApproachTarget(ref velocity, ref yaw, ref addedRotation, ref distanceToDestination); } } // Update the car's velocity with the result of the handle functions: // Temporarily store the current speed. var speed = velocity.Length; // Rotate the velocity based on the addedRotation this tick. velocity = MathUtil.RotateVector(velocity, -addedRotation); // Normalize the velocity and multiply with the speed to make sure it stays the same. velocity.Normalize(); velocity = Vector.Multiply(velocity, speed); // Actually update the car's velocity. Car.Velocity = velocity; // Calculate the rotation by normalizing the velocity. var rotation = new Vector(velocity.X, velocity.Y); rotation.Normalize(); // If the rotation vector is invalid or the car is not moving, set the rotation to the absolute direction. if (rotation.Length < 0.9 || double.IsNaN(rotation.Length) || velocity.Length < 0.1) { rotation = Car.Direction.GetVector(); } // Actually update the rotation and update the absolute direction. Car.Rotation = rotation; Car.Direction = DirectionCarMethods.Parse(rotation); // Update the car's location by adding the velocity to it. Car.Location = Vector.Add(Car.Location, Car.Velocity); Car.DistanceTraveled += Car.Velocity.Length; }
public static FLOAT GetY(VECTOR v) { return v.Y; }
/* * All the Handle functions take references to variable from the Update function. * They will modify these variables to change behaviour of the car. The value of * these variables shouldn't be overwritten, but only changed (adding, multiplying, etc) */ /// <summary> /// Makes the car turn on an intersection towards the target. /// </summary> /// <param name="velocity">Current velocity of the car</param> /// <param name="yaw">Current relative yaw of the car</param> /// <param name="addedRotation">Amount of rotation (in degrees) to add</param> public void HandleTurn(ref Vector velocity, ref double yaw, ref double addedRotation) { // Get the current speed and rotation of the car. var speed = velocity.Length; var rotation = MathUtil.VelocityToRotation(velocity); var intersection = Car.CurrentIntersection; // If we're going too fast to turn, slow down. if (speed > maxTurningSpeed) { velocity = Vector.Add(velocity, CalculateDeccelerationVector(velocity)); } // If we're not on the intersection yet, just keep driving straight. if (intersection == null) { HandleStayInLane(ref velocity, ref yaw, ref addedRotation); return; } // Get the target and current location. var target = Car.CurrentTarget; var location = Car.Location; // Calculate the angle between the car and the target. var targetAngle = new Vector( target.X - location.X, target.Y - location.Y ); var angle = Vector.AngleBetween(rotation, targetAngle); if (angle < 0) { angle += 360; } // If the angle is more than 225 degrees (-90 - 45), rotate to the left. if (angle > 225 && angle < 315) { // If we're not turning around, slowly turn left. if (!flipping) { addedRotation += rotationSpeed * 0.8; } // If we are turning around, keep steering steeply left. else { addedRotation += rotationSpeed * 6; } } // If the angle is more than 135 degrees (180 - 45), turn around. else if (angle > 135 && angle < 315) { if (!flipping) { flipping = true; App.Console.Print($"[C{Car.Id}] Initiating turn-around", Colors.Blue); } addedRotation += rotationSpeed * 6; } // If the angle is more than 45 degrees (90 - 45), rotate to the right. else if (angle > 45 && angle < 315) { addedRotation -= rotationSpeed * 6; } // Otherwise, keep going straight. else { addedRotation = yaw < 0 ? rotationSpeed : -rotationSpeed; } }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT Dot(VECTOR a, VECTOR b) { return VECTOR.Dot(a, b); }
private static void MouseMovement_DeadZoning() { // Each game may use "dead zones" of different size and shape to eliminate near-but-not-zero readings // that controllers give at rest. (See https://itstillworks.com/12629709/what-is-a-dead-zone-in-an-fps.) // Since mice do not suffer from this phenomenon at rest, users expect reaction out of the minimum // possible mouse movements. To translate this to joystick positions effectively, we want that single // pixel of mouse movement to position the joystick just past the joystick dead zone. (For effective // mouse control of any given game, we will have to discover and track dead zone details as part of the // control profile settings, or provide an auto-discovery mechanism that watches for screen change in // order to automatically determine the dead zone details. Difficult, but doable. TODO: ATTEMPT THIS!) // Possibly other details would need to be stored per game, as advanced techniques to combat other // game-specific joystick assists (weird accelerations and such) get figured out. Either way, usually // the user should get best results out of tuning their in-game sensitivities way up, to allow for the // mouse-to-joystick translation to yield a high, accurate range, including fast mouse flicks to attain // fast turning. // Dead zones are usually square or circular, meaning the game will ignore small stick positions when: // * The absolute X and Y values of the stick are less than some value (for a "square" dead zone). // * The (X,Y) vector length is less than some value (for a "circular" dead zone). // For simplicity, we'll assume circular dead zones, because the math to scale into the range of legal // non-ignored values for a square dead zone is more complicated than may appear (so the first attempt // was glitchy), and vector math results work quite well regardless of the dead zone shape. // Grab and reset mouse position and time passed, for calculating mouse velocity for this polling. var mouseX = Cursor.Position.X; var mouseY = Cursor.Position.Y; Cursor.Position = centered; var timeSinceLastPoll = stopwatch.Elapsed.TotalMilliseconds; stopwatch.Restart(); // Mouse velocity here is average pixels per milliseconds passed since the last polling. This helps // get correct-feeling, smooth movements, even if the thread pool is not being particularly nice to // our polling thread ATM. For example, if the thread pool gives us a 22ms cycle from last poll with // 11 pixels of movement on one pass, then gave us a 16ms cycle with 8 pixels of movement on another, // we'd want the same final stick position for both since the user did not vary their mouse velocity. // Also invert these values now if the user has configured input inversion. var changeX = Program.ActiveConfig.Mouse_Invert_X ? centered.X - mouseX : mouseX - centered.X; var changeY = Program.ActiveConfig.Mouse_Invert_Y ? mouseY - centered.Y : centered.Y - mouseY; double sensitivityScaleX = Program.ActiveConfig.Mouse_Sensitivity_X / 1000.0; double sensitivityScaleY = Program.ActiveConfig.Mouse_Sensitivity_Y / 1000.0; double velocityX = changeX * sensitivityScaleX / timeSinceLastPoll; double velocityY = changeY * sensitivityScaleY / timeSinceLastPoll; short joyX = 0, joyY = 0; var deadZoneSize = Program.ActiveConfig.DeadZoneSize; if (deadZoneCalibrator != null) { // Pretend the mouse is always moving one pixel in each axis, until user intervention. deadZoneSize = deadZoneCalibrator.AdvanceDeadZoneSize(); joyX = Convert.ToInt16(deadZoneSize); joyY = 0; } else if (velocityX != 0 || velocityY != 0) { // Find the percentage of the max mouse vector was travelled, in order to scale the final // vector by the full dead zone plus the same percent of the non-dead-zone area. // This will allow tiny movements to be just outside the dead-zone but in the correct // vector, while large movements scale out to the outer edge of possible stick positions, // but still at the correct proportions. var mouseVectorLengthToReachMaxStickPosition = 5d; var mouseVector = new System.Windows.Vector(velocityX, velocityY); var percentMouseMagnitude = mouseVector.Length / mouseVectorLengthToReachMaxStickPosition; percentMouseMagnitude = Math.Min(percentMouseMagnitude, 1.0); // Normalize the mouse vector in preparation for changing to the target stick scale. mouseVector.Normalize(); // The mouseVector is now a raw direction that we want to multiply up into the stick // range past the (assumed-to-be-circular) dead zone. var remainingStickMagnitude = short.MaxValue - deadZoneSize; var targetMagnitude = deadZoneSize + remainingStickMagnitude * percentMouseMagnitude; mouseVector *= targetMagnitude; joyX = Convert.ToInt16(mouseVector.X); joyY = Convert.ToInt16(mouseVector.Y); } // Send Axis SetAxis(joyX, joyY); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT LengthSquared(VECTOR v) { return v.LengthSquared(); }
public static FLOAT DistanceSquared(VECTOR a, VECTOR b) { float dx = a.x - b.x; float dy = a.y - b.y; return(dx * dx + dy * dy); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static FLOAT GetY(VECTOR v) { return v.Y; }
public static FLOAT Dot(VECTOR a, VECTOR b) { return(VECTOR.Dot(a, b)); }