- Joined
- Mar 19, 2008
- Messages
- 3,141
A class for manipulating rectangles.
Note: the x, y coordinates and the width and height stored inside a wxRect object may be negative and that wxRect functions do not perform any check against negative values.
Before uploading this, I've searched for similar libraries and indeed at least one has been found: Rectwraps by azlier. Even though this code highly differs from azlier's snippet and was written without any usage of his project, credits goes to azlier for uploading first library which allows easy rectangle manipulations.
Implementation based on typical Rect class from graphics application libraries. Requires Real2D which is heavly used throughout the code.
Demo:
Note: the x, y coordinates and the width and height stored inside a wxRect object may be negative and that wxRect functions do not perform any check against negative values.
Before uploading this, I've searched for similar libraries and indeed at least one has been found: Rectwraps by azlier. Even though this code highly differs from azlier's snippet and was written without any usage of his project, credits goes to azlier for uploading first library which allows easy rectangle manipulations.
Implementation based on typical Rect class from graphics application libraries. Requires Real2D which is heavly used throughout the code.
JASS:
/*****************************************************************************
*
* Rects v2.0.1.1
* by Bannar
*
* Handly rectangle manipulation.
*
******************************************************************************
*
* Requirements:
*
* Alloc - choose whatever you like
* e.g.: by Sevion hiveworkshop.com/threads/snippet-alloc.192348/
*
*
* Optional requirement:
*
* Real2D by Bannar
* hiveworkshop.com/threads/snippet-real2d.249100/
*
******************************************************************************
*
* Interface RectsForCellAction:
*
* static method forCell takes real x, real y returns nothing
* Performs action on specified rectangle cell.
*
* module RectsForCellActionModule
* Declares body for new action type.
*
*
* Action implementation example:
*
* | struct MyAction extends array
* | static method forCell takes real x, real y returns nothing
* | return CreateItem('crys', x, y)
* | endmethod
* |
* | implement RectsForCellActionModule
* | endstruct
*
******************************************************************************
*
* struct Rect:
*
* General:
*
* | static method create takes real x, real y, real w, real h returns thistype
* | Default ctor.
* |
* | static method operator[] takes thistype other returns thistype
* | Copy ctor.
* |
* | method destroy takes nothing returns nothing
* | Default dctor.
*
*
* Fields:
*
* | real minX
* | real minY
* | real maxX
* | real maxY
* | real width
* | real height
* |
* | readonly Coord coord
* | Coordinate object determining minX & minY. Requires Real2D.
* |
* | readonly Size size
* | Size object determining width & height. Requires Real2D.
* |
* | readonly real centerX
* | Center X of the rectangle.
* |
* | readonly real centerY
* | Center Y of the rectangle.
* |
* | readonly rect rect
* | Returns the underlying rect handle.
*
*
* Methods:
*
* | method refresh takes nothing returns nothing
* | Forces a refresh on the underlying rect handle.
* |
* | method moveTo takes real x, real y returns thistype
* | Center rect to specified coordinates.
* |
* | method empty takes nothing returns boolean
* | Checks whether rectangle is empty.
* |
* | method contains takes real x, real y returns boolean
* | Whether speficied value is within given rectangle.
* |
* | method containtsRect takes Rects r returns boolean
* | method containsItem takes item itm returns boolean
* | method containsUnit takes unit u returns boolean
* | method containsDestructable takes destructable d returns boolean
* |
* | method inflate takes real dx, real dy returns thistype
* | Increases the size of the rectangle.
* |
* | method deflate takes real dx, real dy returns thistype
* | Decreases the rectangle size.
* |
* | method offset takes real dx, real dy returns thistype
* | Moves the rectangle by the specified offset.
* |
* | method intersect takes Rects r returns thistype
* | Modifies this rectangle to contain the overlapping portion of this rectangle and the one passed in as parameter.
* |
* | method getIntersecting takes Rects r returns thistype
* | Returns the overlapping portion of this rectangle and the one passed in as parameter.
* |
* | method intersects takes Rects r returns boolean
* | Returns true if this rectangle has a non-empty intersection with the rectangle rect and false otherwise.
* |
* | method union takes Rects r returns thistype
* | Modifies the rectangle to contain the bounding box of this rectangle and the one passed in as parameter.
* |
* | method forEach takes RectsForCellAction action, real radius returns thistype
* | Performs the specified action on each cell found within rectangle.
*
*
* Methods requiring Real2D:
*
* | static method createFromCoords takes Coord c1, Coord c2 returns thistype
* | static method createFromCoordSize takes Coord c, Size s returns thistype
* | Factory ctors.
* |
* | method containsCoord takes Coord c returns boolean
* | method offsetCoord takes Coord c returns thistype
* |
* | method inflateSize takes Size s returns thistype
* | method deflateSize takes Size s returns thistype
*
*
*****************************************************************************/
library Rects uses Alloc optional Real2D
globals
private trigger array triggers
// iteration related globals
private real argX = 0.0
private real argY = 0.0
endglobals
struct RectsForCellAction extends array
implement Alloc
static method forCell takes real x, real y returns nothing
return
endmethod
static method create takes nothing returns thistype
local thistype this = allocate()
set triggers[this] = CreateTrigger()
return this
endmethod
method destroy takes nothing returns nothing
call DestroyTrigger(triggers[this])
set triggers[this] = null
call deallocate()
endmethod
endstruct
module RectsForCellActionModule
private delegate RectsForCellAction parent
private static method onInvoke takes nothing returns nothing
call forCell(argX, argY)
endmethod
static method create takes nothing returns thistype
local thistype this = RectsForCellAction.create()
set parent = this
call TriggerAddCondition(triggers[this], Condition(function thistype.onInvoke))
return this
endmethod
method destroy takes nothing returns nothing
call parent.destroy()
endmethod
endmodule
struct Rects extends array
readonly rect rect
implement Alloc
static if not LIBRARY_Real2D then
real minX
real minY
real width
real height
else
readonly Coord coord
readonly Size size
method operator width takes nothing returns real
return size.width
endmethod
method operator height takes nothing returns real
return size.height
endmethod
method operator minX takes nothing returns real
return coord.x
endmethod
method operator minY takes nothing returns real
return coord.y
endmethod
method operator width= takes real w returns nothing
set size.width = w
endmethod
method operator height= takes real h returns nothing
set size.height = h
endmethod
method operator minX= takes real x returns nothing
set coord.x = x
endmethod
method operator minY= takes real y returns nothing
set coord.y = y
endmethod
endif
method operator maxX takes nothing returns real
return minX + width
endmethod
method operator maxY takes nothing returns real
return minY + height
endmethod
method operator centerX takes nothing returns real
return minX + (width / 2)
endmethod
method operator centerY takes nothing returns real
return minY + (height / 2)
endmethod
method operator maxX= takes real x returns nothing
set width = x - minX
endmethod
method operator maxY= takes real y returns nothing
set height = y - minY
endmethod
method refresh takes nothing returns nothing
call SetRect(rect, minX, minY, maxX, maxY)
endmethod
method moveTo takes real x, real y returns thistype
set minX = x - (width * 0.5)
set minY = y - (height * 0.5)
call refresh()
return this
endmethod
method empty takes nothing returns boolean
return width <= 0 or height <= 0
endmethod
static method create takes real x, real y, real w, real h returns thistype
local thistype this = allocate()
static if LIBRARY_Real2D then
set coord = Coord.create(x, y)
set size = Size.create(w, h)
else
set minX = x
set minY = y
set width = w
set height = h
endif
set rect = Rect(x, y, x+w, y+h)
return this
endmethod
static method operator[] takes thistype other returns thistype
return create(other.minX, other.minY, other.width, other.height)
endmethod
method destroy takes nothing returns nothing
call RemoveRect(rect)
set rect = null
static if LIBRARY_Real2D then
call coord.destroy()
call size.destroy()
set coord = 0
set size = 0
endif
call deallocate()
endmethod
method contains takes real x, real y returns boolean
return x >= minX and y >= minY and (y - minY) < height and (x - minX) < width
endmethod
method containtsRect takes Rects r returns boolean
return contains(r.minX, r.minY) and contains(r.maxX, r.maxY)
endmethod
method containsItem takes item itm returns boolean
return itm != null and not IsItemOwned(itm) and contains(GetItemX(itm), GetItemY(itm))
endmethod
method containsUnit takes unit u returns boolean
return u != null and contains(GetUnitX(u), GetUnitY(u))
endmethod
method containsDestructable takes destructable d returns boolean
return d != null and contains(GetDestructableX(d), GetDestructableY(d))
endmethod
method inflate takes real dx, real dy returns thistype
if (-2 * dx) > width then
set minX = centerX
set width = 0
else
set minX = minX - dx
set width = width + (2 * dx)
endif
if (-2 * dy) > height then
set minY = centerY
set height = 0
else
set minY = minY - dy
set height = height + (2 * dy)
endif
call refresh()
return this
endmethod
method deflate takes real dx, real dy returns thistype
return inflate(-dx, -dy)
endmethod
method offset takes real dx, real dy returns thistype
set minX = minX + dx
set minY = minY + dy
call refresh()
return this
endmethod
method intersect takes Rects r returns thistype
local real x2 = maxX
local real y2 = maxY
if minX < r.minX then
set minX = r.minX
endif
if minY < r.minY then
set minY = r.minY
endif
if x2 > r.maxX then
set x2 = r.maxX
endif
if y2 > r.maxY then
set y2 = r.maxY
endif
set width = x2 - minX
set height = y2 - minY
if width <= 0 or height <= 0 then
set width = 0
set height = 0
endif
call refresh()
return this
endmethod
method getIntersecting takes Rects r returns thistype
local real x1 = minX
local real y1 = minY
local real x2 = maxX
local real y2 = maxY
local real w
local real h
if minX < r.minX then
set x1 = r.minX
endif
if minY < r.minY then
set y1 = r.minY
endif
if x2 > r.maxX then
set x2 = r.maxX
endif
if y2 > r.maxY then
set y2 = r.maxY
endif
set w = x2 - minX
set h = y2 - minY
if w <= 0 or h <= 0 then
set w = 0
set h = 0
endif
return create(x1, y1, w, h)
endmethod
method intersects takes Rects r returns boolean
local Rects tmp = getIntersecting(r)
local boolean result
set result = (tmp.width != 0)
call tmp.destroy()
return result
endmethod
private static method min takes real x1, real x2 returns real
if x1 <= x2 then
return x1
endif
return x2
endmethod
private static method max takes real x1, real x2 returns real
if x1 >= x2 then
return x1
endif
return x2
endmethod
method union takes Rects r returns thistype
local real x1
local real y1
local real x2
local real y2
if width == 0 or height == 0 then
set minX = r.minX
set minY = r.minY
set width = r.width
set height = r.height
else
set x1 = min(minX, r.minX)
set y1 = min(minY, r.minY)
set x2 = max(maxX, r.maxX)
set y2 = max(maxY, r.maxY)
set minX = x1
set minY = y1
set width = x2 - x1
set height = y2 - y1
endif
call refresh()
return this
endmethod
method forEach takes RectsForCellAction action, real radius returns thistype
local real x = minX
local real y
loop
set y = minY
loop
set argX = x
set argY = y
call TriggerEvaluate(triggers[action])
set y = y + radius
exitwhen y > maxY
endloop
set x = x + radius
exitwhen x > maxX
endloop
return this
endmethod
static if LIBRARY_Real2D then
static method createFromCoords takes Coord c1, Coord c2 returns thistype
local thistype this = allocate()
set coord = Coord.create(c1.x, c1.y)
set size = Size.create(c2.x - c1.x, c2.y - c1.y)
if width < 0 then
set size.width = -width
set coord.x = c2.x
endif
if height < 0 then
set size.height = -height
set coord.y = c2.y
endif
set rect = Rect(minX, minY, maxX, maxY)
return this
endmethod
static method createFromCoordSize takes Coord c, Size s returns thistype
return create(c.x, c.y, s.width, s.height)
endmethod
method containsCoord takes Coord c returns boolean
return contains(c.x, c.y)
endmethod
method offsetCoord takes Coord c returns thistype
return offset(c.x, c.y)
endmethod
method inflateSize takes Size s returns thistype
return inflate(s.width, s.height)
endmethod
method deflateSize takes Size s returns thistype
return inflate(-s.width, -s.height)
endmethod
endif
endstruct
endlibrary
JASS:
library RectsTest requires Rects, Real2D
struct RectsTest extends array
static method draw_rect takes Rects rec, string lightType returns nothing
call AddLightning(lightType, true, rec.minX, rec.minY, rec.minX, rec.maxY)
call AddLightning(lightType, true, rec.maxX, rec.minY, rec.maxX, rec.maxY)
call AddLightning(lightType, true, rec.minX, rec.minY, rec.maxX, rec.minY)
call AddLightning(lightType, true, rec.minX, rec.maxY, rec.maxX, rec.maxY)
endmethod
static method wait takes real period returns nothing
call TriggerSleepAction(period)
endmethod
static method print takes real period, string what returns nothing
call DisplayTimedTextToPlayer(Player(0), 0, 0, period, what)
call wait(period)
endmethod
static method onInit takes nothing returns nothing
local Coord pt = Coord.create(-200, -300)
local Size sz = Size.create(700, 800)
local Rects rec = Rects.createFromCoordSize(pt, sz)
local Rects rec2 = 0
call wait(2)
call draw_rect(rec, "CLPB")
call print(5, "Initial rect |c000080FF(blue)|r: " + R2S(rec.minX) + " " + R2S(rec.minY) + " " + R2S(rec.maxX) + " " +R2S(rec.maxY) )
call print(5, "Now, lets create second rect nearby and use it to intersect with our initial one.")
set rec2 = Rects.create(300, 300, 800, 800)
call draw_rect(rec2, "LEAS")
call print(5, "\nOur second rect |c00FF8000(orange)|r: " + R2S(rec2.minX) + " " + R2S(rec2.minY) + " " + R2S(rec2.maxX) + " " +R2S(rec2.maxY) )
call print(5, "Lets intersect it and see the results:")
call rec.intersect(rec2)
call draw_rect(rec, "AFOD")
call print(5, "\nIntersected rect |c00FF0000(red)|r: " + R2S(rec.minX) + " " + R2S(rec.minY) + " " + R2S(rec.maxX) + " " +R2S(rec.maxY) )
call pt.setXY(200, 200)
set sz.width = 300
call rec.coord.setXY(pt.x, pt.y)
call rec.size.setWH(sz.width, sz.height)
call rec.refresh()
call print(5, "Time to resize our rect. New width: 300; point: (200, 200).")
call draw_rect(rec, "DRAL")
call print(5, "\nResized rect |c0000FF00(green)|r: " + R2S(rec.minX) + " " + R2S(rec.minY) + " " + R2S(rec.maxX) + " " +R2S(rec.maxY) )
call print(5, "Before we finish, perform inflate method. Values: 150, 275.")
call rec.inflate(150, 275)
call draw_rect(rec, "HWPB")
call print(5, "\nInflated rect |c00FFFF00(yellow)|r: " + R2S(rec.minX) + " " + R2S(rec.minY) + " " + R2S(rec.maxX) + " " +R2S(rec.maxY) )
call print(5, "Thank you for your undivided attention.")
endmethod
endstruct
endlibrary
Last edited: