43# include <unordered_set>
44# include <type_traits>
165 const std::string & fill_color)
278 std::ostringstream
ss;
279 ss << std::fixed << std::setprecision(3) << v;
281 std::string
out =
ss.str();
425 box.initialized =
true;
491 if (poly.
size() == 0)
497 const Point p = it.get_current_vertex().to_point();
505 if (poly.
size() == 0)
509 for (
size_t i = 0; i < poly.
size(); ++i)
516 return make_box(
r.get_xmin(),
r.get_xmax(),
r.get_ymin(),
r.get_ymax());
526 std::min(
y0,
y1), std::max(
y0,
y1));
551 for (
const auto & p :
pl.vertices)
562 [](
const auto & val) {
return bbox_of(val); }, entry.object));
580 case '\\':
escaped +=
"\\textbackslash{}";
633 const double s = std::min(map.
sx, map.
sy);
637 const double used_w = xr * s;
638 const double used_h = yr * s;
674 static std::pair<double, double>
694 template <
typename Out>
703 output <<
" (" << x <<
"," <<
y <<
") "
707 template <
typename Out>
709 const std::vector<Point> & vertices,
714 if (vertices.empty())
717 if (vertices.size() == 1)
728 for (
size_t i = 0; i < vertices.size(); ++i)
732 output <<
"(" << x <<
"," <<
y <<
")";
734 output <<
" -- (" << x <<
"," <<
y <<
")";
739 output <<
";" << std::endl;
742 template <
typename Out>
749 template <
typename Out>
756 template <
typename Out>
764 if (
rx == 0.0
or ry == 0.0)
773 output <<
" (" << cx <<
"," << cy <<
") "
774 <<
"ellipse [x radius=" <<
rx <<
", y radius=" <<
ry <<
"];"
778 template <
typename Out>
784 constexpr double two_pi = 2.0 * 3.14159265358979323846;
793 const double t =
two_pi *
static_cast<double>(i) /
810 output <<
"(" << x <<
"," <<
y <<
")";
812 output <<
" -- (" << x <<
"," <<
y <<
")";
814 output <<
" -- cycle;" << std::endl;
817 template <
typename Out>
823 output <<
" \\node[inner sep=1pt";
826 output <<
"] at (" << x <<
"," <<
y <<
") {";
834 template <
typename Out>
838 std::vector<Point> vertices;
839 vertices.reserve(poly.
size());
841 vertices.push_back(it.get_current_vertex().to_point());
846 template <
typename Out>
851 std::vector<Point> vertices;
852 vertices.reserve(poly.
size());
853 for (
size_t i = 0; i < poly.
size(); ++i)
859 template <
typename Out>
863 std::vector<Point> vertices;
865 const std::array<Point, 4> corners =
r.corners();
866 for (
const Point & p: corners)
867 vertices.push_back(p);
871 template <
typename Out>
919 for (
size_t i = 0; i <
clipped.size(); ++i)
920 for (
size_t j = i + 1; j <
clipped.size(); ++j)
934 template <
typename Out>
946 output <<
" (" <<
x0 <<
"," <<
y0 <<
") .. controls ("
947 << x1 <<
"," <<
y1 <<
") .. (" << x2 <<
"," << y2 <<
");"
951 template <
typename Out>
964 output <<
" (" <<
x0 <<
"," <<
y0 <<
") .. controls ("
965 << x1 <<
"," <<
y1 <<
") and (" << x2 <<
"," << y2
966 <<
") .. (" <<
x3 <<
"," <<
y3 <<
");"
981 template <
typename Out>
999 const int nx0 =
static_cast<int>(std::ceil(xmin / sx));
1000 const int nx1 =
static_cast<int>(std::floor(xmax / sx));
1001 const int ny0 =
static_cast<int>(std::ceil(ymin / sy));
1002 const int ny1 =
static_cast<int>(std::floor(ymax / sy));
1004 for (
int i =
nx0; i <=
nx1; ++i)
1015 for (
int i =
ny0; i <=
ny1; ++i)
1017 const auto y =
Geom_Number(
static_cast<double>(i) * sy);
1036 for (
int i =
nx0; i <=
nx1; ++i)
1038 const auto x =
Geom_Number(
static_cast<double>(i) * sx);
1049 for (
int i =
ny0; i <=
ny1; ++i)
1051 const auto y =
Geom_Number(
static_cast<double>(i) * sy);
1068 std::unordered_set<std::string>
seen;
1069 for (
const auto & [label, style]: entries)
1074 std::string
color =
obj.style.draw_color;
1095 template <
typename Out>
1099 if (entries.empty())
1102 for (
size_t i = 0; i < entries.size(); ++i)
1112 output <<
" (" <<
x0 <<
"," <<
y <<
") -- (" << x1 <<
"," <<
y <<
");"
1115 output <<
" \\node[anchor=west] at (" << (x1 + 1.2) <<
"," <<
y
1116 <<
") {" <<
escape_latex(entries[i].label) <<
"};" << std::endl;
1120 template <
typename Out>
1131 output <<
" \\tikzset{" << name <<
"/.style={" <<
opts <<
"}}" << std::endl;
1135 template <
typename Out>
1165 template <
typename Out>
1169 std::visit([&]<
typename T0>(
const T0 & value)
1171 using T = std::decay_t<T0>;
1172 if constexpr (std::is_same_v<T, Point>)
1174 else if constexpr (std::is_same_v<T, Polar_Point>)
1176 else if constexpr (std::is_same_v<T, Segment>)
1178 else if constexpr (std::is_same_v<T, Triangle>)
1180 else if constexpr (std::is_same_v<T, Ellipse>)
1182 else if constexpr (std::is_same_v<T, RotatedEllipse>)
1184 else if constexpr (std::is_same_v<T, Text>)
1186 else if constexpr (std::is_same_v<T, Polygon>)
1188 else if constexpr (std::is_same_v<T, Regular_Polygon>)
1190 else if constexpr (std::is_same_v<T, Rectangle>)
1192 else if constexpr (std::is_same_v<T, LineEq>)
1194 else if constexpr (std::is_same_v<T, Tikz_Quadratic_Bezier>)
1196 else if constexpr (std::is_same_v<T, Tikz_Cubic_Bezier>)
1198 else if constexpr (std::is_same_v<T, Tikz_Polyline>)
1216 const double & xoffset = 0.0,
const double & yoffset = 0.0)
1220 <<
"Tikz_Plane width and height must be greater than zero";
1304 const double step_y = 1.0,
1308 <<
"Grid steps must be greater than zero";
1388 output << std::fixed << std::setprecision(6);
1389 output <<
"% Requires: \\usepackage{tikz}" << std::endl;
1392 output <<
"\\pgfdeclarelayer{background}" << std::endl
1393 <<
"\\pgfdeclarelayer{foreground}" << std::endl
1394 <<
"\\pgfdeclarelayer{overlay}" << std::endl;
1396 output <<
"\\begin{tikzpicture}[x=1mm,y=1mm]" << std::endl;
1398 output <<
" \\pgfsetlayers{background,main,foreground,overlay}" << std::endl;
1400 output <<
" % " <<
objects_.size() <<
" geometric objects in plane" << std::endl;
1411 std::vector<size_t> order(
objects_.size());
1412 for (
size_t i = 0; i <
objects_.size(); ++i)
1415 std::stable_sort(order.begin(), order.end(),
1416 [&](
const size_t lhs,
const size_t rhs)
1418 if (objects_[lhs].layer != objects_[rhs].layer)
1419 return objects_[lhs].layer < objects_[rhs].layer;
1420 return objects_[lhs].order < objects_[rhs].order;
1425 const char *current =
nullptr;
1426 for (
const size_t idx: order)
1429 if (current ==
nullptr or std::string(current) != target)
1431 if (current !=
nullptr)
1432 output <<
" \\end{pgfonlayer}" << std::endl;
1433 output <<
" \\begin{pgfonlayer}{" << target <<
"}" << std::endl;
1438 if (current !=
nullptr)
1439 output <<
" \\end{pgfonlayer}" << std::endl;
1442 for (
const size_t idx: order)
1447 output <<
" \\end{scope}" << std::endl;
1448 output <<
"\\end{tikzpicture}" << std::endl;
1453 template <
typename Geom,
1454 typename = std::enable_if_t<
1455 std::is_constructible_v<Tikz_Plane::Object, std::decay_t<Geom>>>>
1462 template <
typename Geom,
1463 typename = std::enable_if_t<
1464 std::is_constructible_v<Tikz_Plane::Object, std::decay_t<Geom>>>>
1483 Tikz_Polyline curve;
1495 curve.vertices.emplace_back(x,
y);
1513 Tikz_Polyline curve;
1529 curve.vertices.emplace_back(x,
y);
1544 put_in_plane(plane, Tikz_Quadratic_Bezier{p0, p1, p2}, style, layer);
1557 put_in_plane(plane, Tikz_Cubic_Bezier{p0, p1, p2, p3}, style, layer);
1563 const Point & point,
1564 const std::string & label,
1565 const std::string &
placement =
"above",
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
bool has_curr() const noexcept
Return true if the iterator has current item.
const Geom_Number & get_vradius() const
Gets the vertical radius.
const Point & get_center() const
Gets the center point of the ellipse.
Point highest_point() const
Gets the highest point on the ellipse boundary.
Point rightmost_point() const
Gets the rightmost point on the ellipse boundary.
const Geom_Number & get_hradius() const
Gets the horizontal radius.
Point leftmost_point() const
Gets the leftmost point on the ellipse boundary.
Point lowest_point() const
Gets the lowest point on the ellipse boundary.
Represents a point with rectangular coordinates in a 2D plane.
const Geom_Number & get_x() const noexcept
Gets the x-coordinate value.
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Polar representation of a 2D point.
A general (irregular) 2D polygon defined by a sequence of vertices.
const bool & is_closed() const
Check if the polygon is closed.
const size_t & size() const
Get the number of vertices.
An axis-aligned rectangle.
A regular polygon defined by center, side length, and vertex count.
Point get_vertex(const size_t &i) const
Get the i-th vertex of the polygon.
const size_t & size() const
Get the number of vertices.
An ellipse with arbitrary rotation.
const Geom_Number & get_b() const
Gets the semi-axis 'b' (local y-axis radius).
const Geom_Number & get_sin() const
Gets the sine of the rotation angle.
const Geom_Number & get_a() const
Gets the semi-axis 'a' (local x-axis radius).
const Geom_Number & get_cos() const
Gets the cosine of the rotation angle.
const Point & get_center() const
Gets the center point.
Represents a line segment between two points.
const Point & rightmost_point() const noexcept
Gets the endpoint with the largest x-coordinate.
const Point & highest_point() const noexcept
Gets the endpoint with the largest y-coordinate.
const Point & lowest_point() const noexcept
Gets the endpoint with the smallest y-coordinate.
const Point & leftmost_point() const noexcept
Gets the endpoint with the smallest x-coordinate.
const Point & get_tgt_point() const noexcept
Gets the target point of the segment.
const Point & get_src_point() const noexcept
Gets the source point of the segment.
Represents a text string positioned at a 2D point.
Point lowest_point() const
Gets the lowest point (the anchor point).
Point highest_point() const
Gets the highest point (the anchor point).
Point rightmost_point() const
Gets the rightmost point (the anchor point).
const std::string & get_str() const
Gets the text string.
const Point & get_point() const
Gets the position point of the text.
Point leftmost_point() const
Gets the leftmost point (the anchor point).
2D TikZ canvas storing geometry objects and emitting LaTeX output.
static Geom_Number rotated_x_extent(const RotatedEllipse &e)
void set_axis_style(const Tikz_Style &style)
Configure the style used to draw Cartesian axes.
void draw_object(const Styled_Object &entry, Out &output, const Geom_Box &box, const Mapping &map) const
static std::pair< double, double > map_point(const Point &p, const Geom_Box &box, const Mapping &map)
Mapping compute_mapping(const Geom_Box &box, const bool squarize) const
static Geom_Box bbox_of(const Ellipse &e)
static std::string draw_options(const Tikz_Style &style, const bool allow_fill=false)
void draw_regular_polygon(const Regular_Polygon &poly, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
std::variant< Point, Polar_Point, Segment, Triangle, Ellipse, RotatedEllipse, Text, Polygon, Regular_Polygon, Rectangle, LineEq, Tikz_Quadratic_Bezier, Tikz_Cubic_Bezier, Tikz_Polyline > Object
Runtime set of supported objects.
std::vector< Legend_Entry > collect_legend_entries() const
void draw(std::ostream &output, const bool squarize=true) const
Emit a complete tikzpicture with all inserted objects.
void remove_coordinate_grid()
Disable coordinate grid rendering.
void set_clip_padding_mm(const double &padding_mm)
Configure clip expansion around frame borders.
void draw_point(const Point &p, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
void put_cartesian_axis()
Enable Cartesian axes drawing (only when 0 lies in range).
static constexpr int Layer_Default
static Geom_Box make_box(const Geom_Number &xmin, const Geom_Number &xmax, const Geom_Number &ymin, const Geom_Number &ymax)
void clear_tikz_styles()
Clear all registered \tikzset style definitions.
void clear()
Remove all inserted objects from the plane.
static std::string fmt_double(const double v)
static const char * layer_name(const int layer)
const double & get_wide() const
Plane width in millimeters.
static void append_option(std::string &opts, const std::string &opt)
const double & get_height() const
Plane height in millimeters.
void put(const Object &obj, const Tikz_Style &style, const int layer)
Insert an object with explicit style/layer.
void draw_tikzset_styles(Out &output) const
static constexpr int Layer_Foreground
static std::string text_options(const Tikz_Style &style)
Tikz_Plane(const double &wide, const double &height, const double &xoffset=0.0, const double &yoffset=0.0)
Construct a TikZ plane with fixed frame size.
static void draw_text(const Text &t, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map)
void enable_auto_legend(const bool enabled=true)
Enable auto-legend generation from style colors.
static double map_y(const Geom_Number &y, const Geom_Box &box, const Mapping &map)
void enable_native_tikz_layers(const bool enabled=true)
Enable native PGF layers (\pgfdeclarelayer).
void draw_polyline(Out &output, const std::vector< Point > &vertices, const bool closed, const Tikz_Style &style, const Geom_Box &box, const Mapping &map) const
void draw_cartesian_axis(Out &output, const Geom_Box &box, const Mapping &map) const
bool with_cartesian_axis_
Geom_Box compute_box() const
static std::string point_options(const Tikz_Style &style)
size_t size() const
Number of currently inserted objects.
void put_coordinate_grid(const double step_x=1.0, const double step_y=1.0, const bool draw_ticks=true)
Enable coordinate grid/ticks with user step sizes.
static Geom_Box bbox_of(const Polar_Point &pp)
bool with_coordinate_grid_
static Geom_Box bbox_of(const Tikz_Cubic_Bezier &b)
void draw_legend(Out &output) const
const double & get_yoffset() const
Vertical scope offset in millimeters.
static constexpr int Layer_Background
static double map_x_length(const Geom_Number &dx, const Mapping &map)
Tikz_Style default_style_
static std::string escape_latex(const std::string &text)
void set_point_radius_mm(const double &radius_mm)
Configure point marker radius.
void draw_rectangle(const Rectangle &r, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
static double map_x(const Geom_Number &x, const Geom_Box &box, const Mapping &map)
static void draw_cubic_bezier(const Tikz_Cubic_Bezier &b, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map)
const Tikz_Style & get_default_style() const
Default style used by put(obj) and non-styled put_in_plane.
void put(const Object &obj)
Insert an object with default style on default layer.
static Geom_Number rotated_y_extent(const RotatedEllipse &e)
static void draw_rotated_ellipse(const RotatedEllipse &e, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map)
static Geom_Box bbox_of(const Polygon &poly)
static Geom_Box bbox_of(const LineEq &l)
void draw_polygon(const Polygon &poly, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
static Geom_Box bbox_of(const Triangle &t)
std::vector< Legend_Entry > legend_entries_
void set_grid_style(const Tikz_Style &style)
Configure the style used to draw coordinate grids.
const Tikz_Style & get_axis_style() const
Style used for Cartesian axes when enabled.
void draw_coordinate_grid(Out &output, const Geom_Box &box, const Mapping &map) const
static Geom_Box bbox_of(const Segment &s)
static Geom_Box bbox_of(const Point &p)
void draw_triangle(const Triangle &t, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
static Geom_Box bbox_of(const Tikz_Quadratic_Bezier &b)
static Geom_Box bbox_of(const Tikz_Polyline &pl)
void register_tikz_style(const std::string &name, const Tikz_Style &style)
Register a reusable \tikzset style for the rendered picture.
static double map_y_length(const Geom_Number &dy, const Mapping &map)
void add_legend_entry(const std::string &label, const Tikz_Style &style)
Add a legend entry to be rendered in the top-left corner.
static Geom_Box bbox_of(const Rectangle &r)
static void merge_box(Geom_Box &dst, const Geom_Box &src)
std::vector< Styled_Object > objects_
static Geom_Box bbox_of(const Regular_Polygon &poly)
static void draw_quadratic_bezier(const Tikz_Quadratic_Bezier &b, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map)
const Tikz_Style & get_grid_style() const
Style used for coordinate grids when enabled.
void draw_segment(const Segment &s, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
void clear_legend()
Remove user-provided legend entries.
void draw_line_eq(const LineEq &l, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
static Geom_Box bbox_of(const Text &t)
double effective_clip_padding_mm() const
void set_default_style(const Tikz_Style &style)
Configure the default style for subsequent non-styled inserts.
static constexpr int Layer_Overlay
const double & get_clip_padding_mm() const
Clip expansion around the frame; <= 0 means auto (point radius).
const double & get_point_radius_mm() const
Radius used to draw point primitives (millimeters).
double legend_entry_step_mm_
static Geom_Box bbox_of(const RotatedEllipse &e)
void draw_ellipse(const Ellipse &e, const Tikz_Style &style, Out &output, const Geom_Box &box, const Mapping &map) const
std::map< std::string, Tikz_Style > tikz_style_defs_
const double & get_xoffset() const
Horizontal scope offset in millimeters.
void remove_cartesian_axis()
Disable Cartesian axes drawing.
A non-degenerate triangle defined by three points.
const Point & get_p3() const
Gets the third vertex.
const Point & get_p2() const
Gets the second vertex.
const Point & rightmost_point() const
Gets the vertex with the largest x-coordinate.
const Point & lowest_point() const
Gets the vertex with the smallest y-coordinate.
const Point & get_p1() const
Gets the first vertex.
const Point & highest_point() const
Gets the vertex with the largest y-coordinate.
const Point & leftmost_point() const
Gets the vertex with the smallest x-coordinate.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_y1_function > > y1(const __gmp_expr< T, U > &expr)
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_y0_function > > y0(const __gmp_expr< T, U > &expr)
2D infinite line representation using slope-intercept form.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
void put_in_plane(Tikz_Plane &plane, const Geom &geom_obj)
Insert any supported geometry type in a Tikz_Plane.
void put_cubic_bezier_native_in_plane(Tikz_Plane &plane, const Point &p0, const Point &p1, const Point &p2, const Point &p3, const Tikz_Style &style={}, const int layer=Tikz_Plane::Layer_Default)
Insert a cubic Bézier using native TikZ controls syntax.
void put_quadratic_bezier_native_in_plane(Tikz_Plane &plane, const Point &p0, const Point &p1, const Point &p2, const Tikz_Style &style={}, const int layer=Tikz_Plane::Layer_Default)
Insert a quadratic Bézier using native TikZ controls syntax.
void put_cubic_bezier_in_plane(Tikz_Plane &plane, const Point &p0, const Point &p1, const Point &p2, const Point &p3, const size_t subdivisions=64, const Tikz_Style &style={}, const int layer=Tikz_Plane::Layer_Default)
Approximate and insert a cubic Bézier as an open polyline.
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.
std::decay_t< typename HeadC::Item_Type > T
Geom_Number square_root(const Geom_Number &x)
Square root of x (wrapper over mpfr).
double geom_number_to_double(const Geom_Number &n)
Converts a Geom_Number to its double precision representation.
void put_quadratic_bezier_in_plane(Tikz_Plane &plane, const Point &p0, const Point &p1, const Point &p2, const size_t subdivisions=64, const Tikz_Style &style={}, const int layer=Tikz_Plane::Layer_Default)
Approximate and insert a quadratic Bézier as an open polyline.
mpq_class Geom_Number
Numeric type used by the geometry module.
void put_point_label_in_plane(Tikz_Plane &plane, const Point &point, const std::string &label, const std::string &placement="above", const Tikz_Style &style=make_tikz_draw_style("black"), const int layer=Tikz_Plane::Layer_Overlay)
Insert a point label with configurable placement (above, etc.).
Tikz_Style make_tikz_draw_style(const std::string &draw_color)
Create a basic draw style with a custom color.
Tikz_Style make_tikz_fill_style(const std::string &draw_color, const std::string &fill_color)
Create a basic fill style with custom draw/fill colors.
static long & color(typename GT::Node *p)
2D point and geometric utilities.
2D polygon representation and geometric operations.
2D infinite line in slope-intercept form.
Iterator over the vertices of a polygon.
Represents a cubic Bézier curve for native TikZ rendering.
Point p1
First control point.
Point p2
Second control point.
An object with its associated style, layer, and insertion order.
Tikz_Style style
The style used to render the object.
int layer
The rendering layer.
Object object
The geometric object.
size_t order
Insertion order within the layer.
An open or closed polyline for TikZ rendering.
std::vector< Point > vertices
Ordered vertices.
bool closed
Whether to close the polyline.
Represents a quadratic Bézier curve for native TikZ rendering.
Style descriptor for TikZ primitives.
std::string text_anchor
TikZ node anchor (anchor=<value>)
std::string fill_color
TikZ fill color (fill=<color>)
std::string pattern
TikZ pattern (e.g. north east lines)
double opacity
opacity=<value> in [0,1], when >= 0
std::string extra_options
Raw extra options appended as-is.
std::string text_color
TikZ text color (text=<color>)
bool fill
Fill closed shapes (polygon/triangle/ellipse)
std::string text_placement
TikZ placement (above, below left, ...)
std::string tikz_style_name
Optional named style (from \tikzset)
double line_width_mm
line width=<value>mm when > 0
std::string draw_color
TikZ draw color (draw=<color>)
std::string text_font_command
e.g. \\small, \\footnotesize
std::string pattern_color
TikZ pattern color (pattern color=<color>)