Compare commits
3 Commits
24e968cbf1
...
cebd41fc20
Author | SHA1 | Date |
---|---|---|
wuyize | cebd41fc20 | |
wuyize | 382051e341 | |
wuyize | 307771c61a |
|
@ -45,9 +45,9 @@ void Line::push_back(Point now) {
|
|||
}
|
||||
|
||||
bool Line::isLineContained(QVector4D bound) {
|
||||
double xMi = min(*vX.begin(), *vX.rbegin()), xMx = max(*vX.begin(), *vX.rbegin());
|
||||
double yMi = min(*vY.begin(), *vY.rbegin()), yMx = max(*vY.begin(), *vY.rbegin());
|
||||
if (bound.x() <= xMi && xMx <= bound.z() && bound.y() <= yMi && yMx <= bound.w())
|
||||
double xMin = min(*vX.begin(), *vX.rbegin()), xMax = max(*vX.begin(), *vX.rbegin());
|
||||
double yMin = min(*vY.begin(), *vY.rbegin()), yMax = max(*vY.begin(), *vY.rbegin());
|
||||
if (bound.x() <= xMin && xMax <= bound.z() && bound.y() <= yMin && yMax <= bound.w())
|
||||
return true;
|
||||
else return false;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -190,17 +190,21 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
|
|||
//bvhTree.buildBvhTree(initBound.data(), initBound.size());
|
||||
|
||||
|
||||
vector<vector<Point>> lineSet = SvgParser::parse("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100,100);
|
||||
|
||||
//vector<vector<Point>> lineSet = SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse();
|
||||
vector<vector<Point>> 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();
|
||||
qDebug() << lineSet.size();
|
||||
for (vector<Point> line : lineSet)
|
||||
{
|
||||
for (Point p : line)
|
||||
p.show();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
//vector<vector<Point>> 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<vector<Point>> 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(3);
|
||||
shortCutTree.buildShortCutTree(lineSet);
|
||||
vector<float> pointVector;
|
||||
vector<GLuint> lineVector;
|
||||
|
|
|
@ -736,7 +736,8 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, inout vec3 deb
|
|||
{
|
||||
if (leftChild >= elementBvhLength)
|
||||
{
|
||||
debugBVH.r += 0.5;
|
||||
if (any(greaterThan(bound.xy+vec2(0.001), localUV)) || any(greaterThan(localUV, bound.zw-vec2(0.001))))
|
||||
debugBVH.r += 1;
|
||||
|
||||
uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y;
|
||||
// for(int i = 0; i<200;i++)
|
||||
|
@ -915,7 +916,7 @@ void main()
|
|||
|
||||
imageStore(gBaseColor, pixelLocation, vec4(color.rgb,1));
|
||||
//return;
|
||||
if (color.a!=-1)
|
||||
if (color.a!=-1&&debugBVH==vec3(0))
|
||||
imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1));
|
||||
else
|
||||
imageStore(gBaseColor, pixelLocation, vec4(debugBVH,1));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "ShortCutTree.h"
|
||||
#include <qDebug>
|
||||
|
||||
void ShortCutTree::init() {
|
||||
restOfTreeNodes.clear();
|
||||
|
@ -92,7 +93,7 @@ bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNod
|
|||
nowTreeNode.lineSet.push_back(lineIndex);
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << nowTreeNode.lineSet.size() ;
|
||||
if (nowTreeNode.lineSet.size() <= RequiredLineMin) {
|
||||
if (nowTreeNode.lineSet.empty() && nowTreeNode.windingIncrement == 0)
|
||||
return false;
|
||||
|
@ -126,23 +127,26 @@ void ShortCutTree::simplifyLineVector() {
|
|||
|
||||
void ShortCutTree::spliteToShortCutTree() {
|
||||
queue<ShortCutNode> Q;
|
||||
queue<pair<float, float> > lineBound;
|
||||
queue<pair<double, double> > lineBound;
|
||||
ShortCutNode root;
|
||||
int nowEastGroup = 0, eastGroupSize = 1;
|
||||
root.bound = QVector4D(-1, -1, 1, 1);
|
||||
for (int i = 0; i < allLine.size(); i++) {
|
||||
root.lineSet.push_back(i);
|
||||
}
|
||||
root.eastGroup = eastGroupSize;
|
||||
Q.push(root);
|
||||
lineBound.push({ -1, 1 });
|
||||
vector<ShortCutNode> tmpTreeNodes, generatedTreeNodes;
|
||||
while (!lineBound.empty()) {
|
||||
// 取出一行的所有可行方格
|
||||
++nowEastGroup;
|
||||
auto segment = lineBound.front();
|
||||
float yMid = (segment.first + segment.second) / 2;
|
||||
double yMid = (segment.first + segment.second) / 2;
|
||||
lineBound.pop();
|
||||
while (!Q.empty()) {
|
||||
auto nowTreeNode = Q.front();
|
||||
if (nowTreeNode.bound.y() <= segment.first && segment.second <= nowTreeNode.bound.w()) {
|
||||
if (nowTreeNode.eastGroup == nowEastGroup) {
|
||||
tmpTreeNodes.push_back(nowTreeNode);
|
||||
Q.pop();
|
||||
}
|
||||
|
@ -167,7 +171,7 @@ void ShortCutTree::spliteToShortCutTree() {
|
|||
}
|
||||
else {
|
||||
ShortCutNode nwTreeNode, neTreeNode;
|
||||
float xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2;
|
||||
double xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2;
|
||||
neTreeNode.bound = QVector4D(xMid, yMid, nowTreeNode.bound.z(), nowTreeNode.bound.w());
|
||||
isDivided |= handleShortCutNode(nowTreeNode, neTreeNode, yMid, generatedTreeNodes, sumIncrement);
|
||||
nwTreeNode.bound = QVector4D(nowTreeNode.bound.x(), yMid, xMid, nowTreeNode.bound.w());
|
||||
|
@ -175,8 +179,10 @@ void ShortCutTree::spliteToShortCutTree() {
|
|||
}
|
||||
}
|
||||
if (isDivided) {
|
||||
++eastGroupSize;
|
||||
lineBound.push({yMid, segment.second});
|
||||
for (auto& nowTreeNode : generatedTreeNodes) {
|
||||
for (auto nowTreeNode : generatedTreeNodes) {
|
||||
nowTreeNode.eastGroup = eastGroupSize;
|
||||
Q.push(nowTreeNode);
|
||||
}
|
||||
}
|
||||
|
@ -186,13 +192,18 @@ void ShortCutTree::spliteToShortCutTree() {
|
|||
isDivided = false;
|
||||
for (auto& nowTreeNode : tmpTreeNodes) {
|
||||
if (!nowTreeNode.divided) {
|
||||
sumIncrement += nowTreeNode.windingIncrement;
|
||||
for (int& lineIndex : nowTreeNode.lineSet) {
|
||||
int type = allLine[lineIndex]->judgeBoundIntersection(segment.first, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
||||
if (type == 2)
|
||||
sumIncrement++;
|
||||
if (type == 3)
|
||||
sumIncrement--;
|
||||
}
|
||||
generatedTreeNodes.push_back(nowTreeNode);
|
||||
}
|
||||
else {
|
||||
ShortCutNode seTreeNode, swTreeNode;
|
||||
float xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2;
|
||||
yMid = (nowTreeNode.bound.y() + nowTreeNode.bound.w()) / 2;
|
||||
seTreeNode.bound = QVector4D(xMid, nowTreeNode.bound.y(), nowTreeNode.bound.z(), yMid);
|
||||
isDivided |= handleShortCutNode(nowTreeNode, seTreeNode, segment.first, generatedTreeNodes, sumIncrement);
|
||||
swTreeNode.bound = QVector4D(nowTreeNode.bound.x(), nowTreeNode.bound.y(), xMid, yMid);
|
||||
|
@ -200,11 +211,14 @@ void ShortCutTree::spliteToShortCutTree() {
|
|||
}
|
||||
}
|
||||
if (isDivided) {
|
||||
++eastGroupSize;
|
||||
lineBound.push({segment.first, yMid});
|
||||
for (auto& nowTreeNode : generatedTreeNodes) {
|
||||
for (auto nowTreeNode : generatedTreeNodes) {
|
||||
nowTreeNode.eastGroup = eastGroupSize;
|
||||
Q.push(nowTreeNode);
|
||||
}
|
||||
}
|
||||
tmpTreeNodes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ using std::for_each;
|
|||
|
||||
struct ShortCutNode {
|
||||
typedef vector<Point> vectorPoint;
|
||||
int windingIncrement;
|
||||
int windingIncrement, eastGroup;
|
||||
bool divided;
|
||||
/* type 代表进入广度优先搜索队列的节点种类:
|
||||
0:不需要拆开的节点
|
||||
|
@ -20,6 +20,7 @@ struct ShortCutNode {
|
|||
ShortCutNode() {
|
||||
divided = true;
|
||||
windingIncrement = 0;
|
||||
eastGroup = 0;
|
||||
lineSet.clear();
|
||||
bound = { 0, 0, 0, 0 };
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ double StraightLine::getLineValueByT(double t, bool isY) {
|
|||
}
|
||||
else {
|
||||
valueBegin = *vX.begin();
|
||||
valueEnd = *vY.rbegin();
|
||||
valueEnd = *vX.rbegin();
|
||||
}
|
||||
return t * (valueEnd - valueBegin) + valueBegin;
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ int StraightLine::judgeBoundIntersection(double xy, double l, double r, bool isY
|
|||
}
|
||||
return 0;
|
||||
} else {
|
||||
if (pointBegin.y <= l && pointEnd.y < l) return 0;
|
||||
if (pointBegin.y >= r && pointEnd.y > r) return 0;
|
||||
if (pointBegin.y <= l && pointEnd.y <= l) return 0;
|
||||
if (pointBegin.y >= r && pointEnd.y >= r) return 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -1,44 +1,594 @@
|
|||
#include "SvgParser.h"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
vector<vector<Point>> SvgParser::parse(const std::string path, float width, float height)
|
||||
{
|
||||
std::string tmp;
|
||||
vector<double> point;
|
||||
vector<Point> line;
|
||||
vector<vector<Point>> 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<double> elements) {
|
||||
int commandLength = getCommandLength(t);
|
||||
SVGPath chunk;
|
||||
bool abs = isAbsolute(t);
|
||||
if (t == SVG_CLOSE_PATH) chunk.push_back(make_shared<SVGClosePath>());
|
||||
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<SVGLineTo>(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<SVGMoveTo>(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<SVGCubicCurveTo>(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<SVGSmoothCubicCurveTo>(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<SVGQuadraticCurveTo>(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<SVGSmoothQuadraticCurveTo>(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<SVGArcTo>(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<SVGHLineTo>(elements[i * commandLength + 0], abs));
|
||||
break;
|
||||
case SVG_VERTICAL_LINE_TO_REL:
|
||||
case SVG_VERTICAL_LINE_TO_ABS:
|
||||
chunk.push_back(make_shared<SVGVLineTo>(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<double> 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<vector<Point>> SvgParser::parse()
|
||||
{
|
||||
vector<Point> line;
|
||||
vector<vector<Point>> lines;
|
||||
|
||||
istringstream stringStream(path);
|
||||
SVGPath svgPath = parsePath(stringStream);
|
||||
for (shared_ptr<SVGCommand> svgCmd : svgPath)
|
||||
{
|
||||
switch (svgCmd->getType())
|
||||
{
|
||||
case SVG_MOVE_TO_ABS:
|
||||
{
|
||||
shared_ptr<SVGMoveTo> cmd = static_pointer_cast<SVGMoveTo>(svgCmd);
|
||||
line.push_back(convertAbsPoint(cmd->x, cmd->y));
|
||||
break;
|
||||
}
|
||||
case SVG_LINE_TO_REL:
|
||||
{
|
||||
shared_ptr<SVGLineTo> cmd = static_pointer_cast<SVGLineTo>(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<SVGLineTo> cmd = static_pointer_cast<SVGLineTo>(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<SVGHLineTo> cmd = static_pointer_cast<SVGHLineTo>(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<SVGHLineTo> cmd = static_pointer_cast<SVGHLineTo>(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<SVGVLineTo> cmd = static_pointer_cast<SVGVLineTo>(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<SVGVLineTo> cmd = static_pointer_cast<SVGVLineTo>(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<SVGQuadraticCurveTo> cmd = static_pointer_cast<SVGQuadraticCurveTo>(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<SVGQuadraticCurveTo> cmd = static_pointer_cast<SVGQuadraticCurveTo>(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<SVGCubicCurveTo> cmd = static_pointer_cast<SVGCubicCurveTo>(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<SVGCubicCurveTo> cmd = static_pointer_cast<SVGCubicCurveTo>(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<SVGArcTo> cmd = static_pointer_cast<SVGArcTo>(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<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:
|
||||
{
|
||||
line.push_back(lines[0][0]);
|
||||
lines.push_back(line);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cout << "PARSE ERROR" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lines.erase(lines.begin());
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,139 @@
|
|||
|
||||
#include <string>
|
||||
#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<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*);
|
||||
};
|
||||
class SvgParser
|
||||
{
|
||||
public:
|
||||
static vector<vector<Point>> parse(const std::string path, float width, float height);
|
||||
SvgParser(const std::string path, const double width, const double height) ;
|
||||
vector<vector<Point>> 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);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue