Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__LIBGRID__SELECTOR_INTERFACE__
34 : #define __H__LIBGRID__SELECTOR_INTERFACE__
35 :
36 : #include <cassert>
37 : #include "lib_grid/grid/grid.h"
38 :
39 : #ifdef UG_PARALLEL
40 : #include "lib_grid/parallelization/parallel_grid_layout.h"
41 : #include "pcl/pcl_interface_communicator.h"
42 : #endif
43 :
44 :
45 : namespace ug
46 : {
47 : /** \ingroup lib_grid_tools
48 : * \{ */
49 :
50 : ////////////////////////////////////////////////////////////////////////
51 : // SelectorElements
52 : /// Use these constants to specify which elements shall be supported by a Selector.
53 : /**
54 : * You may combine the constants using or-operations.
55 : */
56 : enum SelectorElements
57 : {
58 : SE_NONE = 0,
59 : SE_VERTEX = 1,
60 : SE_EDGE = 1<<1,
61 : SE_FACE = 1<<2,
62 : SE_VOLUME = 1 << 3,
63 : SE_ALL = SE_VERTEX | SE_EDGE | SE_FACE | SE_VOLUME
64 : };
65 :
66 : ////////////////////////////////////////////////////////////////////////
67 : ////////////////////////////////////////////////////////////////////////
68 : // ISelector
69 : /// base-implementation of a selector
70 : /**
71 : * A selector is a useful class, that allows the user to mark
72 : * elements of a grid as selected or deselected.
73 : * The selection status is maintained even if new elements
74 : * are created or old ones deleted. Features like
75 : * autoselection and selection_inheritance allow users to
76 : * follow the creation and removal of elements in all kind of
77 : * algorithms.
78 : *
79 : * Derived classes like Selector and MGSelector or
80 : * VertexSelector, EdgeSelector, FaceSelector and VolumeSelector
81 : * keep selected elements in linked lists and allow the user
82 : * to iterate over them. If a selected element is removed
83 : * from the underlying grid, it is automatically removed
84 : * from the element-lists of all associated selectors.
85 : *
86 : * Please note that the selector has to be registered at a
87 : * grid before it may be used. Derived classes may use the
88 : * protected method set_grid to do so, or pass a grid directly to
89 : * the constructor.
90 : *
91 : * This is a base implementation that can not be instatiated.
92 : * It features most cruical methods like is_selected,
93 : * select, deselect etc.
94 : *
95 : * autoselection and selection_inheritance can be enabled here.
96 : * If autoselection is enabled, then all elements that are created
97 : * while the selector is registered at a grid will automatically
98 : * be selected.
99 : *
100 : * If selection_inheritance is enabled, then all elements that are
101 : * created while the selector is registered at a grid, and whose
102 : * parents (from the same grid) are selected will be automatically
103 : * selected, too. selection_inheritance is ignored if autoselection
104 : * is enabled.
105 : *
106 : * Support for different element-types can be enabled / disabled
107 : * by derived classes using set_supported_elements,
108 : * enable_element_support or disable_element_support.
109 : *
110 : * Derived classes have to store the selected elements in linked lists
111 : * of type ISelector::SectionContainer and should feature begin and
112 : * end itertors to the sections of those lists.
113 : *
114 : * ISelector communicates with derived classes via the methods
115 : * add_to_list and erase_from_list.
116 : *
117 : * Especially for the implementation of erase_from_list the protected
118 : * member function get_iterator may be useful, which returns the
119 : * iterator that is associated with the selected element.
120 : *
121 : * If a derived class wants to change the selection-status of an
122 : * element behind the scenes (avoids select, deselect), then it
123 : * may use the protected methods mark_selected, mark_deselected.
124 : */
125 : class UG_API ISelector : public GridObserver
126 : {
127 : public:
128 : typedef byte status_t;
129 :
130 : enum{
131 : DESELECTED = 0,
132 : SELECTED = 1
133 : };
134 :
135 : public:
136 : ISelector(uint supportedElements = SE_ALL);
137 : ISelector(Grid& grid, uint supportedElements = SE_ALL);
138 : virtual ~ISelector();
139 :
140 : // virtual methods
141 : virtual void clear() = 0;
142 :
143 : // selection
144 : /// selects an element
145 : /** You may optionally pass a status-flag. Note that 0 is reserved for
146 : * non-selected elements. status thus has to be bigger then 0.
147 : *
148 : * If the element is already selected, then select only alters the status-
149 : * flag of the element. It however does not change the elements position
150 : * in the list of selected elements.
151 : * \{
152 : */
153 : inline void select(GridObject* elem, byte status);
154 : inline void select(GridObject* elem)
155 0 : {select(elem, 1);}
156 :
157 : template <class TElem>
158 : inline void select(TElem* elem, byte status);
159 : template <class TElem>
160 0 : inline void select(TElem* elem)
161 0 : {select(elem, 1);}
162 :
163 : template <class TIterator>
164 : inline void select(TIterator iterBegin, TIterator iterEnd, byte status = 1);
165 : /** \} */
166 :
167 : /// selects an element
168 : /** In this context 'mark' is simply a synonym for 'select' and simply forwards
169 : * to the corresponding 'select' method.
170 : * \{ */
171 : template <class TElem>
172 : inline void mark(TElem* elem)
173 : {select(elem);}
174 :
175 : template <class TElem>
176 : inline void mark(TElem* elem, byte status)
177 : {select(elem, status);}
178 : /** \} */
179 :
180 :
181 : // deselection
182 : inline void deselect(GridObject* elem);
183 :
184 : template <class TElem>
185 : inline void deselect(TElem* elem);
186 :
187 : template <class TIterator>
188 : inline void deselect(TIterator iterBegin, TIterator iterEnd);
189 :
190 : /// deselects an element
191 : /** In this context 'unmark' is simply a synonym for 'deselect'.*/
192 : template <class TElem>
193 : inline void unmark(TElem* elem)
194 : {deselect(elem);}
195 :
196 : // selection status
197 : /// returns the selection state of the specified elelent
198 : /** \{ */
199 : inline byte get_selection_status(GridObject* elem) const;
200 0 : inline byte get_selection_status(Vertex* vrt) const {if(!elements_are_supported(SE_VERTEX)) return 0; return m_aaSelVRT[vrt];}
201 0 : inline byte get_selection_status(Edge* edge) const {if(!elements_are_supported(SE_EDGE)) return 0; return m_aaSelEDGE[edge];}
202 0 : inline byte get_selection_status(Face* face) const {if(!elements_are_supported(SE_FACE)) return 0; return m_aaSelFACE[face];}
203 0 : inline byte get_selection_status(Volume* vol) const {if(!elements_are_supported(SE_VOLUME)) return 0; return m_aaSelVOL[vol];}
204 : /** \} */
205 :
206 : /// returns the selection state of the specified elelent
207 : /** In this context, 'get_mark' is simply a synonym for 'get_selection_status'
208 : * and simply forwards to the corresponding method.*/
209 : template <class TElem>
210 : inline byte get_mark(TElem* elem) const
211 : {return get_selection_status(elem);}
212 :
213 : /// returns true if an element is selected
214 : template <class TElem>
215 0 : inline bool is_selected(TElem* elem) const {return get_selection_status(elem) != 0;}
216 :
217 : // non-virtual methods.
218 0 : inline Grid* grid() const {return m_pGrid;}
219 :
220 : /// returns a geometric object collection, containing all selected objects
221 : virtual GridObjectCollection get_grid_objects() const = 0;
222 :
223 : /// returns true if the given element-types are supported.
224 : /** pass an or-combination of constants enumerated in SubsetHandlerElements.*/
225 : inline bool elements_are_supported(uint shElements) const;
226 :
227 : // if enabled, all new elements will be automatically enabled. Disabled by default.
228 : void enable_autoselection(bool bEnable);
229 0 : inline bool autoselection_enabled() {return m_bAutoselectionEnabled;}
230 :
231 : // if enabled, newly created elements derive their selection status from their parents. Enabled by default.
232 : void enable_selection_inheritance(bool bEnable);
233 0 : inline bool selection_inheritance_enabled() {return m_bSelectionInheritanceEnabled;}
234 :
235 : /** restricts subset inheritance so that new elements derive their
236 : * selection status only from parents with the same base-type.
237 : * Disabled by default.
238 : * NOTE: strict inheritance only has an effect if
239 : * selection inheritance is enabled.*/
240 : void enable_strict_inheritance(bool bEnable);
241 : inline bool strict_inheritance_enabled() {return m_bStrictInheritanceEnabled;}
242 : // grid callbacks
243 : /*
244 : virtual void registered_at_grid(Grid* grid);
245 : virtual void unregistered_from_grid(Grid* grid);
246 : */
247 : virtual void grid_to_be_destroyed(Grid* grid);
248 : virtual void elements_to_be_cleared(Grid* grid);
249 :
250 : // element callbacks
251 : virtual void vertex_created(Grid* grid, Vertex* vrt,
252 : GridObject* pParent = NULL,
253 : bool replacesParent = false);
254 :
255 : virtual void edge_created(Grid* grid, Edge* e,
256 : GridObject* pParent = NULL,
257 : bool replacesParent = false);
258 :
259 : virtual void face_created(Grid* grid, Face* f,
260 : GridObject* pParent = NULL,
261 : bool replacesParent = false);
262 :
263 : virtual void volume_created(Grid* grid, Volume* vol,
264 : GridObject* pParent = NULL,
265 : bool replacesParent = false);
266 :
267 : virtual void vertex_to_be_erased(Grid* grid, Vertex* vrt,
268 : Vertex* replacedBy = NULL);
269 :
270 : virtual void edge_to_be_erased(Grid* grid, Edge* e,
271 : Edge* replacedBy = NULL);
272 :
273 : virtual void face_to_be_erased(Grid* grid, Face* f,
274 : Face* replacedBy = NULL);
275 :
276 : virtual void volume_to_be_erased(Grid* grid, Volume* vol,
277 : Volume* replacedBy = NULL);
278 :
279 : virtual void vertices_to_be_merged(Grid* grid, Vertex* target,
280 : Vertex* elem1, Vertex* elem2);
281 :
282 : virtual void edges_to_be_merged(Grid* grid, Edge* target,
283 : Edge* elem1, Edge* elem2);
284 :
285 : virtual void faces_to_be_merged(Grid* grid, Face* target,
286 : Face* elem1, Face* elem2);
287 :
288 : virtual void volumes_to_be_merged(Grid* grid, Volume* target,
289 : Volume* elem1, Volume* elem2);
290 :
291 : /// returns true if the selector contains vertices
292 : virtual bool contains_vertices() const = 0;
293 :
294 : /// returns true if the selector contains edges
295 : virtual bool contains_edges() const = 0;
296 :
297 : /// returns true if the selector contains faces
298 : virtual bool contains_faces() const = 0;
299 :
300 : /// returns true if the selector contains volumes
301 : virtual bool contains_volumes() const = 0;
302 :
303 : /// broadcasts the current selection
304 : /** This method is only interesting for parallel algorithms.
305 : * By setting 'deselect' to true, all copies of an element will be deselected if
306 : * one or more copies already were deselected.
307 : *
308 : * If 'deselect' is false (this is the default), the selection-states of all
309 : * copies of an element will be united and applied to all copies of that element.
310 : *
311 : * Set 'includeGhosts' to true, to also broadcast the selection-state to
312 : * ghost-copies. Default is false.
313 : */
314 : virtual void broadcast_selection_states(bool deselect = false,
315 : bool includeGhosts = false);
316 :
317 : protected:
318 : typedef Grid::traits<Vertex>::AttachedElementList AttachedVertexList;
319 : typedef Grid::traits<Edge>::AttachedElementList AttachedEdgeList;
320 : typedef Grid::traits<Face>::AttachedElementList AttachedFaceList;
321 : typedef Grid::traits<Volume>::AttachedElementList AttachedVolumeList;
322 :
323 : typedef Grid::traits<Vertex>::SectionContainer VertexSectionContainer;
324 : typedef Grid::traits<Edge>::SectionContainer EdgeSectionContainer;
325 : typedef Grid::traits<Face>::SectionContainer FaceSectionContainer;
326 : typedef Grid::traits<Volume>::SectionContainer VolumeSectionContainer;
327 :
328 : protected:
329 : virtual void add_to_list(Vertex* elem) = 0;
330 : virtual void add_to_list(Edge* elem) = 0;
331 : virtual void add_to_list(Face* elem) = 0;
332 : virtual void add_to_list(Volume* elem) = 0;
333 :
334 : virtual void erase_from_list(Vertex* elem) = 0;
335 : virtual void erase_from_list(Edge* elem) = 0;
336 : virtual void erase_from_list(Face* elem) = 0;
337 : virtual void erase_from_list(Volume* elem) = 0;
338 :
339 : protected:
340 : /// performs grid registration / deregistration and initialisation of the observer.
341 : /** If you call this method with NULL, deregistration and cleanup is performed.
342 : *
343 : * Please note: sine set_grid calls virtual methods it shouldn't
344 : * be invoked from any constructors / destructors.*/
345 : void set_grid(Grid* grid);
346 :
347 : /// set the type of elements that shall be handled by the SubsetHandler.
348 : /** Pass an or-combination of constants enumerated in SubsetHandlerElements.
349 : * \sa SubsetHandler::enable_element_support*/
350 : // Protected non-virtual to avoid virtual calls during construction
351 : void set_supported_elements(uint shElements);
352 :
353 : /// enable support for element-types. Does not invalidate previous settings.
354 : /** pass an or-combination of constants enumerated in SubsetHandlerElements.*/
355 : // Protected non-virtual to avoid virtual calls during construction
356 : void enable_element_support(uint shElements);
357 :
358 : /// disable support for element-types.
359 : /** pass an or-combination of constants enumerated in SubsetHandlerElements.*/
360 : // Protected non-virtual to avoid virtual calls during construction
361 : void disable_element_support(uint shElements);
362 :
363 0 : inline void mark_selected(Vertex* elem, byte status) {assert(elements_are_supported(SE_VERTEX)); m_aaSelVRT[elem] = status;}
364 0 : inline void mark_selected(Edge* elem, byte status) {assert(elements_are_supported(SE_EDGE)); m_aaSelEDGE[elem] = status;}
365 0 : inline void mark_selected(Face* elem, byte status) {assert(elements_are_supported(SE_FACE)); m_aaSelFACE[elem] = status;}
366 0 : inline void mark_selected(Volume* elem, byte status) {assert(elements_are_supported(SE_VOLUME)); m_aaSelVOL[elem] = status;}
367 :
368 0 : inline void mark_deselected(Vertex* elem) {assert(elements_are_supported(SE_VERTEX)); m_aaSelVRT[elem] = 0;}
369 0 : inline void mark_deselected(Edge* elem) {assert(elements_are_supported(SE_EDGE)); m_aaSelEDGE[elem] = 0;}
370 0 : inline void mark_deselected(Face* elem) {assert(elements_are_supported(SE_FACE)); m_aaSelFACE[elem] = 0;}
371 0 : inline void mark_deselected(Volume* elem) {assert(elements_are_supported(SE_VOLUME)); m_aaSelVOL[elem] = 0;}
372 :
373 : /// helper for GridObserver callbacks.
374 : template <class TElem>
375 : void elems_to_be_merged(Grid* grid, TElem* target,
376 : TElem* elem1, TElem* elem2);
377 :
378 : private:
379 : ISelector(const ISelector& sel){};///< Copy Constructor not yet implemented!
380 :
381 : #ifdef UG_PARALLEL
382 : template <class TIntfcCom>
383 : void broadcast_selection_states(bool deselect, bool includeGhosts,
384 : TIntfcCom& icom);
385 : #endif
386 :
387 : protected:
388 : Grid* m_pGrid;
389 : uint m_supportedElements;
390 : bool m_bAutoselectionEnabled;
391 : bool m_bSelectionInheritanceEnabled;
392 : bool m_bStrictInheritanceEnabled;
393 :
394 : // will use a default constructor
395 : typedef Attachment<unsigned char> AUChar;
396 : AUChar m_aSelected;
397 :
398 : Grid::AttachmentAccessor<Vertex, AUChar> m_aaSelVRT;
399 : Grid::AttachmentAccessor<Edge, AUChar> m_aaSelEDGE;
400 : Grid::AttachmentAccessor<Face, AUChar> m_aaSelFACE;
401 : Grid::AttachmentAccessor<Volume, AUChar> m_aaSelVOL;
402 :
403 : #ifdef UG_PARALLEL
404 : pcl::InterfaceCommunicator<VertexLayout> m_icomVRT;
405 : pcl::InterfaceCommunicator<EdgeLayout> m_icomEDGE;
406 : pcl::InterfaceCommunicator<FaceLayout> m_icomFACE;
407 : pcl::InterfaceCommunicator<VolumeLayout> m_icomVOL;
408 : #endif
409 : };
410 :
411 : /// \}
412 :
413 : }// end of namespace
414 :
415 : ////////////////////////////////
416 : // include implementation
417 : #include "selector_interface_impl.hpp"
418 :
419 : #endif
|