Clipper. How to cut a polygon using an open polygon?

line_clipping2.png

The example with ovals uses only closed paths. But how do I get the result like in the picture? Particularly interested in intersection. Do I understand correctly that with open paths I need to use PolyTree? I did not find any such example.

Hi, pahuchiy.

Yes, in reviewing the docs it does sound like a poly-tree is what you want, assuming you need to know the open- or closed-ness of the paths. And I have indeed neglected such an example.  :frowning:

Roughly, it might go something like:

local clipper = require("plugin.clipper") local my\_clipper = clipper.NewClipper() local tree = clipper.NewPolyTree() -- populate and add to paths to my\_clipper my\_clipper:Execute("Intersection", { out = tree }) local open = clipper.OpenPathsFromPolyTree(tree) local closed = clipper.ClosedPathsFromPolyTree(tree)

I’ll try to add such an example, though I can’t say how soon. Looks like the docs need a few minor fixes too.

thanks but not working

local clipper = require("plugin.clipper") local my\_clipper = clipper.NewClipper() local tree = clipper.NewPolyTree() print("this text does not appear in the console") local path1={100,100, 300,100, 300,200, 100, 200} local path2={140, 70, 220, 320} local UD1 = clipper.NewPath() for i = 1, #path1,2 do UD1:AddPoint(path1[i], path1[i+1]) end local subj = clipper.NewPathArray() subj:AddPath(UD1 ) local UD2 = clipper.NewPath() for i = 1, #path2,2 do UD2:AddPoint(path2[i], path2[i+1]) end local clip = clipper.NewPathArray() clip:AddPath(UD2 ) my\_clipper:AddPaths(subj, "SubjectClosed") my\_clipper:AddPaths(clip, "Clip") my\_clipper:Execute("Intersection", { out = tree }) local open = clipper.OpenPathsFromPolyTree(tree) local closed = clipper.ClosedPathsFromPolyTree(tree)

I’ve not seen or used Clipper before (will check it out) but just in case this helps, take a look at my slicer:

https://github.com/HoraceBury/slicer

There is an interactive build, too.

@ pahuchiy If that line of text isn’t appearing, the function is probably failing somehow. (Rule #1: the one thing you forget to try will fail publicly  :)) I’ll have to take a look.

@ horacebury Very cool. I only skimmed the source a bit. What sort of process are you following?

I’m not. Essentially, it works out the intersections and copies the list of points from the original into two new tables. The hard part is making sure the intersected lines don’t generate duplicates.

I finally had a chance to dig into this yesterday and I believe now have it working. I basically have a rough approximation of the polyline / polygon case at the bottom of this page, cycling between the clip types, and agreeing with the results shown there.

There were indeed some issues.  :stuck_out_tongue:

I might see about adapting this into another sample too.

I should be able to do all the non-Windows builds in the next day or so and then upload all the binaries at once, including the whole gamut for Android.

Minor breaking change: in that clip type link, I read some of those rules about open / closed paths a bit clumsily and just assumed only closed clip paths made sense. I’ve now broken them up into “Clip” and “ClipClosed”, following the style used by subject paths. For this reason I’ll probably wait until the new uploads go live before updating the samples.

Please complete the remaining clipper functions. Especially with open paths  :frowning:

I did update the binaries after my last post. Are you still seeing errors?

local clipper = require("plugin.clipper") local my\_clipper = clipper.NewClipper() local tree = clipper.NewPolyTree() print("this text does not appear in the console") local path1={100,100, 300,100, 300,200, 100, 200} local path2={140, 70, 220, 320} local UD1 = clipper.NewPath() for i = 1, #path1,2 do UD1:AddPoint(path1[i], path1[i+1]) end local subj = clipper.NewPathArray() subj:AddPath(UD1 ) local UD2 = clipper.NewPath() for i = 1, #path2,2 do UD2:AddPoint(path2[i], path2[i+1]) end local clip = clipper.NewPathArray() clip:AddPath(UD2 ) my\_clipper:AddPaths(subj, "SubjectClosed") my\_clipper:AddPaths(clip, "Clip") my\_clipper:Execute("Intersection", { out = tree }) local open = clipper.OpenPathsFromPolyTree(tree) local closed = clipper.ClosedPathsFromPolyTree(tree)

my code still doesn’t work. Please correct my code. I want to get 2 parts of a polygon cut by a line

Wow! There is a LUA version of clipper? Thats awesome!

Ive actually been trying to solve polygon union for polygons that are next to each other - you know - two polygons that have one or more common vertexes. But I have not been able to solve how to merge these two polygons. In my scenario there are always two polygons that do not intersect or overlap other than sharing a few common vertexes on their hulls. One polygon is always convex and other is always concave.

. If anyone has any suggestions, I would appreciate.

@ pahuchiy  I’ll try to give it some attention soon.

@ pixec  If it makes sense, you could try a mesh, which would let you have either separate regions or shared vertices via indexing. I’ve also bound libtess2 (used in many of the Clipper samples, too), which might let you merge in these cases.

Meshes sound like an interesting approach and that libtess2 by StarCrunch is quite spectacular.

@ pixec , if you are working with shapes like that, you should be able to get by with simply comparing the edges of the two polygons and determining where they intersect. Then you’d use these intersect points as the merging points for the two polygons. This kind of approach would only work with simple polygons though.

@ pahuchiy I’ve gotten a chance to revisit some plugins today.

I believe it was just some trouble with the set that was receiving the paths. Here’s a revised and expanded version of the above:

local clipper = require("plugin.clipper") local my\_clipper = clipper.NewClipper() local tree = clipper.NewPolyTree() print("this text does not appear in the console") local path1={100,100, 300,100, 300,200, 100, 200} local path2={140, 70, 220, 320} local path3={200,150, 400,150, 400,225, 200, 225} local l1 = display.newLine(unpack(path1)) local l2 = display.newLine(unpack(path2)) local l3 = display.newLine(unpack(path3)) l1.strokeWidth = 3 l2.strokeWidth = 3 l3.strokeWidth = 3 l1:setStrokeColor(1, 0, 0) l2:setStrokeColor(0, 0, 1) l3:setStrokeColor(1, 0, 1) l1:append(100, 100) l3:append(200, 150) local UD1 = clipper.NewPath() for i = 1, #path1,2 do UD1:AddPoint(path1[i], path1[i+1]) end local subj = clipper.NewPathArray() subj:AddPath(UD1 ) local UD2 = clipper.NewPath() for i = 1, #path2,2 do UD2:AddPoint(path2[i], path2[i+1]) end local UD3 = clipper.NewPath() for i = 1, #path3,2 do UD3:AddPoint(path3[i], path3[i+1]) end local clip = clipper.NewPathArray() clip:AddPath(UD2 ) my\_clipper:AddPaths(subj, "ClipClosed")--"SubjectClosed") my\_clipper:AddPaths(clip, "Subject")--"Clip") my\_clipper:AddPath(UD3, "SubjectClosed") my\_clipper:Execute("Intersection", { out = tree }) local open = clipper.OpenPathsFromPolyTree(tree) local closed = clipper.ClosedPathsFromPolyTree(tree) print("O",open) print("C",closed) for \_, set in ipairs{open, closed} do for i = 1, #set do local out, path = {}, set:GetPath(i) for j = 1, #path do local x, y = path:GetPoint(j) out[#out + 1] = x out[#out + 1] = y end if set == closed then local x, y = path:GetPoint(1) out[#out + 1] = x out[#out + 1] = y end local l4 = display.newLine(unpack(out)) l4.strokeWidth = 3 l4:setStrokeColor(0, 1, 0) end end