GML Check if a shape is convex/concave & get an angle between three points

acidemic

Member
GM Version: GM:S 1.x | GMS 2.x
Target Platform: All
Download: N/A

Summary:
Use following code to find out whether a shape is convex or concave. It can be placed in "User" action of an object and run on request. Shape coordinates must be supplied as DS List in a 'list' variable. End result is stored into 'shape_convex' variable as 'true' (1) if shape is convex or 'false' (0) if shape is concave.

Tutorial:
In order to find out whether a shape is convex or concave we must find out a total sum of all shape angles. In a convex shape the sum of all vertex angles will be 180(n-2) degrees. For example if a shape has 5 vertexes, then 180(5-2)=540. If the total sum of all degrees is less, then the shape is concave!

Code:
/// @description Check if shape is Convex
var shape_angles = 0;
shape_convex = false

var shape_list = list;   // DS_LIST with shape coordinates in following format: x0,y0,x1,y1,x2,y2,x3,y3,x4,y4,x5,y5.....etc.

var list_size = ds_list_size(shape_list); // Getting the total size of a ds_list

if (list_size > 3)
{
   for (i=0; i<list_size-5; i+=2)
   {
       shape_angles += angle_get(shape_list[| i], shape_list[| i+1], shape_list[| i+2], shape_list[| i+3], shape_list[| i+4], shape_list[| i+5]);
   }
   shape_angles += angle_get(shape_list[| list_size-2], shape_list[| list_size-1], shape_list[| 0], shape_list[| 1],shape_list[| 2], shape_list[| 3]);
   shape_angles += angle_get(shape_list[| list_size-4], shape_list[| list_size-3], shape_list[| list_size-2], shape_list[| list_size-1], shape_list[| 0], shape_list[| 1]);

   if(abs(180*((list_size/2)-2) - shape_angles) < 0.001)
   {
      shape_convex = true;
   }
   else
   {
      shape_convex = false;
   }
}
else
{
   shape_convex = true;
}
angle_get() script calculates inner angle between three points.
Code:
/// @description angle_get(x1,y1,x2,y2,x3,y3);
/// @function angle_get
/// script to get angle between two lines
/// @param0 - Line1 x
/// @param1 - Line1 y
/// @param2 - Common x
/// @param3 - Common y
/// @param4 - line2 x
/// @param5 - Line2 y

var dx21 = argument0-argument2;
var dx31 = argument4-argument2;
var dy21 = argument1-argument3;
var dy31 = argument5-argument3;
var m12 = sqrt( dx21*dx21 + dy21*dy21 );
var m13 = sqrt( dx31*dx31 + dy31*dy31 );
return radtodeg(arccos( (dx21*dx31 + dy21*dy31) / (m12 * m13) ));
Please let me know if this was useful for you.
 
Last edited:
Top