Skip to content

Commit

Permalink
Clipper.Offset: fixed a bug seen with excessive deflation (#916)
Browse files Browse the repository at this point in the history
  • Loading branch information
AngusJohnson committed Nov 22, 2024
1 parent 2b665ac commit fe5f6b7
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 68 deletions.
17 changes: 7 additions & 10 deletions CPP/Clipper2Lib/src/clipper.offset.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 24 July 2024 *
* Date : 22 November 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -326,16 +326,11 @@ void ClipperOffset::OffsetPoint(Group& group, const Path64& path, size_t j, size
// to ensure that path reversals (ie over-shrunk paths) are removed.
#ifdef USINGZ
path_out.push_back(Point64(GetPerpendic(path[j], norms[k], group_delta_), path[j].z));
#else
path_out.push_back(GetPerpendic(path[j], norms[k], group_delta_));
#endif

// when the angle is almost flat (cos_a ~= 1), it's safe to skip this middle point
if (cos_a < 0.999) path_out.push_back(path[j]); // (#405, #873)

#ifdef USINGZ
path_out.push_back(path[j]); // (#405, #873, #916)
path_out.push_back(Point64(GetPerpendic(path[j], norms[j], group_delta_), path[j].z));
#else
path_out.push_back(GetPerpendic(path[j], norms[k], group_delta_));
path_out.push_back(path[j]); // (#405, #873, #916)
path_out.push_back(GetPerpendic(path[j], norms[j], group_delta_));
#endif
}
Expand Down Expand Up @@ -594,7 +589,8 @@ void ClipperOffset::ExecuteInternal(double delta)

if (!solution->size()) return;

bool paths_reversed = CheckReverseOrientation();
bool paths_reversed = CheckReverseOrientation();

//clean up self-intersections ...
Clipper64 c;
c.PreserveCollinear(false);
Expand All @@ -621,6 +617,7 @@ void ClipperOffset::ExecuteInternal(double delta)
else
c.Execute(ClipType::Union, FillRule::Positive, *solution);
}

}

void ClipperOffset::Execute(double delta, Paths64& paths)
Expand Down
7 changes: 2 additions & 5 deletions CSharp/Clipper2Lib/Clipper.Offset.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 24 July 2024 *
* Date : 22 November 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -551,10 +551,7 @@ private void OffsetPoint(Group group, Path64 path, int j, ref int k)
// will be removed later by the finishing union operation. This is also the best way
// to ensure that path reversals (ie over-shrunk paths) are removed.
pathOut.Add(GetPerpendic(path[j], _normals[k]));

// when the angle is almost flat (cos_a ~= 1), it's safe to skip this middle point
if (cosA < 0.999) pathOut.Add(path[j]); // (#405, #873)

pathOut.Add(path[j]); // (#405, #873, #916)
pathOut.Add(GetPerpendic(path[j], _normals[j]));
}
else if ((cosA > 0.999) && (_joinType != JoinType.Round))
Expand Down
38 changes: 27 additions & 11 deletions Delphi/Clipper2Lib/Clipper.Core.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

(*******************************************************************************
* Author : Angus Johnson *
* Date : 17 September 2024 *
* Date : 22 November 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : Core Clipper Library module *
Expand All @@ -18,20 +18,23 @@ interface
SysUtils, Classes, Math;

type
{$IFDEF USINGZ}
ZType = Int64; // or alternatively, ZType = double
{$ENDIF}

PPoint64 = ^TPoint64;
TPoint64 = record
X, Y: Int64;
{$IFDEF USINGZ}
Z: Int64;
Z: ZType;
{$ENDIF}
end;

PPointD = ^TPointD;
TPointD = record
X, Y: double;
{$IFDEF USINGZ}
Z: Int64;
Z: ZType;
{$ENDIF}
end;

Expand Down Expand Up @@ -121,6 +124,7 @@ TListEx = class
fCount : integer;
fCapacity : integer;
fList : TPointerList;
fSorted : Boolean;
protected
function UnsafeGet(idx: integer): Pointer; // no range checking
procedure UnsafeSet(idx: integer; val: Pointer);
Expand All @@ -130,10 +134,12 @@ TListEx = class
destructor Destroy; override;
procedure Clear; virtual;
function Add(item: Pointer): integer;
procedure DeleteLast;
procedure Swap(idx1, idx2: integer);
procedure Sort(Compare: TListSortCompare);
procedure Sort(Compare: TListSortCompareFunc);
procedure Resize(count: integer);
property Count: integer read fCount;
property Sorted: Boolean read fSorted;
property Item[idx: integer]: Pointer read UnsafeGet; default;
end;

Expand Down Expand Up @@ -186,11 +192,11 @@ function PointsNearEqual(const pt1, pt2: TPointD; distanceSqrd: double): Boolean
{$IFDEF INLINING} inline; {$ENDIF}

{$IFDEF USINGZ}
function Point64(const X, Y: Int64; Z: Int64 = 0): TPoint64; overload;
function Point64(const X, Y: Int64; Z: ZType = 0): TPoint64; overload;
{$IFDEF INLINING} inline; {$ENDIF}
function Point64(const X, Y: Double; Z: Int64 = 0): TPoint64; overload;
function Point64(const X, Y: Double; Z: ZType = 0): TPoint64; overload;
{$IFDEF INLINING} inline; {$ENDIF}
function PointD(const X, Y: Double; Z: Int64 = 0): TPointD; overload;
function PointD(const X, Y: Double; Z: ZType = 0): TPointD; overload;
{$IFDEF INLINING} inline; {$ENDIF}
{$ELSE}
function Point64(const X, Y: Int64): TPoint64; overload; {$IFDEF INLINING} inline; {$ENDIF}
Expand Down Expand Up @@ -540,6 +546,7 @@ procedure TListEx.Clear;
fList := nil;
fCount := 0;
fCapacity := 0;
fSorted := false;
end;
//------------------------------------------------------------------------------

Expand All @@ -555,6 +562,13 @@ function TListEx.Add(item: Pointer): integer;
fList[fCount] := item;
Result := fCount;
inc(fCount);
fSorted := false;
end;
//------------------------------------------------------------------------------

procedure TListEx.DeleteLast;
begin
dec(fCount);
end;
//------------------------------------------------------------------------------

Expand Down Expand Up @@ -611,10 +625,11 @@ procedure QuickSort(SortList: TPointerList; L, R: Integer;
end;
//------------------------------------------------------------------------------

procedure TListEx.Sort(Compare: TListSortCompare);
procedure TListEx.Sort(Compare: TListSortCompareFunc);
begin
if fCount < 2 then Exit;
QuickSort(FList, 0, fCount - 1, Compare);
fSorted := true;
end;
//------------------------------------------------------------------------------

Expand Down Expand Up @@ -654,6 +669,7 @@ procedure TListEx.Swap(idx1, idx2: integer);
p := fList[idx1];
fList[idx1] := fList[idx2];
fList[idx2] := p;
fSorted := false;
end;

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -1383,23 +1399,23 @@ function ArrayOfPathsToPaths(const ap: TArrayOfPaths): TPaths64;
//------------------------------------------------------------------------------

{$IFDEF USINGZ}
function Point64(const X, Y: Int64; Z: Int64): TPoint64;
function Point64(const X, Y: Int64; Z: ZType): TPoint64;
begin
Result.X := X;
Result.Y := Y;
Result.Z := Z;
end;
//------------------------------------------------------------------------------

function Point64(const X, Y: Double; Z: Int64): TPoint64;
function Point64(const X, Y: Double; Z: ZType): TPoint64;
begin
Result.X := Round(X);
Result.Y := Round(Y);
Result.Z := Z;
end;
//------------------------------------------------------------------------------

function PointD(const X, Y: Double; Z: Int64): TPointD;
function PointD(const X, Y: Double; Z: ZType): TPointD;
begin
Result.X := X;
Result.Y := Y;
Expand Down
Loading

0 comments on commit fe5f6b7

Please sign in to comment.