/* * 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" " 0 && H > 0) svgStream << " width='" << W << "px' height='"<< H << "px'" " preserveAspectRatio='xMinYMin meet'" " viewBox='0 0 " << W << ' ' << H <<"'"; svgStream << " xmlns='http://www.w3.org/2000/svg'" " xmlns:xlink='http://www.w3.org/1999/xlink'" " version='1.1'>\n"; } ///Circle draw -> x,y position and radius void drawCircle(float cx, float cy, float r, const svgStyle& style) { svgStream << "\n" : "/>\n"); } ///Line draw -> start and end point void drawLine(float ax, float ay, float bx, float by, const svgStyle& style) { svgStream << "\n" : "/>\n"); } ///Reference to an image (path must be relative to the SVG file) void drawImage(const std::string& simagePath, int W, int H, int posx = 0, int posy = 0, float opacity =1.f) { svgStream << "\n"; } ///Square draw -> x,y position and size void drawSquare(float cx, float cy, float W, const svgStyle& style) { drawRectangle(cx, cy, W, W, style); } ///Circle draw -> x,y position and width and height void drawRectangle(float cx, float cy, float W, float H, const svgStyle& style) { svgStream << "\n" : "/>\n"); } ///Text display -> x,y position, font size void drawText(float cx, float cy, const std::string& stext, const std::string& scol = "", const std::string& sattr = "", float fontSize = 1.f) { svgStream << "" << stext << "\n"; } template< typename DataInputIteratorX, typename DataInputIteratorY> void drawPolyline(DataInputIteratorX xStart, DataInputIteratorX xEnd, DataInputIteratorY yStart, DataInputIteratorY /*yEnd*/, const svgStyle& style) { svgStream << "\n" : "/>\n"); } ///Close the svg tag. std::ostringstream& closeSvgFile() { svgStream << ""; 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_