source: trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp @ 306

Revision 306, 5.1 KB checked in by mattausch, 19 years ago (diff)

fixed polygon area, eval candidate plane

Line 
1#include "Polygon3.h"
2#include "Mesh.h"
3#include "ViewCellBsp.h" // TODO: erase this
4#include "Intersectable.h"
5#include "AxisAlignedBox3.h"
6
7// tolerance value for side relation
8#define SIDE_TOLERANCE 0.002f // TODO: Test different values
9#define SIDE_TOLERANCE_SQRD 0.000004f
10#define AREA_LIMIT 0.0001f
11
12Polygon3::Polygon3(): mMaterial(NULL), mParent(NULL)
13{}
14
15Polygon3::Polygon3(const VertexContainer &vertices): mVertices(vertices), mMaterial(NULL), mParent(NULL)
16{}
17
18Polygon3::Polygon3(Intersectable *parent): mMaterial(NULL), mParent(parent)
19{
20}
21Polygon3::Polygon3(Face *face, Mesh *parentMesh)
22{       
23        VertexIndexContainer::iterator it = face->mVertexIndices.begin();
24        for (; it != face->mVertexIndices.end();  ++it)
25        {
26                mVertices.push_back(parentMesh->mVertices[*it]);
27                mMaterial = parentMesh->mMaterial;
28        }
29}
30
31Plane3 Polygon3::GetSupportingPlane() const
32{
33        Vector3 v1 = mVertices[0] - mVertices[1];
34        Vector3 v2 = mVertices[2] - mVertices[1];
35#ifdef _DEBUG
36        Debug << "plane spanned by " <<  v1 << ", " << v2  << endl;
37#endif
38        return Plane3(mVertices[0], mVertices[1], mVertices[2]);
39}
40
41Vector3 Polygon3::GetNormal() const
42{
43    return Normalize(CrossProd(mVertices[0]-mVertices[1],
44                                                           mVertices[2]-mVertices[1]));
45}
46
47void Polygon3::Split(Plane3 *partition, Polygon3 *front, Polygon3 *back)
48{
49        Vector3 ptA = mVertices.back();
50       
51        int sideA = partition->Side(ptA, SIDE_TOLERANCE);
52       
53        VertexContainer::const_iterator it;
54        bool foundSplit = false;
55
56        Vector3 prevSplitPt(ptA);
57
58        // find line - plane intersections
59        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
60        {
61                Vector3 ptB = *it;
62                int sideB = partition->Side(ptB, SIDE_TOLERANCE);
63       
64                // vertices on different sides => split
65            if (sideB > 0)
66                {
67                        if (sideA < 0)
68                        {
69                                //-- plane - line intersection
70                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
71                       
72                                if (!foundSplit || (SqrDistance(splitPt, prevSplitPt) > SIDE_TOLERANCE_SQRD))
73                                {
74                                        // add vertex to both polygons
75                                        front->mVertices.push_back(splitPt);
76                                        back->mVertices.push_back(splitPt);
77
78                                        foundSplit = true;
79                                        prevSplitPt = splitPt;
80                                }
81                        }
82                        front->mVertices.push_back(ptB);
83                }
84                else if (sideB < 0)
85                {
86                        if (sideA > 0)
87                        {
88                                //-- plane - line intersection
89                                Vector3 splitPt = partition->FindIntersection(ptA, ptB);
90                       
91                                if (!foundSplit || (SqrDistance(splitPt, prevSplitPt) > SIDE_TOLERANCE_SQRD))
92                                {
93                                        // add vertex to both polygons
94                                        front->mVertices.push_back(splitPt);
95                                        back->mVertices.push_back(splitPt);
96
97                                        foundSplit = true;
98                                        prevSplitPt = splitPt;
99                                }       
100                        }
101                        back->mVertices.push_back(ptB);
102                }
103                else
104                {
105                        // vertex on plane => add vertex to both polygons
106                        front->mVertices.push_back(ptB);
107                        back->mVertices.push_back(ptB);
108                }
109       
110                ptA = ptB;
111                sideA = sideB;
112        }
113}
114
115float Polygon3::GetArea() const
116{
117        Vector3 v = CrossProd(mVertices.back(), mVertices.front());
118   
119    for (int i=0; i < mVertices.size() - 1; ++i)
120                v += CrossProd(mVertices[i], mVertices[i+1]);
121   
122    //Debug << "area2: " << 0.5f * fabs(DotProd(GetNormal(), v)) << endl; 
123
124        return 0.5f * fabs(DotProd(GetNormal(), v));
125}
126
127int Polygon3::Side(const Plane3 &plane) const
128{
129        int classification = ClassifyPlane(plane);
130       
131        if (classification == BACK_SIDE)
132                return -1;
133        else if (classification == FRONT_SIDE)
134                return 1;
135
136        return 0;
137}
138
139int Polygon3::ClassifyPlane(const Plane3 &plane) const
140{
141        VertexContainer::const_iterator it;
142
143        bool onFrontSide = false;
144        bool onBackSide = false;
145       
146        int count = 0;
147        // find possible line-plane intersections
148        for (it = mVertices.begin(); it != mVertices.end(); ++ it)
149        {
150                int side = plane.Side(*it, SIDE_TOLERANCE);
151               
152                if (side > 0)
153                        onFrontSide = true;
154                else if (side < 0)
155                        onBackSide = true;
156               
157                //TODO: check if split goes through vertex
158                if (onFrontSide && onBackSide) // split
159                {
160                        return SPLIT;
161                }
162                // 3 vertices enough to decide coincident
163                else if (((++ count) >= 3) && !onFrontSide && !onBackSide)
164                        return COINCIDENT;
165        }
166
167        if (onBackSide)
168        {
169                return BACK_SIDE;
170        }
171        else if (onFrontSide)
172        {
173                return FRONT_SIDE;
174        }
175
176        return COINCIDENT; // plane and polygon are coincident
177}
178
179
180Vector3
181Polygon3::Center() const
182{
183        int i;
184        Vector3 sum = mVertices[0];
185        for (i=1; i < mVertices.size(); i++)
186                sum += mVertices[i];
187       
188        return sum/(float)i;
189}
190
191
192void
193Polygon3::Scale(const float scale)
194{
195        int i;
196        Vector3 center = Center();
197        for (i=0; i < mVertices.size(); i++) {
198                mVertices[i] = center + scale*(mVertices[i] - center);
199        }
200}
201
202bool Polygon3::Valid() const
203{
204        if (mVertices.size() < 3)
205                return false;
206
207#if 1
208        // check if area exceeds certain size
209        if (AREA_LIMIT > GetArea())
210        {
211                //Debug << "area too small: " << GetArea() << endl;
212                return false;
213        }
214#else
215        Vector3 vtx = mVertices.back();
216        VertexContainer::const_iterator it, it_end = mVertices.end();
217
218        for (it = mVertices.begin(); it != it_end; ++it)
219        {
220                if (!(SqrDistance(vtx, *it) > SIDE_TOLERANCE_SQRD))
221                {
222                        Debug << "Malformed vertices:\n" << *this << endl;
223                        return false;
224                }
225                vtx = *it;
226        }
227#endif 
228        return true;
229}
230
231void Polygon3::IncludeInBox(const PolygonContainer &polys, AxisAlignedBox3 &box)
232{
233        PolygonContainer::const_iterator it, it_end = polys.end();
234
235        for (it = polys.begin(); it != it_end; ++ it)
236                box.Include(*(*it));
237}
Note: See TracBrowser for help on using the repository browser.