Hi all.
As far as the "Resources that have yet to be coded" states, Polygon2D and Polygon3D do not exist.
I think we should be able to change that:
(Test maps out of date.)
As far as the "Resources that have yet to be coded" states, Polygon2D and Polygon3D do not exist.
I think we should be able to change that:
(Test maps out of date.)
JASS:
library Polygon uses PositionFunctions
//! runtextmacro NewLinkedList("polygonList")
/** <to-do>
* - public method split takes nothing returns Polygon[]
* - public method add takes Polygon p returns nothing
* - public method substract takes Polygon p returns nothing
* - public method exclusiveOr takes Polygon p returns nothing
* - public static method add takes Polygon p1, Polygon p2, Polygon dest returns Polygon
* - public static method substract takes Polygon p1, Polygon p2, Polygon dest returns Polygon
* - public static method exclusiveOr takes Polygon p1, Polygon p2, Polygon dest returns Polygon
* - implement trigger calls for some functions to prevent OP limits
*/
/** Credits:
* - Shadow Flux : containsPoint algorithm.
*/
struct Polygon
//Data storage for each line.
private static real array line_startX
private static real array line_startY
private static real array line_endX
private static real array line_endY
//Data storage for each polygon.
readonly real rotation
readonly real scaling
readonly real minX
readonly real minY
readonly real maxX
readonly real maxY
readonly real centerX
readonly real centerY
private integer numberOfLines
//private static LinkedList polygonList
public static method create takes nothing returns Polygon
local Polygon this = allocate()
set numberOfLines = 0
set minX = 0
set minY = 0
set maxX = 0
set maxY = 0
set centerX = 0
set centerY = 0
set scaling = 1
return this
endmethod
public method clear takes nothing returns nothing
local integer c
local integer n = polygonList.first[this]
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set line_startX[c] = 0
set line_startY[c] = 0
set line_endX[c] = 0
set line_endY[c] = 0
call polygonList.removeIndex(c)
endloop
set numberOfLines = 0
set minX = 0
set minY = 0
set maxX = 0
set maxY = 0
set centerX = 0
set centerY = 0
set scaling = 0
endmethod
public method remove takes nothing returns nothing
call clear()
call deallocate()
endmethod
public method getBounds takes nothing returns rect
call SetRect(RECT, minX, minY, maxX, maxY)
return RECT
endmethod
public method getCenter takes nothing returns Coord
return Coord.create(centerX, centerY)
endmethod
public method insertLine takes real startX, real startY, real endX, real endY, integer index returns integer
local integer id = polygonList.insertIndex(this, index)
set line_startX[id] = startX
set line_startY[id] = startY
set line_endX[id] = endX
set line_endY[id] = endY
if numberOfLines == 0 then
if startX < endX then
set minX = startX
set maxX = endX
else
set minX = endX
set maxX = startX
endif
if startY < endY then
set minY = startY
set maxY = endY
else
set minY = endY
set maxY = startY
endif
set centerX = (startX + endX)/2
set centerY = (startY + endY)/2
else
if startX < minX then
set minX = startX
elseif startX > maxX then
set maxX = startX
endif
if endX < minX then
set minX = endX
elseif endX > maxX then
set maxX = endX
endif
if startY < minY then
set minY = startY
elseif startY > maxY then
set maxY = startY
endif
if endY < minY then
set minY = endY
elseif endY > maxY then
set maxY = endY
endif
set centerX = (centerX*numberOfLines*2 + startX + endX) / ((numberOfLines+1)*2)
set centerY = (centerY*numberOfLines*2 + startY + endY) / ((numberOfLines+1)*2)
endif
set numberOfLines = numberOfLines +1
return id
endmethod
public method addLine takes real startX, real startY, real endX, real endY returns integer
return insertLine(startX, startY, endX, endY, 0)
endmethod
public method move takes real xOffset, real yOffset returns nothing
local integer c
local integer n = polygonList.first[this]
set minX = minX + xOffset
set minY = minY + yOffset
set maxX = maxX + xOffset
set maxY = maxY + yOffset
set centerX = centerX + xOffset
set centerY = centerY + yOffset
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set line_startX[c] = line_startX[c] + xOffset
set line_startY[c] = line_startY[c] + yOffset
set line_endX[c] = line_endX[c] + xOffset
set line_endY[c] = line_endY[c] + yOffset
endloop
endmethod
public method setPosition takes real x, real y returns nothing
call move(x - centerX, y - centerY)
endmethod
public method rotateAroundPoint takes real angle, real originX, real originY returns nothing
local real sin = Sin(angle)
local real cos = Cos(angle)
local real oldX
local real oldY
local integer c
local integer n = polygonList.first[this]
set rotation = rotation + angle
set centerX = (originX + ((centerX - originX) * cos) - ((centerY - originY) * sin))
set centerY = (originY + ((centerX - originX) * sin) + ((centerY - originY) * cos))
set minX = centerX
set minY = centerY
set maxX = centerX
set maxY = centerY
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set oldX = line_startX[c]
set oldY = line_startY[c]
set line_startX[c] = (originX + ((oldX - originX) * cos) - ((oldY - originY) * sin))
set line_startY[c] = (originY + ((oldX - originX) * sin) + ((oldY - originY) * cos))
set oldX = line_endX[c]
set oldY = line_endY[c]
set line_endX[c] = (originX + ((oldX - originX) * cos) - ((oldY - originY) * sin))
set line_endY[c] = (originY + ((oldX - originX) * sin) + ((oldY - originY) * cos))
if line_startX[c] < minX then
set minX = line_startX[c]
elseif line_startX[c] > maxX then
set maxX = line_startX[c]
endif
if line_endX[c] < minX then
set minX = line_endX[c]
elseif line_endX[c] > maxX then
set maxX = line_endX[c]
endif
if line_startY[c] < minY then
set minY = line_startY[c]
elseif line_startY[c] > maxY then
set maxY = line_startY[c]
endif
if line_endY[c] < minY then
set minY = line_endY[c]
elseif line_endY[c] > maxY then
set maxY = line_endY[c]
endif
endloop
endmethod
public method rotateAroundPointDeg takes real angle, real originX, real originY returns nothing
call rotateAroundPoint(angle*DEGTORAD, originX, originY)
endmethod
public method rotate takes real angle returns nothing
call rotateAroundPoint(angle, centerX, centerY)
endmethod
public method rotateDeg takes real angle returns nothing
call rotate(angle*DEGTORAD)
endmethod
public method setRotation takes real angle returns nothing
call rotate(angle - rotation)
endmethod
public method setRotationDeg takes real angle returns nothing
call setRotation(angle*DEGTORAD)
endmethod
public method rotateAsDefault takes real angle returns nothing
call rotate(angle)
set rotation = 0
endmethod
public method rotateAsDefaultDeg takes real angle returns nothing
call rotateAsDefault(angle*DEGTORAD)
endmethod
public method setRotationAsDefault takes real angle returns nothing
call rotateAsDefault(angle - rotation)
endmethod
public method setRotationAsDefaultDeg takes real angle returns nothing
call setRotationAsDefault(angle*DEGTORAD)
endmethod
public method getRotation takes nothing returns real
return rotation
endmethod
public method getRotationDeg takes nothing returns real
return rotation*RADTODEG
endmethod
public method scale takes real scale returns nothing
local integer c
local integer n = polygonList.first[this]
set scaling = scaling * scale
set minX = centerX + (minX-centerX)*scale
set minY = centerY + (minY-centerY)*scale
set maxX = centerX + (maxX-centerX)*scale
set maxY = centerY + (maxY-centerY)*scale
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set line_startX[c] = centerX + (line_startX[c] - centerX)*scale
set line_startY[c] = centerX + (line_startY[c] - centerY)*scale
set line_endX[c] = centerX + (line_endX[c] - centerX)*scale
set line_endY[c] = centerX + (line_endY[c] - centerY)*scale
endloop
endmethod
public method setScale takes real scale returns nothing
call scale(scale / scaling)
endmethod
public method scaleAsDefault takes real scale returns nothing
call scale(scale)
set scaling = 1
endmethod
public method setScaleAsDefault takes real scale returns nothing
call scaleAsDefault(scale / scaling)
endmethod
public method getScale takes nothing returns real
return scaling
endmethod
public method containsPoint takes real px, real py returns boolean
local integer c
local integer n = polygonList.first[this]
local boolean b
if px >= minX and px <= maxX and py >= minY and py <= maxY then
set b = false
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
if (py >= line_endY[c]) != (py >= line_startY[c]) and px < (line_startX[c] - line_endX[c]) * (py - line_endY[c]) /(line_startY[c] - line_endY[c]) + line_endX[c] then
set b = not b
endif
endloop
return b
endif
return false
endmethod
public method getSurface takes nothing returns real
local real area = 0
local integer c
local integer n = polygonList.first[this]
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set area = area + line_endX[c] * line_startY[c] - line_startX[c] * line_endY[c]
endloop
set area = area/2
if area > 0 then
return area
else
return -area
endif
endmethod
public method clone takes nothing returns Polygon
local Polygon poly = Polygon.create()
local integer id
local integer c
local integer n = polygonList.first[this]
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set id = polygonList.insertIndex(poly, 0)
set line_startX[id] = line_startX[c]
set line_startY[id] = line_startY[c]
set line_endX[id] = line_endX[c]
set line_endY[id] = line_endY[c]
endloop
set poly.numberOfLines = numberOfLines
set poly.minX = minX
set poly.minY = minY
set poly.maxX = maxX
set poly.maxY = maxY
set poly.centerX = centerX
set poly.centerY = centerY
set poly.scaling = scaling
return poly
endmethod
public static integer pointCount
public static real array pointX
public static real array pointY
private method getLineIntersection takes integer i1, integer i2 returns boolean
local real s1_x
local real s1_y
local real s2_x
local real s2_y
local real s
local real t
local real a
set s1_x = line_endX[i1] - line_startX[i1]
set s1_y = line_endY[i1] - line_startY[i1]
set s2_x = line_endX[i2] - line_startX[i2]
set s2_y = line_endY[i2] - line_startY[i2]
set a = -s2_x * s1_y + s1_x * s2_y
if a == 0 then
return false
endif
set s = (-s1_y * (line_startX[i1] - line_startX[i2]) + s1_x * (line_startY[i1] - line_startY[i2])) / a
set t = ( s2_x * (line_startY[i1] - line_startY[i2]) - s2_y * (line_startX[i1] - line_startX[i2])) / a
if s >= 0 and s <= 1 and t >= 0 and t <= 1 then
// Collision detected
set pointX[pointCount] = line_startX[i1] + t*s1_x
set pointY[pointCount] = line_startY[i1] + t*s1_y
set pointCount = pointCount +1
return true
endif
return false
endmethod
public method getIntersectionPoints takes Polygon p returns nothing
local integer c1
local integer n1 = polygonList.first[this]
local integer c2
local integer n2
set pointCount = 0
loop
exitwhen n1 == 0
set c1 = n1
set n1 = polygonList.next[c1]
set n2 = polygonList.first
loop
exitwhen n2 == 0
set c2 = n2
set n2 = polygonList.next[c2]
call getLineIntersection(c1, c2)
endloop
endloop
endmethod
public method intersect takes Polygon p returns boolean
local integer c1
local integer n1 = polygonList.first[this]
local integer c2
local integer n2
set pointCount = 0
loop
exitwhen n1 == 0
set c1 = n1
set n1 = polygonList.next[c1]
set n2 = polygonList.first
loop
exitwhen n2 == 0
set c2 = n2
set n2 = polygonList.next[c2]
if getLineIntersection(c1, c2) then
return true
endif
endloop
endloop
return false
endmethod
public method toString takes nothing returns string
local string result = ""
local integer c
local integer n = polygonList.first[this]
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set result = result + ", ["+Coordinates2String(line_startX[c], line_startY[c])+", "+Coordinates2String(line_endX[c], line_endY[c])+"]"
endloop
return "[ "+SubString(result, 2, StringLength(result))+" ]"
endmethod
//Test method
public method generateLightnings takes string model, real duration returns nothing
local lightning l
local integer c
local integer n = polygonList.first[this]
loop
exitwhen n == 0
set c = n
set n = polygonList.next[c]
set l = AddLightning(model, true, line_startX[c], line_startY[c], line_endX[c], line_endY[c])
call TimedL.P2P(l, duration, 100, 100)
set l = null
endloop
endmethod
//Test method
public static method createStar takes integer numberOfPoints, real centerX, real centerY, real outerRadius, real innerRadius returns Polygon
local Polygon this = Polygon.create()
local real angleStep = TAU/numberOfPoints/2
local integer i = 0
local real angle = 0
local real startX
local real startY
local real endX
local real endY
set startX = centerX + innerRadius * Cos(-angleStep)
set startY = centerY + innerRadius * Sin(-angleStep)
loop
exitwhen i >= numberOfPoints
set endX = centerX + outerRadius * Cos(angle)
set endY = centerY + outerRadius * Sin(angle)
call addLine(startX, startY, endX, endY)
set startX = endX
set startY = endY
set angle = angle + angleStep
set endX = centerX + innerRadius * Cos(angle)
set endY = centerY + innerRadius * Sin(angle)
call addLine(startX, startY, endX, endY)
set startX = endX
set startY = endY
set angle = angle + angleStep
set i = i +1
endloop
return this
endmethod
//Test method
public static method createCircle takes integer numberOfVertices, real centerX, real centerY, real radius returns Polygon
local Polygon this = create()
local real angleStep = TAU/numberOfVertices
local integer i = 0
local real angle = 0
local real startX
local real startY
local real endX
local real endY
set startX = centerX + radius * Cos(-angleStep)
set startY = centerX + radius * Sin(-angleStep)
loop
exitwhen i >= numberOfVertices
set endX = centerX + radius * Cos(angle)
set endY = centerY + radius * Sin(angle)
call addLine(startX, startY, endX, endY)
set startX = endX
set startY = endY
set angle = angle + angleStep
set i = i +1
endloop
return this
endmethod
endstruct
endlibrary
Attachments
Last edited: