1818#include " axom/primal/geometry/Point.hpp"
1919#include " axom/primal/geometry/Vector.hpp"
2020#include " axom/primal/geometry/BezierCurve.hpp"
21+ #include " axom/primal/geometry/NURBSCurve.hpp"
2122#include " axom/primal/geometry/BoundingBox.hpp"
2223
24+ // For NURBSCurveGWNCache objects
25+ #include " axom/primal/operators/detail/winding_number_3d_memoization.hpp"
26+
2327#include < vector>
2428#include < ostream>
2529
2630namespace axom
2731{
2832namespace primal
2933{
30- // Forward declare the templated classes and operator functions
34+ namespace internal
35+ {
36+ // /@{
37+ // / \name Boilerplate to deduce the numeric type from the curve object
38+ template <typename U>
39+ struct get_numeric_type ;
40+
3141template <typename T, int NDIMS>
42+ struct get_numeric_type <BezierCurve<T, NDIMS>>
43+ {
44+ using type = T;
45+ };
46+
47+ template <typename T, int NDIMS>
48+ struct get_numeric_type <NURBSCurve<T, NDIMS>>
49+ {
50+ using type = T;
51+ };
52+
53+ template <typename T>
54+ struct get_numeric_type <detail::NURBSCurveGWNCache<T>>
55+ {
56+ using type = T;
57+ };
58+ // /@}
59+
60+ // /@{
61+ // / \name Boilerplate for a compile-time flag for the cached object
62+ template <typename U>
63+ struct has_cached_data : std::false_type
64+ { };
65+
66+ template <typename T>
67+ struct has_cached_data <detail::NURBSCurveGWNCache<T>> : std::true_type
68+ { };
69+ // /@}
70+ } // namespace internal
71+
72+ // Forward declare the templated classes and operator functions
73+ template <typename CurveType>
3274class CurvedPolygon ;
3375
3476/* ! \brief Overloaded output operator for polygons */
35- template <typename T, int NDIMS >
36- std::ostream& operator <<(std::ostream& os, const CurvedPolygon<T, NDIMS >& poly);
77+ template <typename CurveType >
78+ std::ostream& operator <<(std::ostream& os, const CurvedPolygon<CurveType >& poly);
3779
3880/* !
3981 * \class CurvedPolygon
@@ -44,15 +86,15 @@ std::ostream& operator<<(std::ostream& os, const CurvedPolygon<T, NDIMS>& poly);
4486 * \note The component curves should be ordered in a counter clockwise
4587 * orientation with respect to the polygon's normal vector
4688 */
47- template <typename T, int NDIMS >
89+ template <typename CurveType >
4890class CurvedPolygon
4991{
5092public:
51- using PointType = Point<T, NDIMS> ;
52- using VectorType = Vector<T, NDIMS>;
53- using NumArrayType = axom::NumericArray<T, NDIMS> ;
54- using BezierCurveType = BezierCurve<T, NDIMS> ;
55- using BoundingBoxType = typename BezierCurveType ::BoundingBoxType;
93+ using T = typename internal::get_numeric_type<CurveType>::type ;
94+
95+ using PointType = typename CurveType::PointType ;
96+ using VectorType = typename CurveType::VectorType ;
97+ using BoundingBoxType = typename CurveType ::BoundingBoxType;
5698
5799public:
58100 // / Default constructor for an empty polygon
@@ -73,20 +115,30 @@ class CurvedPolygon
73115 m_edges.resize (nEdges);
74116 }
75117
76- // / Constructor from an array of \a nEdges curves
77- CurvedPolygon (BezierCurveType* curves, int nEdges)
118+ /* !
119+ * \brief Copy constructor for another curve type
120+ */
121+ template <typename OtherCurveType>
122+ CurvedPolygon (const CurvedPolygon<OtherCurveType>& other_poly)
78123 {
79- SLIC_ASSERT (curves != nullptr );
80- SLIC_ASSERT (nEdges >= 1 );
81-
82- m_edges.reserve (nEdges);
83-
84- for (int e = 0 ; e < nEdges; ++e)
124+ m_edges.resize (other_poly.numEdges ());
125+ for (int e = 0 ; e < other_poly.numEdges (); ++e)
85126 {
86- this -> addEdge (curves [e]);
127+ m_edges[e] = CurveType (other_poly [e]);
87128 }
88129 }
89130
131+ // /! \brief Constructor for CurvedPolygon from an ArrayView of curves
132+ CurvedPolygon (axom::ArrayView<const CurveType> curves) : m_edges(curves) { }
133+
134+ // /! \brief Constructor from a c-style array of \a nEdges curves
135+ CurvedPolygon (const CurveType* curves, int nEdges)
136+ : CurvedPolygon(axom::ArrayView<const CurveType>(curves, nEdges))
137+ { }
138+
139+ // /! \brief Constructor from a Axom array of curves
140+ CurvedPolygon (const axom::Array<CurveType>& curves) : CurvedPolygon(curves.view()) { }
141+
90142 // / Clears the list of edges
91143 void clear () { m_edges.clear (); }
92144
@@ -105,36 +157,43 @@ class CurvedPolygon
105157 m_edges.resize (ngon);
106158 }
107159
108- // / Appends a BezierCurve to the list of edges
109- void addEdge (const BezierCurveType& c1) { m_edges.push_back (c1); }
160+ // / Appends a curve to the list of edges
161+ void addEdge (const CurveType& c1) { m_edges.push_back (c1); }
162+
163+ // / Consumes then appends a curve to the list of edges
164+ void addEdge (CurveType&& c1) { m_edges.push_back (std::move (c1)); }
110165
111166 // / Splits an edge "in place"
112167 void splitEdge (int idx, T t)
113168 {
114- SLIC_ASSERT (idx < static_cast <int >(m_edges.size ()));
169+ SLIC_ASSERT (idx >= 0 && idx < static_cast <int >(m_edges.size ()));
170+ AXOM_STATIC_ASSERT_MSG (!internal::has_cached_data<CurveType>::value,
171+ " splitEdge cannot be called on objects with associated cache data" );
115172
173+ m_edges.reserve (numEdges () + 1 );
116174 m_edges.insert (m_edges.begin () + idx + 1 , 1 , m_edges[idx]);
117175 auto & csplit = m_edges[idx];
118176 csplit.split (t, m_edges[idx], m_edges[idx + 1 ]);
119177 }
120178
121- axom::Array<BezierCurve<T, NDIMS>> getEdges () const { return m_edges; }
122-
179+ axom::Array<CurveType> getEdges () const { return m_edges; }
123180 // / @}
124181
125- /* ! Retrieves the Bezier Curve at index idx */
126- BezierCurveType & operator [](int idx) { return m_edges[idx]; }
127- /* ! Retrieves the vertex at index idx */
128- const BezierCurveType & operator [](int idx) const { return m_edges[idx]; }
182+ /* ! Retrieves the curve at index idx */
183+ CurveType & operator [](int idx) { return m_edges[idx]; }
184+ /* ! Retrieves the curve at index idx */
185+ const CurveType & operator [](int idx) const { return m_edges[idx]; }
129186
130187 // / Tests equality of two CurvedPolygons
131- friend inline bool operator ==(const CurvedPolygon<T, NDIMS>& lhs, const CurvedPolygon<T, NDIMS>& rhs)
188+ friend inline bool operator ==(const CurvedPolygon<CurveType>& lhs,
189+ const CurvedPolygon<CurveType>& rhs)
132190 {
133191 return lhs.m_edges == rhs.m_edges ;
134192 }
135193
136194 // / Tests inequality of two CurvedPolygons
137- friend inline bool operator !=(const CurvedPolygon<T, NDIMS>& lhs, const CurvedPolygon<T, NDIMS>& rhs)
195+ friend inline bool operator !=(const CurvedPolygon<CurveType>& lhs,
196+ const CurvedPolygon<CurveType>& rhs)
138197 {
139198 return !(lhs == rhs);
140199 }
@@ -149,7 +208,7 @@ class CurvedPolygon
149208 {
150209 const int sz = numEdges ();
151210
152- os << " {" << sz << " -sided Bezier polygon:" ;
211+ os << " {" << sz << " -sided curved polygon:" ;
153212 for (int i = 0 ; i < sz - 1 ; ++i)
154213 {
155214 os << m_edges[i] << " ," ;
@@ -177,17 +236,16 @@ class CurvedPolygon
177236 const int nEdges = numEdges ();
178237
179238 // initial basic check: no edges, or one edge or linear or quadratic order cannot be closed
180- if (nEdges < 1 || (nEdges == 1 && m_edges[0 ].getOrder () <= 2 ))
239+ if (nEdges < 1 || (nEdges == 1 && m_edges[0 ].getNumControlPoints () <= 2 ))
181240 {
182241 return false ;
183242 }
184243
185244 // foreach edge: check last vertex of previous edge against first vertex of current edge
186245 for (int cur = 0 , prev = nEdges - 1 ; cur < nEdges; prev = cur++)
187246 {
188- const auto ord = m_edges[prev].getOrder ();
189- const auto & lastPrev = m_edges[prev][ord];
190- const auto & firstCur = m_edges[cur][0 ];
247+ const auto & lastPrev = m_edges[prev].getEndPoint ();
248+ const auto & firstCur = m_edges[cur].getInitPoint ();
191249 if (!isNearlyEqual (squared_distance (lastPrev, firstCur), 0 ., sq_tol))
192250 {
193251 return false ;
@@ -200,6 +258,10 @@ class CurvedPolygon
200258 // / \brief Reverses orientation of a CurvedPolygon
201259 void reverseOrientation ()
202260 {
261+ AXOM_STATIC_ASSERT_MSG (
262+ !internal::has_cached_data<CurveType>::value,
263+ " reverseOrientation cannot be called on objects with associated cache data" );
264+
203265 const int ngon = numEdges ();
204266 const int mid = ngon >> 1 ;
205267 const bool isOdd = (ngon & 1 ) != 0 ;
@@ -233,14 +295,14 @@ class CurvedPolygon
233295 }
234296
235297private:
236- axom::Array<BezierCurve<T, NDIMS> > m_edges;
298+ axom::Array<CurveType > m_edges;
237299};
238300
239301// ------------------------------------------------------------------------------
240302// / Free functions implementing Polygon's operators
241303// ------------------------------------------------------------------------------
242- template <typename T, int NDIMS >
243- std::ostream& operator <<(std::ostream& os, const CurvedPolygon<T, NDIMS >& poly)
304+ template <typename CurveType >
305+ std::ostream& operator <<(std::ostream& os, const CurvedPolygon<CurveType >& poly)
244306{
245307 poly.print (os);
246308 return os;
0 commit comments