/// <summary> /// Tries to merge two <see cref="AngleInterval" />. /// </summary> /// <param name="newInterval"><see cref="AngleInterval" /> to be merged.</param> /// <param name="resultInterval">Result <see cref="AngleInterval" /> if merge is success.</param> /// <returns>True if merge is success.</returns> public bool TryMerge(AngleInterval newInterval, out AngleInterval resultInterval) { if (newInterval._full) { resultInterval = newInterval; return(true); } if (_full || Equals(newInterval)) { resultInterval = this; return(true); } var aStart = _from; var aEnd = aStart > _to ? _to + 360 : _to; var bStart = newInterval._from; var bEnd = bStart > newInterval._to ? newInterval._to + 360 : newInterval._to; var diffA = (aEnd - aStart) / 2; var diffB = (bEnd - bStart) / 2; var avgA = (aStart + aEnd) / 2; var avgB = (bStart + bEnd) / 2; var cosDiffA = Math.Cos(diffA.ToRadians()); var cosDiffB = Math.Cos(diffB.ToRadians()); var resultFlag = MergeFlag.None; if (Math.Cos((avgA - bStart).ToRadians()).AboutGreaterThanOrEqual(cosDiffA)) { resultFlag |= MergeFlag.BStartInsideA; } if (Math.Cos((avgA - bEnd).ToRadians()).AboutGreaterThanOrEqual(cosDiffA)) { resultFlag |= MergeFlag.BEndInsideA; } if (Math.Cos((avgB - aStart).ToRadians()).AboutGreaterThanOrEqual(cosDiffB)) { resultFlag |= MergeFlag.AStartInsideB; } if (Math.Cos((avgB - aEnd).ToRadians()).AboutGreaterThanOrEqual(cosDiffB)) { resultFlag |= MergeFlag.AEndInsideB; } if (NotHasFlags(resultFlag, MergeFlag.BStartInsideA, MergeFlag.BEndInsideA, MergeFlag.AEndInsideB, MergeFlag.AStartInsideB)) { resultInterval = null; return(false); } if (HasFlags(resultFlag, MergeFlag.BStartInsideA, MergeFlag.BEndInsideA, MergeFlag.AEndInsideB, MergeFlag.AStartInsideB)) { resultInterval = new AngleInterval(true); return(true); } if (HasFlags(resultFlag, MergeFlag.BStartInsideA, MergeFlag.BEndInsideA)) { resultInterval = this; return(true); } if (HasFlags(resultFlag, MergeFlag.AEndInsideB, MergeFlag.AStartInsideB)) { resultInterval = newInterval; return(true); } if (HasFlags(resultFlag, MergeFlag.AEndInsideB, MergeFlag.BStartInsideA) && NotHasFlags(resultFlag, MergeFlag.AStartInsideB, MergeFlag.BEndInsideA)) { resultInterval = new AngleInterval(aStart, bEnd); return(true); } // Invert if if (!HasFlags(resultFlag, MergeFlag.AStartInsideB, MergeFlag.BEndInsideA) || !NotHasFlags(resultFlag, MergeFlag.AEndInsideB, MergeFlag.BStartInsideA)) { throw new InvalidOperationException("This should never happen."); } resultInterval = new AngleInterval(bStart, aEnd); return(true); }
public bool Equals(AngleInterval shadow) { return(_from.AboutEqual(shadow._from) && _to.AboutEqual(shadow._to) && _full == shadow._full); }