Update python wrapper

This commit is contained in:
John Zhao 2018-05-20 09:25:30 +08:00
parent d414182721
commit 13939734a7
12 changed files with 1702 additions and 33 deletions

5
.gitignore vendored
View File

@ -29,3 +29,8 @@ _output/
/mynteye/ /mynteye/
/mynteye.bag /mynteye.bag
/dataset*/ /dataset*/
# wrappers
/wrappers/python/third_party/numpy-opencv-converter/
/wrappers/python/third_party/pyboostcvconverter/

View File

@ -163,7 +163,6 @@ ifneq ($(MAKE),)
endif endif
CMAKE_OPTIONS := CMAKE_OPTIONS :=
CMAKE_OPTIONS += -DCMAKE_INSTALL_PREFIX=$(shell pwd)/_install
# CMAKE_OPTIONS += -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON # CMAKE_OPTIONS += -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
CMAKE_OPTIONS_AFTER := CMAKE_OPTIONS_AFTER :=

View File

@ -13,6 +13,9 @@
# limitations under the License. # limitations under the License.
include CommonDefs.mk include CommonDefs.mk
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
MKFILE_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))
.DEFAULT_GOAL := help .DEFAULT_GOAL := help
help: help:
@ -77,7 +80,7 @@ init: submodules
build: third_party build: third_party
@$(call echo,Make $@) @$(call echo,Make $@)
@$(call cmake_build,./_build) @$(call cmake_build,./_build,..,-DCMAKE_INSTALL_PREFIX=$(MKFILE_DIR)/_install)
.PHONY: build .PHONY: build
@ -161,11 +164,30 @@ cleanros:
# python # python
PBCVT_DIR := wrappers/python/third_party/pyboostcvconverter
$(PBCVT_DIR):
@git clone https://github.com/Algomorph/pyboostcvconverter.git $@
pbcvt: $(PBCVT_DIR)
@$(call cmake_build,$(PBCVT_DIR)/_build,.., \
-DCMAKE_INSTALL_PREFIX=$(MKFILE_DIR)/wrappers/python/_install \
-DPYTHON_DESIRED_VERSION=2.X)
@cd $(PBCVT_DIR)/_build; make install
.PHONY: pbcvt
NPCV_DIR := wrappers/python/third_party/numpy-opencv-converter
$(NPCV_DIR):
@git clone https://github.com/GarrickLin/numpy-opencv-converter.git $@
py: python py: python
python: install python: install $(NPCV_DIR)
@$(call echo,Make $@) @$(call echo,Make $@)
@$(call cmake_build,./wrappers/python/_build) @$(call cmake_build,./wrappers/python/_build)
@cd ./wrappers/python/_build; make install
.PHONY: py python .PHONY: py python
@ -173,6 +195,8 @@ cleanpy:
@$(call echo,Make $@) @$(call echo,Make $@)
@$(call rm,./wrappers/python/_build/) @$(call rm,./wrappers/python/_build/)
@$(call rm,./wrappers/python/_output/) @$(call rm,./wrappers/python/_output/)
@$(call rm,./wrappers/python/_install/)
@$(call rm,./$(PBCVT_DIR)/_build/)
.PHONY: cleanpy .PHONY: cleanpy
@ -206,6 +230,8 @@ cleanall: clean
@$(call rm,./test/gtest/_build/) @$(call rm,./test/gtest/_build/)
@$(call rm,./third_party/glog/_build/) @$(call rm,./third_party/glog/_build/)
@$(FIND) . -type f -name ".DS_Store" -print0 | xargs -0 rm -f @$(FIND) . -type f -name ".DS_Store" -print0 | xargs -0 rm -f
@$(call rm,./$(PBCVT_DIR)/)
@$(call rm,./$(NPCV_DIR)/)
.PHONY: clean cleanlog cleanall .PHONY: clean cleanlog cleanall
@ -213,6 +239,8 @@ cleanall: clean
host: host:
@$(call echo,Make $@) @$(call echo,Make $@)
@echo MKFILE_PATH: $(MKFILE_PATH)
@echo MKFILE_DIR: $(MKFILE_DIR)
@echo HOST_OS: $(HOST_OS) @echo HOST_OS: $(HOST_OS)
@echo HOST_ARCH: $(HOST_ARCH) @echo HOST_ARCH: $(HOST_ARCH)
@echo HOST_NAME: $(HOST_NAME) @echo HOST_NAME: $(HOST_NAME)

View File

@ -41,6 +41,14 @@ struct MYNTEYE_API StreamData {
std::shared_ptr<ImgData> img; std::shared_ptr<ImgData> img;
/** Frame. */ /** Frame. */
cv::Mat frame; cv::Mat frame;
bool operator==(const StreamData &other) const {
if (img && other.img) {
return img->frame_id == other.img->frame_id &&
img->timestamp == other.img->timestamp;
}
return false;
}
}; };
/** /**
@ -50,6 +58,14 @@ struct MYNTEYE_API StreamData {
struct MYNTEYE_API MotionData { struct MYNTEYE_API MotionData {
/** ImuData. */ /** ImuData. */
std::shared_ptr<ImuData> imu; std::shared_ptr<ImuData> imu;
bool operator==(const MotionData &other) const {
if (imu && other.imu) {
return imu->frame_id == other.imu->frame_id &&
imu->timestamp == other.imu->timestamp;
}
return false;
}
}; };
} // namespace api } // namespace api
@ -65,7 +81,7 @@ class MYNTEYE_API API {
using motion_callback_t = std::function<void(const api::MotionData &data)>; using motion_callback_t = std::function<void(const api::MotionData &data)>;
explicit API(std::shared_ptr<Device> device); explicit API(std::shared_ptr<Device> device);
/*virtual*/ ~API(); virtual ~API();
/** /**
* Create the API instance. * Create the API instance.

View File

@ -87,7 +87,7 @@ message(STATUS "Found mynteye: ${mynteye_VERSION}")
if(CMAKE_VERSION VERSION_LESS "3.10" OR CMAKE_VERSION VERSION_EQUAL "3.10") if(CMAKE_VERSION VERSION_LESS "3.10" OR CMAKE_VERSION VERSION_EQUAL "3.10")
find_package(Boost ${BOOST_FIND_VERSION} REQUIRED find_package(Boost ${BOOST_FIND_VERSION} REQUIRED
COMPONENTS python${PYTHON_BOOST_CODE} COMPONENTS python${PYTHON_BOOST_CODE} # numpy${PYTHON_BOOST_CODE}
) )
else() else()
find_package(Boost ${BOOST_FIND_VERSION} REQUIRED COMPONENTS find_package(Boost ${BOOST_FIND_VERSION} REQUIRED COMPONENTS
@ -103,6 +103,8 @@ message(STATUS "Found PythonLibs: ${PYTHONLIBS_VERSION_STRING}")
message(STATUS " PYTHON_INCLUDE_DIRS: ${PYTHON_INCLUDE_DIRS}") message(STATUS " PYTHON_INCLUDE_DIRS: ${PYTHON_INCLUDE_DIRS}")
message(STATUS " PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}") message(STATUS " PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}")
include(${PRO_DIR}/cmake/DetectOpenCV.cmake)
#LIST(APPEND CMAKE_MODULE_PATH ${PRO_DIR}/cmake) #LIST(APPEND CMAKE_MODULE_PATH ${PRO_DIR}/cmake)
# targets # targets
@ -115,6 +117,14 @@ set_outdir(
"${OUT_DIR}/bin" "${OUT_DIR}/bin"
) )
set(DEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}/_install")
message(STATUS "DEST_DIR: ${DEST_DIR}")
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${DEST_DIR}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if(OS_WIN) if(OS_WIN)
add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
endif() endif()
@ -145,4 +155,42 @@ endmacro()
## mynteye_py ## mynteye_py
add_library_py(mynteye_py SRCS src/mynteye_py.cc LINK_LIBS mynteye) include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/third_party/array
)
#set(PBCVT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/pyboostcvconverter")
#
#include_directories(
# ${PBCVT_DIR}/include
#)
#
#set(PBCVT_SRCS
# ${PBCVT_DIR}/src/pyboost_cv2_converter.cpp
# ${PBCVT_DIR}/src/pyboost_cv3_converter.cpp
# ${PBCVT_DIR}/include/pyboostcvconverter/pyboostcvconverter.hpp
#)
set(NPCV_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/numpy-opencv-converter")
include_directories(
${NPCV_DIR}
)
set(NPCV_SRCS
${NPCV_DIR}/np_opencv_converter.cpp
${NPCV_DIR}/utils/conversion.cpp
)
add_library_py(mynteye_py
SRCS src/mynteye_py.cc ${NPCV_SRCS}
LINK_LIBS mynteye ${OpenCV_LIBS}
)
# insall
install(TARGETS mynteye_py
ARCHIVE DESTINATION "${DEST_DIR}/lib"
LIBRARY DESTINATION "${DEST_DIR}/lib"
RUNTIME DESTINATION "${DEST_DIR}/bin"
)

View File

@ -22,15 +22,177 @@ import os
import sys import sys
PY_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PY_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.join(PY_DIR, '_output/lib')) LIB_DIR = os.path.join(PY_DIR, '_install/lib')
for root, dirs, files in os.walk(LIB_DIR):
if files:
sys.path.append(root)
import mynteye_py # pylint: disable=import-error,wrong-import-position # pylint: disable=import-error,wrong-import-position
# glog_init = mynteye_py.glog_init.create(sys.argv) import mynteye_py as mynteye
# glog_init = mynteye.glog_init.create(sys.argv)
def main(): def main():
# api = mynteye_py.api.create() # should glog_init # api = mynteye.API.create() # should glog_init
api = mynteye_py.api.create(sys.argv) # pylint: disable=unused-variable api = mynteye.API.create(sys.argv)
if not api:
sys.exit(1)
# model
print('model: {}'.format(api.model))
# supports
supports_types = (
mynteye.Stream,
mynteye.Capabilities,
mynteye.Option,
mynteye.AddOns)
for x in supports_types:
print('\nsupports({})'.format(x.__name__))
for k, v in x.names.iteritems():
print(' supports({}): {}'.format(k, api.supports(v)))
# get_stream_requests
for k, v in mynteye.Capabilities.names.iteritems():
if v != mynteye.STEREO:
continue
if not api.supports(v):
continue
print('\nget_stream_requests({})'.format(k))
for req in api.get_stream_requests(v):
print(' {}'.format(req))
# config_stream_request
# print('\nconfig_stream_request({},?)'.format(mynteye.STEREO))
# api.config_stream_request(mynteye.STEREO, req)
# print(' {}'.format(req))
# get_info
print()
for k, v in mynteye.Info.names.iteritems():
print('get_info({}): {}'.format(k, api.get_info(v)))
# get_intrinsics
print('\nget_intrinsics(LEFT)\n{}'.format(api.get_intrinsics(mynteye.LEFT)))
print('\nget_intrinsics(RIGHT)\n{}'.format(api.get_intrinsics(mynteye.RIGHT)))
# get_extrinsics
print('\nget_extrinsics(LEFT, RIGHT)\n{}'.format(
api.get_extrinsics(mynteye.LEFT, mynteye.RIGHT)))
# get_motion_intrinsics
print('\nget_motion_intrinsics()\n{}'.format(api.get_motion_intrinsics()))
# get_motion_extrinsics
print('\nget_motion_extrinsics(LEFT)\n{}'.format(
api.get_motion_extrinsics(mynteye.LEFT)))
# api.log_option_infos()
# get_option_info, get_option_value
print()
for k, v in mynteye.Option.names.iteritems():
if v == mynteye.ZERO_DRIFT_CALIBRATION or v == mynteye.ERASE_CHIP:
continue
if not api.supports(v):
continue
print('get_option_info({}): {}, cur: {}'.format(
k, api.get_option_info(v), api.get_option_value(v)))
# set_option_value
def set_rate(frame_rate=25, imu_frequency=500): # pylint: disable=unused-variable
# FRAME_RATE values: 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60
api.set_option_value(mynteye.FRAME_RATE, frame_rate)
# IMU_FREQUENCY values: 100, 200, 250, 333, 500
api.set_option_value(mynteye.IMU_FREQUENCY, imu_frequency)
def set_ir(intensity=80): # pylint: disable=unused-variable
# set infrared intensity value: range [0,48], default 160
api.set_option_value(mynteye.IR_CONTROL, intensity)
def set_auto_exposure( # pylint: disable=unused-variable
max_gain=48, # pylint: disable=bad-continuation
max_exposure_time=240, # pylint: disable=bad-continuation
desired_brightness=192): # pylint: disable=bad-continuation
# auto-exposure: 0
api.set_option_value(mynteye.EXPOSURE_MODE, 0)
# max_gain: range [0,48], default 48
api.set_option_value(mynteye.MAX_GAIN, max_gain)
# max_exposure_time: range [0,240], default 240
api.set_option_value(mynteye.MAX_EXPOSURE_TIME, max_exposure_time)
# desired_brightness: range [0,255], default 192
api.set_option_value(mynteye.DESIRED_BRIGHTNESS, desired_brightness)
def set_manual_exposure(gain=24, brightness=120, contrast=127): # pylint: disable=unused-variable
# manual-exposure: 1
api.set_option_value(mynteye.EXPOSURE_MODE, 1)
# gain: range [0,48], default 24
api.set_option_value(mynteye.GAIN, gain)
# brightness/exposure_time: range [0,240], default 120
api.set_option_value(mynteye.BRIGHTNESS, brightness)
# contrast/black_level_calibration: range [0,255], default 127
api.set_option_value(mynteye.CONTRAST, contrast)
# set_rate(25, 500);
# set_ir(80);
# set_auto_exposure(48, 240, 192);
# set_manual_exposure(24, 120, 127);
# run_option_action
# api.run_option_action(mynteye.ZERO_DRIFT_CALIBRATION)
##############################################################################
# get stream and motion datas
import cv2
import numpy as np
from util.cv_painter import Gravity, draw_text
# api.enable_stream_data(mynteye.DISPARITY_NORMALIZED);
api.enable_motion_datas()
api.start(mynteye.ALL)
# cv2.namedWindow('frame')
# cv2.namedWindow('disparity')
fps = 0.
while True:
t = cv2.getTickCount()
api.wait_for_streams()
left_data = api.get_stream_data(mynteye.LEFT)
right_data = api.get_stream_data(mynteye.RIGHT)
motion_datas = api.get_motion_datas()
img = np.hstack((left_data.frame, right_data.frame))
draw_text(img, '{1}x{0}'.format(*img.shape), Gravity.TOP_LEFT)
draw_text(img, '{:.1f}'.format(fps), Gravity.TOP_RIGHT)
if motion_datas:
imu = motion_datas[0].imu
draw_text(img,
'accel: {:+8f}, {:+8f}, {:+8f}'.format(*imu.accel),
Gravity.BOTTOM_LEFT)
draw_text(img,
'gyro: {:+8f}, {:+8f}, {:+8f}'.format(*imu.gyro),
Gravity.BOTTOM_RIGHT)
cv2.imshow('frame', img)
# disp_data = api.get_stream_data(mynteye.DISPARITY_NORMALIZED);
# if disp_data.frame is not None:
# cv2.imshow('disparity', disp_data.frame);
t = cv2.getTickCount() - t
fps = cv2.getTickFrequency() / t
key = cv2.waitKey(10) & 0xFF
if key == 27 or key == ord('q'): # esc, q
break
api.stop(mynteye.ALL)
cv2.destroyAllWindows()
if __name__ == '__main__': if __name__ == '__main__':

View File

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2018 Slightech Co., Ltd. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# pylint: disable=missing-docstring
import cv2
FONT_FACE = cv2.FONT_HERSHEY_SIMPLEX
FONT_SCALE = 1
FONT_COLOR = (255, 255, 255)
THICKNESS = 1
class Gravity(object): # pylint: disable=no-init
TOP_LEFT = 1
TOP_RIGHT = 2
BOTTOM_LEFT = 3
BOTTOM_RIGHT = 4
def draw_text(img, text, gravity, margin=10, offset_x=0, offset_y=0):
h, w = img.shape[:2] # pylint: disable=invalid-name
# getTextSize, result: ((width, height), baseline)
x, y = cv2.getTextSize(text, FONT_FACE, FONT_SCALE, THICKNESS)[0]
org = {
Gravity.TOP_LEFT: (margin, margin + y),
Gravity.TOP_RIGHT: (w - margin - x, margin + y),
Gravity.BOTTOM_LEFT: (margin, h - margin),
Gravity.BOTTOM_RIGHT: (w - margin - x, h - margin),
}.get(gravity, (margin, margin + y))
org = (org[0] + offset_x, org[1] + offset_y)
# putText(img, text, org, fontFace, fontScale, color, thickness, lineType)
cv2.putText(img, text, org, FONT_FACE, FONT_SCALE,
FONT_COLOR, THICKNESS, cv2.LINE_AA)

View File

@ -11,34 +11,52 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <boost/python.hpp>
// #include <boost/python.hpp>
#include <boost/python/class.hpp>
#include <boost/python/enum.hpp>
#include <boost/python/list.hpp>
#include <boost/python/module.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/stl_iterator.hpp> #include <boost/python/stl_iterator.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <opencv2/core/core.hpp>
#include <vector> #include <vector>
#include "mynteye/api.h" #include "mynteye/api.h"
#include "mynteye/glog_init.h" #include "mynteye/glog_init.h"
#include "mynteye/utils.h"
#include "array_indexing_suite.hpp"
#include "array_ref.hpp"
// #define PY_ARRAY_UNIQUE_SYMBOL pbcvt_ARRAY_API
// #include "pyboostcvconverter/pyboostcvconverter.hpp"
#include "np_opencv_converter.hpp"
#define ENUM_EXPORT_VALUES
namespace bp = boost::python;
namespace { namespace {
template <typename T> template <typename T>
inline void std_vector_assign( inline void std_vector_assign(
std::vector<T> &l, const boost::python::object &o) { // NOLINT std::vector<T> &l, const bp::object &o) { // NOLINT
l.assign( l.assign(bp::stl_input_iterator<T>(o), bp::stl_input_iterator<T>());
boost::python::stl_input_iterator<T>(o),
boost::python::stl_input_iterator<T>());
} }
template <typename T> template <typename T>
inline std::vector<T> py_list_to_std_vector(const boost::python::object &o) { inline std::vector<T> py_list_to_std_vector(const bp::object &o) {
return std::vector<T>( return std::vector<T>(
boost::python::stl_input_iterator<T>(o), bp::stl_input_iterator<T>(o), bp::stl_input_iterator<T>());
boost::python::stl_input_iterator<T>());
} }
template <typename T> template <typename T>
inline boost::python::list std_vector_to_py_list(const std::vector<T> &v) { inline bp::list std_vector_to_py_list(const std::vector<T> &v) {
boost::python::list l; bp::list l;
for (auto &&val : v) { for (auto &&val : v) {
l.append(val); l.append(val);
} }
@ -64,29 +82,100 @@ void del_cstrings(char **cstrings, std::size_t n) {
} // namespace } // namespace
using namespace boost::python; // NOLINT MYNTEYE_BEGIN_NAMESPACE
MYNTEYE_USE_NAMESPACE namespace python {
// api wrapper
struct MYNTEYE_API StreamData {
/** ImgData. */
ImgData img;
/** Frame. */
PyObject *frame;
bool operator==(const StreamData &other) const {
return img.frame_id == other.img.frame_id &&
img.timestamp == other.img.timestamp;
}
};
struct MYNTEYE_API MotionData {
/** ImuData. */
ImuData imu;
bool operator==(const MotionData &other) const {
return imu.frame_id == other.imu.frame_id &&
imu.timestamp == other.imu.timestamp;
}
};
class MYNTEYE_API APIWrap : public API {
public:
explicit APIWrap(std::shared_ptr<Device> device) : API(device) {}
~APIWrap() {}
static std::shared_ptr<APIWrap> Create() {
auto &&device = device::select();
if (!device)
return nullptr;
return std::make_shared<APIWrap>(device);
}
static std::shared_ptr<APIWrap> Create(int argc, char *argv[]) {
static glog_init _(argc, argv);
auto &&device = device::select();
if (!device)
return nullptr;
return std::make_shared<APIWrap>(device);
}
python::StreamData GetStreamData(const Stream &stream) {
auto &&data = API::GetStreamData(stream);
// return {*data.img, pbcvt::fromMatToNDArray(data.frame)};
return {*data.img,
fs::python::Mat_to_PyObject<cv::Mat>::convert(data.frame)};
}
std::vector<python::StreamData> GetStreamDatas(const Stream &stream) {
std::vector<python::StreamData> datas;
for (auto &&data : API::GetStreamDatas(stream)) {
// datas.push_back({*data.img, pbcvt::fromMatToNDArray(data.frame)});
datas.push_back(
{*data.img,
fs::python::Mat_to_PyObject<cv::Mat>::convert(data.frame)});
}
return datas;
}
std::vector<python::MotionData> GetMotionDatas() {
std::vector<python::MotionData> datas;
for (auto &&data : API::GetMotionDatas()) {
datas.push_back({*data.imu});
}
return datas;
}
};
// api create static methods // api create static methods
std::shared_ptr<API> (*api_create_1)() = &API::Create; std::shared_ptr<APIWrap> (*api_create_1)() = &APIWrap::Create;
std::shared_ptr<API> api_create_2(list argv) { std::shared_ptr<APIWrap> api_create_2(bp::list argv) {
auto &&args = py_list_to_std_vector<std::string>(argv); auto &&args = py_list_to_std_vector<std::string>(argv);
auto &&n = args.size(); auto &&n = args.size();
if (n == 0) { if (n == 0) {
return API::Create(); return APIWrap::Create();
} }
char **cstrings = new_cstrings(args, n); char **cstrings = new_cstrings(args, n);
auto &&api = API::Create(args.size(), cstrings); auto &&api = APIWrap::Create(args.size(), cstrings);
del_cstrings(cstrings, n); del_cstrings(cstrings, n);
return api; return api;
} }
// glog_init create static methods // glog_init create static methods
std::shared_ptr<glog_init> glog_init_create(list argv) { std::shared_ptr<glog_init> glog_init_create(bp::list argv) {
auto &&args = py_list_to_std_vector<std::string>(argv); auto &&args = py_list_to_std_vector<std::string>(argv);
auto &&n = args.size(); auto &&n = args.size();
assert(n > 0); assert(n > 0);
@ -99,16 +188,278 @@ std::shared_ptr<glog_init> glog_init_create(list argv) {
// BOOST_PYTHON_MODULE // BOOST_PYTHON_MODULE
BOOST_PYTHON_MODULE(mynteye_py) { BOOST_PYTHON_MODULE(mynteye_py) {
class_<API, boost::noncopyable>("api", no_init) /*
Py_Initialize();
import_array();
bp::to_python_converter<cv::Mat, pbcvt::matToNDArrayBoostConverter>();
pbcvt::matFromNDArrayBoostConverter();
*/
fs::python::init_and_export_converters();
py::scope scope = py::scope();
bp::class_<array_ref<double>>("DoubleArray")
.def(array_indexing_suite<array_ref<double>>());
bp::class_<array_ref<array_ref<double>>>("Double2DArray")
.def(array_indexing_suite<array_ref<array_ref<double>>>{});
// types.h - enums
bp::enum_<Model>("Model")
.value("STANDARD", Model::STANDARD)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
bp::enum_<Stream>("Stream")
.value("LEFT", Stream::LEFT)
.value("RIGHT", Stream::RIGHT)
.value("LEFT_RECTIFIED", Stream::LEFT_RECTIFIED)
.value("RIGHT_RECTIFIED", Stream::RIGHT_RECTIFIED)
.value("DISPARITY", Stream::DISPARITY)
.value("DISPARITY_NORMALIZED", Stream::DISPARITY_NORMALIZED)
.value("DEPTH", Stream::DEPTH)
.value("POINTS", Stream::POINTS)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
bp::enum_<Capabilities>("Capabilities")
.value("STEREO", Capabilities::STEREO)
.value("COLOR", Capabilities::COLOR)
.value("DEPTH", Capabilities::DEPTH)
.value("POINTS", Capabilities::POINTS)
.value("FISHEYE", Capabilities::FISHEYE)
.value("INFRARED", Capabilities::INFRARED)
.value("INFRARED2", Capabilities::INFRARED2)
.value("IMU", Capabilities::IMU)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
bp::enum_<Info>("Info")
.value("DEVICE_NAME", Info::DEVICE_NAME)
.value("SERIAL_NUMBER", Info::SERIAL_NUMBER)
.value("FIRMWARE_VERSION", Info::FIRMWARE_VERSION)
.value("HARDWARE_VERSION", Info::HARDWARE_VERSION)
.value("SPEC_VERSION", Info::SPEC_VERSION)
.value("LENS_TYPE", Info::LENS_TYPE)
.value("IMU_TYPE", Info::IMU_TYPE)
.value("NOMINAL_BASELINE", Info::NOMINAL_BASELINE)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
bp::enum_<Option>("Option")
.value("GAIN", Option::GAIN)
.value("BRIGHTNESS", Option::BRIGHTNESS)
.value("CONTRAST", Option::CONTRAST)
.value("FRAME_RATE", Option::FRAME_RATE)
.value("IMU_FREQUENCY", Option::IMU_FREQUENCY)
.value("EXPOSURE_MODE", Option::EXPOSURE_MODE)
.value("MAX_GAIN", Option::MAX_GAIN)
.value("MAX_EXPOSURE_TIME", Option::MAX_EXPOSURE_TIME)
.value("DESIRED_BRIGHTNESS", Option::DESIRED_BRIGHTNESS)
.value("IR_CONTROL", Option::IR_CONTROL)
.value("HDR_MODE", Option::HDR_MODE)
.value("ZERO_DRIFT_CALIBRATION", Option::ZERO_DRIFT_CALIBRATION)
.value("ERASE_CHIP", Option::ERASE_CHIP)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
bp::enum_<Source>("Source")
.value("VIDEO_STREAMING", Source::VIDEO_STREAMING)
.value("MOTION_TRACKING", Source::MOTION_TRACKING)
.value("ALL", Source::ALL)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
bp::enum_<AddOns>("AddOns")
.value("INFRARED", AddOns::INFRARED)
.value("INFRARED2", AddOns::INFRARED2)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
bp::enum_<Format>("Format")
.value("GREY", Format::GREY)
.value("YUYV", Format::YUYV)
#ifdef ENUM_EXPORT_VALUES
.export_values()
#endif
; // NOLINT
// types.h - types
bp::class_<StreamRequest>("StreamRequest")
.def_readonly("width", &StreamRequest::width)
.def_readonly("height", &StreamRequest::height)
.def_readonly("format", &StreamRequest::format)
.def_readonly("fps", &StreamRequest::fps)
.def(bp::self == bp::self)
.def(bp::self != bp::self)
.def(bp::self_ns::str(bp::self));
bp::class_<std::vector<StreamRequest>>("StreamRequestVec")
.def(bp::vector_indexing_suite<std::vector<StreamRequest>>());
bp::class_<Intrinsics>("Intrinsics")
.def_readonly("width", &Intrinsics::width)
.def_readonly("height", &Intrinsics::height)
.def_readonly("fx", &Intrinsics::fx)
.def_readonly("fy", &Intrinsics::fy)
.def_readonly("cx", &Intrinsics::cx)
.def_readonly("cy", &Intrinsics::cy)
.def_readonly("model", &Intrinsics::model)
.add_property(
"coeffs", +[](Intrinsics *o) { return array_ref<double>{o->coeffs}; })
.def(bp::self_ns::str(bp::self));
bp::class_<ImuIntrinsics>("ImuIntrinsics")
.add_property(
"scale",
+[](ImuIntrinsics *o) {
return array_ref<array_ref<double>>{o->scale};
})
.add_property(
"drift",
+[](ImuIntrinsics *o) { return array_ref<double>{o->drift}; })
.add_property(
"noise",
+[](ImuIntrinsics *o) { return array_ref<double>{o->noise}; })
.add_property(
"bias", +[](ImuIntrinsics *o) { return array_ref<double>{o->bias}; })
.def(bp::self_ns::str(bp::self));
bp::class_<MotionIntrinsics>("MotionIntrinsics")
.def_readonly("accel", &MotionIntrinsics::accel)
.def_readonly("gyro", &MotionIntrinsics::gyro)
.def(bp::self_ns::str(bp::self));
bp::class_<Extrinsics>("Extrinsics")
.add_property(
"rotation",
+[](Extrinsics *o) {
return array_ref<array_ref<double>>{o->rotation};
})
.add_property(
"translation",
+[](Extrinsics *o) { return array_ref<double>{o->translation}; })
.def("inverse", &Extrinsics::Inverse)
.def(bp::self_ns::str(bp::self));
bp::class_<ImgData>("ImgData")
.def_readonly("frame_id", &ImgData::frame_id)
.def_readonly("timestamp", &ImgData::timestamp)
.def_readonly("exposure_time", &ImgData::exposure_time);
// bp::register_ptr_to_python<std::shared_ptr<ImgData>>();
bp::class_<ImuData>("ImuData")
.def_readonly("frame_id", &ImuData::frame_id)
.def_readonly("timestamp", &ImuData::timestamp)
.add_property(
"accel", +[](ImuData *o) { return array_ref<double>{o->accel}; })
.add_property(
"gyro", +[](ImuData *o) { return array_ref<double>{o->gyro}; })
.def_readonly("temperature", &ImuData::temperature);
// bp::register_ptr_to_python<std::shared_ptr<ImuData>>();
bp::class_<OptionInfo>("OptionInfo")
.def_readonly("min", &OptionInfo::min)
.def_readonly("max", &OptionInfo::max)
.def_readonly("def", &OptionInfo::def)
.def(bp::self_ns::str(bp::self));
// api.h - API
bp::class_<python::StreamData>("StreamData")
.def_readonly("img", &python::StreamData::img)
.def_readonly("frame", &python::StreamData::frame);
bp::class_<std::vector<python::StreamData>>("StreamDataVec")
.def(bp::vector_indexing_suite<std::vector<python::StreamData>>());
bp::class_<python::MotionData>("MotionData")
.def_readonly("imu", &python::MotionData::imu);
bp::class_<std::vector<python::MotionData>>("MotionDataVec")
.def(bp::vector_indexing_suite<std::vector<python::MotionData>>());
bool (APIWrap::*supports_stream)(const Stream &) const = &APIWrap::Supports;
bool (APIWrap::*supports_capabilities)(const Capabilities &) const =
&APIWrap::Supports;
bool (APIWrap::*supports_option)(const Option &) const = &APIWrap::Supports;
bool (APIWrap::*supports_addons)(const AddOns &) const = &APIWrap::Supports;
python::StreamData (APIWrap::*get_stream_data)(const Stream &) =
&APIWrap::GetStreamData;
std::vector<python::StreamData> (APIWrap::*get_stream_datas)(const Stream &) =
&APIWrap::GetStreamDatas;
std::vector<python::MotionData> (APIWrap::*get_motion_datas)() =
&APIWrap::GetMotionDatas;
bp::class_<APIWrap, boost::noncopyable>("API", bp::no_init)
.def("create", api_create_1) .def("create", api_create_1)
.def("create", &api_create_2) .def("create", &api_create_2)
.staticmethod("create"); .staticmethod("create")
.add_property("model", &APIWrap::GetModel)
.def("supports", supports_stream)
.def("supports", supports_capabilities)
.def("supports", supports_option)
.def("supports", supports_addons)
.def(
"get_stream_requests", &APIWrap::GetStreamRequests,
bp::return_value_policy<bp::reference_existing_object>())
.def("config_stream_request", &APIWrap::ConfigStreamRequest)
.def("get_info", &APIWrap::GetInfo)
.def("get_intrinsics", &APIWrap::GetIntrinsics)
.def("get_extrinsics", &APIWrap::GetExtrinsics)
.def("get_motion_intrinsics", &APIWrap::GetMotionIntrinsics)
.def("get_motion_extrinsics", &APIWrap::GetMotionExtrinsics)
.def("log_option_infos", &APIWrap::LogOptionInfos)
.def("get_option_info", &APIWrap::GetOptionInfo)
.def("get_option_value", &APIWrap::GetOptionValue)
.def("set_option_value", &APIWrap::SetOptionValue)
.def("run_option_action", &APIWrap::RunOptionAction)
// .def("set_stream_callback", &APIWrap::SetStreamCallback)
// .def("set_motion_callback", &APIWrap::SetMotionCallback)
// .def("has_stream_callback", &APIWrap::HasStreamCallback)
// .def("has_motion_callback", &APIWrap::HasMotionCallback)
.def("start", &APIWrap::Start)
.def("stop", &APIWrap::Stop)
.def("wait_for_streams", &APIWrap::WaitForStreams)
.def("enable_stream_data", &APIWrap::EnableStreamData)
.def("disable_stream_data", &APIWrap::DisableStreamData)
.def("get_stream_data", get_stream_data)
.def("get_stream_datas", get_stream_datas)
.def(
"enable_motion_datas", &APIWrap::EnableMotionDatas,
(bp::arg("max_size") = std::numeric_limits<std::size_t>::max()))
.def("get_motion_datas", get_motion_datas)
.def("enable_plugin", &APIWrap::EnablePlugin);
register_ptr_to_python<std::shared_ptr<API>>(); bp::register_ptr_to_python<std::shared_ptr<APIWrap>>();
class_<glog_init, boost::noncopyable>("glog_init", no_init) // glog_init.h - glog_init
bp::class_<glog_init, boost::noncopyable>("glog_init", bp::no_init)
.def("create", &glog_init_create) .def("create", &glog_init_create)
.staticmethod("create"); .staticmethod("create");
register_ptr_to_python<std::shared_ptr<glog_init>>(); bp::register_ptr_to_python<std::shared_ptr<glog_init>>();
} }
} // namespace python
MYNTEYE_END_NAMESPACE

View File

@ -0,0 +1,7 @@
# `array_ref` `array_indexing_suite`
From Praetorian's answer here: http://stackoverflow.com/a/27560620
## Extra Links
* [irods_rule_engine_plugin_python](https://github.com/irods/irods_rule_engine_plugin_python)

View File

@ -0,0 +1,142 @@
// From Praetorian's answer here: http://stackoverflow.com/a/27560620
#include <boost/python.hpp>
#include <boost/python/suite/indexing/indexing_suite.hpp>
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <type_traits>
// Forward declaration
template <typename Array, bool NoProxy, typename DerivedPolicies>
class array_indexing_suite;
namespace detail {
template <typename Array, bool NoProxy>
struct final_array_derived_policies
: array_indexing_suite<Array, NoProxy,
final_array_derived_policies<Array, NoProxy>> {};
} /* namespace detail */
template <typename Array,
bool NoProxy = std::is_arithmetic<typename Array::value_type>::value,
typename DerivedPolicies =
detail::final_array_derived_policies<Array, NoProxy>>
class array_indexing_suite
: public boost::python::indexing_suite<Array, DerivedPolicies, NoProxy> {
public:
typedef typename Array::value_type data_type;
typedef typename Array::value_type key_type;
typedef typename Array::size_type index_type;
typedef typename Array::size_type size_type;
typedef typename Array::difference_type difference_type;
static data_type &get_item(Array &arr, index_type i) {
return arr[i];
}
static void set_item(Array &arr, index_type i, data_type const &v) {
arr[i] = v;
}
static void delete_item(Array & /*arr*/, index_type /*i*/) {
::PyErr_SetString(::PyExc_TypeError, "Cannot delete array item");
boost::python::throw_error_already_set();
}
static size_type size(Array &arr) {
return arr.size();
}
static bool contains(Array &arr, key_type const &key) {
return std::find(arr.cbegin(), arr.cend(), key) != arr.cend();
}
static index_type get_min_index(Array &) {
return 0;
}
static index_type get_max_index(Array &arr) {
return arr.size();
}
static bool compare_index(Array &, index_type a, index_type b) {
return a < b;
}
static index_type convert_index(Array &arr, PyObject *i_) {
boost::python::extract<long> i(i_);
if (i.check()) {
long index = i();
if (index < 0) {
index += static_cast<decltype(index)>(DerivedPolicies::size(arr));
}
if ((index >= long(arr.size())) || (index < 0)) {
::PyErr_SetString(::PyExc_IndexError, "Index out of range");
boost::python::throw_error_already_set();
}
return index;
}
::PyErr_SetString(::PyExc_TypeError, "Invalid index type");
boost::python::throw_error_already_set();
return index_type();
}
static boost::python::object get_slice(
Array &arr, index_type from, index_type to) {
if (from > to) {
return boost::python::object(Array());
}
return boost::python::object(Array(arr.begin() + from, arr.begin() + to));
}
static void set_slice(
Array &arr, index_type from, index_type to, data_type const &v) {
if (from > to) {
return;
} else if (to > arr.size()) {
::PyErr_SetString(::PyExc_IndexError, "Index out of range");
boost::python::throw_error_already_set();
} else {
std::fill(arr.begin() + from, arr.begin() + to, v);
}
}
template <typename Iter>
static void set_slice(
Array &arr, index_type from, index_type to, Iter first, Iter last) {
auto num_items = std::distance(first, last);
if ((from + num_items) > arr.size()) {
::PyErr_SetString(::PyExc_IndexError, "Index out of range");
boost::python::throw_error_already_set();
return;
}
if (from > to) {
std::copy(first, last, arr.begin() + from);
} else {
if (static_cast<decltype(num_items)>(to - from) != num_items) {
::PyErr_SetString(::PyExc_TypeError, "Array length is immutable");
boost::python::throw_error_already_set();
return;
}
std::copy(first, last, arr.begin() + from);
}
}
static void delete_slice(
Array & /*arr*/, index_type /*from*/, index_type /*to*/) {
::PyErr_SetString(::PyExc_TypeError, "Cannot delete array item(s)");
boost::python::throw_error_already_set();
}
};

View File

@ -0,0 +1,859 @@
// From Praetorian's answer here: http://stackoverflow.com/a/27560620
#include <cstddef>
#include <iterator>
#include <stdexcept>
#include <type_traits>
template <typename T, bool NullTerminated = false>
class array_ref;
namespace {
template <typename T>
struct base_type {
using type = T;
};
template <typename T, bool b>
struct base_type<array_ref<T, b>> : base_type<T> {};
template <typename T>
using BaseType = typename base_type<T>::type;
template <typename T>
struct pointer_type {
using type = T *;
};
template <typename T, bool b>
struct pointer_type<array_ref<T, b>> {
using type = typename pointer_type<T>::type *;
};
template <typename T>
using PointerType = typename pointer_type<T>::type;
}
/**
* array_ref offers a non-const view into an array. The storage for the array is
* not owned by the
* array_ref object, and it is the client's responsibility to ensure the backing
* store reamins
* alive while the array_ref object is in use.
*
* @tparam T
* Type of elements in the array
*/
template <typename T>
struct array_ref_base {
public:
/** Alias for the type of elements in the array */
using value_type = T;
/** Alias for a pointer to value_type */
using pointer = T *;
/** Alias for a constant pointer to value_type */
using const_pointer = T const *;
/** Alias for a reference to value_type */
using reference = T &;
/** Alias for a constant reference to value_type */
using const_reference = T const &;
/** Alias for an unsigned integral type used to represent size related values
*/
using size_type = std::size_t;
/** Alias for a signed integral type used to represent result of difference
* computations */
using difference_type = std::ptrdiff_t;
/** Default constructor */
};
template <typename T>
bool operator==(const array_ref_base<T> &ref1, const array_ref_base<T> &ref2) {
return &ref1 == &ref2;
}
template <typename T, bool NullTerminated>
class array_ref : public array_ref_base<T> {
public:
using typename array_ref_base<T>::value_type;
using typename array_ref_base<T>::pointer;
using typename array_ref_base<T>::const_pointer;
using typename array_ref_base<T>::reference;
using typename array_ref_base<T>::const_reference;
using typename array_ref_base<T>::size_type;
using typename array_ref_base<T>::difference_type;
/** Alias for an iterator pointing at value_type objects */
using iterator = T *;
/** Alias for a constant iterator pointing at value_type objects */
using const_iterator = T const *;
/** Alias for a reverse iterator pointing at value_type objects */
using reverse_iterator = std::reverse_iterator<iterator>;
/** Alias for a constant reverse iterator pointing at value_type objects */
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
constexpr array_ref() noexcept = default;
template <bool b = NullTerminated,
typename = typename std::enable_if<b, void>::type>
array_ref(pointer first) noexcept : begin_{first}, length_{} {
while (begin_ && begin_[length_++])
;
}
/**
* Constructor that accepts a pointer to an array and the number of elements
* pointed at
*
* @param arr
* Pointer to array
* @param length
* Number of elements pointed at
*/
constexpr array_ref(pointer arr, size_type length) noexcept
: begin_{arr},
length_{length} {}
array_ref(
pointer arr, const std::vector<size_type> &lengths,
std::size_t size_index = 0)
: begin_{arr}, length_{lengths[size_index]} {}
/**
* Constructor that accepts a reference to an array
*
* @tparam N
* Number of elements in the array
*/
template <size_type N>
constexpr array_ref(T (&arr)[N]) noexcept : begin_{&arr[0]}, length_{N} {}
/**
* Constructor taking a pair of pointers pointing to the first element and one
* past the last
* element of the array, respectively.
*
* @param first
* Pointer to the first element of the array
* @param last
* Pointer to one past the last element of the array
*/
array_ref(pointer first, pointer last) noexcept
: begin_{first},
length_{static_cast<size_type>(std::distance(first, last))} {}
/** Copy constructor */
constexpr array_ref(array_ref const &) noexcept = default;
/** Copy assignment operator */
array_ref &operator=(array_ref const &) noexcept = default;
/** Move constructor */
constexpr array_ref(array_ref &&) noexcept = default;
/** Move assignment operator */
array_ref &operator=(array_ref &&) noexcept = default;
/**
* Returns an iterator to the first element of the array. If the array is
* empty, the
* returned iterator will be equal to end().
*
* @return An iterator to the first element of the array
*/
/*constexpr*/ iterator begin() noexcept {
return begin_;
}
/**
* Returns a constant iterator to the first element of the array. If the array
* is empty, the
* returned iterator will be equal to end().
*
* @return A constant iterator to the first element of the array
*/
constexpr const_iterator begin() const noexcept {
return begin_;
}
/**
* Returns a constant iterator to the first element of the array. If the array
* is empty, the
* returned iterator will be equal to end().
*
* @return A constant iterator to the first element of the array
*/
constexpr const_iterator cbegin() const noexcept {
return begin_;
}
/**
* Returns an iterator to the element following the last element of the array.
*
* @return An iterator to the element following the last element of the array
*/
/*constexpr*/ iterator end() noexcept {
return begin() + size();
}
/**
* Returns a constant iterator to the element following the last element of
* the array.
*
* @return A constant iterator to the element following the last element of
* the array
*/
constexpr const_iterator end() const noexcept {
return begin() + size();
}
/**
* Returns a constant iterator to the element following the last element of
* the array.
*
* @return A constant iterator to the element following the last element of
* the array
*/
constexpr const_iterator cend() const noexcept {
return cbegin() + size();
}
/**
* Returns a reverse iterator to the first element of the reversed array. It
* corresponds to the
* last element of the non-reversed array.
*
* @return A reverse iterator to the first element of the reversed array
*/
reverse_iterator rbegin() noexcept {
return reverse_iterator(end());
}
/**
* Returns a constant reverse iterator to the first element of the reversed
* array. It corresponds
* to the last element of the non-reversed array.
*
* @return A constant reverse iterator to the first element of the reversed
* array
*/
const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(cend());
}
/**
* Returns a constant reverse iterator to the first element of the reversed
* array. It corresponds
* to the last element of the non-reversed array.
*
* @return A constant reverse iterator to the first element of the reversed
* array
*/
const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator(cend());
}
/**
* Returns a reverse iterator to the element following the last element of the
* reversed array. It
* corresponds to the element preceding the first element of the non-reversed
* array.
*
* @return A reverse iterator to the element following the last element of the
* reversed array
*/
reverse_iterator rend() noexcept {
return reverse_iterator(begin());
}
/**
* Returns a constant reverse iterator to the element following the last
* element of the reversed
* array. It corresponds to the element preceding the first element of the
* non-reversed array.
*
* @return A constant reverse iterator to the element following the last
* element of the reversed
* array
*/
const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(cbegin());
}
/**
* Returns a constant reverse iterator to the element following the last
* element of the reversed
* array. It corresponds to the element preceding the first element of the
* non-reversed array.
*
* @return A constant reverse iterator to the element following the last
* element of the reversed
* array
*/
const_reverse_iterator crend() const noexcept {
return const_reverse_iterator(cbegin());
}
/**
* Returns the number of elements in the array.
*
* @return The number of elements in the array
*/
constexpr size_type size() const noexcept {
return length_;
}
/**
* Indicates whether the array has no elements
*
* @return true if the array has no elements, false otherwise
*/
constexpr bool empty() const noexcept {
return size() == 0;
}
/**
* Returns a reference to the element at the specified location.
*
* @return A reference to the element at the specified location
* @pre i < size()
*/
/*constexpr*/ reference operator[](size_type i) {
#ifndef NDEBUG
return at(i);
#else
return *(begin() + i);
#endif
}
/**
* Returns a constant reference to the element at the specified location.
*
* @return A constant reference to the element at the specified location
* @pre i < size()
*/
constexpr const_reference operator[](size_type i) const {
#ifndef NDEBUG
return at(i);
#else
return *(begin() + i);
#endif
}
/**
* Returns a reference to the element at the specified location, with bounds
* checking.
*
* @return A reference to the element at the specified location
* @throw std::out_of_range if the specified index is not within the range of
* the array
*/
/*constexpr*/ reference at(size_type i) {
if (i >= size()) {
throw std::out_of_range("index out of range");
}
return *(begin() + i);
}
/**
* Returns a constant reference to the element at the specified location, with
* bounds checking.
*
* @return A constant reference to the element at the specified location
* @throw std::out_of_range if the specified index is not within the range of
* the array
*/
/*constexpr*/ const_reference at(size_type i) const {
if (i >= size()) {
throw std::out_of_range("index out of range");
}
return *(begin() + i);
}
/**
* Returns a reference to the first element of the array
*
* @return A reference to the first element of the array
* @pre empty() == false
*/
/*constexpr*/ reference front() noexcept {
return *begin();
}
/**
* Returns a reference to the first element of the array
*
* @return A reference to the first element of the array
* @pre empty() == false
*/
constexpr const_reference front() const noexcept {
return *begin();
}
/**
* Returns a reference to the last element of the array
*
* @return A reference to the last element of the array
* @pre empty() == false
*/
/*constexpr*/ reference back() noexcept {
return *(end() - 1);
}
/**
* Returns a constant reference to the last element of the array
*
* @return A constant reference to the last element of the array
* @pre empty() == false
*/
constexpr const_reference back() const noexcept {
return *(end() - 1);
}
/**
* Returns a pointer to the address of the first element of the array
*
* @return A pointer to the address of the first element of the array
*/
/*constexpr*/ pointer data() noexcept {
return begin();
}
/**
* Returns a constant pointer to the address of the first element of the array
*
* @return A constant pointer to the address of the first element of the array
*/
constexpr const_pointer data() const noexcept {
return begin();
}
/**
* Resets the operand back to its default constructed state
*
* @post empty() == true
*/
void clear() noexcept {
begin_ = nullptr;
length_ = 0;
}
protected:
/** Pointer to the first element of the referenced array */
pointer begin_ = nullptr;
/** Number of elements in the referenced array */
size_type length_ = size_type();
};
// template<typename T>
// class null_terminated_array_ref : public array_ref<T> {
// public:
// using pointer = typename array_ref<T>::pointer;
// using size_type = typename array_ref<T>::size_type;
//
//
// /** Default constructor */
// constexpr null_terminated_array_ref() noexcept : array_ref<T>{} {}
//
// /**
// * Constructor that accepts a pointer to an array and the number of
// elements pointed at
// *
// * @param arr
// * Pointer to array
// * @param length
// * Number of elements pointed at
// */
// constexpr null_terminated_array_ref( pointer arr, size_type length )
// : array_ref<T>{arr, length} {}
//
// /**
// * Constructor that accepts a reference to an array
// *
// * @tparam N
// * Number of elements in the array
// */
// template<size_type N>
// constexpr null_terminated_array_ref( T (&arr)[N] ) noexcept :
// array_ref<T>{arr} {}
//
// /**
// * Constructor taking a pair of pointers pointing to the first
// element and one past the last
// * element of the array, respectively.
// *
// * @param first
// * Pointer to the first element of the array
// * @param last
// * Pointer to one past the last element of the array
// */
// null_terminated_array_ref( pointer first, pointer last ) noexcept :
// array_ref<T>{first, last} {}
//
// /** Copy constructor */
// constexpr null_terminated_array_ref( null_terminated_array_ref const&
// ) noexcept = default;
//
// /** Copy assignment operator */
// null_terminated_array_ref& operator=( null_terminated_array_ref
// const& ) noexcept = default;
//
// /** Move constructor */
// constexpr null_terminated_array_ref( null_terminated_array_ref&& )
// noexcept = default;
//
// /** Move assignment operator */
// null_terminated_array_ref& operator=( null_terminated_array_ref&& )
// noexcept = default;
//
// };
template <typename T, bool b>
class array_ref<array_ref<T, b>> : public array_ref_base<array_ref<T, b>> {
using internal_type = BaseType<array_ref<T, b>>;
using internal_pointer = PointerType<array_ref<T, b>>;
protected:
std::vector<array_ref<T, b>> vec_;
public:
using typename array_ref_base<array_ref<T, b>>::value_type;
using typename array_ref_base<array_ref<T, b>>::pointer;
using typename array_ref_base<array_ref<T, b>>::const_pointer;
using typename array_ref_base<array_ref<T, b>>::reference;
using typename array_ref_base<array_ref<T, b>>::const_reference;
using typename array_ref_base<array_ref<T, b>>::size_type;
using typename array_ref_base<array_ref<T, b>>::difference_type;
/** Alias for an iterator pointing at value_type objects */
using iterator = typename std::vector<array_ref<T, b>>::iterator;
/** Alias for a constant iterator pointing at value_type objects */
using const_iterator = typename std::vector<array_ref<T, b>>::const_iterator;
/** Alias for a reverse iterator pointing at value_type objects */
using reverse_iterator =
typename std::vector<array_ref<T, b>>::reverse_iterator;
/** Alias for a constant reverse iterator pointing at value_type objects */
using const_reverse_iterator =
typename std::vector<array_ref<T, b>>::const_reverse_iterator;
/** Default constructor */
constexpr array_ref() noexcept = default;
array_ref(internal_pointer arr, const size_type length) {
for (size_type i = 0; i < length; ++i) {
vec_.emplace_back(arr[i]);
}
}
array_ref(
internal_pointer arr, const std::vector<size_type> &lengths,
std::size_t size_index = 0) {
for (size_type i = 0; i < lengths[size_index]; ++i) {
if (size_index < lengths.size()) {
vec_.emplace_back(arr[i], lengths, size_index + 1);
} else {
vec_.emplace_back(arr[i]);
}
}
}
template <typename InputIt>
array_ref(InputIt first, InputIt last) : vec_{first, last} {}
/**
* Constructor that accepts a reference to an array
*
* @tparam N
* Number of elements in the array
*/
template <typename A, std::size_t N>
array_ref(A (&arr)[N]) {
for (size_type i = 0; i < N; ++i) {
vec_.emplace_back(arr[i]);
}
}
/** Copy constructor */
array_ref(array_ref const &) = default;
/** Copy assignment operator */
array_ref &operator=(array_ref const &) = default;
/** Move constructor */
constexpr array_ref(array_ref &&) noexcept = default;
/** Move assignment operator */
array_ref &operator=(array_ref &&) noexcept = default;
/**
* Returns an iterator to the first element of the array. If the array is
* empty, the
* returned iterator will be equal to end().
*
* @return An iterator to the first element of the array
*/
/*constexpr*/ iterator begin() noexcept {
return vec_.begin();
}
/**
* Returns a constant iterator to the first element of the array. If the array
* is empty, the
* returned iterator will be equal to end().
*
* @return A constant iterator to the first element of the array
*/
constexpr const_iterator begin() const noexcept {
return vec_.cbegin();
}
/**
* Returns a constant iterator to the first element of the array. If the array
* is empty, the
* returned iterator will be equal to end().
*
* @return A constant iterator to the first element of the array
*/
constexpr const_iterator cbegin() const noexcept {
return vec_.cbegin();
}
/**
* Returns an iterator to the element following the last element of the array.
*
* @return An iterator to the element following the last element of the array
*/
/*constexpr*/ iterator end() noexcept {
return vec_.end();
}
/**
* Returns a constant iterator to the element following the last element of
* the array.
*
* @return A constant iterator to the element following the last element of
* the array
*/
constexpr const_iterator end() const noexcept {
return vec_.cend();
}
/**
* Returns a constant iterator to the element following the last element of
* the array.
*
* @return A constant iterator to the element following the last element of
* the array
*/
constexpr const_iterator cend() const noexcept {
return vec_.cend();
}
/**
* Returns a reverse iterator to the first element of the reversed array. It
* corresponds to the
* last element of the non-reversed array.
*
* @return A reverse iterator to the first element of the reversed array
*/
reverse_iterator rbegin() noexcept {
return vec_.rbegin();
}
/**
* Returns a constant reverse iterator to the first element of the reversed
* array. It corresponds
* to the last element of the non-reversed array.
*
* @return A constant reverse iterator to the first element of the reversed
* array
*/
const_reverse_iterator rbegin() const noexcept {
return vec_.crbegin();
}
/**
* Returns a constant reverse iterator to the first element of the reversed
* array. It corresponds
* to the last element of the non-reversed array.
*
* @return A constant reverse iterator to the first element of the reversed
* array
*/
const_reverse_iterator crbegin() const noexcept {
return vec_.crbegin();
}
/**
* Returns a reverse iterator to the element following the last element of the
* reversed array. It
* corresponds to the element preceding the first element of the non-reversed
* array.
*
* @return A reverse iterator to the element following the last element of the
* reversed array
*/
reverse_iterator rend() noexcept {
return vec_.rend();
}
/**
* Returns a constant reverse iterator to the element following the last
* element of the reversed
* array. It corresponds to the element preceding the first element of the
* non-reversed array.
*
* @return A constant reverse iterator to the element following the last
* element of the reversed
* array
*/
const_reverse_iterator rend() const noexcept {
return vec_.crend();
}
/**
* Returns a constant reverse iterator to the element following the last
* element of the reversed
* array. It corresponds to the element preceding the first element of the
* non-reversed array.
*
* @return A constant reverse iterator to the element following the last
* element of the reversed
* array
*/
const_reverse_iterator crend() const noexcept {
return vec_.crend();
}
/**
* Returns the number of elements in the array.
*
* @return The number of elements in the array
*/
constexpr size_type size() const noexcept {
return vec_.size();
}
/**
* Indicates whether the array has no elements
*
* @return true if the array has no elements, false otherwise
*/
constexpr bool empty() const noexcept {
return vec_.empty();
}
/**
* Returns a reference to the element at the specified location.
*
* @return A reference to the element at the specified location
* @pre i < size()
*/
/*constexpr*/ reference operator[](size_type i) {
return vec_[i];
}
/**
* Returns a constant reference to the element at the specified location.
*
* @return A constant reference to the element at the specified location
* @pre i < size()
*/
constexpr const_reference operator[](size_type i) const {
return vec_[i];
}
/**
* Returns a reference to the element at the specified location, with bounds
* checking.
*
* @return A reference to the element at the specified location
* @throw std::out_of_range if the specified index is not within the range of
* the array
*/
/*constexpr*/ reference at(size_type i) {
return vec_.at(i);
}
/**
* Returns a constant reference to the element at the specified location, with
* bounds checking.
*
* @return A constant reference to the element at the specified location
* @throw std::out_of_range if the specified index is not within the range of
* the array
*/
/*constexpr*/ const_reference at(size_type i) const {
return vec_.at(i);
}
/**
* Returns a reference to the first element of the array
*
* @return A reference to the first element of the array
* @pre empty() == false
*/
/*constexpr*/ reference front() noexcept {
return vec_.front();
}
/**
* Returns a reference to the first element of the array
*
* @return A reference to the first element of the array
* @pre empty() == false
*/
constexpr const_reference front() const noexcept {
return vec_.front();
}
/**
* Returns a reference to the last element of the array
*
* @return A reference to the last element of the array
* @pre empty() == false
*/
/*constexpr*/ reference back() noexcept {
return vec_.back();
}
/**
* Returns a constant reference to the last element of the array
*
* @return A constant reference to the last element of the array
* @pre empty() == false
*/
constexpr const_reference back() const noexcept {
return vec_.back();
}
/**
* Returns a pointer to the address of the first element of the array
*
* @return A pointer to the address of the first element of the array
*/
/*constexpr*/ pointer data() noexcept {
return vec_.data();
}
/**
* Returns a constant pointer to the address of the first element of the array
*
* @return A constant pointer to the address of the first element of the array
*/
constexpr const_pointer data() const noexcept {
return vec_.data();
}
/**
* Resets the operand back to its default constructed state
*
* @post empty() == true
*/
void clear() noexcept {
vec_.clear();
}
};
// template<typename T, bool b>
// bool operator==(const array_ref<T, b>& ref1, const array_ref<T, b>& ref2) {
// return &ref1 == &ref2;
// }