-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
draw_arc #5
Comments
Note sure about this one, as there might be varying arc-drawing needs? Like, someone would want their arc to have smaller or greater precisions, yet another person would want to draw their arc with varying thickness, yet another would use shaders to draw their arcs... |
Precision and width could be function parameters, or members of the more advanced "draw_arc_ext". Doesn't help people who want to draw things with shaders, but it's a step towards a solution. |
I'm going to leave this one up for discussion, some more research is needed about how people handle their arc-drawing needs. Not saying "no", but with different valid ways to handle it - not just at the implementation level, but at the expected behaviour as well - it might be wise to explore how different people approach arc-drawing before reserving Note: It might become less of a concern once Prefabs arrive and the user will be able to override Prefab functions with same named project-specific counterpart. If that will be the case, I won't object to adding some well-liked |
My proposal would be, that for precision we could use default GM value. However I just found out, that there's no way to read it back, so I've made a feature request in advance: YoYoGames/GameMaker-Bugs#3002 |
btw. on GMLscripts.com there are functions for: |
Good point about covering different functions - we might actually want to look into which of these functions we want covered. |
Yes, setting precision as last param is a good idea, as it's easy to either remove it, or replace with |
I think the version of Also, I think I'd still like to keep the
I'd like the implementation to match the precision of the whole circle (e.g. given precision of 24, it would draw 4 segments' worth for 60 degrees angle difference, as opposed to 24 regardless of the angle), like what I think is done in the GMLscripts.com Is everyone on board of that? If that's alright, I might try and draft some implementation, or someone else can provide one. Once we have the signatures and the precision handling settled, I think it'll be ready for name voting and eventual addition to the toolbox. |
I'm not sure if we could use GM In proposed case (so covering GM native circle), it still need to be decided if it will be rounded, ceiled of floored in case of In HTML5, default precision seems to be... |
I imagine the arc would be a cut-out of a base circle. So e.g. if the precision is 24 - with each segment spanning 15 degrees worth - then given angles from 5deg to 128deg it would draw:
Here is a little graphic showing the general idea, with the green angle range "clipping" to an arc what would otherwise be the 8-precise circle: The most annoying part would be calculating segments intersections for the initial and ending segments, the rest should be pretty straightforward I think. --- EDIT --- |
A picture is worth a thousand words - it perfectly describes what approach will be used, and in that case for sure it could benefit from |
Here is the implementation I came up with; it uses only 3 static functions for additional processing. 😛 /// @func draw_arc(x,y,radius,anglefrom,angleto,[precision])
/// @desc Draws a circular line around the given center, with the given radius and between given angles.
/// @arg {Real} x The x coordinate of the arc center.
/// @arg {Real} y The y coordinate of the arc center.
/// @arg {Real} radius The radius of the arc around the center.
/// @arg {Real} anglefrom The starting angle of the arc.
/// @arg {Real} angleto The ending angle of the arc.
/// @arg {Real} [precision] The precision of the circle the arc is a part of; 24 by default.
function draw_arc(_x, _y, _radius, _anglefrom, _angleto, _precision = 24) {
// static functions
static get_segment_position = function(_angle, _segment_angle) {
_angle = _angle - floor(_angle / _segment_angle) * _segment_angle;
if (_angle == 0)
return 0;
var _yfrom = dsin(_angle);
var _yto = dsin(_angle - _segment_angle);
return _yfrom / (_yfrom - _yto);
}
static draw_circle_vertex = function(_x, _y, _radius, _angle) {
draw_vertex(_x + lengthdir_x(_radius, _angle), _y + lengthdir_y(_radius, _angle));
}
static draw_midsegment_vertex = function(_x, _y, _radius, _angle1, _angle2, _amount) {
var _x1 = _x + lengthdir_x(_radius, _angle1);
var _y1 = _y + lengthdir_y(_radius, _angle1);
var _x2 = _x + lengthdir_x(_radius, _angle2);
var _y2 = _y + lengthdir_y(_radius, _angle2);
draw_vertex(lerp(_x1, _x2, _amount), lerp(_y1, _y2, _amount));
}
// normalise the angles for easier processing
var _anglediff = _angleto - _anglefrom;
if (_anglediff == 0)
return;
if (_anglediff < 0) {
_anglediff = -_anglediff;
_anglefrom = _angleto;
_angleto = _anglefrom + _anglediff;
}
// draw a full circle if the arc covers more than 360 degrees
if (_anglediff >= 360) {
draw_primitive_begin(pr_linestrip);
for (var i = 0; i < _precision; i++) {
draw_circle_vertex(_x, _y, _radius, i * 360 / _precision);
}
draw_circle_vertex(_x, _y, _radius, 0);
draw_primitive_end();
return;
}
// draw the actual arc
var _segment_angle = 360 / _precision;
var _start_amount = get_segment_position(_anglefrom, _segment_angle);
var _end_amount = get_segment_position(_angleto, _segment_angle);
var _start_index = floor(_anglefrom / _segment_angle);
var _end_index = floor(_angleto / _segment_angle);
draw_primitive_begin(pr_linestrip);
if (_start_amount == 0) {
draw_circle_vertex(_x, _y, _radius, _anglefrom);
} else {
draw_midsegment_vertex(_x, _y, _radius, _start_index * 360 / _precision, (_start_index + 1) * 360 / _precision, _start_amount);
}
for (var i = _start_index + 1; i <= _end_index; i++) {
draw_circle_vertex(_x, _y, _radius, i * 360 / _precision);
}
if (_end_amount > 0) {
draw_midsegment_vertex(_x, _y, _radius, _end_index * 360 / _precision, (_end_index + 1) * 360 / _precision, _end_amount);
}
draw_primitive_end();
} |
Implemented and merged! After some discussions here and there I settled on the naming of:
|
draw_arc
behaves likedraw_circle
but only draws part of the outline of the circle, from a given starting angle to ending angle.Possible point of expansion: Supporting a "filled" version as well, which draws either a pie slice or a segment rather than just the outline.
The text was updated successfully, but these errors were encountered: