Closed GeneralGDA closed 5 months ago
Another example, where RectClipLines introduces unexpected point in the end of clipped geometry:
using Clipper2Lib;
var rect = new Rect64(l: 0, t: 0, r: 19000, b: 27700);
var polyline = new Path64
(
[
new (0, 14487),
new (1141, 14336),
new (2214, 14128),
new (3222, 13866),
new (4165, 13551),
new (5045, 13186),
new (5863, 12773),
new (6620, 12312),
new (7317, 11808),
new (7956, 11260),
new (8538, 10673),
new (9064, 10046),
new (9535, 9383),
new (9953, 8686),
new (10319, 7955),
new (10633, 7195),
new (10898, 6405),
new (11114, 5589),
new (11283, 4748),
new (11406, 3885),
new (11483, 3001),
new (81483, 3001),
new (80745, 10098),
new (79389, 16959),
new (77458, 23571),
new (74998, 29919),
new (72053, 35990),
new (68668, 41771),
new (64887, 47247),
new (60755, 52405),
new (56316, 57231),
new (51615, 61711),
new (46697, 65832),
new (41606, 69580),
new (36387, 72941),
new (31083, 75902),
new (25741, 78448),
new (20404, 80567),
new (15117, 82244),
new (9924, 83465),
new (4870, 84217),
new (0, 84487),
new (0, 14487),
]
);
var clipped = Clipper.RectClipLines(rect, polyline);
foreach (var part in clipped)
{
Console.Out.Write("[");
Console.Out.Write(string.Join(';', part));
Console.Out.WriteLine("]");
}
"Unlike closed path clipping, there's not always an obvious or "right way" to clip open path segments when they overlap clipping boundaries. In Clipper2, sometimes these segments will be included in clipping solutions, and sometimes not. When the adjacent (ie preceding and succeeding) segments are both inside or both outside the clipping region, then overlapping segments will be included or excluded respectively. However, for segments overlapping clipping boundaries with one adjacent segment inside and the other outside, their inclusion or otherwise in solutions remains undefined."
@AngusJohnson, did you see the example with self-clipping? Comment from documentation does not explain why the output contains contour twice. Or you state that any non-closed path overlapping boundary clipping result is undefined?
@AngusJohnson, also, take a look at the big example in the comment. The result of RectClipLines is strange even with your explanation from documentation: Clipper2 does not output two paths (one with zero length). It generates single path that is not a subpath by any means of the input path.
Comment from documentation does not explain why the output contains contour twice
Sorry, I tested this in C++, and the output was as expected. However, I agree there is a problem in the C# code (though I don't see the contour being drawn twice).
C++:
void Test()
{
Rect64 rec(0, 0, 19000, 27700);
Path64 line = MakePath({ 0, 14487, 1141, 14336, 2214, 14128, 3222, 13866, 4165, 13551, 5045,
13186, 5863, 12773, 6620, 12312, 7317, 11808, 7956, 11260, 8538, 10673, 9064, 10046, 9535,
9383, 9953, 8686, 10319, 7955, 10633, 7195, 10898, 6405, 11114, 5589, 11283, 4748, 11406,
3885, 11483, 3001, 81483, 3001, 80745, 10098, 79389, 16959, 77458, 23571, 74998, 29919, 72053,
35990, 68668, 41771, 64887, 47247, 60755, 52405, 56316, 57231, 51615, 61711, 46697, 65832, 41606,
69580, 36387, 72941, 31083, 75902, 25741, 78448, 20404, 80567, 15117, 82244, 9924, 83465, 4870,
84217, 0, 84487, 0, 14487 });
Paths64 solution = RectClipLines(rec, line);
std::cout << solution;
Paths64 subject;
subject.push_back(line);
SvgWriter svg;
SvgAddOpenSubject(svg, subject, FillRule::NonZero);
SvgAddClip(svg, Paths64({ rec.AsPath() }), FillRule::NonZero);
SvgAddOpenSolution(svg, solution, FillRule::NonZero, false);
std::string filename = "test_cpp.svg";
SvgSaveToFile(svg, filename, 400, 400, 10);
System(filename);
}
Solution: 0,14487, 1141,14336, 2214,14128, 3222,13866, 4165,13551, 5045,13186, 5863,12773, 6620,12312, 7317,11808, 7956,11260, 8538,10673, 9064,10046, 9535,9383, 9953,8686, 10319,7955, 10633,7195, 10898,6405, 11114,5589, 11283,4748, 11406,3885, 11483,3001, 19000,3001
C#:
public static void Test()
{
string filename = @"..\..\..\test.svg";
Paths64 subject = new();
subject.Add(Clipper.MakePath(new int[] {
0, 14487, 1141, 14336, 2214, 14128, 3222, 13866, 4165, 13551, 5045,
13186, 5863, 12773, 6620, 12312, 7317, 11808, 7956, 11260, 8538, 10673, 9064, 10046, 9535,
9383, 9953, 8686, 10319, 7955, 10633, 7195, 10898, 6405, 11114, 5589, 11283, 4748, 11406,
3885, 11483, 3001, 81483, 3001, 80745, 10098, 79389, 16959, 77458, 23571, 74998, 29919, 72053,
35990, 68668, 41771, 64887, 47247, 60755, 52405, 56316, 57231, 51615, 61711, 46697, 65832, 41606,
69580, 36387, 72941, 31083, 75902, 25741, 78448, 20404, 80567, 15117, 82244, 9924, 83465, 4870,
84217, 0, 84487, 0, 14487 }));
Rect64 rec = new(0, 0, 19000, 27700);
Paths64 solution = Clipper.RectClipLines(rec, subject);
Console.WriteLine(solution.ToString());
SvgWriter svg = new SvgWriter();
SvgUtils.AddOpenSubject(svg, subject);
SvgUtils.AddClip(svg, rec.AsPath());
SvgUtils.AddOpenSolution(svg, solution, false);
SvgUtils.SaveToFile(svg, filename, FillRule.NonZero, 400, 400, 10);
ClipperFileIO.OpenFileWithDefaultApp(filename);
}
Solution: 0,14487 1141,14336 2214,14128 3222,13866 4165,13551 5045,13186 5863,12773 6620,12312 7317,11808 7956,11260 8538,10673 9064,10046 9535,9383 9953,8686 10319,7955 10633,7195 10898,6405 11114,5589 11283,4748 11406,3885 11483,3001 19000,3001 0,27700
@AngusJohnson, thanks for investigating the problem. "The contour being drawn twice" — I was talking about trivial example of self-clipping (the very first code snippet).
"The contour being drawn twice" — I was talking about trivial example of self-clipping (the very first code snippet).
OK, another oddity just in the C# code.
Hopefully fixed now 🤞.
Consider the trivial test of self clipping:
The output seems somewhat unusual: [0,0 ;0,27700 ;19000,27700 ;19000,0 ;0,27700 ;19000,27700 ] I would expect either an empty output if Clipper considers the rectangle as an open set, or the entire input if Clipper treats the rectangle as a closed set. By the way, I couldn't find in the documentation how Clipper treats the boundary of a rectangle.
The test above indicates that Clipper attempts to treat the rectangle as a closed set. This contradicts the following test, where the polyline's end segment is completely clipped: