How to write a polar equation for a five-pointed star

2.3k Views Asked by At

I can't get the formula right.

There is a formula for an equilateral polygon

enter image description here

I'm trying to translate it into code to draw a five-pointed star enter image description here

Here's how I translated the equation:

_mytKrg.integerVector.append(_mytKrg.X + (_mytKrg.R * cos(2*sin(1)+M_PI*3)/(2*5))/((cos(2*sin(cos(1*5*grad_kol_toch)))+M_PI*3)/(2*5))); //point Х
_mytKrg.integerVector.append(_mytKrg.Y + (_mytKrg.R * sin(2*cos(1)+M_PI*3)/(2*5))/((sin(2*cos(sin(1*5*grad_kol_toch)))+M_PI*3)/(2*5))); //point У

here is the result :

enter image description here

Here's the whole code:

zvezda.pro

#ifndef KRUG_QT_H
#define KRUG_QT_H

#include <QMainWindow>
#include <QDebug>
#include <QPainter>
#include <QPen>
#include <QFont>
#include <QtMath>
#include <QPointF>

// структура для отрисовки круга
struct strKryg
{
    strKryg()
    {
        R = 0.0; kol_toch = 0;
        tocka_1 = 0; tocka_2 = 0;
        X = 0.0; Y = 0.0;
        integerVector.clear();
        point_for_line.clear();
    }
    float R;                            // радиус
    int kol_toch;                       // колич точек которые будут формировать круг
    int tocka_1;                        // точка выреза начало
    int tocka_2;                        // точка выреза конец
    float X; float Y;                   // расположение икса и игрика

    QVector<float> integerVector;       // вектор куда кладём точки (Х и У)
    QVector<QPointF> point_for_line;    // вектор куда кладём QPointf для line
};

class Krug_qt : public QMainWindow
{
    Q_OBJECT

public:
    Krug_qt(QWidget *parent = 0);
    ~Krug_qt();

    void krygVertexArray();
    void vvodZnach(float R, int kol_toch);
    void vvodZnach(float R, int kol_toch, float X, float Y);
    void vvodZnach(float R, int kol_toch, int tocka_1, int tocka_2, float X, float Y);



protected:
    void paintEvent(QPaintEvent *event);
    strKryg     _mytKrg;    // структура круга

};

#endif // KRUG_QT_H

zvezda.cpp

#include "zvezda.h"

Krug_qt::Krug_qt(QWidget *parent)
    : QMainWindow(parent)
{

}

Krug_qt::~Krug_qt()
{

}

void Krug_qt::krygVertexArray()
{
    float grad = 360.0/_mytKrg.kol_toch;
    float grad_kol_toch = 0.0;
    // градусы*M_PI/180 = радианы
    int j;
    for (j = 0; j < _mytKrg.kol_toch; ++j){

        _mytKrg.integerVector.append(_mytKrg.X + (_mytKrg.R * cos(2*sin(1)+M_PI*3)/(2*5))/((cos(2*sin(cos(1*5*grad_kol_toch)))+M_PI*3)/(2*5)));
        _mytKrg.integerVector.append(_mytKrg.Y + (_mytKrg.R * sin(2*cos(1)+M_PI*3)/(2*5))/((sin(2*cos(sin(1*5*grad_kol_toch)))+M_PI*3)/(2*5)));

         grad_kol_toch = grad_kol_toch + grad;
    }
}
void Krug_qt::vvodZnach(float R, int kol_toch)
{
    _mytKrg.R = R;
    _mytKrg.kol_toch = kol_toch;
    _mytKrg.tocka_1 = 0;
    _mytKrg.tocka_2 = 0;
    _mytKrg.X = 0.0;
    _mytKrg.Y = 0.0;
}

void Krug_qt::vvodZnach(float R, int kol_toch, float X, float Y)
{
    _mytKrg.R = R;
    _mytKrg.kol_toch = kol_toch;
    _mytKrg.tocka_1 = 0;
    _mytKrg.tocka_2 = 0;
    _mytKrg.X = X;
    _mytKrg.Y = Y;
}

void Krug_qt::vvodZnach(float R, int kol_toch, int tocka_1, int tocka_2, float X, float Y)
{
    _mytKrg.R = R;
    _mytKrg.kol_toch = kol_toch;
    _mytKrg.tocka_1 = tocka_1;
    _mytKrg.tocka_2 = tocka_2;
    _mytKrg.X = 0.0;
    _mytKrg.Y = 0.0;
}

void Krug_qt::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);                                   // Создаём объект отрисовщика
    QPen pen_abris(Qt::black, 2, Qt::SolidLine, Qt::FlatCap); // кисть обрисовки (компаса)
    painter.setRenderHint(QPainter::Antialiasing);            // убираем резкие кубики
    painter.setPen(pen_abris);                                // Устанавливаем кисть обрисовки
     vvodZnach(200, 180, 600, 400);
    krygVertexArray();                                        // Набираем массив
 
 
    int i; bool d_t;  int tocka_1; int tocka_2;            // используемые переменные
    d_t = true; i = 0; tocka_1 =_mytKrg.tocka_1; tocka_2 = _mytKrg.tocka_2;  // ТОЧКА ОТРИСОВКИ
    for( ; i<_mytKrg.kol_toch; ++i)
    {
        if(i > tocka_1)          // угол "вырезания"  начало
        {
            d_t =  false;
            if( i < tocka_2)      // угол "вырезания" конец
            {
                tocka_1 = i*2;
                d_t = true;
            }
        }
        if(d_t == true)
        {
            // это отдельно все работает полноценный круг
            tocka_2 = tocka_1+1;
            painter.drawPoint(QPointF(_mytKrg.integerVector[tocka_1],_mytKrg.integerVector[tocka_2]));
            tocka_1 = tocka_1 +2;

            qDebug() << "i :"<<i;
            qDebug() << "_mytKrg.tocka_1 :"<<_mytKrg.tocka_1;
         }
    }
}

alas, I can't write on stackoverflow, for some reason they called me maybe because I'm a Russian-speaking man

I'm wondering if it's possible to draw with formulas ?? are there any books or training sites ???


According to the advice of @Homieomorphism. I made changes to the code, but so far I still do not understand how to convert polar coordinates to Cartesian coordinates.

float grad = 360.0/_mytKrg.kol_toch;
float grad_kol_toch = 0.0;
// градусы*M_PI/180 = радианы
int j; float chisl; float znam; float k = 1; float n =5; float m =3;
for (j = 0; j < _mytKrg.kol_toch; ++j)
{
    chisl = cos((2*asin(k)+M_PI/180*m)/(2*n));
    znam  = cos((2*asin(k*cos(n*grad_kol_toch)+M_PI/180))/(2*n));

    _mytKrg.integerVector.append(_mytKrg.X + (_mytKrg.R * (chisl/znam) * cos(grad_kol_toch*M_PI/180.0) ));
    _mytKrg.integerVector.append(_mytKrg.Y + (_mytKrg.R * (chisl/znam) * sin(grad_kol_toch*M_PI/180.0) ));

    grad_kol_toch = grad_kol_toch + grad;
}

enter image description here

2

There are 2 best solutions below

5
On BEST ANSWER

Using the given formula for the radius:

$$ r=\frac{\cos\frac{2\arcsin(k)+\pi\cdot m}{2n}}{\cos\frac{2\arcsin(k\cos(n\cdot\theta))+\pi\cdot m}{2n}}=\frac{nom}{denom} $$

I re-implemented the approach based on polar coordinates using Python (since I feel a bit more confident for solving mathematical tasks in Python than in C/C++). The main idea is to generate two arrays of equal size, one contanining the angles theta=[] and one containing the radi r=[] that correspond to the angles. I ran t from $0$ to $2\pi$ in steps of $0.05$, which gives a good resolution for demonstration purpose. Within the loop we append to both arrays the angle $\theta=t$ and the corresponding radius $r$ calculated using the above-given formula:

import numpy as np
import matplotlib.pyplot as plt
from math import pi

m=3
n=5
theta=[]
r=[]
k=1
for t in np.arange(0, 2*pi, 0.05):
    theta.append(t)
    nom = np.cos((2*np.arcsin(k)+pi*m)/(2*n))
    denom = np.cos((2*np.arcsin(k*np.cos(n*t))+pi*m)/(2*n))
    r.append(nom/denom)

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.plot(theta, r)
ax.set_rmax(2)
ax.set_rticks([0.5, 1, 1.5, 2])
ax.set_rlabel_position(-22.5)
ax.grid(True)

ax.set_title("A {0}-pointed star".format(n), va='bottom')
plt.show()

enter image description here

The notebook is here: https://www.kaggle.com/eldarsultanow/five-pointed-star/

Feel free to adjust parameters to get star shapes with more vertices. When you for example choose $n=6$ and $m=4$ you get the following result:

enter image description here

0
On

$n$ is the number of vertices on unit circle. Unable to guess as yet what $( k,m) $ could represent in the Rose geometrically. In the plot here $ (k,m) = (2,-1.25) $.

enter image description here

In Mathematica code:

rho[t_, k_, m_, 
  n_] = (Cos[(ArcSin[k] + m Pi/2)]/
    n)/(Cos[(ArcSin[k Cos[n t]] + m Pi/2)]/n)
{k, m, n} = {.2, -1.25, 5}
x[t_, k, m, n] = rho[t, k, m, n] Cos[t]; 
y[t_, k, m, n] = rho[t, k, m, n] Sin[t];
ParametricPlot[{x[t, k, m, n], y[t, k, m, n]}, {t, -0, 2 Pi}, 
 PlotStyle -> Red, GridLines -> Automatic]