2017-05-17 11 views
0

交差を検出して真または偽を返す関数を書く必要があります。どのような形状の交差関数を書くか

私はShape.cppファイルとrectangle.cppを持っていますが、circle.cppファイルはそれを継承しています。私はそれを計算しようとしましたが、失敗しました。エラーはありませんが、プログラムが起動するとクラッシュします。私の質問はなぜそれがクラッシュするのですか?私の方法は間違っていますか?ここにはcircle.cppファイルがあります。

bool Circ::intersects(Shape* pshape) 
{ 
    Rect *p1 = dynamic_cast<Rect*>(pshape); 
    Circ *p2 = dynamic_cast<Circ*>(pshape); 

    if(p1) 
    { 
     float circleDistance_x = abs(p2->getPos().x - p1->getPos().x); 
     float circleDistance_y = abs(p2->getPos().y - p1->getPos().y); 

     if(circleDistance_x > (p1->getSize().x/2 + p2->getRad())) 
      return false; 
     if(circleDistance_y > (p1->getSize().y/2 + p2->getRad())) 
      return false; 
     if(circleDistance_x <= (p1->getSize().x/2)) 
      return true; 
     if(circleDistance_y <= (p1->getSize().y/2)) 
      return true; 
     float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2)); 

     return (cornerDistance_sq <= p2->getRad()^2); 

    } 

    return false; 
} 

これは、すべて私が書いたいコードではありません。しかし、それが失敗すると、私は書くのをやめました。

と私のSHAPES.Hファイル

#ifndef _SHAPES_H 
#define _SHAPES_H 


struct Point2d 
{ 
    float x, y; 

}; 
struct Point3d 
{ 
    float r, g, b; 

}; 

class Shape 
{ 
protected: 
    bool m_bMarked; 
    Point3d m_col; 
    Point2d m_veldir; 
    Point2d m_pos; 
    float m_vel; 
public: 
    Shape(Point2d& pos, Point2d& veldir, float vel, Point3d& col) 
     :m_pos(pos),m_veldir(veldir),m_vel(vel),m_col(col) 
    { 
     m_bMarked = false; 
    } 
    virtual ~Shape() {} 
    virtual void draw() = 0; 
    virtual bool intersects(Shape*) = 0; 
    inline void move() { m_pos.x += m_veldir.x*m_vel; m_pos.y += m_veldir.y*m_vel; } 
    inline void invert_xdir() { m_veldir.x *= -1; } 
    inline void invert_ydir() { m_veldir.y *= -1; } 
    inline void MarkShape() { m_bMarked = true; } 
    inline void UnMarkShape() { m_bMarked = false; } 
    inline bool isMarked() { return m_bMarked; } 
    inline void increase_vel() { m_vel += 0.01f; } 
    inline void decrease_vel() { m_vel -= 0.01f; } 

}; 


#endif 

そして最後に、私のShapesMain.cppファイル

#include <time.h> 
#include <GL/glut.h> 
#include <cmath> 

#include "Rectangle.h" 
#include "Circle.h" 


// YOU CAN CHANGE THE NUMBER OF SHAPES 
#define SHAPE_COUNT 20 

// YOU CAN MODIFY WINDOW SIZE BY CHANGING THESE 
// YOU MAY ALSO VIEW WINDOW IN FULL SCREEN 
#define WINDOWX 500 
#define WINDOWY 500 

// UNCOMMENT THE LINE BELOW TO STOP MOVING SHAPES 
//#define NO_MOTION 

// CHANGE THESE DIMENSIONS HOWEVER YOU LIKE 
#define MAX_SHAPE_DIM 70 
#define MIN_SHAPE_DIM 10 

float g_windowWidth = WINDOWX; 
float g_windowHeight = WINDOWY; 

Shape* g_shapeList[SHAPE_COUNT]; 
int  g_numShapes = 0; 
bool g_bShowIntersection = true; 



//------------------------------------ 

void Initialize() 
{ 
    srand (time(NULL)); 

    // delete previous shapes, if there is any 
    if (g_numShapes > 0) 
    { 
     for (int i = 0; i < g_numShapes; i++) 
      delete g_shapeList[i]; 
    } 

    // create a new shape repository 
    do { 
     g_numShapes = rand() % SHAPE_COUNT; // number of shapes are randomly determined  
    } while (g_numShapes < 5); // we dont want to have less than 5 shapes 


    int rect_count = g_numShapes * (rand() % 10/10.0f); 
    int circle_count = g_numShapes - rect_count; 

    int half_wind_x = 3* g_windowWidth/4; 
    int half_wind_y = 3* g_windowHeight/4; 
    int max_dim = MAX_SHAPE_DIM; // max dim. of any shape 
    int min_dim = MIN_SHAPE_DIM; // min dim. of any shape 
    int quad_wind = g_windowWidth/4; 

    for (int i= 0; i<g_numShapes; i++) 
    { 

     float x, y; 
     float v1, v2; 

     // set positions 
     do { 
      x = rand() % half_wind_x; 
     } while (x <= quad_wind); 

     do { 
      y = rand() % half_wind_y; 
     } while (y <= quad_wind); 
     Point2d pos = { x,y }; 

     // set velocity directions 
     do{ 
      v1 = rand() % 10/10.0f; 
      v2 = rand() % 10/10.0f;   
     } while (v1 == 0 || v2 == 0); 

     v1 *= (rand() % 2) ? -1 : 1; 
     v2 *= (rand() % 2) ? -1 : 1; 
     float vnorm = sqrt(v1*v1 + v2*v2); 
     Point2d veldir = { v1/vnorm, v2/vnorm }; 

     // set velocity 
     float vel; 
     do { 
      vel = rand() % 2/10.0f; 
     } while (vel == 0); 

#ifdef NO_MOTION 
     vel = 0.0f; 
#endif 
     //set color 
     float R = rand()%100/100.0f; 
     float G = rand()%100/100.0f; 
     float B = rand()%100/100.0f; 
     Point3d color = { R,G,B }; 

     // construct objects 
     if (i < rect_count) 
     { 
      float wx; 
      float wy; 
      do { 
       wx = rand() % quad_wind; 
      } while (wx < min_dim || wx>max_dim); 

      do { 
       wy = rand() % quad_wind; 
      } while (wy < min_dim || wy>max_dim); 

      Point2d size = { wx, wy };   

      Rect* pRect = new Rect(pos, size, veldir, vel, color); 
      g_shapeList[i] = pRect; 
     } 
     else 
     { 
      float rad; 
      do { 
       rad = rand() % quad_wind; 
      } while (rad < min_dim || rad>max_dim); 


      Circ* pCirc = new Circ(pos, rad, veldir, vel, color); 
      g_shapeList[i] = pCirc; 
     } 
    } 

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 

} 
//------------------------------------- 
// This function handles the intersections of shapes. 
// if the user is not interested in marking intersections 
// s/he can set bMarkIntersections to false..in this case 
// no intersection test is performed 
void MarkObjects(bool bMarkIntersections) 
{ 
    if (bMarkIntersections == false) 
    { 
     for (int i = 0; i < g_numShapes; i++) 
      g_shapeList[i]->UnMarkShape(); 
    } 
    else 
    { 
     // reset the states of all shapes as unmarked 
     for (int i = 0; i < g_numShapes; i++) 
      g_shapeList[i]->UnMarkShape(); 

     for (int i = 0; i < g_numShapes; i++) 
     {   
      for (int j = i+1; j < g_numShapes; j++) 
      { 

       if (g_shapeList[i]->intersects(g_shapeList[j])) 
       { 
        g_shapeList[i]->MarkShape(); 
        g_shapeList[j]->MarkShape(); 

       } 
      } 
     } 
    } 

} 
//------------------------------------ 
void UpdateData() 
{ 
    // create viewport bounding rectangles to keep the shapes within the viewport 
    Point2d Winpos = { -1.0,0.0 }; 
    Point2d Winsize = { 1.0 , g_windowHeight }; 
    Point2d Winveldir = { 0,0 }; // dummy veldir 
    float Winvel = 0.0f; //not moving 
    Point3d Wincol = { 0,0,0 }; // dummy color 
    Rect WindowRectLeft(Winpos, Winsize, Winveldir, Winvel, Wincol); 
    Winpos.x = 0.0; Winpos.y = -1.0; 
    Winsize.x = g_windowWidth; Winsize.y = 1.0; 
    Rect WindowRectBottom(Winpos, Winsize, Winveldir, Winvel, Wincol); 
    Winpos.x = g_windowWidth; Winpos.y = 0.0; 
    Winsize.x = 1; Winsize.y = g_windowHeight; 
    Rect WindowRectRight(Winpos, Winsize, Winveldir, Winvel, Wincol); 
    Winpos.x = 0.0; Winpos.y = g_windowHeight; 
    Winsize.x = g_windowWidth; Winsize.y = 1.0f; 
    Rect WindowRectUp(Winpos, Winsize, Winveldir, Winvel, Wincol); 

    for (int i = 0; i < g_numShapes; i++) 
    { 
     // move the shape 
     g_shapeList[i]->move(); 

     // if it bounces to the window walls, invert its veldir 
     if (g_shapeList[i]->intersects(&WindowRectLeft) || 
      g_shapeList[i]->intersects(&WindowRectRight)) 
      g_shapeList[i]->invert_xdir(); 

     if (g_shapeList[i]->intersects(&WindowRectBottom) || 
      g_shapeList[i]->intersects(&WindowRectUp)) 
      g_shapeList[i]->invert_ydir(); 
    } 
} 
//------------------------------------ 
void ChangeSize(GLsizei w, GLsizei h) 
{ 
    if(h == 0) 
     h = 1; 

    glViewport(0, 0, w, h); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    g_windowHeight = h; 
    g_windowWidth = w; 

    glOrtho(0, g_windowWidth, 0, g_windowHeight , 1.0f, -1.0f); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
} 
//------------------------------------ 
void processNormalKeys(unsigned char key, int x, int y) 
{ 

    if (key == 'q') // PRESS 'q' to terminate the application 
     exit(0); 
    if(key=='r') // PRESS 'r' ket to reset the shapes 
     Initialize(); 
    if (key == 's') // toggle between showing the intersections or not 
     g_bShowIntersection = g_bShowIntersection ? false: true; 


} 
//------------------------------------ 
void processSpecialKeys(int key, int x, int y) 
{ 

    switch(key) { 
     case GLUT_KEY_LEFT :     
      break; 
     case GLUT_KEY_RIGHT :  
      break; 
     case GLUT_KEY_UP: 
      // PRESSING UP ARROW KEY INCREASES THE SHAPE VELOCITIES 
      for (int i = 0; i < g_numShapes; i++) 
       g_shapeList[i]->increase_vel(); 
      break; 
     case GLUT_KEY_DOWN: 
      // PRESSING DOWN ARROW KEY DECREASES THE SHAPE VELOCITIES 
      for (int i = 0; i < g_numShapes; i++) 
       g_shapeList[i]->decrease_vel(); 

      break; 
    } 

} 

//------------------------------------- 
void display() { 


    glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer 

    glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

    UpdateData(); 
    MarkObjects(g_bShowIntersection); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    for (int i= 0; i<g_numShapes; i++) 
     g_shapeList[i]->draw(); 


    glutSwapBuffers(); 
} 
//------------------------------------ 
int main(int argc, char* argv[]) 
{ 

    glutInit(&argc, argv);   // Initialize GLUT 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(WINDOWX, WINDOWY); 



    glutCreateWindow("COM102B - PA4"); 


    // Register callback handler for window re-paint 
    glutDisplayFunc(display);  
    glutReshapeFunc(ChangeSize); 
    glutIdleFunc(display); 
    glutKeyboardFunc(processNormalKeys); 
    glutSpecialFunc(processSpecialKeys); 

    Initialize(); 


    glutMainLoop();     // Enter infinitely event-processing loop 

    return 0; 
} 
+0

形状がウィンドウに移動し、あなたは彼らが重なったときに知りたいですか?そうであれば、形状がある領域を追跡し、その領域が他の形状で占められているかどうかを比較する必要があります。ウィンドウ内に「グリッド」を定義し、2つ以上の図形が同じグリッド座標を占めている場合は、それぞれの図形がどこにあるかを計算することができます。まあ、それは私が問題を攻撃する方法です... –

答えて

0

あなたの問題は、これらの行にある:あなたがのRectを継承していない限り

Rect *p1 = dynamic_cast<Rect*>(pshape); 
Circ *p2 = dynamic_cast<Circ*>(pshape); 

Circから、またはその逆に、これがあなたのプログラムをクラッシュさせる原因になります。あなたがReであれば、あなたのpShapeをCircにキャストすることはできませんct、Rectオブジェクトを関数に渡すと、Rect *に正しくキャストされますが、Circ *がnullptrを返して失敗するので、p2からメソッドにアクセスしようとすると、無効なメモリにアクセスしているのでクラッシュします0x00000000の):メソッドが円からあるので、

if(p1) 
     { 
      float circleDistance_x = abs(p2->getPos().x - p1->getPos().x); 
      float circleDistance_y = abs(p2->getPos().y - p1->getPos().y); 

      if(circleDistance_x > (p1->getSize().x/2 + p2->getRad())) 
       return false; 
      if(circleDistance_y > (p1->getSize().y/2 + p2->getRad())) 
       return false; 
      if(circleDistance_x <= (p1->getSize().x/2)) 
       return true; 
      if(circleDistance_y <= (p1->getSize().y/2)) 
       return true; 
      float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2)); 

      return (cornerDistance_sq <= p2->getRad()^2); 

     } 

それで、あなたは単純に最初のP1ポインタをキャストすることができ、P2ポインタのための必要はありませんので、それはそれはのCIRC Objectから呼ばれていたことは明らかです。ライン上でも

Rect *p1 = dynamic_cast<Rect*>(pshape); 
    if(p1) 
     { 
      float circleDistance_x = abs(getPos().x - p1->getPos().x); 
      float circleDistance_y = abs(getPos().y - p1->getPos().y); 

      if(circleDistance_x > (p1->getSize().x/2 + getRad())) 
       return false; 
      if(circleDistance_y > (p1->getSize().y/2 + getRad())) 
       return false; 
      if(circleDistance_x <= (p1->getSize().x/2)) 
       return true; 
      if(circleDistance_y <= (p1->getSize().y/2)) 
       return true; 
      float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2)); 

      return (cornerDistance_sq <= getRad()^2); 

     } 

return (cornerDistance_sq <= getRad()^2) 

は、私はあなたが半径広場を取得しようとしていると思いますが、これは文句を言わないそれを行う、それが実際にやっていることは< becouse

(cornerDistance_sq <= getRad())^2 

です=は^に優先順位があり、^は平方演算子ではありません。ビット演算子です。それでは、あなたが実際に欲しいのです:

return cornerDistance_sq <= getRad() * getRad(); 
関連する問題