+
+vector<Offset>
+Skyline::to_points (Axis horizon_axis) const
+{
+ vector<Offset> out;
+
+ Real start = -infinity_f;
+ for (list<Building>::const_iterator i (buildings_.begin ());
+ i != buildings_.end (); i++)
+ {
+ out.push_back (Offset (start, sky_ * i->height (start)));
+ out.push_back (Offset (i->end_, sky_ * i->height (i->end_)));
+ start = i->end_;
+ }
+
+ if (horizon_axis == Y_AXIS)
+ for (vsize i = 0; i < out.size (); i++)
+ out[i] = out[i].swapped ();
+
+ return out;
+}
+
+bool
+Skyline::is_empty () const
+{
+ Building b = buildings_.front ();
+ return b.end_ == infinity_f && b.y_intercept_ == -infinity_f;
+}
+
+void
+Skyline::clear ()
+{
+ buildings_.clear ();
+ empty_skyline (&buildings_);
+}
+
+/****************************************************************/
+
+IMPLEMENT_SIMPLE_SMOBS (Skyline);
+IMPLEMENT_TYPE_P (Skyline, "ly:skyline?");
+IMPLEMENT_DEFAULT_EQUAL_P (Skyline);
+
+SCM
+Skyline::mark_smob (SCM s)
+{
+ ASSERT_LIVE_IS_ALLOWED (s);
+ 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;
+}
+
+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));
+}