Snippet Angles: Cone

Dirac

22710180
Reaction score
147
JASS:
//Determines if the angle "a" is inside a cone of facing "b" with opening "o"
function Cone takes real a, real b, real o returns boolean
    return Cos(a-b)>=Cos(o)
endfunction


Example:
Lets say there's a cone facing 0 degrees with opening 70, and we want to know if the angle 45 is inside of it
Dirac_cone.jpg

[ljass]Cone(45,0,70)[/ljass] returns true because 45 happens to be inside that cone

Explanation:
[ljass]Cos(45-0) - > Cos(45) == 0.707[/ljass]
[ljass]Cos(70) == 0.342[/ljass]
The result of the Cosine of the difference of both angles is greater than the opening's Cosine, the function returns true.
"Cos" is a function that evaluates the position of an angle according to it's image in the X axis.
So now imagine that the cone's aperture is 0, and Cos(0) == 1, and that Cos can't go beyond 1 and can't got below -1... And the function evaluates if the difference is greater than or equal to the opening's cosine, that means that because there's no greater value than 1, the only possibility to return true is being equal to 1.
Now imagine that the cone's opening is 60, and Cos(60) == 0.5, also that Cos(60) == Cos(360-60) it has a better chance to be over 0.5. The greater the cone operture the greater the chance for the difference of the angles to be greater to it, thats because 0 opening means 1 and 180 aperture means -1.

Please credit if used.
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Dirac, please use a "common" terminology and/or provide definitions for the terms you use.

I mean:

Isn't a cone a 3d geometric shape? Perhaps a circular sector might be better?

What's an aperture?

'//Determines if the angle "a" is inside a cone of facing "b" with aperture "o"'
'a cone of facing "b"' what does that mean?

And why not give an example or two of how to use this, even if the "logic" is not understood the examples could be used nontheless right? =)
 

NoobImbaPro

You can change this now in User CP.
Reaction score
60
@Sgqvur
Aperture: translated into my language and says "opening" so it must be referred to the angle.
The formula checks if A angle is inside B angle +-O degrees.

Example: Dota: Hero Riki: Backstab ability.
JASS:

real angle = Angle from attacking unit to attacked unit
return Cone(angle, GetUnitFacing(GetTriggerUnit()), 80)

if true then apply the bonus damage

@Dirac
Nice job m8 you made tasks easier
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
NoobImbaPro: The formula checks if A angle is inside B angle +-O degrees.

Well, that I can understand unlike '//Determines if the angle "a" is inside a cone of facing "b" with aperture "o"'

PS: the trig natives work with radians, GetUnitFacing works with degrees.
 

Dirac

22710180
Reaction score
147
@Sgqvur
With aperture I meant opening, Idk why I got confused, I'll fix it right away.
I think Cone is an appropriate name. At least in warcraft.
And the picture shown is an example, not the logic.
The cone's facing angle is from where the opening angle begins...
Are you asking because you don't know or because you want me to make it more clear?

@NoomImbaPro
In the examples shown i'm using degrees, but that was only to ease the understanding, it works with radians

Thanks for the feedback
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
>Are you asking because you don't know or because you want me to make it more clear?
Both =), but I think I get it now even the example (picture), it demonstraites what you've written "Cone(45,0,70)" but I think it would be better if it was even more "obvious":
Dirac_cone.jpg


And I think what NoobImbaPro gave as an example could also be put in a picture, something like this:
is_behind.png

>I think Cone is an appropriate name. At least in warcraft.
Really? What makes you write that? It looks/reads to me like a constructor for the 3d geometric shape =), although it takes 3 reals so...but I still think it's kinda confusing.
 

Laiev

Hey Listen!!
Reaction score
188
Want the simplest way to explain what 'cone' means here? Breath of Fire (base skill of Warcraft), you're done.
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
>Want the simplest way to explain what 'cone' means here? Breath of Fire (base skill of Warcraft), you're done.

Wait... isn't Breath of Fire an isosceles trapezoid? =)
 

AgentChaos

New Member
Reaction score
1
This is my revised code,
JASS:
// The code is as Fire Breath
    function AngleDifference takes real angle, real angle1, real angle2 returns boolean
        local real x
        set angle = ModuloReal(angle,360)
        set angle1 = ModuloReal(angle1,360)
        set angle2 = ModuloReal(angle2,360)
        if (angle1>angle2) then
            set x=angle1
            set angle1=angle2
            set angle2=x
        endif
        if (angle2-angle1)>(angle1 - (angle2-360)) then
            set angle2=angle2-360
            if angle > 180 then
                set angle=angle-360
            endif
            return angle>=angle2 and angle<=angle1
        endif
        return (angle>=angle1) and (angle<=angle2)
    endfunction
    
function GroupEnumUnitsInCone takes group whichGroup,real TargAngle ,real Width,real Distance,real x1,real y1 returns nothing
    local group g =  NewGroup()
    local real AngleAdjust = Atan((Width/2)/Distance)*57.295827
    local real AdjustA= TargAngle-AngleAdjust
    local real AdjustB= TargAngle+AngleAdjust
    local real angle = 0
    local unit v
    call GroupEnumUnitsInRange(g,x1, y1, Distance,BOOLEXPR_TRUE)
    loop
    set v=FirstOfGroup(g)
    exitwhen v==null
        call GroupRemoveUnit(g,v)
        set angle = 57.295827*GetUnitAngleXY(x1, y1, GetUnitX(v), GetUnitY(v))
        if AngleDifference(angle, AdjustA, AdjustB) then
            call GroupAddUnit(whichGroup,v)
        endif
    endloop
    call ReleaseGroup(g)
    set g = null
endfunction

  private function OnSpell takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local unit v
   
        local real x1 = GetUnitX(u)
        local real y1 = GetUnitY(u)
        local real tx = GetSpellTargetX()
        local real ty = GetSpellTargetY()
        local real TargAngle = GetUnitAngleXY(x1, y1, tx, ty)*57.295827
        local real Distance = 700
        local real Width = 475
        local group TotalGroup = NewGroup()
   

        call GroupEnumUnitsInCone2(TotalGroup,TargAngle,Distance ,Width,x1,y1)
        loop
            set v = FirstOfGroup(TotalGroup)
            exitwhen v == null
   
            if IsUnitDamgeMatch(v,u) then //Filterfunction
                // ...
                // damage the unit
                // ...
            endif
            call GroupRemoveUnit(TotalGroup,v)
        endloop
    
        set u = null


JASS:
//This code is base on Cone formula
    function GroupEnumUnitsInSector2 takes group whichGroup,unit u,real angle,real facing,real radius returns nothing
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real face = Deg2Rad(facing*0.5)
        local unit v
        local group g = CreateGroup()
        call GroupEnumUnitsInRange(g,x,y,radius,null)
        loop
            set v = FirstOfGroup(g)
            exitwhen v == null
            call GroupRemoveUnit(g,v)
            if Cone(Atan2(GetUnitY(v)-y,GetUnitX(v)-x),angle,face ) and v!=u then
                 call GroupAddUnit(whichGroup, v)
            endif
        endloop
        call DestroyGroup(g)
        set g = null
        set v = null
        set u = null
    endfunction

JASS:
//Pieces of code inspection unit-oriented function is basically for the assassin skills
    function GetUnitAngle takes unit a, unit b returns real // - Angle between units
	return Atan2(GetUnitY(b) - GetUnitY(a), GetUnitX(b)- GetUnitX(a))
    endfunction
    function CheckUnitPosition takes unit b, unit a, real frontL, real frontR, real backL, real backR returns integer//position of b from a
        local real angle = Rad2Deg(GetUnitAngle(a,b))
        if angle >= 0 then
            set angle = angle-GetUnitFacing(a)
        else
            set angle = angle+360-GetUnitFacing(a)
        endif
        if angle < 0 then
            set angle = angle+360
        endif
        if angle <= frontL or angle >= frontR then
            return 1
        endif
        if angle >= backL and angle <= backR then
            return 2
        endif
        if angle > backR and angle < frontR then
            return 3
        endif
        if angle > frontL and angle < backL then
            return 4
        endif
        return 0
    endfunction

    function IsUnitInFront takes unit b, unit a returns boolean//b = infront, a = source
        return CheckUnitPosition(b,a,35,325,135,225) == 1
    endfunction

    function IsUnitBehind takes unit b, unit a returns boolean //b = behide, a = source
        return CheckUnitPosition(b,a,30,330,135,225) == 2
    endfunction

    function IsUnitAtSideRight takes unit b, unit a returns boolean//b = atside, a = source
        return CheckUnitPosition(b,a,30,330,135,225) == 3
    endfunction

    function IsUnitAtSideLeft takes unit b, unit a returns boolean//b = atside, a = source
        return CheckUnitPosition(b,a,30,330,135,225) == 4
    endfunction
     
    private function GetAngleDifference takes real a1, real a2 returns real
        local real x
        set a1=ModuloReal(a1,360)
        set a2=ModuloReal(a2,360)
        if a1>a2 then
            set x=a1
            set a1=a2
            set a2=x
        endif
        set x=a2-360
        if a2-a1 > a1-x then
            set a2=x
        endif
        return RAbsBJ(a1-a2)
    endfunction
    function IsUnitInBehind1 takes unit u, unit t returns boolean
        local real angle= GetAngleDifference(GetUnitFacing(t),bj_RADTODEG *GetUnitAngle(u,t))
        return  angle <= 90 
    endfunction
    function IsUnitInBehind2 takes unit u, unit t returns boolean
        return  RAbsBJ(( GetUnitFacing(u) - GetUnitFacing(t) )) <= 90.00
    endfunction
    function IsUnitInBehind3 takes unit u, unit t returns boolean
        local real d=RAbsBJ(GetUnitFacing(t)-GetUnitFacing(u))
        if d>180 then
            set d=360-d
        endif
        return d<=90
    endfunction
    function IsUnitInBehind4 takes unit a, unit b returns boolean
        return Cone(Atan2(GetUnitY(b)-GetUnitY(a),GetUnitX(b)-GetUnitX(a)),GetUnitFacing(b)*bj_DEGTORAD,90*bj_DEGTORAD)
    endfunction
 

Dirac

22710180
Reaction score
147
I designed this formula to avoid that math overload you're using.
I don't know what a sector is, nor do I know what most of the other functions are supposed to do. But they all look related to calculate if a unit is inside a cone (or am I wrong?)
Anyways picking units inside a cone with this formula should be as easy as this:
JASS:
//This function is fired when a unit casts a somewhat fire breath spell
function onCast takes nothing returns nothing
	local unit u = GetTriggerUnit()
	local real x = GetUnitX(u)
	local real y = GetUnitY(u)
	local real a = Atan2(GetSpellTargetY()-y,GetSpellTargetX()-x)
	local unit e
	call GroupEnumUnitsInRange(bj_lastCreatedGroup,x,y,300,null)
	loop
		set e = FirstOfGroup(bj_lastCreatedGroup)
		exitwhen e == null
		//   angle between caster and target , cast angle , 45 degrees
		if Cone(Atan2(GetUnitY(e)-y,GetUnitX(e)-x),a,bj_PI/4) then
			// ...
			// damage the unit
			// ...
		endif
		call GroupRemoveUnit(bj_lastCreatedGroup,e)
	endloop
	set e = null
	set u = null
endfunction
 

Dirac

22710180
Reaction score
147
No because (as it seems to me) your CheckUntiPosition doesn't quite do that.
It's basically dividing the whole angle spectrum into 4 pieces and returning an integer that determines in which area it's inside?
That makes absolutely no sense to me
Controlling the cone opening results very hard, it has a lot of overhead, and bugs with angles over 360 and below 0.
Delete that ASAP and use mine
 

AgentChaos

New Member
Reaction score
1
JASS:
    function GroupEnumUnitsInSector2 takes group whichGroup,unit u,real angle,real facing,real radius returns nothing
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real face = Deg2Rad(facing*0.5)
        local unit v
        local group g = CreateGroup()
        call GroupEnumUnitsInRange(g,x,y,radius,null)
        loop
            set v = FirstOfGroup(g)
            exitwhen v == null
            call GroupRemoveUnit(g,v)
            if Cone(Atan2(GetUnitY(v)-y,GetUnitX(v)-x),angle,face ) and v!=u then
                 call GroupAddUnit(whichGroup, v)
            endif
        endloop
        call DestroyGroup(g)
        set g = null
        set v = null
        set u = null
    endfunction
    call GroupEnumUnitsInSector2(group,caster,GetUnitFacing(caster)*bj_DEGTORAD,45,450)

I test it,It's work,OK,I will use your formula.
that means continue use CheckUntiPosition function?
JASS:
    function AbsReal takes real a returns real
        return SquareRoot(a*a)
    endfunction
    function AngleConv takes real angle returns real
        local integer factor=0
        if angle>=360 then
            set factor=R2I(angle/360)
            return angle-360*factor
        elseif angle<0 then
            set factor=R2I(AbsReal(angle)/360)
            return angle+360*(factor+1)
        endif
        return angle
    endfunction
  function FixAngle takes real ang returns real
        local real angle = ang
        if angle<0 then
            set angle=angle+6.28319
        elseif angle>6.28319 then
            set angle=angle-6.28319
        endif
        return angle
    endfunction
// angles over 360 and below 0 fix
 

Dirac

22710180
Reaction score
147
With Cone you don't have to fix angles over 360 or below 0, I guess thats another pro on to why use it
 

AgentChaos

New Member
Reaction score
1
JASS:
  function GetUnitAngle takes unit a, unit b returns real // - Angle between units
        return Atan2(GetUnitY(b) - GetUnitY(a), GetUnitX(b)- GetUnitX(a))
    endfunction
        
    private function GetAngleDifference takes real a1, real a2 returns real
        local real x
        set a1=ModuloReal(a1,360)
        set a2=ModuloReal(a2,360)
        if a1>a2 then
            set x=a1
            set a1=a2
            set a2=x
        endif
        set x=a2-360
        if a2-a1 > a1-x then
            set a2=x
        endif
        return RAbsBJ(a1-a2)
    endfunction
    function IsUnitInBehind takes unit u, unit t returns boolean
        local real angle= GetAngleDifference(GetUnitFacing(t),bj_RADTODEG *GetUnitAngle(u,t))
        return  angle <= 90 
    endfunction
    function IsUnitInBehind2 takes unit u, unit t returns boolean
        return  RAbsBJ(( GetUnitFacing(u) - GetUnitFacing(t) )) <= 90.00
    endfunction
    function IsUnitInBehind3 takes unit u, unit t returns boolean
        local real d=RAbsBJ(GetUnitFacing(t)-GetUnitFacing(u))
        if d>180 then
            set d=360-d
        endif
        return d<=90
    endfunction

s
 

Dirac

22710180
Reaction score
147
I take from your posts that you barely speak english and I'm starting to wonder if you understand anything of what i'm saying.
It would be better for all of us if you used google translate and try to explain what are you trying to do here.
 

AgentChaos

New Member
Reaction score
1
I am very sorry, because I do not agree with some of your views,I have updated some new functions, the cone function can not be used for the detection unit facing for the function is used to Assassin skills, CheckUnitPosition function Assassin skills can use the extended functions
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top