/*
* Modified version of:
*
* @file htmlDoc.h
* @brief Simple HTML document writer and SVG drawer
* @author Pierre MOULON
*
* Copyright (c) 2011, 2012, 2013 Pierre MOULON
* All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef _HTMLDOC_H_
#define _HTMLDOC_H_
// I N C L U D E S /////////////////////////////////////////////////
// D E F I N E S ///////////////////////////////////////////////////
#define JSXCHART_BORDER 0.2f
// S T R U C T S ///////////////////////////////////////////////////
namespace HTML {
inline const std::string htmlMarkup(const std::string& markup, const std::string& text) {
std::ostringstream os;
os << '<'<< markup<<'>' << text << ""<' <<"\n";
return os.str();
}
inline const std::string htmlMarkup(const std::string& markup, const std::string& attributes, const std::string& text) {
std::ostringstream os;
os << '<'<' << text << ""<' <<"\n";
return os.str();
}
inline const std::string htmlOpenMarkup(const std::string& markup, const std::string& attributes) {
std::ostringstream os;
os << '<'<" <<"\n";
return os.str();
}
inline const std::string htmlComment(const std::string& text) {
std::ostringstream os;
os << "" << "\n";
return os.str();
}
/// Return a chain in the form attributes="val"
template
inline const std::string quotedAttributes(const std::string& attributes, const T & val) {
std::ostringstream os;
os << attributes << "='" << val << '\'';
return os.str();
}
/// Return a chain of the value T
template
inline const std::string toString(const T& val) {
std::ostringstream os;
os << val;
return os.str();
}
class htmlDocumentStream
{
public:
htmlDocumentStream(const std::string& title) {
htmlStream << "\n";
htmlStream << htmlMarkup("head",
"\n"
"\n"
"\n");
htmlStream << htmlMarkup("title",title);
}
htmlDocumentStream(const std::string& title,
const std::vector& vec_css,
const std::vector& vec_js)
{
htmlStream << "\n\n";
htmlStream << htmlMarkup("title",title);
// CSS and JS resources
for (std::vector::const_iterator iter = vec_css.begin(); iter != vec_css.end(); ++iter)
htmlStream << "\n";
for (std::vector::const_iterator iter = vec_js.begin(); iter != vec_js.end(); ++iter)
htmlStream << "\n";
htmlStream << "\n";
}
void pushInfo(const std::string& text) {
htmlStream << text;
}
std::string getDoc() {
return htmlMarkup("html", htmlStream.str());
}
std::ostringstream htmlStream;
};
/// Class to draw with the JSXGraph library in HTML page.
class JSXGraphWrapper
{
public:
typedef float TRANGE;
typedef std::pair< std::pair, std::pair > RANGE;
JSXGraphWrapper() {
cpt = 0;
}
void reset() {
stream.str("");
stream.precision(4);
//stream.setf(std::ios::fixed,std::ios::floatfield);
cpt = 0;
}
void init(unsigned W, unsigned H, LPCTSTR szGraphName=NULL) {
reset();
std::string strGraphName;
if (szGraphName == NULL) {
strGraphName = SEACAVE::Util::getUniqueName();
szGraphName = strGraphName.c_str();
}
stream <<
"\n"
"\n"
"\n";
}
std::string toStr() const {
return stream.str();
}
template
static inline RANGE autoViewport(TX maxValX, TY maxValY, TX minValX, TY minValY) {
//Use the value with a little margin
const TX rangeX = maxValX-minValX;
const TY rangeY = maxValY-minValY;
return std::make_pair(
std::make_pair(-JSXCHART_BORDER*rangeX+minValX,JSXCHART_BORDER*rangeX+maxValX),
std::make_pair(-JSXCHART_BORDER*rangeY+minValY,JSXCHART_BORDER*rangeY+maxValY));
}
template
static RANGE autoViewport(const VECTX& vec_x, const VECTY& vec_y) {
typedef typename VECTX::value_type TX;
typedef typename VECTY::value_type TY;
if (vec_x.empty() || vec_y.empty() || vec_x.size() != vec_y.size())
return RANGE();
//For X values
const TX minValX = *std::min_element(vec_x.begin(), vec_x.end());
const TX maxValX = *std::max_element(vec_x.begin(), vec_x.end());
//For Y values
const TY minValY = *std::min_element(vec_y.begin(), vec_y.end());
const TY maxValY = *std::max_element(vec_y.begin(), vec_y.end());
return autoViewport(maxValX, maxValY, minValX, minValY);
}
template
static RANGE autoViewport(const VECTY& vec_y, bool bForceY0=true) {
typedef T TX;
typedef typename VECTY::value_type TY;
if (vec_y.empty())
return RANGE();
//For X values
const TX minValX = TX(0);
const TX maxValX = static_cast(vec_y.size());
//For Y values
const TY minValY = (bForceY0 ? TY(0) : *std::min_element(vec_y.begin(), vec_y.end()));
const TY maxValY = *std::max_element(vec_y.begin(), vec_y.end());
return autoViewport(maxValX, maxValY, minValX, minValY);
}
std::ostringstream stream;
size_t cpt; //increment for variable
};
/*----------------------------------------------------------------*/
} // namespace HTML
namespace SVG {
/// Basic SVG style
class svgStyle
{
public:
svgStyle():_sFillCol(""), _sStrokeCol("black"), _sToolTip(""), _fillOpacity(1.f), _strokeW(1.f), _strokeOpacity(1.f) {}
// Configure fill color
svgStyle& fill(const std::string& col, float opacity = 1.f)
{ _sFillCol = col; _fillOpacity = opacity; return *this; }
// Configure stroke color and width
svgStyle& stroke(const std::string& col, float witdh = 1.f, float opacity = 1.f)
{ _sStrokeCol = col; _strokeW = witdh; _strokeOpacity = opacity; return *this; }
// Configure with no stroke
svgStyle& noStroke()
{ _sStrokeCol = ""; _strokeW = 0.f; _strokeOpacity = 0.f; return *this; }
// Configure tooltip
svgStyle& tooltip(const std::string& sTooltip)
{ _sToolTip = sTooltip; return *this; }
const std::string getSvgStream() const {
std::ostringstream os;
if (!_sStrokeCol.empty()) {
os << " stroke='" << _sStrokeCol << "' stroke-width='" << _strokeW << "'";
if (_strokeOpacity < 1)
os << " stroke-opacity='" << _strokeOpacity << "'";
}
if (!_sFillCol.empty()) {
os << " fill='" << _sFillCol << "'";
if (_fillOpacity < 1)
os << " fill-opacity='" << _fillOpacity << "'";
} else {
os << " fill='none'";
}
if (!_sToolTip.empty()) {
os << " tooltip='enable'>" << "" << _sToolTip << "";
}
return os.str();
}
bool bTooltip() const { return !_sToolTip.empty();}
std::string _sFillCol, _sStrokeCol, _sToolTip;
float _fillOpacity, _strokeW, _strokeOpacity;
};
/// Basic class to handle simple SVG draw.
/// You can draw line, square, rectangle, text and image (xlink)
class svgDrawer
{
public:
///Constructor
svgDrawer(size_t W = 0, size_t H = 0) {
svgStream <<
"\n"
"\n"
"";
return svgStream;
}
std::ostringstream svgStream;
};
/// Helper to draw a SVG histogram
/// ____
/// | | ___ |
/// | |__| | |
/// | | | | |
/// -----------|
struct svgHisto
{
template
std::string draw(const VECT& vec_value,
const std::pair& range,
float W, float H)
{
if (vec_value.empty())
return "";
//-- Max value
typedef typename VECT::value_type T;
const T maxi = *max_element(vec_value.begin(), vec_value.end());
const size_t n = vec_value.size();
const float scaleFactorY = H / static_cast(maxi);
const float scaleFactorX = W / static_cast(n);
svgDrawer svgStream;
for (typename VECT::const_iterator iter = vec_value.begin(); iter != vec_value.end(); ++iter)
{
const T dist = std::distance(vec_value.begin(), iter);
const T& val = *iter;
std::ostringstream os;
os << '(' << range.first + dist/float(n) * (range.second-range.first) << ',' << val << ')';
svgStyle style = svgStyle().fill("blue").stroke("black", 1.0).tooltip(os.str());
svgStream.drawRectangle(
scaleFactorX * dist, H-val * scaleFactorY,
scaleFactorX, val * scaleFactorY,
style);
//_________
//| |_________
//| || |
//| || |
//| || |
//0 sFactorX 2*sFactorX
}
svgStyle styleAxis = svgStyle().stroke("black", 1.0f);
// Draw X Axis
svgStream.drawText(.05f*W, 1.2f*H, HTML::toString(range.first), "black", "", .1f*H);
svgStream.drawText(W, 1.2*H, HTML::toString(range.second), "black", "", .1f*H);
svgStream.drawLine(0, 1.1f*H, W, 1.1f*H, styleAxis);
// Draw Y Axis
svgStream.drawText(1.2f*W, .1f*H, HTML::toString(maxi), "black", "", .1f*H);
svgStream.drawText(1.2f*W, H, "0", "black", "", .1f*H);
svgStream.drawLine(1.1f*W, 0, 1.1f*W, H, styleAxis);
return svgStream.closeSvgFile().str();
}
};
/*----------------------------------------------------------------*/
} // namespace SVG
#endif // _HTMLDOC_H_