From 79883302ac4e1b85d2afd9adcad78646757304ac Mon Sep 17 00:00:00 2001 From: "yang.yongquan" <3395816735@qq.com> Date: Tue, 13 Sep 2022 21:01:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=88=86=E5=89=B2?= =?UTF-8?q?=E7=9A=84=E8=B4=9D=E5=A1=9E=E5=B0=94=E6=9B=B2=E7=BA=BF=E7=9A=84?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 2 + ...rchitectureColoredPainting.vcxproj.filters | 6 ++ .../CubicMonotonization.cpp | 73 +++++++++++++++++++ .../CubicMonotonization.h | 24 ++++++ 4 files changed, 105 insertions(+) create mode 100644 ArchitectureColoredPainting/CubicMonotonization.cpp create mode 100644 ArchitectureColoredPainting/CubicMonotonization.h diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 62c0450..dc95cf0 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -87,6 +87,7 @@ + @@ -123,6 +124,7 @@ + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index ed08f43..092c1d5 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -67,6 +67,9 @@ Source Files + + Source Files + @@ -148,5 +151,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/ArchitectureColoredPainting/CubicMonotonization.cpp b/ArchitectureColoredPainting/CubicMonotonization.cpp new file mode 100644 index 0000000..8e96f1b --- /dev/null +++ b/ArchitectureColoredPainting/CubicMonotonization.cpp @@ -0,0 +1,73 @@ +#include "CubicMonotonization.h" + +const double CubicMonotonization::eps = 1e-6; + + +CubicMonotonization::point CubicMonotonization::getPointByT(point a, point b, double t) const { + return { a.first * (1 - t) + b.first, a.second * (1 - t) + b.second }; +} + + +void CubicMonotonization::findPointsOfDivison(vector p, vector& res) { + double a = -p[0] + 7 * p[1] - 9 * p[2] + 3 * p[3]; + double b = 6 * p[0] - 12 * p[1] + 6 * p[2]; + double c = -3 * p[0] + 3*p[1]; + double deta = b * b - 4*a*c; + if (fabs(deta) < eps) return; + double t = 0; + if (fabs(a) <= eps) { + deta = sqrt(deta); + t = -b + deta; + if (0 < t && t < 1) { + res.push_back(t); + } + if (fabs(deta) <= eps) return ; + t = -b - deta; + if (0 < t && t < 1) { + res.push_back(t); + } + } +} + +double CubicMonotonization::getBezierPoint(vector &p, double t) const{ + double pt = 1 - t; + return pt * pt * pt * p[0] + 3 * t * pt * pt * p[1] + 3 * t * t * pt * p[2] + t * t * t * p[3]; +} + +void CubicMonotonization::splitBezierCubic(Line& p, point mid, double t, vector & res) { + Line Lf; Lf.clear(); + double pt = 1 - t; + Lf.push_back(p[0]); + point pointF = getPointByT(p[0], p[1], t); + point pointG = getPointByT(p[1], p[2], t); + point pointH = getPointByT(p[2], p[3], t); + Lf.push_back(pointF); + Lf.push_back(getPointByT(pointF, pointG, t)); + Lf.push_back(mid); + res.push_back(Lf); + p[0] = mid; + p[1] = getPointByT(pointG, pointH, t); + p[2] = pointH; +} + +void CubicMonotonization::getPointsOfDivision(Line p, vector & res) { + vector vX, vY, re; + vX.clear(); + vY.clear(); + re.clear(); + for (point now : p) { + vX.push_back(now.first); + vY.push_back(now.second); + } + findPointsOfDivison(vX, re); + findPointsOfDivison(vY, re); + sort(re.begin(), re.end()); + double lt = 0, x = 0, y = 0; + for (double &t : re) { + if (fabs(t - lt) <= eps) continue; + x = getBezierPoint(vX, t); + y = getBezierPoint(vY, t); + splitBezierCubic(p, { x, y }, t, res); + lt = t; + } +} diff --git a/ArchitectureColoredPainting/CubicMonotonization.h b/ArchitectureColoredPainting/CubicMonotonization.h new file mode 100644 index 0000000..6531b27 --- /dev/null +++ b/ArchitectureColoredPainting/CubicMonotonization.h @@ -0,0 +1,24 @@ +#include +#include +#include +#pragma once +using std::pair; +using std::vector; +using std::min; +using std::max; +using std::sort; +class CubicMonotonization +{ +typedef pair point; +typedef vector Line; +private: + static const double eps; + point getPointByT(point a, point b, double t) const; + void findPointsOfDivison(vector p, vector &res); + double getBezierPoint(vector &p, double t) const; + void splitBezierCubic(Line& p, point mid, double t, vector &res); +public: + // p 为端点、控制点、控制点、端点, res 为所有导数为0的点 + void getPointsOfDivision(Line p, vector &res); +}; +