• 🏆 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] Point

Level 7
Joined
Apr 30, 2011
Messages
359
JASS:
//========================================================================================
//      
//      [   Point   ]
//      -*- overcold_ice -*-
//      
//          An advanced version of location native
//----------------------------------------------------------------------------------------
//      
//     -[*] Features:
//          - Simple operators and dynamic setups
//          - Splits between ground height and z
//          - Auto updated ground height
//----------------------------------------------------------------------------------------
//      
//     -[*] Configurables:      
/*      
        private constant boolean AUTO_DESTROY
*/          //= enables/disables auto destroy, which automatically destroys the struct
            //  at the end of the thread if it has zero lock count
//----------------------------------------------------------------------------------------
//            
//     -[*] API:
/*      
        struct Point extends array
            real x  //= x-coordinate of the Point
            real y  //= y-coordinate of the Point
            real z  //= z-coordinate of the Point, doesn't include ground height
            
            readonly real h //= ground height at the Point, automatically updated
            
            static method operator create takes nothing returns Point
*/              //= allocator for the struct, zero lock count
                //  if AUTO_DESTROY then the struct is automatically destroyed
                //  at the end of the thread if it has zero lock count
/*      
            method lock takes nothing returns Point     //= lock count +1
            method unlock takes nothing returns Point   //= lock count -1, destroy if 0
            method break takes nothing returns Point    //= destroy
*/              //= deallocator for the struct, the values still valid until
                //  a create operator is called
/*      
            static if AUTO_DESTROY then
                method lastUse takes nothing returns nothing
            endif
*/              //= destroys the struct at the end of the thread if it has zero
                //  lock count
/*      
            static method gh takes real x, real y returns real
*/              //= returns the ground height at (x, y) coordinate
/*
            method sx takes real x returns Point
            method sy takes real y returns Point
            method sz takes real z returns Point
*/              //= sets x, y, z to those specified values
                //  allows single line setups
/*
            method distXY   takes real x, real y returns real
            method distXYZ  takes real x, real y, real z returns real
            method distXYP  takes Point p returns real
            method distXYZP takes Point p returns real
*/              //= get the distance from this Point to another location specified
                //  by (x, y, z) coordinate or Point
                //  all of them inlines
/*
            method angleXY   takes real x, real y returns real
            method angleXYZ  takes real x, real y, real z returns real
            method angleXYP  takes Point p returns real
            method angleXYZP takes Point p returns real
*/              //= get the angle from this Point to another location specified
                //  by (x, y, z) coordinate or Point in radians
                //  all of them inlines
//----------------------------------------------------------------------------------------
//      
//     -[*] Examples:
/*      
        local Point p1 = Point.create.sx(10).sy(20).sz(30).lock()
        local Point p2 = Point.create.sx(100).sz(1000).lock()
        local Point p3 = Point.create
        
        set p3.x = 3651
        set p3.y = p3.h
        set p3.z = p3.y
        
        call p3.unlock()                //= -1 lock count, won't be destroyed (don't do this)
        call p3.lock().lock().unlock()  //=  0 lock count, will  be destroyed (don't do this)
*/
/*
        local real h1 = Point.create.sx(1000).sy(1000).break().h    //= WORKS!!!
        local real h2 = Point.gh(1000, 1000)                        //= same as above
*/
//----------------------------------------------------------------------------------------
//========================================================================================
library Point
    
//========================================================================================
//  Configurables
//----------------------------------------------------------------------------------------
        globals
            private constant boolean AUTO_DESTROY = true
        endglobals
//========================================================================================
    
    struct Point extends array
        private static integer  c
        private        thistype r
        private        integer  u
        
        static if AUTO_DESTROY then
            private        thistype ad
            private static timer    t  = CreateTimer()
        endif
        
        private static location l = Location(0, 0)
        
        readonly real h
        private  real px
        private  real py
                 real z
        
        static method gh takes real lx, real ly returns real
            call MoveLocation(l, lx, ly)
            
            return GetLocationZ(l)
        endmethod
        
        method sx takes real nx returns thistype
            set px = nx
            set h  = gh(px, py)
            
            return this
        endmethod
        method sy takes real ny returns thistype
            set py = ny
            set h  = gh(px, py)
            
            return this
        endmethod
        method sz takes real nz returns thistype
            set z = nz
            
            return this
        endmethod
        
        method operator x takes nothing returns real
            return px
        endmethod
        method operator y takes nothing returns real
            return py
        endmethod
        method operator x= takes real nx returns nothing
            call sx(nx)
        endmethod
        method operator y= takes real ny returns nothing
            call sy(ny)
        endmethod
        
        private static method dist takes real dx, real dy returns real
            return SquareRoot(dx * dx + dy * dy)
        endmethod
        method distXY takes real lx, real ly returns real
            return dist(lx - px, ly - py)
        endmethod
        method distXYP takes thistype l returns real
            return distXY(l.x, l.y)
        endmethod
        method distXYZ takes real lx, real ly, real lz returns real
            return dist(distXY(lx, ly), (gh(lx, ly) + lz) - (h + z))
        endmethod
        method distXYZP takes thistype l returns real
            return dist(distXY(l.x, l.y), (l.h + l.z) - (h + z))
        endmethod
        
        private static method angle takes real dx, real dy returns real
            return Atan2(dy, dx)
        endmethod
        method angleXY takes real lx, real ly returns real
            return angle(lx - px, ly - py)
        endmethod
        method angleXYP takes thistype l returns real
            return angleXY(l.x, l.y)
        endmethod
        method angleXYZ takes real lx, real ly, real lz returns real
            return angle(distXY(lx, ly), (gh(lx, ly) + lz) - (h + z))
        endmethod
        method angleXYZP takes thistype l returns real
            return angle(distXY(l.x, l.y), (l.h + l.z) - (h + z))
        endmethod
        
        private method recycle takes nothing returns nothing
            if u == 0 then
                set r             = thistype(0).r
                set thistype(0).r = this
            endif
        endmethod
        
        method lock takes nothing returns thistype
            set u = u + 1
            
            return this
        endmethod
        method unlock takes nothing returns thistype
            set u = u - 1
            
            call recycle()
            
            return this
        endmethod
        method break takes nothing returns thistype
            set u = 0
            
            call recycle()
            
            return this
        endmethod
        
        static if AUTO_DESTROY then
            private static method autoDestroy takes nothing returns nothing
                local thistype this
                
                loop
                    set this = thistype(0).ad
                    exitwhen this == 0
                    
                    call this.recycle()
                    
                    set thistype(0).ad = this.ad
                endloop
            endmethod
            
            method lastUse takes nothing returns nothing
                set u = u - 1
                
                if thistype(0).ad == 0 then
                    call TimerStart(t, 0, false, function thistype.autoDestroy)
                endif
                
                set this.ad        = thistype(0).ad
                set thistype(0).ad = ad
            endmethod
        endif
        
        static method operator create takes nothing returns thistype
            local thistype this = thistype(0).r
            
            if this == 0 then
                set c    = c + 1
                set this = c
            else
                set thistype(0).r = this.r
            endif
            
            set this.px = 0
            set this.py = 0
            set this.z  = 0
            set this.h  = 0
            
            static if AUTO_DESTROY then
                if thistype(0).ad == 0 then
                    call TimerStart(t, 0, false, function thistype.autoDestroy)
                endif
                
                set this.ad        = thistype(0).ad
                set thistype(0).ad = ad
            endif
            
            return this
        endmethod
    endstruct
endlibrary
 
Last edited:
Top