internal LayoutLine GetStringBoundaryLine(SIString str, FingerboardSide dir) { LayoutLine boundary = null; if (dir == FingerboardSide.Bass) { boundary = VisualElements.OfType <StringCenter>().FirstOrDefault(c => c.Right.Index == str.Index); } else { boundary = VisualElements.OfType <StringCenter>().FirstOrDefault(c => c.Left.Index == str.Index); } if (boundary == null) { return(VisualElements.OfType <FingerboardSideEdge>().First(e => e.Side == dir)); } return(boundary); }
public IEnumerable <T> GetElements <T>() where T : VisualElement { return(VisualElements.OfType <T>()); }
public IEnumerable <T> GetElements <T>(Predicate <T> predicate) where T : VisualElement { return(VisualElements.OfType <T>().Where(x => predicate(x))); }
public T GetElement <T>(Predicate <T> predicate) where T : VisualElement { return(VisualElements.OfType <T>().FirstOrDefault(x => predicate(x))); }
private void FinishFingerboardShape() { var trebleSideEdge = VisualElements.OfType <FingerboardSideEdge>().First(e => e.Side == FingerboardSide.Treble); var bassSideEdge = VisualElements.OfType <FingerboardSideEdge>().First(e => e.Side == FingerboardSide.Bass); var trebleNutFret = VisualElements.OfType <FretLine>().First(f => f.IsNut && f.Strings.Contains(FirstString)); var bassNutFret = VisualElements.OfType <FretLine>().First(f => f.IsNut && f.Strings.Contains(LastString)); //create inward fingerboard edges from nut if (!Strings.AllEqual(s => s.StartingFret)) { foreach (var str in Strings) { if (str.Next != null && str.StartingFret != str.Next.StartingFret) { var nut1 = VisualElements.OfType <FretLine>().First(f => f.IsNut && f.Strings.Contains(str)); var nut2 = VisualElements.OfType <FretLine>().First(f => f.IsNut && f.Strings.Contains(str.Next)); AddVisualElement(new FingerboardEdge(nut1.Points.First(), nut2.Points.Last()) { IsSideEdge = true }); //var center = GetStringBoundaryLine(str, FingerboardSide.Bass) as StringCenter; //var p1 = center.GetRelativePoint(str.LayoutLine, str.LayoutLine.P1); //var p2 = center.GetRelativePoint(str.Next.LayoutLine, str.Next.LayoutLine.P1); //AddVisualElement(new FingerboardEdge(p1, p2) { IsSideEdge = true }); } } } var trebSideNutInter = PointM.Empty; if (trebleNutFret.Intersects(trebleSideEdge, out trebSideNutInter)) { trebleSideEdge.P1 = trebSideNutInter; } var bassSideNutInter = PointM.Empty; if (bassNutFret.Intersects(bassSideEdge, out bassSideNutInter)) { bassSideEdge.P1 = bassSideNutInter; } trebleSideEdge.RealEnd = trebleSideEdge.P2; bassSideEdge.RealEnd = bassSideEdge.P2; var trebleLastFret = VisualElements.OfType <FretLine>().First(f => f.FretIndex == FirstString.NumberOfFrets && f.Strings.Contains(FirstString)); var bassLastFret = VisualElements.OfType <FretLine>().First(f => f.FretIndex == LastString.NumberOfFrets && f.Strings.Contains(LastString)); PointM trebleEndPoint = trebleLastFret.Points.Last(); PointM bassEndPoint = bassLastFret.Points.First(); if (!Margins.LastFret.IsEmpty) { trebleEndPoint += trebleSideEdge.Direction * Margins.LastFret; bassEndPoint += bassSideEdge.Direction * Margins.LastFret; } //split physical from virtual fingerboard var virtualTrebleEdge = AddVisualElement(new LayoutLine(trebleEndPoint, trebleSideEdge.P2, VisualElementType.FingerboardContinuation)); var virtualBassEdge = AddVisualElement(new LayoutLine(bassEndPoint, bassSideEdge.P2, VisualElementType.FingerboardContinuation)); trebleSideEdge.P2 = virtualTrebleEdge.P1; bassSideEdge.P2 = virtualBassEdge.P1; if (NumberOfStrings > 1) { var bridgeLine = new LayoutPolyLine(Strings.Select(s => s.LayoutLine.P2), VisualElementType.BridgeLine); VisualElements.Add(bridgeLine); var bridgeTrebleInter = PointM.Empty; if (bridgeLine.Intersects(virtualTrebleEdge, out bridgeTrebleInter)) { virtualTrebleEdge.P2 = bridgeTrebleInter; } var bridgeBassInter = PointM.Empty; if (bridgeLine.Intersects(virtualBassEdge, out bridgeBassInter)) { virtualBassEdge.P2 = bridgeBassInter; } } if (trebleLastFret.Strings.Count() == NumberOfStrings && trebleLastFret.IsStraight && trebleLastFret.FretIndex == MaximumFret) { AddVisualElement(new FingerboardEdge(bassSideEdge.P2, trebleSideEdge.P2)); } else if (!Margins.LastFret.IsEmpty) { var fretLines = VisualElements.OfType <FretLine>(); var edgePoints = new List <PointM>(); for (int i = NumberOfStrings - 1; i >= 0; i--) { var strLastFret = fretLines.First(fl => fl.FretIndex == Strings[i].NumberOfFrets && fl.Strings.Contains(Strings[i])); var trebleSide = GetStringBoundaryLine(Strings[i], FingerboardSide.Treble); var bassSide = GetStringBoundaryLine(Strings[i], FingerboardSide.Bass); var pt1 = PointM.Empty; var pt2 = PointM.Empty; if (!strLastFret.Intersects(bassSide, out pt1)) { pt1 = strLastFret.Points.First(); } if (!strLastFret.Intersects(trebleSide, out pt2)) { pt2 = strLastFret.Points.Last(); } pt1 += bassSide.Direction * Margins.LastFret; pt2 += trebleSide.Direction * Margins.LastFret; edgePoints.Add(pt1); edgePoints.Add(pt2); } //edgePoints.RemoveAll(p => p.IsEmpty); edgePoints = edgePoints.Distinct().ToList(); var fretboardEdge = AddVisualElement(new FingerboardEdge(edgePoints)); //fretboardEdge.InterpolateSpline(); } var fingerboardEnds = VisualElements.OfType <FingerboardEdge>(); var trebleLine = FirstString.LayoutLine; foreach (var end in fingerboardEnds) { if (end.Intersects(trebleLine, out PointM inter, false)) { AddVisualElement(new LayoutLine(trebleLine.P1, inter, VisualElementType.FingerboardMargin)); break; } } if (LastString != FirstString) { var bassLine = LastString.LayoutLine; foreach (var end in fingerboardEnds) { if (end.Intersects(bassLine, out PointM inter, false)) { AddVisualElement(new LayoutLine(bassLine.P1, inter, VisualElementType.FingerboardMargin)); break; } } } }
internal StringCenter GetStringsCenter(SIString left, SIString right) { return(VisualElements.OfType <StringCenter>().FirstOrDefault(c => (left.Index == c.Right.Index || left.Index == c.Left.Index) && (right.Index == c.Right.Index || right.Index == c.Left.Index))); }
private void LayoutStrings(Measure[] nutStringPos, Measure[] bridgeStringPos) { var stringLines = VisualElements.OfType <StringLine>(); if (NumberOfStrings == 1) { ConstructString(Strings[0], nutStringPos[0], bridgeStringPos[0]); } else if (ScaleLengthMode != ScaleLengthType.Multiple) { var trebleStr = ConstructString(Strings[0], nutStringPos[0], bridgeStringPos[0]); var bassStr = ConstructString(Strings[NumberOfStrings - 1], nutStringPos[NumberOfStrings - 1], bridgeStringPos[NumberOfStrings - 1]); var maxHeight = Measure.Max(trebleStr.Bounds.Height, bassStr.Bounds.Height); AdjustStringVerticalPosition(trebleStr, maxHeight); AdjustStringVerticalPosition(bassStr, maxHeight); var nutLine = Line.FromPoints(trebleStr.P1.ToVector(), bassStr.P1.ToVector()); var bridgeLine = Line.FromPoints(trebleStr.P2.ToVector(), bassStr.P2.ToVector()); var twelfthFret = new LayoutLine(PointM.Average(trebleStr.P1, trebleStr.P2), PointM.Average(bassStr.P1, bassStr.P2)); //create the remaining strings by distributing them equally between the outer strings for (int i = 1; i < NumberOfStrings - 1; i++) { var nutPos = nutLine.GetPointForX(nutStringPos[i].NormalizedValue); var bridgePos = bridgeLine.GetPointForX(bridgeStringPos[i].NormalizedValue); var createdString = AddVisualElement(new StringLine(Strings[i], PointM.FromVector(nutPos, nutStringPos[i].Unit), PointM.FromVector(bridgePos, bridgeStringPos[i].Unit))); //strings distributed equally between the outer strings (which are tapered/angled) do not have their centers aligned //so we correct the string length (at bridge) so that its center is aligned with the twelfth fret var middle = createdString.GetIntersection(twelfthFret); var distFromNut = PointM.Distance(createdString.P1, middle); var distFromBridge = PointM.Distance(createdString.P2, middle); var stringCenterOffset = Measure.Abs(distFromNut - distFromBridge); if (!CompensateFretPositions && stringCenterOffset > Measure.Mm(0.05)) { //adjust the end of the string so that it's center is above the 12th fret createdString.P2 = createdString.P1 + (createdString.Direction * distFromNut * 2); } Strings[i].RecalculateLengths();//store the physical length of the string } } else { for (int i = 0; i < NumberOfStrings; i++) { ConstructString(Strings[i], nutStringPos[i], bridgeStringPos[i]); } //*** Adjust strings position for multiscale var maxPerpHeight = Measure.FromNormalizedValue(stringLines.Max(l => l.Bounds.Height.NormalizedValue), UnitOfMeasure.Mm); foreach (var strLine in stringLines) { AdjustStringVerticalPosition(strLine, maxPerpHeight); } } //calculate starting fret position if different from 0 (nut) foreach (var str in Strings) { if (str.StartingFret != 0) { var startingFretPosRatio = GetEqualTemperedFretPosition(str.StartingFret); var stringVector = str.PlaceFretsRelativeToString ? str.LayoutLine.Direction * -1 : new Vector(0, 1); var startingFretPos = str.LayoutLine.P2 + (stringVector * str.CalculatedLength * startingFretPosRatio); if (!str.PlaceFretsRelativeToString) { startingFretPos = str.LayoutLine.SnapToLine(startingFretPos, LineSnapDirection.Horizontal); } str.LayoutLine.P1 = startingFretPos; str.RecalculateLengths(); } } for (int i = 0; i < NumberOfStrings - 1; i++) { AddVisualElement(new StringCenter(Strings[i + 1].LayoutLine, Strings[i].LayoutLine)); } }