quad.cpp (6913B)
1 #include "all_includes.hh" 2 3 Quad::Quad() {} 4 5 Quad::Quad(Vertex ne, Vertex se, Vertex sw, Vertex nw) { 6 c[(int)NE] = ne; 7 c[(int)SE] = se; 8 c[(int)SW] = sw; 9 c[(int)NW] = nw; 10 } 11 12 Quad Quad::inset(Cardinal side, float offset) const { 13 Quad q = (*this) << int(side); 14 Vertex offsetDirection = Triangle(q[NE], q[NW], q[NW] + q.normal()).normal(); 15 Vertex e = q[SE] - q[NE]; 16 Vertex w = q[SW] - q[NW]; 17 float distE = offset / offsetDirection.cosAngle(e); 18 float distW = offset / offsetDirection.cosAngle(w); 19 q[NE] = q[NE] + e.setNorm(distE); 20 q[NW] = q[NW] + w.setNorm(distW); 21 return q >> int(side); 22 } 23 24 Quad Quad::insetNESW(float offsetN, float offsetE, float offsetS, float offsetW) const { 25 return (*this).inset(N,offsetN).inset(E,offsetE).inset(S,offsetS).inset(W,offsetW); 26 } 27 28 Quad Quad::insetNESW(float offset) const { 29 return insetNESW(offset, offset, offset, offset); 30 } 31 32 Quad Quad::insetOpp(Cardinal side, float offset) const { 33 Quad q = (*this) << side; 34 Quad qi = q.inset(N,offset); 35 return (Quad(q[NE],qi[NE],qi[NW],q[NW]) >> side); 36 } 37 38 Quad Quad::makeParallelogram() const { 39 float l1, l2; 40 Quad q(c[NE],c[SE],c[SW],c[NW]); 41 42 if(length(N) < length(S)) { 43 if((l1 = length(E)) < (l2 = length(W))) { 44 q[SW] = Segment(q[NW],q[SW]).reduce(l1).v; 45 q[SE] = q[SW] + (q[NE] - q[NW]); 46 } 47 else if((l1 = length(E)) > (l2 = length(W))) { 48 q[SE] = Segment(q[NE],q[SE]).reduce(l2).v; 49 q[SW] = q[SE] + (q[NW] - q[NE]); 50 } 51 } 52 else { 53 if((l1 = length(E)) < (l2 = length(W))) { 54 q[NW] = Segment(q[SW],q[NW]).reduce(l1).v; 55 q[NE] = q[NW] + (q[SE] - q[SW]); 56 } 57 else if((l1 = length(E)) > (l2 = length(W))) { 58 q[NE] = Segment(q[SE],q[NE]).reduce(l2).v; 59 q[NW] = q[NE] + (q[SW] - q[SE]); 60 } 61 } 62 63 return q; 64 } 65 66 float Quad::length(Cardinal side) const { 67 return Segment(c[NW+int(side)],c[NE+int(side)]).length(); 68 } 69 70 float Quad::minLengthNS() const { 71 return std::min(length(N), length(S)); 72 } 73 74 float Quad::minLengthEW() const { 75 return std::min(length(E), length(W)); 76 } 77 78 float Quad::maxLengthNS() const { 79 return std::max(length(N), length(S)); 80 } 81 82 float Quad::maxLengthEW() const { 83 return std::max(length(E), length(W)); 84 } 85 86 float Quad::minLength() const { 87 return std::min(minLengthNS(), minLengthEW()); 88 } 89 90 float Quad::maxLength() const { 91 return std::max(maxLengthNS(), maxLengthEW()); 92 } 93 94 Cardinal Quad::minLengthSide() const { 95 float ln = length(N); 96 float le = length(E); 97 float ls = length(S); 98 float lw = length(W); 99 if (ln < le && ln < ls && ln < lw) return N; 100 else if (le < ls && le < lw) return E; 101 else if (ls < lw) return S; 102 else return W; 103 } 104 105 Cardinal Quad::maxLengthSide() const { 106 float ln = length(N); 107 float le = length(E); 108 float ls = length(S); 109 float lw = length(W); 110 if (ln > le && ln > ls && ln > lw) return N; 111 else if (le > ls && le > lw) return E; 112 else if (ls > lw) return S; 113 else return W; 114 } 115 116 float Quad::angle(Coin corner) const { 117 return Triangle(c[NW+corner], c[NE+corner], c[SE+corner]).angle(); 118 } 119 120 float Quad::minAngle() const { 121 float ane = angle(NE); 122 float ase = angle(SE); 123 float asw = angle(SW); 124 float anw = 2*Angle::Pi - (ane + ase + asw); 125 return std::min(std::min(ane, ase), std::min(asw, anw)); 126 } 127 128 float Quad::maxAngle() const { 129 float ane = angle(NE); 130 float ase = angle(SE); 131 float asw = angle(SW); 132 float anw = 2*Angle::Pi - (ane + ase + asw); 133 return std::max(std::max(ane, ase), std::max(asw, anw)); 134 } 135 136 Coin Quad::minAngleCorner() const { 137 float ane = angle(NE); 138 float ase = angle(SE); 139 float asw = angle(SW); 140 float anw = 2*Angle::Pi - (ane + ase + asw); 141 if (ane < ase && ane < asw && ane < anw) return NE; 142 else if (ase < asw && ase < anw) return SE; 143 else if (asw < anw) return SW; 144 else return NW; 145 } 146 147 Coin Quad::maxAngleCorner() const { 148 float ane = angle(NE); 149 float ase = angle(SE); 150 float asw = angle(SW); 151 float anw = 2*Angle::Pi - (ane + ase + asw); 152 if (ane > ase && ane > asw && ane > anw) return NE; 153 else if (ase > asw && ase > anw) return SE; 154 else if (asw > anw) return SW; 155 else return NW; 156 } 157 158 Coin Quad::concaveCorner() { 159 Vertex nne = Triangle(c[NW], c[NE], c[SE]).normalizedNormal(); 160 Vertex nse = Triangle(c[NE], c[SE], c[SW]).normalizedNormal(); 161 Vertex nsw = Triangle(c[SE], c[SW], c[NW]).normalizedNormal(); 162 Vertex nnw = Triangle(c[SW], c[NW], c[NE]).normalizedNormal(); 163 164 float dne1 = (nnw - nne).norm(); 165 float dne2 = (nse - nne).norm(); 166 float dse1 = (nne - nse).norm(); 167 float dse2 = (nsw - nse).norm(); 168 float dsw1 = (nse - nsw).norm(); 169 float dsw2 = (nnw - nsw).norm(); 170 float dnw1 = (nsw - nnw).norm(); 171 float dnw2 = (nne - nnw).norm(); 172 173 if(dne1 >= 1.5 && dne2 >= 1.5) 174 return NE; 175 else if(dse1 >= 1.5 && dse2 >= 1.5) 176 return SE; 177 else if(dsw1 >= 1.5 && dsw2 >= 1.5) 178 return SW; 179 else if(dnw1 >= 1.5 && dnw2 >= 1.5) 180 return NW; 181 else 182 return maxAngleCorner(); 183 } 184 185 bool Quad::isConcave() { 186 Vertex nne = Triangle(c[NW], c[NE], c[SE]).normalizedNormal(); 187 Vertex nse = Triangle(c[NE], c[SE], c[SW]).normalizedNormal(); 188 Vertex nsw = Triangle(c[SE], c[SW], c[NW]).normalizedNormal(); 189 Vertex nnw = Triangle(c[SW], c[NW], c[NE]).normalizedNormal(); 190 191 float dne1 = (nnw - nne).norm(); 192 float dse1 = (nne - nse).norm(); 193 float dsw1 = (nse - nsw).norm(); 194 float dnw1 = (nsw - nnw).norm(); 195 196 if(dne1 >= 1.5 || dse1 >= 1.5 || dsw1 >= 1.5 || dnw1 >= 1.5) 197 return true; 198 199 return (maxAngle() > Angle::d2r(160)); 200 } 201 202 Quad operator+(const Quad& q, const Vertex& v) { 203 return Quad(q[NE] + v, q[SE] + v, q[SW] + v, q[NW] + v); 204 } 205 206 Vertex Quad::randomPoint(int seed, int n) const { 207 Triangle ne(c[NW], c[NE], c[SE]); 208 Triangle sw(c[SE], c[SW], c[NW]); 209 float surfacene = ne.surface(); 210 float surfacesw = sw.surface(); 211 if (proba(seed, n, surfacene / (surfacene + surfacesw))) { 212 return ne.randomPoint(seed, hash2(n, 42)); 213 } else { 214 return sw.randomPoint(seed, hash2(n, 42)); 215 } 216 } 217 218 float Quad::surface() const { 219 Triangle ne(c[NW], c[NE], c[SE]); 220 Triangle sw(c[SE], c[SW], c[NW]); 221 return ne.surface() + sw.surface(); 222 } 223 224 Quad Quad::insetProportionnal(float prop) { 225 Quad rQuad= *this; 226 227 Vertex bc = Segment(Segment(c[NW],c[NE]).center(),Segment(c[SW],c[SE]).center()).center(); 228 229 rQuad[NW] = Segment(bc,c[NW]).at(prop); 230 rQuad[NE] = Segment(bc,c[NE]).at(prop); 231 rQuad[SE] = Segment(bc,c[SE]).at(prop); 232 rQuad[SW] = Segment(bc,c[SW]).at(prop); 233 return rQuad; 234 } 235 236 Quad Quad::offsetNormal(float offset) const { 237 return ((*this) + Triangle(c[NE], c[SE], c[SW]).normal().setNorm(offset)); 238 } 239 240 Vertex Quad::normal() const { 241 return Triangle(c[NE], c[SE], c[SW]).normal(); 242 } 243 244 Vertex Quad::normalizedNormal() const { 245 return Triangle(c[NE], c[SE], c[SW]).normalizedNormal(); 246 } 247 248 Vertex Quad::moyenne() const { 249 return ((c[NE] + c[SE] + c[SW] + c[NW]) / 4.f); 250 }