MyGUI  3.2.0
MyGUI_GeometryUtility.cpp
Go to the documentation of this file.
00001 
00006 /*
00007     This file is part of MyGUI.
00008 
00009     MyGUI is free software: you can redistribute it and/or modify
00010     it under the terms of the GNU Lesser General Public License as published by
00011     the Free Software Foundation, either version 3 of the License, or
00012     (at your option) any later version.
00013 
00014     MyGUI is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00021 */
00022 #include "MyGUI_Precompiled.h"
00023 #include "MyGUI_GeometryUtility.h"
00024 
00025 namespace MyGUI
00026 {
00027 
00028     namespace geometry_utility
00029     {
00030 
00031         VectorFloatPoint cropPolygon(FloatPoint* _baseVerticiesPos, size_t _size, const IntCoord& _cropRectangle)
00032         {
00033             VectorFloatPoint resultVerticiesPos;
00034             resultVerticiesPos.resize(_size);
00035             for (size_t i = 0; i < _size; ++i)
00036             {
00037                 resultVerticiesPos[i] = _baseVerticiesPos[i];
00038             }
00039 
00040             cropPolygonSide(resultVerticiesPos, _cropRectangle.left, Left);
00041             cropPolygonSide(resultVerticiesPos, _cropRectangle.right(), Right);
00042             cropPolygonSide(resultVerticiesPos, _cropRectangle.top, Top);
00043             cropPolygonSide(resultVerticiesPos, _cropRectangle.bottom(), Bottom);
00044 
00045             return resultVerticiesPos;
00046         }
00047 
00048         void cropPolygonSide(VectorFloatPoint& _verticies, int _sideCoord, Side _side)
00049         {
00050             VectorFloatPoint newVerticies;
00051             int invert = (_side == Right || _side == Bottom) ? -1 : 1;
00052             for (size_t i = 0; i < _verticies.size(); ++i)
00053             {
00054                 FloatPoint& v0 = _verticies[i];
00055                 FloatPoint& v1 = _verticies[(i+1)%_verticies.size()];
00056                 switch (_side)
00057                 {
00058                 case Left:
00059                 case Right:
00060                     // both inside
00061                     if (invert* v0.left >= invert* _sideCoord && invert* v1.left >= invert * _sideCoord)
00062                         newVerticies.push_back(v0);
00063                     // intersect side (1st vertex in)
00064                     else if (invert* v0.left >= invert * _sideCoord && invert * v1.left < invert * _sideCoord)
00065                     {
00066                         newVerticies.push_back(v0);
00067                         float c = (v0.left - _sideCoord) / (_sideCoord - v1.left);
00068                         newVerticies.push_back(FloatPoint((float)_sideCoord, (v0.top + c * v1.top) / (c + 1)));
00069                     }
00070                     // intersect side (2nd vertex in)
00071                     else if (invert* v0.left <= invert * _sideCoord && invert * v1.left > invert * _sideCoord)
00072                     {
00073                         float c = (v0.left - _sideCoord) / (_sideCoord - v1.left);
00074                         newVerticies.push_back(FloatPoint((float)_sideCoord, (v0.top + c * v1.top) / (c + 1)));
00075                     }
00076                     // else don't add any verticies
00077                     break;
00078                 case Top:
00079                 case Bottom:
00080                     // both inside
00081                     if (invert* v0.top >= invert* _sideCoord && invert* v1.top >= invert * _sideCoord)
00082                         newVerticies.push_back(v0);
00083                     // intersect side (1st vertex in)
00084                     else if (invert* v0.top >= invert * _sideCoord && invert * v1.top < invert * _sideCoord)
00085                     {
00086                         newVerticies.push_back(v0);
00087                         float c = (v0.top - _sideCoord) / (_sideCoord - v1.top);
00088                         newVerticies.push_back(FloatPoint((v0.left + c * v1.left) / (c + 1), (float)_sideCoord));
00089                     }
00090                     // intersect side (2nd vertex in)
00091                     else if (invert* v0.top <= invert * _sideCoord && invert * v1.top > invert * _sideCoord)
00092                     {
00093                         float c = (v0.top - _sideCoord) / (_sideCoord - v1.top);
00094                         newVerticies.push_back(FloatPoint((v0.left + c * v1.left) / (c + 1), (float)_sideCoord));
00095                     }
00096                     // else don't add any verticies
00097                     break;
00098                 }
00099             }
00100 
00101             _verticies = newVerticies;
00102         }
00103 
00104         FloatPoint getPositionInsideRect(const FloatPoint& _point, const FloatPoint& _corner0, const FloatPoint& _corner1, const FloatPoint& _corner2)
00105         {
00106             FloatPoint result;
00107 
00108             FloatPoint point = _point - _corner0;
00109             FloatPoint dirX = _corner1 - _corner0;
00110             FloatPoint dirY = _corner2 - _corner0;
00111 
00112             float div = dirX.left * dirY.top - dirX.top * dirY.left;
00113             if (div == 0.0f)
00114                 return FloatPoint();
00115             return FloatPoint(
00116                 (point.top * dirX.left - point.left * dirX.top) / div,
00117                 (point.left * dirY.top - point.top * dirY.left) / div
00118                 );
00119         }
00120 
00121         FloatPoint getUVFromPositionInsideRect(const FloatPoint& _point, const FloatPoint& _v0, const FloatPoint& _v1, const FloatPoint& _baseUV)
00122         {
00123             return FloatPoint(
00124                 _baseUV.left + _point.left * _v0.left + _point.top * _v1.left,
00125                 _baseUV.top  + _point.left * _v0.top  + _point.top * _v1.top
00126                 );
00127         }
00128 
00129     } // namespace geometry_utility
00130 
00131 } // namespace MyGUI