无法绘制多边形图?

时间:2015-09-24 19:24:04

标签: c++ algorithm computational-geometry

这是一个绘制星星的类,作为 Bjarne Stroustrup的C ++编程:原理与实践的第13章练习19的一部分。

  

Star使用五角形,六角形,七角形八角形作为基础以及具有多个星形的属性(旋转对称)顶点(10,12,14,18等)有,以绘制n-gram 1

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等,我得到了这些部分完成的图。

我知道问题来自makeStar()中的函数Chapter13Exercise19Def.cpp,但我无法弄清楚问题是什么。

问题:

  1. 为什么要绘制部分绘图,功能makeStar()的实现有什么问题?

  2. 还有其他算法可以做类似的工作吗?

  3. 1。目前是5,6,7和8的倍数。

    可以找到所有用于编译的附加文件:here。可以找到 FLTK here

1 个答案:

答案 0 :(得分:2)

我无法真正使用您的代码,因为它依赖于您正在使用的可视化库,但我知道问题是什么,并且我非常有信心我知道解决方案。

rotateCoordinate递归函数生成一个点向量,沿着polygram的边界圆均匀分布,按顺时针方向排序。

然后当你构造定义(绘制...)polygram的线时,你使用这些点,但你不是用来纠正索引。例如,假设你有一个polygram {16/2}(2个hexagrams),你有0-15个索引点,但生成这些行的for循环最多会达到索引8({ {1}},索引it = 1),这显然是错误的。

你应该做的是将你的常数(你添加到[it + 7]的数字)乘以多边形中的多边形数,所以在{16/2}的情况下,这将是2。 / p>

试试这段代码:

it