无法绘制多边形?
Failing to draw polygrams?
这里有一个 class 画星星,作为 Bjarne Stroustrup 的 C++ 编程:原理与实践.
第 13 章练习 19 的一部分
Class Star
uses penta-, hexa-, hepta- and octa-gram as basis together with a property (rotational symmetry) that stars with multiple vertices (10, 12, 14, 18, etc) have, to draw n-grams1:
Chapter13Exercise19.cpp
#include "GUI.h"
#include "Simple_window.h"
#include <iostream>
#include "Chapter13Exercise19.h"
int main(){
// window parameters
int winWidth = 800;
int winHeight = 600;
Point centerPoint((x_max() - winWidth) / 2, (y_max() - winHeight) / 2);
Simple_window* siw = new Simple_window(centerPoint, winWidth,
winHeight, "Chapter 13 Exercise 19");
try{
Point center(siw->x_max()/2, siw->y_max()/2);
int radius = 150;
// Currenly: sides > 5, sides =! 13, 17, 19 and multiples
int sides = 16;
Graph_lib::Star st(center, radius, sides);
siw->attach(st);
siw->wait_for_button();
}catch(exception& e){
cerr << e.what() << endl;
getchar();
}catch(const std::invalid_argument& e){
cerr << e.what() << endl;
getchar();
}catch(...){
cerr <<"Defaul exception!"<< endl;
getchar();
}
}
Chapter13Exercise19.h
#ifndef _Chapter13Exercise19_H_
#define _Chapter13Exercise19_H_
#define PI 3.14159265359
namespace Graph_lib{
class Star: public Lines{
public:
Star(Point c, int r, int n);
private:
int vertexNumber;
Point center;
int radius;
vector<Point>starCoordinates;
// parameters kept as function recursive
void rotateCoordinate(Point& axisOfRotation, Point& initial,
double angRads, int numberOfRotations);
void generatePoly();
void makeStar();
};
#include "Chapter13Exercise19Def.cpp"
} // end of namespace Graph_lib
#endif
Chapter13Exercise19Def.cpp
// Class Members implementation
Star::Star(Point c, int r, int n)
: vertexNumber(n), center(c), radius(r)
{
if(n < 5) throw std::invalid_argument("Not enough verteces!");
generatePoly();
makeStar();
}
void Star::rotateCoordinate(Point& axisOfRotation, Point& initial,
double angRads, int numberOfRotations){
if(numberOfRotations <= 0) return;
else{
double x = cos(angRads) * (initial.x - axisOfRotation.x)
- sin(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.x;
double y = sin(angRads) * (initial.x - axisOfRotation.x)
+ cos(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.y;
starCoordinates.push_back(Point(x, y));
rotateCoordinate(axisOfRotation, Point(x,y), angRads, --numberOfRotations);
}
}
void Star::generatePoly(){
double angRads = (PI / 180.) * (360. / vertexNumber);
Point initial(center.x, center.y - radius);
rotateCoordinate(center, initial, angRads, vertexNumber);
}
void Star::makeStar(){
// every if statement covers Star with n and multiples of n vertexes
// the inner for loops execute one iteration for the fundamental stars
// and n iterations for the multiples (rotational symmetry)
if (vertexNumber % 5 == 0){
for (size_t it = 0; it < starCoordinates.size() / 5; ++it){
Lines::add(starCoordinates[it+3], starCoordinates[it]);
Lines::add(starCoordinates[it], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it+1]);
Lines::add(starCoordinates[it+1], starCoordinates[it+3]);
}
}else if (vertexNumber % 3 == 0){
for (size_t it = 0; it < starCoordinates.size() / 3; ++it){
Lines::add(starCoordinates[it], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it]);
}
}else if (vertexNumber % 7 == 0){
for (size_t it = 0; it < starCoordinates.size() / 7; ++it){
Lines::add(starCoordinates[it], starCoordinates[it+3]);
Lines::add(starCoordinates[it+3], starCoordinates[it+6]);
Lines::add(starCoordinates[it+6], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+5]);
Lines::add(starCoordinates[it+5], starCoordinates[it+1]);
Lines::add(starCoordinates[it+1], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it]);
}
}else if (vertexNumber % 8 == 0){
for (size_t it = 0; it < starCoordinates.size() / 8; ++it){
Lines::add(starCoordinates[it], starCoordinates[it+5]);
Lines::add(starCoordinates[it+5], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+7]);
Lines::add(starCoordinates[it+7], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it+1]);
Lines::add(starCoordinates[it+1], starCoordinates[it+6]);
Lines::add(starCoordinates[it+6], starCoordinates[it+3]);
Lines::add(starCoordinates[it+3], starCoordinates[it]);
}
} else throw std::invalid_argument("Star vertexes'number not supported!");
}
结果:
虽然所有基本的多边形(5、6、7、8 个顶点)看起来都应该是这样,但在多边形的顶点为:10、12、14 等的情况下,我得到了这些部分完成的图纸。
我知道问题来自 Chapter13Exercise19Def.cpp
中的函数 makeStar()
,但我无法弄清楚问题是什么。
问题:
为什么来的图是画的一半,函数实现有什么问题makeStar()
?
是否有其他算法可以完成类似的工作?
1.目前是 5、6、7 和 8 的倍数。
我真的不能玩你的代码,因为它依赖于你正在使用的可视化库,但我知道问题出在哪里,而且我非常有信心我知道解决方案。
rotateCoordinate
递归函数生成点向量,沿多边形的边界圆均匀分布,按顺时针方向排列。
当您随后构建定义(绘制...)多边形的线条时,您使用的是点,但不是用于更正索引。例如,假设您有一个多边形 {16/2}(2 个六角星),您有 0-15 个索引点,但是生成线条的 for
循环最多达到索引 8(it = 1
, index [it + 7]
), 这显然是错误的.
你应该做的是用你的多边形中多边形的数量乘以你的常量数(你添加到 it
的数),所以在 {16/2} 的情况下就是 2 .
试试这个代码:
void Star::makeStar(){
// every if statement covers Star with n and multiples of n vertexes
// the inner for loops execute one iteration for the fundamental stars
// and n iterations for the multiples (rotational symmetry)
if (vertexNumber % 5 == 0){
for (size_t it = 0, polygons = starCoordinates.size() / 5; it < polygons; ++it){
Lines::add(starCoordinates[it + polygons * 3], starCoordinates[it]);
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it + polygons * 1]);
Lines::add(starCoordinates[it + polygons * 1], starCoordinates[it + polygons * 3]);
}
}else if (vertexNumber % 6 == 0){ // for polygons multiples of 6
size_t polygons = starCoordinates.size() / 6;
for (size_t it = 0, ; it < starCoordinates() / 3; ++it){
// generated by two triangles
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it]);
}
}else if (vertexNumber % 7 == 0){
for (size_t it = 0, polygons = starCoordinates.size() / 7; it < polygons; ++it){
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 3]);
Lines::add(starCoordinates[it + polygons * 3], starCoordinates[it + polygons * 6]);
Lines::add(starCoordinates[it + polygons * 6], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 5]);
Lines::add(starCoordinates[it + polygons * 5], starCoordinates[it + polygons * 1]);
Lines::add(starCoordinates[it + polygons * 1], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it]);
}
}else if (vertexNumber % 8 == 0){
for (size_t it = 0, polygons = starCoordinates.size() / 8; it < polygons; ++it){
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 5]);
Lines::add(starCoordinates[it + polygons * 5], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 7]);
Lines::add(starCoordinates[it + polygons * 7], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it + polygons * 1]);
Lines::add(starCoordinates[it + polygons * 1], starCoordinates[it + polygons * 6]);
Lines::add(starCoordinates[it + polygons * 6], starCoordinates[it + polygons * 3]);
Lines::add(starCoordinates[it + polygons * 3], starCoordinates[it]);
}
} else throw std::invalid_argument("Star vertexes'number not supported!");
}
这里有一个 class 画星星,作为 Bjarne Stroustrup 的 C++ 编程:原理与实践.
第 13 章练习 19 的一部分Class
Star
uses penta-, hexa-, hepta- and octa-gram as basis together with a property (rotational symmetry) that stars with multiple vertices (10, 12, 14, 18, etc) have, to draw n-grams1:
Chapter13Exercise19.cpp
#include "GUI.h"
#include "Simple_window.h"
#include <iostream>
#include "Chapter13Exercise19.h"
int main(){
// window parameters
int winWidth = 800;
int winHeight = 600;
Point centerPoint((x_max() - winWidth) / 2, (y_max() - winHeight) / 2);
Simple_window* siw = new Simple_window(centerPoint, winWidth,
winHeight, "Chapter 13 Exercise 19");
try{
Point center(siw->x_max()/2, siw->y_max()/2);
int radius = 150;
// Currenly: sides > 5, sides =! 13, 17, 19 and multiples
int sides = 16;
Graph_lib::Star st(center, radius, sides);
siw->attach(st);
siw->wait_for_button();
}catch(exception& e){
cerr << e.what() << endl;
getchar();
}catch(const std::invalid_argument& e){
cerr << e.what() << endl;
getchar();
}catch(...){
cerr <<"Defaul exception!"<< endl;
getchar();
}
}
Chapter13Exercise19.h
#ifndef _Chapter13Exercise19_H_
#define _Chapter13Exercise19_H_
#define PI 3.14159265359
namespace Graph_lib{
class Star: public Lines{
public:
Star(Point c, int r, int n);
private:
int vertexNumber;
Point center;
int radius;
vector<Point>starCoordinates;
// parameters kept as function recursive
void rotateCoordinate(Point& axisOfRotation, Point& initial,
double angRads, int numberOfRotations);
void generatePoly();
void makeStar();
};
#include "Chapter13Exercise19Def.cpp"
} // end of namespace Graph_lib
#endif
Chapter13Exercise19Def.cpp
// Class Members implementation
Star::Star(Point c, int r, int n)
: vertexNumber(n), center(c), radius(r)
{
if(n < 5) throw std::invalid_argument("Not enough verteces!");
generatePoly();
makeStar();
}
void Star::rotateCoordinate(Point& axisOfRotation, Point& initial,
double angRads, int numberOfRotations){
if(numberOfRotations <= 0) return;
else{
double x = cos(angRads) * (initial.x - axisOfRotation.x)
- sin(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.x;
double y = sin(angRads) * (initial.x - axisOfRotation.x)
+ cos(angRads) * (initial.y - axisOfRotation.y) + axisOfRotation.y;
starCoordinates.push_back(Point(x, y));
rotateCoordinate(axisOfRotation, Point(x,y), angRads, --numberOfRotations);
}
}
void Star::generatePoly(){
double angRads = (PI / 180.) * (360. / vertexNumber);
Point initial(center.x, center.y - radius);
rotateCoordinate(center, initial, angRads, vertexNumber);
}
void Star::makeStar(){
// every if statement covers Star with n and multiples of n vertexes
// the inner for loops execute one iteration for the fundamental stars
// and n iterations for the multiples (rotational symmetry)
if (vertexNumber % 5 == 0){
for (size_t it = 0; it < starCoordinates.size() / 5; ++it){
Lines::add(starCoordinates[it+3], starCoordinates[it]);
Lines::add(starCoordinates[it], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it+1]);
Lines::add(starCoordinates[it+1], starCoordinates[it+3]);
}
}else if (vertexNumber % 3 == 0){
for (size_t it = 0; it < starCoordinates.size() / 3; ++it){
Lines::add(starCoordinates[it], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it]);
}
}else if (vertexNumber % 7 == 0){
for (size_t it = 0; it < starCoordinates.size() / 7; ++it){
Lines::add(starCoordinates[it], starCoordinates[it+3]);
Lines::add(starCoordinates[it+3], starCoordinates[it+6]);
Lines::add(starCoordinates[it+6], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+5]);
Lines::add(starCoordinates[it+5], starCoordinates[it+1]);
Lines::add(starCoordinates[it+1], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it]);
}
}else if (vertexNumber % 8 == 0){
for (size_t it = 0; it < starCoordinates.size() / 8; ++it){
Lines::add(starCoordinates[it], starCoordinates[it+5]);
Lines::add(starCoordinates[it+5], starCoordinates[it+2]);
Lines::add(starCoordinates[it+2], starCoordinates[it+7]);
Lines::add(starCoordinates[it+7], starCoordinates[it+4]);
Lines::add(starCoordinates[it+4], starCoordinates[it+1]);
Lines::add(starCoordinates[it+1], starCoordinates[it+6]);
Lines::add(starCoordinates[it+6], starCoordinates[it+3]);
Lines::add(starCoordinates[it+3], starCoordinates[it]);
}
} else throw std::invalid_argument("Star vertexes'number not supported!");
}
结果:
虽然所有基本的多边形(5、6、7、8 个顶点)看起来都应该是这样,但在多边形的顶点为:10、12、14 等的情况下,我得到了这些部分完成的图纸。
我知道问题来自 Chapter13Exercise19Def.cpp
中的函数 makeStar()
,但我无法弄清楚问题是什么。
问题:
为什么来的图是画的一半,函数实现有什么问题
makeStar()
?是否有其他算法可以完成类似的工作?
1.目前是 5、6、7 和 8 的倍数。
我真的不能玩你的代码,因为它依赖于你正在使用的可视化库,但我知道问题出在哪里,而且我非常有信心我知道解决方案。
rotateCoordinate
递归函数生成点向量,沿多边形的边界圆均匀分布,按顺时针方向排列。
当您随后构建定义(绘制...)多边形的线条时,您使用的是点,但不是用于更正索引。例如,假设您有一个多边形 {16/2}(2 个六角星),您有 0-15 个索引点,但是生成线条的 for
循环最多达到索引 8(it = 1
, index [it + 7]
), 这显然是错误的.
你应该做的是用你的多边形中多边形的数量乘以你的常量数(你添加到 it
的数),所以在 {16/2} 的情况下就是 2 .
试试这个代码:
void Star::makeStar(){
// every if statement covers Star with n and multiples of n vertexes
// the inner for loops execute one iteration for the fundamental stars
// and n iterations for the multiples (rotational symmetry)
if (vertexNumber % 5 == 0){
for (size_t it = 0, polygons = starCoordinates.size() / 5; it < polygons; ++it){
Lines::add(starCoordinates[it + polygons * 3], starCoordinates[it]);
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it + polygons * 1]);
Lines::add(starCoordinates[it + polygons * 1], starCoordinates[it + polygons * 3]);
}
}else if (vertexNumber % 6 == 0){ // for polygons multiples of 6
size_t polygons = starCoordinates.size() / 6;
for (size_t it = 0, ; it < starCoordinates() / 3; ++it){
// generated by two triangles
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it]);
}
}else if (vertexNumber % 7 == 0){
for (size_t it = 0, polygons = starCoordinates.size() / 7; it < polygons; ++it){
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 3]);
Lines::add(starCoordinates[it + polygons * 3], starCoordinates[it + polygons * 6]);
Lines::add(starCoordinates[it + polygons * 6], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 5]);
Lines::add(starCoordinates[it + polygons * 5], starCoordinates[it + polygons * 1]);
Lines::add(starCoordinates[it + polygons * 1], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it]);
}
}else if (vertexNumber % 8 == 0){
for (size_t it = 0, polygons = starCoordinates.size() / 8; it < polygons; ++it){
Lines::add(starCoordinates[it], starCoordinates[it + polygons * 5]);
Lines::add(starCoordinates[it + polygons * 5], starCoordinates[it + polygons * 2]);
Lines::add(starCoordinates[it + polygons * 2], starCoordinates[it + polygons * 7]);
Lines::add(starCoordinates[it + polygons * 7], starCoordinates[it + polygons * 4]);
Lines::add(starCoordinates[it + polygons * 4], starCoordinates[it + polygons * 1]);
Lines::add(starCoordinates[it + polygons * 1], starCoordinates[it + polygons * 6]);
Lines::add(starCoordinates[it + polygons * 6], starCoordinates[it + polygons * 3]);
Lines::add(starCoordinates[it + polygons * 3], starCoordinates[it]);
}
} else throw std::invalid_argument("Star vertexes'number not supported!");
}