00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00026
00027 #include "glc_geomtools.h"
00028 #include "glc_matrix4x4.h"
00029
00030 #include <QtGlobal>
00031
00033
00035
00036
00037 bool glc::polygon2DIsConvex(const QList<GLC_Point2d>& vertices)
00038 {
00039 bool isConvex= true;
00040 const int size= vertices.size();
00041 if (vertices.size() > 3)
00042 {
00043 GLC_Point2d s0(vertices.at(0));
00044 GLC_Point2d s1(vertices.at(1));
00045 GLC_Point2d s2(vertices.at(2));
00046 const bool openAngle= ((s1.getX() - s0.getX()) * (s2.getY() - s0.getY()) - (s2.getX() - s0.getX()) * (s1.getY() - s0.getY())) < 0.0;
00047
00048 int i= 3;
00049 while ((i < size) && isConvex)
00050 {
00051 s0= s1;
00052 s1= s2;
00053 s2= vertices.at(i);
00054 isConvex= openAngle == (((s1.getX() - s0.getX()) * (s2.getY() - s0.getY()) - (s2.getX() - s0.getX()) * (s1.getY() - s0.getY())) < 0.0);
00055 ++i;
00056 }
00057 }
00058
00059 return isConvex;
00060 }
00061
00062 bool glc::polygonIsConvex(QList<GLuint>* pIndexList, const QList<float>& bulkList)
00063 {
00064 bool isConvex= true;
00065 const int size= pIndexList->size();
00066 GLuint currentIndex;
00067 GLC_Vector3d v0;
00068 GLC_Vector3d v1;
00069 int i= 0;
00070 while ((i < size) && isConvex)
00071 {
00072 currentIndex= pIndexList->at(i);
00073 v0.setVect(bulkList.at(currentIndex * 3), bulkList.at(currentIndex * 3 + 1), bulkList.at(currentIndex * 3 + 2));
00074 currentIndex= pIndexList->at((i + 1) % size);
00075 v1.setVect(bulkList.at(currentIndex * 3), bulkList.at(currentIndex * 3 + 1), bulkList.at(currentIndex * 3 + 2));
00076 isConvex= (v0.angleWithVect(v1) < glc::PI);
00077 ++i;
00078 }
00079 return isConvex;
00080 }
00081
00082 QVector<GLC_Point2d> glc::findIntersection(const GLC_Point2d& s1p1, const GLC_Point2d& s1p2, const GLC_Point2d& s2p1, const GLC_Point2d& s2p2)
00083 {
00084 const GLC_Vector2d D0= s1p2 - s1p1;
00085 const GLC_Vector2d D1= s2p2 - s2p1;
00086
00087 QVector<GLC_Point2d> result;
00088
00089 const GLC_Vector2d E(s2p1 - s1p1);
00090 double kross= D0 ^ D1;
00091 double sqrKross= kross * kross;
00092 const double sqrLen0= D0.getX() * D0.getX() + D0.getY() * D0.getY();
00093 const double sqrLen1= D1.getX() * D1.getX() + D1.getY() * D1.getY();
00094
00095 if (sqrKross > (EPSILON * sqrLen0 * sqrLen1))
00096 {
00097 const double s= (E ^ D1) / kross;
00098 if ((s < 0.0) || (s > 1.0))
00099 {
00100
00101 return result;
00102 }
00103 const double t= (E ^ D0) / kross;
00104
00105 if ((t < 0.0) || (t > 1.0))
00106 {
00107
00108 return result;
00109 }
00110
00111
00112 result << (s1p1 + (D0 * s));
00113 return result;
00114 }
00115
00116
00117 const double sqrLenE= E.getX() * E.getX() + E.getY() * E.getY();
00118 kross= E ^ D0;
00119 sqrKross= kross * kross;
00120 if (sqrKross > (EPSILON * sqrLen0 * sqrLenE))
00121 {
00122
00123 return result;
00124 }
00125
00126
00127 const double s0= (D0 * E) / sqrLen0;
00128 const double s1= (D0 * D1) / sqrLen0;
00129 const double sMin= qMin(s0, s1);
00130 const double sMax= qMax(s0, s1);
00131 QVector<double> overlaps= findIntersection(0.0, 1.0, sMin, sMax);
00132 const int iMax= overlaps.size();
00133 for (int i= 0; i < iMax; ++i)
00134 {
00135 result.append(s1p1 + (D0 * overlaps[i]));
00136 }
00137 return result;
00138 }
00139
00140
00141 bool glc::isIntersected(const GLC_Point2d& s1p1, const GLC_Point2d& s1p2, const GLC_Point2d& s2p1, const GLC_Point2d& s2p2)
00142 {
00143 const GLC_Vector2d D0= s1p2 - s1p1;
00144 const GLC_Vector2d D1= s2p2 - s2p1;
00145
00146 const GLC_Vector2d E(s2p1 - s1p1);
00147 double kross= D0 ^ D1;
00148 double sqrKross= kross * kross;
00149 const double sqrLen0= D0.getX() * D0.getX() + D0.getY() * D0.getY();
00150 const double sqrLen1= D1.getX() * D1.getX() + D1.getY() * D1.getY();
00151
00152 if (sqrKross > (EPSILON * sqrLen0 * sqrLen1))
00153 {
00154 const double s= (E ^ D1) / kross;
00155 if ((s < 0.0) || (s > 1.0))
00156 {
00157
00158 return false;
00159 }
00160 const double t= (E ^ D0) / kross;
00161
00162 if ((t < 0.0) || (t > 1.0))
00163 {
00164
00165 return false;
00166 }
00167
00168
00169 return true;
00170 }
00171
00172
00173 const double sqrLenE= E.getX() * E.getX() + E.getY() * E.getY();
00174 kross= E ^ D0;
00175 sqrKross= kross * kross;
00176 if (sqrKross > (EPSILON * sqrLen0 * sqrLenE))
00177 {
00178
00179 return false;
00180 }
00181
00182
00183 const double s0= (D0 * E) / sqrLen0;
00184 const double s1= s0 + (D0 * D1) / sqrLen0;
00185 const double sMin= qMin(s0, s1);
00186 const double sMax= qMax(s0, s1);
00187 if (findIntersection(0.0, 1.0, sMin, sMax).size() == 0) return false; else return true;
00188
00189 }
00190
00191
00192 bool glc::isIntersectedRaySegment(const GLC_Point2d& s1p1, const GLC_Vector2d& s1p2, const GLC_Point2d& s2p1, const GLC_Point2d& s2p2)
00193 {
00194 const GLC_Vector2d D0= s1p2 - s1p1;
00195 const GLC_Vector2d D1= s2p2 - s2p1;
00196
00197 const GLC_Vector2d E(s2p1 - s1p1);
00198 double kross= D0 ^ D1;
00199 double sqrKross= kross * kross;
00200 const double sqrLen0= D0.getX() * D0.getX() + D0.getY() * D0.getY();
00201 const double sqrLen1= D1.getX() * D1.getX() + D1.getY() * D1.getY();
00202
00203 if (sqrKross > (EPSILON * sqrLen0 * sqrLen1))
00204 {
00205 const double s= (E ^ D1) / kross;
00206 if ((s < 0.0))
00207 {
00208
00209 return false;
00210 }
00211 const double t= (E ^ D0) / kross;
00212
00213 if ((t < 0.0) || (t > 1.0))
00214 {
00215
00216 return false;
00217 }
00218
00219
00220 return true;
00221 }
00222
00223
00224 const double sqrLenE= E.getX() * E.getX() + E.getY() * E.getY();
00225 kross= E ^ D0;
00226 sqrKross= kross * kross;
00227 if (sqrKross > (EPSILON * sqrLen0 * sqrLenE))
00228 {
00229
00230 return false;
00231 }
00232 else return true;
00233
00234 }
00235
00236
00237 QVector<double> glc::findIntersection(const double& u0, const double& u1, const double& v0, const double& v1)
00238 {
00239
00240 QVector<double> result;
00241 if (u1 < v0 || u0 > v1) return result;
00242
00243 if (u1 > v0)
00244 {
00245 if (u0 < v1)
00246 {
00247 if (u0 < v0) result.append(v0); else result.append(u0);
00248 if (u1 > v1) result.append(v1); else result.append(u1);
00249 return result;
00250 }
00251 else
00252 {
00253 result.append(u0);
00254 return result;
00255 }
00256 }
00257 else
00258 {
00259 result.append(u1);
00260 return result;
00261 }
00262 }
00263
00264
00265 bool glc::segmentInCone(const GLC_Point2d& V0, const GLC_Point2d& V1, const GLC_Point2d& VM, const GLC_Point2d& VP)
00266 {
00267
00268 const GLC_Vector2d diff(V1 - V0);
00269 const GLC_Vector2d edgeL(VM - V0);
00270 const GLC_Vector2d edgeR(VP - V0);
00271 if ((edgeR ^ edgeL) > 0)
00272 {
00273
00274 return (((diff ^ edgeR) < 0.0) && ((diff ^ edgeL) > 0.0));
00275 }
00276 else
00277 {
00278
00279 return (((diff ^ edgeR) < 0.0) || ((diff ^ edgeL) > 0.0));
00280 }
00281 }
00282
00283
00284 bool glc::isDiagonal(const QList<GLC_Point2d>& polygon, const int i0, const int i1)
00285 {
00286 const int size= polygon.size();
00287 int iM= (i0 - 1) % size;
00288 if (iM < 0) iM= size - 1;
00289 int iP= (i0 + 1) % size;
00290
00291 if (!segmentInCone(polygon[i0], polygon[i1], polygon[iM], polygon[iP]))
00292 {
00293 return false;
00294 }
00295
00296 int j0= 0;
00297 int j1= size - 1;
00298
00299 while (j0 < size)
00300 {
00301 if (j0 != i0 && j0 != i1 && j1 != i0 && j1 != i1)
00302 {
00303 if (isIntersected(polygon[i0], polygon[i1], polygon[j0], polygon[j1]))
00304 return false;
00305 }
00306
00307 j1= j0;
00308 ++j0;
00309 }
00310
00311 return true;
00312 }
00313
00314
00315 void glc::triangulate(QList<GLC_Point2d>& polygon, QList<int>& index, QList<int>& tList)
00316 {
00317 const int size= polygon.size();
00318 if (size == 3)
00319 {
00320 tList << index[0] << index[1] << index[2];
00321 return;
00322 }
00323 int i0= 0;
00324 int i1= 1;
00325 int i2= 2;
00326 while(i0 < size)
00327 {
00328 if (isDiagonal(polygon, i0, i2))
00329 {
00330
00331 tList << index[i0] << index[i1] << index[i2];
00332
00333 polygon.removeAt(i1);
00334 index.removeAt(i1);
00335
00336 triangulate(polygon, index, tList);
00337 return;
00338 }
00339 ++i0;
00340 i1= (i1 + 1) % size;
00341 i2= (i2 + 1) % size;
00342 }
00343 }
00344
00345
00346 bool glc::isCounterclockwiseOrdered(const QList<GLC_Point2d>& polygon)
00347 {
00348 const int size= polygon.size();
00349 int j0= 0;
00350 int j1= size - 1;
00351
00352 while (j0 < size)
00353 {
00354 GLC_Vector2d perp((polygon[j0] - polygon[j1]).perp());
00355 int j2= 0;
00356 int j3= size - 1;
00357 bool isIntersect= false;
00358
00359 GLC_Point2d moy((polygon[j0] + polygon[j1]) * 0.5);
00360 while (j2 < size && !isIntersect)
00361 {
00362 if(j2 != j0 && j3 != j1)
00363 {
00364 if (isIntersectedRaySegment(moy, (perp + moy), polygon[j2], polygon[j3]))
00365 isIntersect= true;
00366 }
00367 j3= j2;
00368 ++j2;
00369 }
00370 if(!isIntersect) return false;
00371 j1= j0;
00372 ++j0;
00373 }
00374
00375 return true;
00376
00377 }
00378
00379
00380 void glc::triangulatePolygon(QList<GLuint>* pIndexList, const QList<float>& bulkList)
00381 {
00382 int size= pIndexList->size();
00383 if (polygonIsConvex(pIndexList, bulkList))
00384 {
00385 QList<GLuint> indexList(*pIndexList);
00386 pIndexList->clear();
00387 for (int i= 0; i < size - 2; ++i)
00388 {
00389 pIndexList->append(indexList.at(0));
00390 pIndexList->append(indexList.at(i + 1));
00391 pIndexList->append(indexList.at(i + 2));
00392 }
00393 }
00394 else
00395 {
00396
00397 QList<GLC_Point3d> originPoints;
00398 QHash<int, int> indexMap;
00399
00400 QList<int> face;
00401 GLC_Point3d currentPoint;
00402 int delta= 0;
00403 for (int i= 0; i < size; ++i)
00404 {
00405 const int currentIndex= pIndexList->at(i);
00406 currentPoint= GLC_Point3d(bulkList.at(currentIndex * 3), bulkList.at(currentIndex * 3 + 1), bulkList.at(currentIndex * 3 + 2));
00407 if (!originPoints.contains(currentPoint))
00408 {
00409 originPoints.append(GLC_Point3d(bulkList.at(currentIndex * 3), bulkList.at(currentIndex * 3 + 1), bulkList.at(currentIndex * 3 + 2)));
00410 indexMap.insert(i - delta, currentIndex);
00411 face.append(i - delta);
00412 }
00413 else
00414 {
00415 qDebug() << "Multi points";
00416 ++delta;
00417 }
00418 }
00419
00420 pIndexList->clear();
00421
00422
00423 size= size - delta;
00424
00425
00426 if (size < 3) return;
00427
00428
00429
00430 const GLC_Point3d point1(originPoints[0]);
00431 const GLC_Point3d point2(originPoints[1]);
00432 const GLC_Point3d point3(originPoints[2]);
00433
00434 const GLC_Vector3d edge1(point2 - point1);
00435 const GLC_Vector3d edge2(point3 - point2);
00436
00437 GLC_Vector3d polygonPlaneNormal(edge1 ^ edge2);
00438 polygonPlaneNormal.normalize();
00439
00440
00441 GLC_Matrix4x4 transformation;
00442
00443 GLC_Vector3d rotationAxis(polygonPlaneNormal ^ Z_AXIS);
00444 if (!rotationAxis.isNull())
00445 {
00446 const double angle= acos(polygonPlaneNormal * Z_AXIS);
00447 transformation.setMatRot(rotationAxis, angle);
00448 }
00449
00450 QList<GLC_Point2d> polygon;
00451
00452 for (int i=0; i < size; ++i)
00453 {
00454 originPoints[i]= transformation * originPoints[i];
00455
00456 polygon << originPoints[i].toVector2d(Z_AXIS);
00457 }
00458
00459 QList<int> index= face;
00460
00461 QList<int> tList;
00462 const bool faceIsCounterclockwise= isCounterclockwiseOrdered(polygon);
00463
00464 if(!faceIsCounterclockwise)
00465 {
00466
00467 const int max= size / 2;
00468 for (int i= 0; i < max; ++i)
00469 {
00470 polygon.swap(i, size - 1 -i);
00471 int temp= face[i];
00472 face[i]= face[size - 1 - i];
00473 face[size - 1 - i]= temp;
00474 }
00475 }
00476
00477 triangulate(polygon, index, tList);
00478 size= tList.size();
00479 for (int i= 0; i < size; i+= 3)
00480 {
00481
00482 if (faceIsCounterclockwise)
00483 {
00484 pIndexList->append(indexMap.value(face[tList[i]]));
00485 pIndexList->append(indexMap.value(face[tList[i + 1]]));
00486 pIndexList->append(indexMap.value(face[tList[i + 2]]));
00487 }
00488 else
00489 {
00490 pIndexList->append(indexMap.value(face[tList[i + 2]]));
00491 pIndexList->append(indexMap.value(face[tList[i + 1]]));
00492 pIndexList->append(indexMap.value(face[tList[i]]));
00493 }
00494 }
00495 Q_ASSERT(size == pIndexList->size());
00496 }
00497
00498 }
00499
00500 bool glc::lineIntersectPlane(const GLC_Line3d& line, const GLC_Plane& plane, GLC_Point3d* pPoint)
00501 {
00502 const GLC_Vector3d n= plane.normal();
00503 const GLC_Point3d p= line.startingPoint();
00504 const GLC_Vector3d d= line.direction();
00505
00506 const double denominator= d * n;
00507 if (qFuzzyCompare(fabs(denominator), 0.0))
00508 {
00509 qDebug() << " glc::lineIntersectPlane : Line parallel to the plane";
00510
00511 return false;
00512 }
00513 else
00514 {
00515
00516 const double t= -((n * p) + plane.coefD()) / denominator;
00517 (*pPoint)= p + (t * d);
00518
00519 return true;
00520 }
00521 }
00522
00523 GLC_Point3d glc::project(const GLC_Point3d& point, const GLC_Line3d& line)
00524 {
00525
00526 const GLC_Plane plane(line.direction().normalize(), point);
00527 GLC_Point3d intersection;
00528 const bool intersect= lineIntersectPlane(line, plane, &intersection);
00529 Q_ASSERT(intersect == true);
00530 return intersection;
00531 }
00532
00533