mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
Refactoring
This commit is contained in:
committed by
Oleg Korshul
parent
5df63a58b7
commit
9ee9192cd4
@ -3,12 +3,12 @@
|
||||
#include <algorithm>
|
||||
|
||||
namespace Aggplus {
|
||||
Segment::Segment()
|
||||
Segment::Segment() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
Segment::Segment(const std::vector<PointD>& points, bool isCurve,
|
||||
int index, int id, bool polyClosed) :
|
||||
Segment::Segment(const std::vector<PointD>& points, const bool& isCurve,
|
||||
const int& index, const int& id, const bool& polyClosed) noexcept :
|
||||
IsCurve(isCurve),
|
||||
PolyClosed(polyClosed),
|
||||
Index(index),
|
||||
@ -24,33 +24,38 @@ Segment::Segment(const std::vector<PointD>& points, bool isCurve,
|
||||
P = points[0];
|
||||
}
|
||||
|
||||
Segment::Segment(const PointD& p, const PointD& hi, const PointD& ho) :
|
||||
Segment::Segment(const PointD& p) noexcept :
|
||||
P(p)
|
||||
{
|
||||
}
|
||||
|
||||
Segment::Segment(const PointD& p, const PointD& hi, const PointD& ho) noexcept :
|
||||
P(p),
|
||||
HI(hi),
|
||||
HO(ho)
|
||||
{
|
||||
if (!hi.Equals(PointD()) || !ho.Equals(PointD()))
|
||||
if (!hi.IsZero() || !ho.IsZero())
|
||||
IsCurve = true;
|
||||
}
|
||||
|
||||
void Segment::SetHandles(const PointD &hi, const PointD &ho)
|
||||
void Segment::SetHandles(const PointD &hi, const PointD &ho) noexcept
|
||||
{
|
||||
IsCurve = true;
|
||||
HI = PointD(hi.X - P.X, hi.Y - P.Y);
|
||||
HO = PointD(ho.X - P.X, ho.Y - P.Y);
|
||||
}
|
||||
|
||||
void Segment::UpdateHandles(const PointD &hi, const PointD &ho)
|
||||
void Segment::UpdateHandles(const PointD &hi, const PointD &ho) noexcept
|
||||
{
|
||||
HI = hi;
|
||||
HO = ho;
|
||||
}
|
||||
|
||||
bool Segment::IsValid(BooleanOpType op) const
|
||||
bool Segment::IsValid(const BooleanOpType& op) const noexcept
|
||||
{
|
||||
if (Visited)
|
||||
return false;
|
||||
if ((bool)Inters)
|
||||
if (Inters)
|
||||
return true;
|
||||
if (op == Subtraction)
|
||||
{
|
||||
@ -64,90 +69,74 @@ bool Segment::IsValid(BooleanOpType op) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Segment::IsEmpty() const
|
||||
bool Segment::IsEmpty() const noexcept
|
||||
{
|
||||
return Id == 0 && Index == -1 && P.Equals(PointD()) && HI.Equals(PointD()) && HO.Equals(PointD());
|
||||
return Id == 0 && Index == -1 && P.IsZero() && HI.IsZero() && HO.IsZero();
|
||||
}
|
||||
|
||||
bool Segment::operator==(const Segment& other) const
|
||||
bool Segment::operator==(const Segment& other) const noexcept
|
||||
{
|
||||
return (Index == other.Index) && (Id == other.Id);
|
||||
}
|
||||
|
||||
bool Segment::operator!=(const Segment& other) const
|
||||
bool Segment::operator!=(const Segment& other) const noexcept
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
Curve::Curve()
|
||||
Curve::Curve() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
Curve::Curve(const Segment& segment1, const Segment& segment2) :
|
||||
Curve::Curve(const Segment& segment1, const Segment& segment2) noexcept :
|
||||
Segment1(segment1),
|
||||
Segment2(segment2)
|
||||
{
|
||||
}
|
||||
|
||||
Curve::Curve(const std::vector<double>& values)
|
||||
Curve::Curve(const std::vector<double>& values) noexcept
|
||||
{
|
||||
if (values.size() == 4)
|
||||
{
|
||||
Segment1 = Segment(PointD(values[0], values[1]),
|
||||
PointD(),
|
||||
PointD());
|
||||
Segment2 = Segment(PointD(values[2], values[3]),
|
||||
PointD(),
|
||||
PointD());
|
||||
Segment1 = Segment(PointD(values[0], values[1]));
|
||||
Segment2 = Segment(PointD(values[2], values[3]));
|
||||
}
|
||||
else if (values.size() == 8)
|
||||
{
|
||||
Segment1 = Segment(PointD(values[0], values[1]),
|
||||
PointD(),
|
||||
PointD());
|
||||
Segment1 = Segment(PointD(values[0], values[1]));
|
||||
Segment2 = Segment(PointD(values[6], values[7]),
|
||||
PointD(values[2] - values[6],
|
||||
values[3] - values[7]),
|
||||
PointD(values[4] - values[6],
|
||||
values[5] - values[7]));
|
||||
}
|
||||
else
|
||||
{
|
||||
Segment1 = Segment();
|
||||
Segment2 = Segment();
|
||||
}
|
||||
}
|
||||
|
||||
Curve::Curve(double x0, double y0, double x1, double y1,
|
||||
double x2, double y2, double x3, double y3)
|
||||
Curve::Curve(const double& x0, const double& y0, const double& x1, const double& y1,
|
||||
const double& x2, const double& y2, const double& x3, const double& y3) noexcept :
|
||||
Segment1(Segment(PointD(x0, y0))),
|
||||
Segment2(Segment(PointD(x3, y3), PointD(x1, y1), PointD(x2, y2)))
|
||||
{
|
||||
Segment1 = Segment(PointD(x0, y0), PointD(), PointD());
|
||||
Segment2 = Segment(PointD(x3, y3), PointD(x1, y1), PointD(x2, y2));
|
||||
}
|
||||
|
||||
std::vector<double> Curve::GetXValues() const
|
||||
std::vector<double> Curve::GetXValues() const noexcept
|
||||
{
|
||||
if (IsStraight())
|
||||
return {Segment1.P.X, Segment1.P.X, Segment2.P.X, Segment2.P.X};
|
||||
return {Segment1.P.X, Segment2.P.X + Segment2.HI.X,
|
||||
Segment2.P.X + Segment2.HO.X, Segment2.P.X};
|
||||
if (IsStraight()) return {Segment1.P.X, Segment1.P.X, Segment2.P.X, Segment2.P.X};
|
||||
return {Segment1.P.X, Segment2.P.X + Segment2.HI.X, Segment2.P.X + Segment2.HO.X, Segment2.P.X};
|
||||
}
|
||||
|
||||
std::vector<double> Curve::GetYValues() const
|
||||
std::vector<double> Curve::GetYValues() const noexcept
|
||||
{
|
||||
if (IsStraight())
|
||||
return {Segment1.P.Y, Segment1.P.Y, Segment2.P.Y, Segment2.P.Y};
|
||||
return {Segment1.P.Y,
|
||||
Segment2.P.Y + Segment2.HI.Y,
|
||||
Segment2.P.Y + Segment2.HO.Y,
|
||||
Segment2.P.Y};
|
||||
if (IsStraight()) return {Segment1.P.Y, Segment1.P.Y, Segment2.P.Y, Segment2.P.Y};
|
||||
return {Segment1.P.Y, Segment2.P.Y + Segment2.HI.Y, Segment2.P.Y + Segment2.HO.Y, Segment2.P.Y};
|
||||
}
|
||||
|
||||
std::vector<double> Curve::GetPeeks() const
|
||||
{
|
||||
std::vector<double> x = GetXValues(),
|
||||
std::vector<double> x = GetXValues(),
|
||||
y = GetYValues(),
|
||||
roots;
|
||||
|
||||
double ax = -x[0] + 3 * x[1] - 3 * x[2] + x[3],
|
||||
bx = 3 * x[0] - 6 * x[1] + 3 * x[2],
|
||||
cx = -3 * x[0] + 3 * x[1],
|
||||
@ -172,17 +161,29 @@ double Curve::GetLength(double a, double b) const
|
||||
{
|
||||
if(IsStraight())
|
||||
{
|
||||
Curve c = *this;
|
||||
Curve c;
|
||||
double dx, dy;
|
||||
if (b < 1)
|
||||
{
|
||||
c = Subdivide(b)[0];
|
||||
if (a > 0)
|
||||
c = Subdivide(a)[1];
|
||||
double dx = c.Segment2.P.X - c.Segment1.P.X,
|
||||
dx = c.Segment2.P.X - c.Segment1.P.X;
|
||||
dy = c.Segment2.P.Y - c.Segment1.P.Y;
|
||||
}
|
||||
else if (a > 0)
|
||||
{
|
||||
c = Subdivide(a)[1];
|
||||
dx = c.Segment2.P.X - c.Segment1.P.X;
|
||||
dy = c.Segment2.P.Y - c.Segment1.P.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = Segment2.P.X - Segment1.P.X;
|
||||
dy = Segment2.P.Y - Segment1.P.Y;
|
||||
}
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
std::vector<double> x = GetXValues(),
|
||||
std::vector<double> x = GetXValues(),
|
||||
y = GetYValues();
|
||||
|
||||
double ax = 9 * (x[1] - x[2]) + 3 * (x[3] - x[0]),
|
||||
@ -195,34 +196,28 @@ double Curve::GetLength(double a, double b) const
|
||||
return integrate(ax, bx, cx, ay, by, cy, a, b);
|
||||
}
|
||||
|
||||
double Curve::GetSquaredLineLength() const
|
||||
double Curve::GetSquaredLineLength() const noexcept
|
||||
{
|
||||
double x = Segment2.P.X - Segment1.P.X,
|
||||
y = Segment2.P.Y - Segment1.P.Y;
|
||||
|
||||
return x * x + y * y;
|
||||
return (Segment2.P.X - Segment1.P.X) * (Segment2.P.X - Segment1.P.X) +
|
||||
(Segment2.P.Y - Segment1.P.Y) * (Segment2.P.Y - Segment1.P.Y);
|
||||
}
|
||||
|
||||
double Curve::GetTimeOf(const PointD& point) const
|
||||
double Curve::GetTimeOf(const PointD& point) const noexcept
|
||||
{
|
||||
PointD p0 = Segment1.P,
|
||||
p3 = Segment2.P;
|
||||
|
||||
double d0 = getDistance(point.X, point.Y, p0.X, p0.Y),
|
||||
d3 = getDistance(point.X, point.Y, p3.X, p3.Y);
|
||||
double d0 = getDistance(point.X, point.Y, Segment1.P.X, Segment1.P.Y),
|
||||
d3 = getDistance(point.X, point.Y, Segment2.P.X, Segment2.P.Y);
|
||||
|
||||
if (d0 > EPSILON && d3 > EPSILON)
|
||||
{
|
||||
std::vector<double> coords = {point.X, point.Y},
|
||||
roots;
|
||||
std::vector<double> roots;
|
||||
for (int c = 0; c < 2; c++)
|
||||
{
|
||||
int count = SolveCubic(c, coords[c], roots, 0.0, 1.0);
|
||||
int count = SolveCubic(c, c == 0 ? point.X : point.Y, roots, 0.0, 1.0);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
double u = roots[i];
|
||||
if (u > 1 || u < 0)
|
||||
return - 1;
|
||||
if (u > 1.0 || u < 0.0)
|
||||
return - 1.0;
|
||||
if (getDistance(point, GetPoint(u)) <= GEOMETRIC_EPSILON)
|
||||
return u;
|
||||
}
|
||||
@ -230,10 +225,10 @@ double Curve::GetTimeOf(const PointD& point) const
|
||||
}
|
||||
bool firstDist = d0 <= GEOMETRIC_EPSILON,
|
||||
secondDist = d3 <= GEOMETRIC_EPSILON;
|
||||
return firstDist ? 0 : secondDist ? 1 : - 1;
|
||||
return firstDist ? 0.0 : secondDist ? 1.0 : - 1.0;
|
||||
}
|
||||
|
||||
double Curve::GetTimeAt(double offset) const
|
||||
double Curve::GetTimeAt(const double& offset) const noexcept
|
||||
{
|
||||
bool forward = offset > 0;
|
||||
double start = !forward ? 1 : 0;
|
||||
@ -251,9 +246,9 @@ double Curve::GetTimeAt(double offset) const
|
||||
return MIN;
|
||||
|
||||
double guess = offset / rangeLength,
|
||||
length = 0;
|
||||
length = 0.0;
|
||||
|
||||
std::vector<double> x = GetXValues(),
|
||||
std::vector<double> x = GetXValues(),
|
||||
y = GetYValues();
|
||||
|
||||
double ax = 9 * (x[1] - x[2]) + 3 * (x[3] - x[0]),
|
||||
@ -267,9 +262,9 @@ double Curve::GetTimeAt(double offset) const
|
||||
ay, by, cy, start + guess, a, b);
|
||||
}
|
||||
|
||||
PointD Curve::Get(double t, int type) const
|
||||
PointD Curve::Get(const double& t, const int& type) const noexcept
|
||||
{
|
||||
std::vector<double> x = GetXValues(),
|
||||
std::vector<double> x = GetXValues(),
|
||||
y = GetYValues();
|
||||
|
||||
if (isZero(x[1] - x[0]) && isZero(y[1] - y[0]))
|
||||
@ -306,8 +301,8 @@ PointD Curve::Get(double t, int type) const
|
||||
}
|
||||
else if (t > tMax)
|
||||
{
|
||||
x0 = 3 * (x[3] - x[2]);
|
||||
y0 = 3 * (y[3] - y[2]);
|
||||
x0 = 3 * (x[3] - y[2]);
|
||||
y0 = 3 * (y[3] - x[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -332,28 +327,24 @@ PointD Curve::Get(double t, int type) const
|
||||
return PointD(x0, y0);
|
||||
}
|
||||
|
||||
PointD Curve::GetPoint(double t) const
|
||||
PointD Curve::GetPoint(const double& t) const noexcept
|
||||
{
|
||||
return Get(t, 0);
|
||||
}
|
||||
|
||||
PointD Curve::GetTangent(double t) const
|
||||
PointD Curve::GetTangent(const double& t) const noexcept
|
||||
{
|
||||
return Get(t, 1);
|
||||
}
|
||||
|
||||
PointD Curve::GetTangent(double t, double offset,
|
||||
bool inside, const PointD& p) const
|
||||
PointD Curve::GetTangent(const double& t, const double& offset,
|
||||
const bool& inside, const PointD& p) const noexcept
|
||||
{
|
||||
if (inside)
|
||||
return GetTangent(t);
|
||||
|
||||
PointD point = GetPoint(GetTimeAt(offset));
|
||||
|
||||
return PointD(point.X - p.X, point.Y - p.Y);
|
||||
if (inside) return GetTangent(t);
|
||||
return GetPoint(GetTimeAt(offset)) - p;
|
||||
}
|
||||
|
||||
Curve Curve::GetPart(double from, double to) const
|
||||
Curve Curve::GetPart(double from, double to) const noexcept
|
||||
{
|
||||
Curve result = *this;
|
||||
if (from > to)
|
||||
@ -367,8 +358,7 @@ Curve Curve::GetPart(double from, double to) const
|
||||
result.Segment2.HO.X -= result.Segment2.P.X;
|
||||
result.Segment2.HO.Y -= result.Segment2.P.Y;
|
||||
}
|
||||
|
||||
if (to < 1)
|
||||
else if (to < 1)
|
||||
{
|
||||
result = result.Subdivide((to - from) / (1 - from))[0];
|
||||
result.Segment2.HI.X -= result.Segment2.P.X;
|
||||
@ -383,11 +373,10 @@ Curve Curve::GetPart(double from, double to) const
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::pair<double, double>> Curve::GetOverlaps(const Curve& curve) const
|
||||
std::vector<std::pair<double, double>> Curve::GetOverlaps(const Curve& curve) const noexcept
|
||||
{
|
||||
bool swap = this->GetSquaredLineLength() <
|
||||
curve.GetSquaredLineLength(),
|
||||
straight1 = this->IsStraight(),
|
||||
bool swap = GetSquaredLineLength() < curve.GetSquaredLineLength(),
|
||||
straight1 = IsStraight(),
|
||||
straight2 = curve.IsStraight(),
|
||||
straightBoth = straight1 && straight2;
|
||||
|
||||
@ -479,8 +468,8 @@ std::vector<std::pair<double, double>> Curve::GetOverlaps(const Curve& curve) co
|
||||
return pairs;
|
||||
}
|
||||
|
||||
std::vector<double> Curve::GetCurveLineIntersection(double px, double py,
|
||||
double vx, double vy) const
|
||||
std::vector<double> Curve::GetCurveLineIntersection(const double& px, const double& py,
|
||||
const double& vx, const double& vy) const noexcept
|
||||
{
|
||||
if (isZero(vx) && isZero(vy))
|
||||
{
|
||||
@ -498,20 +487,20 @@ std::vector<double> Curve::GetCurveLineIntersection(double px, double py,
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
double cx = x[i] - px,
|
||||
double cx = x[i] - px,
|
||||
cy = y[i] - py;
|
||||
|
||||
rv.push_back(cx * cos - cy * sin);
|
||||
rv.push_back(cx * sin + cy * cos);
|
||||
}
|
||||
|
||||
Curve curve = Curve(rv);
|
||||
curve.SolveCubic(1, 0, roots, 0, 1);
|
||||
Curve c(rv);
|
||||
c.SolveCubic(1, 0, roots, 0, 1);
|
||||
|
||||
return roots;
|
||||
}
|
||||
|
||||
std::vector<Curve> Curve::Subdivide(double t) const
|
||||
std::vector<Curve> Curve::Subdivide(const double& t) const noexcept
|
||||
{
|
||||
std::vector<double> x = GetXValues(),
|
||||
y = GetYValues();
|
||||
@ -528,7 +517,7 @@ std::vector<Curve> Curve::Subdivide(double t) const
|
||||
Curve(x2[5], y2[5], x2[4], y2[4], x2[2], y2[2], x[3], y[3])};
|
||||
}
|
||||
|
||||
Curve Curve::DivideAtTime(double time)
|
||||
Curve Curve::DivideAtTime(const double& time) noexcept
|
||||
{
|
||||
double tMin = CURVETIME_EPSILON,
|
||||
tMax = 1 - tMin;
|
||||
@ -554,8 +543,8 @@ Curve Curve::DivideAtTime(double time)
|
||||
return Curve();
|
||||
}
|
||||
|
||||
int Curve::SolveCubic(int coord, double value, std::vector<double>& roots,
|
||||
double mn, double mx) const
|
||||
int Curve::SolveCubic(const int& coord, const double& value, std::vector<double>& roots,
|
||||
const double& mn, const double& mx) const noexcept
|
||||
{
|
||||
int count = 0;
|
||||
std::vector<double> v = coord == 0 ? GetXValues() : GetYValues();
|
||||
@ -575,7 +564,7 @@ int Curve::SolveCubic(int coord, double value, std::vector<double>& roots,
|
||||
}
|
||||
|
||||
int Curve::SolveCubic(double a, double b, double c, double d,
|
||||
std::vector<double>& roots, double mn, double mx) const
|
||||
std::vector<double>& roots, const double& mn, const double& mx) const noexcept
|
||||
{
|
||||
int count = 0;
|
||||
double f = max(abs(a), abs(b), abs(c), abs(d));
|
||||
@ -651,33 +640,33 @@ int Curve::SolveCubic(double a, double b, double c, double d,
|
||||
return count;
|
||||
}
|
||||
|
||||
void Curve::Flip()
|
||||
void Curve::Flip() noexcept
|
||||
{
|
||||
std::swap(Segment1.P, Segment2.P);
|
||||
std::swap(Segment1.HI, Segment1.HO);
|
||||
}
|
||||
|
||||
bool Curve::IsStraight() const
|
||||
bool Curve::IsStraight() const noexcept
|
||||
{
|
||||
return !Segment2.IsCurve;
|
||||
}
|
||||
|
||||
bool Curve::operator==(const Curve& other) const
|
||||
bool Curve::operator==(const Curve& other) const noexcept
|
||||
{
|
||||
return Segment1 == other.Segment1 &&
|
||||
Segment2 == other.Segment2;
|
||||
}
|
||||
|
||||
bool Curve::operator!=(const Curve& other) const
|
||||
bool Curve::operator!=(const Curve& other) const noexcept
|
||||
{
|
||||
return !operator ==(other);
|
||||
}
|
||||
|
||||
Location::Location()
|
||||
Location::Location() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
Location::Location(const Curve& curve, double time, bool overlap, bool ends) :
|
||||
Location::Location(const Curve& curve, const double& time, const bool& overlap, const bool& ends) noexcept :
|
||||
C(curve),
|
||||
Time(time),
|
||||
Overlap(overlap),
|
||||
@ -685,9 +674,9 @@ Location::Location(const Curve& curve, double time, bool overlap, bool ends) :
|
||||
{
|
||||
}
|
||||
|
||||
bool Location::IsTouching()
|
||||
bool Location::IsTouching() noexcept
|
||||
{
|
||||
if (this->Inters == nullptr)
|
||||
if (!Inters)
|
||||
return false;
|
||||
if (!isCollinear(C.GetTangent(Time), Inters->C.GetTangent(Inters->Time)))
|
||||
return false;
|
||||
@ -746,10 +735,10 @@ void CBooleanOperations::TraceBoolean()
|
||||
SetWinding();
|
||||
else
|
||||
{
|
||||
int length = Locations.size() - 1;
|
||||
int length = static_cast<int>(Locations.size() - 1);
|
||||
for (int i = 0; i <= length; i++)
|
||||
{
|
||||
int before = Locations.size();
|
||||
int before = static_cast<int>(Locations.size());
|
||||
InsertLocation(Locations[i]->Inters, Locations[i]->Inters->Overlap);
|
||||
if (before == Locations.size())
|
||||
Locations.erase(Locations.begin() + i);
|
||||
@ -1076,7 +1065,7 @@ void CBooleanOperations::InsertSegment(const Segment& segment, const Segment& ha
|
||||
{
|
||||
if (segment.Id == 1)
|
||||
{
|
||||
int length = Segments1.size(),
|
||||
int length = static_cast<int>(Segments1.size()),
|
||||
index = segment.Index == length ? 0 : segment.Index;
|
||||
if (getDistance(segment.P, Segments1[index].P) <= GEOMETRIC_EPSILON)
|
||||
{
|
||||
@ -1099,7 +1088,7 @@ void CBooleanOperations::InsertSegment(const Segment& segment, const Segment& ha
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = Segments2.size(),
|
||||
int length = static_cast<int>(Segments2.size()),
|
||||
index = segment.Index == length ? 0 : segment.Index;
|
||||
if (getDistance(segment.P, Segments2[index].P) <= GEOMETRIC_EPSILON)
|
||||
{
|
||||
@ -1126,21 +1115,21 @@ void CBooleanOperations::InsertSegment(const Segment& segment, const Segment& ha
|
||||
l->S.Index++;
|
||||
}
|
||||
|
||||
Curve CBooleanOperations::GetCurve(const Segment& segment) const
|
||||
Curve CBooleanOperations::GetCurve(const Segment& segment) const noexcept
|
||||
{
|
||||
return segment.Id == 1 ? Curves1[segment.Index] : Curves2[segment.Index];
|
||||
}
|
||||
|
||||
Curve CBooleanOperations::GetPreviousCurve(const Curve& curve) const
|
||||
Curve CBooleanOperations::GetPreviousCurve(const Curve& curve) const noexcept
|
||||
{
|
||||
bool path1 = curve.Segment1.Id == 1;
|
||||
int length = path1 ? Curves1.size()
|
||||
: Curves2.size();
|
||||
size_t last = path1 ? Curves1.size() - 1
|
||||
: Curves2.size() - 1;
|
||||
|
||||
if (curve.Segment1.Index == 0)
|
||||
{
|
||||
if (curve.Segment1.PolyClosed)
|
||||
return path1 ? Curves1[length - 1] : Curves2[length - 1];
|
||||
return path1 ? Curves1[last] : Curves2[last];
|
||||
else
|
||||
return Curve();
|
||||
}
|
||||
@ -1149,11 +1138,11 @@ Curve CBooleanOperations::GetPreviousCurve(const Curve& curve) const
|
||||
: Curves2[curve.Segment1.Index - 1];
|
||||
}
|
||||
|
||||
Curve CBooleanOperations::GetNextCurve(const Curve& curve) const
|
||||
Curve CBooleanOperations::GetNextCurve(const Curve& curve) const noexcept
|
||||
{
|
||||
bool path1 = curve.Segment1.Id == 1;
|
||||
int last = path1 ? Curves1.size() - 1
|
||||
: Curves2.size() - 1;
|
||||
int last = path1 ? static_cast<int>(Curves1.size()) - 1
|
||||
: static_cast<int>(Curves2.size()) - 1;
|
||||
|
||||
if (curve.Segment1.Index == last)
|
||||
{
|
||||
@ -1167,13 +1156,13 @@ Curve CBooleanOperations::GetNextCurve(const Curve& curve) const
|
||||
: Curves2[curve.Segment1.Index + 1];
|
||||
}
|
||||
|
||||
Segment CBooleanOperations::GetNextSegment(const Segment& segment) const
|
||||
Segment CBooleanOperations::GetNextSegment(const Segment& segment) const noexcept
|
||||
{
|
||||
bool path1 = segment.Id == 1;
|
||||
int length = path1 ? Segments1.size()
|
||||
: Segments2.size();
|
||||
int last = path1 ? static_cast<int>(Segments1.size()) - 1
|
||||
: static_cast<int>(Segments2.size()) - 1;
|
||||
|
||||
if (segment.Index == (length - 1))
|
||||
if (segment.Index == last)
|
||||
{
|
||||
if (segment.PolyClosed)
|
||||
return path1 ? Segments1[0] : Segments2[0];
|
||||
@ -1193,7 +1182,7 @@ void CBooleanOperations::SetVisited(const Segment& segment)
|
||||
Segments2[segment.Index].Visited = true;
|
||||
}
|
||||
|
||||
std::vector<std::vector<double>> CBooleanOperations::GetBoundsForCurves(const std::vector<Curve>& curves) const
|
||||
std::vector<std::vector<double>> CBooleanOperations::GetBoundsForCurves(const std::vector<Curve>& curves) const noexcept
|
||||
{
|
||||
std::vector<std::vector<double>> bounds;
|
||||
for (int i = 0; i < curves.size(); i++)
|
||||
@ -1219,8 +1208,8 @@ std::vector<std::vector<int>> CBooleanOperations::FindBoundsCollisions()
|
||||
if (!self)
|
||||
std::copy(bounds2.begin(), bounds2.end(), std::back_inserter(allBounds));
|
||||
|
||||
int allLength = allBounds.size(),
|
||||
length1 = bounds1.size();
|
||||
int allLength = static_cast<int>(allBounds.size()),
|
||||
length1 = static_cast<int>(bounds1.size());
|
||||
|
||||
std::vector<int> allIdicesByPri1(allLength);
|
||||
for (int i = 0; i < allLength; i++)
|
||||
@ -1253,7 +1242,7 @@ std::vector<std::vector<int>> CBooleanOperations::FindBoundsCollisions()
|
||||
|
||||
double curSec2 = curBounds[3],
|
||||
curSec1 = curBounds[1];
|
||||
for (int j = 0; j < activeIndicesByPri2.size(); j++)
|
||||
for (int j = 0; j < static_cast<int>(activeIndicesByPri2.size()); j++)
|
||||
{
|
||||
int activeIndex = activeIndicesByPri2[j];
|
||||
std::vector<double> activeBounds = allBounds[activeIndex];
|
||||
@ -1294,9 +1283,9 @@ std::vector<std::vector<int>> CBooleanOperations::FindBoundsCollisions()
|
||||
return allCollisions;
|
||||
}
|
||||
|
||||
bool CBooleanOperations::IsCrossing(std::shared_ptr<Location> loc)
|
||||
bool CBooleanOperations::IsCrossing(std::shared_ptr<Location> loc) noexcept
|
||||
{
|
||||
if(loc->Inters == nullptr)
|
||||
if(!loc->Inters)
|
||||
return false;
|
||||
|
||||
double t1 = loc->Time,
|
||||
@ -1358,12 +1347,12 @@ bool CBooleanOperations::IsCrossing(std::shared_ptr<Location> loc)
|
||||
return t1Inside ? inRange1 : inRange2;
|
||||
}
|
||||
|
||||
bool CBooleanOperations::FilterIntersections(std::shared_ptr<Location> loc)
|
||||
bool CBooleanOperations::FilterIntersections(std::shared_ptr<Location> loc) noexcept
|
||||
{
|
||||
return loc->Overlap || IsCrossing(loc);
|
||||
}
|
||||
|
||||
bool CBooleanOperations::IntersectsBounds()
|
||||
bool CBooleanOperations::IntersectsBounds() noexcept
|
||||
{
|
||||
RectF_T<double> rect1, rect2;
|
||||
Path1->GetBounds(rect1.X, rect1.Y, rect1.Width, rect1.Height);
|
||||
@ -1383,17 +1372,10 @@ void CBooleanOperations::GetIntersection()
|
||||
std::vector<std::vector<int>> boundsCollisions = FindBoundsCollisions();
|
||||
for (int index1 = 0; index1 < Curves1.size(); index1++)
|
||||
{
|
||||
Curve curve1 = Curves1[index1];
|
||||
std::vector<int> collisions1 = boundsCollisions[index1];
|
||||
if (!collisions1.empty())
|
||||
{
|
||||
for (int j = 0; j < collisions1.size(); j++)
|
||||
{
|
||||
int index2 = collisions1[j];
|
||||
Curve curve2 = Curves2[index2];
|
||||
GetCurveIntersection(curve1, curve2);
|
||||
}
|
||||
}
|
||||
GetCurveIntersection(Curves1[index1], Curves2[collisions1[j]]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1418,29 +1400,22 @@ void CBooleanOperations::GetCurveIntersection(const Curve& curve1, const Curve&
|
||||
{
|
||||
std::vector<std::pair<double, double>> overlaps = curve1.GetOverlaps(curve2);
|
||||
if (!overlaps.empty())
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
std::pair<double, double> overlap = overlaps[i];
|
||||
AddLocation(curve1, curve2, overlap.first,
|
||||
overlap.second, true);
|
||||
}
|
||||
}
|
||||
AddLocation(curve1, curve2, overlaps[i].first, overlaps[i].second, true);
|
||||
else
|
||||
{
|
||||
bool straight1 = curve1.IsStraight(),
|
||||
straight2 = curve2.IsStraight(),
|
||||
straight = straight1 && straight2,
|
||||
flip = straight1 && !straight2;
|
||||
Curve c1 = flip ? curve2 : curve1,
|
||||
c2 = flip ? curve1 : curve2;
|
||||
size_t before = Locations.size();
|
||||
if (straight)
|
||||
AddLineIntersection(c1, c2);
|
||||
AddLineIntersection(flip ? curve2 : curve1, flip ? curve1 : curve2);
|
||||
else if (straight1 || straight2)
|
||||
AddCurveLineIntersection(c1, c2, flip);
|
||||
AddCurveLineIntersection(flip ? curve2 : curve1, flip ? curve1 : curve2, flip);
|
||||
else
|
||||
AddCurveIntersection(c1, c2, c1, c2, flip);
|
||||
AddCurveIntersection(flip ? curve2 : curve1, flip ? curve1 : curve2,
|
||||
flip ? curve2 : curve1, flip ? curve1 : curve2, flip);
|
||||
|
||||
if (Locations.size() == before && (!straight || Locations.empty()))
|
||||
{
|
||||
@ -1472,10 +1447,10 @@ void CBooleanOperations::LinkIntersection(std::shared_ptr<Location> from,
|
||||
prev = prev->Prev;
|
||||
}
|
||||
|
||||
while (from->Next != nullptr && from->Next != to)
|
||||
while (from->Next && from->Next != to)
|
||||
from = from->Next;
|
||||
|
||||
if (from->Next == nullptr)
|
||||
if (!from->Next)
|
||||
{
|
||||
while (to->Prev)
|
||||
to = to->Prev;
|
||||
@ -1630,7 +1605,7 @@ int CBooleanOperations::CheckInters(const PointD& point, const Segment& segment,
|
||||
if (!curve.IsStraight())
|
||||
{
|
||||
std::vector<double> roots = curve.GetCurveLineIntersection(segment.P.X,segment.P.Y, point.X - segment.P.X, point.Y - segment.P.Y);
|
||||
Curve line = Curve(segment, Segment(point, PointD(), PointD()));
|
||||
Curve line(segment, Segment(point));
|
||||
|
||||
int count = 0;
|
||||
for (const auto& r : roots)
|
||||
@ -1669,21 +1644,19 @@ void CBooleanOperations::DivideLocations()
|
||||
|
||||
Curve prevCurve;
|
||||
|
||||
for (int i = Locations.size() - 1; i >= 0; i--)
|
||||
for (int i = static_cast<int>(Locations.size()) - 1; i >= 0; i--)
|
||||
{
|
||||
std::shared_ptr<Location> loc = Locations[i];
|
||||
|
||||
double origTime = loc->Time,
|
||||
double origTime = Locations[i]->Time,
|
||||
time = origTime;
|
||||
|
||||
Segment segment;
|
||||
Curve curve = GetCurve(loc->C.Segment1),
|
||||
Curve curve = GetCurve(Locations[i]->C.Segment1),
|
||||
newCurve;
|
||||
|
||||
bool updateHandles = false;
|
||||
|
||||
if (loc->C != prevCurve)
|
||||
prevCurve = loc->C;
|
||||
if (Locations[i]->C != prevCurve)
|
||||
prevCurve = Locations[i]->C;
|
||||
else if (prevTime >= tMin)
|
||||
time /= prevTime;
|
||||
|
||||
@ -1700,7 +1673,7 @@ void CBooleanOperations::DivideLocations()
|
||||
else
|
||||
{
|
||||
if (curve.IsStraight())
|
||||
segment = Segment({loc->C.GetPoint(origTime)},
|
||||
segment = Segment({Locations[i]->C.GetPoint(origTime)},
|
||||
false,
|
||||
curve.Segment1.Index + 1,
|
||||
curve.Segment1.Id,
|
||||
@ -1714,13 +1687,13 @@ void CBooleanOperations::DivideLocations()
|
||||
}
|
||||
}
|
||||
std::shared_ptr<Location> inter = segment.Inters,
|
||||
dest = loc->Inters;
|
||||
if ((bool)inter)
|
||||
dest = Locations[i]->Inters;
|
||||
if (inter)
|
||||
{
|
||||
LinkIntersection(inter, dest);
|
||||
|
||||
std::shared_ptr<Location> other = inter;
|
||||
while ((bool)other)
|
||||
while (other)
|
||||
{
|
||||
LinkIntersection(other->Inters, inter);
|
||||
other = other->Next;
|
||||
@ -1730,7 +1703,7 @@ void CBooleanOperations::DivideLocations()
|
||||
segment.Inters = dest;
|
||||
|
||||
InsertSegment(segment, newCurve.Segment2, updateHandles);
|
||||
loc->S = segment;
|
||||
Locations[i]->S = segment;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1742,16 +1715,15 @@ void CBooleanOperations::InsertLocation(std::shared_ptr<Location> loc, bool over
|
||||
return;
|
||||
}
|
||||
|
||||
int length = Locations.size(),
|
||||
int length = static_cast<int>(Locations.size()),
|
||||
l = 0,
|
||||
r = length - 1;
|
||||
while (l <= r)
|
||||
{
|
||||
int mid = (l + r) >> 1;
|
||||
std::shared_ptr<Location> loc1 = Locations[mid];
|
||||
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), loc1->C.GetPoint(loc1->Time)) <= GEOMETRIC_EPSILON
|
||||
&& loc->C.Segment1.Id == loc1->C.Segment1.Id)
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), Locations[mid]->C.GetPoint(Locations[mid]->Time)) <= GEOMETRIC_EPSILON
|
||||
&& loc->C.Segment1.Id == Locations[mid]->C.Segment1.Id)
|
||||
return;
|
||||
|
||||
if (overlap)
|
||||
@ -1761,27 +1733,27 @@ void CBooleanOperations::InsertLocation(std::shared_ptr<Location> loc, bool over
|
||||
|
||||
for (int i = mid - 1; i >= -1; i--)
|
||||
{
|
||||
std::shared_ptr<Location> loc2 = Locations[((i % length) + length) % length];
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), loc2->C.GetPoint(loc2->Time)) > GEOMETRIC_EPSILON)
|
||||
size_t idx = ((i % length) + length) % length;
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), Locations[idx]->C.GetPoint(Locations[idx]->Time)) > GEOMETRIC_EPSILON)
|
||||
break;
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), loc2->C.GetPoint(loc2->Time)) <= GEOMETRIC_EPSILON &&
|
||||
loc->C.Segment1.Id == loc2->C.Segment1.Id)
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), Locations[idx]->C.GetPoint(Locations[idx]->Time)) <= GEOMETRIC_EPSILON &&
|
||||
loc->C.Segment1.Id == Locations[idx]->C.Segment1.Id)
|
||||
return;
|
||||
}
|
||||
for (int i = mid + 1; i <= length; i++)
|
||||
{
|
||||
std::shared_ptr<Location> loc2 = Locations[((i % length) + length) % length];
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), loc2->C.GetPoint(loc2->Time)) > GEOMETRIC_EPSILON)
|
||||
size_t idx = ((i % length) + length) % length;
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), Locations[idx]->C.GetPoint(Locations[idx]->Time)) > GEOMETRIC_EPSILON)
|
||||
break;
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), loc2->C.GetPoint(loc2->Time)) <= GEOMETRIC_EPSILON &&
|
||||
loc->C.Segment1.Id == loc2->C.Segment1.Id)
|
||||
if (getDistance(loc->C.GetPoint(loc->Time), Locations[idx]->C.GetPoint(Locations[idx]->Time)) <= GEOMETRIC_EPSILON &&
|
||||
loc->C.Segment1.Id == Locations[idx]->C.Segment1.Id)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double diffId = loc->C.Segment1.Id - loc1->C.Segment1.Id,
|
||||
diffT = (loc->C.Segment1.Index + loc->Time) - (loc1->C.Segment1.Index + loc1->Time);
|
||||
bool self = loc->C.Segment1.Id == loc1->C.Segment1.Id;
|
||||
double diffId = loc->C.Segment1.Id - Locations[mid]->C.Segment1.Id,
|
||||
diffT = (loc->C.Segment1.Index + loc->Time) - (Locations[mid]->C.Segment1.Index + Locations[mid]->Time);
|
||||
bool self = loc->C.Segment1.Id == Locations[mid]->C.Segment1.Id;
|
||||
double diff = self ? (diffT) : (diffId);
|
||||
if (diff < 0)
|
||||
r = mid - 1;
|
||||
@ -1791,7 +1763,7 @@ void CBooleanOperations::InsertLocation(std::shared_ptr<Location> loc, bool over
|
||||
Locations.insert(Locations.begin() + l, loc);
|
||||
}
|
||||
|
||||
bool CBooleanOperations::AllOverlap() const
|
||||
bool CBooleanOperations::AllOverlap() const noexcept
|
||||
{
|
||||
if (Locations.empty()) return false;
|
||||
|
||||
@ -1802,7 +1774,7 @@ bool CBooleanOperations::AllOverlap() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBooleanOperations::AllInters(const std::vector<Segment>& segments) const
|
||||
bool CBooleanOperations::AllInters(const std::vector<Segment>& segments) const noexcept
|
||||
{
|
||||
for (const auto& s : segments)
|
||||
if (!s.Inters)
|
||||
@ -1842,7 +1814,7 @@ void CBooleanOperations::AddOffsets(std::vector<double>& offsets,
|
||||
{
|
||||
std::vector<double> roots = curve.GetPeeks();
|
||||
|
||||
int count = roots.size();
|
||||
size_t count = roots.size();
|
||||
bool first = end && count != 0,
|
||||
second = !end && count != 0;
|
||||
|
||||
|
||||
@ -13,28 +13,29 @@ namespace Aggplus
|
||||
PointD HI{};
|
||||
PointD HO{};
|
||||
|
||||
bool IsCurve = false;
|
||||
bool Visited = false;
|
||||
bool IsCurve = false;
|
||||
bool Visited = false;
|
||||
bool PolyClosed = false;
|
||||
|
||||
int Index = -1;
|
||||
int Id = 0;
|
||||
int Winding = 0;
|
||||
int Index = -1;
|
||||
int Id = 0;
|
||||
int Winding = 0;
|
||||
|
||||
std::shared_ptr<Location> Inters{nullptr};
|
||||
|
||||
Segment();
|
||||
Segment(const std::vector<PointD>& points, bool isCurve, int index, int id,
|
||||
bool polyClosed);
|
||||
Segment(const PointD& p, const PointD& hi, const PointD& ho);
|
||||
Segment() noexcept;
|
||||
Segment(const std::vector<PointD>& points, const bool& isCurve,
|
||||
const int& index, const int& id, const bool& polyClosed) noexcept;
|
||||
Segment(const PointD& p) noexcept;
|
||||
Segment(const PointD& p, const PointD& hi, const PointD& ho) noexcept;
|
||||
|
||||
void SetHandles(const PointD& hi, const PointD& ho);
|
||||
void UpdateHandles(const PointD& hi, const PointD& ho);
|
||||
void SetHandles(const PointD& hi, const PointD& ho) noexcept;
|
||||
void UpdateHandles(const PointD& hi, const PointD& ho) noexcept;
|
||||
|
||||
bool IsValid(BooleanOpType op) const;
|
||||
bool IsEmpty() const;
|
||||
bool operator==(const Segment& other) const;
|
||||
bool operator!=(const Segment& other) const;
|
||||
bool IsValid(const BooleanOpType& op) const noexcept;
|
||||
bool IsEmpty() const noexcept;
|
||||
bool operator==(const Segment& other) const noexcept;
|
||||
bool operator!=(const Segment& other) const noexcept;
|
||||
};
|
||||
|
||||
struct Curve
|
||||
@ -42,40 +43,44 @@ namespace Aggplus
|
||||
Segment Segment1{};
|
||||
Segment Segment2{};
|
||||
|
||||
Curve();
|
||||
Curve(const Segment& segment1, const Segment& segment2);
|
||||
Curve(const std::vector<double>& values);
|
||||
Curve(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3);
|
||||
Curve() noexcept;
|
||||
Curve(const Segment& segment1, const Segment& segment2) noexcept;
|
||||
Curve(const std::vector<double>& values) noexcept;
|
||||
Curve(const double& x0, const double& y0, const double& x1, const double& y1,
|
||||
const double& x2, const double& y2, const double& x3, const double& y3) noexcept;
|
||||
|
||||
std::vector<double> GetXValues() const;
|
||||
std::vector<double> GetYValues() const;
|
||||
std::vector<double> GetXValues() const noexcept;
|
||||
std::vector<double> GetYValues() const noexcept;
|
||||
std::vector<double> GetPeeks() const;
|
||||
double GetLength(double a = 0, double b = 1) const;
|
||||
double GetSquaredLineLength() const;
|
||||
double GetTimeOf(const PointD& point) const;
|
||||
double GetTimeAt(double offset) const;
|
||||
PointD Get(double t, int type) const;
|
||||
PointD GetPoint(double t) const;
|
||||
PointD GetTangent(double t) const;
|
||||
PointD GetTangent(double t, double offset, bool inside, const PointD& p) const;
|
||||
Curve GetPart(double from, double to) const;
|
||||
std::vector<Curve> GetMonoCurves(bool dir) const;
|
||||
std::vector<double> GetCurveLineIntersection(double px, double py, double vx, double vy) const;
|
||||
std::vector<std::pair<double, double>> GetOverlaps(const Curve& curve) const;
|
||||
double GetSquaredLineLength() const noexcept;
|
||||
double GetTimeOf(const PointD& point) const noexcept;
|
||||
double GetTimeAt(const double& offset) const noexcept;
|
||||
PointD Get(const double& t, const int& type) const noexcept;
|
||||
PointD GetPoint(const double& t) const noexcept;
|
||||
PointD GetTangent(const double& t) const noexcept;
|
||||
PointD GetTangent(const double& t, const double& offset,
|
||||
const bool& inside, const PointD& p) const noexcept;
|
||||
Curve GetPart(double from, double to) const noexcept;
|
||||
std::vector<Curve> GetMonoCurves(const bool& dir) const noexcept;
|
||||
std::vector<double> GetCurveLineIntersection(const double& px, const double& py,
|
||||
const double& vx, const double& vy) const noexcept;
|
||||
std::vector<std::pair<double, double>> GetOverlaps(const Curve& curve) const noexcept;
|
||||
|
||||
std::vector<Curve> Subdivide(double t) const;
|
||||
Curve DivideAtTime(double time);
|
||||
std::vector<Curve> Subdivide(const double& t) const noexcept;
|
||||
Curve DivideAtTime(const double& time) noexcept;
|
||||
|
||||
int SolveCubic(int coord, double value, std::vector<double>& roots, double mn, double mx) const;
|
||||
int SolveCubic(double a, double b, double c, double d, std::vector<double>& roots, double mn, double mx) const;
|
||||
int SolveCubic(const int& coord, const double& value, std::vector<double>& roots,
|
||||
const double& mn, const double& mx) const noexcept;
|
||||
int SolveCubic(double a, double b, double c, double d, std::vector<double>& roots,
|
||||
const double& mn, const double& mx) const noexcept;
|
||||
|
||||
void Flip();
|
||||
void ClearHandles();
|
||||
void Flip() noexcept;
|
||||
|
||||
bool IsStraight() const;
|
||||
bool HasHandle() const;
|
||||
bool operator==(const Curve& other) const;
|
||||
bool operator!=(const Curve& other) const;
|
||||
bool IsStraight() const noexcept;
|
||||
bool HasHandle() const noexcept;
|
||||
bool operator==(const Curve& other) const noexcept;
|
||||
bool operator!=(const Curve& other) const noexcept;
|
||||
};
|
||||
|
||||
struct Location
|
||||
@ -90,10 +95,10 @@ namespace Aggplus
|
||||
std::shared_ptr<Location> Next{nullptr};
|
||||
std::shared_ptr<Location> Prev{nullptr};
|
||||
|
||||
Location();
|
||||
Location(const Curve& curve, double time, bool overlap, bool ends);
|
||||
Location() noexcept;
|
||||
Location(const Curve& curve, const double& time, const bool& overlap, const bool& ends) noexcept;
|
||||
|
||||
bool IsTouching();
|
||||
bool IsTouching() noexcept;
|
||||
};
|
||||
|
||||
class CBooleanOperations
|
||||
@ -113,20 +118,20 @@ namespace Aggplus
|
||||
void PreparePath(std::shared_ptr<CGraphicsPath> path, int id, std::vector<Segment>& segments,
|
||||
std::vector<Curve>& curves, bool reverse = false);
|
||||
void InsertSegment(const Segment& segment, const Segment& handles, bool updateHandles);
|
||||
Curve GetCurve(const Segment& segment) const;
|
||||
Curve GetPreviousCurve(const Curve& curve) const;
|
||||
Curve GetNextCurve(const Curve& curve) const;
|
||||
Segment GetNextSegment(const Segment& segment) const;
|
||||
Curve GetCurve(const Segment& segment) const noexcept;
|
||||
Curve GetPreviousCurve(const Curve& curve) const noexcept;
|
||||
Curve GetNextCurve(const Curve& curve) const noexcept;
|
||||
Segment GetNextSegment(const Segment& segment) const noexcept;
|
||||
void SetVisited(const Segment& segment);
|
||||
|
||||
// Bounds
|
||||
std::vector<std::vector<double>> GetBoundsForCurves(const std::vector<Curve>& curves) const;
|
||||
std::vector<std::vector<double>> GetBoundsForCurves(const std::vector<Curve>& curves) const noexcept;
|
||||
std::vector<std::vector<int>> FindBoundsCollisions();
|
||||
|
||||
// Intersection
|
||||
bool IsCrossing(std::shared_ptr<Location> loc);
|
||||
bool FilterIntersections(std::shared_ptr<Location> loc);
|
||||
bool IntersectsBounds();
|
||||
bool IsCrossing(std::shared_ptr<Location> loc) noexcept;
|
||||
bool FilterIntersections(std::shared_ptr<Location> loc) noexcept;
|
||||
bool IntersectsBounds() noexcept;
|
||||
void GetIntersection();
|
||||
void GetCurveIntersection(const Curve& curve1, const Curve& curve2);
|
||||
void LinkIntersection(std::shared_ptr<Location> form, std::shared_ptr<Location> to);
|
||||
@ -141,8 +146,8 @@ namespace Aggplus
|
||||
void DivideLocations();
|
||||
void AddLocation(Curve curve1, Curve curve2, double t1, double t2, bool overlap = false, bool filter = true, bool bothEnds = false);
|
||||
void InsertLocation(std::shared_ptr<Location> loc, bool overlap);
|
||||
bool AllOverlap() const;
|
||||
bool AllInters(const std::vector<Segment>& segments) const;
|
||||
bool AllOverlap() const noexcept;
|
||||
bool AllInters(const std::vector<Segment>& segments) const noexcept;
|
||||
void AddOffsets(std::vector<double>& offsets, const Curve& curve, bool end);
|
||||
|
||||
private:
|
||||
|
||||
@ -899,6 +899,16 @@ namespace Aggplus
|
||||
}
|
||||
}
|
||||
|
||||
if (!close)
|
||||
{
|
||||
PointD firstPoint = subPath->GetPoints(0, 1)[0];
|
||||
double x, y;
|
||||
subPath->GetLastPoint(x, y);
|
||||
if (!firstPoint.Equals(PointD(x, y)) || subPath->GetPointCount() == 1) subPath->LineTo(firstPoint.X, firstPoint.Y);
|
||||
subPath->CloseFigure();
|
||||
result.push_back(subPath);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -123,8 +123,10 @@ public:
|
||||
PointF_T(T x, T y) : X(x), Y(y) { }
|
||||
//~PointF() { }
|
||||
INT Equals(const PointF_T& point) const { return(X==point.X && Y==point.Y); }
|
||||
BOOL IsZero() const noexcept { return X == 0.0 && Y == 0.0; }
|
||||
PointF_T operator+(const PointF_T& point) const { return PointF_T(X + point.X, Y + point.Y); }
|
||||
PointF_T operator-(const PointF_T& point) const { return PointF_T(X - point.X, Y - point.Y); }
|
||||
PointF_T& operator=(const PointF_T& other) noexcept {X = other.X; Y = other.Y; return *this;}
|
||||
public:
|
||||
T X, Y;
|
||||
};
|
||||
|
||||
@ -7,17 +7,17 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
const double EPSILON = 1e-12;
|
||||
const double POINT_EPSILON = 1e-2;
|
||||
const double GEOMETRIC_EPSILON = 1e-7;
|
||||
const double TIME_EPSILON = 1e-8;
|
||||
const double MACHINE_EPSILON = 1.12e-16;
|
||||
const double TRIGANOMETRIC_EPSILON = 1e-8;
|
||||
const double CURVETIME_EPSILON = 1e-8;
|
||||
const double LINE_EPSILON = 1e-9;
|
||||
const Aggplus::PointD MIN_POINT(-500.0, -500.0);
|
||||
constexpr double EPSILON = 1e-12;
|
||||
constexpr double POINT_EPSILON = 1e-2;
|
||||
constexpr double GEOMETRIC_EPSILON = 1e-7;
|
||||
constexpr double TIME_EPSILON = 1e-8;
|
||||
constexpr double MACHINE_EPSILON = 1.12e-16;
|
||||
constexpr double TRIGANOMETRIC_EPSILON = 1e-8;
|
||||
constexpr double CURVETIME_EPSILON = 1e-8;
|
||||
constexpr double LINE_EPSILON = 1e-9;
|
||||
constexpr double MIN = std::numeric_limits<double>::min();
|
||||
constexpr double MAX = std::numeric_limits<double>::max();
|
||||
const Aggplus::PointD MIN_POINT(-500.0, -500.0);
|
||||
|
||||
const std::vector<double> ABSCISSAS[16] = {
|
||||
{0.5773502691896257645091488},
|
||||
@ -81,76 +81,73 @@ const std::vector<double> WEIGHT[16] {
|
||||
0.0622535239386478928628438,0.0271524594117540948517806}
|
||||
};
|
||||
|
||||
double max(double v1, double v2, double v3, double v4)
|
||||
inline double max(const double& v1, const double& v2, const double& v3, const double& v4)
|
||||
{
|
||||
return std::max(std::max(v1, v2), std::max(v3, v4));
|
||||
}
|
||||
|
||||
double max(double v1, double v2, double v3)
|
||||
inline double max(const double& v1, const double& v2, const double& v3)
|
||||
{
|
||||
return std::max(std::max(v1, v2), v3);
|
||||
}
|
||||
|
||||
double min(double v1, double v2, double v3, double v4)
|
||||
inline double min(const double& v1, const double& v2, const double& v3, const double& v4)
|
||||
{
|
||||
return std::min(std::min(v1, v2), std::min(v3, v4));
|
||||
}
|
||||
|
||||
double min(double v1, double v2, double v3)
|
||||
inline double min(const double& v1, const double& v2, const double& v3)
|
||||
{
|
||||
return std::min(std::min(v1, v2), v3);
|
||||
}
|
||||
|
||||
bool isZero(double value)
|
||||
inline bool isZero(const double& value)
|
||||
{
|
||||
return value >= -EPSILON && value <= EPSILON;
|
||||
}
|
||||
|
||||
bool isMachineZero(double value)
|
||||
inline bool isMachineZero(const double& value)
|
||||
{
|
||||
return value >= -MACHINE_EPSILON && value <= MACHINE_EPSILON;
|
||||
}
|
||||
|
||||
bool isInRange(double angle, double mn, double mx)
|
||||
inline bool isInRange(const double& angle, const double& mn, const double& mx)
|
||||
{
|
||||
return (mn < mx) ? (angle > mn && angle < mx)
|
||||
: (angle > mn || angle < mx);
|
||||
return (mn < mx) ? (angle > mn && angle < mx) : (angle > mn || angle < mx);
|
||||
}
|
||||
|
||||
double clamp(double value, double mn, double mx)
|
||||
inline double clamp(const double& value, const double& mn, const double& mx)
|
||||
{
|
||||
return value < mn ? mn : value > mx ? mx : value;
|
||||
}
|
||||
|
||||
bool isCollinear(const Aggplus::PointD& p1, const Aggplus::PointD& p2)
|
||||
inline bool isCollinear(const Aggplus::PointD& p1, const Aggplus::PointD& p2)
|
||||
{
|
||||
return abs(p1.X * p2.X + p1.Y * p2.Y) <= sqrt((p1.X * p1.X + p1.Y * p1.Y) * (p2.X * p2.X + p2.Y * p2.Y)) * TRIGANOMETRIC_EPSILON;
|
||||
}
|
||||
|
||||
int getIterations(double a, double b)
|
||||
inline int getIterations(const double& a, const double& b)
|
||||
{
|
||||
double n1 = 2.0, n2 = 16.0;
|
||||
|
||||
return std::max(n1, std::min(n2, ceil(abs(b - a) * 32)));
|
||||
}
|
||||
|
||||
double CurveLength(double t, double ax, double bx, double cx, double ay, double by, double cy)
|
||||
inline double CurveLength(const double& t, const double& ax, const double& bx, const double& cx,
|
||||
const double& ay, const double& by, const double& cy)
|
||||
{
|
||||
double dx = ((ax * t) + bx) * t + cx,
|
||||
dy = ((ay * t) + by) * t + cy;
|
||||
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
return sqrt((((ax * t) + bx) * t + cx) * (((ax * t) + bx) * t + cx) + (((ay * t) + by) * t + cy) * (((ay * t) + by) * t + cy));
|
||||
}
|
||||
|
||||
double integrate(double ax, double bx, double cx, double ay, double by, double cy,
|
||||
double a, double b, size_t n = 16)
|
||||
inline double integrate(const double& ax, const double& bx, const double& cx, const double& ay,
|
||||
const double& by, const double& cy, const double& a, const double& b, size_t n = 16)
|
||||
{
|
||||
std::vector<double> x = ABSCISSAS[n - 2],
|
||||
w = WEIGHT[n - 2];
|
||||
|
||||
double A = (b - a) * 0.5,
|
||||
B = A + a;
|
||||
double sum = n & 1 ? CurveLength(B, ax, bx, cx, ay, by, cy) : 0;
|
||||
double sum = n & 1 ? CurveLength(B, ax, bx, cx, ay, by, cy) : 0.0;
|
||||
|
||||
for (size_t i = 0; i < (n + 1) >> 1; i++)
|
||||
{
|
||||
@ -162,8 +159,9 @@ double integrate(double ax, double bx, double cx, double ay, double by, double c
|
||||
return A * sum;
|
||||
}
|
||||
|
||||
double fLength(double t, double& length, double& start, double offset,
|
||||
double ax, double bx, double cx, double ay, double by, double cy)
|
||||
double fLength(const double& t, double& length, double& start, const double& offset,
|
||||
const double& ax, const double& bx, const double& cx, const double& ay,
|
||||
const double& by, const double& cy)
|
||||
{
|
||||
length += integrate(ax, bx, cx, ay, by, cy, start, t, getIterations(start, t));
|
||||
start = t;
|
||||
@ -171,8 +169,9 @@ double fLength(double t, double& length, double& start, double offset,
|
||||
return length - offset;
|
||||
}
|
||||
|
||||
double findRoot(double& length, double& start, double offset, double ax, double bx,
|
||||
double cx, double ay, double by, double cy, double x, double a, double b)
|
||||
double findRoot(double& length, double& start, const double& offset, const double& ax,
|
||||
const double& bx, const double& cx, const double& ay, const double& by,
|
||||
const double& cy, double x, double a, double b)
|
||||
{
|
||||
for (size_t i = 0; i < 32; i++)
|
||||
{
|
||||
@ -229,7 +228,8 @@ bool intersect(std::vector<double> v, Aggplus::PointD& res)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::vector<Aggplus::PointD>> getConvexHull(double dq0, double dq1, double dq2, double dq3)
|
||||
std::vector<std::vector<Aggplus::PointD>> getConvexHull(const double& dq0, const double& dq1,
|
||||
const double& dq2, const double& dq3)
|
||||
{
|
||||
Aggplus::PointD p0 = Aggplus::PointD(0.0, dq0),
|
||||
p1 = Aggplus::PointD(1.0 / 3.0, dq1),
|
||||
@ -262,7 +262,8 @@ std::vector<std::vector<Aggplus::PointD>> getConvexHull(double dq0, double dq1,
|
||||
return hull;
|
||||
}
|
||||
|
||||
double clipConvexHullPart(std::vector<Aggplus::PointD> part, bool top, double threshold)
|
||||
double clipConvexHullPart(const std::vector<Aggplus::PointD>& part, const bool& top,
|
||||
const double& threshold)
|
||||
{
|
||||
double px = part[0].X,
|
||||
py = part[0].Y;
|
||||
@ -281,7 +282,9 @@ double clipConvexHullPart(std::vector<Aggplus::PointD> part, bool top, double th
|
||||
return MIN;
|
||||
}
|
||||
|
||||
double clipConvexHull(std::vector<Aggplus::PointD> top, std::vector<Aggplus::PointD> bottom, double dMin, double dMax)
|
||||
inline double clipConvexHull(const std::vector<Aggplus::PointD>& top,
|
||||
const std::vector<Aggplus::PointD>& bottom,
|
||||
const double& dMin, const double& dMax)
|
||||
{
|
||||
if (top[0].Y < dMin)
|
||||
return clipConvexHullPart(top, true, dMin);
|
||||
@ -291,10 +294,11 @@ double clipConvexHull(std::vector<Aggplus::PointD> top, std::vector<Aggplus::Poi
|
||||
return top[0].X;
|
||||
}
|
||||
|
||||
int binarySearch(std::vector<std::vector<double>> allBounds, std::vector<int> indices, size_t coord, double value)
|
||||
inline int binarySearch(const std::vector<std::vector<double>>& allBounds,
|
||||
const std::vector<int>& indices, const size_t& coord, const double& value)
|
||||
{
|
||||
int lo = 0,
|
||||
hi = indices.size();
|
||||
hi = static_cast<int>(indices.size());
|
||||
|
||||
while(lo < hi)
|
||||
{
|
||||
@ -308,7 +312,8 @@ int binarySearch(std::vector<std::vector<double>> allBounds, std::vector<int> in
|
||||
return lo - 1;
|
||||
}
|
||||
|
||||
double getSignedDistance(double px, double py, double vx, double vy, double x, double y, bool asVector = false)
|
||||
inline double getSignedDistance(const double& px, const double& py, double vx, double vy,
|
||||
const double& x, const double& y, bool asVector = false)
|
||||
{
|
||||
if (!asVector)
|
||||
{
|
||||
@ -331,12 +336,14 @@ double getSignedDistance(double px, double py, double vx, double vy, double x, d
|
||||
return vx0 ? distX : vy0 ? distY : distXY;
|
||||
}
|
||||
|
||||
double getDistance(double px, double py, double vx, double vy, double x, double y, bool asVector)
|
||||
inline double getDistance(const double& px, const double& py, const double& vx, const double& vy,
|
||||
const double& x, const double& y, const bool& asVector)
|
||||
{
|
||||
return abs(getSignedDistance(px, py, vx, vy, x, y, asVector));
|
||||
}
|
||||
|
||||
double getDistance(double px, double py, double vx, double vy, double x, double y)
|
||||
inline double getDistance(const double& px, const double& py, const double& vx, const double& vy,
|
||||
const double& x, const double& y)
|
||||
{
|
||||
if (vx == 0)
|
||||
{
|
||||
@ -361,21 +368,17 @@ double getDistance(double px, double py, double vx, double vy, double x, double
|
||||
return dist / (dir ? epsY : epsX);
|
||||
}
|
||||
|
||||
double getDistance(double x1, double y1, double x2, double y2)
|
||||
inline double getDistance(const double& x1, const double& y1, const double& x2, const double& y2)
|
||||
{
|
||||
double x = x2 - x1,
|
||||
y = y2 - y1,
|
||||
d = x * x + y * y;
|
||||
|
||||
return sqrt(d);
|
||||
return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||
}
|
||||
|
||||
double getDistance(Aggplus::PointD point1, Aggplus::PointD point2)
|
||||
inline double getDistance(const Aggplus::PointD& point1, const Aggplus::PointD& point2)
|
||||
{
|
||||
return getDistance(point1.X, point1.Y, point2.X, point2.Y);
|
||||
}
|
||||
|
||||
std::pair<double, double> split(double v)
|
||||
inline std::pair<double, double> split(const double& v)
|
||||
{
|
||||
double x = v * 134217729.0,
|
||||
y = v - x,
|
||||
@ -385,7 +388,7 @@ std::pair<double, double> split(double v)
|
||||
return std::pair<double, double>(hi, lo);
|
||||
}
|
||||
|
||||
double getDiscriminant(double a, double b, double c)
|
||||
inline double getDiscriminant(const double& a, const double& b, const double& c)
|
||||
{
|
||||
double D = b * b - a * c,
|
||||
E = b * b + a * c;
|
||||
@ -413,7 +416,7 @@ double getDiscriminant(double a, double b, double c)
|
||||
}
|
||||
|
||||
int solveQuadratic(double a, double b, double c, std::vector<double>& roots,
|
||||
double mn, double mx)
|
||||
const double& mn, const double& mx)
|
||||
{
|
||||
double x1 = MAX, x2 = MAX;
|
||||
if (abs(a) < EPSILON)
|
||||
@ -432,7 +435,7 @@ int solveQuadratic(double a, double b, double c, std::vector<double>& roots,
|
||||
double f = max(abs(a), abs(b), abs(c));
|
||||
if (f < 1e-8 || f < 1e8)
|
||||
{
|
||||
f = pow(2, -roundf(log2(f)));
|
||||
f = pow(2, -round(log2(f)));
|
||||
a *= f;
|
||||
b *= f;
|
||||
c *= f;
|
||||
|
||||
@ -212,7 +212,7 @@ void MainWindow::AddPath(NSGraphics::IGraphicsRenderer* pathRenderer, const Aggp
|
||||
pathRenderer->BeginCommand(c_nPathType);
|
||||
|
||||
size_t length = path.GetPointCount(),
|
||||
compound = path.GetCompoundPath();
|
||||
compound = path.GetCloseCount();
|
||||
std::vector<Aggplus::PointD> points = path.GetPoints(0, length + compound);
|
||||
|
||||
for (size_t i = 0; i < length + compound; i++)
|
||||
|
||||
Reference in New Issue
Block a user