Tools2D.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <cstdlib>
00028 # include <set>
00029 #endif
00030
00031 #include "Tools2D.h"
00032 #include "Vector3D.h"
00033
00034 using namespace Base;
00035
00036 float Vector2D::GetAngle (const Vector2D &rclVect) const
00037 {
00038 float fDivid, fNum;
00039
00040 fDivid = Length() * rclVect.Length();
00041
00042 if ((fDivid < -1e-10f) || (fDivid > 1e-10f))
00043 {
00044 fNum = (*this * rclVect) / fDivid;
00045 if (fNum < -1)
00046 return F_PI;
00047 else
00048 if (fNum > 1)
00049 return 0.0F;
00050 else
00051 return float(acos(fNum));
00052 }
00053 else
00054 return -FLOAT_MAX;
00055 }
00056
00057 void Vector2D::ProjToLine (const Vector2D &rclPt, const Vector2D &rclLine)
00058 {
00059 float l = rclLine.Length();
00060 float t1 = (rclPt * rclLine) / l;
00061 Vector2D clNormal = rclLine;
00062 clNormal.Normalize();
00063 clNormal.Scale(t1);
00064 *this = clNormal;
00065 }
00066
00067
00070 bool BoundBox2D::operator|| (const Line2D &rclLine) const
00071 {
00072 Line2D clThisLine;
00073 Vector2D clVct;
00074
00075
00076 clThisLine.clV1.fX = fMinX;
00077 clThisLine.clV1.fY = fMinY;
00078 clThisLine.clV2.fX = fMaxX;
00079 clThisLine.clV2.fY = fMinY;
00080 if (clThisLine.IntersectAndContain (rclLine, clVct))
00081 return true;
00082
00083
00084 clThisLine.clV1 = clThisLine.clV2;
00085 clThisLine.clV2.fX = fMaxX;
00086 clThisLine.clV2.fY = fMaxY;
00087 if (clThisLine.IntersectAndContain (rclLine, clVct))
00088 return true;
00089
00090
00091 clThisLine.clV1 = clThisLine.clV2;
00092 clThisLine.clV2.fX = fMinX;
00093 clThisLine.clV2.fY = fMaxY;
00094 if (clThisLine.IntersectAndContain (rclLine, clVct))
00095 return true;
00096
00097
00098 clThisLine.clV1 = clThisLine.clV2;
00099 clThisLine.clV2.fX = fMinX;
00100 clThisLine.clV2.fY = fMinY;
00101 if (clThisLine.IntersectAndContain (rclLine, clVct))
00102 return true;
00103
00104 return false;
00105 }
00106
00107 bool BoundBox2D::operator|| (const BoundBox2D &rclBB) const
00108 {
00110
00111
00112
00113
00114
00116
00117
00118
00119
00120
00121 if (fMinX < rclBB.fMaxX &&
00122 rclBB.fMinX < fMaxX &&
00123 fMinY < rclBB.fMaxY &&
00124 rclBB.fMinY < fMaxY )
00125 return true;
00126 else
00127 return false;
00128 }
00129
00130 bool BoundBox2D::operator|| (const Polygon2D &rclPoly) const
00131 {
00132 unsigned long i;
00133 Line2D clLine;
00134
00135
00136 for (i = 0; i < rclPoly.GetCtVectors(); i++)
00137 if (Contains (rclPoly[i]))
00138 return true;
00139
00140
00141 if (rclPoly.Contains (Vector2D (fMinX, fMinY)) ||
00142 rclPoly.Contains (Vector2D (fMaxX, fMinY)) ||
00143 rclPoly.Contains (Vector2D (fMaxX, fMaxY)) ||
00144 rclPoly.Contains (Vector2D (fMinX, fMaxY)))
00145 return true;
00146
00147
00148 if (rclPoly.GetCtVectors() < 3) return false;
00149 for (i = 0; i < rclPoly.GetCtVectors(); i++)
00150 {
00151 if (i == rclPoly.GetCtVectors() - 1)
00152 {
00153 clLine.clV1 = rclPoly[i];
00154 clLine.clV2 = rclPoly[0];
00155 }
00156 else
00157 {
00158 clLine.clV1 = rclPoly[i];
00159 clLine.clV2 = rclPoly[i + 1];
00160 }
00161 if (*this || clLine)
00162 return true;
00163 }
00164
00165 return false;
00166 }
00167
00168 bool BoundBox2D::Contains (const Vector2D &rclV) const
00169 {
00170 return
00171 (rclV.fX >= fMinX) && (rclV.fX <= fMaxX) &&
00172 (rclV.fY >= fMinY) && (rclV.fY <= fMaxY);
00173 }
00174
00175
00178 BoundBox2D Line2D::CalcBoundBox (void) const
00179 {
00180 BoundBox2D clBB;
00181 clBB.fMinX = std::min<float> (clV1.fX, clV2.fX);
00182 clBB.fMinY = std::min<float> (clV1.fY, clV2.fY);
00183 clBB.fMaxX = std::max<float> (clV1.fX, clV2.fX);
00184 clBB.fMaxY = std::max<float> (clV1.fY, clV2.fY);
00185 return clBB;
00186 }
00187
00188 bool Line2D::Intersect (const Line2D& rclLine, Vector2D &rclV) const
00189 {
00190 float m1, m2, b1, b2;
00191
00192
00193 if (fabs (clV2.fX - clV1.fX) > 1e-10)
00194 m1 = (clV2.fY - clV1.fY) / (clV2.fX - clV1.fX);
00195 else
00196 m1 = FLOAT_MAX;
00197 if (fabs (rclLine.clV2.fX - rclLine.clV1.fX) > 1e-10)
00198 m2 = (rclLine.clV2.fY - rclLine.clV1.fY) / (rclLine.clV2.fX - rclLine.clV1.fX);
00199 else
00200 m2 = FLOAT_MAX;
00201 if (m1 == m2)
00202 return false;
00203
00204 b1 = clV1.fY - m1 * clV1.fX;
00205 b2 = rclLine.clV1.fY - m2 * rclLine.clV1.fX;
00206
00207
00208 if (m1 == FLOAT_MAX)
00209 {
00210 rclV.fX = clV1.fX;
00211 rclV.fY = m2 * rclV.fX + b2;
00212 }
00213 else
00214 if (m2 == FLOAT_MAX)
00215 {
00216 rclV.fX = rclLine.clV1.fX;
00217 rclV.fY = m1 * rclV.fX + b1;
00218 }
00219 else
00220 {
00221 rclV.fX = (b2 - b1) / (m1 - m2);
00222 rclV.fY = m1 * rclV.fX + b1;
00223 }
00224
00225 return true;
00226 }
00227
00228 Vector2D Line2D::FromPos (float fDistance) const
00229 {
00230 Vector2D clDir(clV2 - clV1);
00231 clDir.Normalize();
00232 return Vector2D(clV1.fX + (clDir.fX * fDistance), clV1.fY + (clDir.fY * fDistance));
00233 }
00234
00235 bool Line2D::IntersectAndContain (const Line2D& rclLine, Vector2D &rclV) const
00236 {
00237 bool rc = Intersect (rclLine, rclV);
00238 if (rc)
00239 rc = Contains (rclV) && rclLine.Contains (rclV);
00240 return rc;
00241 }
00242
00243
00246 BoundBox2D Polygon2D::CalcBoundBox (void) const
00247 {
00248 unsigned long i;
00249 BoundBox2D clBB;
00250 for (i = 0; i < _aclVct.size(); i++)
00251 {
00252 clBB.fMinX = std::min<float> (clBB.fMinX, _aclVct[i].fX);
00253 clBB.fMinY = std::min<float> (clBB.fMinY, _aclVct[i].fY);
00254 clBB.fMaxX = std::max<float> (clBB.fMaxX, _aclVct[i].fX);
00255 clBB.fMaxY = std::max<float> (clBB.fMaxY, _aclVct[i].fY);
00256 }
00257 return clBB;
00258 }
00259
00260 static short _CalcTorsion (float *pfLine, float fX, float fY)
00261 {
00262 short sQuad[2], i;
00263 float fResX;
00264
00265
00266 for (i = 0; i < 2; i++)
00267 {
00268 if (pfLine[i * 2] <= fX)
00269 sQuad[i] = (pfLine[i * 2 + 1] > fY) ? 0 : 3;
00270 else
00271 sQuad[i] = (pfLine[i * 2 + 1] > fY) ? 1 : 2;
00272 }
00273
00274
00275
00276 if (abs (sQuad[0] - sQuad[1]) <= 1) return 0;
00277
00278
00279 if (abs (sQuad[0] - sQuad[1]) == 3)
00280 return (sQuad[0] == 0) ? 1 : -1;
00281
00282
00283
00284 fResX = pfLine[0] + (fY - pfLine[1]) /
00285 ((pfLine[3] - pfLine[1]) / (pfLine[2] - pfLine[0]));
00286 if (fResX < fX)
00287
00288
00289 return (sQuad[0] <= 1) ? 1 : -1;
00290
00291
00292 return 0;
00293 }
00294
00295 bool Polygon2D::Contains (const Vector2D &rclV) const
00296 {
00297
00298
00299
00300 float pfTmp[4];
00301 unsigned long i;
00302 short sTorsion = 0;
00303
00304
00305 if (GetCtVectors() < 3) return false;
00306
00307
00308 for (i = 0; i < GetCtVectors(); i++)
00309 {
00310
00311 if (i == GetCtVectors() - 1)
00312 {
00313
00314 pfTmp[0] = _aclVct[i].fX;
00315 pfTmp[1] = _aclVct[i].fY;
00316 pfTmp[2] = _aclVct[0].fX;
00317 pfTmp[3] = _aclVct[0].fY;
00318 }
00319 else
00320 {
00321
00322 pfTmp[0] = _aclVct[i].fX;
00323 pfTmp[1] = _aclVct[i].fY;
00324 pfTmp[2] = _aclVct[i + 1].fX;
00325 pfTmp[3] = _aclVct[i + 1].fY;
00326 }
00327
00328
00329 sTorsion += _CalcTorsion (pfTmp, rclV.fX, rclV.fY);
00330 }
00331
00332
00333 return sTorsion != 0;
00334 }
00335
00336 void Polygon2D::Intersect (const Polygon2D &rclPolygon, std::list<Polygon2D> &rclResultPolygonList) const
00337 {
00338
00339
00340
00341 if ((rclPolygon.GetCtVectors() < 2) || (GetCtVectors() < 2))
00342 return;
00343
00344
00345 bool bInner = Contains(rclPolygon[0]);
00346
00347 Polygon2D clResultPolygon;
00348 if (bInner == true)
00349 clResultPolygon.Add(rclPolygon[0]);
00350
00351
00352 size_t ulPolyCt = rclPolygon.GetCtVectors();
00353 size_t ulTrimCt = GetCtVectors();
00354 for (size_t ulVec = 0; ulVec < (ulPolyCt-1); ulVec++)
00355 {
00356 Vector2D clPt0 = rclPolygon[ulVec];
00357 Vector2D clPt1 = rclPolygon[ulVec+1];
00358 Line2D clLine(clPt0, clPt1);
00359
00360
00361 std::set<float> afIntersections;
00362 Vector2D clTrimPt2;
00363 for (size_t i = 0; i < ulTrimCt; i++)
00364 {
00365 clTrimPt2 = At((i + 1) % ulTrimCt);
00366 Line2D clToTrimLine(At(i), clTrimPt2);
00367
00368 Vector2D clV;
00369 if (clLine.IntersectAndContain(clToTrimLine, clV) == true)
00370 {
00371
00372 float fDist = (clV - clPt0).Length();
00373 afIntersections.insert(fDist);
00374 }
00375 }
00376
00377 if (afIntersections.size() > 0)
00378 {
00379 for (std::set<float>::iterator pF = afIntersections.begin(); pF != afIntersections.end(); pF++)
00380 {
00381
00382 Vector2D clPtIS = clLine.FromPos(*pF);
00383 if (bInner == true)
00384 {
00385 clResultPolygon.Add(clPtIS);
00386 rclResultPolygonList.push_back(clResultPolygon);
00387 clResultPolygon.DeleteAll();
00388 bInner = false;
00389 }
00390 else
00391 {
00392 clResultPolygon.Add(clPtIS);
00393 bInner = true;
00394 }
00395 }
00396
00397 if (bInner == true)
00398 clResultPolygon.Add(clPt1);
00399 }
00400 else
00401 {
00402 if (bInner == true)
00403 clResultPolygon.Add(clPt1);
00404 }
00405 }
00406
00407
00408 if (clResultPolygon.GetCtVectors() > 0)
00409 rclResultPolygonList.push_back(clResultPolygon);
00410 }
00411