Merge branch 'master' of https://github.com/jsmaniac/2011-m2s3-city-builder
This commit is contained in:
commit
ef282b8e98
|
@ -15,6 +15,7 @@ class Chose;
|
|||
#include <GL/glu.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "angle.hh"
|
||||
#include "directions.hh"
|
||||
#include "vertex.hh"
|
||||
#include "segment.hh"
|
||||
|
@ -32,6 +33,8 @@ class Chose;
|
|||
#include "rules/quadrilatere.hh"
|
||||
#include "rules/quadcroix.hh"
|
||||
#include "rules/quadrect.hh"
|
||||
#include "rules/quadangle.hh"
|
||||
#include "rules/quadherbe.hh"
|
||||
#include "rules/tiletri.hh"
|
||||
|
||||
#endif
|
||||
|
|
6
angle.hh
Normal file
6
angle.hh
Normal file
|
@ -0,0 +1,6 @@
|
|||
namespace Angle {
|
||||
const float Pi = 3.141592653589793238462643383279;
|
||||
const double dPi = 3.141592653589793238462643383279;
|
||||
float r2d(float rad) { return rad / Pi * 180; }
|
||||
float d2r(float deg) { return deg / 180 * Pi; }
|
||||
};
|
46
quad.cpp
46
quad.cpp
|
@ -15,30 +15,42 @@ void Quad::offset(/*Cardinal*/int side, int offset) {
|
|||
corner[NW + side] = corner[NW + side] + voffset.projectOn(corner[NW + side]-corner[SW + side]);
|
||||
}
|
||||
|
||||
int Quad::minLength() {
|
||||
int Quad::minLengthNS() {
|
||||
return std::min(
|
||||
std::min(
|
||||
Segment(corner[NE],corner[SE]).length(),
|
||||
Segment(corner[SE],corner[SW]).length()
|
||||
), std::min(
|
||||
Segment(corner[SW],corner[NW]).length(),
|
||||
Segment(corner[NW],corner[NE]).length()
|
||||
)
|
||||
Segment(corner[NW],corner[NE]).length(),
|
||||
Segment(corner[SE],corner[SW]).length()
|
||||
);
|
||||
}
|
||||
|
||||
int Quad::maxLength() {
|
||||
return std::max(
|
||||
std::max(
|
||||
Segment(corner[NE],corner[SE]).length(),
|
||||
Segment(corner[SE],corner[SW]).length()
|
||||
), std::max(
|
||||
Segment(corner[SW],corner[NW]).length(),
|
||||
Segment(corner[NW],corner[NE]).length()
|
||||
)
|
||||
int Quad::minLengthEW() {
|
||||
return std::min(
|
||||
Segment(corner[NE],corner[SE]).length(),
|
||||
Segment(corner[SW],corner[NW]).length()
|
||||
);
|
||||
}
|
||||
|
||||
int Quad::maxLengthNS() {
|
||||
return std::max(
|
||||
Segment(corner[NW],corner[NE]).length(),
|
||||
Segment(corner[SE],corner[SW]).length()
|
||||
);
|
||||
}
|
||||
|
||||
int Quad::maxLengthEW() {
|
||||
return std::max(
|
||||
Segment(corner[NE],corner[SE]).length(),
|
||||
Segment(corner[SW],corner[NW]).length()
|
||||
);
|
||||
}
|
||||
|
||||
int Quad::minLength() {
|
||||
return std::min(minLengthNS(), minLengthEW());
|
||||
}
|
||||
|
||||
int Quad::maxLength() {
|
||||
return std::max(maxLengthNS(), maxLengthEW());
|
||||
}
|
||||
|
||||
float Quad::minAngle() {
|
||||
float a = 370; // > 360.
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
|
4
quad.hh
4
quad.hh
|
@ -11,6 +11,10 @@ public:
|
|||
Quad();
|
||||
Quad(Vertex ne, Vertex se, Vertex sw, Vertex nw);
|
||||
void offset(/*Cardinal*/int side, int offset);
|
||||
int minLengthNS();
|
||||
int minLengthEW();
|
||||
int maxLengthNS();
|
||||
int maxLengthEW();
|
||||
int minLength();
|
||||
int maxLength();
|
||||
float minAngle();
|
||||
|
|
|
@ -13,6 +13,7 @@ public:
|
|||
Carrefour(Vertex ne, Vertex se, Vertex sw, Vertex nw);
|
||||
virtual bool subdivide();
|
||||
virtual void triangulation();
|
||||
// TODO : Carrefour::replacePoint (pour pouvoir transformer un carrefour 4 en carrefour 5 et +).
|
||||
public:
|
||||
friend std::ostream& operator<<(std::ostream& os, const Carrefour& c);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Carrefour* c);
|
||||
|
|
|
@ -35,4 +35,4 @@ void Chose::display() {
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int Chose::initialSeed = random_seed();
|
||||
unsigned int Chose::initialSeed = 1814949558;//random_seed();
|
||||
|
|
48
rules/quadangle.cpp
Normal file
48
rules/quadangle.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "all_includes.hh"
|
||||
|
||||
QuadAngle::QuadAngle(Vertex ne, Vertex se, Vertex sw, Vertex nw) : Quadrilatere(ne, se, sw, nw) {
|
||||
triangulation();
|
||||
}
|
||||
|
||||
bool QuadAngle::subdivide() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (Triangle(corner[NW+i], corner[NE+i], corner[SE+i]).angle() >= Angle::d2r(130)) {
|
||||
Triangle t1(corner[NE+i], corner[SE+i], corner[SW+i]);
|
||||
t1.offsetBase(-hrw);
|
||||
Triangle t2(corner[SW+i], corner[NW+i], corner[NE+i]);
|
||||
t2.offsetBase(-hrw);
|
||||
addChild(TileTri::factory(seed, 0, t1.v1, t1.v2, t1.v3));
|
||||
addChild(TileTri::factory(seed, 1, t2.v1, t2.v2, t2.v3));
|
||||
addChild(new Route(t1.v1, t1.v3, t2.v1, t2.v3));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (Triangle(corner[NW+i], corner[NE+i], corner[SE+i]).angle() <= Angle::d2r(50)) {
|
||||
// "couper ce coin".
|
||||
Vertex n = (corner[NW+i] + corner[NE+i]) / 2;
|
||||
Vertex e = (corner[NE+i] + corner[SE+i]) / 2;
|
||||
Triangle tn = Triangle(n, corner[NE+i], corner[SE+i]);
|
||||
Triangle te = Triangle(corner[NW+i], corner[NE+i], e);
|
||||
Triangle t;
|
||||
Quad q;
|
||||
if (tn.minAngle() > te.minAngle()) {
|
||||
t = tn;
|
||||
q = Quad(n, corner[SE+i], corner[SW+i], corner[NW+i]);
|
||||
} else {
|
||||
t = te;
|
||||
q = Quad(corner[NW+i], e, corner[SE+i], corner[SW+i]);
|
||||
}
|
||||
t.offsetBase(-hrw);
|
||||
addChild(TileTri::factory(seed, 0, t.v1, t.v2, t.v3));
|
||||
q.offset(E, -hrw);
|
||||
addChild(Quadrilatere::factory(seed, 1, q.corner[0], q.corner[1], q.corner[2], q.corner[3]));
|
||||
addChild(new Route(t.v1, t.v3, q.corner[1], q.corner[0]));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Ne devait jamais arriver ici !
|
||||
addChild(new QuadHerbe(corner[NE], corner[SE], corner[SW], corner[NW]));
|
||||
return true;
|
||||
}
|
15
rules/quadangle.hh
Normal file
15
rules/quadangle.hh
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef _RULES_QUAD_ANGLE_HH_
|
||||
#define _RULES_QUAD_ANGLE_HH_
|
||||
|
||||
#include "all_includes.hh"
|
||||
|
||||
// QuadAngle est un quadrilatère avec des angles malfichus (< 90-40 ou > 90+40).
|
||||
class QuadAngle : public Quadrilatere {
|
||||
private:
|
||||
static const int hrw = 150; // half road width : 2,50m.
|
||||
public:
|
||||
QuadAngle(Vertex ne, Vertex se, Vertex sw, Vertex nw);
|
||||
virtual bool subdivide();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -10,28 +10,23 @@ 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) {
|
||||
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)) {
|
||||
bool small = q.minLength() < 2500;
|
||||
bool big = q.maxLength() >= 5000;
|
||||
bool anglesAcceptable = q.minAngle() > Angle::d2r(30) && q.maxAngle() < Angle::d2r(150);
|
||||
bool anglesOk = q.minAngle() > Angle::d2r(50) && q.maxAngle() < Angle::d2r(130);
|
||||
bool tooWideX = q.minLengthEW() * 2 < q.maxLengthNS(); // trop allongé (côté E ou W deux fois plus petit que le côté N ou S).
|
||||
bool tooWideY = q.minLengthNS() * 2 < q.maxLengthEW(); // trop allongé (côté N ou S deux fois plus petit que le côté E ou W).
|
||||
if (!big && proba(seed, n, 1, 20)) {
|
||||
return new QuadHerbe(ne, se, sw, nw);
|
||||
} else if (minLength < 2500 && minAngle > 50/180.f*3.1415926535 && maxAngle < 130/180.f*3.1415926535) { // + contrainte sur les angles
|
||||
} else if (small && anglesAcceptable) {
|
||||
return new Batiment(ne, se, sw, nw);
|
||||
} else if (minAngle <= 50/180.f*3.1415926535 && maxAngle >= 130/180.f*3.1415926535) {
|
||||
// angles trop pointus
|
||||
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 (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 (minLength > 2500) {
|
||||
} else if (!small && !anglesOk) {
|
||||
return new QuadAngle(ne, se, sw, nw);
|
||||
} else if (!small && tooWideY) {
|
||||
return new QuadRect(nw, ne, se, sw);
|
||||
} else if (!small && tooWideX) {
|
||||
return new QuadRect(ne, se, sw, nw);
|
||||
} else if (!small) {
|
||||
return new QuadCroix(ne, se, sw, nw);
|
||||
} else {
|
||||
return new QuadHerbe(ne, se, sw, nw);
|
||||
|
|
45
rules/tiletri.cpp
Normal file
45
rules/tiletri.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include "all_includes.hh"
|
||||
|
||||
TileTri::TileTri(Vertex left, Vertex top, Vertex right) : Chose() {
|
||||
addEntropy(left, top, right);
|
||||
corner[0] = left;
|
||||
corner[1] = top;
|
||||
corner[2] = right;
|
||||
triangulation();
|
||||
}
|
||||
|
||||
Chose* TileTri::factory(int seed, int n, Vertex left, Vertex top, Vertex right) {
|
||||
(void)seed;
|
||||
(void)n;
|
||||
return new TileTri(left, top, right);
|
||||
// Quad q = Quad(ne,se,sw,nw);
|
||||
// bool small = q.minLength() < 2500;
|
||||
// bool big = q.maxLength() >= 5000;
|
||||
// bool anglesOk = q.minAngle() > Angle::d2r(50) && q.maxAngle() < Angle::d2r(130);
|
||||
// bool tooWideX = q.minLengthEW() * 2 < q.maxLengthNS(); // trop allongé (côté E ou W deux fois plus petit que le côté N ou S).
|
||||
// bool tooWideY = q.minLengthNS() * 2 < q.maxLengthEW(); // trop allongé (côté N ou S deux fois plus petit que le côté E ou W).
|
||||
// if (!big && proba(seed, n, 1, 20)) {
|
||||
// return new QuadHerbe(ne, se, sw, nw);
|
||||
// } else if (small && anglesOk) {
|
||||
// return new Batiment(ne, se, sw, nw);
|
||||
// } else if (!anglesOk) {
|
||||
// return new QuadAngle(ne, se, sw, nw);
|
||||
// } else if (!small && tooWideY) {
|
||||
// return new QuadRect(nw, ne, se, sw);
|
||||
// } else if (!small && tooWideX) {
|
||||
// return new QuadRect(ne, se, sw, nw);
|
||||
// } else if (!small) {
|
||||
// return new QuadCroix(ne, se, sw, nw);
|
||||
// } else {
|
||||
// return new QuadHerbe(ne, se, sw, nw);
|
||||
// }
|
||||
}
|
||||
|
||||
bool TileTri::subdivide() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void TileTri::triangulation() {
|
||||
triangles.reserve(1);
|
||||
addTriangle(new Triangle(corner[0], corner[1], corner[2], 0xf0, 0xc0, 0xc0));
|
||||
}
|
17
rules/tiletri.hh
Normal file
17
rules/tiletri.hh
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef _RULES_TRIANGLE_HH_
|
||||
#define _RULES_TRIANGLE_HH_
|
||||
|
||||
#include "all_includes.hh"
|
||||
|
||||
// RectangleRoutes est un quadrilatère de routes avec des angles aux coins égaux à 90°.
|
||||
class TileTri : public Chose {
|
||||
public:
|
||||
Vertex corner[3];
|
||||
public:
|
||||
TileTri(Vertex left, Vertex top, Vertex right);
|
||||
virtual bool subdivide();
|
||||
virtual void triangulation();
|
||||
static Chose* factory(int seed, int n, Vertex left, Vertex top, Vertex right);
|
||||
};
|
||||
|
||||
#endif
|
17
triangle.cpp
17
triangle.cpp
|
@ -4,6 +4,8 @@
|
|||
// ê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() {
|
||||
}
|
||||
Triangle::Triangle(Vertex v1, Vertex v2, Vertex v3): v1(v1), v2(v2), v3(v3) {
|
||||
}
|
||||
|
||||
|
@ -32,6 +34,21 @@ float Triangle::angle() {
|
|||
return std::acos(cosAngle());
|
||||
}
|
||||
|
||||
float Triangle::minAngle() {
|
||||
float a2 = angle();
|
||||
float a3 = Triangle(v2,v3,v1).angle();
|
||||
float a1 = Angle::Pi - a2 - a3;
|
||||
return std::min(std::min(a1, a2), a3);
|
||||
}
|
||||
|
||||
void Triangle::offsetBase(int offset) {
|
||||
Quad q = Quad(v2, v1, v3, v2);
|
||||
q.offset(S, -offset);
|
||||
v1 = q.corner[1];
|
||||
v2 = q.corner[0];
|
||||
v3 = q.corner[2];
|
||||
}
|
||||
|
||||
void Triangle::display() {
|
||||
// glDisable(GL_LIGHTING);
|
||||
// glDisable(GL_TEXTURE_2D);
|
||||
|
|
|
@ -16,10 +16,13 @@ class Triangle {
|
|||
public:
|
||||
friend std::ostream& operator<<(std::ostream& os, const Triangle* t);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Triangle& t);
|
||||
Triangle();
|
||||
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 !
|
||||
float minAngle(); // angle minimum du triangle (en v1, v2 ou v3).
|
||||
void offsetBase(int offset);
|
||||
void display();
|
||||
|
||||
private :
|
||||
|
|
Loading…
Reference in New Issue
Block a user