Skip to content

Commit 102ee66

Browse files
committed
add buffer protocol support to PointCloud
1 parent 8507941 commit 102ee66

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

pcl/_pcl.pxd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ cimport pcl_defs as cpp
77
cdef class PointCloud:
88
cdef cpp.PointCloudPtr_t thisptr_shared
99

10+
# Buffer protocol support.
11+
cdef Py_ssize_t _shape[2]
12+
cdef Py_ssize_t _view_count
13+
1014
cdef inline cpp.PointCloud[cpp.PointXYZ] *thisptr(self) nogil:
1115
# Shortcut to get raw pointer to underlying PointCloud<PointXYZ>.
1216
return self.thisptr_shared.get()

pcl/_pcl.pyx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ cimport pcl_defs as cpp
1010

1111
cimport cython
1212
from cython.operator import dereference as deref
13+
14+
from cpython cimport Py_buffer
15+
1316
from libcpp.string cimport string
1417
from libcpp cimport bool
1518
from libcpp.vector cimport vector
@@ -125,6 +128,20 @@ cdef class SegmentationNormal:
125128
def set_axis(self, double ax, double ay, double az):
126129
mpcl_sacnormal_set_axis(deref(self.me),ax,ay,az)
127130

131+
132+
# Empirically determine strides, for buffer support.
133+
# XXX Is there a more elegant way to get these?
134+
cdef Py_ssize_t _strides[2]
135+
cdef PointCloud _pc_tmp = PointCloud(np.array([[1, 2, 3],
136+
[4, 5, 6]], dtype=np.float32))
137+
cdef cpp.PointCloud[cpp.PointXYZ] *p = _pc_tmp.thisptr()
138+
_strides[0] = ( <Py_ssize_t><void *>cpp.getptr(p, 1)
139+
- <Py_ssize_t><void *>cpp.getptr(p, 0))
140+
_strides[1] = ( <Py_ssize_t><void *>&(cpp.getptr(p, 0).y)
141+
- <Py_ssize_t><void *>&(cpp.getptr(p, 0).x))
142+
_pc_tmp = None
143+
144+
128145
cdef class PointCloud:
129146
"""Represents a cloud of points in 3-d space.
130147
@@ -137,6 +154,8 @@ cdef class PointCloud:
137154
def __cinit__(self, init=None):
138155
cdef PointCloud other
139156

157+
self._view_count = 0
158+
140159
sp_assign(self.thisptr_shared, new cpp.PointCloud[cpp.PointXYZ]())
141160

142161
if init is None:
@@ -170,6 +189,32 @@ cdef class PointCloud:
170189
def __repr__(self):
171190
return "<PointCloud of %d points>" % self.size
172191

192+
# Buffer protocol support. Taking a view locks the pointcloud for
193+
# resizing, because that can move it around in memory.
194+
def __getbuffer__(self, Py_buffer *buffer, int flags):
195+
# TODO parse flags
196+
cdef Py_ssize_t npoints = self.thisptr().size()
197+
198+
if self._view_count == 0:
199+
self._view_count += 1
200+
self._shape[0] = npoints
201+
self._shape[1] = 3
202+
203+
buffer.buf = <char *>&(cpp.getptr_at(self.thisptr(), 0).x)
204+
buffer.format = 'f'
205+
buffer.internal = NULL
206+
buffer.itemsize = sizeof(float)
207+
buffer.len = npoints * 3 * sizeof(float)
208+
buffer.ndim = 2
209+
buffer.obj = self
210+
buffer.readonly = 0
211+
buffer.shape = self._shape
212+
buffer.strides = _strides
213+
buffer.suboffsets = NULL
214+
215+
def __releasebuffer__(self, Py_buffer *buffer):
216+
self._view_count -= 1
217+
173218
# Pickle support. XXX this copies the entire pointcloud; it would be nice
174219
# to have an asarray member that returns a view, or even better, implement
175220
# the buffer protocol (https://docs.python.org/c-api/buffer.html).
@@ -246,6 +291,9 @@ cdef class PointCloud:
246291
return self.to_array().tolist()
247292

248293
def resize(self, cnp.npy_intp x):
294+
if self._view_count > 0:
295+
raise ValueError("can't resize PointCloud while there are"
296+
" arrays/memoryviews referencing it")
249297
self.thisptr().resize(x)
250298

251299
def get_point(self, cnp.npy_intp row, cnp.npy_intp col):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy