- Joined
- Apr 24, 2012
- Messages
- 5,111
JASS:
library Polygon requires Real2D Rects
private module Init
private static method onInit takes nothing returns nothing
call init()
endmethod
endmodule
struct Polygon extends array
private Coord head
private static integer array prev
private static integer array next
readonly Coord center
readonly integer points
private Rects AABB
private static thistype array recycler
private static method allocate takes nothing returns thistype
local thistype this = recycler[0]
if recycler[this] == 0 then
set recycler[0] = this + 1
else
set recycler[0] = recycler[this]
endif
set center = Coord.create(0, 0)
set AABB = Rects.create(0, 0, 1, 1)
set points = 0
set head = 0
return this
endmethod
private method deallocate takes nothing returns nothing
set recycler[this] = recycler[0]
set recycler[0] = this
endmethod
private static method min takes real a, real b returns real
if a < b then
return a
endif
return b
endmethod
private static method max takes real a, real b returns real
if a > b then
return a
endif
return b
endmethod
static method create takes Coord A, Coord B, Coord C returns thistype
local thistype this = allocate()
set head = A
set prev[A] = C
set next[A] = B
set prev[B] = head
set next[B] = C
set prev[C] = B
set next[C] = A
set center.x = (A.x + B.x + C.x)/3
set center.y = (A.y + B.y + C.y)/3
set AABB.minX = min(min(A.x, B.x), C.x)
set AABB.minY = min(min(A.y, B.y), C.y)
set AABB.maxX = max(max(A.x, B.x), C.x)
set AABB.maxY = max(max(A.y, B.y), C.y)
call AABB.refresh()
set points = 3
return this
endmethod
method destroy takes nothing returns nothing
call deallocate()
call center.destroy()
set head = 0
set points = 0
endmethod
method refresh takes nothing returns nothing
local Coord p = next[head]
local real sx = p.x
local real sy = p.y
local real minX = p.x
local real minY = p.y
local real maxX = p.x
local real maxY = p.y
set p = next
loop
set minX = min(p.x, minX)
set minY = min(p.y, minY)
set maxX = min(p.x, maxX)
set maxY = min(p.y, maxY)
set sx = sx + p.x
set sy = sy + p.y
exitwhen p == head
set p = next
endloop
set center.x = sx/R2I(points)
set center.y = sy/R2I(points)
endmethod
method has takes Coord coord returns boolean
local Coord p = next[head]
loop
if coord == p then
return true
endif
exitwhen p == head
set p = next
endloop
return false
endmethod
method insert takes Coord coord returns nothing
if not has(coord) then
set points = points + 1
set next[coord] = head
set prev[coord] = prev[head]
set next[prev[head]] = coord
set prev[head] = coord
call refresh()
endif
endmethod
method remove takes Coord coord returns nothing
if has(coord) and points > 3 then
set next[prev[coord]] = next[coord]
set prev[next[coord]] = prev[coord]
if head == coord then
set head = next[coord]
endif
set points = points - 1
call refresh()
endif
endmethod
method rotate takes real rad returns nothing
local Coord p = next[head]
local real tx
loop
set tx = p.x
set p.x = p.x*Cos(rad) - p.y*Sin(rad)
set p.y = p.y*Cos(rad) + tx*Sin(rad)
exitwhen p == head
set p = next
endloop
call refresh()
endmethod
method scale takes real factor returns nothing
local Coord p = next[head]
local real dist
loop
set p.x = center.x + (p.x - center.x)*factor
set p.y = center.y + (p.y - center.y)*factor
exitwhen p == head
set p = next
endloop
call refresh()
endmethod
method containsPoint takes real x, real y returns boolean
local Coord p = next[head]
local boolean result = false
loop
if ((p.y >= y) != (head.y >= y)) and (x < ((head.x - p.x)*(y - p.y)/(head.y - p.y) + p.x)) then
set result = not result
endif
exitwhen p == head
set p = next
endloop
return result
endmethod
method intersects takes Polygon p returns boolean
return false
endmethod
endstruct
endlibrary