Compare commits

...

1 Commits

Author SHA1 Message Date
ce1763501b Optimization 2025-02-25 10:59:19 +03:00
4 changed files with 73 additions and 65 deletions

View File

@ -730,14 +730,14 @@ bool Location::IsTouching() noexcept
PointD pt;
bool straight = C.IsStraight() && Inters->C.IsStraight();
return !straight || !intersect({C.Segment1.P.X,
C.Segment1.P.Y,
C.Segment2.P.X,
C.Segment2.P.Y,
Inters->C.Segment1.P.X,
Inters->C.Segment1.P.Y,
Inters->C.Segment2.P.X,
Inters->C.Segment2.P.Y}, pt);
return !straight || !intersect(C.Segment1.P.X,
C.Segment1.P.Y,
C.Segment2.P.X,
C.Segment2.P.Y,
Inters->C.Segment1.P.X,
Inters->C.Segment1.P.Y,
Inters->C.Segment2.P.X,
Inters->C.Segment2.P.Y, pt);
}
CBooleanOperations::CBooleanOperations(const CGraphicsPath& path1,
@ -943,7 +943,7 @@ void CBooleanOperations::TraceAllOverlap()
{
int touchCount = 0;
for (const auto& c : OriginCurves2)
count1 += CheckInters(MIN_POINT, s, c, touchCount);
count1 += CheckInters(s, c, touchCount);
break;
}
}
@ -954,7 +954,7 @@ void CBooleanOperations::TraceAllOverlap()
{
int touchCount = 0;
for (const auto& c : OriginCurves1)
count2 += CheckInters(MIN_POINT, s, c, touchCount);
count2 += CheckInters(s, c, touchCount);
break;
}
}
@ -1255,20 +1255,26 @@ void CBooleanOperations::SetVisited(const Segment& segment)
std::vector<std::vector<int>> CBooleanOperations::FindBoundsCollisions()
{
int length1 = static_cast<int>(Curves1.size()),
length2 = static_cast<int>(Curves2.size());
std::vector<std::vector<double>> allBounds, bounds2;
allBounds.reserve(length1 + length2);
bounds2.reserve(length2);
for (const auto& c : Curves1)
allBounds.push_back(c.GetBound());
allBounds.emplace_back(c.GetBound());
for (const auto& c : Curves2)
bounds2.push_back(c.GetBound());
bounds2.emplace_back(c.GetBound());
bool self = allBounds == bounds2;
if (!self)
for (auto it = bounds2.begin(); it != bounds2.end(); ++it)
allBounds.push_back(*it);
{
allBounds.resize(length1 + length2);
for (size_t i = 0; i < length2; i++)
allBounds[i + length1] = std::move(bounds2[i]);
}
int allLength = static_cast<int>(allBounds.size()),
length1 = static_cast<int>(Curves1.size());
int allLength = static_cast<int>(allBounds.size());
std::vector<int> allIdicesByPri1(allLength);
for (int i = 0; i < allLength; i++)
@ -1502,8 +1508,8 @@ void CBooleanOperations::LinkIntersection(std::shared_ptr<Location> from,
void CBooleanOperations::AddLineIntersection(const Curve& curve1, const Curve& curve2)
{
PointD pt;
if (intersect({curve1.Segment1.P.X, curve1.Segment1.P.Y, curve1.Segment2.P.X, curve1.Segment2.P.Y,
curve2.Segment1.P.X, curve2.Segment1.P.Y, curve2.Segment2.P.X, curve2.Segment2.P.Y}, pt))
if (intersect(curve1.Segment1.P.X, curve1.Segment1.P.Y, curve1.Segment2.P.X, curve1.Segment2.P.Y,
curve2.Segment1.P.X, curve2.Segment1.P.Y, curve2.Segment2.P.X, curve2.Segment2.P.Y, pt))
AddLocation(curve1, curve2, curve1.GetTimeOf(pt), curve2.GetTimeOf(pt));
}
@ -1626,10 +1632,10 @@ int CBooleanOperations::AddCurveIntersection(const Curve& curve1, const Curve& c
return calls;
}
int CBooleanOperations::CheckInters(const PointD& point, const Segment& segment, const Curve& curve, int& touchCount) const
int CBooleanOperations::CheckInters(const Segment& segment, const Curve& curve, int& touchCount) const
{
PointD pt{};
if (intersect({point.X, point.Y, segment.P.X, segment.P.Y, curve.Segment1.P.X, curve.Segment1.P.Y, curve.Segment2.P.X, curve.Segment2.P.Y}, pt))
if (intersect(MIN_POINT.X, MIN_POINT.Y, segment.P.X, segment.P.Y, curve.Segment1.P.X, curve.Segment1.P.Y, curve.Segment2.P.X, curve.Segment2.P.Y, pt))
{
if (getDistance(segment.P, pt) <= GEOMETRIC_EPSILON) return (touchCount + 1) % 2;
if (getDistance(curve.Segment1.P, pt) <= GEOMETRIC_EPSILON || getDistance(curve.Segment2.P, pt) <= GEOMETRIC_EPSILON)
@ -1642,8 +1648,8 @@ 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(segment, Segment(point));
std::vector<double> roots = curve.GetCurveLineIntersection(segment.P.X,segment.P.Y, MIN_POINT.X - segment.P.X, MIN_POINT.Y - segment.P.Y);
Curve line(segment, Segment(MIN_POINT));
int count = 0;
for (const auto& r : roots)
@ -1672,7 +1678,7 @@ void CBooleanOperations::SetWinding()
int count = 0,
touchCount = 0;
for (const auto& c : OriginCurves2)
count += CheckInters(MIN_POINT, s1, c, touchCount);
count += CheckInters(s1, c, touchCount);
for (auto& s : Segments1)
s.Winding = count % 2;
@ -1680,7 +1686,7 @@ void CBooleanOperations::SetWinding()
count = 0;
touchCount = 0;
for (const auto& c : OriginCurves1)
count += CheckInters(MIN_POINT, s2, c, touchCount);
count += CheckInters(s2, c, touchCount);
for (auto& s : Segments2)
s.Winding = count % 2;
@ -1698,7 +1704,7 @@ void CBooleanOperations::SetWinding()
int count = 0,
touchCount = 0;
for (const auto& c : (s.Id == 1 ? OriginCurves2 : OriginCurves1))
count += CheckInters(MIN_POINT, s, c, touchCount);
count += CheckInters(s, c, touchCount);
do
{

View File

@ -140,7 +140,7 @@ namespace Aggplus
void AddCurveLineIntersection(const Curve& curve1, const Curve& curve2, bool flip);
int AddCurveIntersection(const Curve& curve1, const Curve& curve2, const Curve& startCurve1, const Curve& startCurve2, bool flip,
int recursion = 0, int calls = 0, double tMin = 0.0, double tMax = 1.0, double uMin = 0.0, double uMax = 1.0);
int CheckInters(const PointD& point, const Segment& segment, const Curve& curve, int& touchCount) const;
int CheckInters(const Segment& segment, const Curve& curve, int& touchCount) const;
void SetWinding();
// Location

View File

@ -837,12 +837,13 @@ namespace Aggplus
{
std::vector<PointD> points;
unsigned length = m_internal->m_agg_ps.total_vertices();
points.resize(count);
for (unsigned i = 0; i < count; i++)
{
double x,y;
if (idx + i > length) break;
this->m_internal->m_agg_ps.vertex(idx + i, &x, &y);
points.push_back(PointD(x, y));
points[i] = PointD(x, y);
}
return points;
@ -885,37 +886,37 @@ namespace Aggplus
{
std::vector<CGraphicsPath> result;
CGraphicsPath subPath;
bool close = true;
CGraphicsPath sub_path;
for (unsigned i = 0; i < m_internal->m_agg_ps.total_vertices(); i++)
{
if (IsMovePoint(i))
{
if (!close)
{
PointD firstPoint = subPath.GetPoints(0, 1)[0];
PointD firstPoint = sub_path.GetPoints(0, 1)[0];
double x, y;
subPath.GetLastPoint(x, y);
sub_path.GetLastPoint(x, y);
if ((abs(firstPoint.X - x) <= 1e-2 && abs(firstPoint.Y - y) <= 1e-2) ||
subPath.GetPointCount() == 1)
sub_path.GetPointCount() == 1)
{
if (!firstPoint.Equals(PointD(x, y)) || subPath.GetPointCount() == 1)
subPath.LineTo(firstPoint.X, firstPoint.Y);
subPath.CloseFigure();
if (!firstPoint.Equals(PointD(x, y)) || sub_path.GetPointCount() == 1)
sub_path.LineTo(firstPoint.X, firstPoint.Y);
sub_path.CloseFigure();
}
result.push_back(subPath);
subPath.Reset();
result.push_back(sub_path);
sub_path.Reset();
}
subPath.StartFigure();
sub_path.StartFigure();
PointD point = GetPoints(i, 1)[0];
subPath.MoveTo(point.X, point.Y);
sub_path.MoveTo(point.X, point.Y);
close = false;
}
else if (IsCurvePoint(i))
{
std::vector<PointD> points = GetPoints(i, 3);
subPath.CurveTo(points[0].X, points[0].Y,
sub_path.CurveTo(points[0].X, points[0].Y,
points[1].X, points[1].Y,
points[2].X, points[2].Y);
i += 2;
@ -923,40 +924,40 @@ namespace Aggplus
else if (IsLinePoint(i))
{
PointD point = GetPoints(i, 1)[0];
subPath.LineTo(point.X, point.Y);
sub_path.LineTo(point.X, point.Y);
}
else if (IsClosePoint(i))
{
PointD firstPoint = subPath.GetPoints(0, 1)[0];
PointD firstPoint = sub_path.GetPoints(0, 1)[0];
double x, y;
subPath.GetLastPoint(x, y);
sub_path.GetLastPoint(x, y);
if (!firstPoint.Equals(PointD(x, y)) || subPath.GetPointCount() == 1)
subPath.LineTo(firstPoint.X, firstPoint.Y);
if (!firstPoint.Equals(PointD(x, y)) || sub_path.GetPointCount() == 1)
sub_path.LineTo(firstPoint.X, firstPoint.Y);
subPath.CloseFigure();
result.push_back(subPath);
subPath.Reset();
sub_path.CloseFigure();
result.push_back(sub_path);
sub_path.Reset();
close = true;
}
}
if (!close)
{
PointD firstPoint = subPath.GetPoints(0, 1)[0];
PointD firstPoint = sub_path.GetPoints(0, 1)[0];
double x, y;
subPath.GetLastPoint(x, y);
sub_path.GetLastPoint(x, y);
if ((abs(firstPoint.X - x) <= 1e-2 && abs(firstPoint.Y - y) <= 1e-2) ||
subPath.GetPointCount() == 1)
sub_path.GetPointCount() == 1)
{
if (!firstPoint.Equals(PointD(x, y)) ||
subPath.GetPointCount() == 1)
subPath.LineTo(firstPoint.X, firstPoint.Y);
subPath.CloseFigure();
sub_path.GetPointCount() == 1)
sub_path.LineTo(firstPoint.X, firstPoint.Y);
sub_path.CloseFigure();
}
result.push_back(subPath);
result.push_back(sub_path);
}
return result;

View File

@ -151,27 +151,28 @@ inline double integrate(const double& ax, const double& bx, const double& cx, co
return A * sum;
}
inline bool intersect(std::vector<double> v, Aggplus::PointD& res)
inline bool intersect(double v0, double v1, double v2, double v3, double v4,
double v5, double v6, double v7, Aggplus::PointD& res)
{
v[2] -= v[0];
v[3] -= v[1];
v[6] -= v[4];
v[7] -= v[5];
v2 -= v0;
v3 -= v1;
v6 -= v4;
v7 -= v5;
double cross = v[2] * v[7] - v[3] * v[6];
double cross = v2 * v7 - v3 * v6;
if (!isMachineZero(cross))
{
double dx = v[0] - v[4],
dy = v[1] - v[5],
u1 = (v[6] * dy - v[7] * dx) / cross,
u2 = (v[2] * dy - v[3] * dx) / cross,
double dx = v0 - v4,
dy = v1 - v5,
u1 = (v6 * dy - v7 * dx) / cross,
u2 = (v2 * dy - v3 * dx) / cross,
uMin = -EPSILON,
uMax = 1 + EPSILON;
if (uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax)
{
u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;
res = Aggplus::PointD(v[0] + u1 * v[2], v[1] + u1 * v[3]);
res = Aggplus::PointD(v0 + u1 * v2, v1 + u1 * v3);
return true;
}