Browse Source

Merge pull request #754 from opensheetmusicdisplay/feat/optimizeStafflineDistance

Optimize staff lines distance using SkyBottomline intersections
Simon 5 years ago
parent
commit
6b8db5b707

+ 14 - 3
src/MusicalScore/Graphical/DrawingParameters.ts

@@ -122,10 +122,21 @@ export class DrawingParameters {
     }
 
     public setForCompactTightMode(): void {
-        this.rules.CompactMode = true;
-        this.DrawCredits = false;
+        this.setForCompactMode(); // also sets CompactMode = true
         this.DrawPartNames = false;
-        this.drawHiddenNotes = false;
+
+        // tight rendering mode, lower margins and safety distances between systems, staffs etc. may cause overlap.
+        // these options can afterwards be finetuned by setting osmd.rules.BetweenStaffDistance for example
+        this.rules.MinimumSkyBottomLineDistance = 1.0; // default 1.0. this can cause collisions with slurs and dynamics sometimes
+        // note that this.rules === osmd.rules, since it's passed as a reference
+
+        this.rules.BetweenStaffDistance = 2.5;
+        this.rules.StaffDistance = 3.5;
+        this.rules.MinimumDistanceBetweenSystems = 1;
+        // this.rules.PageTopMargin = 0.0; // see this.rules.PageTopMarginNarrow used in compact mode
+        this.rules.PageBottomMargin = 1.0;
+        this.rules.PageLeftMargin = 2.0;
+        this.rules.PageRightMargin = 2.0;
         // this.BetweenStaffDistance = 2.5 // etc needs to be set in OSMD.rules
         // this.StaffDistance = 3.5
         // this.MinimumDistanceBetweenSystems = 1

+ 9 - 1
src/MusicalScore/Graphical/EngravingRules.ts

@@ -167,6 +167,7 @@ export class EngravingRules {
     private octaveShiftVerticalLineLength: number;
     private graceLineWidth: number;
     private minimumStaffLineDistance: number;
+    private minimumSkyBottomLineDistance: number;
     private minimumCrossedBeamDifferenceMargin: number;
     private displacedNoteMargin: number;
     private minNoteDistance: number;
@@ -406,7 +407,8 @@ export class EngravingRules {
         this.graceLineWidth = this.staffLineWidth * this.GraceNoteScalingFactor;
 
         // Line Widths
-        this.minimumStaffLineDistance = 1.0;
+        this.minimumStaffLineDistance = 4.0;
+        this.minimumSkyBottomLineDistance = 2.0; // default. 1.0 for compacttight mode (1.0 can cause overlaps)
         this.minimumCrossedBeamDifferenceMargin = 0.0001;
 
         // xSpacing Variables
@@ -1325,6 +1327,12 @@ export class EngravingRules {
     public set MinimumStaffLineDistance(value: number) {
         this.minimumStaffLineDistance = value;
     }
+    public get MinimumSkyBottomLineDistance(): number {
+        return this.minimumSkyBottomLineDistance;
+    }
+    public set MinimumSkyBottomLineDistance(value: number) {
+        this.minimumSkyBottomLineDistance = value;
+    }
     public get MinimumCrossedBeamDifferenceMargin(): number {
         return this.minimumCrossedBeamDifferenceMargin;
     }

+ 16 - 9
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -919,15 +919,22 @@ export class MusicSystemBuilder {
         // don't perform any y-spacing in case of a StaffEntryLink (in both StaffLines)
         if (!musicSystem.checkStaffEntriesForStaffEntryLink()) {
             for (let i: number = 0; i < musicSystem.StaffLines.length - 1; i++) {
-                const upperBottomLine: number = musicSystem.StaffLines[i].SkyBottomLineCalculator.getBottomLineMax();
-                // TODO: Lower skyline should add to offset when there are items above the line. Currently no test
-                // file available
-                // const lowerSkyLine: number = Math.min(...musicSystem.StaffLines[i + 1].SkyLine);
-                if (Math.abs(upperBottomLine) > this.rules.MinimumStaffLineDistance) {
-                    // Remove staffheight from offset. As it results in huge distances
-                    const offset: number = Math.abs(upperBottomLine) + this.rules.MinimumStaffLineDistance - this.rules.StaffHeight;
-                    this.updateStaffLinesRelativePosition(musicSystem, i + 1, offset);
+                const upperBottomLine: number[] = musicSystem.StaffLines[i].BottomLine;
+                const lowerSkyline: number[] = musicSystem.StaffLines[i + 1].SkyLine;
+                // 1. Find maximum required space for sky bottom line touching each other
+                let maxDistance: number = 0;
+                for (let j: number = 0; j < upperBottomLine.length; j++) {
+                    const bottomLineValue: number = upperBottomLine[j];
+                    const skylineValue: number = lowerSkyline[j];
+                    const distance: number = bottomLineValue - skylineValue;
+                    maxDistance = Math.max(distance, maxDistance);
                 }
+                // 2. Add user defined distance between sky bottom line
+                maxDistance += this.rules.MinimumSkyBottomLineDistance;
+                // 3. Take the maximum between previous value and user defined value for staff line minimum distance
+                maxDistance = Math.max(maxDistance, this.rules.StaffHeight + this.rules.MinimumStaffLineDistance);
+                const lowerStafflineYPos: number = maxDistance + musicSystem.StaffLines[i].PositionAndShape.RelativePosition.y;
+                this.updateStaffLinesRelativePosition(musicSystem, i + 1, lowerStafflineYPos);
             }
         }
         const firstStaffLine: StaffLine = musicSystem.StaffLines[0];
@@ -944,7 +951,7 @@ export class MusicSystemBuilder {
      */
     protected updateStaffLinesRelativePosition(musicSystem: MusicSystem, index: number, value: number): void {
         for (let i: number = index; i < musicSystem.StaffLines.length; i++) {
-            musicSystem.StaffLines[i].PositionAndShape.RelativePosition.y += value;
+            musicSystem.StaffLines[i].PositionAndShape.RelativePosition.y = value;
         }
 
         musicSystem.PositionAndShape.BorderBottom += value;

+ 1 - 11
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -335,17 +335,7 @@ export class OpenSheetMusicDisplay {
         if (options.drawingParameters) {
             this.drawingParameters.DrawingParametersEnum =
                 (<any>DrawingParametersEnum)[options.drawingParameters.toLowerCase()];
-            if (this.drawingParameters.DrawingParametersEnum === DrawingParametersEnum.compacttight) {
-                // tight rendering mode, lower margins and safety distances between systems, staffs etc. may cause overlap.
-                // these options can afterwards be finetuned by setting osmd.rules.BetweenStaffDistance for example
-                this.rules.BetweenStaffDistance = 2.5;
-                this.rules.StaffDistance = 3.5;
-                this.rules.MinimumDistanceBetweenSystems = 1;
-                // this.rules.PageTopMargin = 0.0; // see this.rules.PageTopMarginNarrow used in compact mode
-                this.rules.PageBottomMargin = 1.0;
-                this.rules.PageLeftMargin = 2.0;
-                this.rules.PageRightMargin = 2.0;
-            }
+                // see DrawingParameters.ts: set DrawingParametersEnum, and DrawingParameters.ts:setForCompactTightMode()
         }
 
         const backendNotInitialized: boolean = !this.drawer || !this.drawer.Backends || this.drawer.Backends.length < 1;