Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat
clipper - Gideros Forum

clipper

I tried to understand the clipper plugin and this is what I have got:
require "clipper"
local subject = Polygon.new()
subject:addPoint(0, 0)
subject:addPoint(16, 16)
subject:addPoint(16, 32)
subject:addPoint(0, 32)
subject:addPoint(-16, 16)
subject:addPoint(0, 0)
 
local clipper = Polygon.new()
clipper:addPoint(0, 0)
clipper:addPoint(32, 32)
clipper:addPoint(32, 64)
clipper:addPoint(0, 64)
clipper:addPoint(-32, 32)
clipper:addPoint(0, 0)
 
local myclipper = Clipper.new()
myclipper:addSubjectPolygon(subject, Polygon.FILL_EVEN_ODD, true)
myclipper:addClipPolygon(clipper, Polygon.FILL_EVEN_ODD, true)
local myc = myclipper:getDifference(subject, clipper)
local myi = myclipper:getIntersection(subject, clipper)
local x, y, w, h = myclipper:getBounds(subject, clipper)
print(x) -- ok
 
--local solution = Polygon.new() -- ???
--stage:addChild(myclipper) -- not ok
And I am stuck, I don't know how to retrieve the getDifference value and draw the solution polygon.
Tagged:

Comments

  • i've found a different lua binding:
    https://luapower.com/clipper
    it seems it has a different api from the current gideros clipper.
    perhaps this could replace the current one in gideros?

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
  • keszeghkeszegh Member
    edited September 13 Accepted Answer
    for the current one this could help: https://github.com/gideros/giderosplugins/blob/master/Clipper/apireference.html

    i did not test it, but according to the docs i think something like this would be better:
    myclipper:addSubjectPolygon(subject)
    myclipper:addClipPolygon(clipper)
    local myc = myclipper:getDifference(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)

    and then myc is still just an abstract polygon object, not a sprite, so first from reading its vertices (by using myc:getPoints() ) you need to build a sprite using path2d for example. and then that can be added to the stage.

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
  • MoKaLuxMoKaLux Member
    edited September 13
    @keszegh yes that looks very similar to what we have in gideros. I don't think I am going to need it soon but I was just curious about how to use it a simple example would be nice for the wiki.

    Thank you for your insights I am going to try what you suggested.
  • keszegh said:

    for the current one this could help: https://github.com/gideros/giderosplugins/blob/master/Clipper/apireference.html
    and then myc is still just an abstract polygon object, not a sprite, so first from reading its vertices (by using myc:getPoints() ) you need to build a sprite using path2d for example. and then that can be added to the stage.

    (by using myc:getPoints() ) This function does not exist. I think the points are hold in the table:
    local myc = myclipper:getDifference(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)

    But I cannot retrieve anything from this table!
  • well, that's a problem, according to the reference, it should.
    in zerobrane studio you can watch tables with all the subvalues and then it's easier to see what and how is stored in the myc object.
  • yes I have tried with this function (I don't use zerobrane).
    function tprint (tbl, indent)
      if not indent then indent = 0 end
      local toprint = string.rep(" ", indent) .. "{\r\n"
      indent = indent + 2 
      for k, v in pairs(tbl) do
        toprint = toprint .. string.rep(" ", indent)
        if (type(k) == "number") then
          toprint = toprint .. "[" .. k .. "] = "
        elseif (type(k) == "string") then
          toprint = toprint  .. k ..  "= "   
        end
        if (type(v) == "number") then
          toprint = toprint .. v .. ",\r\n"
        elseif (type(v) == "string") then
          toprint = toprint .. "\"" .. v .. "\",\r\n"
        elseif (type(v) == "table") then
          toprint = toprint .. tprint(v, indent + 2) .. ",\r\n"
        else
          toprint = toprint .. "\"" .. tostring(v) .. "\",\r\n"
        end
      end
      toprint = toprint .. string.rep(" ", indent-2) .. "}"
      return toprint
    end
    But the result is something like that:

    print(tprint(myi))
    {
      [1] =     {
          __userdata= "userdata: 015DAB18",
        },
    }
    And that's chinese for me.
  • MoKaLuxMoKaLux Member
    edited September 14
    no worries though.

    My last attempt:
    require "clipper"
    local subject = Polygon.new(Polygon.FILL_EVEN_ODD)
    subject:addPoint(0, 0)
    subject:addPoint(16, 16)
    subject:addPoint(16, 32)
    subject:addPoint(0, 32)
    subject:addPoint(-16, 16)
    subject:addPoint(-32, 96)
    subject:addPoint(0, 0)
     
    local clipper = Polygon.new(Polygon.FILL_EVEN_ODD)
    clipper:addPoint(0, 0)
    clipper:addPoint(32, 32)
    clipper:addPoint(32, 64)
    clipper:addPoint(0, 64)
    clipper:addPoint(-32, 32)
    clipper:addPoint(-48, 64)
    clipper:addPoint(0, 0)
     
    local psubject = subject:getPoints()
    local pclipper = clipper:getPoints()
    local mypixel
    for k, v in ipairs(psubject) do
    	mypixel = Pixel.new(0xff0000, 0.25, 8, 8)
    	mypixel:setPosition(v[1] + 128, v[2] + 128)
    	stage:addChild(mypixel)
    end
    for k, v in ipairs(pclipper) do
    	mypixel = Pixel.new(0x000000, 0.25, 8, 8)
    	mypixel:setPosition(v[1] + 128, v[2] + 128)
    	stage:addChild(mypixel)
    end
     
    local myclipper = Clipper.new()
    myclipper:addSubjectPolygon(subject)
    myclipper:addClipPolygon(clipper)
    myclipper:getDifference(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)
    local x, y, w, h = myclipper:getBounds(subject, clipper)
    mypixel = Pixel.new(0x0000ff, 0.1, w, h)
    mypixel:setPosition(x + 128, y + 128)
    stage:addChild(mypixel)
     
    local solution = Polygon.new()
     
    --stage:addChild(myclipper) -- not ok
    I feel I am almost there but the final solution polygon is missing!

    image.png
    243 x 283 - 1K
  • I found this example:

    Polygon clipping example
    local clipper = require 'clipper'
     
    local p1 = clipper.Path()
    p1:add(100,100)
    p1:add(150,100)
    p1:add(150,150)
    p1:add(100,150)
     
    local p2 = clipper.Path()
    p2:add(100,120)
    p2:add(150,120)
    p2:add(150,130)
    p2:add(100,130)
     
    local cl = clipper.Clipper()
    cl:addPath(p1,'subject')
    cl:addPath(p2,'clip')
    local out = cl:execute('difference')
    But I don't see the execute in the gideros clipper implementation! Almost there?!

    Likes: Apollo14

    +1 -1 (+1 / -0 ) Share on Facebook
  • hgy29hgy29 Maintainer
    Accepted Answer
    @MoKaLux, reading the c++ code it looks like the result of getDifference/getIntersection and others is a list of Polygon objects, so you should iterate over your ‘myc’ and call getPoints() for each entry.

    Likes: keszegh, MoKaLux

    +1 -1 (+2 / -0 ) Share on Facebook
  • keszeghkeszegh Member
    edited September 14 Accepted Answer
    so following @hgy29 's remark the following code gives me (in zbs) the following result:
    require "clipper"
    local subject = Polygon.new()
    subject:addPoint(0, 0)
    subject:addPoint(16, 16)
    subject:addPoint(16, 32)
    subject:addPoint(0, 32)
    subject:addPoint(-16, 16)
    --subject:addPoint(0, 0)
     
    local clipper = Polygon.new()
    clipper:addPoint(0, 0)
    clipper:addPoint(32, 32)
    clipper:addPoint(32, 64)
    clipper:addPoint(0, 64)
    clipper:addPoint(-32, 32)
    --clipper:addPoint(0, 0)
     
    local myclipper = Clipper.new()
    myclipper:addSubjectPolygon(subject)
    myclipper:addClipPolygon(clipper)
    local myc = myclipper:getUnion(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)
    --iterate over all polygons in the union:
    for key,value in pairs(myc) do 	 
        print(key)
        print(value:getPoints())
    end
    result:
    1
    {{0, 0}, {32, 32}, {32, 64}, {0, 64}, {-32, 32}}
    that is, indeed myc consists of tables storing polygons, which can be read using getPoints.

    note that i used getUnion in my example to make sure that the result is not empty!

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
  • keszeghkeszegh Member
    Accepted Answer
    also i think in your example the last "subject:addPoint(0, 0)" for each polygon is probably not necessary as it anyway closes the polygon.
    and if you want difference then better exchange clipper and subject as otherwise you get an empty difference (as the bigger contains the smaller one). that's why i used union in my example to avoid this.

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
  • keszeghkeszegh Member
    edited September 14 Accepted Answer
    e.g. when you exchange clipper and subject and generate difference:
    myclipper:addSubjectPolygon(clipper)
    myclipper:addClipPolygon(subject)
    local myc = myclipper:getDifference(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)
    you correctly get:
    1
    {{0, 32}, {16, 32}, {16, 16}, {32, 32}, {32, 64}, {0, 64}, {-32, 32}, {-16, 16}}

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
  • thank you guys, I am going to follow your example, make some nice code and add it to the wiki. I was so curious about this clipper thing. You are the best! Viva gideros.

    Likes: keszegh

    +1 -1 (+1 / -0 ) Share on Facebook
  • ok I had it working but what a mess!
    require "clipper"
    function createPolygon(xpoints, xcolor)
    	local myshape = Shape.new()
    	myshape:setFillStyle(Shape.SOLID, xcolor or 0xff0000, 1)
    	myshape:beginPath()
    	myshape:moveTo(xpoints:getPoints()[1][1], xpoints:getPoints()[1][2])
    	--print(#xpoints:getPoints())
    	for p = 2, #xpoints:getPoints() do
    		myshape:lineTo(xpoints:getPoints()[p][1], xpoints:getPoints()[p][2])
    	end
    	myshape:endPath()
    	myshape:setPosition(128, 128)
    	stage:addChild(myshape)
    end
     
    local subject = Polygon.new()
    subject:addPoint(-32, -32)
    subject:addPoint(32, -32)
    subject:addPoint(32, 32)
    subject:addPoint(-32, 32)
     
    local clip = Polygon.new()
    clip:addPoint(-16, -16)
    clip:addPoint(0, 0)
    clip:addPoint(16, -16)
    clip:addPoint(16, 16)
    clip:addPoint(-16, 16)
     
    --print(clip:getPoints()[3][2])
    createPolygon(subject)
    createPolygon(clip, 0x00ff00)
     
    function createShape(xtable)
    	local myshape = Shape.new()
    	myshape:setFillStyle(Shape.SOLID, 0x0000ff, 1)
    	myshape:beginPath()
    	myshape:moveTo(xtable.x[1], xtable.y[1])
    	for c = 2, #xtable.x do
    		myshape:lineTo(xtable.x[c], xtable.y[c])
    	end
    	myshape:endPath()
    	myshape:setPosition(128, 128)
    	stage:addChild(myshape)
    end
     
    local myclipper = Clipper.new()
    local mysolution = {}
    mysolution.x = {}
    mysolution.y = {}
     
    myclipper:addSubjectPolygon(subject)
    myclipper:addClipPolygon(clip)
    --local myc = myclipper:getUnion(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)
    --local myc = myclipper:getDifference(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)
    --local myc = myclipper:getIntersection(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)
    --local myc = myclipper:getIntersection(Polygon.FILL_NON_ZERO, Polygon.FILL_NON_ZERO)
    local myc = myclipper:getIntersection(Polygon.FILL_POSITIVE, Polygon.FILL_POSITIVE)
    --local myc = myclipper:getIntersection(Polygon.FILL_NEGATIVE, Polygon.FILL_NEGATIVE)
    --local myc = myclipper:getIntersection(Polygon.FILL_POSITIVE, Polygon.FILL_NEGATIVE)
    --local myc = myclipper:getExclusion(Polygon.FILL_EVEN_ODD, Polygon.FILL_EVEN_ODD)
    for k, v in ipairs(myc) do
    	for k1, v1 in ipairs(v:getPoints()) do
    		for i = 1, #v1 do
    			if i % 2 == 1 then -- x position
    				mysolution.x[#mysolution.x + 1] = v1[i]
    			else -- y position
    				mysolution.y[#mysolution.y + 1] = v1[i]
    			end
    		end
    	end
    	createShape(mysolution)
    end

    You can copy paste the code and it should work (you need to add the clipper plugin).
    You can uncomment the local myc lines to see different effects.

    But what a mess. I saw somewhere in this forum a clipping example that was quite good. I don't see the point of this clipper plugin and I won't add it to the wiki. I suggest to remove it completely from gideros! We could gain back a few kb :*

    Next 3D in gideros o:)
  • some clipper image: the blue part is the clipper result. It does not work well with every type of clipping though.
    Untitled.png
    180 x 182 - 955B
  • there are clipping situations for which you need this plugin. e.g. to compute the exact shadows of multiple light sources with obstacles, which was my original motivation when i asked @ar2rsawseen to add this plugin. at the end i did not pursue this project at the time.
  • MoKaLuxMoKaLux Member
    edited September 14
    oh so you are the one :) Will anybody ever use it? that is the question. I still think we should remove it completely from gideros because people will want to know how this work and try to use it.
  • let it be :smile:

    Likes: MoKaLux

    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
    +1 -1 (+1 / -0 ) Share on Facebook
  • @MoKaLux , this is useful stuff just it maybe should have a name different from clipping to avoid confusement, in 3d software they call it boolean operations.

    Likes: oleg

    +1 -1 (+1 / -0 ) Share on Facebook
  • keszegh said:

    @MoKaLux , this is useful stuff just it maybe should have a name different from clipping to avoid confusement, in 3d software they call it boolean operations.

    In the illustrator this is also called boolean operations ..
    my games:
    https://play.google.com/store/apps/developer?id=razorback456
    мій блог по гідерос https://simartinfo.blogspot.com
    Слава Україні!
Sign In or Register to comment.