~s-cecilio/lomse/master

« back to all changes in this revision

Viewing changes to src/graphic_model/layouters/lomse_spacing_algorithm_gourlay.cpp

  • Committer: GitHub
  • Author(s): Cecilio Salmeron
  • Date: 2016-09-15 14:46:58 UTC
  • mfrom: (202.1.10)
  • Revision ID: git-v1:5fa3dc2c55edae65a670f6ee4bd2c5dad932371e
Merge pull request #61 from cecilios/fixes

Improved support for tuplets and some fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
147
147
    pData->m_pShape = pShape;
148
148
 
149
149
    //determine slice type for the new object to include
150
 
    dbgLogger << "StaffObj type= " << pSO->get_obj_type();
 
150
//    dbgLogger << "StaffObj type= " << pSO->get_obj_type();
151
151
    int curType = TimeSlice::k_undefined;
152
152
    if (fInProlog)
153
153
        curType = TimeSlice::k_prolog;
207
207
            curType = TimeSlice::k_non_timed;
208
208
        }
209
209
    }
210
 
    dbgLogger << ", slice type= " << curType;
 
210
//    dbgLogger << ", slice type= " << curType;
211
211
 
212
212
    //include entry in current or new slice
213
213
    if (fCreateNewSlice)
214
214
    {
215
 
        dbgLogger << ", Start new slice. m_prevType:" << m_prevType
216
 
            << ", m_prevTime:" << m_prevTime << ", curTime:" << curTime
217
 
            << endl;
 
215
//        dbgLogger << ", Start new slice. m_prevType:" << m_prevType
 
216
//            << ", m_prevTime:" << m_prevTime << ", curTime:" << curTime
 
217
//            << endl;
218
218
        //terminate previous slice
219
219
        finish_slice(m_pLastEntry, m_numEntries);
220
220
 
248
248
    }
249
249
    else
250
250
    {
251
 
        dbgLogger << ", Use previous slice." << endl;
 
251
//        dbgLogger << ", Use previous slice." << endl;
252
252
        if (pSO->is_note_rest())
253
253
        {
254
254
            m_maxNoteDur = max(m_maxNoteDur, pSO->get_duration());
383
383
 
384
384
    //determine column spacing function slope in the neighborhood of Fopt
385
385
    m_columns[iCol]->determine_approx_sff_for(m_Fopt);
 
386
 
 
387
    if (fTrace || m_libraryScope.dump_column_tables())
 
388
    {
 
389
        dbgLogger << "Column " << iCol << ". Slope for Fopt= " << m_Fopt
 
390
                  << " is slope= " << m_columns[iCol]->m_slope << endl;
 
391
    }
386
392
}
387
393
 
388
394
//---------------------------------------------------------------------------------------
509
515
//---------------------------------------------------------------------------------------
510
516
void SpAlgGourlay::justify_system(int iFirstCol, int iLastCol, LUnits uSpaceIncrement)
511
517
{
512
 
#if 1
513
 
    //method 2: proportional division of the space and specific force for each column.
514
 
    //          Exact. No approximations used. It woks OK.
515
 
 
516
 
    vector<LUnits> colWidths;
517
 
    int numCols = iLastCol - iFirstCol;
518
 
    colWidths.reserve(numCols);
519
 
 
520
 
    LUnits stretchableWidth = 0.0f;
521
 
    int i=0;
522
 
    for (int iCol = iFirstCol; iCol < iLastCol; ++i, ++iCol)
523
 
    {
524
 
        colWidths[i] = m_columns[iCol]->get_column_width() - m_columns[iCol]->m_xFixed;
525
 
        stretchableWidth += colWidths[i];
526
 
    }
527
 
 
528
 
    i=0;
529
 
    for (int iCol = iFirstCol; iCol < iLastCol; ++i, ++iCol)
530
 
    {
531
 
        LUnits extraWidth = stretchableWidth == 0.0f ?
532
 
                uSpaceIncrement / (iLastCol - iFirstCol)
533
 
                : uSpaceIncrement * colWidths[i] / stretchableWidth;
534
 
        LUnits colWidth = m_columns[iCol]->get_column_width();
535
 
        float F = m_columns[iCol]->determine_force_for(colWidth + extraWidth);
536
 
        m_columns[iCol]->apply_force(F);
537
 
 
538
 
//        dbgLogger << "Justifying system. Col " << iCol
539
 
//                  << ": extraWidth= " << extraWidth
540
 
//                  << ", stretchableWidth= " << stretchableWidth
541
 
//                  << ", Force= " << F
542
 
//                  << ", target width= " << (colWidth + extraWidth)
543
 
//                  << ", achieved= " << m_columns[iCol]->get_column_width()
544
 
//                  << endl;
545
 
    }
546
 
 
547
 
#else
548
 
    //Method 1: use approximate spacing function sff[cicj]
549
 
    //          Not good. Errors are noticeable when required force is > 20% of Fopt
 
518
    //Use approximate spacing function sff[cicj] for computing the required force.
 
519
    //If required force is greater than 20% Fopt the errors are noticeable. In this
 
520
    //case, a loop of succesive approximations is started (usually a single
 
521
    //pass is enough).
 
522
 
550
523
 
551
524
    //determine required line width
552
 
    /*dbg*/ LUnits required = uSpaceIncrement;
 
525
    LUnits required = uSpaceIncrement;
553
526
    LUnits lineWidth = uSpaceIncrement;
554
527
    for (int i = iFirstCol; i < iLastCol; ++i)
555
528
    {
556
 
        /*dbg*/ required  += m_columns[i]->get_column_width();
 
529
        required  += m_columns[i]->get_column_width();
557
530
        lineWidth += m_columns[i]->get_column_width();
558
531
        lineWidth -= m_columns[i]->m_xFixed;
559
532
    }
573
546
    float F = lineWidth * c;
574
547
 
575
548
    //apply this force to columns
576
 
    /*dbg*/ LUnits achieved = 0.0f;
 
549
    LUnits achieved = 0.0f;
577
550
    for (int i = iFirstCol; i < iLastCol; ++i)
578
551
    {
579
552
        m_columns[i]->apply_force(F);
580
 
        /*dbg*/ achieved += m_columns[i]->get_column_width();
581
 
    }
582
 
 
583
 
    dbgLogger << "Justifing system: cols " << iFirstCol << ", " << iLastCol
584
 
              << ", line width " << lineWidth
585
 
              << ", c= " << c << ", new force: " << F
586
 
              << ", required width= " << required
587
 
              << ", achieved= " << achieved
588
 
              << endl;
589
 
#endif
 
553
        achieved += m_columns[i]->get_column_width();
 
554
    }
 
555
 
 
556
//    dbgLogger << "Justifing system: cols " << iFirstCol << ", " << iLastCol
 
557
//              << ", line width " << lineWidth
 
558
//              << ", c= " << fixed << setprecision(6) << c << ", new force: " << F
 
559
//              << ", required width= " << setprecision(2) << required
 
560
//              << ", achieved= " << achieved
 
561
//              << endl;
 
562
 
 
563
    //Errors are noticeable when required force is > 20% of Fopt.
 
564
    //If error is greater than one tenth of a millimeter, a loop of
 
565
    //succesive approximations is started.
 
566
 
 
567
    LUnits uError = required - achieved;
 
568
    int round=0;
 
569
    while (abs(uError) > 10.0f && round < 8)     //10.0f = one tenth of a millimeter
 
570
    {
 
571
//        dbgLogger << "Error = " << uError << ". Correction round "
 
572
//                  << round << ". ";
 
573
        ++round;
 
574
 
 
575
        //compute an increment for F
 
576
        float deltaF = F - m_Fopt;
 
577
        LUnits deltaS = uSpaceIncrement - uError;
 
578
        F += (uError/deltaS) * deltaF;
 
579
 
 
580
        //apply then new force to columns
 
581
        LUnits achieved = 0.0f;
 
582
        for (int i = iFirstCol; i < iLastCol; ++i)
 
583
        {
 
584
            m_columns[i]->apply_force(F);
 
585
            achieved += m_columns[i]->get_column_width();
 
586
        }
 
587
 
 
588
        uError = required - achieved;
 
589
 
 
590
//        dbgLogger << "New: F= " << setprecision(6) << F
 
591
//                  << ", achieved= " << setprecision(2) << achieved
 
592
//                  << ", error= " << uError
 
593
//                  << endl;
 
594
    }
590
595
}
591
596
 
592
597
//---------------------------------------------------------------------------------------
1773
1778
{
1774
1779
    //compute combined spring constant for all springs that will react to F
1775
1780
 
1776
 
#if 0
1777
 
    //method 2: direct computation of the slope
1778
 
    //          produces more or less the same results than method 1 but requires
1779
 
    //          more computations.
1780
 
 
1781
 
    // extent1 = apply optimum force fopt to sff  (inverse of Algorithm 1)
1782
 
    // extent2 = apply optimum force fopt * 1.15 to sff  (inverse of Algorithm 1)    fopt + 15%
1783
 
    // slope = (extent1 - extent2) / (0.15 * fopt)
1784
 
 
1785
 
    LUnits e1 = get_column_width();
1786
 
    apply_force(F * 1.15f);
1787
 
    LUnits e2 = get_column_width();
1788
 
    m_slope = (e2 - e1) / (F * 0.15f);
1789
 
 
1790
 
    m_xFixed = 0.0f;
1791
 
    vector<TimeSlice*>::iterator it;
1792
 
    for (it = m_orderedSlices.begin(); it != m_orderedSlices.end(); ++it)
1793
 
    {
1794
 
        m_xFixed += (*it)->m_xLeft;
1795
 
 
1796
 
        //if the force of this spring is bigger than F do not take this spring into
1797
 
        //account, only its pre-stretching extent
1798
 
        if (F <= (*it)->m_fi)
1799
 
            m_xFixed += (*it)->get_xi();
1800
 
    }
1801
 
 
1802
 
#else
1803
 
    //method 1: compute combined spring for active springs at force F
1804
 
 
1805
1781
    m_slope = 0.0f;
1806
1782
    m_xFixed = 0.0f;
1807
1783
    vector<TimeSlice*>::iterator it;
1830
1806
    //if F is lower than minimum force for all springs, use the first one
1831
1807
    if (m_slope == 0.0f)
1832
1808
        m_slope = 1.0f / m_orderedSlices[0]->m_ci;
1833
 
#endif
 
1809
 
1834
1810
//    dbgLogger << "Final slope=" << m_slope
1835
1811
//              << ", xFixed=" << m_xFixed
1836
1812
//              << endl;