Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
eepicgeom.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
61# ifndef EEPICGEOM_H
62# define EEPICGEOM_H
63
64
65# include <fstream>
66# include <tpl_dynDlist.H>
67# include <tpl_sort_utils.H>
68# include <point.H>
69# include <polygon.H>
70# include <ah-errors.H>
71
77extern bool tiny_keys;
78
79// TODO: dotted polygon curves
80
81class Eepic_Plane;
82
83
108{
110
112
113protected:
120
127
128public:
135 Eepic_Geom_Object(Geom_Object *ptr, const bool & __to_delete = false)
137 {
138 // empty
139 }
140
146 {
147 if (to_delete)
148 delete geom_object_ptr;
149 }
150
162 virtual void draw(Eepic_Plane *plane, std::ostream & output) const
163 {
164 (void)plane;
165 (void)output;
166
168 << "Eepic_Geom_Object is null";
169
170 ah_logic_error() << "Call to draw() method from abstract class";
171 }
172
180 virtual Eepic_Geom_Object * clone() const = 0;
181
185 virtual Point highest_point() const = 0;
186
190 virtual Point lowest_point() const = 0;
191
195 virtual Point leftmost_point() const = 0;
196
200 virtual Point rightmost_point() const = 0;
201};
202
203
250{
251 // Picture environment frame defined at construction time
252 double wide;
253 double height;
254
255 // Final frame dimensions based on user's scaling choice
256 double real_wide = 0;
257 double real_height = 0;
258
259 double xoffset;
260 double yoffset;
261
264
266
269
270 // NOTE: These must be initialized to zero as they are used in
271 // self-referential calculations
272 double x_min;
273 double y_min;
274
275 // Extreme points for computing object dimensions
280
282
284 static const double default_r;
285
286 double r;
287
288 // Parameters that control the LaTeX picture environment
289 double resolution;
290
291 std::string fill_type;
292 std::string shade_type;
293
294 static const double normal_thickness;
295 static const double default_shade_thickness;
296
298
299 static const double dotgap;
300
307 const Geom_Number & geom_max,
308 const double & max) const
309 {
310 const Geom_Number ratio = p / geom_max;
311
312 double result = geom_number_to_double(ratio);
313
314 result = max * result;
315
316 return result;
317 }
318
325 double xpic(const double & x) const
326 {
327 return x - x_min;
328 }
329
331 double ypic(const double & y) const
332 {
333 return y - y_min;
334 }
335
336public:
338 double h_geom_number_to_eepic(const Geom_Number & x) const
339 {
341 }
342
345 {
347 }
348
350 double x_geom_number_to_eepic(const Geom_Number & x) const
351 {
353 }
354
357 {
358 const double result = geom_number_to_plane(y, geom_height, height);
359
360 return ypic(result);
361 }
362
365 {
366 // Scan all objects searching extreme coordinates (left, right, top, bottom).
368
369 ah_domain_error_if(not it.has_curr()) << "No objects in plane";
370
371 Eepic_Geom_Object *curr = it.get_curr();
372
373 __lowest = curr->lowest_point();
374 __highest = curr->highest_point();
375 __leftmost = curr->leftmost_point();
377
378 for (it.next(); it.has_curr(); it.next_ne())
379 {
380 curr = it.get_curr();
381
382 if (curr->lowest_point().get_y() < __lowest.get_y())
383 __lowest = curr->lowest_point();
384
385 if (curr->highest_point().get_y() > __highest.get_y())
386 __highest = curr->highest_point();
387
388 if (curr->leftmost_point().get_x() < __leftmost.get_x())
389 __leftmost = curr->leftmost_point();
390
391 if (curr->rightmost_point().get_x() > __rightmost.get_x())
393 }
394 }
395
397 void zoom(const double & factor)
398 {
399 ah_domain_error_if(factor <= 0) << "zoom factor must be greater than zero";
400
401 height *= factor;
402 wide *= factor;
403 }
404
405private:
408 void compute_geom_plane(const bool & squarize)
409 {
411
412 // Compute minimal bounding box from contained figures.
415
416 // Pad degenerate ranges so coordinate mapping never divides by zero.
417 if (geom_wide == 0)
419 if (geom_height == 0)
421
422 // Compute minimal x/y.
425
426 // Shift so that min point maps to plane origin (0,0).
429
430 if (squarize) // Preserve aspect ratio (avoid distorting figures).
431 {
433 {
436 real_wide = wide;
437 }
438 else
439 {
443 }
444 }
445 else
446 {
447 real_wide = wide;
449 }
450
452 << "Degenerate bounding box";
453 }
454
455 void draw_cartesian_axis(std::ostream & output);
456
457public:
458 const Point &leftmost() const { return __leftmost; }
459
460 const Point &rightmost() const { return __rightmost; }
461
462 const Point &highest() const { return __highest; }
463
464 const Point &lowest() const { return __lowest; }
465
467 std::string point_string(const Point & p)
468 {
469 const double x = x_geom_number_to_eepic(p.get_x());
470 const double y = y_geom_number_to_eepic(p.get_y());
471 return "(" + std::to_string(x) + "," + std::to_string(y) + ")";
472 }
473
484 void draw(std::ostream & output, const bool & squarize = true)
485 {
487
488 // Set floating point output format.
489 output << std::fixed << std::setprecision(6);
490
491 // Emit header and open picture environment.
492 output << "\\setlength{\\unitlength}{" << resolution << "mm}" << std::endl
493 << std::endl
494 << "\\filltype{" << fill_type << "}" << std::endl
495 << std::endl
496 << "% leftmost point is " << __leftmost.to_string() << " --> "
497 << point_string(__leftmost) << std::endl
498 << "% rightmost point is " << __rightmost.to_string() << " --> "
499 << point_string(__rightmost) << std::endl
500 << "% highest point is " << __highest.to_string() << " --> "
501 << point_string(__highest) << std::endl
502 << "% lowest point is " << __lowest.to_string() << " --> "
503 << point_string(__lowest) << std::endl
504 << "% " << list.size() << " geometric objects were put in the plane"
505 << std::endl
506 << "\\begin{picture}(" << real_wide << "," << real_height << ")"
507 << "(" << xoffset << "," << yoffset << ")" << std::endl
508 << std::endl;
509
510 draw_cartesian_axis(output); // Only if enabled.
511
512 // Draw each object.
514 it.has_curr(); it.next_ne())
515 {
516 Eepic_Geom_Object *curr = it.get_curr();
517
518 // Reset to default thickness each time.
519 output << "\\thinlines" << std::endl
520 << std::endl;
521
522 curr->draw(this, output);
523 }
524
525 // Close picture environment.
526 output << "\\end{picture}" << std::endl
527 << std::endl;
528 }
529
532 const double &get_wide() const { return wide; }
533
535 const double &get_height() const { return height; }
536
538 const double &get_yoffset() const { return yoffset; }
539
541 const double &get_xoffset() const { return xoffset; }
542
544 const double &get_r() const { return r; }
545
553 Eepic_Plane(const double & __wide,
554 const double & __height,
555 const double & __xoffset = 0.0,
556 const double & __yoffset = 0.0)
561 {
562 // empty
563 }
564
567 {
568 while (not list.is_empty())
569 delete list.remove_first_ne();
570 }
571
574 {
575 with_cartesian_axis = true;
576 }
577
614
616 void set_resolution(const double & res)
617 {
618 resolution = res;
619 }
620
622 const double &get_resolution() const { return resolution; }
623
625 void set_fill_type(const std::string & ftype)
626 {
628 }
629
631 void set_shade_thickness(const double & __thickness)
632 {
634 }
635
637 double get_shade_thickness() const { return shade_thickness; }
638
640 double get_dotgap() const { return dotgap; }
641
653 void draw_point(const Point & p, std::ostream & output)
654 {
655 const double x = x_geom_number_to_eepic(p.get_x());
656
657 const double y = y_geom_number_to_eepic(p.get_y());
658
659 output << " %% Point " << p.to_string()
660 << " %% mapped in this plane to (" << x << "," << y << ")"
661 << std::endl
662 << "\\put(" << x << "," << y << "){\\ellipse{" << r
663 << "}{" << r << "}}" << std::endl
664 << std::endl;
665 }
666
667 // Compute source/target EEPIC coordinates for a segment (macro for brevity).
668# define COMPUTE_SEGMENT_EEPIC_COORDENATES() \
669 const double src_x = x_geom_number_to_eepic(sg.get_src_point().get_x()); \
670 \
671 const double src_y = y_geom_number_to_eepic(sg.get_src_point().get_y()); \
672 \
673 const double tgt_x = x_geom_number_to_eepic(sg.get_tgt_point().get_x()); \
674 \
675 const double tgt_y = y_geom_number_to_eepic(sg.get_tgt_point().get_y());
676
677 // Draw the segment `sg` to `output` (macro uses locals above).
678# define DRAW_SEGMENT(sg, output) \
679 COMPUTE_SEGMENT_EEPIC_COORDENATES(); \
680 output << " %% Segment from " << sg.get_src_point().to_string() \
681 << " to " << sg.get_tgt_point().to_string() << std::endl \
682 << " %% mapped in this plane to (" << src_x << "," << src_y \
683 << ") to (" << tgt_x << "," << tgt_y << ")" << std::endl \
684 << "\\path(" << src_x << "," << src_y \
685 << ")(" << tgt_x << "," << tgt_y << ")" << std::endl \
686 << std::endl;
688 void draw_segment(const Segment & sg, std::ostream & output)
689 {
690 DRAW_SEGMENT(sg, output);
691 }
692
693 static const double arrow_width_in_mm;
694
695 static const double arrow_lenght_in_mm;
696
697 // Compute and draw the two small segments that form an arrow head.
698 // Uses src/tgt coordinates from COMPUTE_SEGMENT_EEPIC_COORDENATES().
699 // Geometry is controlled by arrow_width_in_mm and arrow_lenght_in_mm.
700# define PUT_ARROW() \
701 const double arrow_width = arrow_width_in_mm/resolution; \
702 const double arrow_lenght = arrow_lenght_in_mm/resolution; \
703 \
704 const double l = sqrt(arrow_width*arrow_width + arrow_lenght*arrow_lenght); \
705 const double tetha = atan2(arrow_width, arrow_lenght); \
706 const double phi = atan2( fabs(tgt_y - src_y), fabs(tgt_x - src_x) ); \
707 \
708 double dx1 = l*cos(phi - tetha); \
709 double dy1 = l*sin(phi - tetha); \
710 \
711 double dx2 = l*sin(M_PI_2 - (phi + tetha)); \
712 double dy2 = l*cos(M_PI_2 - (phi + tetha)); \
713 \
714 if (tgt_x > src_x) \
715 { \
716 dx1 = -dx1; \
717 dx2 = -dx2; \
718 } \
719 \
720 if (tgt_y > src_y) \
721 { \
722 dy1 = -dy1; \
723 dy2 = -dy2; \
724 } \
725 \
726 output << std::endl \
727 << " % Drawing of arrow's edges at (" << tgt_x \
728 << "," << tgt_y << ")" << std::endl \
729 << "\\path(" << tgt_x << "," << tgt_y << ")(" \
730 << tgt_x + dx1 << "," << tgt_y + dy1 << ")" << std::endl \
731 << "\\path(" << tgt_x << "," << tgt_y << ")(" \
732 << tgt_x + dx2 << "," << tgt_y + dy2 << ")" << std::endl << std::endl;
733
734 // Draw segment plus arrow head.
735# define DRAW_ARROW(sg, output) \
736 DRAW_SEGMENT(sg, output); \
737 PUT_ARROW();
738
740 void draw_arrow(const Segment & sg, std::ostream & output)
741 {
742 DRAW_ARROW(sg, output);
743 }
744
745 // Macro to draw a dotted segment.
746# define DRAW_DOTTED_SEGMENT(sg, output) \
747 COMPUTE_SEGMENT_EEPIC_COORDENATES(); \
748 \
749 output << " %% Dotted Segment from " << sg.get_src_point().to_string() \
750 << " to " << sg.get_tgt_point().to_string() << std::endl \
751 << " %% mapped in this plane to (" << src_x << "," << src_y \
752 << ") to (" << tgt_x << "," << tgt_y << ")" << std::endl \
753 << "\\dottedline{" << dotgap << "}(" << src_x \
754 << "," << src_y << ")(" << tgt_x << "," << tgt_y << ")" << std::endl \
755 << std::endl;
756
758 void draw_dotted_segment(const Segment & sg, std::ostream & output)
759 {
761 }
762
763 // Macro to draw a dashed segment.
764# define DRAW_DASH_SEGMENT(sg, output) \
765 COMPUTE_SEGMENT_EEPIC_COORDENATES(); \
766 \
767 output << " %% Dash Segment from " << sg.get_src_point().to_string() \
768 << " to " << sg.get_tgt_point().to_string() << std::endl \
769 << " %% mapped in this plane to (" << src_x << "," << src_y \
770 << ") to (" << tgt_x << "," << tgt_y << ")" << std::endl \
771 << "\\dashline{" << dotgap << "}(" << src_x \
772 << "," << src_y << ")(" << tgt_x << "," << tgt_y << ")" << std::endl \
773 << std::endl;
774
776 void draw_dash_segment(const Segment & sg, std::ostream & output)
777 {
779 }
780
781 // Dotted segment with arrow head (macro).
782# define DRAW_ARROW_DOTTED_SEGMENT(sg, output) \
783 COMPUTE_SEGMENT_EEPIC_COORDENATES(); \
784 \
785 output << " %% Dotted arrow Segment from " << sg.get_src_point().to_string() \
786 << " to " << sg.get_tgt_point().to_string() << std::endl \
787 << " %% mapped in this plane to (" << src_x << "," << src_y \
788 << ") to (" << tgt_x << "," << tgt_y << ")" << std::endl \
789 << "\\dottedline{" << dotgap << "}(" << src_x \
790 << "," << src_y << ")(" << tgt_x << "," << tgt_y << ")" << std::endl \
791 << std::endl; \
792 PUT_ARROW();
793
795 void draw_arrow_dotted_segment(const Segment & sg, std::ostream & output)
796 {
798 }
799
800 // Dashed segment with arrow head (macro).
801# define DRAW_ARROW_DASH_SEGMENT(sg, output) \
802 COMPUTE_SEGMENT_EEPIC_COORDENATES(); \
803 \
804 output << " %% Dash arrow Segment from " << sg.get_src_point().to_string() \
805 << " to " << sg.get_tgt_point().to_string() << std::endl \
806 << " %% mapped in this plane to (" << src_x << "," << src_y \
807 << ") to (" << tgt_x << "," << tgt_y << ")" << std::endl \
808 << "\\dashline{" << dotgap << "}(" << src_x \
809 << "," << src_y << ")(" << tgt_x << "," << tgt_y << ")" << std::endl \
810 << std::endl; \
811 PUT_ARROW();
812
814 void draw_arrow_dash_segment(const Segment & sg, std::ostream & output)
815 {
817 }
818
820 void draw_ellipse(const Ellipse & e, std::ostream & output)
821 {
822 const Point & center = e.get_center();
823
824 const double x = x_geom_number_to_eepic(center.get_x());
825
826 const double y = y_geom_number_to_eepic(center.get_y());
827
828 const double hd = h_geom_number_to_eepic(2 * e.get_hradius());
829
830 const double vd = v_geom_number_to_eepic(2 * e.get_vradius());
831
832 output << " %% Ellipse with center in " << center.to_string()
833 << " with horizontal radius of " << e.get_hradius()
834 << " and vertical radius of " << e.get_vradius() << std::endl
835 << " %% mapped in the plane at center (" << x
836 << "," << y << ") with horizontal radius of " << hd
837 << " and vertical radius of " << vd << std::endl
838 << "\\put(" << x << "," << y << "){\\ellipse{" << hd
839 << "}{" << vd << "}}" << std::endl
840 << std::endl;
841 }
842
843 // Member-function pointer type used to draw a segment.
844 // Lets us implement polygon drawing generically by viewing polygon sides as segments.
846 std::ostream & output);
847
848
849 // Draw a polygon by iterating its sides (segments).
850 // draw_sg_fct is the member-function pointer used to draw each side.
851 // This is generic and is also used for regular polygons.
852 template <class Poly>
853 void draw_polygon(Poly & poly,
854 std::ostream & output,
856 {
857 for (typename Poly::Segment_Iterator it(poly); it.has_curr(); it.next_ne())
858 (this->*draw_sg_fct)(it.get_current_segment(), output);
859 }
860
861 // Draw polygon interior shading using a vertex path.
862 // Faster than the segment-based version, but less flexible.
863 template <class Poly>
864 void draw_closed_polygon(Poly & poly, std::ostream & output)
865 {
866 output << " % Drawing of polygon of " << poly.size()
867 << " sides" << std::endl
868 << "\\shade\\path";
869
870 for (typename Poly::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
871 output << point_string(it.get_current_vertex());
872
873 if (poly.is_closed())
874 output << point_string(poly.get_first_vertex()) << std::endl;
875 }
876
877 // Draw shaded polygon with dotted border.
878 template <class Poly>
879 void draw_dotted_closed_polygon(Poly & poly, std::ostream & output)
880 {
881 output << " % Drawing of dotted line Polygon" << std::endl
882 << "\\shade\\dottedline{" << dotgap << "}";
883
884 for (typename Poly::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
885 output << point_string(it.get_current_vertex());
886
887 if (poly.is_closed())
888 output << point_string(poly.get_first_vertex()) << std::endl;
889 }
890
891 // Draw only polygon vertices as points (does NOT draw sides).
892 template <class Poly>
893 void draw_dots_from_polygon(Poly & poly, std::ostream & output)
894 {
895 for (typename Poly::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
896 {
897 Vertex & vertex = it.get_current_vertex();
898
899 draw_point(vertex, output);
900 }
901 }
902
903 // Draw only the arrow head of segment sg.
904 void draw_arrow_extreme(const Segment & sg, std::ostream & output)
905 { // ¡tal cual!
907 PUT_ARROW();
908 }
909
910 // Draw arrow heads for each polygon side (does NOT draw the sides).
911 template <class Poly>
912 void draw_arrows_in_polygon(Poly & poly, std::ostream & output)
913 {
914 for (typename Poly::Segment_Iterator it(poly); it.has_curr(); it.next_ne())
915 {
916 const Segment & sg = it.get_current_segment();
917
919 }
920 }
921
922 template <class Poly>
923 void draw_closed_polygon_with_arrows(Poly & poly, std::ostream & output)
924 {
927 }
928
929 // Draw a text label for point p (as "(x,y)"), slightly shifted in y.
930 void draw_point_text(const Point & p, std::ostream & output)
931 {
932 const double x = x_geom_number_to_eepic(p.get_x());
933
934 const double y = y_geom_number_to_eepic(p.get_y()) + r;
935
936 const std::string str = p.to_string();
937
938 output << " %% Text Point " << str
939 << " %% mapped in this plane to (" << x << "," << y << ")"
940 << std::endl
941 << "\\put(" << x << "," << y << "){\\texttt{" << str
942 << "}}" << std::endl
943 << std::endl;
944 }
945
946 // Draw text labels for polygon vertices (does NOT draw sides).
947 // TODO: place text inside/outside without crossing edges.
948 template <class Poly>
949 void draw_points_text_in_polygon(Poly & poly, std::ostream & output)
950 {
951 for (typename Poly::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
952 draw_point_text(it.get_current_vertex(), output);
953 }
954
955 // Draw vertex numbers (does NOT draw sides).
956 // TODO: place numbers inside/outside without crossing edges.
957 template <class Poly>
958 void draw_vertex_numbers_in_polygon(Poly & poly, std::ostream & output)
959 {
960 int n = 0;
961
962 for (typename Poly::Vertex_Iterator it(poly);
963 it.has_curr(); it.next_ne(), ++n)
964 {
965 Vertex & vertex = it.get_current_vertex();
966
967 const double x = x_geom_number_to_eepic(vertex.get_x());
968
969 const double y = y_geom_number_to_eepic(vertex.get_y()) - r;
970
971 output << " %% Poligon Vertex Number " << n
972 << " %% mapped in this plane to (" << x << "," << y << ")"
973 << std::endl
974 << "\\put(" << x << "," << y << "){$" << n << "$}" << std::endl
975 << std::endl;
976 }
977 }
978
979 // Draw a spline through polygon vertices.
980 template <class Poly>
981 void draw_spline(Poly & poly, std::ostream & output)
982 {
983 output << " % Drawing spline of " << poly.size()
984 << " points" << std::endl
985 << "\\spline";
986
987 for (typename Poly::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
988 output << point_string(it.get_current_vertex());
989
990 if (poly.is_closed())
991 output << point_string(poly.get_first_vertex()) << std::endl;
992 }
993
994 // Draw a piecewise-linear curve through polygon vertices.
995 template <class Poly>
996 void draw_dash_spline(Poly & poly, std::ostream & output)
997 {
998 output << " % Drawing dash curve of " << poly.size()
999 << " points" << std::endl
1000 << "\\closecurve";
1001
1002 for (typename Poly::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
1003 output << point_string(it.get_current_vertex());
1004
1005 if (poly.is_closed())
1006 output << point_string(poly.get_first_vertex()) << std::endl;
1007 }
1008
1009 // Draw spline plus an arrow head at the last segment.
1010 template <class Poly>
1011 void draw_spline_arrow(Poly & poly, std::ostream & output)
1012 {
1013 draw_spline(poly, output); // draw curve first
1014
1015 // Now draw the arrow head using the slope of the last segment.
1016
1017 draw_arrow_extreme(poly.get_last_segment(), output);
1018 }
1019
1020 // Draw dashed curve plus an arrow head at the last segment.
1021 template <class Poly>
1022 void draw_dash_spline_arrow(Poly & poly, std::ostream & output)
1023 {
1024 draw_dash_spline(poly, output); // draw curve first
1025
1026 // Now draw the arrow head using the slope of the last segment.
1027
1028 draw_arrow_extreme(poly.get_last_segment(), output);
1029 }
1030
1031 void draw_text(const Text & t, std::ostream & output,
1032 const double & hfactor, const double & vfactor)
1033 {
1034 const Point & p = t.get_point();
1035
1037
1038 const double x =
1040
1041 const double y = (y_geom_number_to_eepic(p.get_y()) -
1043
1044 output << "% std::string at " << p.to_string() << std::endl
1045 << "% mapped to the plane at (" << x << "," << y << ")" << std::endl
1046 << "\\put(" << x << "," << y << "){\\texttt{"
1047 << (tiny_keys ? "\\tiny " : "") << t.get_str()
1048 << "}}" << std::endl
1049 << std::endl;
1050 }
1051};
1052
1053
1063# define DEFINE_EEPIC_COPY_CTOR(Type) \
1064 Eepic_##Type(const Type & o) : Eepic_Geom_Object(new Type(o), true) { }
1065
1066
1068# define DEFINE_EEPIC_COMMON_METHODS(Type) \
1069 friend void put_in_plane(Eepic_Plane & plane, const Type & geom_obj); \
1070 \
1071 ~Eepic_##Type() { } \
1072 \
1073 Point highest_point() const override \
1074 { \
1075 return static_cast<const Type*>(geom_object_ptr)->highest_point(); \
1076 } \
1077 \
1078 Point lowest_point() const override \
1079 { \
1080 return static_cast<const Type*>(geom_object_ptr)->lowest_point(); \
1081 } \
1082 \
1083 Point leftmost_point() const override \
1084 { \
1085 return static_cast<const Type*>(geom_object_ptr)->leftmost_point(); \
1086 } \
1087 \
1088 Point rightmost_point() const override \
1089 { \
1090 return static_cast<const Type*>(geom_object_ptr)->rightmost_point(); \
1091 } \
1092 \
1093 Eepic_Geom_Object * clone() const override \
1094 { \
1095 return new Eepic_##Type(static_cast<const Type&>(*geom_object_ptr)); \
1096 } \
1097 \
1098 void draw(Eepic_Plane * plane, std::ostream & output) const override;
1099
1100
1102# define DEFINE_EEPIC_COMMON_WITH_COPY_CTOR(Type) \
1103 DEFINE_EEPIC_COPY_CTOR(Type) \
1104 DEFINE_EEPIC_COMMON_METHODS(Type)
1105
1106
1108# define DEFINE_EEPIC_COMMON_WITHOUT_COPY_CTOR(Type) \
1109 DEFINE_EEPIC_COMMON_METHODS(Type) \
1110 Eepic_##Type(const Type &);
1111
1112
1114# define DEFINE_PUT_IN_PLANE(Type) \
1115 extern void put_in_plane(Eepic_Plane & plane, const Type & geom_obj)
1116
1117
1118# define IMPL_PUT_IN_PLANE(Type) \
1119 void put_in_plane(Eepic_Plane & plane, const Type & geom_obj) \
1120 { \
1121 Eepic_##Type eepic_obj(geom_obj); \
1122 \
1123 plane.put(eepic_obj); \
1124 }
1125
1132// Typical definition of an Eepic_Type wrapper class.
1133// Only Eepic_Plane::put(const Eepic_Type&) needs to be implemented.
1134# define DEFINE_EEPIC_CLASS(Type) \
1135 class Eepic_##Type : public Eepic_Geom_Object \
1136 { \
1137 DEFINE_EEPIC_COMMON_WITH_COPY_CTOR(Type) \
1138 }; \
1139 \
1140 DEFINE_PUT_IN_PLANE(Type)
1141
1142
1143// Typical definition of an Eepic_Type wrapper class with extra members.
1144// This implies defining the copy-constructor separately to initialize
1145// additional attributes.
1146# define DEFINE_EEPIC_CLASS_AND_MEMBERS(Type, ...) \
1147 class Eepic_##Type : public Eepic_Geom_Object \
1148 { \
1149 __VA_ARGS__ ; \
1150 DEFINE_EEPIC_COMMON_WITHOUT_COPY_CTOR(Type) \
1151 }; \
1152 \
1153 DEFINE_PUT_IN_PLANE(Type)
1154
1155
1161
1162
1164
1165
1170# define DEFINE_CLASS_DERIVATED_FROM_SEGMENT(Name) \
1171 struct Name : public Segment \
1172 { \
1173 Name() { } \
1174 \
1175 Name(const Segment & s) : Segment(s) \
1176 { \
1177 \
1178 } \
1179 Name(const Point & __src, const Point & __tgt) \
1180 : Segment(__src, __tgt) \
1181 { \
1182 \
1183 } \
1184 \
1185 Name(const Point & __src, \
1186 const Geom_Number & m, \
1187 const Geom_Number & d) \
1188 : Segment(__src, m, d) \
1189 { \
1190 \
1191 } \
1192 };
1193
1194// Define a Segment-derived type named Name. Purpose: provide a distinct geometric
1195// type name (different from Segment) so it can have different EEPIC drawing behavior.
1196# define DEFINE_EEPIC_SEGMENT_CLASS(Name) \
1197 DEFINE_CLASS_DERIVATED_FROM_SEGMENT(Name) \
1198 DEFINE_EEPIC_CLASS(Name);
1199
1200
1201// Same as DEFINE_EEPIC_SEGMENT_CLASS, but allows extra members to be injected
1202// via the macro parameter list.
1203# define DEFINE_EEPIC_SEGMENT_CLASS_AND_MEMBERS(Name, ...) \
1204 DEFINE_CLASS_DERIVATED_FROM_SEGMENT(Name) \
1205 DEFINE_EEPIC_CLASS_AND_MEMBERS(Name, __VA_ARGS__);
1206
1207
1215
1217
1219
1221
1223
1225
1227
1229
1231
1232
1235
1236
1239
1240
1241// Define an Ellipse-derived type to allow different drawing behaviors.
1242# define DEFINE_CLASS_DERIVATED_FROM_ELLIPSE(Name) \
1243 struct Name : public Ellipse \
1244 { \
1245 Name() { } \
1246 \
1247 Name(const Ellipse & p) : Ellipse(p) \
1248 { \
1249 \
1250 } \
1251 \
1252 Name(const Point & center, \
1253 const Geom_Number & hr, \
1254 const Geom_Number & vr) \
1255 : Ellipse(center, hr, vr) \
1256 { \
1257 \
1258 } \
1259 };
1260
1261
1263
1265
1267
1269
1270
1273# define DEFINE_CLASS_DERIVATED_FROM_TEXT(Name) \
1274 struct Name : public Text \
1275 { \
1276 Name() { } \
1277 \
1278 Name(const Text & t) : Text(t) \
1279 { \
1280 \
1281 } \
1282 \
1283 Name(const Point & p, const std::string & str) \
1284 : Text(p, str) \
1285 { \
1286 \
1287 } \
1288 };
1289
1290
1292
1294
1296
1298
1300
1302
1304
1305
1312// The simplest polygon wrapper (default drawing behavior).
1314
1315
1316// Define a Polygon-derived type to allow different drawing behaviors.
1317# define DEFINE_CLASS_DERIVATED_FROM_POLYGON(Name) \
1318 struct Name : public Polygon \
1319 { \
1320 Name() { } \
1321 \
1322 Name(const Polygon & p) : Polygon(p) \
1323 { \
1324 \
1325 } \
1326 };
1327
1328
1329# define DEFINE_EEPIC_POLYGON(Name) \
1330 DEFINE_CLASS_DERIVATED_FROM_POLYGON(Name); \
1331 DEFINE_EEPIC_CLASS(Name);
1332
1333
1334// Polygon variants.
1335
1336// With point circles at vertices.
1338
1339// With point circles at vertices and arrow heads on sides.
1341
1342// Dotted sides.
1344
1345// Dashed sides.
1347
1348// Dotted sides with point circles at vertices.
1350
1351// Dashed sides with point circles at vertices.
1353
1354// Dashed sides with an arrow head on the last segment.
1356
1357// Shaded interior (gray).
1359
1360// Shaded interior with point circles at vertices.
1362
1363// Shaded interior, sides drawn as arrows.
1365
1366// Shaded interior with vertex coordinate labels.
1368
1369// Shaded interior with vertex numbers.
1371
1372// Spline curve built from polygon vertices.
1374
1375// Piecewise-linear curve built from polygon vertices.
1377
1378// Spline curve with arrow head at the end.
1380
1381// Piecewise-linear curve with arrow head at the end.
1383
1384// With point circles at vertices.
1386
1387// With point circles at vertices.
1389
1390// Dotted sides.
1392
1393// Dashed sides.
1395
1396// Dotted sides with point circles at vertices.
1398
1399// Dashed sides with point circles at vertices.
1401
1402// Dashed sides with arrow heads.
1404
1405// Shaded interior (gray).
1407
1408// Shaded interior with point circles at vertices.
1410
1411// Shaded interior, sides drawn as arrows.
1413
1414// Shaded interior with vertex coordinate text.
1416
1417// Shaded interior with vertex numbers.
1419
1420// Thick spline curve built from polygon vertices.
1422
1423// Thick piecewise-linear curve built from polygon vertices.
1425
1426// Thick spline curve with arrow head.
1428
1429// Thick piecewise-linear curve with arrow head.
1431
1444// Define a new class derived from Regular_Polygon to allow different drawing behaviors.
1445// A new type is needed because the constructor differs.
1446# define DEFINE_CLASS_DERIVATED_FROM_REGULAR_POLYGON(Name) \
1447 struct Name : public Regular_Polygon \
1448 { \
1449 Name() { } \
1450 \
1451 Name(const Regular_Polygon & p) : Regular_Polygon(p) \
1452 { \
1453 \
1454 } \
1455 \
1456 Name(const Point & c, \
1457 const double & side_sz, \
1458 const size_t & n, \
1459 const double & ang = 0) \
1460 : Regular_Polygon(c, side_sz, n, ang) \
1461 { \
1462 \
1463 } \
1464 };
1465
1466
1467# define DEFINE_EEPIC_REGULAR_POLYGON(Name) \
1468 DEFINE_CLASS_DERIVATED_FROM_REGULAR_POLYGON(Name); \
1469 DEFINE_EEPIC_CLASS(Name);
1470
1471
1473
1474// Regular polygon variants.
1476
1478
1480
1482
1484
1486
1488
1490
1492
1494
1495
1496# endif // EEPICGEOM_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_logic_error()
Throws std::logic_error unconditionally.
Definition ah-errors.H:341
long double vd
Definition btreepic.C:152
long double hd
Definition btreepic.C:151
Iterator dynamic list.
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
T & get_curr() const
Return the current item; throw overflow_error if there is no current item.
void next()
Move the iterator one item forward.
Dynamic doubly linked list with O(1) size and bidirectional access.
const size_t & size() const noexcept
Return the number of elements (constant time)
T & append(const T &item)
Append a copied item at the end of the list.
T remove_first_ne() noexcept
Remove the first item of the list; return a copy of removed item.
An axis-aligned ellipse.
Definition point.H:2006
const Geom_Number & get_vradius() const
Gets the vertical radius.
Definition point.H:2080
const Point & get_center() const
Gets the center point of the ellipse.
Definition point.H:2076
const Geom_Number & get_hradius() const
Gets the horizontal radius.
Definition point.H:2078
Represents a point with rectangular coordinates in a 2D plane.
Definition point.H:229
const Geom_Number & get_x() const noexcept
Gets the x-coordinate value.
Definition point.H:457
std::string to_string() const
Returns a string representation of the point as "(x,y)".
Definition point.H:651
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Definition point.H:466
A general (irregular) 2D polygon defined by a sequence of vertices.
Definition polygon.H:246
A regular polygon defined by center, side length, and vertex count.
Definition polygon.H:1132
Represents a line segment between two points.
Definition point.H:827
Represents a text string positioned at a 2D point.
Definition point.H:2739
static constexpr double font_height_in_points
Definition point.H:2749
static constexpr double font_width_in_points
Definition point.H:2747
const std::string & get_str() const
Gets the text string.
Definition point.H:2775
const Point & get_point() const
Gets the position point of the text.
Definition point.H:2769
const size_t & len() const
Gets the estimated length of the text.
Definition point.H:2766
A non-degenerate triangle defined by three points.
Definition point.H:1478
A vertex in a polygon's doubly linked vertex list.
Definition polygon.H:119
Abstract base class for EEPIC-drawable geometric objects.
Definition eepicgeom.H:108
virtual Eepic_Geom_Object * clone() const =0
Create a polymorphic copy of this object.
const Geom_Object *const geom_object_ptr
Pointer to the wrapped geometric object.
Definition eepicgeom.H:119
virtual ~Eepic_Geom_Object()
Virtual destructor.
Definition eepicgeom.H:145
Eepic_Geom_Object(Geom_Object *ptr, const bool &__to_delete=false)
Construct an EEPIC wrapper for a geometric object.
Definition eepicgeom.H:135
Eepic_Geom_Object(const Eepic_Geom_Object &)
virtual void draw(Eepic_Plane *plane, std::ostream &output) const
Generate EEPIC code for this object.
Definition eepicgeom.H:162
virtual Point lowest_point() const =0
Get the lowest point (minimum y-coordinate) of this object.
virtual Point highest_point() const =0
Get the highest point (maximum y-coordinate) of this object.
bool to_delete
Flag indicating ownership of geom_object_ptr.
Definition eepicgeom.H:126
virtual Point rightmost_point() const =0
Get the rightmost point (maximum x-coordinate) of this object.
virtual Point leftmost_point() const =0
Get the leftmost point (minimum x-coordinate) of this object.
2D canvas for generating EEPIC/LaTeX picture environments.
Definition eepicgeom.H:250
static const double dotgap
Gap between dots in dotted lines.
Definition eepicgeom.H:299
void draw_dotted_segment(const Segment &sg, std::ostream &output)
Emit EEPIC code to draw dotted segment sg.
Definition eepicgeom.H:758
const double & get_height() const
Picture height (in EEPIC units).
Definition eepicgeom.H:535
Geom_Number geom_height
Height from lowest to highest point.
Definition eepicgeom.H:263
std::string fill_type
Fill type for shapes (e.g., "black")
Definition eepicgeom.H:291
void draw_arrow_dash_segment(const Segment &sg, std::ostream &output)
Emit EEPIC code to draw dashed segment sg with arrow head.
Definition eepicgeom.H:814
Point __lowest
Point with minimum y-coordinate.
Definition eepicgeom.H:279
Point __leftmost
Point with minimum x-coordinate.
Definition eepicgeom.H:276
Eepic_Plane(const double &__wide, const double &__height, const double &__xoffset=0.0, const double &__yoffset=0.0)
Construct a plane with a fixed picture frame.
Definition eepicgeom.H:553
void zoom(const double &factor)
Scale the EEPIC plane in real points (zoom in/out).
Definition eepicgeom.H:397
void set_fill_type(const std::string &ftype)
Set the fill type used by LaTeX eepic (e.g., "black").
Definition eepicgeom.H:625
void draw_point_text(const Point &p, std::ostream &output)
Definition eepicgeom.H:930
double real_wide
Actual width after scaling.
Definition eepicgeom.H:256
void draw_segment(const Segment &sg, std::ostream &output)
Emit EEPIC code to draw segment sg.
Definition eepicgeom.H:688
double get_shade_thickness() const
Return the current shading thickness.
Definition eepicgeom.H:637
Geom_Number geom_y_min
Minimum y value in geometric coordinates.
Definition eepicgeom.H:268
double y_geom_number_to_eepic(const Geom_Number &y) const
Convert a geometric y coordinate into plane y coordinate.
Definition eepicgeom.H:356
void compute_geom_plane(const bool &squarize)
Compute extreme coordinates and derive width/height of all objects.
Definition eepicgeom.H:408
DynDlist< Eepic_Geom_Object * > list
List of geometric objects.
Definition eepicgeom.H:265
double x_min
Minimum x value in plane coordinates.
Definition eepicgeom.H:272
const double & get_yoffset() const
Y offset of the LaTeX picture environment.
Definition eepicgeom.H:538
double r
Actual radius in real points for drawing a point.
Definition eepicgeom.H:286
void draw_dash_spline(Poly &poly, std::ostream &output)
Definition eepicgeom.H:996
void set_resolution(const double &res)
Set the output resolution in millimeters (unitlength = res mm).
Definition eepicgeom.H:616
double y_min
Minimum y value in plane coordinates.
Definition eepicgeom.H:273
double resolution
Resolution in millimeters (default: 0.05mm)
Definition eepicgeom.H:289
double height
Height in resolution points.
Definition eepicgeom.H:253
Point __rightmost
Point with maximum x-coordinate.
Definition eepicgeom.H:277
bool with_cartesian_axis
Flag to draw Cartesian axes.
Definition eepicgeom.H:281
static const double arrow_lenght_in_mm
Definition eepicgeom.H:695
Point __highest
Point with maximum y-coordinate.
Definition eepicgeom.H:278
static const double normal_thickness
Default line thickness.
Definition eepicgeom.H:294
const double & get_wide() const
Plane accessors.
Definition eepicgeom.H:532
Geom_Number geom_wide
Width from leftmost to rightmost point.
Definition eepicgeom.H:262
double wide
Width in resolution points.
Definition eepicgeom.H:252
const double & get_xoffset() const
X offset of the LaTeX picture environment.
Definition eepicgeom.H:541
double ypic(const double &y) const
Normalize to y-axis origin.
Definition eepicgeom.H:331
static const double default_r
Default radius for drawing points (also used for text height)
Definition eepicgeom.H:284
void compute_extreme_points()
Linear scan over all objects to compute extreme points.
Definition eepicgeom.H:364
double get_dotgap() const
Return the dot gap used for dotted/dashed lines.
Definition eepicgeom.H:640
void draw_ellipse(const Ellipse &e, std::ostream &output)
Emit EEPIC code to draw ellipse e.
Definition eepicgeom.H:820
void draw_arrow_extreme(const Segment &sg, std::ostream &output)
Definition eepicgeom.H:904
static const double default_shade_thickness
Default shading thickness.
Definition eepicgeom.H:295
double xoffset
Additional horizontal margin.
Definition eepicgeom.H:259
double h_geom_number_to_eepic(const Geom_Number &x) const
Convert a geometric x proportion into plane units using wide.
Definition eepicgeom.H:338
const double & get_resolution() const
Return the current output resolution in millimeters.
Definition eepicgeom.H:622
void draw_text(const Text &t, std::ostream &output, const double &hfactor, const double &vfactor)
Definition eepicgeom.H:1031
void draw_dots_from_polygon(Poly &poly, std::ostream &output)
Definition eepicgeom.H:893
void set_shade_thickness(const double &__thickness)
Set the thickness used for shaded primitives.
Definition eepicgeom.H:631
void(Eepic_Plane::* Draw_Segment_Fct)(const Segment &poly, std::ostream &output)
Definition eepicgeom.H:845
void draw_points_text_in_polygon(Poly &poly, std::ostream &output)
Definition eepicgeom.H:949
void draw_dash_spline_arrow(Poly &poly, std::ostream &output)
Definition eepicgeom.H:1022
double real_height
Actual height after scaling.
Definition eepicgeom.H:257
void draw_closed_polygon(Poly &poly, std::ostream &output)
Definition eepicgeom.H:864
void draw_polygon(Poly &poly, std::ostream &output, Draw_Segment_Fct draw_sg_fct)
Definition eepicgeom.H:853
void draw_closed_polygon_with_arrows(Poly &poly, std::ostream &output)
Definition eepicgeom.H:923
double x_geom_number_to_eepic(const Geom_Number &x) const
Convert a geometric x coordinate into plane x coordinate.
Definition eepicgeom.H:350
const Point & highest() const
Definition eepicgeom.H:462
std::string shade_type
Shading type for segments.
Definition eepicgeom.H:292
void put_cartesian_axis()
Enable drawing Cartesian axes when calling draw().
Definition eepicgeom.H:573
void draw_arrow(const Segment &sg, std::ostream &output)
Emit EEPIC code to draw segment sg with an arrow head.
Definition eepicgeom.H:740
void draw_vertex_numbers_in_polygon(Poly &poly, std::ostream &output)
Definition eepicgeom.H:958
double shade_thickness
Current shading thickness.
Definition eepicgeom.H:297
double yoffset
Additional vertical margin.
Definition eepicgeom.H:260
const double & get_r() const
Radius used to draw points (also used as text baseline offset).
Definition eepicgeom.H:544
void draw_arrows_in_polygon(Poly &poly, std::ostream &output)
Definition eepicgeom.H:912
double v_geom_number_to_eepic(const Geom_Number &y) const
Convert a geometric y proportion into plane units using height.
Definition eepicgeom.H:344
Geom_Number geom_x_min
Minimum x value in geometric coordinates.
Definition eepicgeom.H:267
static const double arrow_width_in_mm
Definition eepicgeom.H:693
void put(const Eepic_Geom_Object &__eepic_geom_obj)
Design note: why Eepic_Plane stores Eepic_Geom_Object wrappers.
Definition eepicgeom.H:608
const Point & lowest() const
Definition eepicgeom.H:464
const Point & rightmost() const
Definition eepicgeom.H:460
void draw_spline(Poly &poly, std::ostream &output)
Definition eepicgeom.H:981
void draw_point(const Point &p, std::ostream &output)
EEPIC "primitive drawing" methods.
Definition eepicgeom.H:653
double geom_number_to_plane(const Geom_Number &p, const Geom_Number &geom_max, const double &max) const
Rescales a coordinate value p from a geometric scale geom_max into the plane scale max.
Definition eepicgeom.H:306
void draw_dotted_closed_polygon(Poly &poly, std::ostream &output)
Definition eepicgeom.H:879
void draw(std::ostream &output, const bool &squarize=true)
Emits a complete LaTeX picture environment containing the geometric objects.
Definition eepicgeom.H:484
~Eepic_Plane()
Destructor: deletes all stored Eepic_Geom_Object clones.
Definition eepicgeom.H:566
void draw_arrow_dotted_segment(const Segment &sg, std::ostream &output)
Emit EEPIC code to draw dotted segment sg with arrow head.
Definition eepicgeom.H:795
void draw_dash_segment(const Segment &sg, std::ostream &output)
Emit EEPIC code to draw dashed segment sg.
Definition eepicgeom.H:776
void draw_spline_arrow(Poly &poly, std::ostream &output)
Definition eepicgeom.H:1011
void draw_cartesian_axis(std::ostream &output)
Draws the Cartesian axes on the plane, if enabled.
Definition eepicgeom.C:232
const Point & leftmost() const
Definition eepicgeom.H:458
double xpic(const double &x) const
Points must be normalized to the plane size (in picture coordinates).
Definition eepicgeom.H:325
std::string point_string(const Point &p)
Given point p, returns "(x,y)" in normalized plane coordinates.
Definition eepicgeom.H:467
#define DRAW_DOTTED_SEGMENT(sg, output)
Definition eepicgeom.H:746
#define DEFINE_EEPIC_CLASS(Type)
Fundamental macro to declare a class derived from Eepic_Geom_Object.
Definition eepicgeom.H:1134
#define DEFINE_EEPIC_REGULAR_POLYGON(Name)
Definition eepicgeom.H:1467
#define DRAW_ARROW(sg, output)
Definition eepicgeom.H:735
bool tiny_keys
Global flag to enable tiny font size for keys/labels.
#define DRAW_ARROW_DOTTED_SEGMENT(sg, output)
Definition eepicgeom.H:782
#define DEFINE_EEPIC_SEGMENT_CLASS(Name)
Definition eepicgeom.H:1196
#define DEFINE_CLASS_DERIVATED_FROM_ELLIPSE(Name)
Definition eepicgeom.H:1242
#define DRAW_DASH_SEGMENT(sg, output)
Definition eepicgeom.H:764
#define PUT_ARROW()
Definition eepicgeom.H:700
#define COMPUTE_SEGMENT_EEPIC_COORDENATES()
Definition eepicgeom.H:668
#define DRAW_ARROW_DASH_SEGMENT(sg, output)
Definition eepicgeom.H:801
#define DEFINE_EEPIC_POLYGON(Name)
Definition eepicgeom.H:1329
#define DEFINE_CLASS_DERIVATED_FROM_TEXT(Name)
Text wrappers.
Definition eepicgeom.H:1273
#define DRAW_SEGMENT(sg, output)
Definition eepicgeom.H:678
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4110
bool squarize
Definition graphpic.C:259
static mpfr_t y
Definition mpfr_mul_d.c:3
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
double geom_number_to_double(const Geom_Number &n)
Converts a Geom_Number to its double precision representation.
Definition point.H:122
mpq_class Geom_Number
Numeric type used by the geometry module.
Definition point.H:115
STL namespace.
2D point and geometric utilities.
2D polygon representation and geometric operations.
Base class for all geometric objects.
Definition point.H:214
Segment-drawing variants (types).
Definition eepicgeom.H:1214
Dynamic doubly linked list implementation.
Comprehensive sorting algorithms and search utilities for Aleph-w.
ofstream output
Definition writeHeap.C:215