8#include <tracking/trackFindingCDC/display/SVGPrimitivePlotter.h>
10#include <framework/logging/Logger.h>
15using namespace TrackFindingCDC;
22 , m_svgContentStream()
23 , m_nIndentationSpaces(s_defaultNIndentationSpaces)
30 , m_svgContentStream()
31 , m_nIndentationSpaces(s_defaultNIndentationSpaces)
32 , m_svgAttributes(svgAttributes)
38 , m_svgContentStream(plotter.m_svgContentStream.str(),
std::ostringstream::ate)
39 , m_nIndentationSpaces(plotter.m_nIndentationSpaces)
40 , m_svgAttributes(plotter.m_svgAttributes)
46 return std::make_unique<SVGPrimitivePlotter>(*
this);
58 {
"x1", std::to_string(startX)},
59 {
"x2", std::to_string(endX)},
60 {
"y1", std::to_string(startY)},
61 {
"y2", std::to_string(endY)}
78 {
"x1", std::to_string(startX)},
79 {
"x2", std::to_string(endX)},
80 {
"y1", std::to_string(startY)},
81 {
"y2", std::to_string(endY)},
82 {
"marker-end",
"url(#endArrow)"}
97 {
"cx", std::to_string(centerX)},
98 {
"cy", std::to_string(centerY)},
99 {
"r", std::to_string(std::fabs(radius))}
129 const float radiusX = std::fabs(radius);
130 const float radiusY = std::fabs(radius);
131 const float rotationAngle = 0;
133 std::ostringstream pathStream;
135 pathStream <<
"M" <<
' ';
136 pathStream << std::to_string(startX) <<
' ';
137 pathStream << std::to_string(startY) <<
' ';
138 pathStream <<
"A" <<
' ';
139 pathStream << std::to_string(radiusX) <<
' ';
140 pathStream << std::to_string(radiusY) <<
' ';
141 pathStream << std::to_string(rotationAngle) <<
' ';
142 pathStream << std::to_string(longArc) <<
' ';
143 pathStream << std::to_string(sweepFlag) <<
' ';
144 pathStream << std::to_string(endX) <<
' ';
145 pathStream << std::to_string(endY);
147 AttributeMap geometryAttributeMap{{
"d", pathStream.str()}};
153 const std::vector<std::array<float, 2>>& tangents,
157 static const double k = 4.0 / 3.0 * (std::sqrt(2.0) - 1.0);
159 B2ASSERT(
"Expect number of points and tangents to be the same", points.size() == tangents.size());
160 if (points.size() < 2)
return;
164 std::ostringstream pathStream;
167 float startX = std::get<0>(points[0]);
168 float startY = std::get<1>(points[0]);
171 pathStream <<
' ' << std::to_string(startX);
172 pathStream <<
' ' << std::to_string(startY);
174 for (
size_t iCurrent = 0, iNext = 1; iNext < points.size(); iCurrent = iNext, ++iNext) {
176 float currentTX = std::get<0>(tangents[iCurrent]);
177 float currentTY = std::get<1>(tangents[iCurrent]);
179 float nextTX = std::get<0>(tangents[iNext]);
180 float nextTY = std::get<1>(tangents[iNext]);
182 float currentT = std::hypot(currentTX, currentTY);
183 float nextT = std::hypot(nextTX, nextTY);
185 currentTX /= currentT;
186 currentTY /= currentT;
190 float currentX = std::get<0>(points[iCurrent]);
191 float currentY = std::get<1>(points[iCurrent]);
193 float nextX = std::get<0>(points[iNext]);
194 float nextY = std::get<1>(points[iNext]);
197 float alpha = std::atan2(currentTX * nextTY - currentTY * nextTX,
198 currentTX * nextTX + currentTY * nextTY);
200 float distance = std::hypot(currentX - nextX, currentY - nextY);
201 float controlLength = k * distance / 2 / std::cos(alpha / 2);
203 float currentControlX = currentX + currentTX * controlLength;
204 float currentControlY = currentY + currentTY * controlLength;
206 float nextControlX = nextX - nextTX * controlLength;
207 float nextControlY = nextY - nextTY * controlLength;
209 pathStream <<
' ' <<
"C";
211 pathStream <<
' ' << std::to_string(currentControlX);
212 pathStream <<
' ' << std::to_string(currentControlY);
214 pathStream <<
' ' << std::to_string(nextControlX);
215 pathStream <<
' ' << std::to_string(nextControlY);
217 pathStream <<
' ' << std::to_string(nextX);
218 pathStream <<
' ' << std::to_string(nextY);
221 AttributeMap geometryAttributeMap{{
"d", pathStream.str()}};
240 B2WARNING(
"Mismatching calls to startGroup and endGroup detected. "
241 <<
"Proceeding to write the illforamed result.");
247 std::ofstream outputFileStream;
248 outputFileStream.open(fileName);
253 {
"baseProfile",
"full"},
254 {
"ev",
"http://www.w3.org/2001/xml-events"},
256 {
"xlink",
"http://www.w3.org/1999/xlink"},
257 {
"xmlns",
"http://www.w3.org/2000/svg"}
263 std::ostringstream viewBoxStringStream;
266 viewBoxStringStream <<
" ";
268 viewBoxStringStream <<
" ";
270 viewBoxStringStream <<
" ";
276 {
"viewBox", viewBoxStringStream.str()},
281 writeOpeningTag(outputFileStream,
"svg", standardAttributeMap, variableAttributeMap);
290 outputFileStream.close();
315 outputStream <<
"<?xml version=\"1.0\" ?>" << std::endl;
316 outputStream <<
"<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>" << std::endl;
325 {
"viewBox",
"0 0 10 10"},
328 {
"markerUnits",
"strokeWidth"},
329 {
"markerWidth",
"4"},
330 {
"markerHeight",
"3"},
338 {
"points",
"0,0 10,5 0,10 1,5"},
349 const std::string& tagName,
360 writeTagIntern(outputStream, tagName, geometryAttributeMap, styleAttributeMap);
366 outputStream << std::endl;
370 if (geometryAttributeMap.count(
"_showAt") + styleAttributeMap.count(
"_showAt")) {
371 const std::string showAt = geometryAttributeMap.count(
"_showAt")
372 ? geometryAttributeMap.at(
"_showAt")
373 : styleAttributeMap.at(
"_showAt");
376 {
"attributeName",
"visibility"},
387 const std::string& tagName,
392 if (geometryAttributeMap.count(
"_showAt") + styleAttributeMap.count(
"_showAt")) {
393 writeOpeningTag(outputStream, tagName, geometryAttributeMap, styleAttributeMap);
404 writeTagIntern(outputStream, tagName, geometryAttributeMap, styleAttributeMap);
407 outputStream <<
'/' <<
'>';
410 outputStream << std::endl;
415 const std::string& tagName,
420 outputStream << tagName;
423 if (not geometryAttributeMap.empty()) {
429 if (not styleAttributeMap.empty()) {
439 for (
const std::pair<std::string, std::string> attribute : attributeMap) {
441 const std::string& key = attribute.first;
442 const std::string& value = attribute.second;
457 outputStream <<
'=' <<
'"';
458 outputStream << value;
471 outputStream <<
'<' <<
'/';
474 outputStream << tagName;
480 outputStream << std::endl;
float getBottom() const
Getter for the location of the bottom of the bounding box rectangle (lower y bound)....
float getWidth() const
Getter for the width of the bounding box rectangle.
float getLeft() const
Getter for the location of the left of the bounding box rectangle (lower x bound)....
float getHeight() const
Getter for the height of the bounding box rectangle.
A base class for plots of primitive objects.
float getCanvasWidth()
Getter for the canvas width in pixels.
virtual void drawCurve(const std::vector< std::array< float, 2 > > &points, const std::vector< std::array< float, 2 > > &tangents, const AttributeMap &attributeMap=AttributeMap())
Adds a smooth curve to the plot.
const BoundingBox & getBoundingBox() const
Getter for the bounding box of all drawn objects.
virtual void drawCircleArc(float startX, float startY, float endX, float endY, float radius, bool longArc, bool sweepFlag, const AttributeMap &attributeMap=AttributeMap())
Adds a circle arc to the plot.
virtual void drawArrow(float startX, float startY, float endX, float endY, const AttributeMap &attributeMap=AttributeMap())
Adds an arrow to the plot.
Belle2::TrackFindingCDC::AttributeMap AttributeMap
A map type for attributes names to values for additional drawing information.
float getCanvasHeight()
Getter for the canvas height in pixels.
virtual void clear()
Clears all drawn elements from the plotter.
virtual void drawLine(float startX, float startY, float endX, float endY, const AttributeMap &attributeMap=AttributeMap())
Adds a line to the plot.
virtual void drawCircle(float centerX, float centerY, float radius, const AttributeMap &attributeMap=AttributeMap())
Adds a circle to the plot.
A concrete plotter that can draw primitive objects to standalone SVG files.
void startGroup(const AttributeMap &attributeMap=AttributeMap()) override
Indicates the start of a group of drawn elements.
std::unique_ptr< PrimitivePlotter > clone() const override
Returns a newly created plotter instance containing all information of this.
void indent()
Increases the current indentation by one.
void writeAttributes(std::ostream &outputStream, const AttributeMap &attributeMap)
Writes attribute specification that belongs between the <, > brackets after the tag name.
void drawCurve(const std::vector< std::array< float, 2 > > &points, const std::vector< std::array< float, 2 > > &tangents, const AttributeMap &attributeMap=AttributeMap()) override
Adds a smooth curve to the plot.
void writeStandAloneTag(std::ostream &outputStream, const std::string &tagName, const AttributeMap &geometryAttributeMap=AttributeMap(), const AttributeMap &styleAttributeMap=AttributeMap())
Writes a stand alone xml tag to the given output stream taking attributes from two sources.
std::ostringstream m_svgContentStream
Memory for the plotted elements. This contains only the fragment that is in-between the svg tags and ...
int m_nIndentationSpaces
Memory for the number of spaces that shall be prepended to each line.
void writeSVGDefs(std::ostream &outputStream)
Writes a preamble of definitions that define an arrow cap which can be referenced by lines.
static const int s_defaultNIndentationSpaces
Constant for the number of indentation space to be used within the svg block.
AttributeMap m_svgAttributes
Memory for additional attributes to the top-level svg element.
void drawCircleArc(float startX, float startY, float endX, float endY, float radius, bool longArc, bool sweepFlag, const AttributeMap &attributeMap=AttributeMap()) override
Adds a circle arc to the plot.
void drawCircle(float centerX, float centerY, float radius, const AttributeMap &attributeMap=AttributeMap()) override
Adds a circle to the plot.
SVGPrimitivePlotter()
Default constructor for ROOT compatibility.
void writeSVGHeader(std::ostream &outputStream)
Writes the xml header that indicates that this document will be a SVG document to the given output st...
void drawLine(float startX, float startY, float endX, float endY, const AttributeMap &attributeMap=AttributeMap()) override
Adds a line to the plot.
void drawArrow(float startX, float startY, float endX, float endY, const AttributeMap &attributeMap=AttributeMap()) override
Adds an arrow to the plot.
void writeOpeningTag(std::ostream &outputStream, const std::string &tagName, const AttributeMap &geometryAttributeMap=AttributeMap(), const AttributeMap &styleAttributeMap=AttributeMap())
Writes an opening xml tag to the given output stream taking attributes from two sources.
void dedent()
Decreases the current indentation by one.
void clear() override
Clears all drawn elements from the plotter.
static const int s_addtionalNIndentationSpaces
Constant for the additional number of space to be prepended with each open tag group.
const std::string save(const std::string &fileName) override
Saves the current plot state to a file.
void writeTagIntern(std::ostream &outputStream, const std::string &tagName, const AttributeMap &geometryAttributeMap=AttributeMap(), const AttributeMap &styleAttributeMap=AttributeMap())
Writes part that belongs between the <, > brackets.
void endGroup() override
Indicates the end of a group of drawn elements.
void writeClosingTag(std::ostream &outputStream, const std::string &tagName)
Writes a closing xml tag to the given output stream.
Abstract base class for different kinds of events.