/* * 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 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 Inters{nullptr}; Segment() noexcept; Segment(const std::vector& 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& 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 GetXValues() const noexcept; std::vector GetYValues() const noexcept; std::vector GetBound() const noexcept; std::vector 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 GetMonoCurves(const bool& dir) const noexcept; std::vector GetCurveLineIntersection(const double& px, const double& py, const double& vx, const double& vy) const noexcept; std::vector> GetOverlaps(const Curve& curve) const noexcept; std::vector Subdivide(const double& t) const noexcept; Curve DivideAtTime(const double& time) noexcept; int SolveCubic(const int& coord, const double& value, std::vector& roots, const double& mn, const double& mx) const noexcept; int SolveCubic(double a, double b, double c, double d, std::vector& 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 Inters{nullptr}; std::shared_ptr Next{nullptr}; std::shared_ptr 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& segments, std::vector& 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>& adjMatr) noexcept; // Bounds std::vector> FindBoundsCollisions(); // Intersection bool IsCrossing(std::shared_ptr loc) noexcept; bool IntersectsBounds() noexcept; void GetIntersection(); void GetCurveIntersection(const Curve& curve1, const Curve& curve2); void LinkIntersection(std::shared_ptr form, std::shared_ptr 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 loc, bool overlap); bool AllOverlap() const noexcept; bool AllInters(const std::vector& segments) const noexcept; bool IsOneCurvePath(int pathIndex) const noexcept; void AddOffsets(std::vector& offsets, const Curve& curve, bool end); bool CheckLocation(std::shared_ptr 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 Segments1; std::vector Segments2; std::vector OriginCurves1; std::vector OriginCurves2; std::vector Curves1; std::vector Curves2; std::vector> Locations; }; } // namespace Aggplus #endif // BOOLEANOPERATIONS_H