quartier.cpp (8254B)
1 #include "all_includes.hh" 2 3 QuartierQuad::QuartierQuad(Quad _c) : Chose(), c(_c) { 4 addEntropy(c); 5 } 6 7 void QuartierQuad::getBoundingBoxPoints() { 8 addBBPoints(c, Dimensions::hauteurMaxBatiment); 9 } 10 11 void QuartierQuad::split() { 12 bool small = c.minLength() < 35 * 100; 13 bool big = (c.minLengthNS() > 100 * 100 || c.minLengthEW() > 100 * 100) && c.minLength() > 40*100 && c.maxLength() < 300*100; 14 bool isConcave = c.isConcave(); 15 bool nearConcave = c.maxAngle() > Angle::d2r(160); 16 bool anglesOk = c.minAngle() > Angle::d2r(90-40) && c.maxAngle() < Angle::d2r(90+40); 17 bool tooWideX = c.minLengthEW() * 2 < c.maxLengthNS(); // trop allongé (côté E ou W deux fois plus petit que le côté N ou S). 18 bool tooWideY = c.minLengthNS() * 2 < c.maxLengthEW(); // trop allongé (côté N ou S deux fois plus petit que le côté E ou W). 19 bool bigPlace = c.maxLength() > Dimensions::maxRayonPlace * 4; 20 bool tooBigPlace = c.maxLength() > Dimensions::maxRayonPlace * 8; 21 if (isConcave) 22 concave(); 23 else if (nearConcave) 24 angleAngle(); 25 else if (big && anglesOk && proba(seed, -2, 0.25f)) 26 longueRue(); 27 else if (!small && !anglesOk && proba(seed, -3, 0.5f)) 28 angleAngle(); 29 else if (!small && !anglesOk) 30 angleCote(); 31 else if (!small && (tooWideX || tooWideY)) 32 rect(); 33 else if (bigPlace && !tooBigPlace && proba(seed, -4, 0.4)) 34 place(); 35 else if (!small) 36 carre(); 37 else 38 addChild(new BatimentQuad(c)); 39 } 40 41 void QuartierQuad::triangulation() { 42 if (c.isConcave()) { 43 Quad q = c << c.concaveCorner(); 44 triangulationConcave(Triangle(q[NE], q[SE], q[SW])); 45 triangulationConcave(Triangle(q[SW], q[NW], q[NE])); 46 } else { 47 Quad ci = c.insetNESW(Dimensions::largeurRoute + Dimensions::largeurTrottoir); 48 Quad cih = ci.offsetNormal(Dimensions::hauteurMaxBatiment); 49 addGPUFourQuads(c, ci, Couleurs::route); 50 addGPUQuad(cih, Couleurs::toit); 51 for (int i = 0; i < 4; i++) 52 addGPUQuad(Quad(ci[NE+i], ci[SE+i], cih[SE+i], cih[NE+i]), Couleurs::mur); 53 } 54 } 55 56 void QuartierQuad::triangulationConcave(Triangle t) { 57 // Même code que QuartierTri::triangulation. 58 Triangle ci = t.insetLTR(Dimensions::largeurRoute + Dimensions::largeurTrottoir); 59 Triangle cih = ci.offsetNormal(Dimensions::hauteurMaxBatiment); 60 addGPUThreeQuads(t, ci, Couleurs::route); 61 addGPUTriangle(cih, Couleurs::toit); 62 for (int i = 0; i < 3; i++) 63 addGPUQuad(Quad(ci[LEFT+i], ci[TOP+i], cih[TOP+i], cih[LEFT+i]), Couleurs::mur); 64 } 65 66 void QuartierQuad::concave() { 67 Quad q = c << c.concaveCorner(); 68 addChild(new QuartierTri(Triangle(q[NE], q[SE], q[SW]))); 69 addChild(new QuartierTri(Triangle(q[SW], q[NW], q[NE]))); 70 } 71 72 void QuartierQuad::angleCote() { 73 Quad q = c << c.maxAngleCorner(); 74 Vertex s = Segment(q[SE], q[SW]).randomPos(seed, 1, 0.4f, 0.6f); 75 Vertex w = Segment(q[SW], q[NW]).randomPos(seed, 0, 0.4f, 0.6f); 76 Triangle ts(q[SE], s, q[NE]); 77 Triangle tw(q[NE], w, q[NW]); 78 if (ts.minAngle() > tw.minAngle()) { 79 addChild(new QuartierTri(ts)); 80 addChild(new QuartierQuad(Quad(q[NE], s, q[SW], q[NW]))); 81 } else { 82 addChild(new QuartierTri(tw)); 83 addChild(new QuartierQuad(Quad(q[NE], q[SE], q[SW], w))); 84 } 85 } 86 87 void QuartierQuad::angleAngle() { 88 Quad q = c << c.maxAngleCorner(); 89 addChild(new QuartierTri(Triangle(q[NE], q[SE], q[SW]))); 90 addChild(new QuartierTri(Triangle(q[SW], q[NW], q[NE]))); 91 } 92 93 void QuartierQuad::rect() { 94 Quad q = c << c.maxLengthSide(); 95 Vertex n = Segment(q[NW], q[NE]).randomPos(seed, 0, 1.f/3.f, 2.f/3.f); 96 Vertex s = Segment(q[SE], q[SW]).randomPos(seed, 1, 1.f/3.f, 2.f/3.f); 97 98 addChild(new QuartierQuad(Quad(q[NE], q[SE], s, n))); 99 addChild(new QuartierQuad(Quad(q[SW], q[NW], n, s))); 100 } 101 102 void QuartierQuad::carre() { 103 Vertex center = c.insetProportionnal(0.33f).randomPoint(seed, 0); 104 Vertex middle[4]; 105 for (int i = 0; i < 4; i++) 106 middle[N+i] = Segment(c[NW+i], c[NE+i]).randomPos(seed, i + 1, 0.25f, 0.75f); 107 108 for (int i = 0; i < 4; i++) 109 addChild(new QuartierQuad(Quad(c[NE+i], middle[E+i], center, middle[N+i]))); 110 } 111 112 void QuartierQuad::place() { 113 Vertex center = c.insetProportionnal(0.25f).randomPoint(seed, 0); 114 Vertex middle[4]; 115 for (int i = 0; i < 4; i++) 116 middle[N+i] = Segment(c[NW+i], c[NE+i]).randomPos(seed, i + 1, 0.45f, 0.55f); 117 118 Vertex smallOcto[8]; 119 Vertex interieur[8]; 120 Vertex bigOcto[8]; 121 float r = floatInRange(seed, 12345, Dimensions::minRayonPlace, Dimensions::maxRayonPlace); 122 float shift = std::tan(Angle::Pi/8.f) * r; 123 for (int i = 0; i < 4; i++) { 124 Quad q(c[NE+i], middle[E+i], center, middle[N+i]); 125 smallOcto[2*i] = q.inset(W, shift).inset(S, r)[SW]; 126 smallOcto[2*i+1] = q.inset(S, shift).inset(W, r)[SW]; 127 bigOcto[2*i] = q.inset(W, shift).inset(S, r)[NW]; 128 bigOcto[2*i+1] = q.inset(S, shift).inset(W, r)[SE]; 129 Triangle t = Triangle(smallOcto[2*i+1], center, smallOcto[2*i]).inset(BASE, Dimensions::largeurRoute + Dimensions::largeurTrottoir); 130 interieur[2*i] = t[RIGHT]; 131 interieur[2*i+1] = t[LEFT]; 132 } 133 134 for (int i = 0; i < 4; i++) { 135 addChild(new QuartierQuad(Quad(bigOcto[2*i], smallOcto[2*i], smallOcto[((2*i-1) + 8) % 8], bigOcto[((2*i-1) + 8) % 8]))); 136 addChild(new QuartierQuad(Quad(smallOcto[2*i+1], smallOcto[2*i], bigOcto[2*i], bigOcto[2*i+1]))); 137 addChild(new QuartierTri(Triangle(bigOcto[2*i], c[NE+i], bigOcto[2*i+1]))); 138 } 139 for (int i = 0; i < 8; i++) { 140 addChild(new RouteTrottoirQuad(Quad(smallOcto[i], smallOcto[(i+1)%8], interieur[(i+1)%8], interieur[i]))); 141 addChild(new TerrainTri(Triangle(interieur[(i+1)%8], center, interieur[i]))); 142 } 143 } 144 145 void QuartierQuad::longueRue() { 146 Quad q = c << c.maxLengthSide(); 147 Vertex e = Segment(q[NE], q[SE]).randomPos(seed, 0, 1.f/3.f, 2.f/3.f); 148 Vertex w = Segment(q[SW], q[NW]).randomPos(seed, 1, 1.f/3.f, 2.f/3.f); 149 Quad qn = Quad(q[NE], e, w, q[NW]).inset(S, 7*100); 150 Quad qs = Quad(q[SW], w, e, q[SE]).inset(S, 7*100); 151 152 addChild(new QuartierQuad(qn)); 153 addChild(new QuartierQuad(qs)); 154 addChild(new BatimentQuad(Quad(qn[SE], qs[SW], qs[SE], qn[SW]))); 155 } 156 157 QuartierTri::QuartierTri(Triangle _c) : Chose(), c(_c) { 158 addEntropy(c); 159 } 160 161 void QuartierTri::getBoundingBoxPoints() { 162 addBBPoints(c, Dimensions::hauteurMaxBatiment); 163 } 164 165 void QuartierTri::split() { 166 bool small = c.minLength() < 80 * 100; 167 bool big = c.maxLength() >= 150 * 100; 168 float minAngle = c.minAngle(); 169 float maxAngle = c.maxAngle(); 170 bool equilateral = maxAngle < Angle::d2r(60+15) && minAngle > Angle::d2r(60-15); 171 bool angleObtus = maxAngle > Angle::d2r(120); 172 bool angleAigu = minAngle < Angle::d2r(30); 173 bool anglesAcceptable = !angleAigu && !angleObtus; 174 if (!big && proba(seed, -1, 0.05f)) { 175 addChild(new BatimentTri(c)); 176 } else if (big && anglesAcceptable) { 177 switch (hash2(seed, -2) % 3) { 178 case 0: centre(); break; 179 case 1: hauteur(); break; 180 case 2: 181 default: trapeze(); break; 182 } 183 } else if (!small && equilateral) { 184 centre(); 185 } else if (!small && angleObtus) { 186 hauteur(); 187 } else if (!small) { 188 trapeze(); 189 } else { 190 addChild(new BatimentTri(c)); 191 } 192 } 193 194 void QuartierTri::triangulation() { 195 Triangle ci = c.insetLTR(Dimensions::largeurRoute + Dimensions::largeurTrottoir); 196 Triangle cih = ci.offsetNormal(Dimensions::hauteurMaxBatiment); 197 addGPUThreeQuads(c, ci, Couleurs::route); 198 addGPUTriangle(cih, Couleurs::toit); 199 for (int i = 0; i < 3; i++) 200 addGPUQuad(Quad(ci[LEFT+i], ci[TOP+i], cih[TOP+i], cih[LEFT+i]), Couleurs::mur); 201 } 202 203 void QuartierTri::centre() { 204 Vertex center = c.insetProportionnal(0.3f).randomPoint(seed, 0); 205 Vertex edge[3]; 206 for (int i = 0; i < 3; i++) 207 edge[LEFTSIDE+i] = Segment(c[LEFT+i], c[TOP+i]).randomPos(seed, i+1, 1.f/3.f, 2.f/3.f); 208 209 for (int i = 0; i < 3; i++) 210 addChild(new QuartierQuad(Quad(c[TOP+i], edge[RIGHTSIDE+i], center, edge[LEFTSIDE+i]))); 211 } 212 213 void QuartierTri::hauteur() { 214 Triangle t = c << c.maxAngleCorner(); 215 Vertex opposite = Segment(t[TOP], t[RIGHT]).randomPos(seed, 0, 1.f/3.f, 2.f/3.f); 216 217 addChild(new QuartierTri(Triangle(t[TOP], opposite, t[LEFT]))); 218 addChild(new QuartierTri(Triangle(t[LEFT], opposite, t[RIGHT]))); 219 } 220 221 void QuartierTri::trapeze() { 222 Triangle t = c << c.minAngleCorner(); 223 Vertex left = Segment(t[LEFT], t[TOP]).randomPos(seed, 0, 1.f/3.f, 2.f/3.f); 224 Vertex base = Segment(t[RIGHT], t[LEFT]).randomPos(seed, 1, 1.f/3.f, 2.f/3.f); 225 226 addChild(new QuartierTri(Triangle(base, t[LEFT], left))); 227 addChild(new QuartierQuad(Quad(base, left, t[TOP], t[RIGHT]))); 228 }