gcc_const static std::pair<unsigned,unsigned> AngleToDonutVertices(Angle start, Angle end) { static const Angle epsilon = Angle::FullCircle() / 64 / 2; const Angle delta = end - start; if (delta >= Angle::FullCircle() - epsilon) /* full circle */ return std::make_pair(0, 64); const unsigned istart = AngleToDonutVertex(start); unsigned iend = AngleToDonutVertex(end); if (istart == iend && delta > epsilon) { if (end - start >= Angle::HalfCircle()) /* nearly full circle, round down the end */ iend = (iend - 2) & 0x3e; else /* slightly larger than epsilon: draw at least two indices */ iend = (iend + 2) & 0x3e; } return std::make_pair(istart, iend); }
gcc_const static std::pair<unsigned,unsigned> AngleToDonutVertices(Angle start, Angle end) { static constexpr Angle epsilon = Angle::FullCircle() / int(GLDonutVertices::CIRCLE_SIZE * 4u); const Angle delta = end - start; if (fabs(delta.AsDelta().Native()) <= epsilon.Native()) /* full circle */ return std::make_pair(0u, unsigned(GLDonutVertices::MAX_ANGLE)); const unsigned istart = AngleToDonutVertex(start); unsigned iend = AngleToDonutVertex(end); if (istart == iend && delta > epsilon) { if (end - start >= Angle::HalfCircle()) /* nearly full circle, round down the end */ iend = GLDonutVertices::PreviousAngle(iend); else /* slightly larger than epsilon: draw at least two indices */ iend = GLDonutVertices::NextAngle(iend); } return std::make_pair(istart, iend); }
void Canvas::annulus(int x, int y, unsigned small_radius, unsigned big_radius, Angle start, Angle end) { GLDonutVertices vertices(x, y, small_radius, big_radius); const unsigned istart = AngleToDonutVertex(start); const unsigned iend = AngleToDonutVertex(end); if (!brush.is_hollow()) { brush.set(); vertices.bind(); if (istart > iend) { glDrawArrays(GL_TRIANGLE_STRIP, istart, 64 - istart + 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, iend + 2); } else { glDrawArrays(GL_TRIANGLE_STRIP, istart, iend - istart + 2); } } if (pen_over_brush()) { pen.set(); if (istart != iend) { if (brush.is_hollow()) vertices.bind(); glDrawArrays(GL_LINE_STRIP, istart, 2); glDrawArrays(GL_LINE_STRIP, iend, 2); } const unsigned pstart = istart / 2; const unsigned pend = iend / 2; vertices.bind_inner_circle(); if (pstart < pend) { glDrawArrays(GL_LINE_STRIP, pstart, pend - pstart + 1); } else { glDrawArrays(GL_LINE_STRIP, pstart, 32 - pstart + 1); glDrawArrays(GL_LINE_STRIP, 0, pend + 1); } vertices.bind_outer_circle(); if (pstart < pend) { glDrawArrays(GL_LINE_STRIP, pstart, pend - pstart + 1); } else { glDrawArrays(GL_LINE_STRIP, pstart, 32 - pstart + 1); glDrawArrays(GL_LINE_STRIP, 0, pend + 1); } } }