|
2 | 2 |
|
3 | 3 | (******************************************************************************* |
4 | 4 | * Author : Angus Johnson * |
5 | | -* Date : 22 November 2024 * |
6 | | -* Website : http://www.angusj.com * |
7 | | -* Copyright : Angus Johnson 2010-2024 * |
| 5 | +* Date : 22 January 2025 * |
| 6 | +* Website : https://www.angusj.com * |
| 7 | +* Copyright : Angus Johnson 2010-2025 * |
8 | 8 | * Purpose : Path Offset (Inflate/Shrink) * |
9 | | -* License : http://www.boost.org/LICENSE_1_0.txt * |
| 9 | +* License : https://www.boost.org/LICENSE_1_0.txt * |
10 | 10 | *******************************************************************************) |
11 | 11 |
|
12 | 12 | {$I Clipper.inc} |
@@ -142,6 +142,20 @@ implementation |
142 | 142 | TwoPi : Double = 2 * PI; |
143 | 143 | InvTwoPi : Double = 1/(2 * PI); |
144 | 144 |
|
| 145 | +// Clipper2 approximates arcs by using series of relatively short straight |
| 146 | +//line segments. And logically, shorter line segments will produce better arc |
| 147 | +// approximations. But very short segments can degrade performance, usually |
| 148 | +// with little or no discernable improvement in curve quality. Very short |
| 149 | +// segments can even detract from curve quality, due to the effects of integer |
| 150 | +// rounding. Since there isn't an optimal number of line segments for any given |
| 151 | +// arc radius (that perfectly balances curve approximation with performance), |
| 152 | +// arc tolerance is user defined. Nevertheless, when the user doesn't define |
| 153 | +// an arc tolerance (ie leaves alone the 0 default value), the calculated |
| 154 | +// default arc tolerance (offset_radius / 500) generally produces good (smooth) |
| 155 | +// arc approximations without producing excessively small segment lengths. |
| 156 | +// See also: https://www.angusj.com/clipper2/Docs/Trigonometry.htm |
| 157 | +const arc_const = 0.002; // <-- 1/500 |
| 158 | + |
145 | 159 | //------------------------------------------------------------------------------ |
146 | 160 | // Miscellaneous offset support functions |
147 | 161 | //------------------------------------------------------------------------------ |
@@ -364,13 +378,12 @@ procedure TClipperOffset.DoGroupOffset(group: TGroup); |
364 | 378 | if (group.joinType = jtRound) or (group.endType = etRound) then |
365 | 379 | begin |
366 | 380 | // calculate the number of steps required to approximate a circle |
367 | | - // (see http://www.angusj.com/clipper2/Docs/Trigonometry.htm) |
| 381 | + // (see https://www.angusj.com/clipper2/Docs/Trigonometry.htm) |
368 | 382 | // arcTol - when arc_tolerance_ is undefined (0) then curve imprecision |
369 | 383 | // will be relative to the size of the offset (delta). Obviously very |
370 | 384 | //large offsets will almost always require much less precision. |
371 | | - arcTol := Iif(fArcTolerance > 0.01, |
372 | | - Min(absDelta, fArcTolerance), |
373 | | - Log10(2 + absDelta) * 0.25); // empirically derived |
| 385 | + arcTol := Iif(fArcTolerance > 0.0, |
| 386 | + Min(absDelta, fArcTolerance), absDelta * arc_const); |
374 | 387 |
|
375 | 388 | stepsPer360 := Pi / ArcCos(1 - arcTol / absDelta); |
376 | 389 | if (stepsPer360 > absDelta * Pi) then |
@@ -745,7 +758,7 @@ function IntersectPoint(const ln1a, ln1b, ln2a, ln2b: TPointD): TPointD; |
745 | 758 | m1,b1,m2,b2: double; |
746 | 759 | begin |
747 | 760 | result := NullPointD; |
748 | | - //see http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/ |
| 761 | + //see https://paulbourke.net/geometry/pointlineplane/#i2l |
749 | 762 | if (ln1B.X = ln1A.X) then |
750 | 763 | begin |
751 | 764 | if (ln2B.X = ln2A.X) then exit; //parallel lines |
@@ -917,10 +930,8 @@ procedure TClipperOffset.DoRound(j, k: Integer; angle: double); |
917 | 930 | // when fDeltaCallback64 is assigned, fGroupDelta won't be constant, |
918 | 931 | // so we'll need to do the following calculations for *every* vertex. |
919 | 932 | absDelta := Abs(fGroupDelta); |
920 | | - arcTol := Iif(fArcTolerance > 0.01, |
921 | | - Min(absDelta, fArcTolerance), |
922 | | - Log10(2 + absDelta) * 0.25); // empirically derived |
923 | | - //http://www.angusj.com/clipper2/Docs/Trigonometry.htm |
| 933 | + arcTol := Iif(fArcTolerance > 0.0, |
| 934 | + Min(absDelta, fArcTolerance), absDelta * arc_const); |
924 | 935 | stepsPer360 := Pi / ArcCos(1 - arcTol / absDelta); |
925 | 936 | if (stepsPer360 > absDelta * Pi) then |
926 | 937 | stepsPer360 := absDelta * Pi; // avoid excessive precision |
|
0 commit comments