我如何简化这个数学方法(旋转到步骤)

How do i simplify this math method (rotations to steps)

所以我正在为统一创建一个捕捉工具包,我想通过特定值来限制旋转的捕捉增量。

您可以按 2.5、5、10、15、30、45 和 90 的增量捕捉旋转(这样当用户旋转对象时,它只会旋转该增量值)。

我有一个带有滑块的工具栏,滑块有 7 个步长(0-6),每个步长代表一个旋转。所以我需要将旋转转换为步数。

代码和功能已经完成,但是将旋转转换为步进和反之的函数又长又难看。可以simplify/shorten吗?

步数和旋转:

Step Rotation
0 2.5
1 5
2 10
3 15
4 30
5 45
6 90

代码:

        private float ConvertFromStepToRotation(int step)
    {
        switch (step)
        {
            case 0:
                return 2.5f;
            case 1:
                return 5;
            case 2:
                return 10;
            case 3:
                return 15;
            case 4:
                return 30;
            case 5:
                return 45;
            case 6:
                return 90;
        }

        return 15;
    }

    private int ConvertFromRotationToStep(float rotation)
    {
        if (rotation >= 90)
        {
            return 6;
        }

        if (rotation >= 45)
        {
            return 5;
        }

        if (rotation >= 30)
        {
            return 4;
        }

        if (rotation >= 15)
        {
            return 3;
        }

        if (rotation >= 10)
        {
            return 2;
        }

        if (rotation >= 5)
        {
            return 1;
        }

        if (rotation >= 2.5f)
        {
            return 0;
        }

        return 2;
    }

没什么大不了的,只是让我唠叨应该有更好的方法

编辑:尝试让 table 正常工作

看来我们可以用数组让它更漂亮。

ConvertFromStepToRotation 是一个明显的候选者:我们只是将索引转换为相应的值,因此我们可以使用它来索引值数组。

ConvertFromRotationToStep 稍微有点棘手,但我们可以向后遍历数组,return 是 rotation >= steps[i].

的第一个索引
private static readonly float[] steps = new[] { 2.5f, 5f, 10f, 15f, 30f, 45f, 90f };

private float ConvertFromStepToRotation(int step)
{
    if (step < steps.Length)
    {
        return steps[step];
    }
    
    return 15f;
}

private int ConvertFromRotationToStep(float rotation)
{
    for (int i = steps.Length - 1; i >= 0; i++)
    {
        if (rotation >= steps[i])
        {
            return i;
        }
    }
    
    return 2;
}

对于一个很好的偏执解决方案,步骤 s 可以通过 one-liner

从角度 a 获得
s = floor(log(a)/log(√3)-1.5).

在你不能依赖数组索引的情况下(或者你想更好地控制哪个步骤引用哪个旋转),你可以选择将关系存储在字典中:

//using System.Collections.Generic;

private Dictionary<int, float> rotationForStep = new()
{
    [0] = 2.5f,
    //...
    [6] = 90
};

并实施您的方法,例如如下:

//using System.Linq;

private float ConvertFromStepToRotation(int step)
{
    if (rotationForStep.TryGetValue(step, out float rotation))
    {
        return rotation;
    }
    
    return 15;
}

private int ConvertFromRotationToStep(float rotation)
{
    if (rotationForStep.Values.Any(v => v <= rotation))
    {
        return rotationForStep
            .Where(r => r.Value <= rotation)
            .MaxBy(r => r.Value)
            .Key;
    }
    
    return 2;
}

或者最后一种方法:

//using System.Linq;

private int ConvertFromRotationToStep(float rotation)
{
    var possibleRotations = rotationForStep.Where(r => r.Value <= rotation);
    
    if (possibleRotations.Any())
    {
        return possibleRotations.MaxBy(r => r.Value).Key;
    }
    
    return 2;
}