初步完成了LineTree,待测试
parent
f3b0a3069c
commit
2745e8c47b
|
@ -1,6 +1,8 @@
|
||||||
#include "CubicBezier.h"
|
#include "CubicBezier.h"
|
||||||
|
#include "CubicBezierSignedDistance.h"
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
using std::swap;
|
||||||
double CubicBezier::getLineValueByT(double t, bool isY) {
|
double CubicBezier::getLineValueByT(double t, bool isY) {
|
||||||
vector<double> p;
|
vector<double> p;
|
||||||
if (isY) p = vY;
|
if (isY) p = vY;
|
||||||
|
@ -101,7 +103,7 @@ double CubicBezier::findTByValue(double value, bool isY) {
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CubicBezier::judgeBoundIntersection(double xy, double l, double r, bool isY) {
|
int CubicBezier::judgeOneSideIntersection(double xy, double l, double r, bool isY) {
|
||||||
double valueBegin = *vX.begin(), valueEnd = *vX.rbegin();
|
double valueBegin = *vX.begin(), valueEnd = *vX.rbegin();
|
||||||
if (isY) {
|
if (isY) {
|
||||||
valueBegin = *vY.begin();
|
valueBegin = *vY.begin();
|
||||||
|
@ -115,3 +117,7 @@ int CubicBezier::judgeBoundIntersection(double xy, double l, double r, bool isY)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double CubicBezier::getMinDistanceFromPoint(Point p) {
|
||||||
|
return CubicBezierSignedDistance::cubic_bezier_dis(p, getBegin(), getPointByIndex(1), getPointByIndex(2), getEnd());
|
||||||
|
}
|
|
@ -15,7 +15,8 @@ namespace Renderer
|
||||||
virtual double findTByValue(double value, bool isY);
|
virtual double findTByValue(double value, bool isY);
|
||||||
virtual void monotonization(std::vector <LinePtr>& res);
|
virtual void monotonization(std::vector <LinePtr>& res);
|
||||||
virtual double getLineValueByT(double t, bool isY);
|
virtual double getLineValueByT(double t, bool isY);
|
||||||
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY);
|
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
|
||||||
|
virtual double getMinDistanceFromPoint(Point p);
|
||||||
void transformToCubic();
|
void transformToCubic();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,10 +81,10 @@ int Line::direction(bool isY) {
|
||||||
|
|
||||||
bool Line::judgeIntersection(QVector4D bound) {
|
bool Line::judgeIntersection(QVector4D bound) {
|
||||||
return isLineContained(bound)
|
return isLineContained(bound)
|
||||||
|| judgeBoundIntersection(bound.y(), bound.x(), bound.z(), true)
|
|| judgeOneSideIntersection(bound.y(), bound.x(), bound.z(), true)
|
||||||
|| judgeBoundIntersection(bound.w(), bound.x(), bound.z(), true)
|
|| judgeOneSideIntersection(bound.w(), bound.x(), bound.z(), true)
|
||||||
|| judgeBoundIntersection(bound.x(), bound.y(), bound.w(), false)
|
|| judgeOneSideIntersection(bound.x(), bound.y(), bound.w(), false)
|
||||||
|| judgeBoundIntersection(bound.z(), bound.y(), bound.w(), false);
|
|| judgeOneSideIntersection(bound.z(), bound.y(), bound.w(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Line::upwardOffsetForY(bool isStart, double offset) {
|
void Line::upwardOffsetForY(bool isStart, double offset) {
|
||||||
|
@ -95,3 +95,57 @@ void Line::upwardOffsetForY(bool isStart, double offset) {
|
||||||
vY[siz - 1] = vY[siz - 1] + offset;
|
vY[siz - 1] = vY[siz - 1] + offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point Line::getMinDistancePointOnSide(double xy, double l, double r, bool isY) {
|
||||||
|
Point pMid = { xy, l }, pMidr = { xy, r };
|
||||||
|
if (isY) {
|
||||||
|
swap(pMid.x, pMid.y);
|
||||||
|
swap(pMidr.x, pMidr.y);
|
||||||
|
}
|
||||||
|
double mid, midr;
|
||||||
|
while (fabs(r - l) > eps) {
|
||||||
|
mid = (l + r) / 2;
|
||||||
|
midr = (mid + r) / 2;
|
||||||
|
if (isY) {
|
||||||
|
pMid.x = mid;
|
||||||
|
pMidr.x = midr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pMid.y = mid;
|
||||||
|
pMidr.y = midr;
|
||||||
|
}
|
||||||
|
if (getMinDistanceFromPoint(pMid) > getMinDistanceFromPoint(pMidr)) {
|
||||||
|
l = mid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = midr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Point ans = { xy, l };
|
||||||
|
if (isY) swap(ans.x, ans.y);
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Line::getPointSideOfLine(Point p) {
|
||||||
|
// 1 Ϊ×ó²à£¬ 2 ΪÓÒ²à
|
||||||
|
double z = (p.x - vX[0]) * (*vY.rbegin() - vY[0]) - (p.y - vY[0]) * (*vX.rbegin() - vX[0]);
|
||||||
|
if (z == 0) return 0;
|
||||||
|
else if(z>0) return 1;
|
||||||
|
else return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Line::judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type) {
|
||||||
|
Point p = getMinDistancePointOnSide(xy, l, r, isY);
|
||||||
|
if (type && getPointSideOfLine(p) != type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getMinDistanceFromPoint(p) <= width;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Line::judgeIntersectionWithWidth(QVector4D bound, double width, int type) {
|
||||||
|
return isLineContained(bound)
|
||||||
|
|| judgeOneSideIntersectionWithWidth(bound.y(), bound.x(), bound.z(), true, width, type)
|
||||||
|
|| judgeOneSideIntersectionWithWidth(bound.w(), bound.x(), bound.z(), true, width, type)
|
||||||
|
|| judgeOneSideIntersectionWithWidth(bound.x(), bound.y(), bound.w(), false, width, type)
|
||||||
|
|| judgeOneSideIntersectionWithWidth(bound.z(), bound.y(), bound.w(), false, width, type);
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,9 @@ namespace Renderer
|
||||||
bool operator< (const Point& a) const {
|
bool operator< (const Point& a) const {
|
||||||
return fabs(x - a.x) <= eps ? y < a.y : x < a.x;
|
return fabs(x - a.x) <= eps ? y < a.y : x < a.x;
|
||||||
}
|
}
|
||||||
|
operator glm::dvec2() {
|
||||||
|
return glm::dvec2(x, y);
|
||||||
|
}
|
||||||
void show() {
|
void show() {
|
||||||
std::cout << '(' << x << ',' << y << ')' << ' ';
|
std::cout << '(' << x << ',' << y << ')' << ' ';
|
||||||
}
|
}
|
||||||
|
@ -45,8 +49,13 @@ namespace Renderer
|
||||||
int direction(bool isY);
|
int direction(bool isY);
|
||||||
virtual double getLineValueByT(double t, bool isY) = 0;
|
virtual double getLineValueByT(double t, bool isY) = 0;
|
||||||
virtual void monotonization(std::vector <LinePtr>& res) = 0;
|
virtual void monotonization(std::vector <LinePtr>& res) = 0;
|
||||||
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY) = 0;
|
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0;
|
||||||
virtual bool judgeIntersection(QVector4D bound);
|
virtual double getMinDistanceFromPoint(Point p) = 0;
|
||||||
|
bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type);
|
||||||
|
bool judgeIntersectionWithWidth(QVector4D bound, double width, int type);
|
||||||
|
bool judgeIntersection(QVector4D bound);
|
||||||
|
int getPointSideOfLine(Point p);
|
||||||
|
Point getMinDistancePointOnSide(double xy, double l, double r, bool isY);
|
||||||
// virtual double minDistanceToLine(Point uv);
|
// virtual double minDistanceToLine(Point uv);
|
||||||
void upwardOffsetForY(bool isStart, double offset);
|
void upwardOffsetForY(bool isStart, double offset);
|
||||||
bool isLineContained(QVector4D bound);
|
bool isLineContained(QVector4D bound);
|
||||||
|
@ -58,3 +67,4 @@ namespace Renderer
|
||||||
virtual ~Line() {}
|
virtual ~Line() {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
#include "LineTree.h"
|
#include "LineTree.h"
|
||||||
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
using std::set;
|
using std::set;
|
||||||
|
using std::pair;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
using std::queue;
|
||||||
|
|
||||||
void LineTree::init() {
|
void LineTree::init() {
|
||||||
restOfTreeNodes.clear();
|
restOfTreeNodes.clear();
|
||||||
allLine.clear();
|
allLines.clear();
|
||||||
pointMap.clear();
|
pointMap.clear();
|
||||||
lineIndexs.clear();
|
lineIndexs.clear();
|
||||||
numLine = numPoint = 0;
|
numLine = numPoint = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineTree::setLineWidth(int width) {
|
void LineTree::setLineWidth(double width) {
|
||||||
lineWidth = width;
|
lineWidth = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +108,8 @@ void LineTree::monotonization(vector<PointVector>& inLines, vector<std::shared_p
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineTree::simplifyLineVector() {
|
void LineTree::simplifyLineVector() {
|
||||||
numLine = allLine.size();
|
numLine = allLines.size();
|
||||||
for (auto& nowLine : allLine) {
|
for (auto& nowLine : allLines) {
|
||||||
PointVector pointVector = nowLine->toPointVector();
|
PointVector pointVector = nowLine->toPointVector();
|
||||||
for (Point& p : pointVector) {
|
for (Point& p : pointVector) {
|
||||||
int pointIndex = getPointIndex(p);
|
int pointIndex = getPointIndex(p);
|
||||||
|
@ -115,3 +119,147 @@ void LineTree::simplifyLineVector() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LineTree::handleShortCutNode(LineTreeNode& fa, LineTreeNode& nowTreeNode, double yValue, std::vector<LineTreeNode>& v) {
|
||||||
|
for (int& lineIndex : fa.lineSet) {
|
||||||
|
if (allLines[lineIndex]->judgeIntersectionWithWidth(nowTreeNode.bound, lineWidth, lineType)) {
|
||||||
|
nowTreeNode.lineSet.push_back(lineIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nowTreeNode.lineSet.size() <= requiredLineMin) {
|
||||||
|
if (nowTreeNode.lineSet.empty())
|
||||||
|
return false;
|
||||||
|
restOfTreeNodes.push_back(nowTreeNode);
|
||||||
|
nowTreeNode.divided = false;
|
||||||
|
v.push_back(nowTreeNode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.push_back(nowTreeNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineTree::spliteToLineTree() {
|
||||||
|
// 防止直线的点落在边界上
|
||||||
|
set<double> xLineSet, yLineSet;
|
||||||
|
for (int i = 0; i < allLines.size(); i++) {
|
||||||
|
xLineSet.insert(allLines[i]->getBegin().x);
|
||||||
|
xLineSet.insert(allLines[i]->getEnd().x);
|
||||||
|
yLineSet.insert(allLines[i]->getBegin().y);
|
||||||
|
yLineSet.insert(allLines[i]->getEnd().y);
|
||||||
|
}
|
||||||
|
// 生成方格
|
||||||
|
queue<LineTreeNode> Q;
|
||||||
|
queue<pair<double, double> > lineBound;
|
||||||
|
LineTreeNode root;
|
||||||
|
int nowEastGroup = 0, eastGroupSize = 1;
|
||||||
|
root.bound = QVector4D(-1, -1, 1, 1);
|
||||||
|
for (int i = 0; i < allLines.size(); i++) {
|
||||||
|
root.lineSet.push_back(i);
|
||||||
|
}
|
||||||
|
root.eastGroup = eastGroupSize;
|
||||||
|
Q.push(root);
|
||||||
|
lineBound.push({ -1, 1 });
|
||||||
|
vector<LineTreeNode> tmpTreeNodes, upperTreeNodes, lowerTreeNodes;
|
||||||
|
bool isUpperDivided = false, isLowerDivided = false;
|
||||||
|
while (!lineBound.empty()) {
|
||||||
|
// 取出一行的所有可行方格
|
||||||
|
++nowEastGroup;
|
||||||
|
auto segment = lineBound.front(); lineBound.pop();
|
||||||
|
double yMid = (segment.first + segment.second) / 2;
|
||||||
|
yMid = findBorderValueNotOnLine(yMid, yLineSet);
|
||||||
|
while (!Q.empty()) {
|
||||||
|
auto nowTreeNode = Q.front();
|
||||||
|
if (nowTreeNode.eastGroup == nowEastGroup) {
|
||||||
|
tmpTreeNodes.push_back(nowTreeNode);
|
||||||
|
Q.pop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isUpperDivided = false; isLowerDivided = false;
|
||||||
|
upperTreeNodes.clear(); lowerTreeNodes.clear();
|
||||||
|
// 处理方格;
|
||||||
|
for (auto& nowTreeNode : tmpTreeNodes) {
|
||||||
|
LineTreeNode nwTreeNode, neTreeNode, seTreeNode, swTreeNode;
|
||||||
|
double xMid = (nowTreeNode.bound.x() + nowTreeNode.bound.z()) / 2;
|
||||||
|
xMid = findBorderValueNotOnLine(xMid, xLineSet);
|
||||||
|
// 上部分
|
||||||
|
neTreeNode.bound = QVector4D(xMid, yMid, nowTreeNode.bound.z(), nowTreeNode.bound.w());
|
||||||
|
isUpperDivided |= handleShortCutNode(nowTreeNode, neTreeNode, yMid, upperTreeNodes);
|
||||||
|
nwTreeNode.bound = QVector4D(nowTreeNode.bound.x(), yMid, xMid, nowTreeNode.bound.w());
|
||||||
|
isUpperDivided |= handleShortCutNode(nowTreeNode, nwTreeNode, yMid, upperTreeNodes);
|
||||||
|
// 下部分
|
||||||
|
seTreeNode.bound = QVector4D(xMid, nowTreeNode.bound.y(), nowTreeNode.bound.z(), yMid);
|
||||||
|
isLowerDivided |= handleShortCutNode(nowTreeNode, seTreeNode, segment.first, lowerTreeNodes);
|
||||||
|
swTreeNode.bound = QVector4D(nowTreeNode.bound.x(), nowTreeNode.bound.y(), xMid, yMid);
|
||||||
|
isLowerDivided |= handleShortCutNode(nowTreeNode, swTreeNode, segment.first, lowerTreeNodes);
|
||||||
|
}
|
||||||
|
if (isUpperDivided) {
|
||||||
|
++eastGroupSize;
|
||||||
|
lineBound.push({ yMid, segment.second });
|
||||||
|
for (auto& nowTreeNode : upperTreeNodes) {
|
||||||
|
nowTreeNode.eastGroup = eastGroupSize;
|
||||||
|
Q.push(nowTreeNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isLowerDivided) {
|
||||||
|
++eastGroupSize;
|
||||||
|
lineBound.push({ segment.first, yMid });
|
||||||
|
for (auto& nowTreeNode : lowerTreeNodes) {
|
||||||
|
nowTreeNode.eastGroup = eastGroupSize;
|
||||||
|
Q.push(nowTreeNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmpTreeNodes.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineTree::buildLineTree(std::vector<PointVector>& lineSet, double width, int type) {
|
||||||
|
init();
|
||||||
|
lineWidth = width;
|
||||||
|
lineType = type;
|
||||||
|
monotonization(lineSet, allLines);
|
||||||
|
spliteToLineTree();
|
||||||
|
simplifyLineVector();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<BvhTreeData> LineTree::getPointLineAndBvhTree(vector<float>& resPoints, vector<GLuint>& resLines) {
|
||||||
|
// 点集
|
||||||
|
vector<pair<GLuint, Point> > tmpPoints; tmpPoints.clear();
|
||||||
|
for (auto& mapIter : pointMap) {
|
||||||
|
tmpPoints.push_back({ mapIter.second , mapIter.first });
|
||||||
|
}
|
||||||
|
sort(tmpPoints.begin(), tmpPoints.end());
|
||||||
|
for (auto& vectorIter : tmpPoints) {
|
||||||
|
resPoints.push_back(vectorIter.second.x);
|
||||||
|
resPoints.push_back(vectorIter.second.y);
|
||||||
|
vectorIter.second.show();
|
||||||
|
std::cout << '\n';
|
||||||
|
}
|
||||||
|
// 线集
|
||||||
|
for (auto& nowLineIndex : lineIndexs) {
|
||||||
|
resLines.push_back(nowLineIndex);
|
||||||
|
std::cout << nowLineIndex << ' ';
|
||||||
|
}
|
||||||
|
std::cout << '\n';
|
||||||
|
// 返回构造BvhTree数据
|
||||||
|
vector<BvhTreeData> resBvhTreeData;
|
||||||
|
for (auto& nowTreeNode : restOfTreeNodes) {
|
||||||
|
BvhTreeData oneData;
|
||||||
|
oneData.leftSon = resLines.size();
|
||||||
|
//oneData.rightSon = rightSon;
|
||||||
|
oneData.bound = nowTreeNode.bound;
|
||||||
|
std::cout << nowTreeNode.lineSet.size() << ' ';
|
||||||
|
resLines.push_back(nowTreeNode.lineSet.size());
|
||||||
|
for (auto& lineIndex : nowTreeNode.lineSet) {
|
||||||
|
resLines.push_back(lineIndex);
|
||||||
|
std::cout << lineIndex << ' ';
|
||||||
|
}
|
||||||
|
std::cout << '\n';
|
||||||
|
resBvhTreeData.push_back(oneData);
|
||||||
|
}
|
||||||
|
return resBvhTreeData;
|
||||||
|
}
|
|
@ -27,10 +27,12 @@ namespace Renderer {
|
||||||
typedef std::vector<int> PointIndexVector;
|
typedef std::vector<int> PointIndexVector;
|
||||||
private:
|
private:
|
||||||
std::vector<LineTreeNode> restOfTreeNodes;
|
std::vector<LineTreeNode> restOfTreeNodes;
|
||||||
std::vector<std::shared_ptr<Line>> allLine;
|
std::vector<std::shared_ptr<Line>> allLines;
|
||||||
int requiredLineMin, numPoint, numLine, lineWidth;
|
int requiredLineMin, numPoint, numLine;
|
||||||
std::map<Point, int> pointMap;
|
std::map<Point, int> pointMap;
|
||||||
std::vector<int> lineIndexs;
|
std::vector<int> lineIndexs;
|
||||||
|
double lineWidth;
|
||||||
|
int lineType;
|
||||||
|
|
||||||
int getPointIndex(Point nowPoint);
|
int getPointIndex(Point nowPoint);
|
||||||
void spliteToLineTree();
|
void spliteToLineTree();
|
||||||
|
@ -42,10 +44,10 @@ namespace Renderer {
|
||||||
static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& outL);
|
static void monotonization(std::vector<PointVector>& inL, std::vector<std::shared_ptr<Line>>& outL);
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void setLineWidth(int width);
|
void setLineWidth(double width);
|
||||||
LineTree(int lineMin = 3, int width = 0.3)
|
LineTree(int lineMin = 3, int width = 0.3)
|
||||||
: requiredLineMin(lineMin), lineWidth(width), numLine(0), numPoint(0) {}
|
: requiredLineMin(lineMin), lineWidth(width), numLine(0), numPoint(0) {}
|
||||||
void buildLineTree(std::vector<PointVector>& lineSet);
|
void buildLineTree(std::vector<PointVector>& lineSet, double width, int type = 0);
|
||||||
std::vector<BvhTreeData> getPointLineAndBvhTree(std::vector<float>& pointSet, std::vector<GLuint>& lineSet);
|
std::vector<BvhTreeData> getPointLineAndBvhTree(std::vector<float>& pointSet, std::vector<GLuint>& lineSet);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@ using std::pair;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
void ShortCutTree::init() {
|
void ShortCutTree::init() {
|
||||||
restOfTreeNodes.clear();
|
restOfTreeNodes.clear();
|
||||||
allLine.clear();
|
allLines.clear();
|
||||||
pointMap.clear();
|
pointMap.clear();
|
||||||
lineIndexs.clear();
|
lineIndexs.clear();
|
||||||
numLine = numPoint = 0;
|
numLine = numPoint = 0;
|
||||||
|
@ -80,13 +80,13 @@ void ShortCutTree::generateShortCutSegment(ShortCutNode& nowTreeNode) {
|
||||||
Point p = {0, 0};
|
Point p = {0, 0};
|
||||||
set<pair<int, int> > pointSet;
|
set<pair<int, int> > pointSet;
|
||||||
for (int & lineIndex : nowTreeNode.lineSet) {
|
for (int & lineIndex : nowTreeNode.lineSet) {
|
||||||
int type = allLine[lineIndex]->judgeBoundIntersection(nowTreeNode.bound.z(), nowTreeNode.bound.y(), nowTreeNode.bound.w(), false), lineIndexBegin, lineIndexEnd;
|
int type = allLines[lineIndex]->judgeOneSideIntersection(nowTreeNode.bound.z(), nowTreeNode.bound.y(), nowTreeNode.bound.w(), false), lineIndexBegin, lineIndexEnd;
|
||||||
if (type >= 2) {
|
if (type >= 2) {
|
||||||
if (type == 2) {
|
if (type == 2) {
|
||||||
p = allLine[lineIndex]->getEnd();
|
p = allLines[lineIndex]->getEnd();
|
||||||
}
|
}
|
||||||
if (type == 3) {
|
if (type == 3) {
|
||||||
p = allLine[lineIndex]->getBegin();
|
p = allLines[lineIndex]->getBegin();
|
||||||
}
|
}
|
||||||
lineIndexBegin = getPointIndex({ nowTreeNode.bound.z(), nowTreeNode.bound.w()});
|
lineIndexBegin = getPointIndex({ nowTreeNode.bound.z(), nowTreeNode.bound.w()});
|
||||||
lineIndexEnd = getPointIndex({ nowTreeNode.bound.z(), p.y });
|
lineIndexEnd = getPointIndex({ nowTreeNode.bound.z(), p.y });
|
||||||
|
@ -123,12 +123,12 @@ void ShortCutTree::generateShortCutSegment(ShortCutNode& nowTreeNode) {
|
||||||
bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, double yValue, vector<ShortCutNode>& v, int& sumIncrement) {
|
bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, double yValue, vector<ShortCutNode>& v, int& sumIncrement) {
|
||||||
nowTreeNode.windingIncrement = sumIncrement;
|
nowTreeNode.windingIncrement = sumIncrement;
|
||||||
for (int & lineIndex : fa.lineSet) {
|
for (int & lineIndex : fa.lineSet) {
|
||||||
int type = allLine[lineIndex]->judgeBoundIntersection(yValue, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
int type = allLines[lineIndex]->judgeOneSideIntersection(yValue, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
||||||
if (type == 2)
|
if (type == 2)
|
||||||
sumIncrement++;
|
sumIncrement++;
|
||||||
if (type == 3)
|
if (type == 3)
|
||||||
sumIncrement--;
|
sumIncrement--;
|
||||||
if (allLine[lineIndex]->judgeIntersection(nowTreeNode.bound)) {
|
if (allLines[lineIndex]->judgeIntersection(nowTreeNode.bound)) {
|
||||||
nowTreeNode.lineSet.push_back(lineIndex);
|
nowTreeNode.lineSet.push_back(lineIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,8 +149,8 @@ bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNod
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortCutTree::simplifyLineVector() {
|
void ShortCutTree::simplifyLineVector() {
|
||||||
numLine = allLine.size();
|
numLine = allLines.size();
|
||||||
for (auto& nowLine : allLine) {
|
for (auto& nowLine : allLines) {
|
||||||
PointVector pointVector = nowLine->toPointVector();
|
PointVector pointVector = nowLine->toPointVector();
|
||||||
for (Point& p : pointVector) {
|
for (Point& p : pointVector) {
|
||||||
int pointIndex = getPointIndex(p);
|
int pointIndex = getPointIndex(p);
|
||||||
|
@ -167,11 +167,11 @@ void ShortCutTree::simplifyLineVector() {
|
||||||
void ShortCutTree::spliteToShortCutTree() {
|
void ShortCutTree::spliteToShortCutTree() {
|
||||||
// 防止直线的点落在边界上
|
// 防止直线的点落在边界上
|
||||||
set<double> xLineSet, yLineSet;
|
set<double> xLineSet, yLineSet;
|
||||||
for (int i = 0; i < allLine.size(); i++) {
|
for (int i = 0; i < allLines.size(); i++) {
|
||||||
xLineSet.insert(allLine[i]->getBegin().x);
|
xLineSet.insert(allLines[i]->getBegin().x);
|
||||||
xLineSet.insert(allLine[i]->getEnd().x);
|
xLineSet.insert(allLines[i]->getEnd().x);
|
||||||
yLineSet.insert(allLine[i]->getBegin().y);
|
yLineSet.insert(allLines[i]->getBegin().y);
|
||||||
yLineSet.insert(allLine[i]->getEnd().y);
|
yLineSet.insert(allLines[i]->getEnd().y);
|
||||||
}
|
}
|
||||||
// 生成方格
|
// 生成方格
|
||||||
queue<ShortCutNode> Q;
|
queue<ShortCutNode> Q;
|
||||||
|
@ -179,7 +179,7 @@ void ShortCutTree::spliteToShortCutTree() {
|
||||||
ShortCutNode root;
|
ShortCutNode root;
|
||||||
int nowEastGroup = 0, eastGroupSize = 1;
|
int nowEastGroup = 0, eastGroupSize = 1;
|
||||||
root.bound = QVector4D(-1, -1, 1, 1);
|
root.bound = QVector4D(-1, -1, 1, 1);
|
||||||
for (int i = 0; i < allLine.size(); i++) {
|
for (int i = 0; i < allLines.size(); i++) {
|
||||||
root.lineSet.push_back(i);
|
root.lineSet.push_back(i);
|
||||||
}
|
}
|
||||||
root.eastGroup = eastGroupSize;
|
root.eastGroup = eastGroupSize;
|
||||||
|
@ -212,13 +212,13 @@ void ShortCutTree::spliteToShortCutTree() {
|
||||||
if (!nowTreeNode.divided) {
|
if (!nowTreeNode.divided) {
|
||||||
for (int& lineIndex : nowTreeNode.lineSet) {
|
for (int& lineIndex : nowTreeNode.lineSet) {
|
||||||
// 上半部分
|
// 上半部分
|
||||||
int type = allLine[lineIndex]->judgeBoundIntersection(yMid, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
int type = allLines[lineIndex]->judgeOneSideIntersection(yMid, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
||||||
if (type == 2)
|
if (type == 2)
|
||||||
sumUpperIncrement++;
|
sumUpperIncrement++;
|
||||||
if (type == 3)
|
if (type == 3)
|
||||||
sumUpperIncrement--;
|
sumUpperIncrement--;
|
||||||
// 下半部分
|
// 下半部分
|
||||||
type = allLine[lineIndex]->judgeBoundIntersection(segment.first, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
type = allLines[lineIndex]->judgeOneSideIntersection(segment.first, nowTreeNode.bound.x(), nowTreeNode.bound.z(), true);
|
||||||
if (type == 2)
|
if (type == 2)
|
||||||
sumLowerIncrement++;
|
sumLowerIncrement++;
|
||||||
if (type == 3)
|
if (type == 3)
|
||||||
|
@ -265,7 +265,7 @@ void ShortCutTree::spliteToShortCutTree() {
|
||||||
|
|
||||||
void ShortCutTree::buildShortCutTree(vector<PointVector>& lineSet) {
|
void ShortCutTree::buildShortCutTree(vector<PointVector>& lineSet) {
|
||||||
init();
|
init();
|
||||||
monotonization(lineSet, allLine);
|
monotonization(lineSet, allLines);
|
||||||
spliteToShortCutTree();
|
spliteToShortCutTree();
|
||||||
simplifyLineVector();
|
simplifyLineVector();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace Renderer
|
||||||
typedef std::vector<int> PointIndexVector;
|
typedef std::vector<int> PointIndexVector;
|
||||||
private:
|
private:
|
||||||
std::vector<ShortCutNode> restOfTreeNodes;
|
std::vector<ShortCutNode> restOfTreeNodes;
|
||||||
std::vector<std::shared_ptr<Line>> allLine;
|
std::vector<std::shared_ptr<Line>> allLines;
|
||||||
int requiredLineMin, numPoint, numLine;
|
int requiredLineMin, numPoint, numLine;
|
||||||
std::map<Point, int> pointMap;
|
std::map<Point, int> pointMap;
|
||||||
std::vector<int> lineIndexs;
|
std::vector<int> lineIndexs;
|
||||||
|
|
|
@ -26,7 +26,7 @@ double StraightLine::findTByValue(double value, bool isY) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int StraightLine::judgeBoundIntersection(double xy, double l, double r, bool isY) {
|
int StraightLine::judgeOneSideIntersection(double xy, double l, double r, bool isY) {
|
||||||
Point pointBegin = getBegin(), pointEnd = getEnd();
|
Point pointBegin = getBegin(), pointEnd = getEnd();
|
||||||
if (isY) {
|
if (isY) {
|
||||||
swap(pointBegin.x, pointBegin.y);
|
swap(pointBegin.x, pointBegin.y);
|
||||||
|
@ -47,3 +47,15 @@ int StraightLine::judgeBoundIntersection(double xy, double l, double r, bool isY
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double StraightLine::getMinDistanceFromPoint(Point p) {
|
||||||
|
Point se = { vX[1] - vX[0], vY[1] - vY[0] };
|
||||||
|
Point dd = { p.x - vX[0], p.y - vY[0] };
|
||||||
|
double d = se.x * se.x + se.y * se.y;
|
||||||
|
double t = se.x * dd.x + se.y * dd.y;
|
||||||
|
if (d > 0) t /= d;
|
||||||
|
if (t < 0) t = 0;
|
||||||
|
else if (t > 1) t = 1;
|
||||||
|
double dx = vX[0] + t * se.x - p.x, dy = vY[0] + t * se.y - p.y;
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}
|
|
@ -5,9 +5,11 @@ namespace Renderer
|
||||||
class StraightLine : public Line
|
class StraightLine : public Line
|
||||||
{
|
{
|
||||||
using Line::Line;
|
using Line::Line;
|
||||||
|
public:
|
||||||
virtual double getLineValueByT(double t, bool isY);
|
virtual double getLineValueByT(double t, bool isY);
|
||||||
virtual void monotonization(std::vector <LinePtr>& res) {};
|
virtual void monotonization(std::vector <LinePtr>& res) {};
|
||||||
virtual double findTByValue(double value, bool isY);
|
virtual double findTByValue(double value, bool isY);
|
||||||
virtual int judgeBoundIntersection(double xy, double l, double r, bool isY);
|
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
|
||||||
|
virtual double getMinDistanceFromPoint(Point p);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
#include "Renderer/Painting/CubicBezier.h"
|
||||||
|
|
||||||
|
using Renderer::CubicBezier;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
_declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
|
_declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
|
||||||
|
@ -8,10 +11,6 @@ extern "C" {
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
|
||||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
return 0;
|
||||||
QApplication a(argc, argv);
|
|
||||||
MainWindow w;
|
|
||||||
w.show();
|
|
||||||
return a.exec();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue