Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* | 1 /* |
2 This file is part of LilyPond, the GNU music typesetter. | 2 This file is part of LilyPond, the GNU music typesetter. |
3 | 3 |
4 Copyright (C) 2006--2012 Joe Neeman <joeneeman@gmail.com> | 4 Copyright (C) 2006--2012 Joe Neeman <joeneeman@gmail.com> |
5 | 5 |
6 LilyPond is free software: you can redistribute it and/or modify | 6 LilyPond is free software: you can redistribute it and/or modify |
7 it under the terms of the GNU General Public License as published by | 7 it under the terms of the GNU General Public License as published by |
8 the Free Software Foundation, either version 3 of the License, or | 8 the Free Software Foundation, either version 3 of the License, or |
9 (at your option) any later version. | 9 (at your option) any later version. |
10 | 10 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 | 101 |
102 start_ = start; | 102 start_ = start; |
103 end_ = end; | 103 end_ = end; |
104 precompute (start, height, height, end); | 104 precompute (start, height, height, end); |
105 } | 105 } |
106 | 106 |
107 void | 107 void |
108 Building::precompute (Real start, Real start_height, Real end_height, Real end) | 108 Building::precompute (Real start, Real start_height, Real end_height, Real end) |
109 { | 109 { |
110 slope_ = 0.0; /* if they were both infinite, we would get nan, not 0, from the prev line */ | 110 slope_ = 0.0; /* if they were both infinite, we would get nan, not 0, from the prev line */ |
111 if (start_height != end_height) | 111 if (start_height != end_height) |
Keith
2012/09/16 18:52:55
Does anyone know the reason for this change?
For
| |
112 slope_ = (end_height - start_height) / (end - start); | 112 slope_ = (end_height - start_height) / (end - start); |
113 | 113 |
114 assert (!isinf (slope_) && !isnan (slope_)); | 114 assert (!isinf (slope_) && !isnan (slope_)); |
115 | 115 |
116 if (isinf (start)) | 116 if (isinf (start)) |
117 { | 117 { |
118 assert (start_height == end_height); | 118 assert (start_height == end_height); |
119 y_intercept_ = start_height; | 119 y_intercept_ = start_height; |
120 } | 120 } |
121 else | 121 else |
(...skipping 25 matching lines...) Expand all Loading... | |
147 assert (chop <= end_); | 147 assert (chop <= end_); |
148 end_ = chop; | 148 end_ = chop; |
149 } | 149 } |
150 | 150 |
151 // Returns a shift s such that (x + s, y) intersects the roof of | 151 // Returns a shift s such that (x + s, y) intersects the roof of |
152 // this building. If no such shift exists, returns infinity_f. | 152 // this building. If no such shift exists, returns infinity_f. |
153 Real | 153 Real |
154 Building::shift_to_intersect (Real x, Real y) const | 154 Building::shift_to_intersect (Real x, Real y) const |
155 { | 155 { |
156 // Solve for s: y = (x + s)*m + b | 156 // Solve for s: y = (x + s)*m + b |
157 Real ret = (y - y_intercept_ - slope_ * x) / slope_; | 157 Real ret = (y - y_intercept_ - slope_ * x) / slope_; |
Keith
2012/08/14 04:21:33
(y - height(x))
MikeSol
2012/08/16 04:15:39
Done.
| |
158 | 158 |
159 if (ret >= start_ && ret <= end_ && !isinf (ret)) | 159 if (ret >= start_ && ret <= end_ && !isinf (ret)) |
160 return ret; | 160 return ret; |
161 return infinity_f; | 161 return infinity_f; |
162 } | 162 } |
163 | 163 |
164 // Returns the interval of horizontal shifts for which this | 164 // Returns the interval of horizontal shifts for which this |
165 // building (pointing up) overlaps the other building (pointing down). | 165 // building (pointing up) overlaps the other building (pointing down). |
166 Interval | 166 Interval |
167 Building::overlapping_shift_interval (Building const& other) const | 167 Building::overlapping_shift_interval (Building const &other) const |
168 { | 168 { |
169 Interval iv; | 169 Interval iv; |
170 | 170 |
171 // If one building is empty, there will never be an overlap. | 171 // If one building is empty, there will never be an overlap. |
172 if (y_intercept_ == -infinity_f || other.y_intercept_ == -infinity_f) | 172 if (y_intercept_ == -infinity_f || other.y_intercept_ == -infinity_f) |
173 return iv; | 173 return iv; |
174 | 174 |
175 // There are two kinds of interesting positions: | 175 // There are two kinds of interesting positions: |
176 // - when the horizontal extents of the buildings just touch | 176 // - when the horizontal extents of the buildings just touch |
177 // - when an endpoint of one building intersects the roof of the other. | 177 // - when an endpoint of one building intersects the roof of the other. |
178 // The interval we are looking for is the smallest one that | 178 // The interval we are looking for is the smallest one that |
179 // contains all of the interesting points. | 179 // contains all of the interesting points. |
180 | 180 |
181 | 181 |
182 Real my_y1 = height (start_); | 182 Real my_y1 = height (start_); |
183 Real my_y2 = height (end_); | 183 Real my_y2 = height (end_); |
184 Real his_y1 = -other.height (other.start_); // "-" because OTHER points down | 184 Real his_y1 = -other.height (other.start_); // "-" because OTHER points down |
185 Real his_y2 = -other.height (other.end_); | 185 Real his_y2 = -other.height (other.end_); |
186 | 186 |
187 // If both buildings are infinite in the same direction, | 187 // If both buildings are infinite in the same direction, |
188 // the return value is either empty or full. | 188 // the return value is either empty or full. |
189 if ((isinf (start_) && isinf (other.start_)) | 189 if ((isinf (start_) && isinf (other.start_)) |
190 || (isinf (end_) && isinf (other.end_))) | 190 || (isinf (end_) && isinf (other.end_))) |
191 return (y_intercept_ > other.y_intercept_) | 191 return (y_intercept_ > other.y_intercept_) |
192 ? Interval (-infinity_f, infinity_f) : Interval (); | 192 ? Interval (-infinity_f, infinity_f) : Interval (); |
193 | 193 |
194 // ...when the horizontal extents of the buildings just touch... | 194 // ...when the horizontal extents of the buildings just touch... |
195 if (my_y1 >= his_y2) | 195 if (my_y1 >= his_y2) |
196 iv.add_point (other.end_ - start_); | 196 iv.add_point (other.end_ - start_); |
197 if (my_y2 >= his_y1) | 197 if (my_y2 >= his_y1) |
198 iv.add_point (other.start_ - end_); | 198 iv.add_point (other.start_ - end_); |
199 | 199 |
200 // ...when an endpoint of one building intersects the roof of the other. | 200 // ...when an endpoint of one building intersects the roof of the other. |
201 Real p1 = shift_to_intersect (other.start_, his_y1); | 201 Real p1 = shift_to_intersect (other.start_, his_y1); |
202 Real p2 = shift_to_intersect (other.end_, his_y2); | 202 Real p2 = shift_to_intersect (other.end_, his_y2); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 if (last_empty && i->y_intercept_ == -infinity_f) | 272 if (last_empty && i->y_intercept_ == -infinity_f) |
273 { | 273 { |
274 list<Building>::iterator last = i; | 274 list<Building>::iterator last = i; |
275 last--; | 275 last--; |
276 last->end_ = i->end_; | 276 last->end_ = i->end_; |
277 buildings_.erase (i); | 277 buildings_.erase (i); |
278 i = last; | 278 i = last; |
279 } | 279 } |
280 last_empty = (i->y_intercept_ == -infinity_f); | 280 last_empty = (i->y_intercept_ == -infinity_f); |
281 } | 281 } |
282 | |
283 assert (buildings_.front ().start_ == -infinity_f); | |
284 assert (buildings_.back ().end_ == infinity_f); | |
282 } | 285 } |
283 | 286 |
284 void | 287 void |
285 Skyline::deholify () | 288 Skyline::deholify () |
286 { | 289 { |
287 // Since a skyline should always be normalized, we can | 290 // Since a skyline should always be normalized, we can |
Keith
2012/08/14 04:21:33
I think you mean "this function requires the skyli
MikeSol
2012/08/16 04:15:39
Done.
| |
288 // assume that there are never two adjacent empty buildings. | 291 // assume that there are never two adjacent empty buildings. |
289 // That is, if center is empty then left and right are not. | 292 // That is, if center is empty then left and right are not. |
290 list<Building>::iterator left = buildings_.begin (); | 293 list<Building>::iterator left = buildings_.begin (); |
291 list<Building>::iterator center = buildings_.begin (); | 294 list<Building>::iterator center = buildings_.begin (); |
292 list<Building>::iterator right; | 295 list<Building>::iterator right; |
293 | 296 |
294 for (right = buildings_.begin (); right != buildings_.end (); right++) | 297 for (right = buildings_.begin (); right != buildings_.end (); right++) |
295 { | 298 { |
296 if (center != buildings_.begin () && center->y_intercept_ == -infinity_f) | 299 if (center != buildings_.begin () && center->y_intercept_ == -infinity_f) |
297 { | 300 { |
(...skipping 11 matching lines...) Expand all Loading... | |
309 Skyline::internal_merge_skyline (list<Building> *s1, list<Building> *s2, | 312 Skyline::internal_merge_skyline (list<Building> *s1, list<Building> *s2, |
310 list<Building> *const result) const | 313 list<Building> *const result) const |
311 { | 314 { |
312 if (s1->empty () || s2->empty ()) | 315 if (s1->empty () || s2->empty ()) |
313 { | 316 { |
314 programming_error ("tried to merge an empty skyline"); | 317 programming_error ("tried to merge an empty skyline"); |
315 return; | 318 return; |
316 } | 319 } |
317 | 320 |
318 Real x = -infinity_f; | 321 Real x = -infinity_f; |
322 Real last_end = -infinity_f; | |
319 while (!s1->empty ()) | 323 while (!s1->empty ()) |
320 { | 324 { |
321 if (s2->front ().conceals (s1->front (), x)) | 325 if (s2->front ().conceals (s1->front (), x)) |
322 swap (s1, s2); | 326 swap (s1, s2); |
323 | 327 |
324 Building b = s1->front (); | 328 Building b = s1->front (); |
325 Building c = s2->front (); | 329 Building c = s2->front (); |
326 | 330 |
327 // Optimization: if the other skyline is empty at this point, | 331 // Optimization: if the other skyline is empty at this point, |
328 // we can avoid testing some intersections. Just grab as many | 332 // we can avoid testing some intersections. Just grab as many |
329 // buildings from s1 as we can, and shove them onto the output. | 333 // buildings from s1 as we can, and shove them onto the output. |
330 if (c.y_intercept_ == -infinity_f | 334 if (c.y_intercept_ == -infinity_f |
331 && c.end_ >= b.end_) | 335 && c.end_ >= b.end_) |
332 { | 336 { |
333 list<Building>::iterator i = s1->begin (); | 337 list<Building>::iterator i = s1->begin (); |
334 i++; | 338 i++; |
335 while (i != s1->end () && i->end_ <= c.end_) | 339 while (i != s1->end () && i->end_ <= c.end_) |
336 i++; | 340 i++; |
337 | 341 |
338 s1->front ().start_ = x; | 342 s1->front ().start_ = x; |
339 result->splice (result->end (), *s1, s1->begin (), i); | 343 result->splice (result->end (), *s1, s1->begin (), i); |
340 x = result->back ().end_; | 344 x = result->back ().end_; |
345 last_end = x; | |
341 continue; | 346 continue; |
342 } | 347 } |
343 | 348 |
344 Real end = first_intersection (b, s2, x); | 349 Real end = first_intersection (b, s2, x); |
345 if (s2->empty ()) | 350 if (s2->empty ()) |
346 { | 351 { |
347 b.start_ = result->back ().end_; | 352 b.start_ = last_end; |
348 result->push_back (b); | 353 result->push_back (b); |
349 break; | 354 break; |
350 } | 355 } |
351 | 356 |
352 /* only include buildings wider than epsilon */ | 357 /* only include buildings wider than epsilon */ |
353 if (end > x + EPS) | 358 if (end > x + EPS) |
354 { | 359 { |
355 b.leading_part (end); | 360 b.leading_part (end); |
356 b.start_ = result->back ().end_; | 361 b.start_ = last_end; |
362 last_end = b.end_; | |
357 result->push_back (b); | 363 result->push_back (b); |
358 } | 364 } |
359 | 365 |
360 if (end >= s1->front ().end_) | 366 if (end >= s1->front ().end_) |
361 s1->pop_front (); | 367 s1->pop_front (); |
362 | 368 |
363 x = end; | 369 x = end; |
364 } | 370 } |
365 } | 371 } |
366 | 372 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
437 result.push_back (Building (last_end, -infinity_f, -infinity_f, infinity_f)) ; | 443 result.push_back (Building (last_end, -infinity_f, -infinity_f, infinity_f)) ; |
438 return result; | 444 return result; |
439 } | 445 } |
440 | 446 |
441 class LessThanBuilding | 447 class LessThanBuilding |
442 { | 448 { |
443 public: | 449 public: |
444 bool operator () (Building const &b1, Building const &b2) | 450 bool operator () (Building const &b1, Building const &b2) |
445 { | 451 { |
446 return b1.start_ < b2.start_ | 452 return b1.start_ < b2.start_ |
447 || (b1.start_ == b2.start_ && b1.height (b1.start_) > b2.height (b1.start_ )); | 453 || (b1.start_ == b2.start_ && b1.height (b1.start_) > b2.height (b1.s tart_)); |
448 } | 454 } |
449 }; | 455 }; |
450 | 456 |
451 /** | 457 /** |
452 BUILDINGS is a list of buildings, but they could be overlapping | 458 BUILDINGS is a list of buildings, but they could be overlapping |
453 and in any order. The returned list of buildings is ordered and non-overlapp ing. | 459 and in any order. The returned list of buildings is ordered and non-overlapp ing. |
454 */ | 460 */ |
455 list<Building> | 461 list<Building> |
456 Skyline::internal_build_skyline (list<Building> *buildings) const | 462 Skyline::internal_build_skyline (list<Building> *buildings) const |
457 { | 463 { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
545 | 551 |
546 Buildings should have fatness in the horizon_axis, otherwise they are ignored. | 552 Buildings should have fatness in the horizon_axis, otherwise they are ignored. |
547 */ | 553 */ |
548 Skyline::Skyline (vector<Drul_array<Offset> > const &segments, Axis horizon_axis , Direction sky) | 554 Skyline::Skyline (vector<Drul_array<Offset> > const &segments, Axis horizon_axis , Direction sky) |
549 { | 555 { |
550 list<Building> buildings; | 556 list<Building> buildings; |
551 sky_ = sky; | 557 sky_ = sky; |
552 | 558 |
553 for (vsize i = 0; i < segments.size (); i++) | 559 for (vsize i = 0; i < segments.size (); i++) |
554 { | 560 { |
555 Drul_array<Offset> const& seg = segments[i]; | 561 Drul_array<Offset> const &seg = segments[i]; |
556 Offset left = seg[LEFT]; | 562 Offset left = seg[LEFT]; |
557 Offset right = seg[RIGHT]; | 563 Offset right = seg[RIGHT]; |
558 if (left[horizon_axis] > right[horizon_axis]) | 564 if (left[horizon_axis] > right[horizon_axis]) |
559 swap (left, right); | 565 swap (left, right); |
560 | 566 |
561 Real x1 = left[horizon_axis]; | 567 Real x1 = left[horizon_axis]; |
562 Real x2 = right[horizon_axis]; | 568 Real x2 = right[horizon_axis]; |
563 Real y1 = left[other_axis (horizon_axis)] * sky; | 569 Real y1 = left[other_axis (horizon_axis)] * sky; |
564 Real y2 = right[other_axis (horizon_axis)] * sky; | 570 Real y2 = right[other_axis (horizon_axis)] * sky; |
565 | 571 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
688 { | 694 { |
689 if (horizon_padding == 0.0) | 695 if (horizon_padding == 0.0) |
690 return internal_distance (other, touch_point); | 696 return internal_distance (other, touch_point); |
691 | 697 |
692 // Note that it is not necessary to build a padded version of other, | 698 // Note that it is not necessary to build a padded version of other, |
693 // because the same effect can be achieved just by doubling horizon_padding. | 699 // because the same effect can be achieved just by doubling horizon_padding. |
694 Skyline padded_this = padded (horizon_padding); | 700 Skyline padded_this = padded (horizon_padding); |
695 return padded_this.internal_distance (other, touch_point); | 701 return padded_this.internal_distance (other, touch_point); |
696 } | 702 } |
697 | 703 |
698 | |
699 Skyline | 704 Skyline |
700 Skyline::padded (Real horizon_padding) const | 705 Skyline::padded (Real horizon_padding) const |
701 { | 706 { |
702 list<Building> pad_buildings; | 707 list<Building> pad_buildings; |
703 for (list<Building>::const_iterator i = buildings_.begin (); i != buildings_.e nd (); ++i) | 708 for (list<Building>::const_iterator i = buildings_.begin (); i != buildings_.e nd (); ++i) |
704 { | 709 { |
705 if (i->start_ > -infinity_f) | 710 if (i->start_ > -infinity_f) |
706 { | 711 { |
707 Real height = i->height (i->start_); | 712 Real height = i->height (i->start_); |
708 if (height > -infinity_f) | 713 if (height > -infinity_f) |
709 { | 714 { |
710 // Add the sloped building that pads the left side of the current building. | 715 // Add the sloped building that pads the left side of the current building. |
711 Real start = i->start_ - 2*horizon_padding; | 716 Real start = i->start_ - 2 * horizon_padding; |
712 Real end = i->start_ - horizon_padding; | 717 Real end = i->start_ - horizon_padding; |
713 pad_buildings.push_back (Building (start, height - horizon_padding , height, end)); | 718 pad_buildings.push_back (Building (start, height - horizon_padding , height, end)); |
714 | 719 |
715 // Add the flat building that pads the left side of the current bu ilding. | 720 // Add the flat building that pads the left side of the current bu ilding. |
716 start = i->start_ - horizon_padding; | 721 start = i->start_ - horizon_padding; |
717 end = i->start_; | 722 end = i->start_; |
718 pad_buildings.push_back (Building (start, height, height, end)); | 723 pad_buildings.push_back (Building (start, height, height, end)); |
719 } | 724 } |
720 } | 725 } |
721 | 726 |
722 if (i->end_ < infinity_f) | 727 if (i->end_ < infinity_f) |
723 { | 728 { |
724 Real height = i->height (i->end_); | 729 Real height = i->height (i->end_); |
725 if (height > -infinity_f) | 730 if (height > -infinity_f) |
726 { | 731 { |
727 // Add the flat building that pads the right side of the current b uilding. | 732 // Add the flat building that pads the right side of the current b uilding. |
728 Real start = i->end_; | 733 Real start = i->end_; |
729 Real end = start + horizon_padding; | 734 Real end = start + horizon_padding; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
777 i++; | 782 i++; |
778 else | 783 else |
779 j++; | 784 j++; |
780 start = end; | 785 start = end; |
781 } | 786 } |
782 | 787 |
783 *touch_point = touch; | 788 *touch_point = touch; |
784 return dist; | 789 return dist; |
785 } | 790 } |
786 | 791 |
787 Skyline_intersection_info | |
788 Skyline::intersects (Skyline const &other) const | |
789 { | |
790 assert (sky_ == -other.sky_); | |
791 | |
792 /* | |
793 For systems, padding is not added at creation time. Padding is | |
794 added to AxisGroup objects when outside-staff objects are added. | |
795 Thus, when we want to place systems with horizontal padding, | |
796 we do it at distance calculation time. | |
797 */ | |
798 | |
799 list<Building>::const_iterator i = buildings_.begin (); | |
800 list<Building>::const_iterator j = other.buildings_.begin (); | |
801 | |
802 Real start = -infinity_f; | |
803 Drul_array<bool> intersections (false, false); | |
804 while (i != buildings_.end () && j != other.buildings_.end ()) | |
805 { | |
806 Real end = min (i->end_, j->end_); | |
807 Real start_dist = i->height (start) + j->height (start); | |
808 Real end_dist = i->height (end) + j->height (end); | |
809 if (!isinf (start_dist)) | |
810 { | |
811 if (start_dist == 0.0) | |
812 return INTERSECTS; | |
813 intersections[Direction (sign (start_dist))] = true; | |
814 } | |
815 if (!isinf (end_dist)) | |
816 { | |
817 if (end_dist == 0.0) | |
818 return INTERSECTS; | |
819 intersections[Direction (sign (end_dist))] = true; | |
820 } | |
821 if (intersections[DOWN] && intersections[UP]) | |
822 return INTERSECTS; | |
823 | |
824 if (i->end_ <= j->end_) | |
825 i++; | |
826 else | |
827 j++; | |
828 start = end; | |
829 } | |
830 | |
831 if (intersections[DOWN]) | |
832 return ALWAYS_LESS; | |
833 if (intersections[UP]) | |
834 return ALWAYS_GREATER; | |
835 return NOT_ENOUGH_INFO; | |
836 } | |
837 | |
838 // changes the direction that the skyline is pointing | 792 // changes the direction that the skyline is pointing |
839 void | 793 void |
840 Skyline::invert () | 794 Skyline::invert () |
841 { | 795 { |
842 list<Building>::iterator i; | 796 list<Building>::iterator i; |
843 for (i = buildings_.begin (); i != buildings_.end (); i++) | 797 for (i = buildings_.begin (); i != buildings_.end (); i++) |
844 if (!isinf (i->y_intercept_)) | 798 if (!isinf (i->y_intercept_)) |
845 { | 799 { |
846 i->y_intercept_ *= -1; | 800 i->y_intercept_ *= -1; |
847 i->slope_ *= -1; | 801 i->slope_ *= -1; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
912 } | 866 } |
913 | 867 |
914 if (horizon_axis == Y_AXIS) | 868 if (horizon_axis == Y_AXIS) |
915 for (vsize i = 0; i < out.size (); i++) | 869 for (vsize i = 0; i < out.size (); i++) |
916 out[i] = out[i].swapped (); | 870 out[i] = out[i].swapped (); |
917 | 871 |
918 return out; | 872 return out; |
919 } | 873 } |
920 | 874 |
921 // Returns the smallest (non-negative) shift in the given | 875 // Returns the smallest (non-negative) shift in the given |
922 // direction which will result in THIS and OTHER not overlapping. | 876 // direction which will result in THIS and OTHER not overlapping. |
Keith
2012/08/14 04:21:33
.. in the given direction /along/ the skyline, loc
MikeSol
2012/08/16 04:15:39
Done.
| |
923 // Warning: this function is O(n^2 log n). Use sparingly. | 877 // Warning: this function is O(n^2 log n). Use sparingly. |
924 Real | 878 Real |
925 Skyline::smallest_shift (Skyline const& other, | 879 Skyline::smallest_shift (Skyline const &other, |
926 Direction d, | 880 Direction d, |
927 Real horizon_padding, | 881 Real horizon_padding, |
928 Real vertical_padding) const | 882 Real vertical_padding) const |
929 { | 883 { |
930 // If one or both of the paddings is zero, this can | 884 // If one or both of the paddings is zero, this can |
931 // be optimized... | 885 // be optimized... |
932 Skyline padded_me = padded (horizon_padding); | 886 Skyline padded_me = padded (horizon_padding); |
933 padded_me.raise (vertical_padding); | 887 padded_me.raise (vertical_padding); |
934 | 888 |
935 list<Building>::const_iterator i = padded_me.buildings_.begin (); | 889 list<Building>::const_iterator i = padded_me.buildings_.begin (); |
(...skipping 12 matching lines...) Expand all Loading... | |
948 forbidden_shifts.push_back (iv); | 902 forbidden_shifts.push_back (iv); |
949 } | 903 } |
950 | 904 |
951 // Now comes the trick: we want to find the smallest point | 905 // Now comes the trick: we want to find the smallest point |
952 // that is not in the union of forbidden_shifts. We can represent | 906 // that is not in the union of forbidden_shifts. We can represent |
953 // the union of forbidden_shifts as a skyline, where a point is | 907 // the union of forbidden_shifts as a skyline, where a point is |
954 // allowed if it has height -infinity_f and forbidden otherwise. | 908 // allowed if it has height -infinity_f and forbidden otherwise. |
955 vector<Box> boxes; | 909 vector<Box> boxes; |
956 for (vector<Interval>::iterator k = forbidden_shifts.begin (); | 910 for (vector<Interval>::iterator k = forbidden_shifts.begin (); |
957 k != forbidden_shifts.end (); ++k) | 911 k != forbidden_shifts.end (); ++k) |
958 boxes.push_back (Box (*k, Interval(-1, 0))); | 912 boxes.push_back (Box (*k, Interval (-1, 0))); |
959 Skyline s (boxes, X_AXIS, UP); | 913 Skyline s (boxes, X_AXIS, UP); |
960 | 914 |
961 // Find the smallest (ie. closest to zero, in the appropriate direction) | 915 // Find the smallest (ie. closest to zero, in the appropriate direction) |
962 // coordinate where the height of s is -infinity_f. | 916 // coordinate where the height of s is -infinity_f. |
963 Real last_good_point = -infinity_f; | 917 Real last_good_point = -infinity_f; |
964 for (i = s.buildings_.begin (); i != s.buildings_.end (); ++i) | 918 for (i = s.buildings_.begin (); i != s.buildings_.end (); ++i) |
965 { | 919 { |
966 if (d == LEFT && i->start_ > 0) | 920 if (d == LEFT && i->start_ > 0) |
967 return last_good_point; | 921 return last_good_point; |
968 | 922 |
(...skipping 10 matching lines...) Expand all Loading... | |
979 | 933 |
980 return infinity_f * d; | 934 return infinity_f * d; |
981 } | 935 } |
982 | 936 |
983 Real | 937 Real |
984 Skyline::left () const | 938 Skyline::left () const |
985 { | 939 { |
986 for (list<Building>::const_iterator i (buildings_.begin ()); | 940 for (list<Building>::const_iterator i (buildings_.begin ()); |
987 i != buildings_.end (); i++) | 941 i != buildings_.end (); i++) |
988 if (i->y_intercept_ > -infinity_f) | 942 if (i->y_intercept_ > -infinity_f) |
989 return i->start_; | 943 return i->start_; |
990 | 944 |
991 return infinity_f; | 945 return infinity_f; |
992 } | 946 } |
993 | 947 |
994 Real | 948 Real |
995 Skyline::right () const | 949 Skyline::right () const |
996 { | 950 { |
997 for (list<Building>::const_reverse_iterator i (buildings_.rbegin ()); | 951 for (list<Building>::const_reverse_iterator i (buildings_.rbegin ()); |
998 i != buildings_.rend (); ++i) | 952 i != buildings_.rend (); ++i) |
999 if (i->y_intercept_ > -infinity_f) | 953 if (i->y_intercept_ > -infinity_f) |
(...skipping 17 matching lines...) Expand all Loading... | |
1017 return buildings_.size () == 3; | 971 return buildings_.size () == 3; |
1018 } | 972 } |
1019 | 973 |
1020 void | 974 void |
1021 Skyline::clear () | 975 Skyline::clear () |
1022 { | 976 { |
1023 buildings_.clear (); | 977 buildings_.clear (); |
1024 empty_skyline (&buildings_); | 978 empty_skyline (&buildings_); |
1025 } | 979 } |
1026 | 980 |
1027 string | |
1028 Skyline::intersection_info_to_string (Skyline_intersection_info sii) | |
1029 { | |
1030 if (sii == INTERSECTS) | |
1031 return "intersection"; | |
1032 if (sii == ALWAYS_GREATER) | |
1033 return "alwaysGreater"; | |
1034 if (sii == ALWAYS_LESS) | |
1035 return "alwaysLess"; | |
1036 if (sii == NOT_ENOUGH_INFO) | |
1037 return "notEnoughInfo"; | |
1038 | |
1039 assert (1 == 0); | |
1040 return "veryBad"; | |
1041 } | |
1042 | |
1043 Direction | |
1044 Skyline::intersection_info_to_direction (Skyline_intersection_info sii) | |
1045 { | |
1046 if (sii == INTERSECTS) | |
1047 return CENTER; | |
1048 if (sii == ALWAYS_GREATER) | |
1049 return UP; | |
1050 if (sii == ALWAYS_LESS) | |
1051 return DOWN; | |
1052 if (sii == NOT_ENOUGH_INFO) | |
1053 return CENTER; | |
1054 | |
1055 assert (1 == 0); | |
1056 return CENTER; | |
1057 } | |
1058 | |
1059 /****************************************************************/ | 981 /****************************************************************/ |
1060 | 982 |
1061 IMPLEMENT_SIMPLE_SMOBS (Skyline); | 983 IMPLEMENT_SIMPLE_SMOBS (Skyline); |
1062 IMPLEMENT_TYPE_P (Skyline, "ly:skyline?"); | 984 IMPLEMENT_TYPE_P (Skyline, "ly:skyline?"); |
1063 IMPLEMENT_DEFAULT_EQUAL_P (Skyline); | 985 IMPLEMENT_DEFAULT_EQUAL_P (Skyline); |
1064 | 986 |
1065 SCM | 987 SCM |
1066 Skyline::mark_smob (SCM s) | 988 Skyline::mark_smob (SCM s) |
1067 { | 989 { |
1068 ASSERT_LIVE_IS_ALLOWED (s); | 990 ASSERT_LIVE_IS_ALLOWED (s); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1130 return scm_from_double (Skyline::unsmob (skyline_scm)->max_height_position ()) ; | 1052 return scm_from_double (Skyline::unsmob (skyline_scm)->max_height_position ()) ; |
1131 } | 1053 } |
1132 | 1054 |
1133 MAKE_SCHEME_CALLBACK (Skyline, get_height, 2) | 1055 MAKE_SCHEME_CALLBACK (Skyline, get_height, 2) |
1134 SCM | 1056 SCM |
1135 Skyline::get_height (SCM skyline_scm, SCM x_scm) | 1057 Skyline::get_height (SCM skyline_scm, SCM x_scm) |
1136 { | 1058 { |
1137 Real x = robust_scm2double (x_scm, 0.0); | 1059 Real x = robust_scm2double (x_scm, 0.0); |
1138 return scm_from_double (Skyline::unsmob (skyline_scm)->height (x)); | 1060 return scm_from_double (Skyline::unsmob (skyline_scm)->height (x)); |
1139 } | 1061 } |
LEFT | RIGHT |