+ list<Building>::iterator end = buildings_.end ();
+ for (list<Building>::iterator i = buildings_.begin (); i != end; i++)
+ {
+ i->height_[LEFT] += sky_ * r;
+ i->height_[RIGHT] += sky_ * r;
+ i->y_intercept_ += sky_ * r;
+ }
+ assert (is_legal_skyline (buildings_));
+}
+
+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
+{
+ assert (sky_ == -other.sky_);
+ list<Building>::const_iterator i = buildings_.begin ();
+ list<Building>::const_iterator j = other.buildings_.begin ();
+
+ Real dist = -infinity_f;
+ while (i != buildings_.end () && j != other.buildings_.end ())
+ {
+ Interval iv = intersection (i->iv_, j->iv_);
+ dist = max (dist, max (i->height (iv[LEFT]) + j->height (iv[LEFT]),
+ i->height (iv[RIGHT]) + j->height (iv[RIGHT])));
+ if (i->iv_[RIGHT] <= j->iv_[RIGHT])
+ i++;
+ else
+ j++;
+ }
+ return dist;
+}
+
+Real
+Skyline::height (Real airplane) const
+{
+ assert (!isinf (airplane));
+
+ list<Building>::const_iterator i;
+ for (i = buildings_.begin (); i != buildings_.end (); i++)
+ {
+ if (i->iv_[RIGHT] >= airplane)
+ return sky_ * i->height (airplane);
+ }
+
+ assert (0);
+ return 0;
+}
+
+Real
+Skyline::max_height () const
+{
+ Skyline s (-sky_);
+ s.set_minimum_height (0);
+ return sky_ * distance (s);
+}
+
+void
+Skyline::set_minimum_height (Real h)
+{
+ Skyline s (sky_);
+ s.buildings_.front ().height_[LEFT] = h * sky_;
+ s.buildings_.front ().height_[RIGHT] = h * sky_;
+ s.buildings_.front ().y_intercept_ = h * sky_;
+ merge (s);
+}
+
+
+vector<Offset>
+Skyline::to_points () const
+{
+ vector<Offset> out;
+
+ for (list<Building>::const_iterator i (buildings_.begin ());
+ i != buildings_.end (); i++)
+ {
+ if (!isinf (i->iv_[LEFT]) && !isinf (i->height_[LEFT]))
+ out.push_back (Offset (i->iv_[LEFT], sky_ * i->height_[LEFT]));
+ if (!isinf (i->iv_[RIGHT]) && !isinf (i->height_[RIGHT]))
+ out.push_back (Offset (i->iv_[RIGHT], sky_ * i->height_[RIGHT]));
+ }
+ 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];
+}
+
+/****************************************************************/
+
+
+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)
+{
+ ASSERT_LIVE_IS_ALLOWED();
+ return SCM_EOL;
+}
+
+int
+Skyline::print_smob (SCM s, SCM port, scm_print_state *)
+{
+ Skyline *r = (Skyline *) SCM_CELL_WORD_1 (s);
+ (void) r;
+
+ scm_puts ("#<Skyline>", port);
+
+ 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;