summaryrefslogtreecommitdiff
path: root/src/break.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/break.cc')
-rw-r--r--src/break.cc135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/break.cc b/src/break.cc
new file mode 100644
index 0000000000..de9a704984
--- /dev/null
+++ b/src/break.cc
@@ -0,0 +1,135 @@
+/*
+ do calculations for breaking problem
+
+ */
+#include "paper.hh"
+#include "linespace.hh"
+#include "debug.hh"
+#include "scoreline.hh"
+#include "pscore.hh"
+
+// construct an appropriate Spacing_problem and solve it.
+svec<Real>
+PScore::solve_line(svec<const PCol *> curline) const
+{
+ Spacing_problem sp;
+
+ sp.add_column(curline[0], true, 0.0);
+ for (int i=1; i< curline.sz()-1; i++)
+ sp.add_column(curline[i]);
+ sp.add_column(curline.last(), true, paper_->linewidth);
+
+ // misschien moeven uit Spacing_problem?
+ for (PCursor<Idealspacing *> i(suz); i.ok(); i++) {
+ sp.add_ideal(i);
+ }
+ svec<Real> the_sol=sp.solve();
+ return the_sol;
+}
+
+bool
+PScore::feasible(svec<const PCol *> curline) const
+{
+ Real l =0;
+ for (int i=0; i < curline.sz(); i++)
+ l +=curline[i]->width().length();
+ return l < paper_->linewidth;
+}
+
+void
+PScore::problem_OK() const
+{
+ if (!cols.size())
+ error("PScore::problem_OK(): Score does not have any columns");
+ PCursor<PCol *> start(cols);
+ PCursor<PCol *> end (((PScore*)this)->cols.bottom());
+
+ assert(start->breakable());
+ assert(end->breakable());
+}
+
+struct Col_configuration {
+ svec<const PCol*> line;
+ svec<Real> config;
+ Real energy;
+
+ Col_configuration() {
+ energy = INFTY;
+ }
+ void add(const PCol*c) { line.add(c);}
+ void setsol(svec<Real> sol) {
+ config = sol;
+ energy = config.last();
+ config.pop();
+ }
+ void print() const {
+#ifndef NPRINT
+ mtor << "energy : " << energy << '\n';
+ mtor << "line of " << config.sz() << " cols\n";
+#endif
+ }
+};
+
+/// wordwrap type algorithm
+/* el stupido. This should be done more accurately:
+
+ It would be nice to have a Dynamic Programming type of algorithm
+ similar to TeX's
+
+ */
+
+void
+PScore::calc_breaking()
+{
+ OK();
+ problem_OK();
+ PCursor<PCol *> curcol(cols);
+
+ svec<const PCol *> breakpoints(find_breaks());
+ assert(breakpoints.sz()>=2);
+ for (int i=0 ; i < breakpoints.sz() -1; ) {
+ Col_configuration minimum;
+ Col_configuration current;
+
+ // do another line
+ PCol *post = breakpoints[i]->postbreak;
+ current.add( post);
+ curcol++; // skip the breakable.
+ i++;
+
+ while (i < breakpoints.sz()) {
+
+ // add another measure.
+ while(breakpoints[i] !=curcol){
+
+ current.add(curcol);
+ curcol++;
+ }
+ current.add(breakpoints[i]->prebreak );
+ if (!feasible(current.line)) {
+ if (!minimum.line.sz())
+ error("sorry, this measure is too long");
+ break;
+ }
+ current.setsol(solve_line(current.line));
+ current.print();
+
+ if (current.energy < minimum.energy) {
+ minimum = current;
+ } else { // we're one col too far.
+ i--;
+ while (curcol != breakpoints[i])
+ curcol --;
+
+ break;
+ }
+
+ current.line.last()=breakpoints[i];
+ curcol ++;
+ i++;
+ }
+ mtor << "Adding line, next breakpoint " << i << '\n';
+ add_line(minimum.line, minimum.config);
+ }
+}
+