Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting
commit
63996ec51a
|
@ -31,7 +31,7 @@
|
||||||
<Import Project="$(QtMsBuild)\qt_defaults.props" />
|
<Import Project="$(QtMsBuild)\qt_defaults.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
||||||
<QtInstall>5.15.2_msvc2019_64</QtInstall>
|
<QtInstall>5.15.0_msvc2019_64</QtInstall>
|
||||||
<QtModules>core;gui;widgets</QtModules>
|
<QtModules>core;gui;widgets</QtModules>
|
||||||
<QtBuildConfig>debug</QtBuildConfig>
|
<QtBuildConfig>debug</QtBuildConfig>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace SVGParser {
|
namespace SVGParser
|
||||||
|
{
|
||||||
|
|
||||||
SVGCommandType getSVGCommand(char c) {
|
SVGCommandType getSVGCommand(char c)
|
||||||
switch (c) {
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
case 'm':
|
case 'm':
|
||||||
return SVG_MOVE_TO_REL;
|
return SVG_MOVE_TO_REL;
|
||||||
break;
|
break;
|
||||||
|
@ -78,9 +81,11 @@ namespace SVGParser {
|
||||||
return SVG_INVALID;
|
return SVG_INVALID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
int getCommandLength(SVGCommandType t) {
|
int getCommandLength(SVGCommandType t)
|
||||||
switch (t) {
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
case SVG_MOVE_TO_REL:
|
case SVG_MOVE_TO_REL:
|
||||||
case SVG_LINE_TO_REL:
|
case SVG_LINE_TO_REL:
|
||||||
case SVG_MOVE_TO_ABS:
|
case SVG_MOVE_TO_ABS:
|
||||||
|
@ -94,7 +99,6 @@ namespace SVGParser {
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case SVG_QUADRATIC_CURVE_TO_REL:
|
case SVG_QUADRATIC_CURVE_TO_REL:
|
||||||
case SVG_QUADRATIC_CURVE_TO_ABS:
|
case SVG_QUADRATIC_CURVE_TO_ABS:
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -124,57 +128,71 @@ namespace SVGParser {
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
bool isAbsolute(SVGCommandType t) {
|
bool isAbsolute(SVGCommandType t)
|
||||||
if (t == SVG_CLOSE_PATH) return false;
|
{
|
||||||
|
if (t == SVG_CLOSE_PATH)
|
||||||
|
return false;
|
||||||
return t % 2;
|
return t % 2;
|
||||||
}
|
}
|
||||||
SVGPath createCommandChunk(SVGCommandType t, vector<double> elements) {
|
SVGPath createCommandChunk(SVGCommandType t, vector<double> elements)
|
||||||
|
{
|
||||||
int commandLength = getCommandLength(t);
|
int commandLength = getCommandLength(t);
|
||||||
SVGPath chunk;
|
SVGPath chunk;
|
||||||
bool abs = isAbsolute(t);
|
bool abs = isAbsolute(t);
|
||||||
if (t == SVG_CLOSE_PATH) chunk.push_back(make_shared<SVGClosePath>());
|
if (t == SVG_CLOSE_PATH)
|
||||||
|
chunk.push_back(make_shared<SVGClosePath>());
|
||||||
if (commandLength > 0)
|
if (commandLength > 0)
|
||||||
for (int i = 0; i < int(elements.size() / commandLength); i++) {
|
for (int i = 0; i < int(elements.size() / commandLength); i++)
|
||||||
switch (t) {
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
case SVG_LINE_TO_REL:
|
case SVG_LINE_TO_REL:
|
||||||
case SVG_LINE_TO_ABS:
|
case SVG_LINE_TO_ABS:
|
||||||
chunk.push_back(make_shared<SVGLineTo>(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
|
chunk.push_back(
|
||||||
|
make_shared<SVGLineTo>(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
|
||||||
break;
|
break;
|
||||||
case SVG_MOVE_TO_REL:
|
case SVG_MOVE_TO_REL:
|
||||||
case SVG_MOVE_TO_ABS:
|
case SVG_MOVE_TO_ABS:
|
||||||
chunk.push_back(make_shared<SVGMoveTo>(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
|
chunk.push_back(
|
||||||
|
make_shared<SVGMoveTo>(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
|
||||||
break;
|
break;
|
||||||
case SVG_CUBIC_CURVE_TO_REL:
|
case SVG_CUBIC_CURVE_TO_REL:
|
||||||
case SVG_CUBIC_CURVE_TO_ABS:
|
case SVG_CUBIC_CURVE_TO_ABS:
|
||||||
chunk.push_back(make_shared<SVGCubicCurveTo>(elements[i * commandLength + 0], elements[i * commandLength + 1],
|
chunk.push_back(make_shared<SVGCubicCurveTo>(
|
||||||
elements[i * commandLength + 2], elements[i * commandLength + 3],
|
elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2],
|
||||||
elements[i * commandLength + 4], elements[i * commandLength + 5], abs));
|
elements[i * commandLength + 3], elements[i * commandLength + 4], elements[i * commandLength + 5],
|
||||||
|
abs));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SVG_SMOOTH_CUBIC_CURVE_TO_REL:
|
case SVG_SMOOTH_CUBIC_CURVE_TO_REL:
|
||||||
case SVG_SMOOTH_CUBIC_CURVE_TO_ABS:
|
case SVG_SMOOTH_CUBIC_CURVE_TO_ABS:
|
||||||
chunk.push_back(make_shared<SVGSmoothCubicCurveTo>(elements[i * commandLength + 0], elements[i * commandLength + 1],
|
chunk.push_back(make_shared<SVGSmoothCubicCurveTo>(
|
||||||
elements[i * commandLength + 2], elements[i * commandLength + 3], abs));
|
elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2],
|
||||||
|
elements[i * commandLength + 3], abs));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SVG_QUADRATIC_CURVE_TO_REL:
|
case SVG_QUADRATIC_CURVE_TO_REL:
|
||||||
case SVG_QUADRATIC_CURVE_TO_ABS:
|
case SVG_QUADRATIC_CURVE_TO_ABS:
|
||||||
chunk.push_back(make_shared<SVGQuadraticCurveTo>(elements[i * commandLength + 0], elements[i * commandLength + 1],
|
chunk.push_back(make_shared<SVGQuadraticCurveTo>(
|
||||||
elements[i * commandLength + 2], elements[i * commandLength + 3], abs));
|
elements[i * commandLength + 0], elements[i * commandLength + 1], elements[i * commandLength + 2],
|
||||||
|
elements[i * commandLength + 3], abs));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL:
|
case SVG_SMOOTH_QUADRATIC_CURVE_TO_REL:
|
||||||
case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS:
|
case SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS:
|
||||||
chunk.push_back(make_shared<SVGSmoothQuadraticCurveTo>(elements[i * commandLength + 0], elements[i * commandLength + 1], abs));
|
chunk.push_back(make_shared<SVGSmoothQuadraticCurveTo>(elements[i * commandLength + 0],
|
||||||
|
elements[i * commandLength + 1], abs));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SVG_ARC_TO_REL:
|
case SVG_ARC_TO_REL:
|
||||||
case SVG_ARC_TO_ABS:
|
case SVG_ARC_TO_ABS:
|
||||||
chunk.push_back(make_shared<SVGArcTo>(elements[i * commandLength + 0], elements[i * commandLength + 1],//rx, ry
|
chunk.push_back(make_shared<SVGArcTo>(
|
||||||
elements[i * commandLength + 2],//rotation,
|
elements[i * commandLength + 0], elements[i * commandLength + 1], // rx, ry
|
||||||
int(elements[i * commandLength + 3]) == 1, int(elements[i * commandLength + 4]) == 1, //large arc, sweep
|
elements[i * commandLength + 2], // rotation,
|
||||||
elements[i * commandLength + 5], elements[i * commandLength + 6], //end x, end y
|
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));
|
abs));
|
||||||
break;
|
break;
|
||||||
case SVG_HORIZONTAL_LINE_TO_REL:
|
case SVG_HORIZONTAL_LINE_TO_REL:
|
||||||
|
@ -186,190 +204,222 @@ namespace SVGParser {
|
||||||
chunk.push_back(make_shared<SVGVLineTo>(elements[i * commandLength + 0], abs));
|
chunk.push_back(make_shared<SVGVLineTo>(elements[i * commandLength + 0], abs));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//This here is funky.
|
// This here is funky.
|
||||||
if (t == SVG_MOVE_TO_REL || t == SVG_MOVE_TO_ABS) t = SVGCommandType(int(t) + 2);
|
if (t == SVG_MOVE_TO_REL || t == SVG_MOVE_TO_ABS)
|
||||||
|
t = SVGCommandType(int(t) + 2);
|
||||||
}
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
SVGPath parsePath(istream& ss) {
|
SVGPath parsePath(istream &ss)
|
||||||
|
{
|
||||||
SVGPath commandArray;
|
SVGPath commandArray;
|
||||||
//istringstream ss(path);
|
// istringstream ss(path);
|
||||||
//bool absolute = false;
|
// bool absolute = false;
|
||||||
SVGCommandType command = SVG_INVALID;
|
SVGCommandType command = SVG_INVALID;
|
||||||
vector<double> elements;
|
vector<double> elements;
|
||||||
|
|
||||||
while (ss.good()) {
|
while (ss.good())
|
||||||
|
{
|
||||||
char c = ss.get();
|
char c = ss.get();
|
||||||
SVGCommandType cmd = getSVGCommand(c);
|
SVGCommandType cmd = getSVGCommand(c);
|
||||||
|
|
||||||
if (cmd != SVG_INVALID) {
|
if (cmd != SVG_INVALID)
|
||||||
|
{
|
||||||
SVGPath chunk = createCommandChunk(command, elements);
|
SVGPath chunk = createCommandChunk(command, elements);
|
||||||
commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
|
commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
|
||||||
command = cmd;
|
command = cmd;
|
||||||
elements.clear();
|
elements.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (!(isspace(c) || c == ',')) {//its a number...
|
else if (!(isspace(c) || c == ','))
|
||||||
|
{ // its a number...
|
||||||
double x;
|
double x;
|
||||||
ss.unget();
|
ss.unget();
|
||||||
ss >> x;
|
ss >> x;
|
||||||
elements.push_back(x);
|
elements.push_back(x);
|
||||||
}// else its a separator
|
} // else its a separator
|
||||||
}
|
}
|
||||||
SVGPath chunk = createCommandChunk(command, elements);
|
SVGPath chunk = createCommandChunk(command, elements);
|
||||||
commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
|
commandArray.insert(commandArray.end(), chunk.begin(), chunk.end());
|
||||||
return commandArray;
|
return commandArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGCommand::SVGCommand(double _x, double _y, bool abs) : x(_x), y(_y), absolute(abs) {}
|
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) {
|
{
|
||||||
}
|
}
|
||||||
|
SVGLineTo::SVGLineTo(double x, double y, bool abs) : SVGCommand(x, y, abs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const string SVGLineTo::toString() const {
|
const string SVGLineTo::toString() const
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "L" : "l") << x << "," << y;
|
s << (absolute ? "L" : "l") << x << "," << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGLineTo::toString2() {
|
string SVGLineTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Line to (" << (absolute ? "absolute" : "relative") << ") " << x << "x" << y;
|
s << "Line to (" << (absolute ? "absolute" : "relative") << ") " << x << "x" << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGCommandType SVGLineTo::getType() {
|
SVGCommandType SVGLineTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_LINE_TO_ABS : SVG_LINE_TO_REL;
|
return absolute ? SVG_LINE_TO_ABS : SVG_LINE_TO_REL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGHLineTo::SVGHLineTo(double x, bool abs) : SVGCommand(x, 0, abs) {
|
SVGHLineTo::SVGHLineTo(double x, bool abs) : SVGCommand(x, 0, abs)
|
||||||
}
|
{
|
||||||
const string SVGHLineTo::toString() const {
|
}
|
||||||
|
const string SVGHLineTo::toString() const
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "H" : "h") << x;
|
s << (absolute ? "H" : "h") << x;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGHLineTo::toString2() {
|
string SVGHLineTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Horizontal Line (" << (absolute ? "absolute" : "relative") << ") " << x << "px";
|
s << "Horizontal Line (" << (absolute ? "absolute" : "relative") << ") " << x << "px";
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGCommandType SVGHLineTo::getType() {
|
SVGCommandType SVGHLineTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_HORIZONTAL_LINE_TO_ABS : SVG_HORIZONTAL_LINE_TO_REL;
|
return absolute ? SVG_HORIZONTAL_LINE_TO_ABS : SVG_HORIZONTAL_LINE_TO_REL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGVLineTo::SVGVLineTo(double y, bool abs) : SVGCommand(0, y, abs) {
|
SVGVLineTo::SVGVLineTo(double y, bool abs) : SVGCommand(0, y, abs)
|
||||||
}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const string SVGVLineTo::toString() const {
|
const string SVGVLineTo::toString() const
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "V" : "v") << y;
|
s << (absolute ? "V" : "v") << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGVLineTo::toString2() {
|
string SVGVLineTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Vertical Line (" << (absolute ? "absolute" : "relative") << ") " << y << "px";
|
s << "Vertical Line (" << (absolute ? "absolute" : "relative") << ") " << y << "px";
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
SVGCommandType SVGVLineTo::getType() {
|
SVGCommandType SVGVLineTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_VERTICAL_LINE_TO_ABS : SVG_VERTICAL_LINE_TO_REL;
|
return absolute ? SVG_VERTICAL_LINE_TO_ABS : SVG_VERTICAL_LINE_TO_REL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SVGMoveTo::SVGMoveTo(double x, double y, bool abs) : SVGCommand(x, y, abs)
|
||||||
|
{
|
||||||
|
}
|
||||||
SVGMoveTo::SVGMoveTo(double x, double y, bool abs) : SVGCommand(x, y, abs) {
|
const string SVGMoveTo::toString() const
|
||||||
}
|
{
|
||||||
const string SVGMoveTo::toString() const {
|
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "M" : "m") << x << "," << y;
|
s << (absolute ? "M" : "m") << x << "," << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGMoveTo::toString2() {
|
string SVGMoveTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Move to (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
|
s << "Move to (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
SVGCommandType SVGMoveTo::getType() {
|
SVGCommandType SVGMoveTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_MOVE_TO_ABS : SVG_MOVE_TO_REL;
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SVGCubicCurveTo::SVGCubicCurveTo(double _x0, double _y0,
|
const string SVGCubicCurveTo::toString() const
|
||||||
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;
|
stringstream s;
|
||||||
s << (absolute ? "C" : "c") << x0 << "," << y0 << " " << x1 << "," << y1 << " " << x << "," << y;
|
s << (absolute ? "C" : "c") << x0 << "," << y0 << " " << x1 << "," << y1 << " " << x << "," << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGCubicCurveTo::toString2() {
|
string SVGCubicCurveTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Cubic Curve (" << (absolute ? "absolute" : "relative") << ") control points: " << x0 << "," << y0 << " " << x1 << "," << y1 << " to " << x << "x" << y;
|
s << "Cubic Curve (" << (absolute ? "absolute" : "relative") << ") control points: " << x0 << "," << y0 << " " << x1
|
||||||
|
<< "," << y1 << " to " << x << "x" << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
SVGCommandType SVGCubicCurveTo::getType() {
|
SVGCommandType SVGCubicCurveTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_CUBIC_CURVE_TO_ABS : SVG_CUBIC_CURVE_TO_REL;
|
return absolute ? SVG_CUBIC_CURVE_TO_ABS : SVG_CUBIC_CURVE_TO_REL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGSmoothCubicCurveTo::SVGSmoothCubicCurveTo(
|
SVGSmoothCubicCurveTo::SVGSmoothCubicCurveTo(double _x1, double _y1, double x, double y, bool abs)
|
||||||
double _x1, double _y1,
|
: SVGCommand(x, y, abs), x1(_x1), y1(_y1)
|
||||||
double x, double y, bool abs) : SVGCommand(x, y, abs),
|
{
|
||||||
x1(_x1), y1(_y1) {
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const string SVGSmoothCubicCurveTo::toString() const {
|
const string SVGSmoothCubicCurveTo::toString() const
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "S" : "s") << x1 << "," << y1 << " " << x << "," << y;
|
s << (absolute ? "S" : "s") << x1 << "," << y1 << " " << x << "," << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGSmoothCubicCurveTo::toString2() {
|
string SVGSmoothCubicCurveTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Smooth cubic curve to (" << (absolute ? "absolute" : "relative") << ") control point: " << x1 << "," << y1 << " to " << x << "x" << y;
|
s << "Smooth cubic curve to (" << (absolute ? "absolute" : "relative") << ") control point: " << x1 << "," << y1
|
||||||
|
<< " to " << x << "x" << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
SVGCommandType SVGSmoothCubicCurveTo::getType() {
|
SVGCommandType SVGSmoothCubicCurveTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_SMOOTH_CUBIC_CURVE_TO_ABS : SVG_SMOOTH_CUBIC_CURVE_TO_REL;
|
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)
|
||||||
SVGQuadraticCurveTo::SVGQuadraticCurveTo(double _x0, double _y0,
|
: SVGCommand(x, y, abs), x0(_x0), y0(_y0)
|
||||||
double x, double y, bool abs) : SVGCommand(x, y, abs), x0(_x0), y0(_y0) {
|
{
|
||||||
}
|
}
|
||||||
const string SVGQuadraticCurveTo::toString() const {
|
const string SVGQuadraticCurveTo::toString() const
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "Q" : "q") << x0 << "," << y0 << " " << x << "," << y;
|
s << (absolute ? "Q" : "q") << x0 << "," << y0 << " " << x << "," << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGQuadraticCurveTo::toString2() {
|
string SVGQuadraticCurveTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "quadratic curve (" << (absolute ? "absolute" : "relative") << ") control point: " << x0 << "," << y0 << " to " << x << "x" << y;
|
s << "quadratic curve (" << (absolute ? "absolute" : "relative") << ") control point: " << x0 << "," << y0 << " to "
|
||||||
|
<< x << "x" << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
SVGCommandType SVGQuadraticCurveTo::getType() {
|
SVGCommandType SVGQuadraticCurveTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_QUADRATIC_CURVE_TO_ABS : SVG_QUADRATIC_CURVE_TO_REL;
|
return absolute ? SVG_QUADRATIC_CURVE_TO_ABS : SVG_QUADRATIC_CURVE_TO_REL;
|
||||||
}
|
}
|
||||||
SVGSmoothQuadraticCurveTo::SVGSmoothQuadraticCurveTo(
|
SVGSmoothQuadraticCurveTo::SVGSmoothQuadraticCurveTo(double x, double y, bool abs) : SVGCommand(x, y, abs)
|
||||||
double x, double y, bool abs) : SVGCommand(x, y, abs) {
|
{
|
||||||
}
|
}
|
||||||
const string SVGSmoothQuadraticCurveTo::toString() const {
|
const string SVGSmoothQuadraticCurveTo::toString() const
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "T" : "t") << x << "," << y;
|
s << (absolute ? "T" : "t") << x << "," << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGSmoothQuadraticCurveTo::toString2() {
|
string SVGSmoothQuadraticCurveTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Smooth quadratic curve (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
|
s << "Smooth quadratic curve (" << (absolute ? "absolute" : "relative") << ") to " << x << "x" << y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
SVGCommandType SVGSmoothQuadraticCurveTo::getType() {
|
SVGCommandType SVGSmoothQuadraticCurveTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS : SVG_SMOOTH_QUADRATIC_CURVE_TO_REL;
|
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) {
|
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->rx = rx;
|
||||||
this->ry = ry;
|
this->ry = ry;
|
||||||
|
|
||||||
|
@ -377,64 +427,75 @@ namespace SVGParser {
|
||||||
|
|
||||||
this->large = large;
|
this->large = large;
|
||||||
this->sweep = sweep;
|
this->sweep = sweep;
|
||||||
}
|
}
|
||||||
const string SVGArcTo::toString() const {
|
const string SVGArcTo::toString() const
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "A" : "a") << rx << "," << ry << " " << rot << " " << large << "," << sweep << " " << x << "," << y;
|
s << (absolute ? "A" : "a") << rx << "," << ry << " " << rot << " " << large << "," << sweep << " " << x << ","
|
||||||
|
<< y;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
string SVGArcTo::toString2() {
|
string SVGArcTo::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
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;
|
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();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGCommandType SVGArcTo::getType() {
|
SVGCommandType SVGArcTo::getType()
|
||||||
|
{
|
||||||
return absolute ? SVG_ARC_TO_ABS : SVG_ARC_TO_REL;
|
return absolute ? SVG_ARC_TO_ABS : SVG_ARC_TO_REL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGClosePath::SVGClosePath(bool abs) :SVGCommand(0, 0, abs) {
|
SVGClosePath::SVGClosePath(bool abs) : SVGCommand(0, 0, abs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
}
|
const string SVGClosePath::toString() const
|
||||||
|
{
|
||||||
const string SVGClosePath::toString() const {
|
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << (absolute ? "Z" : "z");
|
s << (absolute ? "Z" : "z");
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
string SVGClosePath::toString2() {
|
string SVGClosePath::toString2()
|
||||||
|
{
|
||||||
stringstream s;
|
stringstream s;
|
||||||
s << "Close path";
|
s << "Close path";
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
SVGCommandType SVGClosePath::getType() {
|
SVGCommandType SVGClosePath::getType()
|
||||||
|
{
|
||||||
return SVG_CLOSE_PATH;
|
return SVG_CLOSE_PATH;
|
||||||
}
|
}
|
||||||
std::ostream& operator<< (std::ostream& out, const SVGParser::SVGPath& path) {
|
std::ostream &operator<<(std::ostream &out, const SVGParser::SVGPath &path)
|
||||||
for (SVGParser::SVGPath::const_iterator it = path.begin(); it != path.end(); it++) {
|
{
|
||||||
|
for (SVGParser::SVGPath::const_iterator it = path.begin(); it != path.end(); it++)
|
||||||
|
{
|
||||||
out << (*it)->toString();
|
out << (*it)->toString();
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
std::ostream& operator<< (std::ostream& out, const SVGParser::SVGCommand* cmd) {
|
std::ostream &operator<<(std::ostream &out, const SVGParser::SVGCommand *cmd)
|
||||||
|
{
|
||||||
out << cmd->toString();
|
out << cmd->toString();
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}; // namespace SVGParser
|
||||||
|
|
||||||
SvgParser::SvgParser(const std::string path, double width, double height) :path(path), width(width), height(height)
|
SvgParser::SvgParser(const std::string path, double width, double height) : path(path), width(width), height(height)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Point SvgParser::convertPoint(double x, double y)
|
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)
|
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)
|
Point SvgParser::convertAbsPoint(double x, double y)
|
||||||
{
|
{
|
||||||
|
@ -442,7 +503,7 @@ Point SvgParser::convertAbsPoint(double x, double y)
|
||||||
}
|
}
|
||||||
Point SvgParser::convertRelPoint(Point pointBegin, double x, double 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;
|
using namespace SVGParser;
|
||||||
vector<vector<Point>> SvgParser::parse()
|
vector<vector<Point>> SvgParser::parse()
|
||||||
|
@ -456,62 +517,54 @@ vector<vector<Point>> SvgParser::parse()
|
||||||
{
|
{
|
||||||
switch (svgCmd->getType())
|
switch (svgCmd->getType())
|
||||||
{
|
{
|
||||||
case SVG_MOVE_TO_ABS:
|
case SVG_MOVE_TO_ABS: {
|
||||||
{
|
|
||||||
shared_ptr<SVGMoveTo> cmd = static_pointer_cast<SVGMoveTo>(svgCmd);
|
shared_ptr<SVGMoveTo> cmd = static_pointer_cast<SVGMoveTo>(svgCmd);
|
||||||
line.push_back(convertAbsPoint(cmd->x, cmd->y));
|
line.push_back(convertAbsPoint(cmd->x, cmd->y));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_LINE_TO_REL:
|
case SVG_LINE_TO_REL: {
|
||||||
{
|
|
||||||
shared_ptr<SVGLineTo> cmd = static_pointer_cast<SVGLineTo>(svgCmd);
|
shared_ptr<SVGLineTo> cmd = static_pointer_cast<SVGLineTo>(svgCmd);
|
||||||
line.push_back(convertRelPoint(line.back(), cmd->x, cmd->y));
|
line.push_back(convertRelPoint(line.back(), cmd->x, cmd->y));
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_LINE_TO_ABS:
|
case SVG_LINE_TO_ABS: {
|
||||||
{
|
|
||||||
shared_ptr<SVGLineTo> cmd = static_pointer_cast<SVGLineTo>(svgCmd);
|
shared_ptr<SVGLineTo> cmd = static_pointer_cast<SVGLineTo>(svgCmd);
|
||||||
line.push_back(convertAbsPoint(cmd->x, cmd->y));
|
line.push_back(convertAbsPoint(cmd->x, cmd->y));
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_HORIZONTAL_LINE_TO_REL:
|
case SVG_HORIZONTAL_LINE_TO_REL: {
|
||||||
{
|
|
||||||
shared_ptr<SVGHLineTo> cmd = static_pointer_cast<SVGHLineTo>(svgCmd);
|
shared_ptr<SVGHLineTo> cmd = static_pointer_cast<SVGHLineTo>(svgCmd);
|
||||||
line.push_back(convertRelPoint(line.back(), cmd->x, 0));
|
line.push_back(convertRelPoint(line.back(), cmd->x, 0));
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_HORIZONTAL_LINE_TO_ABS:
|
case SVG_HORIZONTAL_LINE_TO_ABS: {
|
||||||
{
|
|
||||||
shared_ptr<SVGHLineTo> cmd = static_pointer_cast<SVGHLineTo>(svgCmd);
|
shared_ptr<SVGHLineTo> cmd = static_pointer_cast<SVGHLineTo>(svgCmd);
|
||||||
line.push_back(convertAbsPoint(cmd->x, line.back().y));
|
line.push_back(convertAbsPoint(cmd->x, line.back().y));
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_VERTICAL_LINE_TO_REL:
|
case SVG_VERTICAL_LINE_TO_REL: {
|
||||||
{
|
|
||||||
shared_ptr<SVGVLineTo> cmd = static_pointer_cast<SVGVLineTo>(svgCmd);
|
shared_ptr<SVGVLineTo> cmd = static_pointer_cast<SVGVLineTo>(svgCmd);
|
||||||
line.push_back(convertRelPoint(line.back(), 0, cmd->y));
|
line.push_back(convertRelPoint(line.back(), 0, cmd->y));
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_VERTICAL_LINE_TO_ABS:
|
case SVG_VERTICAL_LINE_TO_ABS: {
|
||||||
{
|
|
||||||
shared_ptr<SVGVLineTo> cmd = static_pointer_cast<SVGVLineTo>(svgCmd);
|
shared_ptr<SVGVLineTo> cmd = static_pointer_cast<SVGVLineTo>(svgCmd);
|
||||||
line.push_back(convertAbsPoint(line.back().x, cmd->y));
|
line.push_back(convertAbsPoint(line.back().x, cmd->y));
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_QUADRATIC_CURVE_TO_REL:
|
case SVG_QUADRATIC_CURVE_TO_REL: {
|
||||||
{
|
|
||||||
shared_ptr<SVGQuadraticCurveTo> cmd = static_pointer_cast<SVGQuadraticCurveTo>(svgCmd);
|
shared_ptr<SVGQuadraticCurveTo> cmd = static_pointer_cast<SVGQuadraticCurveTo>(svgCmd);
|
||||||
Point pointBegin = line.back();
|
Point pointBegin = line.back();
|
||||||
Point pointControl = convertRelPoint(pointBegin, cmd->x0, cmd->y0);
|
Point pointControl = convertRelPoint(pointBegin, cmd->x0, cmd->y0);
|
||||||
|
@ -523,8 +576,7 @@ vector<vector<Point>> SvgParser::parse()
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_QUADRATIC_CURVE_TO_ABS:
|
case SVG_QUADRATIC_CURVE_TO_ABS: {
|
||||||
{
|
|
||||||
shared_ptr<SVGQuadraticCurveTo> cmd = static_pointer_cast<SVGQuadraticCurveTo>(svgCmd);
|
shared_ptr<SVGQuadraticCurveTo> cmd = static_pointer_cast<SVGQuadraticCurveTo>(svgCmd);
|
||||||
Point pointBegin = line.back();
|
Point pointBegin = line.back();
|
||||||
Point pointControl = convertAbsPoint(cmd->x0, cmd->y0);
|
Point pointControl = convertAbsPoint(cmd->x0, cmd->y0);
|
||||||
|
@ -536,8 +588,7 @@ vector<vector<Point>> SvgParser::parse()
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_CUBIC_CURVE_TO_REL:
|
case SVG_CUBIC_CURVE_TO_REL: {
|
||||||
{
|
|
||||||
shared_ptr<SVGCubicCurveTo> cmd = static_pointer_cast<SVGCubicCurveTo>(svgCmd);
|
shared_ptr<SVGCubicCurveTo> cmd = static_pointer_cast<SVGCubicCurveTo>(svgCmd);
|
||||||
Point pointBegin = line.back();
|
Point pointBegin = line.back();
|
||||||
line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0));
|
line.push_back(convertRelPoint(pointBegin, cmd->x0, cmd->y0));
|
||||||
|
@ -547,8 +598,7 @@ vector<vector<Point>> SvgParser::parse()
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVG_CUBIC_CURVE_TO_ABS:
|
case SVG_CUBIC_CURVE_TO_ABS: {
|
||||||
{
|
|
||||||
shared_ptr<SVGCubicCurveTo> cmd = static_pointer_cast<SVGCubicCurveTo>(svgCmd);
|
shared_ptr<SVGCubicCurveTo> cmd = static_pointer_cast<SVGCubicCurveTo>(svgCmd);
|
||||||
line.push_back(convertAbsPoint(cmd->x0, cmd->y0));
|
line.push_back(convertAbsPoint(cmd->x0, cmd->y0));
|
||||||
line.push_back(convertAbsPoint(cmd->x1, cmd->y1));
|
line.push_back(convertAbsPoint(cmd->x1, cmd->y1));
|
||||||
|
@ -567,19 +617,14 @@ vector<vector<Point>> SvgParser::parse()
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
line.erase(line.begin(), line.end() - 1);
|
line.erase(line.begin(), line.end() - 1);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case SVG_ARC_TO_ABS:
|
|
||||||
{
|
|
||||||
shared_ptr<SVGArcTo> cmd = static_pointer_cast<SVGArcTo>(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:
|
case SVG_ARC_TO_ABS: {
|
||||||
{
|
shared_ptr<SVGArcTo> cmd = static_pointer_cast<SVGArcTo>(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]);
|
line.push_back(lines[0][0]);
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
break;
|
break;
|
||||||
|
@ -591,4 +636,118 @@ vector<vector<Point>> SvgParser::parse()
|
||||||
}
|
}
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
void SvgParser::ellipticalArcConverter(Point beginPoint, double radiusX, double radiusY, double phi, bool flagA,
|
||||||
|
bool flagS, Point endPoint, vector<vector<Point>> &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<Point>{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<Point>{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<Point>{p_1, q_1, q_2, p_2});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<double> 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<double>{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};
|
||||||
|
}
|
||||||
|
|
|
@ -1,27 +1,41 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "Line.h"
|
#include "Line.h"
|
||||||
namespace SVGParser {
|
#include <cmath>
|
||||||
enum SVGCommandType {
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
namespace SVGParser
|
||||||
|
{
|
||||||
|
enum SVGCommandType
|
||||||
|
{
|
||||||
SVG_INVALID = -1,
|
SVG_INVALID = -1,
|
||||||
//SVG_MOVE_TO_REL, SVG_LINE_TO_REL, SVG_QUADRATIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_REL,
|
// 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_ABS, SVG_LINE_TO_ABS, SVG_QUADRATIC_CURVE_TO_ABS, SVG_CUBIC_CURVE_TO_ABS,
|
||||||
SVG_MOVE_TO_REL, SVG_MOVE_TO_ABS,
|
SVG_MOVE_TO_REL,
|
||||||
SVG_LINE_TO_REL, SVG_LINE_TO_ABS,
|
SVG_MOVE_TO_ABS,
|
||||||
SVG_HORIZONTAL_LINE_TO_REL, SVG_HORIZONTAL_LINE_TO_ABS,
|
SVG_LINE_TO_REL,
|
||||||
SVG_VERTICAL_LINE_TO_REL, SVG_VERTICAL_LINE_TO_ABS,
|
SVG_LINE_TO_ABS,
|
||||||
SVG_QUADRATIC_CURVE_TO_REL, SVG_QUADRATIC_CURVE_TO_ABS,
|
SVG_HORIZONTAL_LINE_TO_REL,
|
||||||
SVG_CUBIC_CURVE_TO_REL, SVG_CUBIC_CURVE_TO_ABS,
|
SVG_HORIZONTAL_LINE_TO_ABS,
|
||||||
SVG_SMOOTH_CUBIC_CURVE_TO_REL, SVG_SMOOTH_CUBIC_CURVE_TO_ABS,
|
SVG_VERTICAL_LINE_TO_REL,
|
||||||
SVG_SMOOTH_QUADRATIC_CURVE_TO_REL, SVG_SMOOTH_QUADRATIC_CURVE_TO_ABS,
|
SVG_VERTICAL_LINE_TO_ABS,
|
||||||
SVG_ARC_TO_REL, SVG_ARC_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
|
SVG_CLOSE_PATH
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isAbsolute(SVGCommandType);
|
bool isAbsolute(SVGCommandType);
|
||||||
class SVGCommand {
|
class SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SVGCommand(double, double, bool = false);
|
SVGCommand(double, double, bool = false);
|
||||||
static const int length;
|
static const int length;
|
||||||
|
@ -30,76 +44,85 @@ namespace SVGParser {
|
||||||
virtual const std::string toString() const = 0;
|
virtual const std::string toString() const = 0;
|
||||||
virtual SVGCommandType getType() = 0;
|
virtual SVGCommandType getType() = 0;
|
||||||
virtual std::string toString2() = 0;
|
virtual std::string toString2() = 0;
|
||||||
};
|
};
|
||||||
class SVGMoveTo : public SVGCommand {
|
class SVGMoveTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const int length = 2;
|
static const int length = 2;
|
||||||
SVGMoveTo(double, double, bool = false);
|
SVGMoveTo(double, double, bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SVGLineTo : public SVGCommand {
|
class SVGLineTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const int length = 2;
|
static const int length = 2;
|
||||||
SVGLineTo(double, double, bool = false);
|
SVGLineTo(double, double, bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
class SVGHLineTo : public SVGCommand {
|
class SVGHLineTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const int length = 1;
|
static const int length = 1;
|
||||||
SVGHLineTo(double, bool = false);
|
SVGHLineTo(double, bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
class SVGVLineTo : public SVGCommand {
|
class SVGVLineTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const int length = 1;
|
static const int length = 1;
|
||||||
SVGVLineTo(double, bool = false);
|
SVGVLineTo(double, bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SVGQuadraticCurveTo : public SVGCommand {
|
class SVGQuadraticCurveTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SVGQuadraticCurveTo(double, double, double, double, bool = false);
|
SVGQuadraticCurveTo(double, double, double, double, bool = false);
|
||||||
double x0, y0;
|
double x0, y0;
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SVGCubicCurveTo : public SVGCommand {
|
class SVGCubicCurveTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
double x0, y0, x1, y1;
|
double x0, y0, x1, y1;
|
||||||
SVGCubicCurveTo(double, double, double, double, double, double, bool = false);
|
SVGCubicCurveTo(double, double, double, double, double, double, bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
class SVGSmoothQuadraticCurveTo : public SVGCommand {
|
class SVGSmoothQuadraticCurveTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SVGSmoothQuadraticCurveTo(double, double, bool = false);
|
SVGSmoothQuadraticCurveTo(double, double, bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SVGSmoothCubicCurveTo : public SVGCommand {
|
class SVGSmoothCubicCurveTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
double x1, y1;
|
double x1, y1;
|
||||||
SVGSmoothCubicCurveTo(double, double, double, double, bool = false);
|
SVGSmoothCubicCurveTo(double, double, double, double, bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SVGArcTo : public SVGCommand {
|
class SVGArcTo : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
double rx, ry, rot;
|
double rx, ry, rot;
|
||||||
bool large, sweep;
|
bool large, sweep;
|
||||||
|
@ -107,27 +130,31 @@ namespace SVGParser {
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SVGClosePath : public SVGCommand {
|
class SVGClosePath : public SVGCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SVGClosePath(bool = false);
|
SVGClosePath(bool = false);
|
||||||
virtual const std::string toString() const;
|
virtual const std::string toString() const;
|
||||||
virtual SVGCommandType getType();
|
virtual SVGCommandType getType();
|
||||||
virtual std::string toString2();
|
virtual std::string toString2();
|
||||||
};
|
|
||||||
typedef vector<std::shared_ptr<SVGCommand>> SVGPath;
|
|
||||||
SVGPath parsePath(std::istream&);
|
|
||||||
|
|
||||||
std::ostream& operator<< (std::ostream&, const SVGParser::SVGPath&);
|
|
||||||
std::ostream& operator<< (std::ostream&, const SVGParser::SVGCommand*);
|
|
||||||
};
|
};
|
||||||
|
typedef vector<std::shared_ptr<SVGCommand>> 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
|
class SvgParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SvgParser(const std::string path, const double width, const double height) ;
|
SvgParser(const std::string path, const double width, const double height);
|
||||||
vector<vector<Point>> parse();
|
vector<vector<Point>> parse();
|
||||||
private:
|
|
||||||
|
private:
|
||||||
|
static constexpr const double eps = 1e-6;
|
||||||
|
static constexpr const double PI = 3.14159265358979323846;
|
||||||
const std::string path;
|
const std::string path;
|
||||||
const double width;
|
const double width;
|
||||||
const double height;
|
const double height;
|
||||||
|
@ -136,5 +163,11 @@ private:
|
||||||
Point clampPoint(Point p);
|
Point clampPoint(Point p);
|
||||||
Point convertAbsPoint(double x, double y);
|
Point convertAbsPoint(double x, double y);
|
||||||
Point convertRelPoint(Point pointBegin, 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<vector<Point>>& lines);
|
||||||
|
vector<double> 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue