mirror of
https://github.com/ruby-opencv/ruby-opencv
synced 2023-03-27 23:22:12 -04:00
287 lines
7.6 KiB
C++
287 lines
7.6 KiB
C++
/************************************************************
|
|
|
|
pointset.cpp -
|
|
|
|
$Author: lsxi $
|
|
|
|
Copyright (C) 2005-2006 Masakazu Yonekura
|
|
|
|
************************************************************/
|
|
#include "pointset.h"
|
|
/*
|
|
* Document-class: OpenCV::PointSet
|
|
*/
|
|
|
|
__NAMESPACE_BEGIN_OPENCV
|
|
__NAMESPACE_BEGIN_POINT_SET
|
|
|
|
VALUE module;
|
|
|
|
VALUE
|
|
rb_module()
|
|
{
|
|
return module;
|
|
}
|
|
|
|
void
|
|
define_ruby_module()
|
|
{
|
|
if (module)
|
|
return;
|
|
/*
|
|
* opencv = rb_define_module("OpenCV");
|
|
*
|
|
* note: this comment is used by rdoc.
|
|
*/
|
|
VALUE opencv = rb_module_opencv();
|
|
module = rb_define_module_under(opencv, "PointSet");
|
|
rb_define_method(module, "contour_area", RUBY_METHOD_FUNC(rb_contour_area), -1);
|
|
rb_define_method(module, "fit_ellipse2", RUBY_METHOD_FUNC(rb_fit_ellipse2), 0);
|
|
|
|
rb_define_method(module, "convex_hull2", RUBY_METHOD_FUNC(rb_convex_hull2), -1);
|
|
rb_define_method(module, "check_contour_convexity", RUBY_METHOD_FUNC(rb_check_contour_convexity), 0);
|
|
rb_define_alias(module, "convexity?", "check_contour_convexity");
|
|
rb_define_method(module, "convexity_defects", RUBY_METHOD_FUNC(rb_convexity_defects), 1);
|
|
rb_define_method(module, "min_area_rect2", RUBY_METHOD_FUNC(rb_min_area_rect2), 0);
|
|
rb_define_method(module, "min_enclosing_circle", RUBY_METHOD_FUNC(rb_min_enclosing_circle), 0);
|
|
}
|
|
|
|
/*
|
|
* call-seq:
|
|
* contour_area -> float
|
|
*
|
|
* Calculates area of the whole contour or contour section.
|
|
*
|
|
* note: Orientation of the contour affects the area sign, thus the method may return negative result.
|
|
*/
|
|
VALUE
|
|
rb_contour_area(int argc, VALUE *argv, VALUE self)
|
|
{
|
|
VALUE slice;
|
|
rb_scan_args(argc, argv, "01", &slice);
|
|
double area = 0;
|
|
try {
|
|
area = cvContourArea(CVARR(self), NIL_P(slice) ? CV_WHOLE_SEQ : VALUE_TO_CVSLICE(slice));
|
|
}
|
|
catch (cv::Exception& e) {
|
|
raise_cverror(e);
|
|
}
|
|
return rb_float_new(area);
|
|
}
|
|
|
|
/*
|
|
* call-seq:
|
|
* fit_ellipse2 -> cvbox2d
|
|
*
|
|
* Return fits ellipse to set of 2D points.
|
|
*/
|
|
VALUE
|
|
rb_fit_ellipse2(VALUE self)
|
|
{
|
|
CvBox2D box;
|
|
try {
|
|
box = cvFitEllipse2(CVARR(self));
|
|
}
|
|
catch (cv::Exception& e) {
|
|
raise_cverror(e);
|
|
}
|
|
return cCvBox2D::new_object(box);
|
|
}
|
|
|
|
/*
|
|
* call-seq:
|
|
* convex_hull2(<i>[orientation_clockwise = true]</i>) -> cvcontour
|
|
*
|
|
* Finds convex hull of 2D point set using Sklansky's algorithm.
|
|
*
|
|
* <i>orientation_clockwise</i>: Desired orientation of convex hull (true: clockwise, false: counter clockwise).
|
|
*/
|
|
VALUE
|
|
rb_convex_hull2(int argc, VALUE *argv, VALUE self)
|
|
{
|
|
VALUE clockwise, return_points;
|
|
rb_scan_args(argc, argv, "02", &clockwise, &return_points);
|
|
VALUE storage = cCvMemStorage::new_object();
|
|
CvSeq *hull = NULL;
|
|
int return_pts = TRUE_OR_FALSE(return_points, 1);
|
|
try {
|
|
hull = cvConvexHull2(CVSEQ(self), CVMEMSTORAGE(storage),
|
|
TRUE_OR_FALSE(clockwise, 1) ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE,
|
|
return_pts);
|
|
}
|
|
catch (cv::Exception& e) {
|
|
raise_cverror(e);
|
|
}
|
|
return cCvSeq::new_sequence(cCvContour::rb_class(), hull, cCvPoint::rb_class(), storage);
|
|
}
|
|
|
|
/*
|
|
* call-seq:
|
|
* check_contour_convexity -> true or false
|
|
*
|
|
* Tests whether the input contour is convex or not. The contour must be simple, i.e. without self-intersections.
|
|
*/
|
|
VALUE
|
|
rb_check_contour_convexity(VALUE self)
|
|
{
|
|
int convexity = 0;
|
|
try {
|
|
convexity = cvCheckContourConvexity(CVARR(self));
|
|
}
|
|
catch (cv::Exception& e) {
|
|
raise_cverror(e);
|
|
}
|
|
return convexity ? Qtrue : Qfalse;
|
|
}
|
|
|
|
/*
|
|
* call-seq:
|
|
* convexity_defects(<i>hull</i>) -> cvseq(include CvConvexityDefect)
|
|
*
|
|
* Finds convexity defects of contour.
|
|
*/
|
|
VALUE
|
|
rb_convexity_defects(VALUE self, VALUE hull)
|
|
{
|
|
CvSeq *defects = NULL;
|
|
CvSeq *hull_seq = CVSEQ_WITH_CHECK(hull);
|
|
CvMemStorage *stg = hull_seq->storage;
|
|
try {
|
|
defects = cvConvexityDefects(CVSEQ(self), hull_seq, stg);
|
|
}
|
|
catch (cv::Exception& e) {
|
|
raise_cverror(e);
|
|
}
|
|
// FIXME: This storage is shared with the argument "hull".
|
|
// This causes a severe problem that when "hull"'s memory is collected by GC, "defects"'s storage is
|
|
// also collected.
|
|
VALUE storage = Data_Wrap_Struct(cCvMemStorage::rb_class(), 0, cCvMemStorage::cvmemstorage_free, stg);
|
|
return cCvSeq::new_sequence(cCvSeq::rb_class(), defects, cCvConvexityDefect::rb_class(), storage);
|
|
}
|
|
|
|
/*
|
|
* call-seq:
|
|
* min_area_rect2 -> cvbox2d
|
|
*
|
|
* Finds circumscribed rectangle of minimal area for given 2D point set.
|
|
*/
|
|
VALUE
|
|
rb_min_area_rect2(VALUE self)
|
|
{
|
|
VALUE storage = cCvMemStorage::new_object();
|
|
CvBox2D rect;
|
|
try {
|
|
rect = cvMinAreaRect2(CVARR(self), CVMEMSTORAGE(storage));
|
|
}
|
|
catch (cv::Exception& e) {
|
|
raise_cverror(e);
|
|
}
|
|
return cCvBox2D::new_object(rect);
|
|
}
|
|
|
|
/*
|
|
* call-seq:
|
|
* min_enclosing_circle -> cvcircle32f
|
|
*
|
|
* Finds circumscribed circle of minimal area for given 2D point set.
|
|
*/
|
|
VALUE
|
|
rb_min_enclosing_circle(VALUE self)
|
|
{
|
|
VALUE circle = cCvCircle32f::rb_allocate(cCvCircle32f::rb_class());
|
|
int success = 0;
|
|
try {
|
|
success = cvMinEnclosingCircle(CVARR(self), &CVCIRCLE32F(circle)->center,
|
|
&CVCIRCLE32F(circle)->radius);
|
|
}
|
|
catch (cv::Exception& e) {
|
|
raise_cverror(e);
|
|
}
|
|
return success ? circle : Qnil;
|
|
}
|
|
|
|
VALUE
|
|
rb_calc_pgh(VALUE self)
|
|
{
|
|
/* not yet */
|
|
return Qnil;
|
|
}
|
|
|
|
__NAMESPACE_END_POINT_SET
|
|
|
|
int
|
|
CVPOINTS_FROM_POINT_SET(VALUE object, CvPoint **pointset)
|
|
{
|
|
VALUE storage;
|
|
CvSeq *seq = 0;
|
|
CvPoint2D32f p32;
|
|
if (rb_obj_is_kind_of(object, cCvSeq::rb_class())) {
|
|
if (CV_IS_SEQ_POINT_SET(CVSEQ(object))) {
|
|
*pointset = (CvPoint*)cvCvtSeqToArray(CVSEQ(object),
|
|
rb_cvAlloc(CVSEQ(object)->total * CVSEQ(object)->elem_size));
|
|
return CVSEQ(object)->total;
|
|
}
|
|
else {
|
|
rb_raise(rb_eTypeError, "sequence does not contain %s or %s.",
|
|
rb_class2name(cCvPoint::rb_class()), rb_class2name(cCvPoint2D32f::rb_class()));
|
|
}
|
|
}
|
|
else if (rb_obj_is_kind_of(object, cCvMat::rb_class())) {
|
|
/* to do */
|
|
rb_raise(rb_eNotImpError, "CvMat to CvSeq conversion not implemented.");
|
|
}
|
|
else if (rb_obj_is_kind_of(object, rb_cArray)) {
|
|
int len = RARRAY_LEN(object);
|
|
*pointset = (CvPoint*)rb_cvAlloc(len * sizeof(CvPoint));
|
|
ID id_x = rb_intern("x");
|
|
ID id_y = rb_intern("y");
|
|
for (int i = 0; i < len; ++i) {
|
|
(*pointset)[i].x = NUM2INT(rb_funcall(rb_ary_entry(object, i), id_x, 0));
|
|
(*pointset)[i].y = NUM2INT(rb_funcall(rb_ary_entry(object, i), id_y, 0));
|
|
}
|
|
return len;
|
|
}
|
|
else {
|
|
rb_raise(rb_eTypeError, "Can't convert CvSeq(PointSet).");
|
|
}
|
|
}
|
|
|
|
CvSeq*
|
|
VALUE_TO_POINT_SET(VALUE object)
|
|
{
|
|
CvSeq *seq = 0;
|
|
VALUE tmp, storage;
|
|
int length;
|
|
CvPoint2D32f p32;
|
|
if (rb_obj_is_kind_of(object, cCvSeq::rb_class())) {
|
|
seq = CVSEQ(object);
|
|
if (CV_IS_SEQ_POINT_SET(seq)) {
|
|
return seq;
|
|
}
|
|
else {
|
|
rb_raise(rb_eTypeError, "sequence is not contain %s or %s.", rb_class2name(cCvPoint::rb_class()), rb_class2name(cCvPoint2D32f::rb_class()));
|
|
}
|
|
}
|
|
else if (rb_obj_is_kind_of(object, cCvMat::rb_class())) {
|
|
/* to do */
|
|
rb_raise(rb_eNotImpError, "CvMat to CvSeq conversion not implemented.");
|
|
}
|
|
else if (rb_obj_is_kind_of(object, rb_cArray)) {
|
|
//pointset = cCvSeq::new_sequence(cCvSeq::rb_class(), )
|
|
length = RARRAY_LEN(object);
|
|
storage = cCvMemStorage::new_object();
|
|
seq = cvCreateSeq(CV_SEQ_POINT_SET, sizeof(CvSeq), sizeof(CvPoint), CVMEMSTORAGE(storage));
|
|
for (int i = 0; i < RARRAY_LEN(object); i++) {
|
|
p32.x = NUM2DBL(rb_funcall(rb_ary_entry(object, i), rb_intern("x"), 0));
|
|
p32.y = NUM2DBL(rb_funcall(rb_ary_entry(object, i), rb_intern("y"), 0));
|
|
cvSeqPush(seq, &p32);
|
|
}
|
|
tmp = cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvPoint2D32f::rb_class(), storage);
|
|
return seq;
|
|
}
|
|
else {
|
|
rb_raise(rb_eTypeError, "Can't convert CvSeq(PointSet).");
|
|
}
|
|
}
|
|
|
|
__NAMESPACE_END_OPENCV
|