mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 00:04:04 +08:00
Co-authored-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com> Co-committed-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com>
229 lines
8.3 KiB
C++
229 lines
8.3 KiB
C++
/*
|
|
* Copyright (C) Ascensio System SIA, 2009-2026
|
|
*
|
|
* This program is a free software product. You can redistribute it and/or
|
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
* version 3 as published by the Free Software Foundation, together with the
|
|
* additional terms provided in the LICENSE file.
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
* details, see the GNU AGPL at: https://www.gnu.org/licenses/agpl-3.0.html
|
|
*
|
|
* You can contact Ascensio System SIA by email at info@onlyoffice.com
|
|
* or by postal mail at 20A-6 Ernesta Birznieka-Upisha Street, Riga,
|
|
* LV-1050, Latvia, European Union.
|
|
*
|
|
* The interactive user interfaces in modified versions of the Program
|
|
* are required to display Appropriate Legal Notices in accordance with
|
|
* Section 5 of the GNU AGPL version 3.
|
|
*
|
|
* No trademark rights are granted under this License.
|
|
*
|
|
* All non-code elements of the Product, including illustrations,
|
|
* icon sets, and technical writing content, are licensed under the
|
|
* Creative Commons Attribution-ShareAlike 4.0 International License:
|
|
* https://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
*
|
|
* This license applies only to such non-code elements and does not
|
|
* modify or replace the licensing terms applicable to the Program's
|
|
* source code, which remains licensed under the GNU Affero General
|
|
* Public License v3.
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
#ifndef BOOLEANOPERATIONS_H
|
|
#define BOOLEANOPERATIONS_H
|
|
|
|
#include "GraphicsPath.h"
|
|
#include <memory>
|
|
|
|
namespace Aggplus
|
|
{
|
|
struct Location;
|
|
|
|
struct Segment
|
|
{
|
|
PointD P{};
|
|
PointD HI{};
|
|
PointD HO{};
|
|
|
|
bool IsCurve = false;
|
|
bool Visited = false;
|
|
bool PolyClosed = false;
|
|
bool Winding = false;
|
|
|
|
int Index = -1;
|
|
int Id = 0;
|
|
|
|
std::shared_ptr<Location> Inters{nullptr};
|
|
|
|
Segment() noexcept;
|
|
Segment(const std::vector<PointD>& points, const bool& isCurve,
|
|
const int& index, const int& id, const bool& polyClosed) noexcept;
|
|
Segment(const PointD& point, 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) noexcept;
|
|
void UpdateHandles(const PointD& hi, const PointD& ho) noexcept;
|
|
|
|
bool IsValid(const BooleanOpType& op) const noexcept;
|
|
bool IsEmpty() const noexcept;
|
|
bool Equals(const Segment& other) const noexcept;
|
|
bool operator==(const Segment& other) const noexcept;
|
|
bool operator!=(const Segment& other) const noexcept;
|
|
};
|
|
|
|
struct Curve
|
|
{
|
|
Segment Segment1{};
|
|
Segment Segment2{};
|
|
|
|
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 noexcept;
|
|
std::vector<double> GetYValues() const noexcept;
|
|
std::vector<double> GetBound() const noexcept;
|
|
std::vector<double> GetPeeks() const;
|
|
double GetLength(double a = 0, double b = 1) 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(const double& t) const noexcept;
|
|
Curve DivideAtTime(const double& time) noexcept;
|
|
|
|
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() noexcept;
|
|
|
|
bool IsStraight() const noexcept;
|
|
bool Equals(const Curve& other) const noexcept;
|
|
bool operator==(const Curve& other) const noexcept;
|
|
bool operator!=(const Curve& other) const noexcept;
|
|
};
|
|
|
|
struct Location
|
|
{
|
|
Curve C{};
|
|
Segment S{};
|
|
double Time = -1.0;
|
|
bool Overlap = false;
|
|
bool Ends = false;
|
|
|
|
std::shared_ptr<Location> Inters{nullptr};
|
|
std::shared_ptr<Location> Next{nullptr};
|
|
std::shared_ptr<Location> Prev{nullptr};
|
|
|
|
Location() noexcept;
|
|
Location(const Curve& curve, const double& time, const bool& overlap, const bool& ends) noexcept;
|
|
|
|
bool IsTouching() noexcept;
|
|
};
|
|
|
|
class CBooleanOperations
|
|
{
|
|
public:
|
|
CBooleanOperations() {};
|
|
CBooleanOperations(const CGraphicsPath& path1, const CGraphicsPath& path2, BooleanOpType op, long fillType, bool isLuminosity, bool isSelf);
|
|
~CBooleanOperations();
|
|
CGraphicsPath&& GetResult();
|
|
bool IsSelfInters(const CGraphicsPath& p);
|
|
|
|
// BooleanOp
|
|
void TraceBoolean();
|
|
void TraceOneInters();
|
|
void TraceAllOverlap();
|
|
void TracePaths();
|
|
void TraceOneCurvePath1();
|
|
void TraceOneCurvePath2();
|
|
|
|
// Path
|
|
void PreparePath(const CGraphicsPath& path, int id, std::vector<Segment>& segments,
|
|
std::vector<Curve>& curves, bool reverse = false);
|
|
void InsertSegment(Segment& segment, const Segment& handles, bool updateHandles);
|
|
Curve GetCurve(const Segment& segment) const noexcept;
|
|
Curve GetPreviousCurve(const Curve& curve) const noexcept;
|
|
Curve GetNextCurve(const Curve& curve) const noexcept;
|
|
Segment GetPreviousSegment(const Segment& segment) const noexcept;
|
|
Segment GetNextSegment(const Segment& segment) const noexcept;
|
|
void SetVisited(const Segment& segment);
|
|
void CreateNewPath(const std::vector<std::vector<int>>& adjMatr) noexcept;
|
|
|
|
// Bounds
|
|
std::vector<std::vector<int>> FindBoundsCollisions();
|
|
|
|
// Intersection
|
|
bool IsCrossing(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);
|
|
void AddLineIntersection(const Curve& curve1, const Curve& curve2);
|
|
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;
|
|
bool IsInside(const Segment& segment) const;
|
|
void SetWinding();
|
|
|
|
// Location
|
|
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 noexcept;
|
|
bool AllInters(const std::vector<Segment>& segments) const noexcept;
|
|
bool IsOneCurvePath(int pathIndex) const noexcept;
|
|
void AddOffsets(std::vector<double>& offsets, const Curve& curve, bool end);
|
|
bool CheckLocation(std::shared_ptr<Location> loc, bool start) const noexcept;
|
|
bool IsOnlyEnds() const noexcept;
|
|
|
|
private:
|
|
BooleanOpType Op = Intersection;
|
|
|
|
bool Close1 = true;
|
|
bool Close2 = true;
|
|
bool IsLuminosity = false;
|
|
bool IsSelf = false;
|
|
|
|
// c_nStroke, c_nWindingFillMode, c_nEvenOddFillMode
|
|
long FillType = c_nWindingFillMode;
|
|
|
|
CGraphicsPath Path1{};
|
|
CGraphicsPath Path2{};
|
|
CGraphicsPath Result{};
|
|
|
|
std::vector<Segment> Segments1;
|
|
std::vector<Segment> Segments2;
|
|
|
|
std::vector<Curve> OriginCurves1;
|
|
std::vector<Curve> OriginCurves2;
|
|
std::vector<Curve> Curves1;
|
|
std::vector<Curve> Curves2;
|
|
|
|
std::vector<std::shared_ptr<Location>> Locations;
|
|
};
|
|
} // namespace Aggplus
|
|
|
|
#endif // BOOLEANOPERATIONS_H
|