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
|
// 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 <cmath>
std::vector<double> superellipse_calc(const double x, const double a,
const double b, const double n);
int main()
{
using namespace Graph_lib;
using namespace std;
Point tl{ 100, 100 };
Simple_window win{ tl, 800, 600, "Super-ellipse" };
try
{
constexpr double a = 3.0;
constexpr double b = 2.0;
constexpr double n = 2.0;
constexpr double precision = 1e-2;
// -a <= x <= a
double x = -a;
while (x < a)
{
vector<double> y0 = superellipse_calc(x, a, b, n);
vector<double> y1 = superellipse_calc(x + precision, a, b, n);
// negative y
// bottom half of superellipse
Line l0
{
{int(x), int(y0[0])},
{int(x + precision), int(y1[1])}
};
// positive y
// top half of superellipse
Line l1
{
{int(x), int(y0[1])},
{int(x + precision), int(y1[1])}
};
l0.set_color(Color::black);
l1.set_color(Color::black);
win.attach(l0);
win.attach(l1);
x += precision;
}
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();
}
}
std::vector<double> superellipse_calc(const double x, const double a,
const double b, const double n)
{
using namespace std;
// two y-coordinates for every x-coordinate
vector<double> y{ 0, 0 };
// y[0] is negative value, y[1] is positive value
y[0] = -b * pow(1 - std::pow(std::abs(x / a), n), 1 / n);
y[1] = b * pow(1 - std::pow(std::abs(x / a), n), 1 / n);
return y;
}
|