# [JASS]Maths help creating complex shapes in warcraft Astroids, Lemniscates and more

#### duindain

Level 3
Hi Folks,

I was interested in creating a complex shape to make a moving unit that creates doodads around them look less boring then just a straight rectangle and I stumbled across this post and this tutorial

I managed to get Daelin's example working from the tutorial link to draw a Cuspoid ok in Jass he had an example in GUI that i converted ok.
He had the formulas for drawing some other complex objects but no implementations so I was trying to convert from my bad maths to working shapes.

You can see from the image that it has the text displayed correctly in the centre of the shape and the shape is correct too for an added bonus

JASS:
``````/*
deltoid (three cusps hypocycloid)
x=[2/3 cos? – 1/3 cos(2?)] * radius
y=[2/3 sin? + 1/3 sin(2?)] * radius
*/
function Draw_Cuspoid takes player owner, integer unitType, location centre, real radius returns nothing
local real twoThirds = 2.0 / 3.0
local real oneThird = 1.0 / 3.0
local real X = 0
local real Y = 0
local real angle = 0
local real centreX = GetLocationX(centre)
local real centreY = GetLocationY(centre)
local integer index = 1
local location tempPosition

call FloatTextAtPoint(centre, "Cuspoid")
loop
exitwhen index > 50
set angle = ((360 / 50) * I2R(index))
set X = (((twoThirds) * (Cos(angle))) - ((oneThird) * (Cos((2.00 * angle)))))
set X = (X * radius) + centreX
set Y = (((twoThirds) * (Sin(angle))) + ((oneThird) * (Sin((2.00 * angle)))))
set Y = (Y * radius) + centreY
set tempPosition = Location(X,Y)
call CreateUnit( owner, unitType, X, Y, AngleBetweenPoints(centre,tempPosition))
call RemoveLocation(tempPosition)
set index = index + 1
endloop
endfunction``````
I've managed to get Astroid, Cardiod and Nephroid to draw correctly but they centre in the wrong position and my Lemniscate is very wrong i think could anyone with some better Jass or mostly Maths skills take a look and tell me how to fix my code please

The shapes other than Lemniscate seem correct but they are way off centre position for some reason I probably have some sign around the wrong way or converted the formulas incorrectly.
i.e.

The shape is correct but the centre point is outside the shape entirely above the top right corner ( I also failed in the screenshot since its not even visible but trust me it exists heh )
JASS:
``````/*
Astroid (4 cusps hypocycloid)
x= x0 + radius * cos^3(angle) = x0 + radius * cos(angle) * cos(angle) * cos(angle)
y= y0 + radius * sin^3(angle) = y0 + radius * sin(angle) * sin(angle) * sin(angle)
*/
function Draw_Astroid takes player owner, integer unitType, location centre, real radius returns nothing
local real X = 0
local real Y = 0
local real x0 = 0
local real y0 = 0
local real angle = 0
local real centreX = GetLocationX(centre)
local real centreY = GetLocationY(centre)
local integer index = 1
local location tempPosition

call FloatTextAtPoint(centre, "Astroid")
loop
exitwhen index > 50
set angle = ((360 / 50) * I2R(index))
set X = (x0 + (radius * Pow(Cos(angle),3))) + centreX
set Y = (y0 + (radius * Pow(Sin(angle),3))) + centreY
if(index == 1) then
set x0 = X
set y0 = Y
else
set tempPosition = Location(X,Y)
call CreateUnit( owner, unitType, X, Y, AngleBetweenPoints(centre,tempPosition))
call RemoveLocation(tempPosition)
endif
set index = index + 1
endloop
endfunction``````
The formulas are above each function as how I interpreted them from the original tutorial from Daelin (tutorial same link as above)

I've attached my test map for this the main code is in the "map-specific custom script code" area
The Functions that I am hoping someone can check over are;
• Draw_Lemniscate
• Draw_Nephroid
• Draw_Cardiod
• Draw_Astroid
The Draw cuspoids trigger selects a center position and calls the functions at 1 second after the map starts

Additional bonus if anyone knows of a way to detect whether a point is inside any of these areas? I could use the angle i guess from the centre point to the point in question then increment out from the centre point and if i hit the desired point before one of the dummies its inside otherwise outside, does that sound feasible?

#### Attachments

• ExampleDestructableCreationMapv2.w3x
41.9 KB · Views: 99
Last edited:

#### PurgeandFire

Level 44
JASS:
``set angle = ((360 / 50) * I2R(index)) * bj_DEGTORAD``
The reason why Daelin could use degrees in GUI is because the GUI functions actually refer to CosBJ and SinBJ, which take degrees instead. (they convert it using *bj_DEGTORAD as I did above)

#### gorillabull

Level 16
these are complex shapes? >.>[] its not even 3d

#### duindain

Level 3
Partially working now

Ok I've changed them to convert from degrees to radians as suggested

I've also drawn them at centered over 0,0 rather than the actual coordinates and translated to the correct position when creating the units at least that was my intention by taking the centreX and centreY out of the formula

JASS:
``````function Draw_Nephroid takes player owner, integer unitType, location centre, real radius returns nothing
local real X = 0
local real Y = 0
local real x0 = 0
local real y0 = 0
local real angle = 0
local real centreX = GetLocationX(centre)
local real centreY = GetLocationY(centre)
local integer index = 1
local location tempPosition

call FloatTextAtPoint(centre, "Nephroid")
loop
exitwhen index > 75
//I dont understand this angle if i set it to the correct value 360/75 it masses the units to closely together if 10 perfect if 15 not so bad but a bit patchy
set angle = ((10) * I2R(index)) * bj_DEGTORAD
set X = (x0 + radius * (3 * Cos(angle) - Cos(3 * angle)))
set Y = (y0 + radius * (3 * Sin(angle) - Sin(3 * angle)))
if(index == 1) then
set x0 = X
set y0 = Y
else
set tempPosition = Location(X,Y)
call CreateUnit( owner, unitType, X + centreX, Y + centreY, AngleBetweenPoints(centre,tempPosition))
call RemoveLocation(tempPosition)
endif
set index = index + 1
endloop
endfunction``````
I think this is probably correct now? the text isn't centered inside the object but starts on a corner of it at least all the other shapes are similar except for the original example from Daelin which is still dead center for the text

JASS:
``````/*
Lemniscate
x=x0 + radius * cos(angle) / 1 + sin^2(angle)
y=y0 + radius * sin(angle) * cos(angle) / 1 + sin^2(angle)
*/
function Draw_Lemniscate takes player owner, integer unitType, location centre, real radius returns nothing
local real X = 0
local real Y = 0
local real x0 = 0
local real y0 = 0
local real angle = 0
local real centreX = GetLocationX(centre)
local real centreY = GetLocationY(centre)
local integer index = 1
local location tempPosition

call FloatTextAtPoint(centre, "Lemniscate")
loop
exitwhen index > 100
set angle = ((360 / 100) * I2R(index)) * bj_DEGTORAD
set X = x0 + (((Cos(angle) / 1 + Pow(Sin(angle),2)) * radius) )
set Y = y0 + (((Sin(angle) * Cos(angle) / 1 + Pow(Sin(angle),2)) * radius))
if(index == 1) then
set x0 = X
set y0 = Y
else
set tempPosition = Location(X,Y)
call CreateUnit( owner, unitType, X + centreX, Y + centreY, AngleBetweenPoints(centre,tempPosition))
call RemoveLocation(tempPosition)
endif
set index = index + 1
endloop
endfunction``````
Complex Shape: A shape made of a combination of 2 or more shapes.

Also known as a compound figure or compound shape.
It might be bending the definition slightly but you could draw some of these shapes from combinations of others and they are definitely not simple shapes

Thank you for your reply PurgeandFire111 certainly fixed most of the issues in one hit

Ive reuploaded the current code if anyone needs to see the shapes its currently making

#### PurgeandFire

Level 44
It is most likely an issue of order of operations. This is the code that Daelin posted:
JASS:
``````x=x0+a*cosφ / 1+sin^2(φ)
y=y0+a*sinφ*cosφ/1+sin^2(φ)``````
The problem is that if defined that way, it will look like this (where b is x0):

Which of course, isn't the way Daelin means it to be. So I assume that is where the problem is. Yours is:
x = x0 + ( (cos φ / 1) + sin2(φ) ) * a
Which is probably not the right way. We can assume 1 and sin should be added because ([cos x] / 1) would just be (cos x), so there would be no point in having the 1 there otherwise.

Since I can't actually test them myself, I would recommend that you play with the code a bit with different combinations to see which one works. For example:
• x = x0 + (a * cos φ) / (1 + sin2(φ))
y = y0 + (a * sin φ * cos φ) / (1 + sin2(φ))
.
• x = (x0 + a * cos φ ) / (1 + sin2(φ))
y = (y0 + a * sin φ * cos φ) / (1 + sin2(φ))

Hopefully I didn't read it wrong or anything. If you need any help with implementation or whatever you can ask in this thread.

#### Attachments

• MSP30161a3f2ghhh225ic4h00006992idci7e63i1eg.gif
1 KB · Views: 217

#### duindain

Level 3
Thank you for the reply again
Definitely narrowing down the issues the /1 being useless in the old position makes sense heh I've tried your suggestions one looks very promising but maybe i have to keep the loop going past 360 degrees or something? it seems like it almost completes the shape 1 corner missing?

The first formula
JASS:
``````set X = x0 + (radius * Cos(angle)) / (1 + Pow(Sin(angle),2))
set Y = y0 + (radius * Sin(angle) * Cos(angle)) / (1 + Pow(Sin(angle),2))``````
Produces this

The second
JASS:
``````set X = (x0 + radius * Cos(angle)) / (1 + Pow(Sin(angle),2))
set Y = (y0 + radius * Sin(angle) * Cos(angle)) / (1 + Pow(Sin(angle),2))``````
produces this

According to a quick google search the first one is definitely the correct shape do you have any ideas why it wouldn't be completing it though?

#### PurgeandFire

Level 44
Haha, awesome. Tbh, both look pretty cool lol.

But anyway, it may either be a problem with the code or hitting the op limit. To verify that it is not the latter, add a debug message (`call BJDebugMsg(I2S(index))`) before `endloop` and make sure that the index reaches 100. If it doesn't, then there is your problem and we'll fix it from there.

If not, then we know it is something with the code and then we'll figure out where to go.

#### gorillabull

Level 16
JASS:
``````set X = (x0 + radius * Cos(angle)) / (1 + Pow(Sin(angle),2))
set Y = (y0 + radius * Sin(angle) * Cos(angle)) / (1 + Pow(Sin(angle),2))``````

what is this x0 and y0 it should be xθ and yθ or in your case "angle"

for the above shapes that you are creating, its possible that you are hitting some number restriction such as a<360 withing the code

#### PurgeandFire

Level 44
x0 refers to x0 (x sub zero). In this case, it just refers to some constant value that will position the graph. For x, x0 will translate the graph either to the left (negative) or right (positive). For y, y0 will translate the graph either up (positive) or down (negative).

#### duindain

Level 3
Heh I had no idea x0 and y0 was to align it in the quadrants does that mean it should be a value between -1 and 1?

I thought it meant the first value of x and y so I was setting it to that on index == 1

I've tried a few things from your suggestions I tried commenting out a few of the other shapes in case the map was running out of units or something and I tried the debug message unfortunately no change the loop did get to 100 and commenting out the others didn't help

The angle value in radians starts at 0.052 at index 1 in the loop and ends at 5.236 at index 100
In degrees thats 3 at index 1 and 300 at index 100

Ahhh brain wave heh

Ok I tested it the angle was being automatically changed to int variables instead of reals

changed
JASS:
``set angle = ((360 / 100) * I2R(index)) * bj_DEGTORAD``
to
JASS:
``set angle = ((360.0 / 100.0) * I2R(index)) * bj_DEGTORAD``
and its not clamping the values anymore

Ok if i set the x0 and y0 to both 0 it works fine and the text is centered at last heh

Thanks everyone specifically PurgeandFire111 Ill finish up a function for checking if a point is within the shape then maybe post this in the code section if anyones interested in making mathematical shapes at some point

Last edited:

#### PurgeandFire

Level 44
I didn't mean aligning in quadrants, I just meant that it offsets by x or y coordinates. Just a horizontal or vertical shift. So if it is "x = 500 + radius*Cos(angle)...." or w/e, it will shift the graph 500 units to the right of where "x = radius*Cos(angle)..." alone would be.

But I'm glad to hear that it works.

Replies
5
Views
556
Replies
13
Views
614
Replies
30
Views
1K
Replies
5
Views
545
Replies
27
Views
2K