• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] Real2D

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Interpretation of real point with helper classes. Real2D is a parent struct to Point and Size structs, and is similar to a Pair object of two reals with ctor, dctor and set2 members to manage its instances.

Both Point Coord and Size are a useful data structures for graphics operations. Point Coord is designed to basically replace location functionality without really being a location object while Size instance represents size, usefull when working with regions, rectangles or even polygon figures.

Note: the x and y stored inside a Point Coord object, as well as width and height stored inside a Size object may be negative and that Point Coord nor Size functions do not perform any check against negative values.

Although Point Coord is almost an equivalent to Size, it has a different meaning: Point Coord represents a position while Size represents the size. They differ in interface too.
JASS:
/*****************************************************************************
*
*    Real2D v1.1.0.3
*       by Bannar aka Spinnaker
*
*    Interpretation of coordinate and size objects usefull for graphic operations.
*
******************************************************************************
*
*    struct Coord:
*
*       real x
*       real y
*
*       static method create takes real xx, real yy returns thistype
*          default ctor
*
*       static method createFromLoc takes location l returns thistype
*          location ctor
*
*       static method operator[] takes thistype c returns thistype
*          copy ctor
*
*       method destroy takes nothing returns nothing
*          default dctor
*
*       method setXY takes real xx, real yy returns nothing
*          set both members of struct instance
*
*       method operator== takes thistype c returns boolean
*          equalTo operator
*
*       method project takes real dist, real angle returns thistype
*          projects coordinate by given distance towards specified angle
*
*       method offset takes real xx, real yy returns thistype
*          offsets coordinate by a vector(xx, yy)
*
*       method loc takes nothing returns location
*          returns location of Coord instance
*
******************************************************************************
*
*    struct Size:
*
*       real width
*       real height
*
*       static method create takes real ww, real hh returns thistype
*          default ctor
*
*       static method operator[] takes thistype s returns thistype
*          copy ctor
*
*       method destroy takes nothing returns nothing
*          default dctor
*
*       method setWH takes real ww, real hh returns nothing
*          set both members of struct instance
*
*       method operator== takes thistype s returns boolean
*          equalTo operator
*
*       method incTo takes thistype s returns thistype
*          increase width and height to s size
*
*       method decTo takes thistype s returns thistype
*          decrease width and height to s size
*
*       method incBy takes real dw, real dh returns thistype
*          increase size by specified values
*
*       method decBy takes real dw, real dh returns thistype
*          decrease size by specified values
*
*       method scale takes real wscale, real hscale returns thistype
*          rescale both width and height
*
******************************************************************************/
library Real2D

    struct Coord extends array
        private static integer count = 0
        private thistype recycle

        real x
        real y

        static method create takes real xx, real yy returns thistype
            local thistype this = thistype(0).recycle

            if ( this == 0 ) then
                set count = count + 1
                set this = count
            else
                set thistype(0).recycle = recycle
            endif

            set x = xx
            set y = yy

            return this
        endmethod

        static method createFromLoc takes location l returns thistype
            return create(GetLocationX(l), GetLocationY(l))
        endmethod

        static method operator[] takes thistype c returns thistype
            return create(c.x, c.y)
        endmethod

        method destroy takes nothing returns nothing
            set recycle = thistype(0).recycle
            set thistype(0).recycle = this
        endmethod

        method setXY takes real xx, real yy returns nothing
            set x = xx
            set y = yy
        endmethod

        method operator== takes thistype c returns boolean
            return ( x == c.x ) and ( y == c.y )
        endmethod

        method project takes real dist, real angle returns thistype
            set x = x + dist * Cos(angle * bj_DEGTORAD)
            set y = y + dist * Sin(angle * bj_DEGTORAD)
            return this
        endmethod

        method offset takes real xx, real yy returns thistype
            set x = x + xx
            set y = y + yy
            return this
        endmethod

        method loc takes nothing returns location
            return Location(x, y)
        endmethod
    endstruct

    struct Size extends array
        private static integer count = 0
        private thistype recycle

        real width
        real height

        static method create takes real ww, real hh returns thistype
            local thistype this = thistype(0).recycle

            if ( this == 0 ) then
                set count = count + 1
                set this = count
            else
                set thistype(0).recycle = recycle
            endif

            set width = ww
            set height = hh

            return this
        endmethod

        static method operator[] takes thistype s returns thistype
            return create(s.width, s.height)
        endmethod

        method destroy takes nothing returns nothing
            set recycle = thistype(0).recycle
            set thistype(0).recycle = this
        endmethod

        method setWH takes real ww, real hh returns nothing
            set width = ww
            set height = hh
        endmethod

        method operator== takes thistype s returns boolean
            return ( width == s.width ) and ( height == s.height )
        endmethod

        method incTo takes thistype s returns thistype
            if ( s.width > width ) then
                set width = s.width
            endif
            if ( s.height > height ) then
                set height = s.height
            endif

            return this
        endmethod

        method decTo takes thistype s returns thistype
            if ( s.width < width ) then
                set width = s.width
            endif
            if ( s.height < height ) then
                set height = s.height
            endif

            return this
        endmethod

        method incBy takes real dw, real dh returns thistype
            set width = width + dw
            set height = height + dh

            return this
        endmethod

        method decBy takes real dw, real dh returns thistype
            call incBy(-dw, -dh)
            return this
        endmethod

        method scale takes real wscale, real hscale returns thistype
            set width = width * wscale
            set height = height * hscale

            return this
        endmethod
    endstruct

endlibrary
 
Last edited:

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
I never ended up using more than 8192 instances of this even when playing with geometry in some maps.

I think that reduction of global variables in this case is good - if you know that some class of objects won't be used as frequently, you should consider modification of approach used - this is what I did here.

Most of recursive calls will be inlined and the idea of parent 2DReal might we good in some cases when you need access just to basic fields.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Real2D came from wxWidget implementation of wrapper library related to screen coordinates - I haven come up with anything better :)

Coord seems nice!

If I were to add those globals, the generic lib probably would lose it's meaning, wouldn't it?
Also, doesn't most of those calls inline? If so, is there any efficiency loss in those cases? I'm asking because I just want to know what's the best approach.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Removed parent struct Real2D and renamed Point to Coord (this might be a subject to change tho).

Removed following methods:
* method isSpecified takes nothing returns boolean
* method setDefaults takes thistype pt returns nothing
* method assignBySum takes thistype pt returns thistype
* method assignByDiff takes thistype pt returns thistype

and for size:
* method incByPoint takes Point pt returns nothing
* method incBySize takes thistype s returns nothing
* method decByPoint takes Point pt returns nothing
* method decBySize takes thistype s returns nothing

constant real DefaultCoord is also gone.

There are inc/dec 'To' and 'By' methods for Size already, additional ones seem unnecessary.
setDefaults/isSpecified are good, but not in jass environment.

Added offset (by vector 2D xx,yy) and project (rotation) methods for Coord struct.

'set2' is now setXY and setWH for Coord and Size respectively. Structs no longer share common instances - this might also be a subject to change.
 
Top