Coverage Report

Created: 2026-01-10 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgrePolygon.cpp
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
(Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
Copyright (c) 2006 Matthias Fink, netAllied GmbH <matthias.fink@web.de>                             
9
10
Permission is hereby granted, free of charge, to any person obtaining a copy
11
of this software and associated documentation files (the "Software"), to deal
12
in the Software without restriction, including without limitation the rights
13
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
copies of the Software, and to permit persons to whom the Software is
15
furnished to do so, subject to the following conditions:
16
17
The above copyright notice and this permission notice shall be included in
18
all copies or substantial portions of the Software.
19
20
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
THE SOFTWARE.
27
-----------------------------------------------------------------------------
28
*/
29
#include "OgreStableHeaders.h"
30
#include "OgrePolygon.h"
31
32
namespace Ogre
33
{
34
35
    //-----------------------------------------------------------------------
36
    Polygon::Polygon()
37
0
    : mNormal( Vector3::ZERO )
38
0
    , mIsNormalSet(false)
39
0
    {
40
        // reserve space for 6 vertices to reduce allocation cost
41
0
        mVertexList.reserve(6);
42
0
    }
43
    //-----------------------------------------------------------------------
44
    Polygon::~Polygon()
45
0
    {
46
0
    }
47
    //-----------------------------------------------------------------------
48
    Polygon::Polygon( const Polygon& cpy )
49
0
    {
50
0
        mVertexList = cpy.mVertexList;
51
0
        mNormal = cpy.mNormal;
52
0
        mIsNormalSet = cpy.mIsNormalSet;
53
0
    }
54
    //-----------------------------------------------------------------------
55
    void Polygon::insertVertex(const Vector3& vdata, size_t vertex )
56
0
    {
57
        // TODO: optional: check planarity
58
0
        OgreAssertDbg(vertex <= getVertexCount(), "Insert position out of range" );
59
60
0
        VertexList::iterator it = mVertexList.begin();
61
62
0
        std::advance(it, vertex);
63
0
        mVertexList.insert(it, vdata);
64
65
0
    }
66
    //-----------------------------------------------------------------------
67
    void Polygon::insertVertex(const Vector3& vdata)
68
0
    {
69
0
        mVertexList.push_back(vdata);
70
0
    }
71
    //-----------------------------------------------------------------------
72
    const Vector3& Polygon::getVertex( size_t vertex ) const
73
0
    {
74
0
        OgreAssertDbg(vertex < getVertexCount(), "Search position out of range");
75
76
0
        return mVertexList[vertex];
77
0
    }
78
    //-----------------------------------------------------------------------
79
    void Polygon::setVertex(const Vector3& vdata, size_t vertex )
80
0
    {
81
        // TODO: optional: check planarity
82
0
        OgreAssertDbg(vertex < getVertexCount(), "Search position out of range" );
83
84
        // set new vertex
85
0
        mVertexList[ vertex ] = vdata;
86
0
    }
87
    //-----------------------------------------------------------------------
88
    void Polygon::removeDuplicates( void )
89
0
    {
90
0
        for ( size_t i = 0; i < getVertexCount(); ++i )
91
0
        {
92
0
            const Vector3& a = getVertex( i );
93
0
            const Vector3& b = getVertex( (i + 1)%getVertexCount() );
94
95
0
            if (a.positionEquals(b))
96
0
            {
97
0
                deleteVertex(i);
98
0
                --i;
99
0
            }
100
0
        }
101
0
    }
102
    //-----------------------------------------------------------------------
103
    size_t Polygon::getVertexCount( void ) const
104
0
    {
105
0
        return mVertexList.size();
106
0
    }
107
    //-----------------------------------------------------------------------
108
    const Vector3& Polygon::getNormal( void ) const
109
0
    {
110
0
        updateNormal();
111
112
0
        return mNormal;
113
0
    }
114
    //-----------------------------------------------------------------------
115
    void Polygon::updateNormal( void ) const
116
0
    {
117
0
        OgreAssertDbg( getVertexCount() >= 3, "Insufficient vertex count!" );
118
119
0
        if (mIsNormalSet)
120
0
            return;
121
122
        // vertex order is ccw
123
0
        const Vector3& a = getVertex( 0 );
124
0
        const Vector3& b = getVertex( 1 );
125
0
        const Vector3& c = getVertex( 2 );
126
127
        // used method: Newell
128
0
        mNormal.x = 0.5f * ( (a.y - b.y) * (a.z + b.z) +
129
0
                               (b.y - c.y) * (b.z + c.z) + 
130
0
                               (c.y - a.y) * (c.z + a.z));
131
132
0
        mNormal.y = 0.5f * ( (a.z - b.z) * (a.x + b.x) +
133
0
                               (b.z - c.z) * (b.x + c.x) + 
134
0
                               (c.z - a.z) * (c.x + a.x));
135
136
0
        mNormal.z = 0.5f * ( (a.x - b.x) * (a.y + b.y) +
137
0
                               (b.x - c.x) * (b.y + c.y) + 
138
0
                               (c.x - a.x) * (c.y + a.y));
139
140
0
        mNormal.normalise();
141
142
0
        mIsNormalSet = true;
143
144
0
    }
145
    //-----------------------------------------------------------------------
146
    void Polygon::deleteVertex( size_t vertex )
147
0
    {
148
0
        OgreAssertDbg( vertex < getVertexCount(), "Search position out of range" );
149
150
0
        VertexList::iterator it = mVertexList.begin();
151
0
        std::advance(it, vertex);
152
153
0
        mVertexList.erase( it );
154
0
    }
155
    //-----------------------------------------------------------------------
156
    void Polygon::storeEdges( Polygon::EdgeMap *edgeMap ) const
157
0
    {
158
0
        OgreAssert( edgeMap != NULL, "EdgeMap ptr is NULL" );
159
160
0
        size_t vertexCount = getVertexCount();
161
162
0
        for ( size_t i = 0; i < vertexCount; ++i )
163
0
        {
164
0
            edgeMap->insert( Edge( getVertex( i ), getVertex( ( i + 1 ) % vertexCount ) ) );
165
0
        }
166
0
    }
167
    //-----------------------------------------------------------------------
168
    void Polygon::reset( void )
169
0
    {
170
        // could use swap() to free memory here, but assume most may be reused so avoid realloc
171
0
        mVertexList.clear();
172
173
0
        mIsNormalSet = false;
174
0
    }
175
    //-----------------------------------------------------------------------
176
    bool Polygon::operator == (const Polygon& rhs) const
177
0
    {
178
0
        if ( getVertexCount() != rhs.getVertexCount() )
179
0
            return false;
180
181
        // Compare vertices. They may differ in its starting position.
182
        // find start
183
0
        size_t start = 0;
184
0
        bool foundStart = false;
185
0
        for (size_t i = 0; i < getVertexCount(); ++i )
186
0
        {   
187
0
            if (getVertex(0).positionEquals(rhs.getVertex(i)))
188
0
            {
189
0
                start = i;
190
0
                foundStart = true;
191
0
                break;
192
0
            }
193
0
        }
194
195
0
        if (!foundStart)
196
0
            return false;
197
198
0
        for (size_t i = 0; i < getVertexCount(); ++i )
199
0
        {
200
0
            const Vector3& vA = getVertex( i );
201
0
            const Vector3& vB = rhs.getVertex( ( i + start) % getVertexCount() );
202
203
0
            if (!vA.positionEquals(vB))
204
0
                return false;
205
0
        }
206
207
0
        return true;
208
0
    }
209
    //-----------------------------------------------------------------------
210
    Polygon& Polygon::operator=(const Ogre::Polygon& rhs)
211
0
    {
212
0
        mIsNormalSet = rhs.mIsNormalSet;
213
0
        mNormal = rhs.mNormal;
214
0
        mVertexList = rhs.mVertexList;
215
0
        return *this;
216
0
    }
217
    //-----------------------------------------------------------------------
218
    std::ostream& operator<< ( std::ostream& strm, const Polygon& poly )
219
0
    {
220
0
        strm << "NUM VERTICES: " << poly.getVertexCount() << std::endl;
221
222
0
        for (size_t j = 0; j < poly.getVertexCount(); ++j )
223
0
        {
224
0
            strm << "VERTEX " << j << ": " << poly.getVertex( j ) << std::endl;
225
0
        }
226
227
0
        return strm;
228
0
    }
229
    //-----------------------------------------------------------------------
230
    bool Polygon::isPointInside(const Vector3& point) const
231
0
    {
232
        // sum the angles 
233
0
        Real anglesum = 0;
234
0
        size_t n = getVertexCount();
235
0
        for (size_t i = 0; i < n; i++) 
236
0
        {
237
0
            const Vector3& p1 = getVertex(i);
238
0
            const Vector3& p2 = getVertex((i + 1) % n);
239
240
0
            Vector3 v1 = p1 - point;
241
0
            Vector3 v2 = p2 - point;
242
243
0
            Real len1 = v1.length();
244
0
            Real len2 = v2.length();
245
246
0
            if (Math::RealEqual(len1 * len2, 0.0f, 1e-4f))
247
0
            {
248
                // We are on a vertex so consider this inside
249
0
                return true; 
250
0
            }
251
0
            else
252
0
            {
253
0
                Real costheta = v1.dotProduct(v2) / (len1 * len2);
254
0
                anglesum += std::acos(costheta);
255
0
            }
256
0
        }
257
258
        // result should be 2*PI if point is inside poly
259
0
        return Math::RealEqual(anglesum, Math::TWO_PI, 1e-4f);
260
261
0
    }
262
}