Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 54 additions & 21 deletions cc/core/Vec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Nan::Persistent<v8::FunctionTemplate> Vec2::constructor;
Nan::Persistent<v8::FunctionTemplate> Vec3::constructor;
Nan::Persistent<v8::FunctionTemplate> Vec4::constructor;
Nan::Persistent<v8::FunctionTemplate> Vec6::constructor;

NAN_MODULE_INIT(Vec::Init) {
v8::Local<v8::FunctionTemplate> vec2Ctor = Nan::New<v8::FunctionTemplate>(Vec2::New);
Expand Down Expand Up @@ -39,42 +40,74 @@ NAN_MODULE_INIT(Vec::Init) {
Nan::SetPrototypeMethod(vec4Ctor, "norm", Vec4::Norm);
Vec4::Init(vec4Ctor);

v8::Local<v8::FunctionTemplate> vec6Ctor = Nan::New<v8::FunctionTemplate>(Vec6::New);
Vec6::constructor.Reset(vec6Ctor);
vec6Ctor->InstanceTemplate()->SetInternalFieldCount(1);
vec6Ctor->SetClassName(Nan::New("Vec6").ToLocalChecked());
Nan::SetAccessor(vec6Ctor->InstanceTemplate(), Nan::New("u").ToLocalChecked(), Vec6::u_getter);
Nan::SetAccessor(vec6Ctor->InstanceTemplate(), Nan::New("v").ToLocalChecked(), Vec6::v_getter);
Nan::SetAccessor(vec6Ctor->InstanceTemplate(), Nan::New("w").ToLocalChecked(), Vec6::w_getter);
Nan::SetAccessor(vec6Ctor->InstanceTemplate(), Nan::New("x").ToLocalChecked(), Vec6::x_getter);
Nan::SetAccessor(vec6Ctor->InstanceTemplate(), Nan::New("y").ToLocalChecked(), Vec6::y_getter);
Nan::SetAccessor(vec6Ctor->InstanceTemplate(), Nan::New("z").ToLocalChecked(), Vec6::z_getter);
Nan::SetPrototypeMethod(vec6Ctor, "at", Vec6::At);
Nan::SetPrototypeMethod(vec6Ctor, "norm", Vec6::Norm);
Vec6::Init(vec6Ctor);

v8::Local<v8::FunctionTemplate> ctor = Nan::New<v8::FunctionTemplate>(Vec::New);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(Nan::New("Vec").ToLocalChecked());
Nan::Set(target,Nan::New("Vec").ToLocalChecked(), FF::getFunction(ctor));
Nan::Set(target,Nan::New("Vec2").ToLocalChecked(), FF::getFunction(ctor));
Nan::Set(target,Nan::New("Vec3").ToLocalChecked(), FF::getFunction(ctor));
Nan::Set(target,Nan::New("Vec4").ToLocalChecked(), FF::getFunction(ctor));
Nan::Set(target,Nan::New("Vec6").ToLocalChecked(), FF::getFunction(ctor));
};

NAN_METHOD(Vec::New) {
FF::TryCatch tryCatch("Vec::New");
FF_ASSERT_CONSTRUCT_CALL();
if (info.Length() < 2) {
return tryCatch.throwError("Vec::New - expected arguments (w), x, y, (z)");
if (info.Length() < 2 || info.Length() > 6 || info.Length() == 5) {
return tryCatch.throwError("Vec::New - expected arguments (u, v), (w), x, y, (z)");
}
v8::Local<v8::Object> jsVec;
if (info.Length() == 4) {
jsVec = FF::newInstance(Nan::New(Vec4::constructor));
Nan::ObjectWrap::Unwrap<Vec4>(jsVec)->self = cv::Vec4d(
info[0]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[2]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[3]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value()
);
} else {
double x = info[0]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value();
double y = info[1]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value();
if (info.Length() == 3) {
double z = info[2]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value();
jsVec = FF::newInstance(Nan::New(Vec3::constructor));
Nan::ObjectWrap::Unwrap<Vec3>(jsVec)->self = cv::Vec3d(x, y, z);
}
else {

switch(info.Length()) {
case 2:
jsVec = FF::newInstance(Nan::New(Vec2::constructor));
Nan::ObjectWrap::Unwrap<Vec2>(jsVec)->self = cv::Vec2d(x, y);
}
Nan::ObjectWrap::Unwrap<Vec2>(jsVec)->self = cv::Vec2d(
info[0]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value()
);
break;
case 3:
jsVec = FF::newInstance(Nan::New(Vec3::constructor));
Nan::ObjectWrap::Unwrap<Vec3>(jsVec)->self = cv::Vec3d(
info[0]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[2]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value()
);
break;
case 4:
jsVec = FF::newInstance(Nan::New(Vec4::constructor));
Nan::ObjectWrap::Unwrap<Vec4>(jsVec)->self = cv::Vec4d(
info[0]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[2]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[3]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value()
);
break;
case 6:
jsVec = FF::newInstance(Nan::New(Vec6::constructor));
Nan::ObjectWrap::Unwrap<Vec6>(jsVec)->self = cv::Vec6d(
info[0]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[1]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[2]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[3]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[4]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value(),
info[5]->ToNumber(Nan::GetCurrentContext()).ToLocalChecked()->Value()
);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to rewrite this using macros to minimise the duplication but I'm too unfamiliar in cpp land to do it correctly, so this is the alternative I came up with.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, no need to introduce macros here :)

break;
}
info.GetReturnValue().Set(jsVec);
}
2 changes: 2 additions & 0 deletions cc/core/Vec.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Vec2.h"
#include "Vec3.h"
#include "Vec4.h"
#include "Vec6.h"

#ifndef __FF_VEC_H__
#define __FF_VEC_H__
Expand All @@ -14,6 +15,7 @@ class Vec : public Nan::ObjectWrap {
static NAN_METHOD(NewVec2);
static NAN_METHOD(NewVec3);
static NAN_METHOD(NewVec4);
static NAN_METHOD(NewVec6);

static Nan::Persistent<v8::FunctionTemplate> constructor;
};
Expand Down
50 changes: 50 additions & 0 deletions cc/core/Vec6.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <opencv2/core.hpp>
#include "coreUtils.h"
#include "NativeNodeUtils.h"
#include "macros.h"

#ifndef __FF_VEC6_H__
#define __FF_VEC6_H__

class Vec6 : public FF::ObjectWrap<Vec6, cv::Vec6d> {
public:
static Nan::Persistent<v8::FunctionTemplate> constructor;

static const char* getClassName() {
return "Vec6";
}

static NAN_METHOD(New) {
Vec6* self = new Vec6();
self->Wrap(info.Holder());
info.GetReturnValue().Set(info.Holder());
}

static void Init(v8::Local<v8::FunctionTemplate> ctor) {
FF_PROTO_SET_MATRIX_OPERATIONS(ctor);
}

FF_GETTER_CUSTOM(u, FF::DoubleConverter, self[0]);
FF_GETTER_CUSTOM(v, FF::DoubleConverter, self[1]);
FF_GETTER_CUSTOM(w, FF::DoubleConverter, self[2]);
FF_GETTER_CUSTOM(x, FF::DoubleConverter, self[3]);
FF_GETTER_CUSTOM(y, FF::DoubleConverter, self[4]);
FF_GETTER_CUSTOM(z, FF::DoubleConverter, self[5]);

FF_INIT_VEC6_OPERATIONS();
static NAN_METHOD(Dot) {
FF_OPERATOR_RET_SCALAR(&cv::Vec6d::dot, FF_APPLY_CLASS_FUNC, Vec6, "Dot");
}
static NAN_METHOD(Norm) {
info.GetReturnValue().Set(Nan::New(cv::norm(Vec6::unwrapSelf(info))));
}

static NAN_METHOD(At) {
FF::TryCatch tryCatch("Vec6::At");
FF_ASSERT_INDEX_RANGE(info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value(), 5, "Vec6");
cv::Vec6d vecSelf = Vec6::unwrapSelf(info);
info.GetReturnValue().Set(vecSelf[info[0]->ToInt32(Nan::GetCurrentContext()).ToLocalChecked()->Value()]);
}
};

#endif
7 changes: 7 additions & 0 deletions cc/core/core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ NAN_METHOD(Core::Partition) {
}
numLabels = cv::partition(pts, labels, predicateFactory<Vec4, cv::Vec4d>(cb));
}
else if (Vec6::hasInstance(data0)) {
std::vector<cv::Vec6d> pts;
if (Vec6::ArrayConverter::arg(0, &pts, info)) {
return tryCatch.reThrow();
}
numLabels = cv::partition(pts, labels, predicateFactory<Vec6, cv::Vec6d>(cb));
}
else if (Mat::hasInstance(data0)) {
std::vector<cv::Mat> mats;
if (Mat::ArrayConverter::arg(0, &mats, info)) {
Expand Down
1 change: 1 addition & 0 deletions cc/core/coreUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
#define FF_INIT_VEC2_OPERATIONS() FF_INIT_MATRIX_OPERATIONS(Vec2);
#define FF_INIT_VEC3_OPERATIONS() FF_INIT_MATRIX_OPERATIONS(Vec3);
#define FF_INIT_VEC4_OPERATIONS() FF_INIT_MATRIX_OPERATIONS(Vec4);
#define FF_INIT_VEC6_OPERATIONS() FF_INIT_MATRIX_OPERATIONS(Vec6);

namespace FF {
template<int cn>
Expand Down
17 changes: 17 additions & 0 deletions test/tests/core/Vec/VecTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ module.exports = function ({ cv, utils }) {
expect(vec4.at(3)).to.equal(30);
});
});

describe('Vec6', () => {
const vec6 = new cv.Vec(5, 10, 20, 30, 40, 50);
it('should throw index out of bounds', () => {
assertError(() => vec6.at(-1), 'Index out of bounds: Vec6 at index -1');
assertError(() => vec6.at(6), 'Index out of bounds: Vec6 at index 6');
});

it('should return values from indices', () => {
expect(vec6.at(0)).to.equal(5);
expect(vec6.at(1)).to.equal(10);
expect(vec6.at(2)).to.equal(20);
expect(vec6.at(3)).to.equal(30);
expect(vec6.at(4)).to.equal(40);
expect(vec6.at(5)).to.equal(50);
});
});
});

};
48 changes: 48 additions & 0 deletions test/tests/core/Vec/constructorTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ module.exports = function ({ cv, utils }) {
assertError(() => new cv.Vec(0), 'expected arguments');
});

it('should throw for trying to insantiate invalid vec5', () => {
assertError(() => new cv.Vec(5, 10, 20, 30, 40), 'Vec::New - expected arguments (u, v), (w), x, y, (z)');
});

describe('Vec2', () => {
it('should have int positions', () => {
const x = 100;
Expand Down Expand Up @@ -107,5 +111,49 @@ module.exports = function ({ cv, utils }) {
assertPropsWithValue(new cv.Vec(w, x, y, z))({ w, x, y, z });
});
});

describe('Vec6', () => {
it('should have int positions', () => {
const u = 50;
const v = 100;
const w = 200;
const x = 300;
const y = 400;
const z = 500;
assertPropsWithValue(new cv.Vec(u, v, w, x, y, z))({ u, v, w, x, y, z });
});

it('should have double positions', () => {
const u = 50.99;
const v = 100.12345;
const w = 200.89764;
const x = 300.034;
const y = 400.254;
const z = 500.543;
assertPropsWithValue(new cv.Vec(u, v, w, x, y, z))({ u, v, w, x, y, z });
});

it('should have negative int positions', () => {
it('should have int positions', () => {
const u = -50;
const v = -100;
const w = -200;
const x = -300;
const y = -400;
const z = -500;
assertPropsWithValue(new cv.Vec(u, v, w, x, y, z))({ u, v, w, x, y, z });
});
});

it('should have negative double positions', () => {
const u = -50.99;
const v = -100.12345;
const w = -200.89764;
const x = -300.034;
const y = -400.254;
const z = -500.543;
assertPropsWithValue(new cv.Vec(u, v, w, x, y, z))({ u, v, w, x, y, z });
});
});
});
};
88 changes: 88 additions & 0 deletions test/tests/core/Vec/operatorTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,5 +289,93 @@ module.exports = function ({ cv, utils }) {
});
});
});

describe('Vec6', () => {
const vec0 = new cv.Vec(50, 100, 200, 300, 400, 500);
const vec1 = new cv.Vec(10, 25, 50, 75, 100, 125);
const vec2 = new cv.Vec(2, 5, 4, 3, 2, 1);
const operatorRequiresArg = OperatorRequiresArg(vec0);
describe('add', () => {
operatorRequiresArg('add');

it('add vectors', () => {
assertPropsWithValue(vec0.add(vec1))({ u: 60, v: 125, w: 250, x: 375, y: 500, z: 625 });
});
});

describe('sub', () => {
operatorRequiresArg('sub');

it('subtract vectors', () => {
assertPropsWithValue(vec0.sub(vec1))({ u: 40, v: 75, w: 150, x: 225, y: 300, z: 375 });
});
});

describe('mul', () => {
operatorRequiresArg('mul', true);

it('multiply vector by scalar', () => {
assertPropsWithValue(vec0.mul(2))({ u: 100, v: 200, w: 400, x: 600, y: 800, z: 1000 });
});
});

describe('div', () => {
operatorRequiresArg('div', true);

it('divide vector by scalar', () => {
assertPropsWithValue(vec0.div(2))({ u: 25, v: 50, w: 100, x: 150, y: 200, z: 250 });
});
});

describe('hMul', () => {
operatorRequiresArg('hMul');

it('elementwise multiply vectors', () => {
assertPropsWithValue(vec0.hMul(vec2))({ u: 100, v: 500, w: 800, x: 900, y: 800, z: 500 });
});
});

describe('hDiv', () => {
operatorRequiresArg('hDiv');

it('elementwise divide vectors', () => {
assertPropsWithValue(vec0.hDiv(vec2))({ u: 25, v: 20, w: 50, x: 100, y: 200, z: 500 });
});
});

describe('dot', () => {
operatorRequiresArg('dot');

it('compute dot product of vectors', () => {
expect(vec0.dot(vec2)).to.equal(3600);
});
});

describe('absdiff', () => {
operatorRequiresArg('absdiff');

it('apply absdiff to matrices', () => {
assertPropsWithValue(new cv.Vec(0, 100, 50, 25, 150, 10).absdiff(new cv.Vec(50, 25, 75, 25, 50, 20)))({ u: 50, v: 75, w: 25, x: 0, y: 100, z: 10 });
});
});

describe('exp', () => {
it('apply exp to vector', () => {
assertPropsWithValue(new cv.Vec(Math.log(1), Math.log(4), 0, Math.log(0), Math.log(4), Math.log(4)).exp())({ u: 1, v: 4, w: 1, x: 0, y: 4, z: 4 });
});
});

describe('sqrt', () => {
it('apply sqrt to vector', () => {
assertPropsWithValue(new cv.Vec(0, 4, 16, 64, 256, 1024).sqrt())({ u: 0, v: 2, w: 4, x: 8, y: 16, z: 32 });
});
});

describe('norm', () => {
it('should return magnitude', () => {
expect(new cv.Vec(Math.sqrt(8), Math.sqrt(8), Math.sqrt(8), Math.sqrt(8), Math.sqrt(16), Math.sqrt(16)).norm()).to.equal(8);
});
});
});
});
};