GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2019-06-05 16:32:53

Juju
Member
Registered: 2015-10-01
Posts: 43

Rounded triangles

Scripts that I wrote to solve a problem on the GMC: https://forum.yoyogames.com/index.php?t … way.64010/

The former is fairly efficient, the latter can probably be improved.

/// draw_triangle_rounded()
/// @jujuadams 2019/05/06
/// 
/// @param x1
/// @param y1
/// @param x2
/// @param y2
/// @param x3
/// @param y3
/// @param radius
/// @param outline

#macro __draw_triangle_rounded__max_angle_step  10

var _x1      = argument0;
var _y1      = argument1;
var _x2      = argument2;
var _y2      = argument3;
var _x3      = argument4;
var _y3      = argument5;
var _radius  = argument6;
var _outline = argument7;

//Find the vectors from point to point
var _delta_x21 = _x2 - _x1;
var _delta_y21 = _y2 - _y1;
var _delta_x32 = _x3 - _x2;
var _delta_y32 = _y3 - _y2;
var _delta_x13 = _x1 - _x3;
var _delta_y13 = _y1 - _y3;

//If the winding number is greater than zero then the vertices have been defined counterclockwise
//Swapping p2 and p3 to corrects this
if (_delta_y21*_delta_x32 - _delta_y32*_delta_x21 > 0)
{
    var _temp_x2 = _x2;
    var _temp_y2 = _y2;
    _x2 = _x3;
    _y2 = _y3;
    _x3 = _temp_x2;
    _y3 = _temp_y2;
    
    _delta_x21 = _x2 - _x1;
    _delta_y21 = _y2 - _y1;
    _delta_x32 = _x3 - _x2;
    _delta_y32 = _y3 - _y2;
    _delta_x13 = _x1 - _x3;
    _delta_y13 = _y1 - _y3;
}

//Force the length of each vector to be the radius of the circle
var _f21 = _radius / sqrt(_delta_x21*_delta_x21 + _delta_y21*_delta_y21);
var _f32 = _radius / sqrt(_delta_x32*_delta_x32 + _delta_y32*_delta_y32);
var _f13 = _radius / sqrt(_delta_x13*_delta_x13 + _delta_y13*_delta_y13);
_delta_x21 *= _f21;
_delta_y21 *= _f21;
_delta_x32 *= _f32;
_delta_y32 *= _f32;
_delta_x13 *= _f13;
_delta_y13 *= _f13;

//Find the angle of each vector
var _angle_21 = darctan2(_delta_x21, _delta_y21);
var _angle_32 = darctan2(_delta_x32, _delta_y32);
var _angle_13 = darctan2(_delta_x13, _delta_y13);

//Here's a crafty trick to get a perpendicular line
// x' = x + dy
// y' = y - dx
//We add the direction vectors to their parent points
//By joining A->B for each pair of points we get the outer boundary of the triangle
var _ax21 = _x1 + _delta_y21;
var _ay21 = _y1 - _delta_x21;
var _bx21 = _x2 + _delta_y21;
var _by21 = _y2 - _delta_x21;

var _ax32 = _x2 + _delta_y32;
var _ay32 = _y2 - _delta_x32;
var _bx32 = _x3 + _delta_y32;
var _by32 = _y3 - _delta_x32;

var _ax13 = _x3 + _delta_y13;
var _ay13 = _y3 - _delta_x13;
var _bx13 = _x1 + _delta_y13;
var _by13 = _y1 - _delta_x13;

//Set up the correct kind of primitive
if (_outline)
{
    draw_primitive_begin(pr_linestrip);
}
else
{
    draw_primitive_begin(pr_trianglefan);
    //The first vertex of a triangle fan is the centre of the fan
    //We can choose any point inside the rounded triangle, but we choose the centre for convenience
    draw_vertex((_x1 + _x2 + _x3)/3, (_y1 + _y2 + _y3)/3);
}

//Iterate around the corner of point 1 to create a rounded edge
var _incr  = angle_difference(_angle_21, _angle_13);
var _steps = ceil(abs(_incr) / __draw_triangle_rounded__max_angle_step);
_incr /= _steps;
var _angle = _angle_13;
repeat(_steps)
{
    draw_vertex(_x1 + lengthdir_x(_radius, _angle), _y1 + lengthdir_y(_radius, _angle));
    _angle += _incr;
}

//Add the edge for the point pair P1->P2
draw_vertex(_ax21, _ay21);
draw_vertex(_bx21, _by21);

//Iterate around the corner of point 2...
_incr  = angle_difference(_angle_32, _angle_21);
_steps = ceil(abs(_incr) / __draw_triangle_rounded__max_angle_step);
_incr /= _steps;
_angle = _angle_21;
repeat(_steps)
{
    draw_vertex(_x2 + lengthdir_x(_radius, _angle), _y2 + lengthdir_y(_radius, _angle));
    _angle += _incr;
}

//Add the edge for the point pair P2->P3
draw_vertex(_ax32, _ay32);
draw_vertex(_bx32, _by32);

//Iterate around the corner of point 3...
_incr  = angle_difference(_angle_13, _angle_32);
_steps = ceil(abs(_incr) / __draw_triangle_rounded__max_angle_step);
_incr /= _steps;
_angle = _angle_32;
repeat(_steps)
{
    draw_vertex(_x3 + lengthdir_x(_radius, _angle), _y3 + lengthdir_y(_radius, _angle));
    _angle += _incr;
}

//Add the edge for the point pair P3->P1 to finish the shape
draw_vertex(_ax13, _ay13);
draw_vertex(_bx13, _by13);

//End the primitive and draw it
draw_primitive_end();
/// draw_triangle_rounded_inside()
/// @jujuadams 2019/05/06
/// 
/// @param x1
/// @param y1
/// @param x2
/// @param y2
/// @param x3
/// @param y3
/// @param radius
/// @param outline

#macro __draw_triangle_rounded_inside__max_angle_step  10

var _x1      = argument0;
var _y1      = argument1;
var _x2      = argument2;
var _y2      = argument3;
var _x3      = argument4;
var _y3      = argument5;
var _radius  = argument6;
var _outline = argument7;

//Find the vectors from point to point
var _delta_x21 = _x2 - _x1;
var _delta_y21 = _y2 - _y1;
var _delta_x32 = _x3 - _x2;
var _delta_y32 = _y3 - _y2;
var _delta_x13 = _x1 - _x3;
var _delta_y13 = _y1 - _y3;

//If the winding number is greater than zero then the vertices have been defined counterclockwise
//Swapping p2 and p3 to corrects this
if (_delta_y21*_delta_x32 - _delta_y32*_delta_x21 > 0)
{
    var _temp_x2 = _x2;
    var _temp_y2 = _y2;
    _x2 = _x3;
    _y2 = _y3;
    _x3 = _temp_x2;
    _y3 = _temp_y2;
    
    _delta_x21 = _x2 - _x1;
    _delta_y21 = _y2 - _y1;
    _delta_x32 = _x3 - _x2;
    _delta_y32 = _y3 - _y2;
    _delta_x13 = _x1 - _x3;
    _delta_y13 = _y1 - _y3;
}

//Force the length of each vector to be the radius of the circle
var _f21 = _radius / sqrt(_delta_x21*_delta_x21 + _delta_y21*_delta_y21);
var _f32 = _radius / sqrt(_delta_x32*_delta_x32 + _delta_y32*_delta_y32);
var _f13 = _radius / sqrt(_delta_x13*_delta_x13 + _delta_y13*_delta_y13);
_delta_x21 *= _f21;
_delta_y21 *= _f21;
_delta_x32 *= _f32;
_delta_y32 *= _f32;
_delta_x13 *= _f13;
_delta_y13 *= _f13;

//Find the angle of each vector
var _angle_21 = darctan2(-_delta_y21, _delta_x21);
var _angle_32 = darctan2(-_delta_y32, _delta_x32);
var _angle_13 = darctan2(-_delta_y13, _delta_x13);



var _angle = angle_difference(_angle_13, _angle_21)/2;

var _tan = dtan(_angle);
var _ax21 = _x1 + _tan*_delta_x21;
var _ay21 = _y1 + _tan*_delta_y21;
var _bx13 = _x1 - _tan*_delta_x13;
var _by13 = _y1 - _tan*_delta_y13;

var _dx = _delta_x21 - _delta_x13;
var _dy = _delta_y21 - _delta_y13;
var _d  = (_radius/dcos(_angle)) / sqrt(_dx*_dx + _dy*_dy);
_x1 += _d*_dx;
_y1 += _d*_dy;



var _angle = angle_difference(_angle_21, _angle_32)/2;

var _tan = dtan(_angle);
var _ax32 = _x2 + _tan*_delta_x32;
var _ay32 = _y2 + _tan*_delta_y32;
var _bx21 = _x2 - _tan*_delta_x21;
var _by21 = _y2 - _tan*_delta_y21;

var _dx = _delta_x32 - _delta_x21;
var _dy = _delta_y32 - _delta_y21;
var _d  = (_radius/dcos(_angle)) / sqrt(_dx*_dx + _dy*_dy);
_x2 += _d*_dx;
_y2 += _d*_dy;



var _angle = angle_difference(_angle_32, _angle_13)/2;

var _tan = dtan(_angle);
var _ax13 = _x3 + _tan*_delta_x13;
var _ay13 = _y3 + _tan*_delta_y13;
var _bx32 = _x3 - _tan*_delta_x32;
var _by32 = _y3 - _tan*_delta_y32;

var _dx = _delta_x13 - _delta_x32;
var _dy = _delta_y13 - _delta_y32;
var _d  = (_radius/dcos(_angle)) / sqrt(_dx*_dx + _dy*_dy);
_x3 += _d*_dx;
_y3 += _d*_dy;



//Set up the correct kind of primitive
if (_outline)
{
    draw_primitive_begin(pr_linestrip);
}
else
{
    draw_primitive_begin(pr_trianglefan);
    //The first vertex of a triangle fan is the centre of the fan
    //We can choose any point inside the rounded triangle, but we choose the centre for convenience
    draw_vertex((_x1 + _x2 + _x3)/3, (_y1 + _y2 + _y3)/3);
}

//Iterate around the corner of point 1 to create a rounded edge
var _angle = point_direction(_x1, _y1, _bx13, _by13);
var _incr  = angle_difference(point_direction(_x1, _y1, _ax21, _ay21), _angle);
var _steps = ceil(abs(_incr) / __draw_triangle_rounded_inside__max_angle_step);
_incr /= _steps;
repeat(_steps)
{
    draw_vertex(_x1 + lengthdir_x(_radius, _angle), _y1 + lengthdir_y(_radius, _angle));
    _angle += _incr;
}

//Add the edge for the point pair P1->P2
draw_vertex(_ax21, _ay21);
draw_vertex(_bx21, _by21);

//Iterate around the corner of point 2...
var _angle = point_direction(_x2, _y2, _bx21, _by21);
var _incr  = angle_difference(point_direction(_x2, _y2, _ax32, _ay32), _angle);
var _steps = ceil(abs(_incr) / __draw_triangle_rounded_inside__max_angle_step);
_incr /= _steps;
repeat(_steps)
{
    draw_vertex(_x2 + lengthdir_x(_radius, _angle), _y2 + lengthdir_y(_radius, _angle));
    _angle += _incr;
}

//Add the edge for the point pair P2->P3
draw_vertex(_ax32, _ay32);
draw_vertex(_bx32, _by32);

//Iterate around the corner of point 3...
var _angle = point_direction(_x3, _y3, _bx32, _by32);
var _incr  = angle_difference(point_direction(_x3, _y3, _ax13, _ay13), _angle);
var _steps = ceil(abs(_incr) / __draw_triangle_rounded_inside__max_angle_step);
_incr /= _steps;
repeat(_steps)
{
    draw_vertex(_x3 + lengthdir_x(_radius, _angle), _y3 + lengthdir_y(_radius, _angle));
    _angle += _incr;
}

//Add the edge for the point pair P3->P1 to finish the shape
draw_vertex(_ax13, _ay13);
draw_vertex(_bx13, _by13);

//End the primitive and draw it
draw_primitive_end();

Last edited by Juju (2019-06-05 16:33:17)

Offline

Board footer

Powered by FluxBB