- if (s2->front ().conceals (s1->front (), x))
- swap (s1, s2);
-
- Building b = s1->front ();
- Real end = first_intersection (b, s2, x);
-
- if (s2->empty ())
- {
- result->push_front (b);
- break;
- }
-
- /* only include buildings wider than epsilon */
- if (end > x + EPS)
- {
- b.leading_part (end);
- result->push_front (b);
- }
-
- if (end >= s1->front ().end_)
- s1->pop_front ();
-
- x = end;
+ /* Building b is continuing from the previous pass through the loop.
+ Building c is newly-considered, and starts no earlier than b started.
+ The comments draw b as if its roof had zero slope ----.
+ with dashes where b lies above c.
+ The roof of c could rise / or fall \ through the roof of b,
+ or the vertical sides | of c could intersect the roof of b. */
+ Building c = sc->front ();
+ if (b.end_ < c.end_) /* finish with b */
+ {
+ if (b.end_ <= b.start_) /* we are already finished with b */
+ ;
+ else if (c.above (b, c.start_)) /* -| . | */
+ {
+ Building m (b);
+ m.end_ = c.start_;
+ if (m.end_ > m.start_)
+ result->push_back (m);
+ if (b.above (c, b.end_)) /* -|\--. */
+ {
+ Building n (c);
+ n.end_ = b.start_ = b.intersection_x (c);
+ result->push_back (n);
+ result->push_back (b);
+ }
+ }
+ else
+ {
+ if (c.above (b, b.end_)) /* ---/ . | */
+ b.end_ = b.intersection_x (c);
+ else /* -----. */
+ c.start_ = b.end_;
+ result->push_back (b);
+ }
+ /* 'c' continues further, so move it into 'b' for the next pass. */
+ b = c;
+ swap (sb, sc);
+ }
+ else /* b.end_ > c.end_ so finish with c */
+ {
+ if (c.above (b, c.start_)) /* -| |---. */
+ {
+ Building m (b);
+ m.end_ = c.start_;
+ if (m.end_ > m.start_)
+ result->push_back (m);
+ if (b.above (c, c.end_)) /* -| \---. */
+ c.end_ = b.intersection_x (c);
+ }
+ else if (c.above (b, c.end_)) /* ---/|--. */
+ {
+ Building m (b);
+ c.start_ = m.end_ = b.intersection_x (c);
+ result->push_back (m);
+ }
+ else /* c is completely hidden by b */
+ continue;
+ result->push_back (c);
+ b.start_ = c.end_;
+ }