]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/skyline.cc
Merge branch 'jneeman' of git+ssh://jneem@git.sv.gnu.org/srv/git/lilypond into jneeman
[lilypond.git] / lily / skyline.cc
index 6c3caab69ebe05b3c223050277576a85e46cae9f..6b53a62ef845174c290f8ea02462afb156392e1a 100644 (file)
 /* A skyline is a sequence of non-overlapping buildings: something like
    this:
                    _______
-                  /       \                                ________
-                 /         \                      ________/        \
-        /\                \                    /                  \
-       /  -----             \                 /                    \
-      /                         \              /                      \
-     /                            ------------/                        ----
+                  |       \                                 ________
+                  |        \                       ________/        \
+        /\        |          \                    /                  \
+       /  --------             \                 /                    \
+      /                          \              /                      \
+     /                             ------------/                        ----
    --
    Each building has a starting position, and ending position, a starting
    height and an ending height.
@@ -111,6 +111,19 @@ Building::Building (Real start, Real start_height, Real end_height, Real end)
   precompute ();
 }
 
+Building::Building (Box const &b, Real horizon_padding, Axis horizon_axis, Direction sky)
+{
+  Real height = sky * b[other_axis (horizon_axis)][sky];
+
+  iv_ = b[horizon_axis];
+  iv_.widen (horizon_padding + EPS);
+  height_[LEFT] = height;
+  height_[RIGHT] = height;
+
+  if (sane ())
+    precompute ();
+}
+
 void
 Building::precompute ()
 {
@@ -174,6 +187,14 @@ Building::sloped_neighbour (Real horizon_padding, Direction d) const
   return Building (left, left_height, right_height, right);
 }
 
+bool
+Building::sane () const
+{
+  return approx_less_than (iv_[LEFT], iv_[RIGHT])
+    && !isinf (height_[RIGHT])
+    && !isinf (height_[LEFT]);
+}
+
 static void
 skyline_trailing_part (list<Building> *sky, Real x)
 {
@@ -259,13 +280,13 @@ single_skyline (Building b, Real horizon_padding, list<Building> *const ret)
   if (!isinf (b.iv_[RIGHT]))
     ret->push_front (Building (b.iv_[RIGHT], -infinity_f,
                               -infinity_f, infinity_f));
-  if (horizon_padding > 0)
+  if (horizon_padding > 0 && !isinf (b.iv_.length ()))
     ret->push_front (b.sloped_neighbour (horizon_padding, RIGHT));
   
   if (b.iv_[RIGHT] > b.iv_[LEFT])
     ret->push_front (b);
 
-  if (horizon_padding > 0)
+  if (horizon_padding > 0 && !isinf (b.iv_.length ()))
     ret->push_front (b.sloped_neighbour (horizon_padding, LEFT));
   if (!isinf (b.iv_[LEFT]))
     ret->push_front (Building (-infinity_f, -infinity_f,
@@ -341,16 +362,11 @@ Skyline::Skyline (vector<Box> const &boxes, Real horizon_padding, Axis horizon_a
 
   for (vsize i = 0; i < boxes.size (); i++)
     {
-      Interval iv = boxes[i][horizon_axis];
-      Real height = sky * boxes[i][other_axis (horizon_axis)][sky];
-      
-      iv.widen (horizon_padding);
-      if (!iv.is_empty () && !isinf (height) && !approx_equal (iv[LEFT], iv[RIGHT]))
+      Building front (boxes[i], horizon_padding, horizon_axis, sky);
+      if (front.sane ())
        {
-         iv.widen (EPS);
-         Building front = Building (iv[LEFT], height, height, iv[RIGHT]);
          bldgs.push_front (front);
-         if (horizon_padding > 0)
+         if (horizon_padding > 0 && !isinf (front.iv_.length ()))
            {
              bldgs.push_front (front.sloped_neighbour (horizon_padding, LEFT));
              bldgs.push_front (front.sloped_neighbour (horizon_padding, RIGHT));
@@ -362,6 +378,13 @@ Skyline::Skyline (vector<Box> const &boxes, Real horizon_padding, Axis horizon_a
   assert (is_legal_skyline ());
 }
 
+Skyline::Skyline (Box const &b, Real horizon_padding, Axis horizon_axis, Direction sky)
+{
+  sky_ = sky;
+  Building front (b, 0, horizon_axis, sky);
+  single_skyline (front, horizon_padding, &buildings_);
+}
+
 void
 Skyline::merge (Skyline const &other)
 {
@@ -379,14 +402,9 @@ Skyline::insert (Box const &b, Real horizon_padding, Axis a)
 {
   list<Building> other_bld;
   list<Building> my_bld;
-  Interval iv = b[a];
-  Real height = sky_ * b[other_axis (a)][sky_];
-
-  assert (!iv.is_empty ());
-  iv.widen (EPS);
 
   my_bld.splice (my_bld.begin (), buildings_);
-  single_skyline (Building (iv[LEFT], height, height, iv[RIGHT]), horizon_padding, &other_bld);
+  single_skyline (Building (b, 0, a, sky_), horizon_padding, &other_bld);
   internal_merge_skyline (&other_bld, &my_bld, &buildings_);
   assert (is_legal_skyline ());
 }
@@ -404,6 +422,17 @@ Skyline::raise (Real r)
   assert (is_legal_skyline ());
 }
 
+void
+Skyline::shift (Real r)
+{
+  list<Building>::iterator end = buildings_.end ();
+  for (list<Building>::iterator i = buildings_.begin (); i != end; i++)
+    {
+      i->iv_[LEFT] += r;
+      i->iv_[RIGHT] += r;
+    }
+}
+
 Real
 Skyline::distance (Skyline const &other) const
 {
@@ -476,6 +505,61 @@ Skyline::to_points () const
   return out;
 }
 
+Skyline_pair::Skyline_pair ()
+  : skylines_ (Skyline (DOWN), Skyline (UP))
+{
+}
+
+Skyline_pair::Skyline_pair (vector<Box> const &boxes, Real padding, Axis a)
+  : skylines_ (Skyline (boxes, padding, a, DOWN), Skyline (boxes, padding, a, UP))
+{
+}
+
+Skyline_pair::Skyline_pair (Box const &b, Real padding, Axis a)
+  : skylines_ (Skyline (b, padding, a, DOWN), Skyline (b, padding, a, UP))
+{
+}
+
+void
+Skyline_pair::raise (Real r)
+{
+  skylines_[UP].raise (r);
+  skylines_[DOWN].raise (r);
+}
+
+void
+Skyline_pair::shift (Real r)
+{
+  skylines_[UP].shift (r);
+  skylines_[DOWN].shift (r);
+}
+
+void
+Skyline_pair::insert (Box const &b, Real padding, Axis a)
+{
+  skylines_[UP].insert (b, padding, a);
+  skylines_[DOWN].insert (b, padding, a);
+}
+
+void
+Skyline_pair::merge (Skyline_pair const &other)
+{
+  skylines_[UP].merge (other[UP]);
+  skylines_[DOWN].merge (other[DOWN]);
+}
+
+Skyline&
+Skyline_pair::operator [] (Direction d)
+{
+  return skylines_[d];
+}
+
+Skyline const&
+Skyline_pair::operator [] (Direction d) const
+{
+  return skylines_[d];
+}
+
 /****************************************************************/
 
 
@@ -483,6 +567,10 @@ IMPLEMENT_SIMPLE_SMOBS (Skyline);
 IMPLEMENT_TYPE_P (Skyline, "ly:skyline?");
 IMPLEMENT_DEFAULT_EQUAL_P (Skyline);
 
+IMPLEMENT_SIMPLE_SMOBS (Skyline_pair);
+IMPLEMENT_TYPE_P (Skyline_pair, "ly:skyline-pair?");
+IMPLEMENT_DEFAULT_EQUAL_P (Skyline_pair);
+
 SCM
 Skyline::mark_smob (SCM)
 {
@@ -499,3 +587,19 @@ Skyline::print_smob (SCM s, SCM port, scm_print_state *)
 
   return 1;
 }
+
+SCM
+Skyline_pair::mark_smob (SCM)
+{
+  return SCM_EOL;
+}
+
+int
+Skyline_pair::print_smob (SCM s, SCM port, scm_print_state *)
+{
+  Skyline_pair *r = (Skyline_pair *) SCM_CELL_WORD_1 (s);
+  (void) r;
+
+  scm_puts ("#<Skyline-pair>", port);
+  return 1;
+}