Page 1 of 1
Polygon outline / offset
Posted: Sun Aug 15, 2021 8:14 pm
by darkfrei
Hi all!
Here is my first try to solve the polygon offset to other polygon. Actually, it can be easy modified to the offset line to other line.
Code: Select all
function get_offset (vertices, offset)
local offset_polygon = {}
print ( #vertices)
for i = 1, #vertices-1, 2 do
local x1, y1 = vertices[i], vertices[i+1]
local x2, y2 = vertices[i+2], vertices[i+3]
if not x2 then
x2, y2 = vertices[1], vertices[2]
end
local dx = x2-x1
local dy = y2-y1
local vnormx, vnormy = normalization (dx, dy, offset)
local nx = vnormy
local ny = -vnormx
if counter_clockwise or other_side then
nx = -vnormy
ny = vnormx
end
local px1, py1 = x1+nx, y1+ny
local px2, py2 = x2+nx, y2+ny
table.insert (offset_polygon, px1)
table.insert (offset_polygon, py1)
table.insert (offset_polygon, px2)
table.insert (offset_polygon, py2)
end
-- print ( #offset_polygon)
return offset_polygon
end
Here gray polygon with white outline becomes green offset polygon.
Re: Polygon offset
Posted: Sun Aug 15, 2021 8:44 pm
by darkfrei
There is the second version: with respect to crossings:
Code: Select all
function get_intersection (ax, ay, bx, by, cx, cy, dx, dy, unlimited) -- start end start end
-- from line-following
local d = (ax-bx)*(cy-dy)-(ay-by)*(cx-dx)
if d == 0 then return end
local a, b = ax*by-ay*bx, cx*dy-cy*dx
local x = (a*(cx-dx) - b*(ax-bx))/d
local y = (a*(cy-dy) - b*(ay-by))/d
if unlimited then return x, y end
if x <= math.max(ax, bx) and x >= math.min(ax, bx) and
x <= math.max(cx, dx) and x >= math.min(cx, dx) then
return x, y
end
end
Code: Select all
function normul (x, y, offset) -- normalization and multiplication
local d = (x*x+y*y)^0.5
offset = offset or 1
return offset*x/d, offset*y/d
end
Code: Select all
function get_parallel_line (x1, y1, x2, y2, offset)
local dx, dy = x2-x1, y2-y1
local vnormx, vnormy = normul (dx, dy, offset) -- normalization and multiplication
local nx, ny = vnormy, -vnormx
local px1, py1 = x1+nx, y1+ny
local px2, py2 = x2+nx, y2+ny
return px1, py1, px2, py2
end
Code: Select all
function get_offset (vertices, offset)
local offset_polygon = {}
print ( #vertices)
for i = 1, #vertices-1, 2 do
local x1, y1 = vertices[i], vertices[i+1]
local x2, y2 = vertices[i+2], vertices[i+3]
local x3, y3 = vertices[i+4], vertices[i+5]
if not x2 then
x2, y2 = vertices[1], vertices[2]
x3, y3 = vertices[3], vertices[4]
elseif not x3 then
x3, y3 = vertices[1], vertices[2]
end
local px1, py1, px2, py2 = get_parallel_line (x1, y1, x2, y2, offset)
local px3, py3, px4, py4 = get_parallel_line (x2, y2, x3, y3, offset)
local x, y = get_intersection (px1, py1, px2, py2, px3, py3, px4, py4, true)
table.insert (offset_polygon, x)
table.insert (offset_polygon, y)
end
return offset_polygon
end
Re: Polygon offset
Posted: Sun Aug 15, 2021 8:54 pm
by GVovkiv
Nice job!
(But it was better, if i understand anything from it)
Re: Polygon offset
Posted: Mon Aug 16, 2021 5:21 am
by ivan
I wrote a short tutorial about this a while ago, hopefully you might find it useful:
https://2dengine.com/?p=polygons#Polygon_offsetting
Re: Polygon offset
Posted: Mon Aug 16, 2021 1:16 pm
by monolifed
Something I did naively
It doesn't handle self intersections
press W/S
Re: Polygon offset
Posted: Mon Aug 16, 2021 2:53 pm
by darkfrei
monolifed wrote: ↑Mon Aug 16, 2021 1:16 pm
Something I did naively
It doesn't handle self intersections
press W/S
Can you comment this function?
Code: Select all
local split = function(o, x, y, x0, y0, x1, y1, a)
local len = #o
local s = (1 - x0 * x1 - y0 * y1) / (x0 * y1 - y0 * x1)
if s * a < 0 then
o[len + 1], o[len + 2] = x + a * (y0 + s * x0), y + a * (-x0 + s * y0)
return
end
o[len + 1], o[len + 2] = x + a * (y0 + cap * s * x0), y + a * (-x0 + cap * s * y0)
o[len + 3], o[len + 4] = x + a * (y1 - cap * s * x1), y + a * (-x1 - cap * s * y1)
end
Re: Polygon offset
Posted: Mon Aug 16, 2021 3:22 pm
by darkfrei
And with rounded outer corners, for example at least one verticle every 30 degrees.
Re: Polygon offset
Posted: Mon Aug 16, 2021 7:29 pm
by monolifed
o is the offset polygon
(x,y) is a corner of the polygon
(x0, y0) is the unit vector of the line to (x, y) (unit normal of this line is (y0, -x0))
(x1, y1) is the unit vector of the line from (x, y) (unit normal of this line is (y1, -x1))
a is offset amount
a is positive for outset, negative for inset
s is negative for wide(>pi) external angle, positive for narrow(<pi) external angle at (x, y)
so we add 2 points for outset+wide or inset+narrow for (x,y)
otherwise we add single point for (x, y)