如果两个线段重叠或相交,则将它们组合在同一个圆上
Combine two segments on the same circle if they overlap or intersect
如果两个片段重叠或 intersect.My 问题类似于 this and this,我会尝试合并它们。但是,我想要的是将两个部分组合起来。
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)
您可以使用我在第二个回答中描述的方法 link。
ma = (a2 + a1)/ 2
mb = (b2 + b1)/ 2
cda = Cos(da)
cdb = Cos(db)
要检查是否存在交集以及发生什么样的交集,找到 4 个布尔值
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
如果两个片段重叠或 intersect.My 问题类似于 this and this,我会尝试合并它们。但是,我想要的是将两个部分组合起来。
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)
您可以使用我在第二个回答中描述的方法 link。
ma = (a2 + a1)/ 2
mb = (b2 + b1)/ 2
cda = Cos(da)
cdb = Cos(db)
要检查是否存在交集以及发生什么样的交集,找到 4 个布尔值
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