Coverage Report

Created: 2024-08-02 07:04

/src/assimp/code/Common/PolyTools.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
Open Asset Import Library (assimp)
3
----------------------------------------------------------------------
4
5
Copyright (c) 2006-2024, assimp team
6
7
All rights reserved.
8
9
Redistribution and use of this software in source and binary forms,
10
with or without modification, are permitted provided that the
11
following conditions are met:
12
13
* Redistributions of source code must retain the above
14
  copyright notice, this list of conditions and the
15
  following disclaimer.
16
17
* Redistributions in binary form must reproduce the above
18
  copyright notice, this list of conditions and the
19
  following disclaimer in the documentation and/or other
20
  materials provided with the distribution.
21
22
* Neither the name of the assimp team, nor the names of its
23
  contributors may be used to endorse or promote products
24
  derived from this software without specific prior
25
  written permission of the assimp team.
26
27
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39
----------------------------------------------------------------------
40
*/
41
42
/** @file PolyTools.h, various utilities for our dealings with arbitrary polygons */
43
44
#pragma once
45
#ifndef AI_POLYTOOLS_H_INCLUDED
46
#define AI_POLYTOOLS_H_INCLUDED
47
48
#include <assimp/material.h>
49
#include <assimp/ai_assert.h>
50
51
namespace Assimp {
52
53
// -------------------------------------------------------------------------------
54
/** Compute the signed area of a triangle.
55
 *  The function accepts an unconstrained template parameter for use with
56
 *  both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
57
template <typename T>
58
0
inline double GetArea2D(const T& v1, const T& v2, const T& v3) {
59
0
    return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
60
0
}
61
62
// -------------------------------------------------------------------------------
63
/** Test if a given point p2 is on the left side of the line formed by p0-p1.
64
 *  The function accepts an unconstrained template parameter for use with
65
 *  both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
66
template <typename T>
67
0
inline int OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2) {
68
0
    double area = GetArea2D(p0,p2,p1);
69
0
    if(std::abs(area) < ai_epsilon)
70
0
        return 0;
71
0
    else if(area > 0)
72
0
        return 1;
73
0
    else
74
0
        return -1;
75
0
}
76
77
// -------------------------------------------------------------------------------
78
/** Test if a given point is inside a given triangle in R2.
79
 * The function accepts an unconstrained template parameter for use with
80
 *  both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
81
template <typename T>
82
0
inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp) {
83
    // pp should be left side of the three triangle side, by ccw arrow
84
0
    int c1 = OnLeftSideOfLine2D(p0, p1, pp);
85
0
    int c2 = OnLeftSideOfLine2D(p1, p2, pp);
86
0
    int c3 = OnLeftSideOfLine2D(p2, p0, pp);
87
0
    return (c1 >= 0) && (c2 >= 0) && (c3 >= 0);
88
0
}
89
90
91
// -------------------------------------------------------------------------------
92
/** Check whether the winding order of a given polygon is counter-clockwise.
93
 *  The function accepts an unconstrained template parameter, but is intended
94
 *  to be used only with aiVector2D and aiVector3D (z axis is ignored, only
95
 *  x and y are taken into account).
96
 * @note Code taken from http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applet1.html and translated to C++
97
 */
98
template <typename T>
99
inline bool IsCCW(T* in, size_t npoints) {
100
    double aa, bb, cc, b, c, theta;
101
    double convex_turn;
102
    double convex_sum = 0;
103
104
    ai_assert(npoints >= 3);
105
106
    for (size_t i = 0; i < npoints - 2; i++) {
107
        aa = ((in[i+2].x - in[i].x) * (in[i+2].x - in[i].x)) +
108
            ((-in[i+2].y + in[i].y) * (-in[i+2].y + in[i].y));
109
110
        bb = ((in[i+1].x - in[i].x) * (in[i+1].x - in[i].x)) +
111
            ((-in[i+1].y + in[i].y) * (-in[i+1].y + in[i].y));
112
113
        cc = ((in[i+2].x - in[i+1].x) *
114
            (in[i+2].x - in[i+1].x)) +
115
            ((-in[i+2].y + in[i+1].y) *
116
            (-in[i+2].y + in[i+1].y));
117
118
        b = std::sqrt(bb);
119
        c = std::sqrt(cc);
120
        theta = std::acos((bb + cc - aa) / (2 * b * c));
121
122
        if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1]) == 1) {
123
            //  if (convex(in[i].x, in[i].y,
124
            //      in[i+1].x, in[i+1].y,
125
            //      in[i+2].x, in[i+2].y)) {
126
            convex_turn = AI_MATH_PI_F - theta;
127
            convex_sum += convex_turn;
128
        } else {
129
            convex_sum -= AI_MATH_PI_F - theta;
130
        }
131
    }
132
    aa = ((in[1].x - in[npoints-2].x) *
133
        (in[1].x - in[npoints-2].x)) +
134
        ((-in[1].y + in[npoints-2].y) *
135
        (-in[1].y + in[npoints-2].y));
136
137
    bb = ((in[0].x - in[npoints-2].x) *
138
        (in[0].x - in[npoints-2].x)) +
139
        ((-in[0].y + in[npoints-2].y) *
140
        (-in[0].y + in[npoints-2].y));
141
142
    cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
143
        ((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
144
145
    b = std::sqrt(bb);
146
    c = std::sqrt(cc);
147
    theta = std::acos((bb + cc - aa) / (2 * b * c));
148
149
    //if (convex(in[npoints-2].x, in[npoints-2].y,
150
    //  in[0].x, in[0].y,
151
    //  in[1].x, in[1].y)) {
152
    if (OnLeftSideOfLine2D(in[npoints-2],in[1],in[0]) == 1) {
153
        convex_turn = AI_MATH_PI_F - theta;
154
        convex_sum += convex_turn;
155
    } else {
156
        convex_sum -= AI_MATH_PI_F - theta;
157
    }
158
159
    return convex_sum >= (2 * AI_MATH_PI_F);
160
}
161
162
// -------------------------------------------------------------------------------
163
/** Compute the normal of an arbitrary polygon in R3.
164
 *
165
 *  The code is based on Newell's formula, that is a polygons normal is the ratio
166
 *  of its area when projected onto the three coordinate axes.
167
 *
168
 *  @param out Receives the output normal
169
 *  @param num Number of input vertices
170
 *  @param x X data source. x[ofs_x*n] is the n'th element.
171
 *  @param y Y data source. y[ofs_y*n] is the y'th element
172
 *  @param z Z data source. z[ofs_z*n] is the z'th element
173
 *
174
 *  @note The data arrays must have storage for at least num+2 elements. Using
175
 *  this method is much faster than the 'other' NewellNormal()
176
 */
177
template <int ofs_x, int ofs_y, int ofs_z, typename TReal>
178
0
inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, TReal* z) {
179
    // Duplicate the first two vertices at the end
180
0
    x[(num+0)*ofs_x] = x[0];
181
0
    x[(num+1)*ofs_x] = x[ofs_x];
182
183
0
    y[(num+0)*ofs_y] = y[0];
184
0
    y[(num+1)*ofs_y] = y[ofs_y];
185
186
0
    z[(num+0)*ofs_z] = z[0];
187
0
    z[(num+1)*ofs_z] = z[ofs_z];
188
189
0
    TReal sum_xy = 0.0, sum_yz = 0.0, sum_zx = 0.0;
190
191
0
    TReal *xptr = x +ofs_x, *xlow = x, *xhigh = x + ofs_x*2;
192
0
    TReal *yptr = y +ofs_y, *ylow = y, *yhigh = y + ofs_y*2;
193
0
    TReal *zptr = z +ofs_z, *zlow = z, *zhigh = z + ofs_z*2;
194
195
0
    for (int tmp=0; tmp < num; tmp++) {
196
0
        sum_xy += (*xptr) * ( (*yhigh) - (*ylow) );
197
0
        sum_yz += (*yptr) * ( (*zhigh) - (*zlow) );
198
0
        sum_zx += (*zptr) * ( (*xhigh) - (*xlow) );
199
200
0
        xptr  += ofs_x;
201
0
        xlow  += ofs_x;
202
0
        xhigh += ofs_x;
203
204
0
        yptr  += ofs_y;
205
0
        ylow  += ofs_y;
206
0
        yhigh += ofs_y;
207
208
0
        zptr  += ofs_z;
209
0
        zlow  += ofs_z;
210
0
        zhigh += ofs_z;
211
0
    }
212
0
    out = aiVector3t<TReal>(sum_yz,sum_zx,sum_xy);
213
0
}
Unexecuted instantiation: void Assimp::NewellNormal<3, 3, 3, double>(aiVector3t<double>&, int, double*, double*, double*)
Unexecuted instantiation: void Assimp::NewellNormal<4, 4, 4, double>(aiVector3t<double>&, int, double*, double*, double*)
Unexecuted instantiation: void Assimp::NewellNormal<3, 3, 3, float>(aiVector3t<float>&, int, float*, float*, float*)
214
215
} // ! namespace Assimp
216
217
#endif // AI_POLYTOOLS_H_INCLUDED