SurfaceBoundary.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2016 Imperial College London
5  * Copyright 2016 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_SurfaceBoundary_H
21 #define MIRTK_SurfaceBoundary_H
22 
23 #include "mirtk/Object.h"
24 
25 #include "mirtk/Memory.h"
26 #include "mirtk/Array.h"
27 #include "mirtk/UnorderedMap.h"
28 #include "mirtk/Point.h"
29 
30 #include "mirtk/EdgeTable.h"
31 #include "mirtk/BoundarySegment.h"
32 
33 #include "vtkSmartPointer.h"
34 #include "vtkPolyData.h"
35 
36 
37 namespace mirtk {
38 
39 
40 /**
41  * Boundary points and boundary segments of surface mesh
42  */
43 class SurfaceBoundary : public Object
44 {
45  mirtkObjectMacro(SurfaceBoundary);
46 
47  // ---------------------------------------------------------------------------
48  // Types
49 
50  /// Type of shared edge table pointer
51  typedef SharedPtr<class EdgeTable> EdgeTablePointer;
52 
53  /// Type of surface point ID to boundary point index map
54  typedef UnorderedMap<int, int> PointIdToIndexMap;
55 
56  // ---------------------------------------------------------------------------
57  // Attributes
58 
59  /// Surface mesh
60  mirtkPublicAttributeMacro(vtkSmartPointer<vtkPolyData>, Surface);
61 
62  /// Pre-computed edge table (optional)
63  mirtkPublicAttributeMacro(EdgeTablePointer, EdgeTable);
64 
65  /// IDs of boundary points
66  mirtkReadOnlyAttributeMacro(Array<int>, PointIds);
67 
68  /// Map from surface point ID to boundary point index
69  mirtkAttributeMacro(PointIdToIndexMap, Index);
70 
71  /// Closed boundary segments
72  mirtkReadOnlyAttributeMacro(Array<BoundarySegment>, Segments);
73 
74  /// Copy attributes of this class from another instance
75  void CopyAttributes(const SurfaceBoundary &);
76 
77  // ---------------------------------------------------------------------------
78  // Construction/Destruction
79 
80 public:
81 
82  /// Constructor
83  SurfaceBoundary(vtkPolyData *, EdgeTablePointer = nullptr);
84 
85  /// Copy constructor
87 
88  /// Assignment operator
90 
91  /// Destructor
92  virtual ~SurfaceBoundary();
93 
94  // ---------------------------------------------------------------------------
95  // Initialization
96 
97  /// Pre-compute maps of surface point ID to boundary (segment) point index
98  void InitializeIndex();
99 
100  /// Pre-compute boundary edge lengths and length of each segment
101  void InitializeLengths();
102 
103  // ---------------------------------------------------------------------------
104  // Boundary points
105 
106  /// Number of surface boundary points
107  int NumberOfPoints() const;
108 
109  /// Surface point index of boundary point
110  ///
111  /// \param[in] i SurfaceBoundary point index.
112  ///
113  /// \returns Surface point index of i-th boundary point.
114  int PointId(int i) const;
115 
116  /// Get coordinates of boundary point
117  ///
118  /// \param[in] i Index of boundary point.
119  /// \param[out] p Boundary point coordinates.
120  void GetPoint(int i, double p[3]) const;
121 
122  /// Get coordinates of boundary point
123  ///
124  /// \param[in] i Index of boundary point.
125  ///
126  /// \return Boundary point coordinates.
127  class Point Point(int i) const;
128 
129  /// Find surface point ID in list of boundary points
130  ///
131  /// \param[in] ptId Surface point ID.
132  ///
133  /// \returns Index of surface boundary point or -1 if point is not on the boundary.
134  int Find(int ptId) const;
135 
136  /// Check if surface point is on the boundary
137  ///
138  /// \param[in] ptId Surface point ID.
139  ///
140  /// \returns Whether a given surface point is on the boundary.
141  bool Contains(int ptId) const;
142 
143  // ---------------------------------------------------------------------------
144  // Boundary segments
145 
146  /// Number of boundary segments
147  int NumberOfSegments() const;
148 
149  /// Get index of boundary segment that a surface point belongs to
150  ///
151  /// \param[in] ptId Index of surface point.
152  /// \param[out] i Corresponding boundary segment point index.
153  ///
154  /// \returns Index of first encountered boundary segment.
155  /// \retval -1 if point is not a boundary point.
156  int FindSegment(int ptId, int *i = nullptr) const;
157 
158  /// Get index of longest boundary segment
159  int FindLongestSegment() const;
160 
161  /// Get index of boundary segment which contains the most boundary points
162  int FindLargestSegment() const;
163 
164  /// Get n-th boundary segment
165  ///
166  /// \param[in] n Index of boundary segment.
167  ///
168  /// \returns Reference to n-th boundary segment.
169  BoundarySegment &Segment(int n);
170 
171  /// Get n-th boundary segment
172  ///
173  /// \param[in] n Index of boundary segment.
174  ///
175  /// \returns Reference to n-th boundary segment.
176  const BoundarySegment &Segment(int n) const;
177 
178  /// Get longest boundary segment
179  const BoundarySegment &LongestSegment() const;
180 
181  /// Get boundary segment which contains the most boundary points
182  const BoundarySegment &LargestSegment() const;
183 
184  /// Number of boundary segment points
185  int NumberOfPoints(int n) const;
186 
187  /// Surface point IDs of points making up a boundary point segment
188  ///
189  /// \param[in] n Index of boundary segment.
190  ///
191  /// \returns Indices of surface points making up the n-th boundary segment.
192  const Array<int> &PointIds(int n) const;
193 
194  /// Surface point ID of boundary segment point
195  ///
196  /// \param[in] n Index of boundary segment.
197  /// \param[in] i Index of boundary segment point.
198  ///
199  /// \returns Surface point ID of i-th point of n-th boundary segment.
200  int PointId(int n, int i) const;
201 
202  /// Get indices of boundary points making up a boundary segment
203  ///
204  /// \param[in] n Index of boundary segment.
205  /// \param[out] i Indices of boundary points making up the n-th boundary segment.
206  void PointIndices(int n, Array<int> &i) const;
207 
208  /// Get indices of boundary points making up a boundary segment
209  ///
210  /// \param[in] n Index of boundary segment.
211  ///
212  /// \returns Indices of boundary points making up the n-th boundary segment.
213  Array<int> PointIndices(int n) const;
214 
215  /// Boundary point index of boundary segment point
216  ///
217  /// \param[in] n Index of boundary segment.
218  /// \param[in] i Index of boundary segment point.
219  ///
220  /// \returns Boundary point index of i-th point of n-th boundary segment.
221  int PointIndex(int n, int i) const;
222 
223  // ---------------------------------------------------------------------------
224  // Selected points
225 
226  /// Select i-th boundary point
227  ///
228  /// \param[in] i Boundary point index.
229  void SelectPoint(int i);
230 
231  /// Deselect i-th boundary point
232  ///
233  /// \param[in] i Boundary point index.
234  void DeselectPoint(int i);
235 
236  // ---------------------------------------------------------------------------
237  // Debug
238 
239  /// Write boundary lines to polygonal data set file
240  bool Write(const char *) const;
241 };
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 // Inline definitions
245 ////////////////////////////////////////////////////////////////////////////////
246 
247 // =============================================================================
248 // Boundary points
249 // =============================================================================
250 
251 // -----------------------------------------------------------------------------
253 {
254  return static_cast<int>(_PointIds.size());
255 }
256 
257 // -----------------------------------------------------------------------------
258 inline int SurfaceBoundary::PointId(int i) const
259 {
260  return _PointIds[i];
261 }
262 
263 // -----------------------------------------------------------------------------
264 inline void SurfaceBoundary::GetPoint(int i, double p[3]) const
265 {
266  const int ptId = PointId(i);
267  _Surface->GetPoint(static_cast<vtkIdType>(ptId), p);
268 }
269 
270 // -----------------------------------------------------------------------------
271 inline Point SurfaceBoundary::Point(int i) const
272 {
273  double p[3];
274  GetPoint(i, p);
275  return p;
276 }
277 
278 // -----------------------------------------------------------------------------
279 inline bool SurfaceBoundary::Contains(int ptId) const
280 {
281  return Find(ptId) != -1;
282 }
283 
284 // =============================================================================
285 // Boundary segments
286 // =============================================================================
287 
288 // -----------------------------------------------------------------------------
290 {
291  return static_cast<int>(_Segments.size());
292 }
293 
294 // -----------------------------------------------------------------------------
296 {
297  return _Segments[n];
298 }
299 
300 // -----------------------------------------------------------------------------
301 inline const BoundarySegment &SurfaceBoundary::Segment(int n) const
302 {
303  return _Segments[n];
304 }
305 
306 // -----------------------------------------------------------------------------
308 {
309  return Segment(FindLongestSegment());
310 }
311 
312 // -----------------------------------------------------------------------------
314 {
315  return Segment(FindLargestSegment());
316 }
317 
318 // -----------------------------------------------------------------------------
319 inline int SurfaceBoundary::NumberOfPoints(int n) const
320 {
321  return Segment(n).NumberOfPoints();
322 }
323 
324 // -----------------------------------------------------------------------------
325 inline const Array<int> &SurfaceBoundary::PointIds(int n) const
326 {
327  return Segment(n).PointIds();
328 }
329 
330 // -----------------------------------------------------------------------------
331 inline int SurfaceBoundary::PointId(int n, int i) const
332 {
333  return Segment(n).PointId(i);
334 }
335 
336 // -----------------------------------------------------------------------------
337 inline void SurfaceBoundary::PointIndices(int n, Array<int> &i) const
338 {
339  i = PointIds(n);
340  for (auto it = i.begin(); it != i.end(); ++it) {
341  *it = Find(*it);
342  }
343 }
344 
345 // -----------------------------------------------------------------------------
346 inline Array<int> SurfaceBoundary::PointIndices(int n) const
347 {
348  Array<int> i;
349  PointIndices(n, i);
350  return i;
351 }
352 
353 // -----------------------------------------------------------------------------
354 inline int SurfaceBoundary::PointIndex(int n, int i) const
355 {
356  return Find(Segment(n).PointId(i));
357 }
358 
359 
360 } // namespace mirtk
361 
362 #endif // MIRTK_SurfaceBoundary_H
int PointIndex(int n, int i) const
void InitializeIndex()
Pre-compute maps of surface point ID to boundary (segment) point index.
void PointIndices(int n, Array< int > &i) const
void InitializeLengths()
Pre-compute boundary edge lengths and length of each segment.
class Point Point(int i) const
bool Write(const char *) const
Write boundary lines to polygonal data set file.
void DeselectPoint(int i)
int NumberOfPoints() const
Number of surface boundary points.
int NumberOfSegments() const
Number of boundary segments.
const Array< int > & PointIds(int n) const
int PointId(int i) const
BoundarySegment & Segment(int n)
Definition: IOConfig.h:41
virtual ~SurfaceBoundary()
Destructor.
SurfaceBoundary(vtkPolyData *, EdgeTablePointer=nullptr)
Constructor.
int Find(int ptId) const
const BoundarySegment & LargestSegment() const
Get boundary segment which contains the most boundary points.
int FindLongestSegment() const
Get index of longest boundary segment.
const BoundarySegment & LongestSegment() const
Get longest boundary segment.
int FindLargestSegment() const
Get index of boundary segment which contains the most boundary points.
bool Contains(int ptId) const
int FindSegment(int ptId, int *i=nullptr) const
void GetPoint(int i, double p[3]) const
int NumberOfPoints() const
Number of boundary segment points.
int PointId(int i) const
SurfaceBoundary & operator=(const SurfaceBoundary &)
Assignment operator.