|
34 | 34 |
|
35 | 35 | #include "PyArray.hpp" |
36 | 36 | #include <pdal/io/MemoryViewReader.hpp> |
37 | | - |
38 | 37 | #include <numpy/arrayobject.h> |
39 | 38 |
|
40 | 39 | namespace pdal |
@@ -90,12 +89,36 @@ std::string toString(PyObject *pname) |
90 | 89 |
|
91 | 90 | } // unnamed namespace |
92 | 91 |
|
93 | | -Array::Array() : m_array(nullptr) |
| 92 | +Array::Array(PointViewPtr view) |
94 | 93 | { |
95 | 94 | if (_import_array() < 0) |
96 | 95 | throw pdal_error("Could not import numpy.core.multiarray."); |
| 96 | + |
| 97 | + PyObject *dtype_dict = (PyObject*)buildNumpyDescription(view); |
| 98 | + if (!dtype_dict) |
| 99 | + throw pdal_error("Unable to build numpy dtype " |
| 100 | + "description dictionary"); |
| 101 | + |
| 102 | + PyArray_Descr *dtype = nullptr; |
| 103 | + if (PyArray_DescrConverter(dtype_dict, &dtype) == NPY_FAIL) |
| 104 | + throw pdal_error("Unable to build numpy dtype"); |
| 105 | + Py_XDECREF(dtype_dict); |
| 106 | + |
| 107 | + // This is a 1 x size array. |
| 108 | + npy_intp size = view->size(); |
| 109 | + m_array = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, |
| 110 | + 1, &size, 0, nullptr, NPY_ARRAY_CARRAY, nullptr); |
| 111 | + |
| 112 | + // copy the data |
| 113 | + DimTypeList types = view->dimTypes(); |
| 114 | + for (PointId idx = 0; idx < view->size(); idx++) |
| 115 | + { |
| 116 | + char *p = (char *)PyArray_GETPTR1(m_array, idx); |
| 117 | + view->getPackedPoint(types, idx, p); |
| 118 | + } |
97 | 119 | } |
98 | 120 |
|
| 121 | + |
99 | 122 | Array::Array(PyArrayObject* array) : m_array(array), m_rowMajor(true) |
100 | 123 | { |
101 | 124 | if (_import_array() < 0) |
@@ -163,50 +186,10 @@ Array::Array(PyArrayObject* array) : m_array(array), m_rowMajor(true) |
163 | 186 |
|
164 | 187 | Array::~Array() |
165 | 188 | { |
166 | | - if (m_array) |
167 | | - Py_XDECREF((PyObject *)m_array); |
| 189 | + Py_XDECREF(m_array); |
168 | 190 | } |
169 | 191 |
|
170 | 192 |
|
171 | | -void Array::update(PointViewPtr view) |
172 | | -{ |
173 | | - if (m_array) |
174 | | - Py_XDECREF((PyObject *)m_array); |
175 | | - m_array = nullptr; // Just in case of an exception. |
176 | | - |
177 | | - Dimension::IdList dims = view->dims(); |
178 | | - npy_intp size = view->size(); |
179 | | - |
180 | | - PyObject *dtype_dict = (PyObject*)buildNumpyDescription(view); |
181 | | - if (!dtype_dict) |
182 | | - throw pdal_error("Unable to build numpy dtype " |
183 | | - "description dictionary"); |
184 | | - |
185 | | - PyArray_Descr *dtype = nullptr; |
186 | | - if (PyArray_DescrConverter(dtype_dict, &dtype) == NPY_FAIL) |
187 | | - throw pdal_error("Unable to build numpy dtype"); |
188 | | - Py_XDECREF(dtype_dict); |
189 | | - |
190 | | - // This is a 1 x size array. |
191 | | - m_array = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, |
192 | | - 1, &size, 0, nullptr, NPY_ARRAY_CARRAY, nullptr); |
193 | | - |
194 | | - // copy the data |
195 | | - DimTypeList types = view->dimTypes(); |
196 | | - for (PointId idx = 0; idx < view->size(); idx++) |
197 | | - { |
198 | | - char *p = (char *)PyArray_GETPTR1(m_array, idx); |
199 | | - view->getPackedPoint(types, idx, p); |
200 | | - } |
201 | | -} |
202 | | - |
203 | | - |
204 | | -//ABELL - Who's responsible for incrementing the ref count? |
205 | | -PyArrayObject *Array::getPythonArray() const |
206 | | -{ |
207 | | - return m_array; |
208 | | -} |
209 | | - |
210 | 193 | PyObject* Array::buildNumpyDescription(PointViewPtr view) const |
211 | 194 | { |
212 | 195 | // Build up a numpy dtype dictionary |
@@ -263,31 +246,100 @@ PyObject* Array::buildNumpyDescription(PointViewPtr view) const |
263 | 246 | return dict; |
264 | 247 | } |
265 | 248 |
|
266 | | -bool Array::rowMajor() const |
| 249 | + |
| 250 | +ArrayIter& Array::iterator() |
267 | 251 | { |
268 | | - return m_rowMajor; |
| 252 | + ArrayIter *it = new ArrayIter(m_array); |
| 253 | + m_iterators.push_back(std::unique_ptr<ArrayIter>(it)); |
| 254 | + return *it; |
269 | 255 | } |
270 | 256 |
|
271 | | -Array::Shape Array::shape() const |
| 257 | + |
| 258 | +Mesh::Mesh(PointViewPtr view) |
272 | 259 | { |
273 | | - return m_shape; |
| 260 | + if (_import_array() < 0) |
| 261 | + throw pdal_error("Could not import numpy.core.multiarray."); |
| 262 | + |
| 263 | + PyObject *dtype_dict = (PyObject*)buildNumpyDescription(view); |
| 264 | + if (!dtype_dict) |
| 265 | + throw pdal_error("Unable to build numpy dtype " |
| 266 | + "description dictionary"); |
| 267 | + |
| 268 | + PyArray_Descr *dtype = nullptr; |
| 269 | + if (PyArray_DescrConverter(dtype_dict, &dtype) == NPY_FAIL) |
| 270 | + throw pdal_error("Unable to build numpy dtype"); |
| 271 | + Py_XDECREF(dtype_dict); |
| 272 | + |
| 273 | + // This is a 1 x size array. |
| 274 | + TriangularMesh* mesh = view->mesh(); |
| 275 | + npy_intp size = mesh ? mesh->size() : 0; |
| 276 | + m_mesh = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, |
| 277 | + 1, &size, 0, nullptr, NPY_ARRAY_CARRAY, nullptr); |
| 278 | + |
| 279 | + for (PointId idx = 0; idx < size; idx++) |
| 280 | + { |
| 281 | + char* p = (char *)PyArray_GETPTR1(m_mesh, idx); |
| 282 | + const Triangle& t = (*mesh)[idx]; |
| 283 | + uint32_t a = (uint32_t)t.m_a; |
| 284 | + std::memcpy(p, &a, 4); |
| 285 | + uint32_t b = (uint32_t)t.m_b; |
| 286 | + std::memcpy(p + 4, &b, 4); |
| 287 | + uint32_t c = (uint32_t)t.m_c; |
| 288 | + std::memcpy(p + 8, &c, 4); |
| 289 | + } |
274 | 290 | } |
275 | 291 |
|
276 | | -const Array::Fields& Array::fields() const |
| 292 | + |
| 293 | +Mesh::~Mesh() |
277 | 294 | { |
278 | | - return m_fields; |
| 295 | + if (m_mesh) |
| 296 | + Py_XDECREF((PyObject *)m_mesh); |
279 | 297 | } |
280 | 298 |
|
281 | | -ArrayIter& Array::iterator() |
| 299 | + |
| 300 | +PyObject* Mesh::buildNumpyDescription(PointViewPtr view) const |
| 301 | +{ |
| 302 | + // Build up a numpy dtype dictionary |
| 303 | + // |
| 304 | + // {'formats': ['f8', 'f8', 'f8', 'u2', 'u1', 'u1', 'u1', 'u1', 'u1', |
| 305 | + // 'f4', 'u1', 'u2', 'f8', 'u2', 'u2', 'u2'], |
| 306 | + // 'names': ['X', 'Y', 'Z', 'Intensity', 'ReturnNumber', |
| 307 | + // 'NumberOfReturns', 'ScanDirectionFlag', 'EdgeOfFlightLine', |
| 308 | + // 'Classification', 'ScanAngleRank', 'UserData', |
| 309 | + // 'PointSourceId', 'GpsTime', 'Red', 'Green', 'Blue']} |
| 310 | + // |
| 311 | + |
| 312 | + Dimension::IdList dims = view->dims(); |
| 313 | + |
| 314 | + PyObject* dict = PyDict_New(); |
| 315 | + PyObject* formats = PyList_New(3); |
| 316 | + PyObject* titles = PyList_New(3); |
| 317 | + |
| 318 | + PyList_SetItem(titles, 0, PyUnicode_FromString("A")); |
| 319 | + PyList_SetItem(formats, 0, PyUnicode_FromString("u4")); |
| 320 | + PyList_SetItem(titles, 1, PyUnicode_FromString("B")); |
| 321 | + PyList_SetItem(formats, 1, PyUnicode_FromString("u4")); |
| 322 | + PyList_SetItem(titles, 2, PyUnicode_FromString("C")); |
| 323 | + PyList_SetItem(formats, 2, PyUnicode_FromString("u4")); |
| 324 | + |
| 325 | + |
| 326 | + PyDict_SetItemString(dict, "names", titles); |
| 327 | + PyDict_SetItemString(dict, "formats", formats); |
| 328 | + |
| 329 | + return dict; |
| 330 | +} |
| 331 | + |
| 332 | +ArrayIter& Mesh::iterator() |
282 | 333 | { |
283 | | - ArrayIter *it = new ArrayIter(*this); |
| 334 | + ArrayIter *it = new ArrayIter(m_mesh); |
284 | 335 | m_iterators.push_back(std::unique_ptr<ArrayIter>(it)); |
285 | 336 | return *it; |
286 | 337 | } |
287 | 338 |
|
288 | | -ArrayIter::ArrayIter(Array& array) |
| 339 | + |
| 340 | +ArrayIter::ArrayIter(PyArrayObject* np_array) |
289 | 341 | { |
290 | | - m_iter = NpyIter_New(array.getPythonArray(), |
| 342 | + m_iter = NpyIter_New(np_array, |
291 | 343 | NPY_ITER_EXTERNAL_LOOP | NPY_ITER_READONLY | NPY_ITER_REFS_OK, |
292 | 344 | NPY_KEEPORDER, NPY_NO_CASTING, NULL); |
293 | 345 | if (!m_iter) |
@@ -324,16 +376,6 @@ ArrayIter& ArrayIter::operator++() |
324 | 376 | return *this; |
325 | 377 | } |
326 | 378 |
|
327 | | -ArrayIter::operator bool () const |
328 | | -{ |
329 | | - return !m_done; |
330 | | -} |
331 | | - |
332 | | -char * ArrayIter::operator * () const |
333 | | -{ |
334 | | - return *m_data; |
335 | | -} |
336 | | - |
337 | 379 | } // namespace python |
338 | 380 | } // namespace pdal |
339 | 381 |
|
0 commit comments