izzi
SVG SUBSET C++ API
Loading...
Searching...
No Matches
a60-svg-graphs-line.h
Go to the documentation of this file.
1// izzi line graphs -*- mode: C++ -*-
2
3// Copyright (c) 2025, Benjamin De Kosnik <b.dekosnik@gmail.com>
4
5// This file is part of the alpha60 library. This library is free
6// software; you can redistribute it and/or modify it under the terms
7// of the GNU General Public License as published by the Free Software
8// Foundation; either version 3, or (at your option) any later
9// version.
10
11// This library is distributed in the hope that it will be useful, but
12// WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15
16#ifndef izzi_SVG_LINE_GRAPHS_H
17#define izzi_SVG_LINE_GRAPHS_H 1
18
19#include <set>
20
21#include "izzi-json-basics.h"
24#include "a60-svg-markers.h"
25
26
27namespace svg {
28
29/// Polyline/line options.
30/// 1: use one line with css dasharray and markers mid, end points
31/// 2: use two lines: one with css dasharray and no markerspoints, two
32/// with explicit marker paths and added text tooltips
33/// 3: use two lines and add js + image tooltips: like 2 above
34/// but add image tooltips, with js controlling image visibility.
41
42/**
43 Line Graphs / Line Charts.
44
45 Some Example:
46 https://www.highcharts.com/demo/highcharts/accessible-line
47
48 Outline:
49
50 input has 2 columns: x, y
51 - how many x, what is range, what is delta
52 - how many y, what is range, what is delta
53
54 plot as grid/matrix system given above.
55
56 line: points, linestyle
57
58 x axis: title, tick mark spacing, tick mark style
59 y axis: title, tick mark spacing, tick mark style
60*/
61
62/// Per-graph constants, metadata, configuration, text.
64{
66
67 // visible_mode (render_state_base)
68
69 /// Key data: title, area, mode
70 string title; /// graph title
71 area_type graph_area; /// graph area
72 graph_mode mode; /// chart_line_style_n to use
73
74 /// Margins/Spaces
75 static constexpr uint xmargin = 100;
76 static constexpr uint ymargin = 100;
77 static constexpr uint xticdigits = 1; // fp sig digits xaxis
78 static constexpr uint yticdigits = 10; // number y tic labelsf
79
80 /// Type sizes.
81 static constexpr uint ttitlesz = 16; // title large bold
82 static constexpr uint th1sz = 12; // h1
83 static constexpr uint tpsz = 10; // text, paragraph,
84 static constexpr uint tticsz = 7; // tic text
85
86 /// Labels, tic units.
87 string xlabel; // x axis label
88 string ylabel;
89 string xticu; // x axis tick mark units postfix
90 string yticu;
91
92 /// Line/Outline/Markers/Tooltip styles
93 style lstyle; /// line style
94 stroke_style sstyle; /// marker stroke style, if any.
95 area_type tooltip_area; /// chart_line_style_3 tooltip size
96 string tooltip_id; /// chart_line_style_3 toolip id prefix
97 string tooltip_images; /// chart_line_style 3 set of image elements
98};
99
100
101/// Simplify sorted vrange by removing interior duplicates.
102vrange
104{
105 // Transform range to the simplest expression, where multiple points
106 // without significant vertical change are coalesed to starting
107 // control point and ending control point.
108 vrange simplevr;
109 point_2t last = { -1.0, -1.0 };
110 double duprangep(false);
111 for (const point_2t& pt : vr)
112 {
113 auto [ x, y] = pt;
114 if (y != get<1>(last))
115 {
116 if (duprangep == true)
117 {
118 simplevr.push_back(last);
119 duprangep = false;
120 }
121 simplevr.push_back(pt);
122 }
123 else
124 duprangep = true;
125 last = pt;
126 }
127 return simplevr;
128}
129
130
131/// Tramsform change points to points where the y-axis (% visual complete) changes
132/// @param points already simplified change points
133vrange
135{
136 vrange simplest;
137 point_2t last = { -1.0, -1.0 };
138 for (const point_2t& pt : points)
139 {
140 auto [ x, y] = pt;
141 if (y != get<1>(last))
142 simplest.push_back(pt);
143 last = pt;
144 }
145 return simplest;
146}
147
148
149/// Tramsform change points to points where the x-axis (time) matches a value in onlypoints.
150/// @param points already simplified change points
151vrange
152find_tooltip_points(const vrange& points, const vspace& onlypoints)
153{
154 vrange edited;
155 for (const space_type& matchx : onlypoints)
156 {
157 for (const auto& pt : points)
158 {
159 auto [ x, y ] = pt;
160 if (x == matchx)
161 {
162 edited.push_back(pt);
163 break;
164 }
165 }
166 }
167 return edited;
168}
169
170
171/// Map data points to cartestian points on graph area.
172/// @param data points
173vrange
175 const graph_rstate& gstate,
176 const point_2t xrange, const point_2t yrange)
177{
178 auto [ minx, maxx ] = xrange;
179 auto [ miny, maxy ] = yrange;
180
181 // Locate graph area on plate area.
182 // aplate is total plate area with margins, aka
183 // pwidth = xmargin + gwidth + xmargin
184 // pheight = ymargin + gheight + ymargin
185 auto [ pwidth, pheight ] = gstate.graph_area;
186 double gwidth = pwidth - (2 * gstate.xmargin);
187 double gheight = pheight - (2 * gstate.ymargin);
188 const double chartyo = pheight - gstate.ymargin;
189
190 // Transform data points to scaled cartasian points in graph area.
191 vrange cpoints;
192 for (uint i = 0; i < points.size(); i++)
193 {
194 const point_2t& pt = points[i];
195 auto [ vx, vy ] = pt;
196
197 // At bottom of graph.
198 const double xlen = scale_value_on_range(vx, minx, maxx, 0, gwidth);
199 double x = gstate.xmargin + xlen;
200
201 // Y axis grows up from chartyo.
202 const double ylen = scale_value_on_range(vy, miny, maxy, 0, gheight);
203 double y = chartyo - ylen;
204
205 cpoints.push_back(std::make_tuple(x, y));
206 }
207 return cpoints;
208}
209
210
211/// Return set of images for image tooltips, one for each point.
212/// @param aimg is size of image embedded inside svg element.
213/// @pathprefix is the path to the directory with the store of images
214/// @idimgbase is the root name for what will be document level unique names of
215/// sequentially numbered images (say fximage-, for fximage-101 et al)
216/// Expected, zero filled imageid.
217/// 2025-06-26-android-15-ptablet-talkback-4usted-firefox_13188.webp
218group_element
219make_line_graph_images(const vrange& points, const graph_rstate& gstate,
220 const string imgprefix,
221 const string imgpath = "../filmstrip/",
222 const string imgext = ".webp")
223{
225 g.start_element(gstate.title + "-tooltip-images");
226 for (const point_2t p : points)
227 {
228 std::ostringstream oss;
229 oss << std::setfill('0') << std::setw(5);
230 oss << static_cast<uint>(std::get<0>(p));
231 const string xms = oss.str();
232
233 const string isrc = imgpath + imgprefix + xms + imgext;
234 const string imgid = gstate.tooltip_id + xms;
235 auto [ width, height ] = gstate.tooltip_area;
236
238 image_element::data di = { isrc, 0, 0, width, height };
239 i.start_element(imgid);
240 i.add_data(di, "anonymous", "hidden", "");
241 //i.add_data(di, "anonymous", "", "none");
242 i.finish_element();
243 g.add_element(i);
244 }
245 g.finish_element();
246 return g;
247}
248
249
250/// Return set of paths of marker shapes with text tooltips.
251string
252make_line_graph_markers(const vrange& points, const vrange& cpoints,
253 const graph_rstate& gstate, const double radius,
254 const string imgidbase = "")
255{
256 string ret;
257 for (uint i = 0; i < points.size(); i++)
258 {
259 auto [ vx, vy ] = points[i];
260 auto [ cx, cy ] = cpoints[i];
261
262 std::ostringstream oss;
263 oss << std::setfill('0') << std::setw(5);
264 oss << static_cast<uint>(vx);
265 const string xms = oss.str();
266 const string imgid = imgidbase + xms;
267
268 // Generate displayed tooltip text....
269 string tipstr(gstate.title);
270 tipstr += k::newline;
271 tipstr += std::to_string(static_cast<uint>(vy));
272 tipstr += '%';
273 tipstr += k::comma;
274 tipstr += k::space;
275 tipstr += std::to_string(static_cast<uint>(vx));
276 tipstr += "ms";
277
278 const string& linecap = gstate.sstyle.linecap;
279 const bool roundp = linecap == "round" || linecap == "circle";
280 const bool squarep = linecap == "square";
281 const bool trianglep = linecap == "triangle";
282
283 // Markers default to closed paths that are filled with no stroke.
284 // Setting visible to vector | echo induces outline behavior.
285 style styl = gstate.lstyle;
286 styl._M_fill_opacity = 1;
287 if (gstate.is_visible(select::echo))
289
290
291 // Circle Centered.
292 // svg::circle_element c = make_circle(cpoints[i], gstate.lstyle, r);
293 if (roundp)
294 {
296 circle_element::data dc = { cx, cy, radius };
297 c.start_element();
298 c.add_data(dc);
299 c.add_style(styl);
300 if (!imgidbase.empty())
303 c.add_title(tipstr);
304 c.add_raw(string { circle_element::pair_finish_tag } + k::newline);
305 ret += c.str();
306 }
307
308 // Square Centered.
309 // svg::rect_element r = (cpoints[i], gstate.lstyle, {2 * r, 2 * r});
310 if (squarep)
311 {
312 rect_element r;
313 rect_element::data dr = { cx - radius, cy - radius,
314 2 * radius, 2 * radius };
315 r.start_element();
316 r.add_data(dr);
317 r.add_style(styl);
318 if (!imgidbase.empty())
321 r.add_title(tipstr);
322 r.add_raw(string { rect_element::pair_finish_tag } + k::newline);
323 ret += r.str();
324 }
325
326 // Triangle Centered.
327 if (trianglep)
328 {
329 string xattr;
330 if (!imgidbase.empty())
332
333 // Visual weight of triangle is smaller, so enlarge slightly.
334 const double tradius = radius * 1.3;
335 path_element p = make_path_triangle(cpoints[i], styl, tradius, 120,
336 false, xattr);
337 p.add_title(tipstr);
338 p.add_raw(string { path_element::pair_finish_tag } + k::newline);
339 ret += p.str();
340 }
341
342 // Throw if marker style not supported.
343 if (!roundp && !squarep && !trianglep)
344 {
345 string m("make_line_graph_markers:: ");
346 m += "linecap value invalid or missing, currently set to: ";
347 m += linecap;
348 m += k::newline;
349 throw std::runtime_error(m);
350 }
351 }
352 return ret;
353}
354
355
356/// Axis Labels
357/// Axis X/Y Ticmarks
358/// X line increments
359///
360/// @param aplate = total size of graph area
361/// @param points = vector of {x,y} points to graph
362/// @param gstate = graph render state
363/// @param xscale = scale x axis by this ammount (1000 if converting ms to s)
364/// @param yscale = scale y axis by this ammount
365/// @param typo = typography to use for labels
366svg_element
368 const graph_rstate& gstate,
369 const double xscale = 1, const double yscale = 1,
370 const typography typo = k::apercu_typo)
371{
372 using namespace std;
373 svg_element lanno(gstate.title, "line graph annotation",
374 gstate.graph_area, false);
375
376
377 // Locate graph area on plate area.
378 auto [ pwidth, pheight ] = gstate.graph_area;
379 double gwidth = pwidth - (2 * gstate.xmargin);
380 double gheight = pheight - (2 * gstate.ymargin);
381 const double chartyo = pheight - gstate.ymargin;
382 const double chartxo = gstate.xmargin;
383 const double chartxe = pwidth - gstate.xmargin;
384
385 // Base typo for annotations.
386 typography anntypo = typo;
387 anntypo._M_style = k::wcagg_style;
389
390 // Axes and Labels
391 if (gstate.is_visible(select::axis))
392 {
393 lanno.add_raw(group_element::start_group("axes-" + gstate.title));
394
395 // Add axis labels.
396 point_2t xlabelp = make_tuple(pwidth / 2, chartyo + (gstate.ymargin / 2));
397 styled_text(lanno, gstate.xlabel, xlabelp, anntypo);
398
399 point_2t ylabelp = make_tuple(chartxo / 2, pheight / 2);
400 styled_text(lanno, gstate.ylabel, ylabelp, anntypo);
401
402 // Add axis lines.
403 line_element lx = make_line({chartxo, chartyo}, {chartxe, chartyo},
404 gstate.lstyle);
405 line_element ly = make_line({chartxo, chartyo}, {chartxo, gstate.ymargin},
406 gstate.lstyle);
407 lanno.add_element(lx);
408 lanno.add_element(ly);
409
411 }
412
413 // Base typo for tic labels.
414 // NB: Assume pointsx/pointsy are monotonically increasing.
417
418 // Separate tic label values for each (x, y) axis, find ranges for each.
419 auto [ maxx, maxy ] = max_vrange(points, gstate.xticdigits, xscale, yscale);
420#if MOZ
421 auto minx = 0;
422 auto miny = 0;
423#else
424 auto minx = 1;
425 auto miny = 0;
426#endif
427
428 const double xrange(maxx - minx);
429 const double gxscale(gwidth / xrange);
430 const double yrange(maxy - miny);
431 const double gyscale(gheight / yrange);
432
433 // Derive the number of tick marks.
434
435 // Use a multiple of 5 to make natural counting easier.
436 // Start with an assumption of 20 tic marks for the x axis.
437#if MOZ
438 double xtickn(xrange * 2); // .5 sec
439 if (xtickn < 10)
440 xtickn = 10;
441 if (xtickn > 26)
442 xtickn = xrange;
443#else
444 double xtickn = 53;
445#endif
446
447 // X axis is seconds, xtickn minimum delta is 0.1 sec.
448#if MOZ
449 double xticmindelta = 0.1;
450 double xdelta = std::max(xrange / xtickn, xticmindelta);
451 // Round up to significant digits, so if xdelta is 0.18 round to 0.2.
452 xdelta = std::round(xdelta * gstate.xticdigits * 10) / (gstate.xticdigits * 10);
453#else
454 double xticmindelta = 1;
455 double xdelta = std::max(xrange / xtickn, xticmindelta);
456#endif
457
458 // Y axis is simpler, 0, 10, 20, ..., 80, 90, 100 in percent.
459 const double ydelta = yrange / gstate.yticdigits;
460
461 // Generate tic marks
462 const double ygo = gstate.ymargin + gheight + graph_rstate::th1sz;
463 if (gstate.is_visible(select::ticks))
464 {
465 // X tic labels
466 lanno.add_raw(group_element::start_group("tic-x-" + gstate.title));
467 for (double x = minx; x <= maxx; x += xdelta)
468 {
469 const double xto = chartxo + (x * gxscale);
470
471 ostringstream oss;
472#if MOZ
473 oss << fixed << setprecision(gstate.xticdigits) << x;
474#else
475 oss << std::trunc(x);
476#endif
477 const string sxui = oss.str() + gstate.xticu;
478 styled_text(lanno, sxui, {xto, ygo}, anntypo);
479 }
481
482 // Y tic labels
483 // Positions for left and right y-axis tic labels.
484 lanno.add_raw(group_element::start_group("tic-y-" + gstate.title));
485 const double yticspacer = graph_rstate::th1sz * 2;
486 const double xgol = gstate.xmargin - yticspacer; // left
487 const double xgor = gstate.xmargin + gwidth + yticspacer; // right
488 const double starty = miny != 0 ? miny : miny + ydelta; // skip zero label
489 for (double y = starty; y < maxy + ydelta; y += ydelta)
490 {
491 const double yto = chartyo - (y * gyscale);
492 const string syui = std::to_string(static_cast<uint>(y)) + gstate.yticu;
493 styled_text(lanno, syui, {xgol, yto}, anntypo);
494 styled_text(lanno, syui, {xgor, yto}, anntypo);
495 }
497 }
498
499 // Horizontal lines linking left and right y-axis tic label value to each other,
500 // perhaps with magnification-ready micro text.
501 if (gstate.is_visible(select::linex))
502 {
503 lanno.add_raw(group_element::start_group("tic-y-lines-" + gstate.title));
504
505 style hlstyl = gstate.lstyle;
507
508 anntypo._M_size = 3;
509 //anntypo._M_style.set_colors(color::gray20);
510 for (double y = miny + ydelta; y < maxy + ydelta; y += ydelta)
511 {
512 // Base line layer.
513 const double yto = chartyo - (y * gyscale);
514 line_element lxe = make_line({chartxo + graph_rstate::th1sz, yto},
515 {chartxe - graph_rstate::th1sz, yto}, hlstyl);
516 lanno.add_element(lxe);
517
518 // Add y-axis tic numbers along line for use when magnified.
519 if (gstate.is_visible(select::alt))
520 {
521 // Skip first and last as covered by either Y-axes tic marks.
522 for (double x = minx + xdelta; x < maxx - xdelta; x += xdelta)
523 {
524 const double xto = chartxo + (x * gxscale);
525 const string syui = std::to_string(static_cast<uint>(y)) + gstate.yticu;
526 styled_text(lanno, syui, {xto, yto}, anntypo);
527 }
528 }
529 }
530
532 }
533
534 return lanno;
535}
536
537
538/// Returns a svg_element with the rendered line graph (char).
539/// Assumptions:
540/// vgrange x axis is monotonically increasing
541///
542/// NB1: Axes and labels drawn in a separate pass (make_line_graph_annotations).
543/// NB2: Output file of x-axis point values for image tooltips if strategy = 3.
544///
545/// @param aplate = total size of graph area
546/// @param points = vector of {x,y} points to graph
547/// @param gstate = graph render state
548/// @param xrange = unified x-axis range for all graphs if multiplot
549/// @param yrange = unified y-axis range for all graphs if multiplot
550/// @param metadata = image filename prefix for tooltips if present
551svg_element
552make_line_graph(const vrange& points, const graph_rstate& gstate,
553 const point_2t xrange, const point_2t yrange)
554{
555 using namespace std;
556 const vrange cpoints = transform_to_graph_points(points, gstate,
557 xrange, yrange);
558
559 // Plot path of points on cartesian plane.
560 const string gname = gstate.title + "_line_graph";
561 svg_element lgraph(gname, "line graph", gstate.graph_area, false);
562 if (gstate.is_visible(select::vector))
563 {
564 if (gstate.mode == chart_line_style_1)
565 {
566 // Use polyline and CSS-based markerspoints all in one line on layer 1.
567 lgraph.add_raw(group_element::start_group("polyline-" + gstate.title));
568 polyline_element pl1 = make_polyline(cpoints, gstate.lstyle, gstate.sstyle);
569 lgraph.add_element(pl1);
571 }
572 if (gstate.mode == chart_line_style_2)
573 {
574 // Use polyline base line on layer 1.
575 // Use set of marker points paths with value as text tooltips on layer 2.
576 lgraph.add_raw(group_element::start_group("polyline-" + gstate.title));
577 stroke_style no_markerstyle = gstate.sstyle;
578 no_markerstyle.markerspoints = "";
579 polyline_element pl1 = make_polyline(cpoints, gstate.lstyle, no_markerstyle);
580 lgraph.add_element(pl1);
582
583 // Markers + text tooltips.
584 lgraph.add_raw(group_element::start_group("markers-" + gstate.title));
585 string markers = make_line_graph_markers(points, cpoints, gstate, 3);
586 lgraph.add_raw(markers);
588 }
589 if (gstate.mode == chart_line_style_3)
590 {
591 string m("requested mode requires use of different overloaded function");
592 throw std::runtime_error(m);
593 }
594 }
595
596 return lgraph;
597}
598
599
600/// Line graph 3 needs more parameters.
601svg_element
602make_line_graph(const vrange& points, const vrange& tpoints, graph_rstate& gstate,
603 const point_2t xrange, const point_2t yrange,
604 const string metadata, script_element::scope scontext)
605{
606 using namespace std;
607 const vrange cpoints = transform_to_graph_points(points, gstate,
608 xrange, yrange);
609
610 // Plot path of points on cartesian plane.
611 const string gname = gstate.title + "_line_graph";
612 svg_element lgraph(gname, "line graph", gstate.graph_area, false);
613 if (gstate.is_visible(select::vector))
614 {
615 if (gstate.mode == chart_line_style_3)
616 {
617 // Use polyline base line on layer 1 of control points (subset points).
618 // Use set of control points marker paths with value as text tooltips on layer 2.
619 // Use set of image points (subset control points) image elements on layer 3.
620 lgraph.add_raw(group_element::start_group("polyline-" + gstate.title));
621 stroke_style no_markerstyle = gstate.sstyle;
622 no_markerstyle.markerspoints = "";
623 polyline_element pl1 = make_polyline(cpoints, gstate.lstyle, no_markerstyle);
624 lgraph.add_element(pl1);
626
627 // Markers + text tooltips, add image id + js to make image visible.
628 // Use simplified points, aka only the visual change points.
629 const vrange& ctpoints = transform_to_graph_points(tpoints, gstate,
630 xrange, yrange);
631
632 lgraph.add_raw(group_element::start_group("markers-" + gstate.title));
633 string markers = make_line_graph_markers(tpoints, ctpoints, gstate, 3,
634 gstate.tooltip_id);
635 lgraph.add_raw(markers);
637
638 // Add tool images to graph_rstate.
639 // Add this plus script at the same layer of the DOM, which varies.
640 const string imgprefix = metadata + k::hyphen + gstate.title + "_";
641 group_element ttips = make_line_graph_images(tpoints, gstate, imgprefix);
642
643 if (scontext == script_element::scope::element)
644 {
645 lgraph.add_element(ttips);
646 lgraph.add_raw(script_element::tooltip_script(scontext).str());
647 }
648 else
649 gstate.tooltip_images = ttips.str();
650 }
651 }
652
653 return lgraph;
654}
655
656} // namepace svg
657
658#endif
void add_data(const data &d)
Either serialize immediately (as below), or create data structure that adds data to data_vec and then...
static const script_element tooltip_script(const scope context)
void add_style(const style &sty)
void add_data(const data &d, string trans="")
void start_element()
For groups of elements that have the same name.
static constexpr const char * pair_finish_tag
static string finish_group()
void add_title(const string &t)
static const string tooltip_attribute(const string &id)
static constexpr const char * pair_finish_tag
static string start_group(const string name)
static constexpr const char * pair_finish_tag
void add_data(const data &d)
Either serialize immediately (as below), or create data structure that adds data to data_vec and then...
void add_raw(const string &raw)
scope
Where is the script element placed? On/within the element itself, or at the document (global)?...
string str() const
void add_element(const element_base &e)
void start_element(const string &id)
static constexpr string finish_tag_hard
line_element make_line(const point_2t origin, const point_2t end, style s, const string dasharray="")
Line primitive.
group_element make_line_graph_images(const vrange &points, const graph_rstate &gstate, const string imgprefix, const string imgpath="../filmstrip/", const string imgext=".webp")
Return set of images for image tooltips, one for each point.
@ pt
Point where 1 pixel x 1/72 dpi x 96 PPI = .26 mm.
unsigned short ushort
Base integer type: positive and negative, signed integral value.
Definition a60-svg.h:56
double scale_value_on_range(const ssize_type value, const ssize_type min, const ssize_type max, const ssize_type nfloor, const ssize_type nceil)
Scale value from min to max on range (nfloor, nceil).
Definition a60-svg.h:67
double space_type
Base floating point type.
Definition a60-svg.h:62
vrange find_tooltip_points(const vrange &points, const vspace &onlypoints)
Tramsform change points to points where the x-axis (time) matches a value in onlypoints.
graph_mode
Polyline/line options. 1: use one line with css dasharray and markers mid, end points 2: use two line...
path_element make_path_triangle(const point_2t origin, const style styl, const double r=4, const double angle=120, const bool selfclosingtagp=true, const string xattr="")
Center a triangle at this point.
void styled_text(element_base &obj, const string text, const point_2t origin, const typography typo)
Text at.
svg_element make_line_graph(const vrange &points, const graph_rstate &gstate, const point_2t xrange, const point_2t yrange)
Returns a svg_element with the rendered line graph (char). Assumptions: vgrange x axis is monotonical...
svg_element make_line_graph_annotations(const vrange &points, const graph_rstate &gstate, const double xscale=1, const double yscale=1, const typography typo=k::apercu_typo)
Axis Labels Axis X/Y Ticmarks X line increments.
std::vector< point_2t > vrange
Definition izzi-points.h:46
point_2t max_vrange(vspace &xpoints, vspace &ypoints, const uint pown)
For each dimension of vrnage, find min/max and return (xmax, ymax) NB: Assumes zero is min.
Definition izzi-points.h:80
vrange transform_to_graph_points(const vrange &points, const graph_rstate &gstate, const point_2t xrange, const point_2t yrange)
Map data points to cartestian points on graph area.
string make_line_graph_markers(const vrange &points, const vrange &cpoints, const graph_rstate &gstate, const double radius, const string imgidbase="")
Return set of paths of marker shapes with text tooltips.
vrange find_change_points(const vrange &vr)
Simplify sorted vrange by removing interior duplicates.
@ alt
alternate use specified in situ
@ ticks
ticks, markers
@ vector
svg path, circle, rectangle, etc.
@ linex
horizontal lines
@ echo
b & w outline version of vector
vrange find_visual_change_points(const vrange &points)
Tramsform change points to points where the y-axis (% visual complete) changes.
std::vector< space_type > vspace
Split range, so one dimension of (x,y) cartesian plane.
Definition izzi-points.h:41
unsigned int uint
Definition a60-svg.h:57
polyline_element make_polyline(const vrange &points, const style s, const stroke_style sstyle={ })
Polyline primitive.
std::tuple< space_type, space_type > point_2t
Point (x,y) in 2D space, space_type defaults to double.
Definition izzi-points.h:22
Per-graph constants, metadata, configuration, text.
string title
Key data: title, area, mode.
static constexpr uint yticdigits
area< space_type > area_type
static constexpr uint xticdigits
string tooltip_id
chart_line_style_3 tooltip size
static constexpr uint th1sz
area_type tooltip_area
marker stroke style, if any.
area_type graph_area
graph title
string xlabel
Labels, tic units.
stroke_style sstyle
line style
graph_mode mode
graph area
static constexpr uint tticsz
static constexpr uint ymargin
static constexpr uint xmargin
chart_line_style_n to use
static constexpr uint ttitlesz
Type sizes.
static constexpr uint tpsz
style lstyle
Line/Outline/Markers/Tooltip styles.
string tooltip_images
chart_line_style_3 toolip id prefix
render_state_base(const select m=select::none)
bool is_visible(const select v) const
Additional path/line/polyline stroke styles.
Datum consolidating style preferences.
color_qi _M_fill_color
color_qi _M_stroke_color