Skip to content

Commit

Permalink
Numerous minor bugfixes to ClipperOffset (#703)
Browse files Browse the repository at this point in the history
  • Loading branch information
AngusJohnson committed Nov 8, 2023
1 parent ff03eac commit 775ec62
Show file tree
Hide file tree
Showing 19 changed files with 1,001 additions and 734 deletions.
32 changes: 24 additions & 8 deletions CPP/Clipper2Lib/include/clipper2/clipper.core.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 4 October 2023 *
* Date : 1 November 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Core Clipper Library structures and functions *
Expand All @@ -19,7 +19,7 @@
#include <algorithm>
#include <climits>
#include <numeric>
#include "clipper.version.h"
#include "clipper2/clipper.version.h"

namespace Clipper2Lib
{
Expand Down Expand Up @@ -229,6 +229,14 @@ namespace Clipper2Lib
using Paths64 = std::vector< Path64>;
using PathsD = std::vector< PathD>;

static const Point64 InvalidPoint64 = Point64(
(std::numeric_limits<int64_t>::max)(),
(std::numeric_limits<int64_t>::max)());
static const PointD InvalidPointD = PointD(
(std::numeric_limits<double>::max)(),
(std::numeric_limits<double>::max)());


// Rect ------------------------------------------------------------------------

template <typename T>
Expand Down Expand Up @@ -259,10 +267,12 @@ namespace Clipper2Lib
else
{
left = top = (std::numeric_limits<T>::max)();
right = bottom = -(std::numeric_limits<int64_t>::max)();
right = bottom = (std::numeric_limits<T>::lowest)();
}
}

bool IsValid() const { return left != (std::numeric_limits<T>::max)(); }

T Width() const { return right - left; }
T Height() const { return bottom - top; }
void Width(T width) { right = left + width; }
Expand Down Expand Up @@ -344,10 +354,16 @@ namespace Clipper2Lib
return result;
}

static const Rect64 MaxInvalidRect64 = Rect64(
INT64_MAX, INT64_MAX, INT64_MIN, INT64_MIN);
static const RectD MaxInvalidRectD = RectD(
MAX_DBL, MAX_DBL, -MAX_DBL, -MAX_DBL);
static const Rect64 InvalidRect64 = Rect64(
(std::numeric_limits<int64_t>::max)(),
(std::numeric_limits<int64_t>::max)(),
(std::numeric_limits<int64_t>::lowest)(),
(std::numeric_limits<int64_t>::lowest)());
static const RectD InvalidRectD = RectD(
(std::numeric_limits<double>::max)(),
(std::numeric_limits<double>::max)(),
(std::numeric_limits<double>::lowest)(),
(std::numeric_limits<double>::lowest)());

template <typename T>
Rect<T> GetBounds(const Path<T>& path)
Expand Down Expand Up @@ -549,7 +565,7 @@ namespace Clipper2Lib
inline void StripDuplicates( Path<T>& path, bool is_closed_path)
{
//https://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector#:~:text=Let%27s%20compare%20three%20approaches%3A
path.erase(std::unique(path.begin(), path.end()),path.end());
path.erase(std::unique(path.begin(), path.end()), path.end());
if (is_closed_path)
while (path.size() > 1 && path.back() == path.front()) path.pop_back();
}
Expand Down
2 changes: 1 addition & 1 deletion CPP/Clipper2Lib/include/clipper2/clipper.engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <numeric>
#include <memory>

#include "clipper.core.h"
#include "clipper2/clipper.core.h"

namespace Clipper2Lib {

Expand Down
15 changes: 9 additions & 6 deletions CPP/Clipper2Lib/include/clipper2/clipper.export.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 29 October 2023 *
* Date : 1 November 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This module exports the Clipper2 Library (ie DLL/so) *
Expand Down Expand Up @@ -138,7 +138,6 @@ EXTERN_DLL_EXPORT void DisposeExportedCPolyTreeD(CPolyTreeD& p)
delete[] p;
}


// Boolean clipping:
// cliptype: None=0, Intersection=1, Union=2, Difference=3, Xor=4
// fillrule: EvenOdd=0, NonZero=1, Positive=2, Negative=3
Expand Down Expand Up @@ -226,7 +225,7 @@ static void GetPolytreeCountAndCStorageSize(const PolyTree64& tree,
template <typename T>
static T* CreateCPaths(const Paths<T>& paths)
{
size_t cnt, array_len;
size_t cnt = 0, array_len = 0;
GetPathCountAndCPathsArrayLen(paths, cnt, array_len);
T* result = new T[array_len], * v = result;
*v++ = array_len;
Expand Down Expand Up @@ -496,13 +495,15 @@ EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths,
double arc_tolerance, bool reverse_solution)
{
if (precision < -8 || precision > 8 || !paths) return nullptr;

const double scale = std::pow(10, precision);
ClipperOffset clip_offset(miter_limit, arc_tolerance, reverse_solution);
Paths64 pp = ConvertCPathsDToPaths64(paths, scale);
clip_offset.AddPaths(pp, JoinType(jointype), EndType(endtype));
Paths64 result;
clip_offset.Execute(delta * scale, result);
return CreateCPathsDFromPaths64(result, 1/scale);

return CreateCPathsDFromPaths64(result, 1 / scale);
}

EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect, const CPaths64 paths)
Expand All @@ -526,7 +527,8 @@ EXTERN_DLL_EXPORT CPathsD RectClipD(const CRectD& rect, const CPathsD paths, int
Paths64 pp = ConvertCPathsDToPaths64(paths, scale);
class RectClip64 rc(rec);
Paths64 result = rc.Execute(pp);
return CreateCPathsDFromPaths64(result, 1/scale);

return CreateCPathsDFromPaths64(result, 1 / scale);
}

EXTERN_DLL_EXPORT CPaths64 RectClipLines64(const CRect64& rect,
Expand All @@ -545,12 +547,13 @@ EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect,
{
if (CRectIsEmpty(rect) || !paths) return nullptr;
if (precision < -8 || precision > 8) return nullptr;

const double scale = std::pow(10, precision);
Rect64 r = ScaleRect<int64_t, double>(CRectToRect(rect), scale);
class RectClipLines64 rcl(r);
Paths64 pp = ConvertCPathsDToPaths64(paths, scale);
Paths64 result = rcl.Execute(pp);
return CreateCPathsDFromPaths64(result, 1/scale);
return CreateCPathsDFromPaths64(result, 1 / scale);
}

} // end Clipper2Lib namespace
Expand Down
16 changes: 8 additions & 8 deletions CPP/Clipper2Lib/include/clipper2/clipper.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 16 July 2023 *
* Date : 1 November 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This module provides a simple interface to the Clipper Library *
Expand All @@ -14,11 +14,11 @@
#include <type_traits>
#include <vector>

#include "clipper.core.h"
#include "clipper.engine.h"
#include "clipper.offset.h"
#include "clipper.minkowski.h"
#include "clipper.rectclip.h"
#include "clipper2/clipper.core.h"
#include "clipper2/clipper.engine.h"
#include "clipper2/clipper.offset.h"
#include "clipper2/clipper.minkowski.h"
#include "clipper2/clipper.rectclip.h"

namespace Clipper2Lib {

Expand Down Expand Up @@ -653,7 +653,7 @@ namespace Clipper2Lib {
}

template <typename T>
inline Path<T> SimplifyPath(const Path<T> path,
inline Path<T> SimplifyPath(const Path<T> &path,
double epsilon, bool isClosedPath = true)
{
const size_t len = path.size(), high = len -1;
Expand Down Expand Up @@ -721,7 +721,7 @@ namespace Clipper2Lib {
}

template <typename T>
inline Paths<T> SimplifyPaths(const Paths<T> paths,
inline Paths<T> SimplifyPaths(const Paths<T> &paths,
double epsilon, bool isClosedPath = true)
{
Paths<T> result;
Expand Down
4 changes: 2 additions & 2 deletions CPP/Clipper2Lib/include/clipper2/clipper.minkowski.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 28 January 2023 *
* Date : 1 November 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Minkowski Sum and Difference *
Expand All @@ -13,7 +13,7 @@
#include <cstdlib>
#include <vector>
#include <string>
#include "clipper.core.h"
#include "clipper2/clipper.core.h"

namespace Clipper2Lib
{
Expand Down
28 changes: 15 additions & 13 deletions CPP/Clipper2Lib/include/clipper2/clipper.offset.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 24 September 2023 *
* Date : 5 November 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -34,13 +34,12 @@ class ClipperOffset {
class Group {
public:
Paths64 paths_in;
Paths64 paths_out;
Path64 path;
std::vector<Rect64> bounds_list;
int lowest_path_idx = -1;
bool is_reversed = false;
JoinType join_type;
EndType end_type;
Group(const Paths64& _paths, JoinType _join_type, EndType _end_type) :
paths_in(_paths), join_type(_join_type), end_type(_end_type) {}
Group(const Paths64& _paths, JoinType _join_type, EndType _end_type);
};

int error_code_ = 0;
Expand All @@ -51,6 +50,7 @@ class ClipperOffset {
double step_sin_ = 0.0;
double step_cos_ = 0.0;
PathD norms;
Path64 path_out;
Paths64 solution;
std::vector<Group> groups_;
JoinType join_type_ = JoinType::Bevel;
Expand All @@ -66,15 +66,17 @@ class ClipperOffset {
#endif
DeltaCallback64 deltaCallback64_ = nullptr;

void DoBevel(Group& group, const Path64& path, size_t j, size_t k);
void DoSquare(Group& group, const Path64& path, size_t j, size_t k);
void DoMiter(Group& group, const Path64& path, size_t j, size_t k, double cos_a);
void DoRound(Group& group, const Path64& path, size_t j, size_t k, double angle);
size_t CalcSolutionCapacity();
bool CheckReverseOrientation();
void DoBevel(const Path64& path, size_t j, size_t k);
void DoSquare(const Path64& path, size_t j, size_t k);
void DoMiter(const Path64& path, size_t j, size_t k, double cos_a);
void DoRound(const Path64& path, size_t j, size_t k, double angle);
void BuildNormals(const Path64& path);
void OffsetPolygon(Group& group, Path64& path);
void OffsetOpenJoined(Group& group, Path64& path);
void OffsetOpenPath(Group& group, Path64& path);
void OffsetPoint(Group& group, Path64& path, size_t j, size_t k);
void OffsetPolygon(Group& group, const Path64& path);
void OffsetOpenJoined(Group& group, const Path64& path);
void OffsetOpenPath(Group& group, const Path64& path);
void OffsetPoint(Group& group, const Path64& path, size_t j, size_t k);
void DoGroupOffset(Group &group);
void ExecuteInternal(double delta);
public:
Expand Down
4 changes: 2 additions & 2 deletions CPP/Clipper2Lib/include/clipper2/clipper.rectclip.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 30 May 2023 *
* Date : 1 November 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : FAST rectangular clipping *
Expand All @@ -13,7 +13,7 @@
#include <cstdlib>
#include <vector>
#include <queue>
#include "clipper.core.h"
#include "clipper2/clipper.core.h"

namespace Clipper2Lib
{
Expand Down
5 changes: 3 additions & 2 deletions CPP/Clipper2Lib/src/clipper.engine.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 19 October 2023 *
* Date : 1 November 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This is the main polygon clipping module *
Expand All @@ -15,6 +15,7 @@
#include <algorithm>

#include "clipper2/clipper.engine.h"
#include "clipper2/clipper.h"

// https://github.com/AngusJohnson/Clipper2/discussions/334
// #discussioncomment-4248602
Expand Down Expand Up @@ -2140,7 +2141,7 @@ namespace Clipper2Lib {
horz_seg_list_.end(),
[](HorzSegment& hs) { return UpdateHorzSegment(hs); });
if (j < 2) return;
std::sort(horz_seg_list_.begin(), horz_seg_list_.end(), HorzSegSorter());
std::stable_sort(horz_seg_list_.begin(), horz_seg_list_.end(), HorzSegSorter());

HorzSegmentList::iterator hs1 = horz_seg_list_.begin(), hs2;
HorzSegmentList::iterator hs_end = hs1 +j;
Expand Down
Loading

0 comments on commit 775ec62

Please sign in to comment.