rism-digital / verovio

🎵 Music notation engraving library for MEI with MusicXML and Humdrum support and various toolkits (JavaScript, Python)
https://www.verovio.org
GNU Lesser General Public License v3.0
649 stars 177 forks source link

Dynamics collision #1275

Open craigsapp opened 4 years ago

craigsapp commented 4 years ago

When dynamics are placed close to each other, they may overlap:

Screen Shot 2020-01-24 at 01 07 42

In such cases, space should be added between the dynamics to separate them far enough apart that they also do not look like a single dynamic (such as mfmp in this case).

MEI test data

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt />
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2020-01-24T01:07:46" version="2.5.0-dev-aff684e">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
  <workList>
   <work>
    <title />
   </work>
  </workList>
 </meiHead>
 <music>
  <body>
   <mdiv xml:id="mdiv-0000000899804041">
    <score xml:id="score-0000000523454643">
     <scoreDef xml:id="scoredef-0000000656350049">
      <staffGrp xml:id="staffgrp-0000000453418734">
       <staffDef xml:id="staffdef-0000001849548129" n="1" lines="5">
        <clef xml:id="clef-0000001161211509" shape="G" line="2" />
        <meterSig xml:id="metersig-L2F1" count="4" unit="4" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L1F1">
      <measure xml:id="measure-L1" right="end" n="0">
       <staff xml:id="staff-0000001154157174" n="1">
        <layer xml:id="layer-L1F1N1" n="1">
         <beam xml:id="beam-L4F1-L7F1">
          <note xml:id="note-L4F1" dur="16" oct="4" pname="c" accid.ges="n" />
          <note xml:id="note-L5F1" dur="16" oct="4" pname="d" accid.ges="n" />
          <note xml:id="note-L6F1" dur="16" oct="4" pname="e" accid.ges="n" />
          <note xml:id="note-L7F1" dur="16" oct="4" pname="f" accid.ges="n" />
         </beam>
        </layer>
       </staff>
       <dynam xml:id="dynam-L4F2" staff="1" tstamp="1.000000" vgrp="100">mf</dynam>
       <dynam xml:id="dynam-L5F2" staff="1" tstamp="1.250000" vgrp="100">mp</dynam>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>

Also notice there is a vertical shift happening when the dynamics are close together (this is similar to the collision of harm labels). Here is an example where the dynamics do not overlap, and also the vertical shift is also gone:

Screen Shot 2020-01-24 at 01 11 36

MEI data for example:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt />
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2020-01-24T01:11:48" version="2.5.0-dev-aff684e">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
  <workList>
   <work>
    <title />
   </work>
  </workList>
 </meiHead>
 <music>
  <body>
   <mdiv xml:id="mdiv-0000000167284925">
    <score xml:id="score-0000001621704704">
     <scoreDef xml:id="scoredef-0000001075495528">
      <staffGrp xml:id="staffgrp-0000000938130031">
       <staffDef xml:id="staffdef-0000001235251243" n="1" lines="5">
        <clef xml:id="clef-0000000117613251" shape="G" line="2" />
        <meterSig xml:id="metersig-L2F1" count="4" unit="4" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L1F1">
      <measure xml:id="measure-L1" right="end" n="0">
       <staff xml:id="staff-0000001610323542" n="1">
        <layer xml:id="layer-L1F1N1" n="1">
         <beam xml:id="beam-L4F1-L7F1">
          <note xml:id="note-L4F1" dur="16" oct="4" pname="c" accid.ges="n" />
          <note xml:id="note-L5F1" dur="16" oct="4" pname="d" accid.ges="n" />
          <note xml:id="note-L6F1" dur="16" oct="4" pname="e" accid.ges="n" />
          <note xml:id="note-L7F1" dur="16" oct="4" pname="f" accid.ges="n" />
         </beam>
        </layer>
       </staff>
       <dynam xml:id="dynam-L4F2" staff="1" tstamp="1.000000" vgrp="100">mf</dynam>
       <dynam xml:id="dynam-L6F2" staff="1" tstamp="1.500000" vgrp="100">mp</dynam>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>
craigsapp commented 4 years ago

Here is the demonstration of the related problem with colliding harm elements (so there may be shared code between the dynamics and harm cases). The harm vertical offsets are described in issue https://github.com/rism-ch/verovio/issues/358.

Here is an example of overlapping harm (illustrated with the same dynamic text):

Screen Shot 2020-01-24 at 01 15 56
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt />
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2020-01-24T01:16:06" version="2.5.0-dev-aff684e">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
  <workList>
   <work>
    <title />
   </work>
  </workList>
 </meiHead>
 <music>
  <body>
   <mdiv xml:id="mdiv-0000000650403742">
    <score xml:id="score-0000000397442270">
     <scoreDef xml:id="scoredef-0000001572136178">
      <staffGrp xml:id="staffgrp-0000000681106746">
       <staffDef xml:id="staffdef-0000000863530015" n="1" lines="5">
        <clef xml:id="clef-0000000928287009" shape="G" line="2" />
        <meterSig xml:id="metersig-L2F1" count="4" unit="4" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L1F1">
      <measure xml:id="measure-L1" right="end" n="0">
       <staff xml:id="staff-0000000740728370" n="1">
        <layer xml:id="layer-L1F1N1" n="1">
         <beam xml:id="beam-L4F1-L7F1">
          <note xml:id="note-L4F1" dur="16" oct="4" pname="c" accid.ges="n" />
          <note xml:id="note-L5F1" dur="16" oct="4" pname="d" accid.ges="n" />
          <note xml:id="note-L6F1" dur="16" oct="4" pname="e" accid.ges="n" />
          <note xml:id="note-L7F1" dur="16" oct="4" pname="f" accid.ges="n" />
         </beam>
        </layer>
       </staff>
       <harm xml:id="harm-L4F2" staff="1" tstamp="1.000000" n="2">mf</harm>
       <harm xml:id="harm-L5F2" staff="1" tstamp="1.250000" n="2">mp</harm>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>

If the harm labels are not overlapping, then there is not an extra vertical offset added:

Screen Shot 2020-01-24 at 01 17 49

MEI data for example:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt />
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2020-01-24T01:17:59" version="2.5.0-dev-aff684e">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
  <workList>
   <work>
    <title />
   </work>
  </workList>
 </meiHead>
 <music>
  <body>
   <mdiv xml:id="mdiv-0000000485833013">
    <score xml:id="score-0000000622634259">
     <scoreDef xml:id="scoredef-0000001209009140">
      <staffGrp xml:id="staffgrp-0000000817028719">
       <staffDef xml:id="staffdef-0000000503486278" n="1" lines="5">
        <clef xml:id="clef-0000001076246374" shape="G" line="2" />
        <meterSig xml:id="metersig-L2F1" count="4" unit="4" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L1F1">
      <measure xml:id="measure-L1" right="end" n="0">
       <staff xml:id="staff-0000002027148582" n="1">
        <layer xml:id="layer-L1F1N1" n="1">
         <beam xml:id="beam-L4F1-L7F1">
          <note xml:id="note-L4F1" dur="16" oct="4" pname="c" accid.ges="n" />
          <note xml:id="note-L5F1" dur="16" oct="4" pname="d" accid.ges="n" />
          <note xml:id="note-L6F1" dur="16" oct="4" pname="e" accid.ges="n" />
          <note xml:id="note-L7F1" dur="16" oct="4" pname="f" accid.ges="n" />
         </beam>
        </layer>
       </staff>
       <harm xml:id="harm-L4F2" staff="1" tstamp="1.000000" n="2">mf</harm>
       <harm xml:id="harm-L6F2" staff="1" tstamp="1.500000" n="2">mp</harm>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>