private:
list<Building> buildings_;
Direction sky_;
-
+
void internal_merge_skyline (list<Building>*, list<Building>*,
list<Building> *const result);
list<Building> internal_build_skyline (list<Box>*, Real, Axis, Direction);
public:
Skyline ();
Skyline (Skyline const &src);
+ Skyline (Skyline const &src, Real horizon_padding, Axis a);
Skyline (Direction sky);
Skyline (vector<Box> const &bldgs, Real horizon_padding, Axis a, Direction sky);
Skyline (Box const &b, Real horizon_padding, Axis a, Direction sky);
-
+
vector<Offset> to_points (Axis) const;
void merge (Skyline const &);
void insert (Box const &, Real horizon_padding, Axis);
void print_points () const;
void raise (Real);
void shift (Real);
- Real distance (Skyline const &) const;
+ Real distance (Skyline const &, Real horizon_padding = 0) const;
Real height (Real airplane) const;
Real max_height () const;
void set_minimum_height (Real height);
y_intercept_ = start_height - slope_ * start;
}
-Real
+Real
Building::height (Real x) const
{
return isinf (x) ? y_intercept_ : slope_*x + y_intercept_;
-infinity_f, infinity_f));
if (sloped_neighbours)
ret->push_front (b.sloped_neighbour (start, horizon_padding, RIGHT));
-
+
if (b.end_ > start + EPS)
ret->push_front (b);
Skyline::Skyline (Skyline const &src)
{
sky_ = src.sky_;
-
+
/* doesn't a list's copy constructor do this? -- jneem */
for (list<Building>::const_iterator i = src.buildings_.begin ();
i != src.buildings_.end (); i++)
empty_skyline (&buildings_);
}
+/*
+ build padded skyline from an existing skyline with padding
+ added to it.
+*/
+
+Skyline::Skyline (Skyline const &src, Real horizon_padding, Axis a)
+{
+ /*
+ We extract boxes from the skyline, then build a new skyline from
+ the boxes.
+ A box is created for every horizontal portion of the skyline
+ Because skylines are defined positive, and then inverted if they
+ are to be down-facing, we create the new skyline in the UP
+ direction, then give it the down direction if needed.
+ */
+ Real start = -infinity_f;
+ list<Box> boxes;
+
+ // establish a baseline box
+ boxes.push_back (Box (Interval (-infinity_f, infinity_f),
+ Interval (0, 0)));
+ list<Building>::const_iterator end = src.buildings_.end ();
+ for (list<Building>::const_iterator i = src.buildings_.begin (); i != end; start=i->end_, i++ )
+ if ((i->slope_ == 0) && !isinf (i->y_intercept_))
+ boxes.push_back (Box (Interval (start, i->end_),
+ Interval (-infinity_f , i->y_intercept_)));
+ buildings_ = internal_build_skyline (&boxes, horizon_padding, X_AXIS, UP);
+ sky_ = src.sky_;
+}
+
+
/*
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
if (iv.length () > EPS && !boxes[i][vert_axis].is_empty ())
filtered_boxes.push_front (boxes[i]);
}
-
+
buildings_ = internal_build_skyline (&filtered_boxes, horizon_padding, horizon_axis, sky);
}
}
Real
-Skyline::distance (Skyline const &other) const
+Skyline::distance (Skyline const &other, Real horizon_padding) const
{
assert (sky_ == -other.sky_);
- list<Building>::const_iterator i = buildings_.begin ();
- list<Building>::const_iterator j = other.buildings_.begin ();
+
+ Skyline const *padded_this = this;
+ Skyline const *padded_other = &other;
+
+ /*
+ For systems, padding is not added at creation time. Padding is
+ added to AxisGroup objects when outside-staff objects are added.
+ Thus, when we want to place systems with horizontal padding,
+ we do it at distance calculation time.
+ */
+ if (horizon_padding != 0.0)
+ {
+ padded_this = new Skyline (*padded_this, horizon_padding, X_AXIS);
+ padded_other = new Skyline (*padded_other, horizon_padding, X_AXIS);
+ }
+
+ list<Building>::const_iterator i = padded_this->buildings_.begin ();
+ list<Building>::const_iterator j = padded_other->buildings_.begin ();
Real dist = -infinity_f;
Real start = -infinity_f;
- while (i != buildings_.end () && j != other.buildings_.end ())
+ 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);