Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenMesh
openmesh-python
Commits
d753b454
Commit
d753b454
authored
Oct 31, 2019
by
Alexander Dielen
Browse files
methods to add multiple vertices and faces using numpy arrays
parent
246fd1e2
Pipeline
#12633
passed with stages
in 6 minutes and 7 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/Mesh.hh
View file @
d753b454
...
...
@@ -346,6 +346,50 @@ py::array_t<int> indices(Mesh& _self) {
return
py
::
array_t
<
int
>
(
shape
,
strides
,
indices
,
base
);
}
template
<
class
Mesh
>
void
add_vertices
(
Mesh
&
_self
,
py
::
array_t
<
typename
Mesh
::
Point
::
value_type
>
_points
)
{
// return if _points is empty
if
(
_points
.
size
()
==
0
)
{
return
;
}
// _points is not empty, throw if _points has wrong shape
if
(
_points
.
ndim
()
!=
2
||
_points
.
shape
(
1
)
!=
3
)
{
PyErr_SetString
(
PyExc_RuntimeError
,
"Array 'points' must have shape (n, 3)"
);
throw
py
::
error_already_set
();
}
for
(
ssize_t
i
=
0
;
i
<
_points
.
shape
(
0
);
++
i
)
{
_self
.
add_vertex
(
typename
Mesh
::
Point
(
_points
.
at
(
i
,
0
),
_points
.
at
(
i
,
1
),
_points
.
at
(
i
,
2
)));
}
}
template
<
class
Mesh
>
void
add_faces
(
Mesh
&
_self
,
py
::
array_t
<
int
>
_faces
)
{
// return if _faces is empty
if
(
_self
.
n_vertices
()
<
3
||
_faces
.
size
()
==
0
)
{
return
;
}
// _faces is not empty, throw if _faces has wrong shape
if
(
_faces
.
ndim
()
!=
2
||
_faces
.
shape
(
1
)
<
3
)
{
PyErr_SetString
(
PyExc_RuntimeError
,
"Array 'face_vertex_indices' must have shape (n, m) with m > 2"
);
throw
py
::
error_already_set
();
}
for
(
ssize_t
i
=
0
;
i
<
_faces
.
shape
(
0
);
++
i
)
{
std
::
vector
<
OM
::
VertexHandle
>
vhandles
;
for
(
ssize_t
j
=
0
;
j
<
_faces
.
shape
(
1
);
++
j
)
{
if
(
_faces
.
at
(
i
,
j
)
>=
0
&&
_faces
.
at
(
i
,
j
)
<
_self
.
n_vertices
())
{
vhandles
.
push_back
(
OM
::
VertexHandle
(
_faces
.
at
(
i
,
j
)));
}
}
if
(
vhandles
.
size
()
>=
3
)
{
_self
.
add_face
(
vhandles
);
}
}
}
/**
* This function template is used to expose mesh member functions that are only
* available for a specific type of mesh (i.e. they are available for polygon
...
...
@@ -599,45 +643,8 @@ void expose_mesh(py::module& m, const char *_name) {
.
def
(
py
::
init
([](
py
::
array_t
<
typename
Point
::
value_type
>
_points
,
py
::
array_t
<
int
>
_faces
)
{
Mesh
mesh
;
// return if _points is empty
if
(
_points
.
size
()
==
0
)
{
return
mesh
;
}
// _points is not empty, throw if _points has wrong shape
if
(
_points
.
ndim
()
!=
2
||
_points
.
shape
(
1
)
!=
3
)
{
PyErr_SetString
(
PyExc_RuntimeError
,
"Array 'points' must have shape (n, 3)"
);
throw
py
::
error_already_set
();
}
for
(
ssize_t
i
=
0
;
i
<
_points
.
shape
(
0
);
++
i
)
{
mesh
.
add_vertex
(
Point
(
_points
.
at
(
i
,
0
),
_points
.
at
(
i
,
1
),
_points
.
at
(
i
,
2
)));
}
// return if _faces is empty
if
(
_faces
.
size
()
==
0
)
{
return
mesh
;
}
// _faces is not empty, throw if _faces has wrong shape
if
(
_faces
.
ndim
()
!=
2
||
_faces
.
shape
(
1
)
<
3
)
{
PyErr_SetString
(
PyExc_RuntimeError
,
"Array 'face_vertex_indices' must have shape (n, m) with m > 2"
);
throw
py
::
error_already_set
();
}
for
(
ssize_t
i
=
0
;
i
<
_faces
.
shape
(
0
);
++
i
)
{
std
::
vector
<
OM
::
VertexHandle
>
vhandles
;
for
(
ssize_t
j
=
0
;
j
<
_faces
.
shape
(
1
);
++
j
)
{
if
(
_faces
.
at
(
i
,
j
)
>=
0
&&
_faces
.
at
(
i
,
j
)
<
_points
.
shape
(
0
))
{
vhandles
.
push_back
(
OM
::
VertexHandle
(
_faces
.
at
(
i
,
j
)));
}
}
if
(
vhandles
.
size
()
>=
3
)
{
mesh
.
add_face
(
vhandles
);
}
}
add_vertices
(
mesh
,
_points
);
add_faces
(
mesh
,
_faces
);
return
mesh
;
}),
py
::
arg
(
"points"
),
py
::
arg
(
"face_vertex_indices"
)
=
py
::
array_t
<
int
>
())
...
...
@@ -1350,6 +1357,17 @@ void expose_mesh(py::module& m, const char *_name) {
.
def
(
"halfedge_edge_indices"
,
&
halfedge_other_indices
<
Mesh
,
FuncHalfedgeEdge
>
)
.
def
(
"he_indices"
,
&
halfedge_other_indices
<
Mesh
,
FuncHalfedgeEdge
>
)
//======================================================================
// numpy add vertices & faces
//======================================================================
.
def
(
"add_vertices"
,
&
add_vertices
<
Mesh
>
,
py
::
arg
(
"points"
))
.
def
(
"add_faces"
,
&
add_faces
<
Mesh
>
,
py
::
arg
(
"face_vertex_indices"
))
.
def
(
"resize_points"
,
[](
Mesh
&
_self
,
size_t
_n_vertices
)
{
_self
.
resize
(
_n_vertices
,
_self
.
n_edges
(),
_self
.
n_faces
());
})
//======================================================================
// new property interface: single item
//======================================================================
...
...
tests/test_add_numpy.py
0 → 100644
View file @
d753b454
import
unittest
import
openmesh
import
numpy
as
np
class
AddNumPy
(
unittest
.
TestCase
):
def
setUp
(
self
):
self
.
points
=
np
.
array
([[
0
,
0
,
0
],
[
0
,
1
,
0
],
[
1
,
1
,
0
],
[
1
,
0
,
0
]])
self
.
fv_indices
=
np
.
array
([[
2
,
1
,
0
],
[
2
,
0
,
3
]])
self
.
mesh
=
openmesh
.
TriMesh
(
self
.
points
,
self
.
fv_indices
)
# Test setup:
# 1 === 2
# | / |
# | / |
# | / |
# 0 === 3
self
.
checkSetUp
()
def
checkSetUp
(
self
):
self
.
assertEqual
(
self
.
mesh
.
n_vertices
(),
4
)
self
.
assertEqual
(
self
.
mesh
.
n_edges
(),
5
)
self
.
assertEqual
(
self
.
mesh
.
n_faces
(),
2
)
self
.
assertEqual
(
self
.
mesh
.
points
().
shape
,
(
4
,
3
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
points
(),
self
.
points
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
fv_indices
(),
self
.
fv_indices
))
def
checkAddVertices
(
self
,
new_points
):
self
.
assertEqual
(
self
.
mesh
.
n_vertices
(),
10
)
self
.
assertEqual
(
self
.
mesh
.
n_edges
(),
5
)
self
.
assertEqual
(
self
.
mesh
.
n_faces
(),
2
)
self
.
assertEqual
(
self
.
mesh
.
points
().
shape
,
(
10
,
3
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
points
()[:
4
],
self
.
points
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
points
()[
4
:],
new_points
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
fv_indices
(),
self
.
fv_indices
))
def
checkAddVerticesAndFaces
(
self
,
new_points
,
new_faces
):
self
.
assertEqual
(
self
.
mesh
.
n_vertices
(),
6
)
self
.
assertEqual
(
self
.
mesh
.
n_edges
(),
9
)
self
.
assertEqual
(
self
.
mesh
.
n_faces
(),
4
)
self
.
assertEqual
(
self
.
mesh
.
points
().
shape
,
(
6
,
3
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
points
()[:
4
],
self
.
points
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
points
()[
4
:],
new_points
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
fv_indices
()[:
2
],
self
.
fv_indices
))
self
.
assertTrue
(
np
.
array_equal
(
self
.
mesh
.
fv_indices
()[
2
:],
new_faces
))
def
test_resize_points
(
self
):
new_points
=
np
.
random
.
rand
(
6
,
3
)
self
.
mesh
.
resize_points
(
10
)
self
.
mesh
.
points
()[
4
:]
=
new_points
self
.
checkAddVertices
(
new_points
)
def
test_add_vertices
(
self
):
new_points
=
np
.
random
.
rand
(
6
,
3
)
self
.
mesh
.
add_vertices
(
new_points
)
self
.
checkAddVertices
(
new_points
)
def
test_add_vertices_wrong_shape
(
self
):
with
self
.
assertRaises
(
RuntimeError
):
self
.
mesh
.
add_vertices
(
np
.
random
.
rand
(
6
,
2
))
self
.
checkSetUp
()
with
self
.
assertRaises
(
RuntimeError
):
self
.
mesh
.
add_vertices
(
np
.
random
.
rand
(
6
,
4
))
self
.
checkSetUp
()
with
self
.
assertRaises
(
RuntimeError
):
self
.
mesh
.
add_vertices
(
np
.
random
.
rand
(
6
,
3
,
3
))
self
.
checkSetUp
()
def
test_add_vertices_empty_array
(
self
):
self
.
mesh
.
add_vertices
(
np
.
random
.
rand
(
0
,
3
))
self
.
checkSetUp
()
def
test_add_faces
(
self
):
new_vertices
=
[[
2
,
1
,
0
],
[
2
,
0
,
0
]]
new_faces
=
[[
4
,
2
,
3
],
[
4
,
3
,
5
]]
self
.
mesh
.
add_vertices
(
new_vertices
)
self
.
mesh
.
add_faces
(
new_faces
)
self
.
checkAddVerticesAndFaces
(
new_vertices
,
new_faces
)
def
test_add_faces_wrong_shape
(
self
):
with
self
.
assertRaises
(
RuntimeError
):
self
.
mesh
.
add_faces
(
np
.
arange
(
10
).
reshape
(
5
,
2
))
self
.
checkSetUp
()
with
self
.
assertRaises
(
RuntimeError
):
self
.
mesh
.
add_faces
(
np
.
arange
(
30
).
reshape
(
5
,
3
,
2
))
self
.
checkSetUp
()
def
test_add_faces_empty_array
(
self
):
self
.
mesh
.
add_faces
(
np
.
random
.
rand
(
0
,
3
))
self
.
checkSetUp
()
if
__name__
==
'__main__'
:
suite
=
unittest
.
TestLoader
().
loadTestsFromTestCase
(
AddNumPy
)
unittest
.
TextTestRunner
(
verbosity
=
2
).
run
(
suite
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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