Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
OpenMesh
OpenMesh
Commits
d04ec789
Commit
d04ec789
authored
Mar 27, 2020
by
Max Lyon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add filtered to SmartRanges
parent
0df4666d
Pipeline
#13880
canceled with stages
in 46 minutes and 53 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
113 additions
and
0 deletions
+113
-0
src/OpenMesh/Core/Mesh/SmartRange.hh
src/OpenMesh/Core/Mesh/SmartRange.hh
+64
-0
src/Unittests/unittests_smart_ranges.cc
src/Unittests/unittests_smart_ranges.cc
+49
-0
No files found.
src/OpenMesh/Core/Mesh/SmartRange.hh
View file @
d04ec789
...
...
@@ -65,10 +65,17 @@ struct Identity
}
template
<
typename
RangeT
,
typename
HandleT
,
typename
Functor
>
struct
FilteredSmartRangeT
;
/// Base class for all smart range types
template
<
typename
RangeT
,
typename
HandleT
>
struct
SmartRangeT
{
using
Handle
=
HandleT
;
using
SmartRange
=
SmartRangeT
<
RangeT
,
HandleT
>
;
using
Range
=
RangeT
;
// TODO: Someone with better c++ knowledge may improve the code below.
/** @brief Computes the sum of elements.
...
...
@@ -386,6 +393,63 @@ struct SmartRangeT
}
/** @brief Only iterate over a subset of elements
*
* Returns a smart range which skips all elements that do not satisfy functor \p f
*
* @param f Functor that needs to be evaluated to true if the element should not be skipped.
*/
template
<
typename
Functor
>
auto
filtered
(
Functor
&&
f
)
->
FilteredSmartRangeT
<
SmartRange
,
Handle
,
typename
std
::
decay
<
Functor
>::
type
>
{
auto
range
=
static_cast
<
const
RangeT
*>
(
this
);
auto
b
=
(
*
range
).
begin
();
auto
e
=
(
*
range
).
end
();
return
FilteredSmartRangeT
<
SmartRange
,
Handle
,
typename
std
::
decay
<
Functor
>::
type
>
(
f
,
b
,
e
);
}
};
/// Class which applies a filter when iterating over elements
template
<
typename
RangeT
,
typename
HandleT
,
typename
Functor
>
struct
FilteredSmartRangeT
:
public
SmartRangeT
<
FilteredSmartRangeT
<
RangeT
,
HandleT
,
Functor
>
,
HandleT
>
{
using
BaseRange
=
SmartRangeT
<
FilteredSmartRangeT
<
RangeT
,
HandleT
,
Functor
>
,
HandleT
>
;
using
BaseIterator
=
decltype
((
std
::
declval
<
typename
RangeT
::
Range
>
().
begin
()));
struct
FilteredIterator
:
public
BaseIterator
{
FilteredIterator
(
Functor
f
,
BaseIterator
it
,
BaseIterator
end
)
:
BaseIterator
(
it
),
f_
(
f
),
end_
(
end
)
{
if
(
!
f_
(
*
(
*
this
)))
// if start is not valid go to first valid one
operator
++
();
}
FilteredIterator
&
operator
++
()
{
if
(
BaseIterator
::
operator
==
(
end_
))
// don't go past end
return
*
this
;
// go to next valid one
do
BaseIterator
::
operator
++
();
while
(
BaseIterator
::
operator
!=
(
end_
)
&&
!
f_
(
*
(
*
this
)));
return
*
this
;
}
Functor
f_
;
BaseIterator
end_
;
};
FilteredSmartRangeT
(
Functor
f
,
BaseIterator
begin
,
BaseIterator
end
)
:
f_
(
f
),
begin_
(
begin
),
end_
(
end
){}
FilteredIterator
begin
()
const
{
return
FilteredIterator
(
f_
,
begin_
,
end_
);
}
FilteredIterator
end
()
const
{
return
FilteredIterator
(
f_
,
end_
,
end_
);
}
Functor
f_
;
BaseIterator
begin_
;
BaseIterator
end_
;
};
...
...
src/Unittests/unittests_smart_ranges.cc
View file @
d04ec789
...
...
@@ -296,5 +296,54 @@ TEST_F(OpenMeshSmartRanges, ForEach)
}
/* Test filter
*/
TEST_F
(
OpenMeshSmartRanges
,
Filtered
)
{
using
VH
=
OpenMesh
::
VertexHandle
;
auto
is_even
=
[](
VH
vh
)
{
return
vh
.
idx
()
%
2
==
0
;
};
auto
is_odd
=
[](
VH
vh
)
{
return
vh
.
idx
()
%
2
==
1
;
};
auto
is_divisible_by_3
=
[](
VH
vh
)
{
return
vh
.
idx
()
%
3
==
0
;
};
auto
to_id
=
[](
VH
vh
)
{
return
vh
.
idx
();
};
auto
even_vertices
=
mesh_
.
vertices
().
filtered
(
is_even
).
to_vector
(
to_id
);
EXPECT_EQ
(
even_vertices
.
size
(),
4
);
EXPECT_EQ
(
even_vertices
[
0
],
0
);
EXPECT_EQ
(
even_vertices
[
1
],
2
);
EXPECT_EQ
(
even_vertices
[
2
],
4
);
EXPECT_EQ
(
even_vertices
[
3
],
6
);
auto
odd_vertices
=
mesh_
.
vertices
().
filtered
(
is_odd
).
to_vector
(
to_id
);
EXPECT_EQ
(
odd_vertices
.
size
(),
4
);
EXPECT_EQ
(
odd_vertices
[
0
],
1
);
EXPECT_EQ
(
odd_vertices
[
1
],
3
);
EXPECT_EQ
(
odd_vertices
[
2
],
5
);
EXPECT_EQ
(
odd_vertices
[
3
],
7
);
auto
even_3_vertices
=
mesh_
.
vertices
().
filtered
(
is_even
).
filtered
(
is_divisible_by_3
).
to_vector
(
to_id
);
EXPECT_EQ
(
even_3_vertices
.
size
(),
2
);
EXPECT_EQ
(
even_3_vertices
[
0
],
0
);
EXPECT_EQ
(
even_3_vertices
[
1
],
6
);
auto
odd_3_vertices
=
mesh_
.
vertices
().
filtered
(
is_odd
).
filtered
(
is_divisible_by_3
).
to_vector
(
to_id
);
EXPECT_EQ
(
odd_3_vertices
.
size
(),
1
);
EXPECT_EQ
(
odd_3_vertices
[
0
],
3
);
// create a vector of vertices in the order they are visited when iterating over face vertices, but every vertex only once
std
::
vector
<
VH
>
vertices
;
OpenMesh
::
VProp
<
bool
>
to_be_processed
(
true
,
mesh_
);
auto
store_vertex
=
[
&
](
VH
vh
)
{
to_be_processed
(
vh
)
=
false
;
vertices
.
push_back
(
vh
);
};
for
(
auto
fh
:
mesh_
.
faces
())
fh
.
vertices
().
filtered
(
to_be_processed
).
for_each
(
store_vertex
);
EXPECT_EQ
(
vertices
.
size
(),
mesh_
.
n_vertices
())
<<
" number of visited vertices not correct"
;
EXPECT_TRUE
(
mesh_
.
vertices
().
all_of
([
&
](
VH
vh
)
{
return
!
to_be_processed
(
vh
);
}))
<<
"did not visit all vertices"
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment