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