00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "transformation-matrix.hh"
00026 #include <cassert>
00027
00028 INLINE
00029 CVertex CGeometry::orthoProjectVertexOnLine(const CVertex& AVertex,
00030 const CVertex& ALineVertex,
00031 const CVertex& ALineDirection)
00032 {
00033 assert(!ALineDirection.isNull());
00034
00035 TCoordinate n2 = ALineDirection.sqrNorm();
00036
00037 assert(!isZero(n2));
00038
00039 TCoordinate t =
00040 ( ( AVertex.getX() - ALineVertex.getX() ) * ALineDirection.getX() +
00041 ( AVertex.getY() - ALineVertex.getY() ) * ALineDirection.getY() +
00042 ( AVertex.getZ() - ALineVertex.getZ() ) * ALineDirection.getZ() ) / n2;
00043
00044 return ALineVertex + t*ALineDirection;
00045 }
00046
00047 INLINE
00048 CVertex CGeometry::orthoProjectVertexOnPlane(const CVertex& AVertex,
00049 const TCoordinate& AA,
00050 const TCoordinate& AB,
00051 const TCoordinate& AC,
00052 const TCoordinate& AD)
00053 {
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #define X (AVertex.getX())
00081 #define Y (AVertex.getY())
00082 #define Z (AVertex.getZ())
00083
00084 TCoordinate t = - (AA*X + AB*Y + AC*Z + AD) / (sqr(AA) + sqr(AB) + sqr(AC));
00085
00086 return CVertex(X + AA*t, Y + AB*t, Z + AC*t);
00087
00088 #undef X
00089 #undef Y
00090 #undef Z
00091 }
00092
00093 INLINE
00094 CVertex CGeometry::orthoProjectVertexOnPlane(const CVertex& AVertex,
00095 const CVertex& APlaneVertex,
00096 const CVertex& APlaneNormal)
00097 {
00098 assert(!APlaneNormal.isNull());
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #define A (APlaneNormal.getX())
00113 #define B (APlaneNormal.getY())
00114 #define C (APlaneNormal.getZ())
00115 #define D (- (A * APlaneVertex.getX() + \
00116 B * APlaneVertex.getY() + \
00117 C * APlaneVertex.getZ()))
00118
00119 return orthoProjectVertexOnPlane(AVertex, A, B, C, D);
00120
00121 #undef A
00122 #undef B
00123 #undef C
00124 #undef D
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 INLINE
00136 CVertex CGeometry::centralHomothety(const CVertex& AVertex,
00137 const CVertex& ACenter,
00138 const TCoordinate& ACoef)
00139 {
00140 return ACenter + ACoef*(AVertex-ACenter);
00141 }
00142
00143 INLINE
00144 CVertex CGeometry::centralHomothety(const CVertex& AVertex,
00145 const CVertex& ACenter,
00146 const CVertex& ACoef)
00147 {
00148 return ACenter + ACoef.multiply(AVertex-ACenter);
00149 }
00150
00151 INLINE
00152 CVertex CGeometry::axialHomothety(const CVertex& AVertex,
00153 const CVertex& ALineVertex,
00154 const CVertex& ALineDirection,
00155 const TCoordinate& ACoef)
00156 {
00157 assert(!ALineDirection.isNull());
00158 CVertex center = orthoProjectVertexOnLine(AVertex,
00159 ALineVertex, ALineDirection);
00160 return center + ACoef*(AVertex-center);
00161 }
00162
00163 INLINE
00164 CVertex CGeometry::planarHomothety(const CVertex& AVertex,
00165 const CVertex& APlaneVertex,
00166 const CVertex& APlaneNormal,
00167 const TCoordinate& ACoef)
00168 {
00169 assert(!APlaneNormal.isNull());
00170 CVertex center = orthoProjectVertexOnPlane(AVertex,
00171 APlaneVertex, APlaneNormal);
00172 return center + ACoef*(AVertex-center);
00173 }
00174
00175 INLINE
00176 TCoordinate CGeometry::distanceToVertex(const CVertex& AVertex,
00177 const CVertex& AOtherVertex)
00178 {
00179 return (AVertex-AOtherVertex).norm();
00180 }
00181
00182 INLINE
00183 TCoordinate CGeometry::distanceToLine(const CVertex& AVertex,
00184 const CVertex& ALineVertex,
00185 const CVertex& ALineDirection)
00186 {
00187 CVertex proj = orthoProjectVertexOnLine(AVertex, ALineVertex, ALineDirection);
00188 return (AVertex-proj).norm();
00189 }
00190
00191 INLINE
00192 TCoordinate CGeometry::distanceToPlane(const CVertex& AVertex,
00193 const CVertex& APlaneVertex,
00194 const CVertex& APlaneNormal)
00195 {
00196 CVertex proj = orthoProjectVertexOnPlane(AVertex, APlaneVertex, APlaneNormal);
00197 return (AVertex-proj).norm();
00198 }
00199
00200 INLINE
00201 CVertex CGeometry::getBissectrix(const CVertex& AVector1,
00202 const CVertex& AVector2,
00203 const CVertex& ANormal)
00204 {
00205 assert(!AVector1.isNull());
00206 assert(!AVector2.isNull());
00207
00208 CVertex V1 = AVector1 / AVector1.norm();
00209 CVertex V2 = AVector2 / AVector2.norm();
00210
00211 if ((V1+V2).isNull())
00212 {
00213 if (ANormal.isNull())
00214 return getNormalVector(V1);
00215 else
00216 return V1*ANormal;
00217 }
00218 else
00219 {
00220 if (isPositive((AVector1*AVector2).dot(ANormal)))
00221 return V1+V2;
00222 else
00223 return -(V1+V2);
00224 }
00225 }
00226
00227 INLINE
00228 CVertex CGeometry::getNormalVector(const CVertex& AVector)
00229 {
00230 assert(!AVector.isNull());
00231
00232 if (isZero(AVector.getX()))
00233 return AVector.norm()*OX;
00234
00235
00236
00237
00238 CVertex V(-AVector.getY(), AVector.getX(), 0);
00239
00240 return (AVector.norm()/V.norm()) * V;
00241 }
00242
00243 INLINE
00244 CVertex CGeometry::getNormalVector(const CVertex& AVector1,
00245 const CVertex& AVector2)
00246 {
00247 TCoordinate n1 = AVector1.norm();
00248 TCoordinate n2 = AVector2.norm();
00249
00250 CVertex V = AVector1*AVector2;
00251
00252 if (V.isNull())
00253 return ORIGIN;
00254
00255 assert(!isZero(n1));
00256 assert(!isZero(n2));
00257
00258 return ((n1+n2)/(2*V.norm()))*V;
00259 }
00260
00261 INLINE
00262 CVertex CGeometry::getNormalVector(const CVertex& AVertex1,
00263 const CVertex& AVertex2,
00264 const CVertex& AVertex3)
00265 { return getNormalVector(AVertex2-AVertex1, AVertex3-AVertex2); }
00266
00267 INLINE
00268 CVertex CGeometry::getLinesIntersection(const CVertex& ALine1Vertex1,
00269 const CVertex& ALine1Vertex2,
00270 const CVertex& ALine2Vertex1,
00271 const CVertex& ALine2Vertex2)
00272 {
00273 assert(ALine1Vertex1 != ALine1Vertex2);
00274 assert(ALine2Vertex1 != ALine2Vertex2);
00275
00276 #define A (ALine1Vertex1)
00277 #define B (ALine1Vertex2)
00278 #define C (ALine2Vertex1)
00279 #define D (ALine2Vertex2)
00280
00281 CVertex AB = B - A;
00282 CVertex CD = D - C;
00283 CVertex AC = C - A;
00284
00285 CVertex ABvCD = AB*CD;
00286
00287 TCoordinate t = det(AC,CD,ABvCD) / ABvCD.sqrNorm();
00288
00289 return A + t*AB;
00290
00291 #undef A
00292 #undef B
00293 #undef C
00294 #undef D
00295 }
00296
00297 INLINE
00298 bool CGeometry::areColinear(const CVertex& AVector1,
00299 const CVertex& AVector2)
00300 {
00301 return (AVector1*AVector2).isNull();
00302 }
00303
00304 INLINE
00305 TCoordinate CGeometry::getAngle(const CVertex& AVector1,
00306 const CVertex& AVector2,
00307 const CVertex& ANormal)
00308 {
00309
00310
00311 CVertex v1 = AVector1;
00312 CVertex v2 = AVector2;
00313 CVertex n = ANormal;
00314
00315 if (!v1.isNull()) v1 /= v1.norm();
00316 if (!v2.isNull()) v2 /= v2.norm();
00317 if (!n .isNull()) n /= n .norm();
00318
00319 TCoordinate cosinus = v1.dot(v2);
00320
00321 if (cosinus > +1) cosinus = +1;
00322 if (cosinus < -1) cosinus = -1;
00323
00324 TCoordinate angle = dAcos(cosinus);
00325
00326 return isPositive((v1*v2).dot(n)) ? +angle : -angle;
00327 }
00328
00329 INLINE
00330 CVertex CGeometry::getAngles(const CVertex& AVx,
00331 const CVertex& AVz)
00332 {
00333 if (AVx.isNull() || AVz.isNull())
00334 return ORIGIN;
00335
00336 CTransformationMatrix matrix;
00337
00338 CVertex Vx(orthoProjectVertexOnPlane(AVx, ORIGIN, AVz));
00339 CVertex Vy(AVz*Vx);
00340 CVertex Vz(AVz);
00341
00342 TCoordinate alpha,beta,gamma;
00343
00344
00345
00346
00347
00348
00349 gamma = getAngle(CVertex(0,+Vz.getZ(),-Vz.getY()),Vy, Vz);
00350
00351 matrix.rotate(Vz, -gamma);
00352 matrix.applyOn(Vx);
00353 matrix.applyOn(Vy);
00354
00355
00356
00357 beta = getAngle(OX,Vx, Vy);
00358
00359 matrix.setToIdentity();
00360 matrix.rotate(Vy, -beta);
00361 matrix.applyOn(Vx);
00362 matrix.applyOn(Vz);
00363
00364
00365
00366 alpha = getAngle(OZ,Vz, Vx);
00367
00368 return CVertex(alpha,beta,gamma);
00369 }
00370
00371 INLINE
00372 int CGeometry::localiseVertexComparedToLine(const CVertex& AVertex,
00373 const CVertex& ALineVertex,
00374 const CVertex& ALineDirection,
00375 const CVertex& APlaneNormal)
00376 {
00377 assert(!ALineDirection.isNull());
00378 assert(!APlaneNormal.isNull());
00379
00380 CVertex direction = ALineDirection / ALineDirection.norm();
00381 CVertex normal = APlaneNormal / APlaneNormal .norm();
00382
00383 return sign((direction * normal).dot(AVertex-ALineVertex));
00384 }
00385
00386 INLINE
00387 void CGeometry::getSegmentsIntersection(const CVertex& AVertexA,
00388 const CVertex& AVertexB,
00389 const CVertex& AVertexC,
00390 const CVertex& AVertexD,
00391 const CVertex& APlaneNormal,
00392 int& AIntersection1On,
00393 CVertex& AIntersection1,
00394 int& AIntersection2On,
00395 CVertex& AIntersection2)
00396 {
00397 assert(!APlaneNormal.isNull());
00398
00399 bool nullLength1 = AVertexA == AVertexB;
00400 bool nullLength2 = AVertexC == AVertexD;
00401
00402
00403 if (nullLength1 || nullLength2)
00404 {
00405
00406 if (nullLength1 && nullLength2)
00407 {
00408 AIntersection1On = AIntersection2On = 0;
00409 return;
00410 }
00411
00412
00413
00414 AIntersection1On = 0;
00415 AIntersection2On = 0;
00416
00417 return;
00418 }
00419
00420
00421 CVertex directionAB = AVertexB - AVertexA;
00422 CVertex directionCD = AVertexD - AVertexC;
00423
00424 int A = localiseVertexComparedToLine(AVertexA,
00425 AVertexC, directionCD,
00426 APlaneNormal);
00427
00428 int B = localiseVertexComparedToLine(AVertexB,
00429 AVertexC, directionCD,
00430 APlaneNormal);
00431
00432 if (A==0 && B==0)
00433 {
00434
00435
00436 const CVertex * vertices[4] =
00437 { & AVertexA, & AVertexB, & AVertexC, & AVertexD };
00438
00439 CVertex normal = directionAB * APlaneNormal;
00440
00441 assert(!normal.isNull());
00442 normal /= normal.norm();
00443
00444 int i,j;
00445
00446
00447
00448 for (i=0; i<3; ++i)
00449 for (j=i+1; j<4; ++j)
00450 if (localiseVertexComparedToLine(*vertices[i], *vertices[j],
00451 normal, APlaneNormal) == 1)
00452 {
00453 const CVertex * tmp = vertices[i];
00454 vertices[i] = vertices[j];
00455 vertices[j] = tmp;
00456 }
00457
00458 bool firstSegment[4];
00459
00460 for (i=0; i<4; ++i)
00461 firstSegment[i] = vertices[i]==&AVertexA || vertices[i]==&AVertexB;
00462
00463
00464 if (firstSegment[0]==firstSegment[1])
00465 {
00466
00467 AIntersection1On = AIntersection2On = 0;
00468 }
00469 else
00470 {
00471
00472 if (*vertices[0] == *vertices[1])
00473 AIntersection1On = 0;
00474 else
00475 {
00476 AIntersection1On = firstSegment[0] ? 1 : 2;
00477 AIntersection1 = * vertices[1];
00478 }
00479
00480 if (*vertices[2] == *vertices[3])
00481 AIntersection2On = 0;
00482 else
00483 {
00484 AIntersection2On = firstSegment[3] ? 1 : 2;
00485 AIntersection2 = * vertices[2];
00486 }
00487 }
00488 }
00489 else
00490 {
00491
00492 int C = localiseVertexComparedToLine(AVertexC,
00493 AVertexA, directionAB,
00494 APlaneNormal);
00495
00496 int D = localiseVertexComparedToLine(AVertexD,
00497 AVertexA, directionAB,
00498 APlaneNormal);
00499
00500
00501
00502 int combineAB = combineSigns(A,B);
00503 int combineCD = combineSigns(C,D);
00504
00505 AIntersection1On = (combineAB==-1 && combineCD<=0) ? 1 : 0;
00506 AIntersection2On = (combineCD==-1 && combineAB<=0) ? 2 : 0;
00507
00508 if (AIntersection1On!=0 || AIntersection2On!=0)
00509 {
00510 AIntersection1 = AIntersection2 =
00511 getLinesIntersection(AVertexA, AVertexB, AVertexC, AVertexD);
00512 }
00513 }
00514 }
00515
00516 INLINE
00517 void CGeometry::getSegmentsIntersection2d(const CVertex& AVertexA,
00518 const CVertex& AVertexB,
00519 const CVertex& AVertexC,
00520 const CVertex& AVertexD,
00521 int& AIntersection1On,
00522 CVertex& AIntersection1,
00523 int& AIntersection2On,
00524 CVertex& AIntersection2)
00525 {
00526 getSegmentsIntersection(AVertexA, AVertexB, AVertexC, AVertexD,
00527 OZ,
00528 AIntersection1On, AIntersection1,
00529 AIntersection2On, AIntersection2);
00530 }
00531
00532 INLINE
00533 CVertex CGeometry::getRoundingNormalVector(const CVertex& AVertex1,
00534 const CVertex& AVertex2,
00535 const CVertex& AVertex3)
00536 {
00537 #define A (AVertex1)
00538 #define B (AVertex2)
00539 #define C (AVertex3)
00540
00541 CVertex AB = B - A;
00542 CVertex AC = C - A;
00543
00544 if (CGeometry::areColinear(AB,AC))
00545 return A;
00546 else
00547 return AC * (AB * AC);
00548
00549 #undef A
00550 #undef B
00551 #undef C
00552 }
00553