+ build skyline from a set of boxes. If horizon_padding > 0, expand all the boxes
+ by that amount and add 45-degree sloped boxes to the edges of each box (of
+ width horizon_padding). That is, the total amount of horizontal expansion is
+ horizon_padding*4, half of which is sloped and half of which is flat.
+
+ Boxes should have fatness in the horizon_axis (after they are expanded by
+ horizon_padding), otherwise they are ignored.
+ */
+Skyline::Skyline (vector<Box> const &boxes, Real horizon_padding, Axis horizon_axis, Direction sky)
+{
+ list<Building> bldgs;
+ sky_ = sky;
+
+ for (vsize i = 0; i < boxes.size (); i++)
+ {
+ Building front (boxes[i], horizon_padding, horizon_axis, sky);
+ if (front.sane ())
+ {
+ bldgs.push_front (front);
+ 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));
+ }
+ }
+ }
+
+ buildings_ = internal_build_skyline (&bldgs);
+ assert (is_legal_skyline (buildings_));
+}
+
+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)
+{
+ assert (sky_ == other.sky_);
+
+ list<Building> other_bld (other.buildings_);
+ list<Building> my_bld;
+ my_bld.splice (my_bld.begin (), buildings_);
+ internal_merge_skyline (&other_bld, &my_bld, &buildings_);
+ assert (is_legal_skyline (buildings_));
+}
+
+void
+Skyline::insert (Box const &b, Real horizon_padding, Axis a)
+{
+ list<Building> other_bld;
+ list<Building> my_bld;
+
+ my_bld.splice (my_bld.begin (), buildings_);
+ single_skyline (Building (b, 0, a, sky_), horizon_padding, &other_bld);
+ internal_merge_skyline (&other_bld, &my_bld, &buildings_);
+ assert (is_legal_skyline (buildings_));
+}
+
+void
+Skyline::raise (Real r)
+{
+ 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;
+ }
+}