/// <summary> /// Calculates slur height trying to avoid collisions with stems /// </summary> /// <param name="note"></param> /// <param name="endPoint"></param> /// <returns></returns> private double DetermineSlurHeight(Note note, Slur slur, SlurInfo slurStartInfo, Point endPoint) { var notesUnderSlur = note.Staff.EnumerateUntilConditionMet <Note>(note, n => n.Slurs.FirstOrDefault(s => s.Number == slur.Number)?.Type == NoteSlurType.Start, true).ToArray(); if (notesUnderSlur.Length < 3) { return(10); } var notesUnderSlurExclusive = notesUnderSlur.Take(notesUnderSlur.Length - 1).Skip(1); var mostExtremePoint = GetMostExtremePoint(notesUnderSlurExclusive, slurStartInfo.StartPlacement); var angle = UsefulMath.BeamAngle(slurStartInfo.StartPoint.X, slurStartInfo.StartPoint.Y, endPoint.X, endPoint.Y); var slurYPositionInMostExtremePoint = slurStartInfo.StartPoint.TranslateHorizontallyAndMaintainAngle(angle, mostExtremePoint.X - slurStartInfo.StartPoint.X).Y; var mostExtremeYPosition = mostExtremePoint.Y; if (slurStartInfo.StartPlacement == VerticalPlacement.Above && mostExtremeYPosition < slurYPositionInMostExtremePoint) { return(Math.Abs(mostExtremeYPosition - slurYPositionInMostExtremePoint) + 10); } if (slurStartInfo.StartPlacement == VerticalPlacement.Below && mostExtremeYPosition > slurYPositionInMostExtremePoint) { return(Math.Abs(slurYPositionInMostExtremePoint - mostExtremeYPosition) + 10); } return(10); }
private static Tuple <Point, Point> GetBezierControlPoints(Point start, Point end, VerticalPlacement placement, double height) { var factor = placement == VerticalPlacement.Above ? -1 : 1; var angle = UsefulMath.BeamAngle(start.X, start.Y, end.X, end.Y); var angle2 = angle + (Math.PI / 2) * factor; var distance = Point.Distance(start, end); var startPointForControlPoints = start.TranslateByAngleOld(angle2, height); var control1 = startPointForControlPoints.TranslateByAngleOld(angle, distance * 0.25); var control2 = startPointForControlPoints.TranslateByAngleOld(angle, distance * 0.75); return(new Tuple <Point, Point>(control1, control2)); }
/// <summary> /// Calculates beam angle /// </summary> /// <param name="beamStart">Beam start position</param> /// <param name="beamEnd">Beam end position</param> /// <returns></returns> public static double BeamAngle(Point beamStart, Point beamEnd) { return(UsefulMath.BeamAngle(beamStart.X, beamStart.Y, beamEnd.X, beamEnd.Y)); }