/* A* ------------------------------------------------------------------- B* This file contains source code for the PyMOL computer program C* Copyright (c) Schrodinger, LLC. D* ------------------------------------------------------------------- E* It is unlawful to modify or remove this copyright notice. F* ------------------------------------------------------------------- G* Please see the accompanying LICENSE file for further information. H* ------------------------------------------------------------------- I* Additional authors of this source file include: -* -* -* Z* ------------------------------------------------------------------- */ #ifndef _H_Field #define _H_Field #include"os_python.h" #include"PyMOLGlobals.h" #include enum cField_t { cFieldFloat = 0, cFieldInt = 1, cFieldOther = 2, }; /** * Multi-dimensional data array with runtime typing. */ struct CField { cField_t type; std::vector data; std::vector dim; std::vector stride; unsigned int base_size; CField() = default; CField( PyMOLGlobals* G, const int* const dim, int n_dim, unsigned int base_size, cField_t type); int n_dim() const noexcept { return dim.size(); } unsigned int size() const noexcept { return data.size(); } /** * Copies data from another vector as stream of bytes * @param other source typed buffer */ template void set_data(const std::vector& other) { auto nbytes = other.size() * sizeof(T); data.resize(nbytes); std::copy_n( reinterpret_cast(other.data()), nbytes, data.begin()); } protected: template static cField_t _get_type() { if (std::is_same::value) { return cFieldFloat; } if (std::is_same::value) { return cFieldInt; } return cFieldOther; } public: /** * Returns heap-allocated handle to CField based on stored type * @param dim dimensions * @param n_dim number of dimensions * @return pointer to heap-allocated CField object. * Note: Lifetime of object (via heap-allocation) must be managed by owner. */ template static CField* make(PyMOLGlobals* G, const int* const dim, int n_dim) { return new CField(G, dim, n_dim, sizeof(T), _get_type()); } private: size_t _data_offset(size_t a, size_t b, size_t c) const { return a * stride[0] + b * stride[1] + c * stride[2]; } size_t _data_offset(size_t a, size_t b, size_t c, size_t d) const { return a * stride[0] + b * stride[1] + c * stride[2] + d * stride[3]; } public: //! Get a pointer to the value at `pos` template T* ptr(SizeTs... pos) { assert(sizeof...(pos) <= n_dim()); return reinterpret_cast(data.data() + _data_offset(pos...)); } template T const* ptr(SizeTs... pos) const { return const_cast(this)->ptr(pos...); } //! Get the value at `pos` template T& get(SizeTs... pos) { assert(sizeof...(pos) == n_dim()); assert(sizeof(T) == base_size); return *ptr(pos...); } template T const& get(SizeTs... pos) const { return const_cast(this)->get(pos...); } }; /** * Multi-dimensional data array with compile-time typing. */ template struct CFieldTyped : CField { CFieldTyped(const int* const dim, int n_dim) : CField(nullptr, dim, n_dim, sizeof(T), _get_type()) { } template T* ptr(SizeTs... pos) { return CField::ptr(pos...); } template T const* ptr(SizeTs... pos) const { return CField::ptr(pos...); } template T& get(SizeTs... pos) { return CField::get(pos...); } template T const& get(SizeTs... pos) const { return CField::get(pos...); } }; /* accessors for getting data from a field */ #define Ffloat3p(f, a, b, c) ((f)->ptr(a, b, c)) #define Ffloat3(f, a, b, c) ((f)->get(a, b, c)) #define Ffloat4p(f, a, b, c, d) ((f)->ptr(a, b, c, d)) #define Ffloat4(f, a, b, c, d) ((f)->get(a, b, c, d)) #define F3 Ffloat3 #define F3Ptr Ffloat3p #define F4 Ffloat4 #define F4Ptr Ffloat4p void FieldZero(CField * I); float FieldInterpolatef(CField * I, int a, int b, int c, float x, float y, float z); void FieldInterpolate3f(CField * I, int *locus, float *fract, float *result); PyObject *FieldAsNumPyArray(CField * I, short copy); PyObject *FieldAsPyList(PyMOLGlobals * G, CField * I); CField *FieldNewFromPyList(PyMOLGlobals * G, PyObject * list); CField *FieldNewFromPyList_From_List(PyMOLGlobals * G, PyObject * list, int); int FieldSmooth3f(CField * I); #endif