1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
// Osman Zakir
// 3 / 29 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 12
// Exercise Specifications:
/**
* A superellipse is a two-dimensional shape defined by the equation
* pow(abs(x/a), m) + pow(abs(y/b), n) = 1, m,n > 0
* Look up superellipse on the web to get a better idea of what such shapes
* look like. Write a program that draws “starlike” patterns by connecting
* points on a superellipse. Take a , b , m , n , and N as arguments. Select N
* points on the superellipse defined by a , b , m , and n . Make the points
* equally spaced for some definition of “equal.” Connect each of those N
* points to one or more other points (if you like you can make the number
* of points to which to connect a point another argument or just use N – 1 ,
* i.e., all the other points).
*/
#include "../../Simple_window.h"
#include "../../Graph.h"
#include <random>
#include <stdexcept>
#include <cstdlib>
#include <cmath>
Graph_lib::Point superellipse(double deg, const double a,
const double b, const double m, const double n);
inline int randint(int min, int max);
inline int randint(int max);
int main()
{
using namespace Graph_lib;
using namespace std;
Point tl{ 100, 100 };
constexpr int win_width = 800;
constexpr int win_height = 600;
Simple_window win{ tl, win_width, win_height, "Super-ellipse" };
try
{
constexpr double a = 100.0;
constexpr double b = 100.0;
constexpr double m = 0.5;
constexpr double n = 0.5;
constexpr int revolution = 360;
Graph_lib::Point center{ win_width / 2, win_height / 2 };
Open_polyline openpl;
for (int d = 0; d <= revolution; d++)
{
openpl.add(superellipse(d, a, b, m, n) += center);
}
constexpr int N = 5;
constexpr int spacing = revolution / N;
int rand_theta = randint(revolution);
Closed_polyline star;
for (int i = 0; i < 2; i++)
{
for (int j = i; j < N; j += 2)
{
star.add(superellipse(rand_theta + j * spacing, a, b, m, n) += center);
}
}
openpl.set_color(Color::blue);
openpl.set_style({ Line_style::solid, 2 });
star.set_color(Color::red);
star.set_style({ Line_style::solid, 2 });
win.attach(openpl);
win.attach(star);
win.wait_for_button();
}
catch (const runtime_error &e)
{
Text err_msg_start{ Point{300, 600}, "Runtime_error: " };
Text err_msg{ Point{400, 600}, e.what() };
err_msg_start.set_color(Color::black);
err_msg.set_color(Color::black);
win.attach(err_msg_start);
win.attach(err_msg);
win.wait_for_button();
}
}
Graph_lib::Point superellipse(double deg, const double a,
const double b, const double m, const double n)
{
constexpr double pi = 3.14159265359;
deg *= pi / 180.0;
return Graph_lib::Point{
int(a * pow(abs(sin(deg)), 2 / m) * (sin(deg) > 0 ? 1 : -1)),
int(b * pow(abs(cos(deg)), 2 / n) * (cos(deg) > 0 ? 1 : -1))
};
}
inline int randint(int min, int max)
{
static std::default_random_engine ran;
return std::uniform_int_distribution<>{min, max}(ran);
}
inline int randint(int max)
{
return randint(0, max);
}
|