C++ 圆上两个度标记之间的最短距离?

C++ 圆上两个度标记之间的最短距离?,c++,trigonometry,geometry,C++,Trigonometry,Geometry,我正在寻找一个公式来计算圆上两个度标记之间的最短距离(以度为单位):例如,30度和170度(140度) 两个度标记实际上可以是任何实数,并且不一定在0和360之间(可以是负数,或者远大于360,例如-528.2和740(即171.8度))。但是,距离应始终为=0度 听起来很简单。但是,我一直在试图找到一个很好的解决方案,我尝试了很多不同的代码,但到目前为止,我发现在我尝试过的所有情况下,没有任何东西是有效的。我在C++中工作。有人有什么想法吗?你可以将这里的公式()应用于两个角度和两个方向。 所

我正在寻找一个公式来计算圆上两个度标记之间的最短距离(以度为单位):例如,30度和170度(140度)

两个度标记实际上可以是任何实数,并且不一定在0和360之间(可以是负数,或者远大于360,例如-528.2和740(即171.8度))。但是,距离应始终为=0度


听起来很简单。但是,我一直在试图找到一个很好的解决方案,我尝试了很多不同的代码,但到目前为止,我发现在我尝试过的所有情况下,没有任何东西是有效的。我在C++中工作。有人有什么想法吗?

你可以将这里的公式()应用于两个角度和两个方向。 所以你可以找到两个互补的距离(如果你把它们加起来,你就会得到周长(或者你可以通过从周长中减去另一个弧的长度得到一个弧的长度)

然后可以比较这两个长度,以获得不同角度的两点之间的最小距离


在C++中,你得到了数学.h库:

当然,你需要导入数学库,对于fMOD和Fab。

double a = -528.2;
double b = 740.0;
double diff = (a > b ? a - b : b - a);
double mod_diff = fmod(diff, 360);
double result = (mod_diff < 180 ? mod_diff : 360 - mod_diff);
double a=-528.2;
双b=740.0;
双差=(a>b?a-b:b-a);
双模差=fmod(差,360);
双结果=(模差<180?模差:360-模差);
  • 步骤1:获取“原始”差异。例如,给定
    -528.2
    740.0
    ,这是
    1268.2

    • 单向:
      raw_diff=first>second?first-second:second-first
    • 另一种方式:
      raw_diff=std::fabs(第一秒)
  • 步骤2:减去
    360.0
    的倍数,得到
    0.0
    (包含)和
    360.0
    (排除)之间的值

    • mod_diff=std::fmod(原始差异,360.0)
  • 步骤3:如果该值大于
    180.0
    ,则从
    360.0
    中减去该值

    • 单向:
      dist=mod_diff>180.0?360.0-mod_diff:mod_diff
    • 另一种方式:
      dist=180.0-std::fabs(mod_diff-180.0)
它可能是最可读的一系列语句:

double raw_diff = first > second ? first - second : second - first;
double mod_diff = std::fmod(raw_diff, 360.0);
double dist = mod_diff > 180.0 ? 360.0 - mod_diff : mod_diff;
但是,如果需要的话,将其全部放在一个表达式中并不困难:

180.0 - std::fabs(std::fmod(std::fabs(first - second), 360.0) - 180.0)

你也可以使用向量数学和三角学;这里的角度是弧度

float angle(float angle1, float angle2)
{
  float x1=cos(angle1);
  float y1=sin(angle1);
  float x2=cos(angle2);
  float y2=sin(angle2);

  float dot_product = x1*x2 + y1*y2;
  return acos(dot_product);
}

你可以试着得到剩余两个角度之差除以360的绝对值

#include <iostream>
#include <cmath>

using namespace std;
int degree_difference(int a, int b)
{
    return abs(a%360-b%360);
}

int main()
{
    int result = degree_difference(-235, 15);
    cout << "Difference: " << result << endl;
    return 0;
}
#包括
#包括
使用名称空间std;
整数阶差(整数a,整数b)
{
返回abs(a%360-b%360);
}
int main()
{
int结果=度差(-235,15);

我们必须假设一个圆只有360度,否则它会变得很棘手

所以,首先你要做的是让每个标记都在0到360之间。要做到这一点,你可以将两个标记的模数都取360。如果数量小于0,那么再加360

假设我们的分数是520和-45

mark1 = ((520 % 360) >= 0) ? (520 % 360) : 360 - (520 % 360);

mark2 = ((-45 % 360) >= 0) ? (-45 % 360) : 360 - (-45 % 360);
标记1为160。标记2为315

现在只需取差值的绝对值:

result = abs(mark1 - mark2) = 155

我也有类似的问题要找

  • 圆中任意点到任意点的最短距离。 我得到的解决方案如下:
如果N=圆中的点数

其中,j是第二点,i是第一点

下面是解决方案的小python代码

for i in range(0, n):
   for j in range(i,n):
          if j < n/2+i:
                 s_rt = j-i
          else :
                 s_rt = n-j+i
范围(0,n)内的i的
:
对于范围(i,n)内的j:
如果j

我认为这可以通过稍微调整度数来找到解决方案。

我一直在为变速箱寻找这样的微控制器解决方案,寻找animatronic木偶,但我没有足够的精力来正确计算触发器

@鲁克的回答是一个很好的基础,但我发现这个标志在某些情况下被错误地翻转了

这是一个对我有效的解决方案。这个解决方案适用于圆中的度标记,但更改
MAX_值
允许它适用于任意的最大范围,这在测量齿轮编码器脉冲时非常有用

在Arduino上测试

#define MAX_VALUE 360

float shortestSignedDistanceBetweenCircularValues(float origin, float target){

  float signedDiff = 0.0;
  float raw_diff = origin > target ? origin - target : target - origin;
  float mod_diff = fmod(raw_diff, MAX_VALUE); //equates rollover values. E.g 0 == 360 degrees in circle

  if(mod_diff > (MAX_VALUE/2) ){
    //There is a shorter path in opposite direction
    signedDiff = (MAX_VALUE - mod_diff);
    if(target>origin) signedDiff = signedDiff * -1;
  } else {
    signedDiff = mod_diff;
    if(origin>target) signedDiff = signedDiff * -1;
  }

  return signedDiff;

}

对于像我这样的初学者来说,其他答案——虽然很可能会给你一个好的结果——有点难以理解到底发生了什么。因此,我的方法是检查cp(当前点)和tp(目标点)之间哪个方向(顺时针或逆时针)最短。它还将最短距离值指定给最短距离变量。根据我特别需要此方法的原因,返回布尔值以确定最短距离是顺时针方向还是逆时针方向对我来说很重要。以下是方法:

public boolean checkIfClockwiseIsShortest(int cp, int tp) {
    boolean clockwiseIsShortest = false;
    if (cp != tp) { // if current point and target point are not the same...
        if (tp > cp) { // if current point is less than target point AND..
            if ((tp - cp) <= ((360 - tp) + cp)) {
                clockwiseIsShortest = true;
                shortestDistance = (tp-cp);
                System.out.println("Case A: " + shortestDistance +" degrees clockwise");//[CAN REMOVE]

            } else if ((tp - cp) > ((360 - tp) + cp)) {
                clockwiseIsShortest = false;
                shortestDistance = ((360 - tp) + cp);
                System.out.println("Case B: " + shortestDistance+" degrees counter-clockwise");//[CAN REMOVE]
            }
        } else { // BUT if target point < current point
            if ((cp - tp) <= ((360 - cp) + tp)) {
                clockwiseIsShortest = false;
                shortestDistance = (cp-tp);
                System.out.println("Case C: " + shortestDistance+" degrees counter-clockwise");//[CAN REMOVE]
            } else if ((cp - tp) > ((360 - cp) + tp)) {
                clockwiseIsShortest = true;
                shortestDistance = ((360 - cp) + tp);
                System.out.println("Case D: " + shortestDistance+" degrees clockwise");//[CAN REMOVE]
            }
        }
    }
    return clockwiseIsShortest;
}
public boolean checkIfClockwiseIsShortest(int-cp,int-tp){
布尔clockwiseIsShortest=false;
如果(cp!=tp){//如果当前点和目标点不相同。。。
如果(tp>cp){//如果当前点小于目标点并且。。
如果((tp-cp)((360-tp)+cp)){
clockwiseIsShortest=假;
最短距离=((360-tp)+cp);
System.out.println(“案例B:+最短距离+”逆时针角度”);//[可以删除]
}
}else{//但如果目标点<当前点
如果((cp-tp)((360-cp)+tp)){
clockwiseIsShortest=真;
最短距离=((360-cp)+tp);
System.out.println(“案例D:+最短距离+“顺时针度”);//[可以删除]
}
}
}
返回时钟短;
}
请注意,cp是整数度的起点,tp是整数度的目标点;类型
public boolean checkIfClockwiseIsShortest(int cp, int tp) {
    boolean clockwiseIsShortest = false;
    if (cp != tp) { // if current point and target point are not the same...
        if (tp > cp) { // if current point is less than target point AND..
            if ((tp - cp) <= ((360 - tp) + cp)) {
                clockwiseIsShortest = true;
                shortestDistance = (tp-cp);
                System.out.println("Case A: " + shortestDistance +" degrees clockwise");//[CAN REMOVE]

            } else if ((tp - cp) > ((360 - tp) + cp)) {
                clockwiseIsShortest = false;
                shortestDistance = ((360 - tp) + cp);
                System.out.println("Case B: " + shortestDistance+" degrees counter-clockwise");//[CAN REMOVE]
            }
        } else { // BUT if target point < current point
            if ((cp - tp) <= ((360 - cp) + tp)) {
                clockwiseIsShortest = false;
                shortestDistance = (cp-tp);
                System.out.println("Case C: " + shortestDistance+" degrees counter-clockwise");//[CAN REMOVE]
            } else if ((cp - tp) > ((360 - cp) + tp)) {
                clockwiseIsShortest = true;
                shortestDistance = ((360 - cp) + tp);
                System.out.println("Case D: " + shortestDistance+" degrees clockwise");//[CAN REMOVE]
            }
        }
    }
    return clockwiseIsShortest;
}