Détection des angles des quadrilatères.

This commit is contained in:
Georges Dupéron 2011-12-11 15:49:27 +01:00
parent e73ea9b7ec
commit e3d4a50b4e
7 changed files with 57 additions and 22 deletions

View File

@ -38,3 +38,19 @@ int Quad::maxLength() {
)
);
}
float Quad::minAngle() {
float a = 370; // > 360.
for (int i = 0; i < 4; i++) {
a = std::min(a, Triangle(corner[NE+i], corner[SE+i], corner[SW+i]).angle());
}
return a;
}
float Quad::maxAngle() {
float a = 0;
for (int i = 0; i < 4; i++) {
a = std::max(a, Triangle(corner[NE+i], corner[SE+i], corner[SW+i]).angle());
}
return a;
}

View File

@ -13,6 +13,8 @@ public:
void offset(/*Cardinal*/int side, int offset);
int minLength();
int maxLength();
float minAngle();
float maxAngle();
};

View File

@ -9,24 +9,29 @@ Quadrilatere::Quadrilatere(Vertex ne, Vertex se, Vertex sw, Vertex nw) : Chose()
}
Chose* Quadrilatere::factory(int seed, int n, Vertex ne, Vertex se, Vertex sw, Vertex nw) {
int minLength = Quad(ne,se,sw,nw).minLength();
if (minLength < 2500 && proba(seed, n, 1, 20)) {
Quad q = Quad(ne,se,sw,nw);
int minLength = q.minLength();
int maxLength = q.maxLength();
float minAngle = q.minAngle();
float maxAngle = q.maxAngle();
if (minLength < 2500 && maxLength > 5000 && proba(seed, n, 1, 20)) {
return new QuadHerbe(ne, se, sw, nw);
} else if (minLength < 2500) { // + contrainte sur les angles
// suffisemment petit pour un bâtiment
} else if (minLength < 2500 && minAngle > 50/180.f*3.1415926535 && maxAngle < 130/180.f*3.1415926535) { // + contrainte sur les angles
return new Batiment(ne, se, sw, nw);
} else if (false) {
} else if (minAngle <= 50/180.f*3.1415926535 && maxAngle >= 130/180.f*3.1415926535) {
// angles trop pointus
return NULL;
} else if (2*std::min(Segment(nw,ne).length(), Segment(se,sw).length())
return new QuadHerbe(0xff, ne, se, sw, nw);
} else if (minLength > 2500 &&
2*std::min(Segment(nw,ne).length(), Segment(se,sw).length())
< std::max(Segment(ne,se).length(), Segment(sw,nw).length())) {
// trop allongé (côté N ou S deux fois plus petit que le côté E ou W).
return new QuadRect(nw, ne, se, sw); // TODO
} else if (2*std::min(Segment(ne,se).length(), Segment(sw,nw).length())
} else if (minLength > 2500 &&
2*std::min(Segment(ne,se).length(), Segment(sw,nw).length())
< std::max(Segment(nw,ne).length(), Segment(se,sw).length())) {
// trop allongé (côté E ou W deux fois plus petit que le côté N ou S).
return new QuadRect(ne, se, sw, nw); // TODO
} else if (true) { // proche du carré
} else if (minLength > 2500) {
return new QuadCroix(ne, se, sw, nw);
} else {
return new QuadHerbe(ne, se, sw, nw);

View File

@ -1,8 +1,14 @@
#include "all_includes.hh"
Triangle::Triangle(Vertex v1, Vertex v2, Vertex v3, unsigned char r, unsigned char g, unsigned char b): v1(v1), v2(v2), v3(v3), r(r), g(g), b(b) {
// TODO : calcul de la normale.
normal = normalVector(v1,v2,v3);
// Triangle "rapide", sert juste aux calculs de coordonnées. Devrait
// être une superclasse de "triangle". Pour calculer le cosinus
// d'angles, on crée un objet triangle assez gros. C'est du
// gaspillage.
Triangle::Triangle(Vertex v1, Vertex v2, Vertex v3): v1(v1), v2(v2), v3(v3) {
}
Triangle::Triangle(Vertex v1, Vertex v2, Vertex v3, unsigned char r, unsigned char g, unsigned char b)
: v1(v1), v2(v2), v3(v3), r(r), g(g), b(b), vnormal(normal(v1,v2,v3)) {
}
std::ostream& operator<<(std::ostream& os, const Triangle* t) {
@ -13,11 +19,19 @@ std::ostream& operator<<(std::ostream& os, const Triangle& t) {
return os << "Triangle " << t.v1 << "--" << t.v2 << "--" << t.v3 << "-- cycle";
}
Vertexf Triangle::normalVector(Vertex v1, Vertex v2, Vertex v3) {
Vertexf Triangle::normal(Vertex v1, Vertex v2, Vertex v3) {
Vertexf normal = (v1 - v2)*(v2 - v3);
return normal / normal.norm();
}
float Triangle::cosAngle() {
return (v1-v2).cosAngle(v3-v2);
}
float Triangle::angle() {
return std::acos(cosAngle());
}
void Triangle::display() {
// glDisable(GL_LIGHTING);
// glDisable(GL_TEXTURE_2D);
@ -25,12 +39,12 @@ void Triangle::display() {
// glColor3ub(255,255,0);
// Vertex v = (v1 + v2 + v3) / 3;
// glVertex3d(v.x,v.y,v.z);
// glVertex3d(v.x+normal.x*50,v.y+normal.y*50,v.z+normal.z*50);
// glVertex3d(v.x+vnormal.x*50,v.y+vnormal.y*50,v.z+vnormal.z*50);
// glEnd( );
// glEnable(GL_LIGHTING);
View::setColor(r,g,b);
glNormal3d(normal.x,normal.y,normal.z);
glNormal3d(vnormal.x,vnormal.y,vnormal.z);
// glBegin(GL_TRIANGLES);
glVertex3d(v1.x,v1.y,v1.z);
glVertex3d(v2.x,v2.y,v2.z);

View File

@ -11,16 +11,19 @@ class Triangle {
unsigned char r;
unsigned char g;
unsigned char b;
Vertexf normal;
Vertexf vnormal;
public:
friend std::ostream& operator<<(std::ostream& os, const Triangle* t);
friend std::ostream& operator<<(std::ostream& os, const Triangle& t);
Triangle(Vertex v1, Vertex v2, Vertex v3);
Triangle(Vertex v1, Vertex v2, Vertex v3, unsigned char r, unsigned char g, unsigned char b);
float cosAngle(); // cosinus de l'angle en v2.
float angle(); // angle en v2, en degrés. TODO : le calcul ne donne que des angles entre 0 et 180 !
void display();
private :
Vertexf normalVector(Vertex v1, Vertex v2, Vertex v3);
Vertexf normal(Vertex v1, Vertex v2, Vertex v3);
};
#endif

View File

@ -45,10 +45,6 @@ float Vertex::cosAngle(Vertex v) {
return ((double)(this->x*v.x + this->y*v.y)) / (((double)norm())*((double)v.norm()));
}
float cosAngle(Vertex u, Vertex v, Vertex w) {
return (u-v).cosAngle(w-v);
}
Vertex::operator Vertexf() { return Vertexf(x,y,z); }
std::ostream& operator<<(std::ostream& os, const Vertex& v) {

View File

@ -18,7 +18,6 @@ class Vertex {
Vertex setNorm(int n);
Vertex perpendicular(); // Perpendiculaire 2D dans le sens contraire des aiguilles d'une montre.
float cosAngle(Vertex v); // cosinus de l'angle entre this et v.
friend float cosAngle(Vertex u, Vertex v, Vertex w);
static Vertex fromSpherical(float r, float xAngle, float yAngle);
friend Vertex intersection(Vertex a, Vertex b, Vertex c, Vertex d); // Intersection entre (a,b) et (c,d).