File indexing completed on 2025-02-02 04:11:07

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "polystar.hpp"
0008 #include "math/math.hpp"
0009 
0010 
0011 GLAXNIMATE_OBJECT_IMPL(glaxnimate::model::PolyStar)
0012 
0013 glaxnimate::math::bezier::Bezier glaxnimate::model::PolyStar::to_bezier(model::FrameTime t) const
0014 {
0015     return draw(
0016         type.get(),
0017         position.get_at(t),
0018         inner_radius.get_at(t),
0019         outer_radius.get_at(t),
0020         math::deg2rad(angle.get_at(t)),
0021         points.get_at(t),
0022         inner_roundness.get_at(t),
0023         outer_roundness.get_at(t),
0024         reversed.get()
0025     );
0026 }
0027 
0028 glaxnimate::math::bezier::Bezier glaxnimate::model::PolyStar::draw(
0029     model::PolyStar::StarType type, const QPointF& pos,
0030     float radius_inner, float radius_outer, float angle_radians, int p,
0031     float round_inner, float round_outer,
0032     bool reverse
0033 )
0034 {
0035     math::bezier::Bezier bezier;
0036     bezier.close();
0037 
0038     qreal direction = reverse ? -1 : 1;
0039     qreal halfd = math::pi / p * direction;
0040     qreal tangent_len_outer = round_outer * (math::tau * radius_outer) / (p * 4) * direction;
0041     qreal tangent_len_inner = round_inner * (math::tau * radius_inner) / (p * 4) * direction;
0042 
0043     for ( int i = 0; i < p; i++ )
0044     {
0045         qreal main_angle = -math::pi / 2 + angle_radians + i * halfd * 2;
0046         qreal dx = radius_outer * math::cos(main_angle);
0047         qreal dy = radius_outer * math::sin(main_angle);
0048 
0049         QPointF tangents_outer;
0050         if ( radius_outer != 0 )
0051             tangents_outer = {
0052                 dy / radius_outer,
0053                 -dx / radius_outer,
0054             };
0055 
0056         bezier.add_point(
0057             QPointF(pos.x() + dx, pos.y() + dy),
0058             tangent_len_outer * tangents_outer,
0059             -tangent_len_outer * tangents_outer
0060         );
0061 
0062         if ( type == Star )
0063         {
0064             dx = radius_inner * math::cos(main_angle+halfd);
0065             dy = radius_inner * math::sin(main_angle+halfd);
0066 
0067             QPointF tangents_inner;
0068             if ( radius_inner != 0 )
0069                 tangents_inner = {
0070                     dy / radius_inner,
0071                     -dx / radius_inner,
0072                 };
0073 
0074             bezier.add_point(
0075                 QPointF(pos.x() + dx, pos.y() + dy),
0076                 tangent_len_inner * tangents_inner,
0077                 -tangent_len_inner * tangents_inner
0078             );
0079         }
0080     }
0081 
0082     return bezier;
0083 }
0084 
0085