/******************************************************************************* * * * Author: Alexis Naveros * * Algorithm and implementation inspired by the Clipper2 library * * This is partly a rewrite of Clipper2, more optimized, scalable and robust * * * * Clipper2's Copyright: (C) Angus Johnson 2010-2022 * * Clipper2's copyright notice included below * * * *******************************************************************************/ /******************************************************************************* * Author : Angus Johnson * * Version : Clipper2 - beta * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2022 * * License : http://www.boost.org/LICENSE_1_0.txt * *******************************************************************************/ #ifndef polyclip_h #define polyclip_h //// #define CLP_DEBUG_VERBOSE (0) //// #ifdef __cplusplus extern "C" { #endif //// /* Packed array of vertices, stored in vertexlist as x,y,x,y,x... */ typedef struct { size_t vertexcount; int64_t *vertexlist; } clpPath; /* Array of paths */ typedef struct { size_t pathcount; clpPath *pathlist; } clpShape; typedef struct clpTree clpTree; /* Hierarchy of closed paths (contours), where holes and parents are identifed */ struct clpTree { clpPath path; clpTree *parent; size_t childcount; clpTree **childlist; int holeflag; }; //// /* Opaque clipper object handle */ typedef struct clpClipper clpClipper; /* Creates the clpClipper object, free it with clpDestroyClipper() */ /* orientation_is_reversed: Normal orientation is origin in top-left (2D graphics) ~ set non-zero to flip orientation */ clpClipper *clpCreateClipper( int orientation_is_reversed ); /* Destroy the clpClipper object previously returned by clpCreateClipper() */ void clpDestroyClipper( clpClipper *clp ); /* Set the "preserve colinear point" flag, default value is non-zero (preserved) */ void clpSetPreserveCollinear( clpClipper *clp, int preservecollinearflag ); /* Set the "reverse solution" flag, default value is zero (not reversed) */ void clpSetReverseSolution( clpClipper *clp, int reversesolutionflag ); /* Add a path to clipper object */ /* vertexlist: packed array of x,y,x,y,x... values, the memory storage must remain valid for further clpClipperExecute*() */ /* pathtype: CLP_PATHTYPE_SUBJECT or CLP_PATHTYPE_CLIP */ /* is_open: zero for a path to be a closed contour, non-zero for a path with open ends */ void clpAddPath( clpClipper *clp, int64_t *vertexlist, size_t vertexcount, uint8_t pathtype, uint8_t is_open ); /* Add a shape (array of contours/paths) to clipper object */ /* shape: clpShape struct (array of contours/paths), the memory storage must remain valid for further clpClipperExecute*() */ /* pathtype: CLP_PATHTYPE_SUBJECT or CLP_PATHTYPE_CLIP */ /* is_open: zero for a path to be a closed contour, non-zero for a path with open ends */ void clpAddShape( clpClipper *clp, const clpShape *shape, uint8_t pathtype, uint8_t is_open ); /* Execute a clip operation between shape(s) of closed paths (contours) */ /* cliptype: CLP_CLIPTYPE_INTERSECTION, CLP_CLIPTYPE_UNION, CLP_CLIPTYPE_DIFFERENCE or CLP_CLIPTYPE_XOR */ /* fillrule: CLP_FILLRULE_EVENODD, CLP_FILLRULE_NONZERO, CLP_FILLRULE_POSITIVE or CLP_FILLRULE_NEGATIVE */ /* shape: pointer to a clpShape where the solution is stored ~ to be freed with clpFreeShape() */ int clpClipperExecute( clpClipper *clp, int cliptype, int fillrule, clpShape *shape ); /* Execute a clip operation with support for non-closed paths */ /* cliptype: CLP_CLIPTYPE_INTERSECTION, CLP_CLIPTYPE_UNION, CLP_CLIPTYPE_DIFFERENCE or CLP_CLIPTYPE_XOR */ /* fillrule: CLP_FILLRULE_EVENODD, CLP_FILLRULE_NONZERO, CLP_FILLRULE_POSITIVE or CLP_FILLRULE_NEGATIVE */ /* shape: pointer to a clpShape where the closed shapes are stored ~ to be freed with clpFreeShape() */ /* shapeopen: pointer to a clpShape where the open shapes are stored ~ to be freed with clpFreeShape() */ int clpClipperExecute_RetOpen( clpClipper *clp, int cliptype, int fillrule, clpShape *shape, clpShape *shapeopen ); /* Execute a clip operation returning a tree hierarchy of paths (identifying holes and parents) */ /* cliptype: CLP_CLIPTYPE_INTERSECTION, CLP_CLIPTYPE_UNION, CLP_CLIPTYPE_DIFFERENCE or CLP_CLIPTYPE_XOR */ /* fillrule: CLP_FILLRULE_EVENODD, CLP_FILLRULE_NONZERO, CLP_FILLRULE_POSITIVE or CLP_FILLRULE_NEGATIVE */ /* shapetree: pointer to a clpTree where the hierarchy of closed shapes are stored ~ to be freed with clpFreeTree() */ /* shapeopen: pointer to a clpShape where the open shapes are stored ~ to be freed with clpFreeShape() */ int clpClipperExecute_RetTree( clpClipper *clp, int cliptype, int fillrule, clpTree *shapetree, clpShape *shapeopen ); /* Free a clpShape solution stored by any clpClipperExecute*() call */ void clpFreeShape( clpShape *shape ); /* Free a clpTree solution stored by any clpClipperExecute*() call */ void clpFreeTree( clpTree *tree ); /* Valid values for "cliptype" argument of clpClipperExecute*() functions */ /* Note: all clipping operations except for Difference are commutative. */ enum { CLP_CLIPTYPE_NONE, CLP_CLIPTYPE_INTERSECTION, CLP_CLIPTYPE_UNION, CLP_CLIPTYPE_DIFFERENCE, CLP_CLIPTYPE_XOR }; /* Valid values for "fillrule" argument of clpClipperExecute*() functions */ /* By far the most widely used filling rules for polygons are EvenOdd */ /* and NonZero, sometimes called Alternate and Winding respectively. */ /* https://en.wikipedia.org/wiki/Nonzero-rule */ enum { CLP_FILLRULE_EVENODD, CLP_FILLRULE_NONZERO, CLP_FILLRULE_POSITIVE, CLP_FILLRULE_NEGATIVE }; /* Valid values for "pathtype" argument of clpAddPath() and clpAddShape() functions */ enum { CLP_PATHTYPE_SUBJECT, CLP_PATHTYPE_CLIP }; //// /* Opaque offset object handle */ typedef struct clpOffset clpOffset; clpOffset *clpOffsetCreate(); void clpOffsetDestroy( clpOffset *clpoffset ); /* shape: clpShape struct (array of contours/paths), the memory storage must remain valid for further clpOffsetExecute*() */ void clpOffsetAddShape( clpOffset *clpoffset, clpShape *shape, int jointype, int endtype ); /* vertexlist: packed array of x,y,x,y,x... values, the memory storage must remain valid for further clpOffsetExecute*() */ void clpOffsetAddPath( clpOffset *clpoffset, int64_t *vertexlist, size_t vertexcount, int jointype, int endtype ); clpShape clpOffsetExecute( clpOffset *clpoffset, double delta ); enum { CLP_JOINTYPE_SQUARE, CLP_JOINTYPE_ROUND, CLP_JOINTYPE_MITER }; enum { // Polygon: offsets only one side of a closed path CLP_ENDTYPE_POLYGON, // Joined : offsets both sides of a path, with joined ends CLP_ENDTYPE_JOINED, // Butt : offsets both sides of a path, with square blunt ends CLP_ENDTYPE_BUTT, // Square : offsets both sides of a path, with square extended ends CLP_ENDTYPE_SQUARE, // Round : offsets both sides of a path, with round extended ends CLP_ENDTYPE_ROUND }; //// void clpConvDoubleToInt64( double *dstvl64, int64_t *srcvld, size_t vertexcount, double convfactor ); void clpConvInt64ToDouble( double *dstvld, int64_t *srcvl64, size_t vertexcount, double convfactor ); int clpTestPointWithinShape( clpShape *shape, int64_t ptx, int64_t pty ); //// #ifdef __cplusplus } #endif //// #endif //polyclip_h