From 25bc2fb2807303005228316bd784512062c351bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=99=BD=E5=B0=81=E7=BE=BD?= <2360164671@qq.com>
Date: Tue, 11 Oct 2022 19:57:30 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E6=A4=AD=E5=9C=86?=
=?UTF-8?q?=E8=BD=AC=E6=8D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ArchitectureColoredPainting.vcxproj | 2 +-
ArchitectureColoredPainting/SvgParser.cpp | 1273 +++++++++--------
ArchitectureColoredPainting/SvgParser.h | 295 ++--
3 files changed, 881 insertions(+), 689 deletions(-)
diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
index 334afac..c8babd2 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
@@ -31,7 +31,7 @@
- 5.15.2_msvc2019_64
+ 5.15.0_msvc2019_64
core;gui;widgets
debug
diff --git a/ArchitectureColoredPainting/SvgParser.cpp b/ArchitectureColoredPainting/SvgParser.cpp
index b5b7760..bfc33e1 100644
--- a/ArchitectureColoredPainting/SvgParser.cpp
+++ b/ArchitectureColoredPainting/SvgParser.cpp
@@ -3,592 +3,751 @@
#include
using namespace std;
-namespace SVGParser {
+namespace SVGParser
+{
- SVGCommandType getSVGCommand(char c) {
- switch (c) {
- case 'm':
- return SVG_MOVE_TO_REL;
- break;
- case 'M':
- return SVG_MOVE_TO_ABS;
- break;
+SVGCommandType getSVGCommand(char c)
+{
+ switch (c)
+ {
+ case 'm':
+ return SVG_MOVE_TO_REL;
+ break;
+ case 'M':
+ return SVG_MOVE_TO_ABS;
+ break;
- case 'l':
- return SVG_LINE_TO_REL;
- break;
- case 'L':
- return SVG_LINE_TO_ABS;
- break;
+ case 'l':
+ return SVG_LINE_TO_REL;
+ break;
+ case 'L':
+ return SVG_LINE_TO_ABS;
+ break;
- case 'c':
- return SVG_CUBIC_CURVE_TO_REL;
- break;
- case 'C':
- return SVG_CUBIC_CURVE_TO_ABS;
- break;
+ case 'c':
+ return SVG_CUBIC_CURVE_TO_REL;
+ break;
+ case 'C':
+ return SVG_CUBIC_CURVE_TO_ABS;
+ break;
- case 'q':
- return SVG_QUADRATIC_CURVE_TO_REL;
- break;
- case 'Q':
- return SVG_QUADRATIC_CURVE_TO_ABS;
- break;
+ case 'q':
+ return SVG_QUADRATIC_CURVE_TO_REL;
+ break;
+ case 'Q':
+ return SVG_QUADRATIC_CURVE_TO_ABS;
+ break;
- case 'a':
- return SVG_ARC_TO_REL;
- break;
- case 'A':
- return SVG_ARC_TO_ABS;
- break;
+ case 'a':
+ return SVG_ARC_TO_REL;
+ break;
+ case 'A':
+ return SVG_ARC_TO_ABS;
+ break;
- case 't':
- return SVG_SMOOTH_QUADRATIC_CURVE_TO_REL;
- break;
- case 'T':
- return SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS;
- break;
+ case 't':
+ return SVG_SMOOTH_QUADRATIC_CURVE_TO_REL;
+ break;
+ case 'T':
+ return SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS;
+ break;
- case 's':
- return SVG_SMOOTH_CUBIC_CURVE_TO_REL;
- break;
- case 'S':
- return SVG_SMOOTH_CUBIC_CURVE_TO_ABS;
- break;
+ case 's':
+ return SVG_SMOOTH_CUBIC_CURVE_TO_REL;
+ break;
+ case 'S':
+ return SVG_SMOOTH_CUBIC_CURVE_TO_ABS;
+ break;
- case 'h':
- return SVG_HORIZONTAL_LINE_TO_REL;
- break;
- case 'H':
- return SVG_HORIZONTAL_LINE_TO_ABS;
- break;
+ case 'h':
+ return SVG_HORIZONTAL_LINE_TO_REL;
+ break;
+ case 'H':
+ return SVG_HORIZONTAL_LINE_TO_ABS;
+ break;
- case 'v':
- return SVG_VERTICAL_LINE_TO_REL;
- break;
- case 'V':
- return SVG_VERTICAL_LINE_TO_ABS;
- break;
-
- case 'z':
- case 'Z':
- return SVG_CLOSE_PATH;
- break;
- default:
- return SVG_INVALID;
- break;
- }
- };
- int getCommandLength(SVGCommandType t) {
- switch (t) {
- case SVG_MOVE_TO_REL:
- case SVG_LINE_TO_REL:
- case SVG_MOVE_TO_ABS:
- case SVG_LINE_TO_ABS:
- return 2;
- break;
- case SVG_HORIZONTAL_LINE_TO_REL:
- case SVG_HORIZONTAL_LINE_TO_ABS:
- case SVG_VERTICAL_LINE_TO_REL:
- case SVG_VERTICAL_LINE_TO_ABS:
- return 1;
- break;
-
-
- case SVG_QUADRATIC_CURVE_TO_REL:
- case SVG_QUADRATIC_CURVE_TO_ABS:
- return 4;
- break;
- case SVG_CUBIC_CURVE_TO_REL:
- case SVG_CUBIC_CURVE_TO_ABS:
- return 6;
- break;
-
- case SVG_SMOOTH_CUBIC_CURVE_TO_REL:
- case SVG_SMOOTH_CUBIC_CURVE_TO_ABS:
- return 4;
- break;
-
- case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL:
- case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS:
- return 2;
- break;
-
- case SVG_ARC_TO_REL:
- case SVG_ARC_TO_ABS:
- return 7;
- break;
- case SVG_CLOSE_PATH:
- case SVG_INVALID:
- default:
- return 0;
- break;
- }
- };
- bool isAbsolute(SVGCommandType t) {
- if (t == SVG_CLOSE_PATH) return false;
- return t % 2;
- }
- SVGPath createCommandChunk(SVGCommandType t, vector elements) {
- int commandLength = getCommandLength(t);
- SVGPath chunk;
- bool abs = isAbsolute(t);
- if (t == SVG_CLOSE_PATH) chunk.push_back(make_shared());
- if (commandLength > 0)
- for (int i = 0; i < int(elements.size() / commandLength); i++) {
- switch (t) {
- case SVG_LINE_TO_REL:
- case SVG_LINE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
- break;
- case SVG_MOVE_TO_REL:
- case SVG_MOVE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
- break;
- case SVG_CUBIC_CURVE_TO_REL:
- case SVG_CUBIC_CURVE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1],
- elements[i * commandLength + 2], elements[i * commandLength + 3],
- elements[i * commandLength + 4], elements[i * commandLength + 5], abs));
- break;
-
- case SVG_SMOOTH_CUBIC_CURVE_TO_REL:
- case SVG_SMOOTH_CUBIC_CURVE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1],
- elements[i * commandLength + 2], elements[i * commandLength + 3], abs));
- break;
-
- case SVG_QUADRATIC_CURVE_TO_REL:
- case SVG_QUADRATIC_CURVE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1],
- elements[i * commandLength + 2], elements[i * commandLength + 3], abs));
- break;
-
- case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL:
- case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
- break;
-
- case SVG_ARC_TO_REL:
- case SVG_ARC_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1],//rx, ry
- elements[i * commandLength + 2],//rotation,
- int(elements[i * commandLength + 3]) == 1, int(elements[i * commandLength + 4]) == 1, //large arc, sweep
- elements[i * commandLength + 5], elements[i * commandLength + 6], //end x, end y
- abs));
- break;
- case SVG_HORIZONTAL_LINE_TO_REL:
- case SVG_HORIZONTAL_LINE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], abs));
- break;
- case SVG_VERTICAL_LINE_TO_REL:
- case SVG_VERTICAL_LINE_TO_ABS:
- chunk.push_back(make_shared(elements[i * commandLength + 0], abs));
- break;
- }
- //This here is funky.
- if (t == SVG_MOVE_TO_REL || t == SVG_MOVE_TO_ABS) t = SVGCommandType(int(t) + 2);
- }
- return chunk;
- }
- SVGPath parsePath(istream& ss) {
- SVGPath commandArray;
- //istringstream ss(path);
- //bool absolute = false;
- SVGCommandType command = SVG_INVALID;
- vector elements;
-
- while (ss.good()) {
- char c = ss.get();
- SVGCommandType cmd = getSVGCommand(c);
-
- if (cmd != SVG_INVALID) {
- SVGPath chunk = createCommandChunk(command, elements);
- commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
- command = cmd;
- elements.clear();
-
- }
- else if (!(isspace(c) || c == ',')) {//its a number...
- double x;
- ss.unget();
- ss >> x;
- elements.push_back(x);
- }// else its a separator
- }
- SVGPath chunk = createCommandChunk(command, elements);
- commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
- return commandArray;
- }
-
- SVGCommand::SVGCommand(double _x, double _y, bool abs) : x(_x), y(_y), absolute(abs) {}
- SVGLineTo::SVGLineTo(double x, double y, bool abs) : SVGCommand(x, y, abs) {
- }
-
- const string SVGLineTo::toString() const {
- stringstream s;
- s << (absolute ? "L" : "l") << x << "," << y;
- return s.str();
- }
- string SVGLineTo::toString2() {
- stringstream s;
- s << "Line to (" << (absolute ? "absolute" : "relative") << ") " << x << "x" << y;
- return s.str();
- }
-
- SVGCommandType SVGLineTo::getType() {
- return absolute ? SVG_LINE_TO_ABS : SVG_LINE_TO_REL;
- }
-
- SVGHLineTo::SVGHLineTo(double x, bool abs) : SVGCommand(x, 0, abs) {
- }
- const string SVGHLineTo::toString() const {
- stringstream s;
- s << (absolute ? "H" : "h") << x;
- return s.str();
- }
- string SVGHLineTo::toString2() {
- stringstream s;
- s << "Horizontal Line (" << (absolute ? "absolute" : "relative") << ") " << x << "px";
- return s.str();
- }
-
- SVGCommandType SVGHLineTo::getType() {
- return absolute ? SVG_HORIZONTAL_LINE_TO_ABS : SVG_HORIZONTAL_LINE_TO_REL;
- }
-
- SVGVLineTo::SVGVLineTo(double y, bool abs) : SVGCommand(0, y, abs) {
- }
-
- const string SVGVLineTo::toString() const {
- stringstream s;
- s << (absolute ? "V" : "v") << y;
- return s.str();
- }
- string SVGVLineTo::toString2() {
- stringstream s;
- s << "Vertical Line (" << (absolute ? "absolute" : "relative") << ") " << y << "px";
- return s.str();
- }
- SVGCommandType SVGVLineTo::getType() {
- return absolute ? SVG_VERTICAL_LINE_TO_ABS : SVG_VERTICAL_LINE_TO_REL;
- }
-
-
-
-
- SVGMoveTo::SVGMoveTo(double x, double y, bool abs) : SVGCommand(x, y, abs) {
- }
- const string SVGMoveTo::toString() const {
- stringstream s;
- s << (absolute ? "M" : "m") << x << "," << y;
- return s.str();
- }
- string SVGMoveTo::toString2() {
- stringstream s;
- s << "Move to (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
- return s.str();
- }
- SVGCommandType SVGMoveTo::getType() {
- return absolute ? SVG_MOVE_TO_ABS : SVG_MOVE_TO_REL;
- }
-
-
- SVGCubicCurveTo::SVGCubicCurveTo(double _x0, double _y0,
- double _x1, double _y1,
- double x, double y, bool abs) : SVGCommand(x, y, abs),
- x0(_x0), y0(_y0),
- x1(_x1), y1(_y1) {
- }
-
- const string SVGCubicCurveTo::toString() const {
- stringstream s;
- s << (absolute ? "C" : "c") << x0 << "," << y0 << " " << x1 << "," << y1 << " " << x << "," << y;
- return s.str();
- }
- string SVGCubicCurveTo::toString2() {
- stringstream s;
- s << "Cubic Curve (" << (absolute ? "absolute" : "relative") << ") control points: " << x0 << "," << y0 << " " << x1 << "," << y1 << " to " << x << "x" << y;
- return s.str();
- }
- SVGCommandType SVGCubicCurveTo::getType() {
- return absolute ? SVG_CUBIC_CURVE_TO_ABS : SVG_CUBIC_CURVE_TO_REL;
- }
-
- SVGSmoothCubicCurveTo::SVGSmoothCubicCurveTo(
- double _x1, double _y1,
- double x, double y, bool abs) : SVGCommand(x, y, abs),
- x1(_x1), y1(_y1) {
- }
-
- const string SVGSmoothCubicCurveTo::toString() const {
- stringstream s;
- s << (absolute ? "S" : "s") << x1 << "," << y1 << " " << x << "," << y;
- return s.str();
- }
- string SVGSmoothCubicCurveTo::toString2() {
- stringstream s;
- s << "Smooth cubic curve to (" << (absolute ? "absolute" : "relative") << ") control point: " << x1 << "," << y1 << " to " << x << "x" << y;
- return s.str();
- }
- SVGCommandType SVGSmoothCubicCurveTo::getType() {
- return absolute ? SVG_SMOOTH_CUBIC_CURVE_TO_ABS : SVG_SMOOTH_CUBIC_CURVE_TO_REL;
- }
-
-
- SVGQuadraticCurveTo::SVGQuadraticCurveTo(double _x0, double _y0,
- double x, double y, bool abs) : SVGCommand(x, y, abs), x0(_x0), y0(_y0) {
- }
- const string SVGQuadraticCurveTo::toString() const {
- stringstream s;
- s << (absolute ? "Q" : "q") << x0 << "," << y0 << " " << x << "," << y;
- return s.str();
- }
- string SVGQuadraticCurveTo::toString2() {
- stringstream s;
- s << "quadratic curve (" << (absolute ? "absolute" : "relative") << ") control point: " << x0 << "," << y0 << " to " << x << "x" << y;
- return s.str();
- }
- SVGCommandType SVGQuadraticCurveTo::getType() {
- return absolute ? SVG_QUADRATIC_CURVE_TO_ABS : SVG_QUADRATIC_CURVE_TO_REL;
- }
- SVGSmoothQuadraticCurveTo::SVGSmoothQuadraticCurveTo(
- double x, double y, bool abs) : SVGCommand(x, y, abs) {
- }
- const string SVGSmoothQuadraticCurveTo::toString() const {
- stringstream s;
- s << (absolute ? "T" : "t") << x << "," << y;
- return s.str();
- }
- string SVGSmoothQuadraticCurveTo::toString2() {
- stringstream s;
- s << "Smooth quadratic curve (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
- return s.str();
- }
- SVGCommandType SVGSmoothQuadraticCurveTo::getType() {
- return absolute ? SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS : SVG_SMOOTH_QUADRATIC_CURVE_TO_REL;
- }
-
- SVGArcTo::SVGArcTo(double rx, double ry, double rotxaxis, bool large, bool sweep, double x, double y, bool abs) : SVGCommand(x, y, abs) {
- this->rx = rx;
- this->ry = ry;
-
- this->rot = rotxaxis;
-
- this->large = large;
- this->sweep = sweep;
- }
- const string SVGArcTo::toString() const {
- stringstream s;
- s << (absolute ? "A" : "a") << rx << "," << ry << " " << rot << " " << large << "," << sweep << " " << x << "," << y;
- return s.str();
- }
-
- string SVGArcTo::toString2() {
- stringstream s;
- s << "Arc (" << (absolute ? "absolute" : "relative") << "x-radii: " << rx << " y-radii: " << ry << " x-rotation: " << rot << " large-arc: " << large << " sweep: " << sweep << " to: " << x << "x" << y;
- return s.str();
- }
-
- SVGCommandType SVGArcTo::getType() {
- return absolute ? SVG_ARC_TO_ABS : SVG_ARC_TO_REL;
- }
-
- SVGClosePath::SVGClosePath(bool abs) :SVGCommand(0, 0, abs) {
-
- }
-
- const string SVGClosePath::toString() const {
- stringstream s;
- s << (absolute ? "Z" : "z");
- return s.str();
- }
- string SVGClosePath::toString2() {
- stringstream s;
- s << "Close path";
- return s.str();
- }
- SVGCommandType SVGClosePath::getType() {
- return SVG_CLOSE_PATH;
- }
- std::ostream& operator<< (std::ostream& out, const SVGParser::SVGPath& path) {
- for (SVGParser::SVGPath::const_iterator it = path.begin(); it != path.end(); it++) {
- out << (*it)->toString();
- }
- return out;
- }
- std::ostream& operator<< (std::ostream& out, const SVGParser::SVGCommand* cmd) {
- out << cmd->toString();
- return out;
- }
+ case 'v':
+ return SVG_VERTICAL_LINE_TO_REL;
+ break;
+ case 'V':
+ return SVG_VERTICAL_LINE_TO_ABS;
+ break;
+ case 'z':
+ case 'Z':
+ return SVG_CLOSE_PATH;
+ break;
+ default:
+ return SVG_INVALID;
+ break;
+ }
};
+int getCommandLength(SVGCommandType t)
+{
+ switch (t)
+ {
+ case SVG_MOVE_TO_REL:
+ case SVG_LINE_TO_REL:
+ case SVG_MOVE_TO_ABS:
+ case SVG_LINE_TO_ABS:
+ return 2;
+ break;
+ case SVG_HORIZONTAL_LINE_TO_REL:
+ case SVG_HORIZONTAL_LINE_TO_ABS:
+ case SVG_VERTICAL_LINE_TO_REL:
+ case SVG_VERTICAL_LINE_TO_ABS:
+ return 1;
+ break;
-SvgParser::SvgParser(const std::string path, double width, double height) :path(path), width(width), height(height)
+ case SVG_QUADRATIC_CURVE_TO_REL:
+ case SVG_QUADRATIC_CURVE_TO_ABS:
+ return 4;
+ break;
+ case SVG_CUBIC_CURVE_TO_REL:
+ case SVG_CUBIC_CURVE_TO_ABS:
+ return 6;
+ break;
+
+ case SVG_SMOOTH_CUBIC_CURVE_TO_REL:
+ case SVG_SMOOTH_CUBIC_CURVE_TO_ABS:
+ return 4;
+ break;
+
+ case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL:
+ case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS:
+ return 2;
+ break;
+
+ case SVG_ARC_TO_REL:
+ case SVG_ARC_TO_ABS:
+ return 7;
+ break;
+ case SVG_CLOSE_PATH:
+ case SVG_INVALID:
+ default:
+ return 0;
+ break;
+ }
+};
+bool isAbsolute(SVGCommandType t)
+{
+ if (t == SVG_CLOSE_PATH)
+ return false;
+ return t % 2;
+}
+SVGPath createCommandChunk(SVGCommandType t, vector elements)
+{
+ int commandLength = getCommandLength(t);
+ SVGPath chunk;
+ bool abs = isAbsolute(t);
+ if (t == SVG_CLOSE_PATH)
+ chunk.push_back(make_shared());
+ if (commandLength > 0)
+ for (int i = 0; i < int(elements.size() / commandLength); i++)
+ {
+ switch (t)
+ {
+ case SVG_LINE_TO_REL:
+ case SVG_LINE_TO_ABS:
+ chunk.push_back(
+ make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
+ break;
+ case SVG_MOVE_TO_REL:
+ case SVG_MOVE_TO_ABS:
+ chunk.push_back(
+ make_shared(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
+ break;
+ case SVG_CUBIC_CURVE_TO_REL:
+ case SVG_CUBIC_CURVE_TO_ABS:
+ chunk.push_back(make_shared(
+ elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2],
+ elements[i * commandLength + 3], elements[i * commandLength + 4], elements[i * commandLength + 5],
+ abs));
+ break;
+
+ case SVG_SMOOTH_CUBIC_CURVE_TO_REL:
+ case SVG_SMOOTH_CUBIC_CURVE_TO_ABS:
+ chunk.push_back(make_shared(
+ elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2],
+ elements[i * commandLength + 3], abs));
+ break;
+
+ case SVG_QUADRATIC_CURVE_TO_REL:
+ case SVG_QUADRATIC_CURVE_TO_ABS:
+ chunk.push_back(make_shared(
+ elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2],
+ elements[i * commandLength + 3], abs));
+ break;
+
+ case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL:
+ case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS:
+ chunk.push_back(make_shared(elements[i * commandLength + 0],
+ elements[i * commandLength + 1], abs));
+ break;
+
+ case SVG_ARC_TO_REL:
+ case SVG_ARC_TO_ABS:
+ chunk.push_back(make_shared(
+ elements[i * commandLength + 0], elements[i * commandLength + 1], // rx, ry
+ elements[i * commandLength + 2], // rotation,
+ int(elements[i * commandLength + 3]) == 1,
+ int(elements[i * commandLength + 4]) == 1, // large arc, sweep
+ elements[i * commandLength + 5], elements[i * commandLength + 6], // end x, end y
+ abs));
+ break;
+ case SVG_HORIZONTAL_LINE_TO_REL:
+ case SVG_HORIZONTAL_LINE_TO_ABS:
+ chunk.push_back(make_shared(elements[i * commandLength + 0], abs));
+ break;
+ case SVG_VERTICAL_LINE_TO_REL:
+ case SVG_VERTICAL_LINE_TO_ABS:
+ chunk.push_back(make_shared(elements[i * commandLength + 0], abs));
+ break;
+ }
+ // This here is funky.
+ if (t == SVG_MOVE_TO_REL || t == SVG_MOVE_TO_ABS)
+ t = SVGCommandType(int(t) + 2);
+ }
+ return chunk;
+}
+SVGPath parsePath(istream &ss)
+{
+ SVGPath commandArray;
+ // istringstream ss(path);
+ // bool absolute = false;
+ SVGCommandType command = SVG_INVALID;
+ vector elements;
+
+ while (ss.good())
+ {
+ char c = ss.get();
+ SVGCommandType cmd = getSVGCommand(c);
+
+ if (cmd != SVG_INVALID)
+ {
+ SVGPath chunk = createCommandChunk(command, elements);
+ commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
+ command = cmd;
+ elements.clear();
+ }
+ else if (!(isspace(c) || c == ','))
+ { // its a number...
+ double x;
+ ss.unget();
+ ss >> x;
+ elements.push_back(x);
+ } // else its a separator
+ }
+ SVGPath chunk = createCommandChunk(command, elements);
+ commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
+ return commandArray;
+}
+
+SVGCommand::SVGCommand(double _x, double _y, bool abs) : x(_x), y(_y), absolute(abs)
+{
+}
+SVGLineTo::SVGLineTo(double x, double y, bool abs) : SVGCommand(x, y, abs)
+{
+}
+
+const string SVGLineTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "L" : "l") << x << "," << y;
+ return s.str();
+}
+string SVGLineTo::toString2()
+{
+ stringstream s;
+ s << "Line to (" << (absolute ? "absolute" : "relative") << ") " << x << "x" << y;
+ return s.str();
+}
+
+SVGCommandType SVGLineTo::getType()
+{
+ return absolute ? SVG_LINE_TO_ABS : SVG_LINE_TO_REL;
+}
+
+SVGHLineTo::SVGHLineTo(double x, bool abs) : SVGCommand(x, 0, abs)
+{
+}
+const string SVGHLineTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "H" : "h") << x;
+ return s.str();
+}
+string SVGHLineTo::toString2()
+{
+ stringstream s;
+ s << "Horizontal Line (" << (absolute ? "absolute" : "relative") << ") " << x << "px";
+ return s.str();
+}
+
+SVGCommandType SVGHLineTo::getType()
+{
+ return absolute ? SVG_HORIZONTAL_LINE_TO_ABS : SVG_HORIZONTAL_LINE_TO_REL;
+}
+
+SVGVLineTo::SVGVLineTo(double y, bool abs) : SVGCommand(0, y, abs)
+{
+}
+
+const string SVGVLineTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "V" : "v") << y;
+ return s.str();
+}
+string SVGVLineTo::toString2()
+{
+ stringstream s;
+ s << "Vertical Line (" << (absolute ? "absolute" : "relative") << ") " << y << "px";
+ return s.str();
+}
+SVGCommandType SVGVLineTo::getType()
+{
+ return absolute ? SVG_VERTICAL_LINE_TO_ABS : SVG_VERTICAL_LINE_TO_REL;
+}
+
+SVGMoveTo::SVGMoveTo(double x, double y, bool abs) : SVGCommand(x, y, abs)
+{
+}
+const string SVGMoveTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "M" : "m") << x << "," << y;
+ return s.str();
+}
+string SVGMoveTo::toString2()
+{
+ stringstream s;
+ s << "Move to (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
+ return s.str();
+}
+SVGCommandType SVGMoveTo::getType()
+{
+ return absolute ? SVG_MOVE_TO_ABS : SVG_MOVE_TO_REL;
+}
+
+SVGCubicCurveTo::SVGCubicCurveTo(double _x0, double _y0, double _x1, double _y1, double x, double y, bool abs)
+ : SVGCommand(x, y, abs), x0(_x0), y0(_y0), x1(_x1), y1(_y1)
+{
+}
+
+const string SVGCubicCurveTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "C" : "c") << x0 << "," << y0 << " " << x1 << "," << y1 << " " << x << "," << y;
+ return s.str();
+}
+string SVGCubicCurveTo::toString2()
+{
+ stringstream s;
+ s << "Cubic Curve (" << (absolute ? "absolute" : "relative") << ") control points: " << x0 << "," << y0 << " " << x1
+ << "," << y1 << " to " << x << "x" << y;
+ return s.str();
+}
+SVGCommandType SVGCubicCurveTo::getType()
+{
+ return absolute ? SVG_CUBIC_CURVE_TO_ABS : SVG_CUBIC_CURVE_TO_REL;
+}
+
+SVGSmoothCubicCurveTo::SVGSmoothCubicCurveTo(double _x1, double _y1, double x, double y, bool abs)
+ : SVGCommand(x, y, abs), x1(_x1), y1(_y1)
+{
+}
+
+const string SVGSmoothCubicCurveTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "S" : "s") << x1 << "," << y1 << " " << x << "," << y;
+ return s.str();
+}
+string SVGSmoothCubicCurveTo::toString2()
+{
+ stringstream s;
+ s << "Smooth cubic curve to (" << (absolute ? "absolute" : "relative") << ") control point: " << x1 << "," << y1
+ << " to " << x << "x" << y;
+ return s.str();
+}
+SVGCommandType SVGSmoothCubicCurveTo::getType()
+{
+ return absolute ? SVG_SMOOTH_CUBIC_CURVE_TO_ABS : SVG_SMOOTH_CUBIC_CURVE_TO_REL;
+}
+
+SVGQuadraticCurveTo::SVGQuadraticCurveTo(double _x0, double _y0, double x, double y, bool abs)
+ : SVGCommand(x, y, abs), x0(_x0), y0(_y0)
+{
+}
+const string SVGQuadraticCurveTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "Q" : "q") << x0 << "," << y0 << " " << x << "," << y;
+ return s.str();
+}
+string SVGQuadraticCurveTo::toString2()
+{
+ stringstream s;
+ s << "quadratic curve (" << (absolute ? "absolute" : "relative") << ") control point: " << x0 << "," << y0 << " to "
+ << x << "x" << y;
+ return s.str();
+}
+SVGCommandType SVGQuadraticCurveTo::getType()
+{
+ return absolute ? SVG_QUADRATIC_CURVE_TO_ABS : SVG_QUADRATIC_CURVE_TO_REL;
+}
+SVGSmoothQuadraticCurveTo::SVGSmoothQuadraticCurveTo(double x, double y, bool abs) : SVGCommand(x, y, abs)
+{
+}
+const string SVGSmoothQuadraticCurveTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "T" : "t") << x << "," << y;
+ return s.str();
+}
+string SVGSmoothQuadraticCurveTo::toString2()
+{
+ stringstream s;
+ s << "Smooth quadratic curve (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
+ return s.str();
+}
+SVGCommandType SVGSmoothQuadraticCurveTo::getType()
+{
+ return absolute ? SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS : SVG_SMOOTH_QUADRATIC_CURVE_TO_REL;
+}
+
+SVGArcTo::SVGArcTo(double rx, double ry, double rotxaxis, bool large, bool sweep, double x, double y, bool abs)
+ : SVGCommand(x, y, abs)
+{
+ this->rx = rx;
+ this->ry = ry;
+
+ this->rot = rotxaxis;
+
+ this->large = large;
+ this->sweep = sweep;
+}
+const string SVGArcTo::toString() const
+{
+ stringstream s;
+ s << (absolute ? "A" : "a") << rx << "," << ry << " " << rot << " " << large << "," << sweep << " " << x << ","
+ << y;
+ return s.str();
+}
+
+string SVGArcTo::toString2()
+{
+ stringstream s;
+ s << "Arc (" << (absolute ? "absolute" : "relative") << "x-radii: " << rx << " y-radii: " << ry
+ << " x-rotation: " << rot << " large-arc: " << large << " sweep: " << sweep << " to: " << x << "x" << y;
+ return s.str();
+}
+
+SVGCommandType SVGArcTo::getType()
+{
+ return absolute ? SVG_ARC_TO_ABS : SVG_ARC_TO_REL;
+}
+
+SVGClosePath::SVGClosePath(bool abs) : SVGCommand(0, 0, abs)
+{
+}
+
+const string SVGClosePath::toString() const
+{
+ stringstream s;
+ s << (absolute ? "Z" : "z");
+ return s.str();
+}
+string SVGClosePath::toString2()
+{
+ stringstream s;
+ s << "Close path";
+ return s.str();
+}
+SVGCommandType SVGClosePath::getType()
+{
+ return SVG_CLOSE_PATH;
+}
+std::ostream &operator<<(std::ostream &out, const SVGParser::SVGPath &path)
+{
+ for (SVGParser::SVGPath::const_iterator it = path.begin(); it != path.end(); it++)
+ {
+ out << (*it)->toString();
+ }
+ return out;
+}
+std::ostream &operator<<(std::ostream &out, const SVGParser::SVGCommand *cmd)
+{
+ out << cmd->toString();
+ return out;
+}
+
+}; // namespace SVGParser
+
+SvgParser::SvgParser(const std::string path, double width, double height) : path(path), width(width), height(height)
{
}
Point SvgParser::convertPoint(double x, double y)
{
- return Point{ x / width * 2. - 1. , 1. - y / height * 2. };
+ return Point{x / width * 2. - 1., 1. - y / height * 2.};
}
Point SvgParser::clampPoint(Point p)
{
- return Point{ std::clamp(p.x, -1., 1.) , std::clamp(p.y , -1., 1.) };
+ return Point{std::clamp(p.x, -1., 1.), std::clamp(p.y, -1., 1.)};
}
Point SvgParser::convertAbsPoint(double x, double y)
{
- return clampPoint(convertPoint(x, y));
+ return clampPoint(convertPoint(x, y));
}
Point SvgParser::convertRelPoint(Point pointBegin, double x, double y)
{
- return clampPoint(pointBegin + Point{ x / width * 2. , - y / height * 2. });
+ return clampPoint(pointBegin + Point{x / width * 2., -y / height * 2.});
}
using namespace SVGParser;
vector> SvgParser::parse()
{
- vector line;
- vector> lines;
+ vector line;
+ vector> lines;
- istringstream stringStream(path);
- SVGPath svgPath = parsePath(stringStream);
- for (shared_ptr svgCmd : svgPath)
- {
- switch (svgCmd->getType())
- {
- case SVG_MOVE_TO_ABS:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertAbsPoint(cmd->x, cmd->y));
- break;
- }
- case SVG_LINE_TO_REL:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertRelPoint(line.back(), cmd->x, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_LINE_TO_ABS:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertAbsPoint(cmd->x, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_HORIZONTAL_LINE_TO_REL:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertRelPoint(line.back(), cmd->x, 0));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_HORIZONTAL_LINE_TO_ABS:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertAbsPoint(cmd->x, line.back().y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_VERTICAL_LINE_TO_REL:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertRelPoint(line.back(), 0, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_VERTICAL_LINE_TO_ABS:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertAbsPoint(line.back().x, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_QUADRATIC_CURVE_TO_REL:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- Point pointBegin = line.back();
- Point pointControl = convertRelPoint(pointBegin, cmd->x0, cmd->y0);
- Point pointEnd = convertRelPoint(pointBegin, cmd->x, cmd->y);
- line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.));
- line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.));
- line.push_back(pointEnd);
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_QUADRATIC_CURVE_TO_ABS:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- Point pointBegin = line.back();
- Point pointControl = convertAbsPoint(cmd->x0, cmd->y0);
- Point pointEnd = convertAbsPoint(cmd->x, cmd->y);
- line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.));
- line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.));
- line.push_back(pointEnd);
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_CUBIC_CURVE_TO_REL:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- Point pointBegin = line.back();
- line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0));
- line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1));
- line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_CUBIC_CURVE_TO_ABS:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertAbsPoint(cmd->x0, cmd->y0));
- line.push_back(convertAbsPoint(cmd->x1, cmd->y1));
- line.push_back(convertAbsPoint(cmd->x, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- /*case SVG_ARC_TO_REL:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- Point pointBegin = line.back();
- line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0));
- line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1));
- line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }
- case SVG_ARC_TO_ABS:
- {
- shared_ptr cmd = static_pointer_cast(svgCmd);
- line.push_back(convertAbsPoint(cmd->x0, cmd->y0));
- line.push_back(convertAbsPoint(cmd->x1, cmd->y1));
- line.push_back(convertAbsPoint(cmd->x, cmd->y));
- lines.push_back(line);
- line.erase(line.begin(), line.end() - 1);
- break;
- }*/
- case SVG_CLOSE_PATH:
- {
- line.push_back(lines[0][0]);
- lines.push_back(line);
- break;
- }
- default:
- cout << "PARSE ERROR" << endl;
- break;
- }
- }
- return lines;
+ istringstream stringStream(path);
+ SVGPath svgPath = parsePath(stringStream);
+ for (shared_ptr svgCmd : svgPath)
+ {
+ switch (svgCmd->getType())
+ {
+ case SVG_MOVE_TO_ABS: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertAbsPoint(cmd->x, cmd->y));
+ break;
+ }
+ case SVG_LINE_TO_REL: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertRelPoint(line.back(), cmd->x, cmd->y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_LINE_TO_ABS: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertAbsPoint(cmd->x, cmd->y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_HORIZONTAL_LINE_TO_REL: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertRelPoint(line.back(), cmd->x, 0));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_HORIZONTAL_LINE_TO_ABS: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertAbsPoint(cmd->x, line.back().y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_VERTICAL_LINE_TO_REL: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertRelPoint(line.back(), 0, cmd->y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_VERTICAL_LINE_TO_ABS: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertAbsPoint(line.back().x, cmd->y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_QUADRATIC_CURVE_TO_REL: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ Point pointBegin = line.back();
+ Point pointControl = convertRelPoint(pointBegin, cmd->x0, cmd->y0);
+ Point pointEnd = convertRelPoint(pointBegin, cmd->x, cmd->y);
+ line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.));
+ line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.));
+ line.push_back(pointEnd);
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_QUADRATIC_CURVE_TO_ABS: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ Point pointBegin = line.back();
+ Point pointControl = convertAbsPoint(cmd->x0, cmd->y0);
+ Point pointEnd = convertAbsPoint(cmd->x, cmd->y);
+ line.push_back(pointBegin + (pointControl - pointBegin) * (2. / 3.));
+ line.push_back(pointEnd + (pointControl - pointEnd) * (2. / 3.));
+ line.push_back(pointEnd);
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_CUBIC_CURVE_TO_REL: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ Point pointBegin = line.back();
+ line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0));
+ line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1));
+ line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ case SVG_CUBIC_CURVE_TO_ABS: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ line.push_back(convertAbsPoint(cmd->x0, cmd->y0));
+ line.push_back(convertAbsPoint(cmd->x1, cmd->y1));
+ line.push_back(convertAbsPoint(cmd->x, cmd->y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }
+ /*case SVG_ARC_TO_REL:
+ {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ Point pointBegin = line.back();
+ line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0));
+ line.push_back(convertRelPoint(pointBegin, cmd->x1, cmd->y1));
+ line.push_back(convertRelPoint(pointBegin, cmd->x, cmd->y));
+ lines.push_back(line);
+ line.erase(line.begin(), line.end() - 1);
+ break;
+ }*/
+ case SVG_ARC_TO_ABS: {
+ shared_ptr cmd = static_pointer_cast(svgCmd);
+ ellipticalArcConverter(line.back(), cmd->rx, cmd->ry, cmd->rot, cmd->large, cmd->sweep,
+ convertAbsPoint(cmd->x, cmd->y), lines);
+ break;
+ }
+ case SVG_CLOSE_PATH: {
+ line.push_back(lines[0][0]);
+ lines.push_back(line);
+ break;
+ }
+ default:
+ cout << "PARSE ERROR" << endl;
+ break;
+ }
+ }
+ return lines;
+}
+void SvgParser::ellipticalArcConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA,
+ bool flagS, Point endPoint, vector> &lines)
+{
+ auto &start = beginPoint;
+ auto &end = endPoint;
+ if (fabs(start.x - end.x) < eps && fabs(start.y - end.y) < eps)
+ return;
+ if (fabs(radiusX) < eps || fabs(radiusY) < eps)
+ {
+ lines.emplace_back(vector{start, end});
+ return;
+ }
+ radiusX = fabs(radiusX);
+ radiusY = fabs(radiusY);
+ auto center = centerConverter(start, radiusX, radiusY, phi, flagA, flagS, end);
+ Point r{center[0], center[1]};
+ Point c{center[2], center[3]};
+ double theta_1 = center[4];
+ double deltTheta = center[5];
+ double segments = deltTheta * 4.0 / PI;
+ int n = floor(segments);
+ Point p_1 = eConverter(c, r, cos(phi), sin(phi), theta_1);
+ Point e_1_ = e2Converter(c, r, cos(phi), sin(phi), theta_1);
+ double alpha = 0.26511477349130245;
+ double t = theta_1 + PI / 4.0;
+ for (int i = 1; i <= n; i++)
+ {
+ Point p_2 = eConverter(c, r, cos(phi), sin(phi), t);
+ Point e_2_ = e2Converter(c, r, cos(phi), sin(phi), t);
+ Point q_1 = p_1 + e_1_ * alpha;
+ Point q_2 = p_2 - e_2_ * alpha;
+ lines.emplace_back(vector{p_1, q_1, q_2, p_2});
+ p_1 = p_2;
+ e_1_ = e_2_;
+ t = t + PI / 4.0;
+ }
+ if (n != ceil(segments)) {
+ double step = t - PI / 4.0;
+ double t = theta_1 + deltTheta;
+ double alpha_t = tan(step / 2.0);
+ alpha = sin(step) * (sqrt(4 + 3.0 * alpha_t * alpha_t) - 1.0) / 3.0;
+ Point p_2 = eConverter(c, r, cos(phi), sin(phi), t);
+ Point e_2_ = e2Converter(c, r, cos(phi), sin(phi), t);
+ Point q_1 = p_1 + e_1_ * alpha;
+ Point q_2 = p_2 - e_2_ * alpha;
+ lines.emplace_back(vector{p_1, q_1, q_2, p_2});
+ }
+}
+vector SvgParser::centerConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA,
+ bool flagS, Point endPoint)
+{
+ Point r{radiusX, radiusY};
+ double x_half = (beginPoint.x - endPoint.x) / 2.0;
+ double y_half = (beginPoint.y - endPoint.y) / 2.0;
+ Point r_2{radiusX * radiusX, radiusY * radiusY};
+ double x_1 = x_half * cos(phi) + y_half * sin(phi);
+ double x_12 = x_1 * x_1;
+ double y_1 = y_half * cos(phi) + x_half * sin(phi);
+ double y_12 = y_1 * y_1;
+ double c_r = x_12 / r_2.x + y_12 / r_2.y;
+ if (fabs(c_r - 1.0) > eps)
+ {
+ c_r = sqrt(c_r);
+ r = Point{r.x * c_r, r.y * c_r};
+ r_2 = Point{r.x * r.x, r.y * r.y};
+ }
+ double d_q = r_2.x * y_12 + r_2.y * x_12;
+ double p_q = (r_2.x * r_2.y - d_q) / d_q;
+ double s_c = sqrt(max(0.0, p_q));
+ if (flagA == flagS)
+ {
+ s_c *= -1.0;
+ }
+ Point c{r.x * s_c * y_1 / r.y, -r.y * s_c * x_1 / r.x};
+ double c_x = c.x * cos(phi) - c.y * sin(phi) + (beginPoint.x + endPoint.x) / 2.0;
+ double c_y = c.x * sin(phi) + c.y * cos(phi) + (beginPoint.y + endPoint.y) / 2.0;
+ Point v{(x_1 - c.x) / r.x, (y_1 - c.y) / r.y};
+ double theta_1 = angleConverter(Point{1, 0}, v);
+ double deltTheta = angleConverter(v, Point{(-x_1 - c.x) / r.x, (-y_1 - c.y) / r.y});
+ while (deltTheta - 2.0 * PI < eps)
+ deltTheta += 2.0 * PI;
+ while (deltTheta - 2.0 * PI >= eps)
+ deltTheta -= 2.0 * PI;
+ if (!flagS)
+ {
+ deltTheta -= 2.0 * PI;
+ }
+ return vector{r.x, r.y, c_x, c_y, theta_1, deltTheta};
+}
+double SvgParser::angleConverter(Point u, Point v)
+{
+ double n_u = sqrt(u.x * u.x + u.y * u.y);
+ double n_v = sqrt(v.x * v.x + v.y * v.y);
+ double a_c = (u.x * v.x + u.y * v.y) / n_u / n_v;
+ if (a_c - 1.0 > eps)
+ a_c = 1.0;
+ else if (a_c + 1.0 < eps)
+ a_c = -1.0;
+ a_c = acos(a_c);
+ if (u.x * v.y < u.y * v.x)
+ a_c = -a_c;
+ return a_c;
+}
+Point SvgParser::eConverter(Point c, Point r, double cosPhi, double sinPhi, double t)
+{
+ double a = r.x * cos(t);
+ double b = r.y * sin(t);
+ return Point{c.x + a * cosPhi - b * sinPhi, c.y + a * sinPhi - b * cosPhi};
+}
+Point SvgParser::e2Converter(Point c, Point r, double cosPhi, double sinPhi, double t)
+{
+ double a = -r.x * cos(t);
+ double b = r.y * sin(t);
+ return Point{a * cosPhi - b * sinPhi, a * sinPhi - b * cosPhi};
}
-
diff --git a/ArchitectureColoredPainting/SvgParser.h b/ArchitectureColoredPainting/SvgParser.h
index 0f6e4e6..3712027 100644
--- a/ArchitectureColoredPainting/SvgParser.h
+++ b/ArchitectureColoredPainting/SvgParser.h
@@ -1,140 +1,173 @@
#pragma once
-#include
#include "Line.h"
-namespace SVGParser {
- enum SVGCommandType {
- SVG_INVALID = -1,
- //SVG_MOVE_TO_REL, SVG_LINE_TO_REL, SVG_QUADRATIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_REL,
- //SVG_MOVE_TO_ABS, SVG_LINE_TO_ABS, SVG_QUADRATIC_CURVE_TO_ABS, SVG_CUBIC_CURVE_TO_ABS,
- SVG_MOVE_TO_REL, SVG_MOVE_TO_ABS,
- SVG_LINE_TO_REL, SVG_LINE_TO_ABS,
- SVG_HORIZONTAL_LINE_TO_REL, SVG_HORIZONTAL_LINE_TO_ABS,
- SVG_VERTICAL_LINE_TO_REL, SVG_VERTICAL_LINE_TO_ABS,
- SVG_QUADRATIC_CURVE_TO_REL, SVG_QUADRATIC_CURVE_TO_ABS,
- SVG_CUBIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_ABS,
- SVG_SMOOTH_CUBIC_CURVE_TO_REL, SVG_SMOOTH_CUBIC_CURVE_TO_ABS,
- SVG_SMOOTH_QUADRATIC_CURVE_TO_REL, SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS,
- SVG_ARC_TO_REL, SVG_ARC_TO_ABS,
+#include
+#include
+using namespace std;
+namespace SVGParser
+{
+enum SVGCommandType
+{
+ SVG_INVALID = -1,
+ // SVG_MOVE_TO_REL, SVG_LINE_TO_REL, SVG_QUADRATIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_REL,
+ // SVG_MOVE_TO_ABS, SVG_LINE_TO_ABS, SVG_QUADRATIC_CURVE_TO_ABS, SVG_CUBIC_CURVE_TO_ABS,
+ SVG_MOVE_TO_REL,
+ SVG_MOVE_TO_ABS,
+ SVG_LINE_TO_REL,
+ SVG_LINE_TO_ABS,
+ SVG_HORIZONTAL_LINE_TO_REL,
+ SVG_HORIZONTAL_LINE_TO_ABS,
+ SVG_VERTICAL_LINE_TO_REL,
+ SVG_VERTICAL_LINE_TO_ABS,
+ SVG_QUADRATIC_CURVE_TO_REL,
+ SVG_QUADRATIC_CURVE_TO_ABS,
+ SVG_CUBIC_CURVE_TO_REL,
+ SVG_CUBIC_CURVE_TO_ABS,
+ SVG_SMOOTH_CUBIC_CURVE_TO_REL,
+ SVG_SMOOTH_CUBIC_CURVE_TO_ABS,
+ SVG_SMOOTH_QUADRATIC_CURVE_TO_REL,
+ SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS,
+ SVG_ARC_TO_REL,
+ SVG_ARC_TO_ABS,
- SVG_CLOSE_PATH
- };
-
- bool isAbsolute(SVGCommandType);
- class SVGCommand {
- public:
- SVGCommand(double, double, bool = false);
- static const int length;
- double x, y;
- bool absolute;
- virtual const std::string toString() const = 0;
- virtual SVGCommandType getType() = 0;
- virtual std::string toString2() = 0;
- };
- class SVGMoveTo : public SVGCommand {
- public:
- static const int length = 2;
- SVGMoveTo(double, double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
-
- class SVGLineTo : public SVGCommand {
- public:
- static const int length = 2;
- SVGLineTo(double, double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
- class SVGHLineTo : public SVGCommand {
- public:
- static const int length = 1;
- SVGHLineTo(double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
- class SVGVLineTo : public SVGCommand {
- public:
- static const int length = 1;
- SVGVLineTo(double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
-
- class SVGQuadraticCurveTo : public SVGCommand {
- public:
- SVGQuadraticCurveTo(double, double, double, double, bool = false);
- double x0, y0;
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
-
- class SVGCubicCurveTo : public SVGCommand {
- public:
- double x0, y0, x1, y1;
- SVGCubicCurveTo(double, double, double, double, double, double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
- class SVGSmoothQuadraticCurveTo : public SVGCommand {
- public:
- SVGSmoothQuadraticCurveTo(double, double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
-
- class SVGSmoothCubicCurveTo : public SVGCommand {
- public:
- double x1, y1;
- SVGSmoothCubicCurveTo(double, double, double, double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
-
- class SVGArcTo : public SVGCommand {
- public:
- double rx, ry, rot;
- bool large, sweep;
- SVGArcTo(double, double, double, bool, bool, double, double, bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
-
- class SVGClosePath : public SVGCommand {
- public:
- SVGClosePath(bool = false);
- virtual const std::string toString() const;
- virtual SVGCommandType getType();
- virtual std::string toString2();
- };
- typedef vector> SVGPath;
- SVGPath parsePath(std::istream&);
-
- std::ostream& operator<< (std::ostream&, const SVGParser::SVGPath&);
- std::ostream& operator<< (std::ostream&, const SVGParser::SVGCommand*);
+ SVG_CLOSE_PATH
};
+
+bool isAbsolute(SVGCommandType);
+class SVGCommand
+{
+ public:
+ SVGCommand(double, double, bool = false);
+ static const int length;
+ double x, y;
+ bool absolute;
+ virtual const std::string toString() const = 0;
+ virtual SVGCommandType getType() = 0;
+ virtual std::string toString2() = 0;
+};
+class SVGMoveTo : public SVGCommand
+{
+ public:
+ static const int length = 2;
+ SVGMoveTo(double, double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+
+class SVGLineTo : public SVGCommand
+{
+ public:
+ static const int length = 2;
+ SVGLineTo(double, double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+class SVGHLineTo : public SVGCommand
+{
+ public:
+ static const int length = 1;
+ SVGHLineTo(double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+class SVGVLineTo : public SVGCommand
+{
+ public:
+ static const int length = 1;
+ SVGVLineTo(double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+
+class SVGQuadraticCurveTo : public SVGCommand
+{
+ public:
+ SVGQuadraticCurveTo(double, double, double, double, bool = false);
+ double x0, y0;
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+
+class SVGCubicCurveTo : public SVGCommand
+{
+ public:
+ double x0, y0, x1, y1;
+ SVGCubicCurveTo(double, double, double, double, double, double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+class SVGSmoothQuadraticCurveTo : public SVGCommand
+{
+ public:
+ SVGSmoothQuadraticCurveTo(double, double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+
+class SVGSmoothCubicCurveTo : public SVGCommand
+{
+ public:
+ double x1, y1;
+ SVGSmoothCubicCurveTo(double, double, double, double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+
+class SVGArcTo : public SVGCommand
+{
+ public:
+ double rx, ry, rot;
+ bool large, sweep;
+ SVGArcTo(double, double, double, bool, bool, double, double, bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+
+class SVGClosePath : public SVGCommand
+{
+ public:
+ SVGClosePath(bool = false);
+ virtual const std::string toString() const;
+ virtual SVGCommandType getType();
+ virtual std::string toString2();
+};
+typedef vector> SVGPath;
+SVGPath parsePath(std::istream &);
+
+std::ostream &operator<<(std::ostream &, const SVGParser::SVGPath &);
+std::ostream &operator<<(std::ostream &, const SVGParser::SVGCommand *);
+}; // namespace SVGParser
class SvgParser
{
-public:
- SvgParser(const std::string path, const double width, const double height) ;
- vector> parse();
-private:
- const std::string path;
- const double width;
- const double height;
+ public:
+ SvgParser(const std::string path, const double width, const double height);
+ vector> parse();
- Point convertPoint(double x, double y);
- Point clampPoint(Point p);
- Point convertAbsPoint(double x, double y);
- Point convertRelPoint(Point pointBegin, double x, double y);
+ private:
+ static constexpr const double eps = 1e-6;
+ static constexpr const double PI = 3.14159265358979323846;
+ const std::string path;
+ const double width;
+ const double height;
+
+ Point convertPoint(double x, double y);
+ Point clampPoint(Point p);
+ Point convertAbsPoint(double x, double y);
+ Point convertRelPoint(Point pointBegin, double x, double y);
+ void ellipticalArcConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA,
+ bool flagS, Point endPoint,vector>& lines);
+ vector centerConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA, bool flagS,
+ Point endPoint);
+ double angleConverter(Point u, Point v);
+ Point eConverter(Point c, Point r, double cosPhi, double sinPhi, double t);
+ Point e2Converter(Point c, Point r, double cosPhi, double sinPhi, double t);
};
-