diff --git a/ArchitectureColoredPainting/Line.h b/ArchitectureColoredPainting/Line.h index db8cf49..6b2ee17 100644 --- a/ArchitectureColoredPainting/Line.h +++ b/ArchitectureColoredPainting/Line.h @@ -20,7 +20,9 @@ const double eps = 1e-5; struct Point { double x, y; + Point operator + (const Point a) { return { x + a.x, y + a.y }; } Point operator - (const Point a) { return { x - a.x, y - a.y }; } + Point operator * (const double a) { return { x * a, y * a }; } double operator * (const Point a) { return x * a.y - y * a.x; } bool operator== (const Point& a) const { return fabs(x - a.x) <= eps && fabs(y - a.y) <= eps; diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp index a037bbc..e110357 100644 --- a/ArchitectureColoredPainting/Model.cpp +++ b/ArchitectureColoredPainting/Model.cpp @@ -190,7 +190,9 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod //bvhTree.buildBvhTree(initBound.data(), initBound.size()); - vector> lineSet = SvgParser::parse("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100,100); + + //vector> lineSet = SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse(); + vector> lineSet = SvgParser("M308.49,212.25l23,28.38-82,78.31c-14.28,13.64-26.34-20.6-53.44,9.32l-30.24-13.4,63.56-51.59L190.71,215.6l-32.92,26.72L149.5,232.1l32.92-26.72L173.2,194l-32.91,26.72-7.38-9.08L165.83,185l-38.69-47.66L94.22,164,85,152.65l32.91-26.72-9.21-11.35L75.79,141.3l-5.53-6.81,32.92-26.72L94,96.42,61.05,123.14l-12-14.76L37.72,117.6l12,14.75L30.41,148,0,110.55,136.2,0l30.4,37.46L147.31,53.12l-12-14.76L124,47.58l12,14.75L103.05,89.05l9.21,11.35,32.92-26.72,5.52,6.81-32.91,26.72L127,118.56l32.92-26.72,9.21,11.35-32.91,26.72,38.69,47.67,32.91-26.72,7.37,9.08-32.91,26.72L191.49,198l32.92-26.72,8.29,10.22-32.92,26.71,38.7,47.68L302,204.3l6.45,7.95Z", 331.52, 328.26).parse(); for (vector line : lineSet) { for (Point p : line) @@ -200,7 +202,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod //vector> lineSet = { {Point{-1,-1}, Point{1,-1}},{Point{1,-1}, Point{1,1}}, {Point{1,1}, Point{-1,1}},{Point{-1,1}, Point{-1,-1}} }; //vector> lineSet = { {Point{-1,-1}, Point{1,-1}},{Point{1,-1}, Point{1,1}}, {Point{1,1}, Point{-1,1}},{Point{-1,1}, Point{-1,-1}} }; - ShortCutTree shortCutTree(5); + ShortCutTree shortCutTree(100); shortCutTree.buildShortCutTree(lineSet); vector pointVector; vector lineVector; diff --git a/ArchitectureColoredPainting/SvgParser.cpp b/ArchitectureColoredPainting/SvgParser.cpp index ac0819e..b5b7760 100644 --- a/ArchitectureColoredPainting/SvgParser.cpp +++ b/ArchitectureColoredPainting/SvgParser.cpp @@ -1,44 +1,594 @@ #include "SvgParser.h" #include +#include +using namespace std; -vector> SvgParser::parse(const std::string path, float width, float height) -{ - std::string tmp; - vector point; - vector line; - vector> lines; - for (char c : path.substr(1)) - { - if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+') - { - tmp += c; +namespace SVGParser { + + 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 '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 '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 '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 '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; - else - { - if (tmp != "") - { - point.push_back(std::stod(tmp)); - tmp = ""; - if (point.size() == 2) - { - line.push_back(Point{ std::clamp(point[0] / width * 2 - 1, -1., 1.) , std::clamp(1 - point[1] / height * 2 , -1., 1.)}); - point.clear(); - } - } - if (c != ',' && c != ' ') - { - lines.push_back(line); - line.erase(line.begin(), line.end() - 1); - if (c == 'Z') - { - line.push_back(lines[0][0]); - lines.push_back(line); + + 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; + } + +}; + +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. }; +} +Point SvgParser::clampPoint(Point p) +{ + 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)); +} +Point SvgParser::convertRelPoint(Point pointBegin, double x, double y) +{ + return clampPoint(pointBegin + Point{ x / width * 2. , - y / height * 2. }); +} +using namespace SVGParser; +vector> SvgParser::parse() +{ + 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; } } - lines.erase(lines.begin()); return lines; } + diff --git a/ArchitectureColoredPainting/SvgParser.h b/ArchitectureColoredPainting/SvgParser.h index f507be7..0f6e4e6 100644 --- a/ArchitectureColoredPainting/SvgParser.h +++ b/ArchitectureColoredPainting/SvgParser.h @@ -2,9 +2,139 @@ #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, + + 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*); +}; class SvgParser { public: - static vector> parse(const std::string path, float width, float height); + SvgParser(const std::string path, const double width, const double height) ; + vector> parse(); +private: + 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); };