#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 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 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); ~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; private: BooleanOpType Op = Intersection; bool Close1 = true; bool Close2 = true; bool IsLuminosity = 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