algorithm - 如果两个线段重叠或相交,则将它们组合在同一个圆上

标签 algorithm math language-agnostic angle

如果两个片段重叠或相交,我会尝试合并它们。我的问题类似于 thisthis .但是,我想要的是将两个部分组合起来。

public class Segment
{
    private readonly double _from;
    private readonly double _to;
    public Segment(double from, double to)
    {
        _from = Normalize(from); // 0 <= x < 360
        _to = Normalize(to);
    }

    public bool Inside(double target)
    {
        if (_from < _to)
            return _from <= target && target <= _to;
        return _from <= target || target <= _to;
    }
}

我正在尝试编写一个 TryCombine()

public bool TryCombine(Segment other, out Segment result)
{
    // if not intersect
    // return false

    // else if overlap
    // return true, out larger one

    // else if intersect
    // return true, out a new one with merged bound
}

预期结果

var seg1 = new Segment(0, 100);
var seg2 = new Segment(50, 150);
var seg3 = new Segment(110, -100);
var seg4 = new Segment(10, 50);
Segment result;

seg1.TryCombine(seg2, result); // True, result = Segment(0, 150)
seg1.TryCombine(seg3, result); // False
seg1.TryCombine(seg4, result); // True, result = Segment(0, 100)
seg2.TryCombine(seg3, result); // True, result = Segment(260, 150)

最佳答案

您可以使用我在第二个链接中的回答中描述的方法。

ma = (a2 + a1)/ 2  
mb = (b2 + b1)/ 2  
cda = Cos(da)
cdb = Cos(db)

要检查是否存在交集以及发生什么样的交集,找到 4 个 bool 值

 BStartInsideA = (Cos(ma - b1) >= cda)
 BEndInsideA  =  (Cos(ma - b2) >= cda)
 AStartInsideB = (Cos(mb - a1) >= cdb)
 AEndInsideB =   (Cos(mb - a2) >= cdb)

这些组合可以形成 16 种可能的结果(并非所有结果都可靠)。我会将这些结果组合成 4 位值的位,并在 case 语句中处理它们。

例如,如果第一个和最后一个值为真(值 0b1001 = 9),您有一个简单的交集,就像您的 seg1-seg2 情况一样 - 所以获取 AStart ans 起点,BEnd 作为结束点指向并归一化它们(如果 BEnd 小于 AStart,则将 360 添加到 BEnd)。

预规范化步骤应提供 BEnd>=BStart 和 AEnd>=AStart(例如,将 (3,1) 圆弧转换为 (3, 361),中点 182,半角 179)

可能的结果(两个额外的情况,4个简单的末端组合,4个一端重合的情况):

 0000: no intersection
 1111: full circle

 0011: AStart-AEnd
 1001: AStart-BEnd
 0110: BStart-AEnd
 1100: BStart-BEnd

 0111: AStart-AEnd
 1011: AStart-AEnd
 1110: BStart-BEnd
 1101: BStart-BEnd

一位组合和 1010、0101 看起来不可能

使用通配符,正如作者所建议的那样:

 At first check for 
   0000: no intersection
   1111: full circle
 then
   **11: AStart-AEnd
   1001: AStart-BEnd
   0110: BStart-AEnd
   11**: BStart-BEnd

关于algorithm - 如果两个线段重叠或相交,则将它们组合在同一个圆上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40584625/

相关文章:

java - 使用 BigInteger 查找 200 位素数

algorithm - 寻找算法以根据距离从 2 个列表中匹配对象

java - 三向快速排序,问题

algorithm - 计算奇数的 PRAM CREW 算法

algorithm - 如何获得不同的最大匹配

math - float 学有问题吗?

algorithm - 查找字谜是否属于回文的最佳算法是什么?

algorithm - 的渐近运行时间是多少

algorithm - Matlab:椭圆voronoi图的算法

c++ - 使用 SDL2 播放正弦声波 - 噪音/抓取问题