private static double GetAverageStemLength(IEnumerable <Note> notes, IMeasurementService measurementService) { var elementsUnderTupletForAverageStemLength = notes.Where(n => MusicalSymbol.DirectionToPlacement(n.StemDirection) == measurementService.TupletState.TupletPlacement).ToList(); double averageStemLength = elementsUnderTupletForAverageStemLength.Count == 0 ? 0 : elementsUnderTupletForAverageStemLength.Average(n => n.ActualStemLength); averageStemLength += 10; //Add space return(averageStemLength); }
public static void TupletMark(IMeasurementService measurementService, IScoreService scoreService, ScoreRendererBase renderer, NoteOrRest element, int beamLoop) { if (measurementService.TupletState == null) { throw new Exception("DrawTupletMark was called but no tuplet is currently open in staff."); } Staff staff = scoreService.CurrentStaff; NoteOrRest firstElementInTuplet = staff.Peek <NoteOrRest>(element, PeekType.BeginningOfTuplet); int index = staff.Elements.IndexOf(firstElementInTuplet); List <MusicalSymbol> elementsUnderTuplet = staff.Elements.GetRange(index, staff.Elements.IndexOf(element) - index); var elementsUnderTupletForAverageStemLength = elementsUnderTuplet.OfType <Note>().Where(n => MusicalSymbol.DirectionToPlacement(n.StemDirection) == measurementService.TupletState.TupletPlacement).ToList(); double averageStemLength = elementsUnderTupletForAverageStemLength.Count == 0 ? 0 : elementsUnderTupletForAverageStemLength.Average(n => n.ActualStemLength); averageStemLength += 10; //Add space int placementMod = measurementService.TupletState.TupletPlacement == VerticalPlacement.Above ? -1 : 1; double tupletBracketStartXPosition = firstElementInTuplet.TextBlockLocation.X + 6; double tupletBracketStartYPosition = firstElementInTuplet.TextBlockLocation.Y + 25 + averageStemLength * placementMod; double tupletBracketEndXPosition = element.TextBlockLocation.X + 12; double tupletBracketEndYPosition = element.TextBlockLocation.Y + 25 + averageStemLength * placementMod; if (measurementService.TupletState.AreSingleBeamsPresentUnderTuplet) //Draw tuplet bracket { renderer.DrawLine(new Point(tupletBracketStartXPosition, tupletBracketStartYPosition), new Point(tupletBracketEndXPosition, tupletBracketEndYPosition), element); renderer.DrawLine(new Point(tupletBracketStartXPosition, tupletBracketStartYPosition), new Point(tupletBracketStartXPosition, firstElementInTuplet.TextBlockLocation.Y + 25 + (averageStemLength - 4) * placementMod), element); renderer.DrawLine(new Point(tupletBracketEndXPosition, tupletBracketEndYPosition), new Point(tupletBracketEndXPosition, element.TextBlockLocation.Y + 25 + (averageStemLength - 4) * placementMod), element); } double numberOfNotesYTranslation = 0; if (measurementService.TupletState.TupletPlacement == VerticalPlacement.Above) { numberOfNotesYTranslation -= 18; //If text should appear above the tuplet, move a bit to up } //If bracket is not drawn, move up or down to fill space if (!measurementService.TupletState.AreSingleBeamsPresentUnderTuplet) { numberOfNotesYTranslation += 10 * (measurementService.TupletState.TupletPlacement == VerticalPlacement.Above ? 1 : -1); } var allElementsUnderTuplet = elementsUnderTuplet.OfType <NoteOrRest>().ToList(); allElementsUnderTuplet.Add(element); var tupletNumber = CalculateTupletNumber(allElementsUnderTuplet); renderer.DrawString(Convert.ToString(tupletNumber), MusicFontStyles.LyricsFont, new Point(tupletBracketStartXPosition + (tupletBracketEndXPosition - tupletBracketStartXPosition) / 2 - 6, tupletBracketStartYPosition + (tupletBracketEndYPosition - tupletBracketStartYPosition) / 2 + numberOfNotesYTranslation), element); }