]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/skyline.cc
Several fixes for annotate-spacing.
[lilypond.git] / lily / skyline.cc
index b5288e2526816ac5a002f37f4426aff6b3b0c5f2..d65e48b573e7eeb4a2be65bc23c946e168ca6ec3 100644 (file)
@@ -392,7 +392,7 @@ Skyline::Skyline (Direction sky)
   added to it.
 */
 
-Skyline::Skyline (Skyline const &src, Real horizon_padding, Axis a)
+Skyline::Skyline (Skyline const &src, Real horizon_padding, Axis /*a*/)
 {
   /*
      We extract boxes from the skyline, then build a new skyline from
@@ -406,6 +406,7 @@ Skyline::Skyline (Skyline const &src, Real horizon_padding, Axis a)
   list<Box> boxes;
 
   // establish a baseline box
+  // FIXME: This has hardcoded logic, assuming a == X_AXIS!
   boxes.push_back (Box (Interval (-infinity_f, infinity_f),
                         Interval (0, 0)));
   list<Building>::const_iterator end = src.buildings_.end ();
@@ -508,11 +509,27 @@ Skyline::shift (Real s)
 
 Real
 Skyline::distance (Skyline const &other, Real horizon_padding) const
+{
+  Real dummy;
+  return internal_distance (other, horizon_padding, &dummy);
+}
+
+Real
+Skyline::touching_point (Skyline const &other, Real horizon_padding) const
+{
+  Real touch;
+  internal_distance (other, horizon_padding, &touch);
+  return touch;
+}
+
+Real
+Skyline::internal_distance (Skyline const &other, Real horizon_padding, Real *touch_point) const
 {
   assert (sky_ == -other.sky_);
 
   Skyline const *padded_this = this;
   Skyline const *padded_other = &other;
+  bool created_tmp_skylines = false;
 
   /*
     For systems, padding is not added at creation time.  Padding is
@@ -524,6 +541,7 @@ Skyline::distance (Skyline const &other, Real horizon_padding) const
     {
       padded_this = new Skyline (*padded_this, horizon_padding, X_AXIS);
       padded_other = new Skyline (*padded_other, horizon_padding, X_AXIS);
+      created_tmp_skylines = true;
     }
 
   list<Building>::const_iterator i = padded_this->buildings_.begin ();
@@ -531,18 +549,33 @@ Skyline::distance (Skyline const &other, Real horizon_padding) const
 
   Real dist = -infinity_f;
   Real start = -infinity_f;
+  Real touch = -infinity_f;
   while (i != padded_this->buildings_.end () && j != padded_other->buildings_.end ())
     {
       Real end = min (i->end_, j->end_);
       Real start_dist = i->height (start) + j->height (start);
       Real end_dist = i->height (end) + j->height (end);
       dist = max (dist, max (start_dist, end_dist));
+
+      if (end_dist == dist)
+       touch = end;
+      else if (start_dist == dist)
+       touch = start;
+
       if (i->end_ <= j->end_)
         i++;
       else
         j++;
       start = end;
     }
+
+  if (created_tmp_skylines)
+    {
+      delete padded_this;
+      delete padded_other;
+    }
+
+  *touch_point = touch;
   return dist;
 }
 
@@ -570,6 +603,14 @@ Skyline::max_height () const
   return sky_ * distance (s);
 }
 
+Real
+Skyline::max_height_position () const
+{
+  Skyline s (-sky_);
+  s.set_minimum_height (0);
+  return touching_point (s);
+}
+
 void
 Skyline::set_minimum_height (Real h)
 {
@@ -636,3 +677,61 @@ Skyline::print_smob (SCM s, SCM port, scm_print_state *)
 
   return 1;
 }
+
+MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Skyline, get_touching_point, 3, 1, "")
+SCM
+Skyline::get_touching_point (SCM skyline_scm, SCM other_skyline_scm, SCM horizon_padding_scm)
+{
+  LY_ASSERT_SMOB (Skyline, other_skyline_scm, 1);
+
+  Real horizon_padding = 0;
+  if (horizon_padding_scm != SCM_UNDEFINED)
+    {
+      LY_ASSERT_TYPE (scm_is_number, horizon_padding_scm, 3);
+      horizon_padding = scm_to_double (horizon_padding_scm);
+    }
+
+  Skyline *skyline = Skyline::unsmob (skyline_scm);
+  Skyline *other_skyline = Skyline::unsmob (other_skyline_scm);
+  return scm_from_double (skyline->touching_point (*other_skyline, horizon_padding));
+}
+
+MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Skyline, get_distance, 3, 1, "")
+SCM
+Skyline::get_distance (SCM skyline_scm, SCM other_skyline_scm, SCM horizon_padding_scm)
+{
+  LY_ASSERT_SMOB (Skyline, other_skyline_scm, 1);
+
+  Real horizon_padding = 0;
+  if (horizon_padding_scm != SCM_UNDEFINED)
+    {
+      LY_ASSERT_TYPE (scm_is_number, horizon_padding_scm, 3);
+      horizon_padding = scm_to_double (horizon_padding_scm);
+    }
+
+  Skyline *skyline = Skyline::unsmob (skyline_scm);
+  Skyline *other_skyline = Skyline::unsmob (other_skyline_scm);
+  return scm_from_double (skyline->distance (*other_skyline, horizon_padding));
+}
+
+MAKE_SCHEME_CALLBACK (Skyline, get_max_height, 1)
+SCM
+Skyline::get_max_height (SCM skyline_scm)
+{
+  return scm_from_double (Skyline::unsmob (skyline_scm)->max_height ());
+}
+
+MAKE_SCHEME_CALLBACK (Skyline, get_max_height_position, 1)
+SCM
+Skyline::get_max_height_position (SCM skyline_scm)
+{
+  return scm_from_double (Skyline::unsmob (skyline_scm)->max_height_position ());
+}
+
+MAKE_SCHEME_CALLBACK (Skyline, get_height, 2)
+SCM
+Skyline::get_height (SCM skyline_scm, SCM x_scm)
+{
+  Real x = robust_scm2double (x_scm, 0.0);
+  return scm_from_double (Skyline::unsmob (skyline_scm)->height (x));
+}