]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/skyline.cc
* lily/stencil-scheme.cc:
[lilypond.git] / lily / skyline.cc
index cc47448ee9d07143d774ea586719a9cd9e3b0d24..718200c01297d1d1f935e8fd4729190ffda36e30 100644 (file)
@@ -3,7 +3,7 @@
 
   source file of the GNU LilyPond music typesetter
 
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c) 2002--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
 */
 
 #include "skyline.hh" 
 */
 
 #include "skyline.hh" 
@@ -26,7 +26,7 @@
   This file deals with building such skyline structure, and computing
   the minimum distance between two opposing skylines.
   
   This file deals with building such skyline structure, and computing
   the minimum distance between two opposing skylines.
   
-  
+   
   Invariants for a skyline:
 
   skyline[...].width_ forms a partition of the real interval, where
   Invariants for a skyline:
 
   skyline[...].width_ forms a partition of the real interval, where
@@ -38,6 +38,8 @@
  */
 
 
  */
 
 
+const Real EPS = 1e-12;  
+
 /*
   TODO: avoid unnecessary fragmentation.
 
 /*
   TODO: avoid unnecessary fragmentation.
 
@@ -49,31 +51,37 @@ insert_extent_into_skyline (Array<Skyline_entry> *line, Box b, Axis line_axis,
                            Direction d)
 {
   Interval extent = b[line_axis];
                            Direction d)
 {
   Interval extent = b[line_axis];
-  if (extent.empty_b())
+  if (extent.is_empty ())
     return;
   
   Real stick_out = b[other_axis (line_axis)][d];
     return;
   
   Real stick_out = b[other_axis (line_axis)][d];
-  
+
+  /*
+    Intersect each segment of LINE with EXTENT, and if non-empty, insert relevant segments. 
+   */
   for (int i = line->size(); i--;)
     {
       Interval w = line->elem(i).width_;
   for (int i = line->size(); i--;)
     {
       Interval w = line->elem(i).width_;
-      if (extent[LEFT] > w[RIGHT])
+      w.intersect (extent);
+
+      if (extent[LEFT] >= w[RIGHT])
        break;
       
        break;
       
-      w.intersect (extent);
       Real my_height = line->elem(i).height_;
 
       Real my_height = line->elem(i).height_;
 
-      if (!w.empty_b () && d* (my_height - stick_out) < 0)
+      if (!w.is_empty () &&
+         w.length() > EPS
+         && d* (my_height - stick_out) < 0)
        {
          Interval e1 (line->elem(i).width_[LEFT], extent[LEFT]);
          Interval e3 (extent[RIGHT], line->elem(i).width_[RIGHT]);
 
        {
          Interval e1 (line->elem(i).width_[LEFT], extent[LEFT]);
          Interval e3 (extent[RIGHT], line->elem(i).width_[RIGHT]);
 
-         if (!e3.empty_b ())
+         if (!e3.is_empty () && e3.length() > EPS)
            line->insert (Skyline_entry (e3, my_height), i+1);
 
          line->elem_ref(i).height_ = stick_out;
          line->elem_ref(i).width_ = w;
            line->insert (Skyline_entry (e3, my_height), i+1);
 
          line->elem_ref(i).height_ = stick_out;
          line->elem_ref(i).width_ = w;
-         if (!e1.empty_b ())
+         if (!e1.is_empty () && e1.length() > EPS)
            line->insert (Skyline_entry (e1, my_height), i );
        }
 
            line->insert (Skyline_entry (e1, my_height), i );
        }
 
@@ -81,6 +89,22 @@ insert_extent_into_skyline (Array<Skyline_entry> *line, Box b, Axis line_axis,
     }
 }
 
     }
 }
 
+void
+merge_skyline (Array<Skyline_entry> * a1,
+              Array<Skyline_entry> const  & a2,
+              Direction dir)
+{
+  for (int i = 0; i < a2.size(); i++)
+    {
+      Box b;
+      b[X_AXIS] = a2[i].width_;
+      b[Y_AXIS][dir] = a2[i].height_;
+      b[Y_AXIS][-dir] = dir * infinity_f ;
+
+      insert_extent_into_skyline (a1, b, X_AXIS, dir);
+    }
+}
+
 
 Array<Skyline_entry>
 empty_skyline (Direction d)
 
 Array<Skyline_entry>
 empty_skyline (Direction d)
@@ -117,6 +141,7 @@ extents_to_skyline (Array<Box> const &extents, Axis a, Direction d)
 }
 
 
 }
 
 
+
 /*
   minimum distance that can be achieved between baselines. "Clouds" is
   a skyline pointing down.
 /*
   minimum distance that can be achieved between baselines. "Clouds" is
   a skyline pointing down.
@@ -137,7 +162,7 @@ skyline_meshing_distance (Array<Skyline_entry> const &buildings,
       Interval w = buildings[i].width_;
       w.intersect(clouds[j].width_);
       
       Interval w = buildings[i].width_;
       w.intersect(clouds[j].width_);
       
-      if (!w.empty_b())
+      if (!w.is_empty ())
        distance = distance >? (buildings[i].height_ - clouds[j].height_);
 
       if (i>0 && buildings[i].width_[LEFT] >=  clouds[j].width_[LEFT])
        distance = distance >? (buildings[i].height_ - clouds[j].height_);
 
       if (i>0 && buildings[i].width_[LEFT] >=  clouds[j].width_[LEFT])
@@ -164,3 +189,10 @@ Skyline_entry::Skyline_entry (Interval i, Real r)
   height_ = r;
   
 }
   height_ = r;
   
 }
+
+void
+heighten_skyline (Array<Skyline_entry> *buildings, Real ground)
+{
+  for (int i = 0; i < buildings->size (); i++)
+    buildings->elem_ref (i).height_ += ground; 
+}