1
0
Fork 0
mirror of https://github.com/ruby-opencv/ruby-opencv synced 2023-03-27 23:22:12 -04:00

tested CvSeq and fixed it's bugs

This commit is contained in:
ser1zw 2011-02-06 20:12:58 +09:00
parent f015503f03
commit 4fccb2ea28
4 changed files with 290 additions and 96 deletions

View file

@ -25,10 +25,6 @@
* When storing object(named "obj") of class B to the sequence.
* Try automatically : A.from_B(obj) => object of class A.
*
* CvSeq has the circulation structure internally.
* That is, when the sequence has three values ("a","b","c"),
* seq[0] and seq[3] are same "a", and seq[-1] and seq[2] are same "c".
*
* The sequence might have another sequence outside. see below.
* Each sequece has h_prev, h_next, v_prev, v_next method.
* If the adjoining sequence exists, each method return the adjoining sequence.
@ -81,7 +77,6 @@ define_ruby_class()
rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1);
rb_define_method(rb_klass, "first", RUBY_METHOD_FUNC(rb_first), 0);
rb_define_method(rb_klass, "last", RUBY_METHOD_FUNC(rb_last), 0);
rb_define_method(rb_klass, "index", RUBY_METHOD_FUNC(rb_index), 1);
rb_define_method(rb_klass, "h_prev", RUBY_METHOD_FUNC(rb_h_prev), 0);
rb_define_method(rb_klass, "h_next", RUBY_METHOD_FUNC(rb_h_next), 0);
@ -142,7 +137,7 @@ rb_initialize(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &klass, &storage);
if(!rb_obj_is_kind_of(klass, rb_cClass))
rb_raise(rb_eTypeError, "argument 1 (sequence-block class) should be %s.", rb_class2name(rb_cClass));
CvSeq *seq = 0;
CvSeq *seq = NULL;
storage = CHECK_CVMEMSTORAGE(storage);
int type = 0, size = 0;
if(klass == cCvIndex::rb_class()){
@ -158,7 +153,7 @@ rb_initialize(int argc, VALUE *argv, VALUE self)
type = CV_SEQ_ELTYPE_POINT3D;
size = sizeof(CvPoint3D32f);
}
auto_extend(self);
// auto_extend(self);
// todo: more various class will be support.
if(!size)
rb_raise(rb_eTypeError, "unsupport %s class for sequence-block.", rb_class2name(klass));
@ -204,9 +199,12 @@ VALUE
rb_aref(VALUE self, VALUE index)
{
CvSeq *seq = CVSEQ(self);
int idx = NUM2INT(index);
if(!(seq->total > 0))
return Qnil;
return REFER_OBJECT(seqblock_class(seq), cvGetSeqElem(seq, NUM2INT(index) % seq->total), self);
if (idx >= seq->total)
rb_raise(rb_eIndexError, "index %d out of sequence", idx);
return REFER_OBJECT(seqblock_class(seq), cvGetSeqElem(seq, idx), self);
}
/*
@ -239,27 +237,6 @@ rb_last(VALUE self)
return REFER_OBJECT(seqblock_class(seq), cvGetSeqElem(seq, -1), self);
}
/*when storing it in CvSeq.
* call-seq:
* index(<i>obj</i>) -> int or nil
*
* Return the index of the first object in <i>self</i>. Return <tt>nil</tt> if no match is found.
*/
VALUE
rb_index(VALUE self, VALUE object)
{
CvSeq *seq = CVSEQ(self);
int index;
if(CLASS_OF(object) == seqblock_class(seq)){
index = cvSeqElemIdx(seq, DATA_PTR(object));
if(!(index < 0))
return INT2FIX(index);
}else{
rb_warn("sequence-block class unmatch.");
}
return Qnil;
}
/*
* call-seq:
* h_prev -> seq or nil
@ -271,10 +248,9 @@ VALUE
rb_h_prev(VALUE self)
{
CvSeq *seq = CVSEQ(self);
if (seq->h_prev) {
if (seq->h_prev)
return new_sequence(CLASS_OF(self), seq->h_prev, seqblock_class(seq), lookup_root_object(seq));
//new_sequence(seq->h_prev, CLASS_OF(self), seqblock_class(seq), lookup_root_object(seq));
} else
else
return Qnil;
}
@ -289,10 +265,9 @@ VALUE
rb_h_next(VALUE self)
{
CvSeq *seq = CVSEQ(self);
if (seq->h_next) {
if (seq->h_next)
return new_sequence(CLASS_OF(self), seq->h_next, seqblock_class(seq), lookup_root_object(seq));
//new_sequence(seq->h_next, CLASS_OF(self), seqblock_class(seq), lookup_root_object(seq));
} else
else
return Qnil;
}
@ -307,15 +282,15 @@ VALUE
rb_v_prev(VALUE self)
{
CvSeq *seq = CVSEQ(self);
if (seq->v_prev) {
if (seq->v_prev)
return new_sequence(CLASS_OF(self), seq->v_prev, seqblock_class(seq), lookup_root_object(seq));
} else
else
return Qnil;
}
/*
* call-seq:
* v_prev -> seq or nil
* v_next -> seq or nil
*
* Return the sequence vertically located in next.
* Return <tt>nil</tt> if not existing.
@ -324,39 +299,50 @@ VALUE
rb_v_next(VALUE self)
{
CvSeq *seq = CVSEQ(self);
if (seq->v_next) {
if (seq->v_next)
return new_sequence(CLASS_OF(self), seq->v_next, seqblock_class(seq), lookup_root_object(seq));
} else
else
return Qnil;
}
VALUE
rb_seq_push(VALUE self, VALUE args, int flag)
{
CvSeq *seq = CVSEQ(self);
VALUE klass = seqblock_class(seq), object;
void *buffer = NULL;
for (int i = 0; i < RARRAY_LEN(args); i++) {
object = RARRAY_PTR(args)[i];
if (CLASS_OF(object) == klass) {
if (flag == CV_FRONT)
cvSeqPushFront(seq, DATA_PTR(object));
else
cvSeqPush(seq, DATA_PTR(object));
}
else if (rb_obj_is_kind_of(object, rb_klass) && CLASS_OF(rb_first(object)) == klass) { // object is CvSeq
buffer = cvCvtSeqToArray(CVSEQ(object), cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size));
cvSeqPushMulti(seq, buffer, CVSEQ(object)->total, flag);
cvFree(&buffer);
}
else {
rb_raise(rb_eTypeError, "arguments should be %s or %s which includes %s.",
rb_class2name(klass), rb_class2name(rb_klass), rb_class2name(klass));
}
}
return self;
}
/*
* call-seq:
* push(<i>obj, ...</i>) -> self
*
* Append - Pushes the given object(s) on the end of this sequence. This expression return the sequence itself,
* so several append may be chainded together.
* so several append may be chained together.
*/
VALUE
rb_push(VALUE self, VALUE args)
{
CvSeq *seq = CVSEQ(self);
VALUE klass = seqblock_class(seq), object;
void *buffer = 0;
for(int i = 0; i < RARRAY_LEN(args); i++){
object = RARRAY_PTR(args)[i];
if(CLASS_OF(object) == klass){
cvSeqPush(seq, DATA_PTR(object));
}else if(rb_obj_is_kind_of(object, rb_klass) && CLASS_OF(object) == klass){ // object is CvSeq
buffer = cvCvtSeqToArray(CVSEQ(object), cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size));
cvSeqPushMulti(seq, buffer, CVSEQ(object)->total);
cvFree((void**)&buffer);
}else{
object = CONVERT(object, klass);
cvSeqPush(seq, DATA_PTR(object));
}
}
return self;
return rb_seq_push(self, args, CV_BACK);
}
/*
@ -400,23 +386,7 @@ rb_clear(VALUE self)
VALUE
rb_unshift(VALUE self, VALUE args)
{
CvSeq *seq = CVSEQ(self);
VALUE klass = seqblock_class(seq), object;
void *buffer = 0;
for(int i = 0; i < RARRAY_LEN(args); i++){
object = RARRAY_PTR(args)[i];
if(CLASS_OF(object) == klass){
cvSeqPushFront(seq, DATA_PTR(object));
}else if(rb_obj_is_kind_of(object, rb_klass) && CLASS_OF(object) == klass){
buffer = cvCvtSeqToArray(CVSEQ(object), cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size));
cvSeqPushMulti(seq, buffer, CVSEQ(object)->total, 1);
cvFree((void**)&buffer);
}else{
object = CONVERT(object, klass);
cvSeqPushFront(seq, DATA_PTR(object));
}
}
return self;
return rb_seq_push(self, args, CV_FRONT);
}
/*
@ -445,7 +415,7 @@ rb_shift(VALUE self)
* passing that sequence-block as a parameter.
* seq = CvSeq.new(CvIndex)
* seq.push(5, 6, 7)
* seq.each{|x| print x, " -- "
* seq.each{|x| print x, " -- " }
* produces:
* 5 -- 6 -- 7 --
*/
@ -506,7 +476,7 @@ rb_insert(VALUE self, VALUE index, VALUE object)
CvSeq *seq = CVSEQ(self);
VALUE klass = seqblock_class(seq);
if(CLASS_OF(object) != klass)
object = CONVERT(object, klass);
rb_raise(rb_eTypeError, "arguments should be %s.", rb_class2name(klass));
cvSeqInsert(seq, FIX2INT(index), DATA_PTR(object));
return self;
}
@ -524,20 +494,6 @@ rb_remove(VALUE self, VALUE index)
return self;
}
/*
* call-seq:
* clone
*
* Return copy of sequence.
*/
VALUE
rb_clone(VALUE self)
{
CvSeq *seq = CVSEQ(self);
VALUE storage = cCvMemStorage::new_object();
return new_sequence(CLASS_OF(self), cvCloneSeq(seq), seqblock_class(seq), storage);
}
/*
VALUE
new_object(CvSeq *seq, VALUE klass)
@ -557,7 +513,6 @@ new_object(CvSeq *seq, VALUE klass, VALUE storage)
}
*/
VALUE
new_sequence(VALUE klass, CvSeq *seq, VALUE element_klass, VALUE storage)
{

View file

@ -33,7 +33,6 @@ VALUE rb_empty_q(VALUE self);
VALUE rb_aref(VALUE self, VALUE index);
VALUE rb_first(VALUE self);
VALUE rb_last(VALUE self);
VALUE rb_index(VALUE self, VALUE object);
VALUE rb_h_prev(VALUE self);
VALUE rb_h_next(VALUE self);
VALUE rb_v_prev(VALUE self);
@ -48,11 +47,9 @@ VALUE rb_each_with_index(VALUE self);
VALUE rb_insert(VALUE self, VALUE index, VALUE object);
VALUE rb_remove(VALUE self, VALUE index);
VALUE rb_clear(VALUE self);
VALUE rb_clone(VALUE self);
VALUE new_object(CvSeq *seq, VALUE klass);
VALUE new_object(CvSeq *seq, VALUE klass, VALUE storage);
//VALUE new_object(CvSeq *seq, VALUE storage, VALUE klass);
VALUE new_sequence(VALUE klass, CvSeq *seq, VALUE element_klass, VALUE storage);
VALUE auto_extend(VALUE object);

View file

@ -165,6 +165,10 @@ extern "C"{
#define RSTRING_PTR(arg) (RSTRING(arg)->ptr)
#endif
#ifndef DBL2NUM
#define DBL2NUM(dbl) (rb_float_new(dbl))
#endif
// OpenCV module
__NAMESPACE_BEGIN_OPENCV
@ -204,7 +208,7 @@ IPLCONVKERNEL_OBJECT(VALUE klass, void *ptr)
inline VALUE
GENERIC_OBJECT(VALUE klass, void *ptr)
{
return Data_Wrap_Struct(klass, 0, 0, ptr);
return Data_Wrap_Struct(klass, 0, -1, ptr);
}
inline VALUE

238
test/test_cvseq.rb Executable file
View file

@ -0,0 +1,238 @@
#!/usr/bin/env ruby
# -*- mode: ruby; coding: utf-8-unix -*-
require 'test/unit'
require 'opencv'
require File.expand_path(File.dirname(__FILE__)) + '/helper'
include OpenCV
# Tests for OpenCV::CvSeq
class TestCvSeq < OpenCVTestCase
def test_initialize
assert_not_nil(CvSeq.new(CvIndex))
assert_not_nil(CvSeq.new(CvPoint))
assert_not_nil(CvSeq.new(CvPoint2D32f))
assert_not_nil(CvSeq.new(CvPoint3D32f))
end
def test_total
seq1 = CvSeq.new(CvPoint)
assert_equal(0, seq1.total)
seq1.push(CvPoint.new(1, 2))
assert_equal(1, seq1.total)
seq1.push(CvPoint.new(3, 4))
assert_equal(2, seq1.total)
# Alias
assert_equal(2, seq1.length)
assert_equal(2, seq1.size)
end
def test_empty
assert(CvSeq.new(CvPoint).empty?)
assert(CvSeq.new(CvPoint2D32f).empty?)
assert(CvSeq.new(CvPoint3D32f).empty?)
end
def test_aref
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40), CvPoint.new(50, 60))
assert_equal(CvPoint, seq1[0].class)
assert_equal(10, seq1[0].x)
assert_equal(20, seq1[0].y)
assert_equal(30, seq1[1].x)
assert_equal(40, seq1[1].y)
assert_equal(50, seq1[2].x)
assert_equal(60, seq1[2].y)
end
def test_push
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40))
assert_equal(2, seq1.total)
assert_equal(CvPoint, seq1[0].class)
assert_equal(10, seq1[0].x)
assert_equal(20, seq1[0].y)
assert_equal(CvPoint, seq1[1].class)
assert_equal(30, seq1[1].x)
assert_equal(40, seq1[1].y)
seq2 = CvSeq.new(CvPoint).push(CvPoint.new(50, 60))
seq2.push(seq1)
assert_equal(3, seq2.total)
assert_equal(CvPoint, seq2[0].class)
assert_equal(50, seq2[0].x)
assert_equal(60, seq2[0].y)
assert_equal(CvPoint, seq2[1].class)
assert_equal(10, seq2[1].x)
assert_equal(20, seq2[1].y)
assert_equal(CvPoint, seq2[2].class)
assert_equal(30, seq2[2].x)
assert_equal(40, seq2[2].y)
assert_raise(TypeError) {
seq1.push(CvPoint2D32f.new(55.5, 66.6))
}
assert_raise(TypeError) {
seq3 = CvSeq.new(CvPoint2D32f).push(CvPoint2D32f.new(55.5, 66.6))
seq1.push(seq3)
}
end
def test_pop
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40))
point1 = seq1.pop
assert_equal(CvPoint, point1.class)
assert_equal(30, point1.x)
assert_equal(40, point1.y)
assert_equal(1, seq1.total)
assert_equal(CvPoint, seq1[0].class)
assert_equal(10, seq1[0].x)
assert_equal(20, seq1[0].y)
assert_nil(CvSeq.new(CvPoint).pop)
end
def test_clear
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40))
seq1.clear
assert_not_nil(seq1)
assert_equal(0, seq1.total)
end
def test_unshift
seq1 = CvSeq.new(CvPoint).unshift(CvPoint.new(10, 20), CvPoint.new(30, 40))
assert_equal(2, seq1.total)
assert_equal(CvPoint, seq1[0].class)
assert_equal(30, seq1[0].x)
assert_equal(40, seq1[0].y)
assert_equal(CvPoint, seq1[1].class)
assert_equal(10, seq1[1].x)
assert_equal(20, seq1[1].y)
seq2 = CvSeq.new(CvPoint).unshift(CvPoint.new(50, 60))
seq2.unshift(seq1)
assert_equal(3, seq2.total)
assert_equal(CvPoint, seq1[0].class)
assert_equal(30, seq1[0].x)
assert_equal(40, seq1[0].y)
assert_equal(CvPoint, seq1[1].class)
assert_equal(10, seq1[1].x)
assert_equal(20, seq1[1].y)
assert_equal(CvPoint, seq2[2].class)
assert_equal(50, seq2[2].x)
assert_equal(60, seq2[2].y)
assert_raise(TypeError) {
seq1.unshift(CvPoint2D32f.new(55.5, 66.6))
}
assert_raise(TypeError) {
seq3 = CvSeq.new(CvPoint2D32f).push(CvPoint2D32f.new(55.5, 66.6))
seq1.unshift(seq3)
}
end
def test_shift
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40))
point1 = seq1.shift
assert_equal(CvPoint, point1.class)
assert_equal(10, point1.x)
assert_equal(20, point1.y)
assert_equal(1, seq1.total)
assert_equal(CvPoint, seq1[0].class)
assert_equal(30, seq1[0].x)
assert_equal(40, seq1[0].y)
assert_nil(CvSeq.new(CvPoint).shift)
end
def test_first
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40), CvPoint.new(50, 60))
point1 = seq1.first
assert_equal(CvPoint, point1.class)
assert_equal(10, point1.x)
assert_equal(20, point1.y)
end
def test_last
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40), CvPoint.new(50, 60))
point1 = seq1.last
assert_equal(CvPoint, point1.class)
assert_equal(50, point1.x)
assert_equal(60, point1.y)
end
def test_each
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40), CvPoint.new(50, 60))
i = 0
seq1.each { |s|
assert_equal(CvPoint, s.class)
assert_equal(seq1[i].x, s.x)
assert_equal(seq1[i].y, s.y)
i += 1
}
assert_equal(3, i)
end
def test_each_index
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40), CvPoint.new(50, 60))
n = 0
seq1.each_index { |i|
assert_equal(n, i)
n += 1
}
assert_equal(3, n)
end
def test_insert
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40))
seq1.insert(1, CvPoint.new(50, 60))
assert_equal(3, seq1.total)
assert_equal(CvPoint, seq1[0].class)
assert_equal(10, seq1[0].x)
assert_equal(20, seq1[0].y)
assert_equal(CvPoint, seq1[1].class)
assert_equal(50, seq1[1].x)
assert_equal(60, seq1[1].y)
assert_equal(CvPoint, seq1[2].class)
assert_equal(30, seq1[2].x)
assert_equal(40, seq1[2].y)
end
def test_remove
seq1 = CvSeq.new(CvPoint).push(CvPoint.new(10, 20), CvPoint.new(30, 40), CvPoint.new(50, 60))
seq1.remove(1)
assert_equal(2, seq1.total)
assert_equal(CvPoint, seq1[0].class)
assert_equal(10, seq1[0].x)
assert_equal(20, seq1[0].y)
assert_equal(CvPoint, seq1[1].class)
assert_equal(50, seq1[1].x)
assert_equal(60, seq1[1].y)
end
def test_h_prev
flunk('FIXME: CvSeq#h_prev is not tested yet.')
end
def test_h_next
flunk('FIXME: CvSeq#h_next is not tested yet.')
end
def test_v_prev
flunk('FIXME: CvSeq#v_prev is not tested yet.')
end
def test_v_next
flunk('FIXME: CvSeq#v_next is not tested yet.')
end
end