diff --git a/.gitignore b/.gitignore index cb21917..8f220cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Eclipse .classpath .project +.cproject .settings/ # Intellij @@ -19,4 +20,5 @@ build/ CMakeFiles/ CMakeCache.txt *.cmake -Makefile \ No newline at end of file +Makefile +Debug/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 1190f9f..c6ed6de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ else() message(FATAL_ERROR "JNI not found.") endif() -find_package(PCL 1.8.1 REQUIRED) +find_package(PCL 1.9.1 REQUIRED) if (PCL_FOUND) message(STATUS "PCL found.") diff --git a/examples/sphere-detection/src/main/java/com/movlad/pcl/examples/SphereDetection.java b/examples/sphere-detection/src/main/java/com/movlad/pcl/examples/SphereDetection.java index ef0737e..8e77a82 100644 --- a/examples/sphere-detection/src/main/java/com/movlad/pcl/examples/SphereDetection.java +++ b/examples/sphere-detection/src/main/java/com/movlad/pcl/examples/SphereDetection.java @@ -8,114 +8,87 @@ import com.movlad.pcl.visualization.Visualizer3d; public class SphereDetection { - + static { // loading the native library in the main class - + System.loadLibrary("pcl_java"); } - + public static void main(String[] args) { - PointCloud3d noisySphere = createNoisySphere(); - SampleConsensusModelSphere sphereModel = new SampleConsensusModelSphere(noisySphere); - - /* - * In order to use a native object it needs to be created in the memory on the native side; - * the create() method does exactly that. - */ - - sphereModel.create(); - - RandomSampleConsensus ransac = new RandomSampleConsensus(sphereModel); - - ransac.create(); - ransac.setDistanceThreshold(.01f); - ransac.computeModel(0); - - PointCloud3d detectedSphere = ransac.getInliners(noisySphere); - - for (Point3d point : detectedSphere) { - point.setRGB((short) 255, (short) 0, (short) 0); - } - - Visualizer visualizer = new Visualizer3d(); - - visualizer.create(); - visualizer.setWindowName("PCL Java Sphere Detection Example"); - visualizer.setBackgroundColor(0.f, 0.f, 0.f); - visualizer.addCoordinateSystem(0.2, 0); - visualizer.addPointCloud(noisySphere, "noisy_sphere", 0); - visualizer.addPointCloud(detectedSphere, "detected_sphere", 0); - visualizer.setPointSize(2, "noisy_sphere"); - visualizer.setPointSize(3, "detected_sphere"); - - while (!visualizer.wasStopped()) { - visualizer.spinOnce(100, false); - - try { - Thread.sleep(100); - } catch (Exception e) { - e.printStackTrace(); + try (PointCloud3d noisySphere = createNoisySphere(); + SampleConsensusModelSphere sphereModel = new SampleConsensusModelSphere(noisySphere); + RandomSampleConsensus ransac = new RandomSampleConsensus(sphereModel)) { + ransac.setDistanceThreshold(.01f); + ransac.computeModel(0); + + try (PointCloud3d detectedSphere = ransac.getInliners(noisySphere)) { + for (Point3d point : detectedSphere) { + point.setRGB((short) 255, (short) 0, (short) 0); + } + + try (Visualizer visualizer = new Visualizer3d()) { + visualizer.setWindowName("PCL Java Sphere Detection Example"); + visualizer.setBackgroundColor(0.f, 0.f, 0.f); + visualizer.addCoordinateSystem(0.2, 0); + visualizer.addPointCloud(noisySphere, "noisy_sphere", 0); + visualizer.addPointCloud(detectedSphere, "detected_sphere", 0); + visualizer.setPointSize(2, "noisy_sphere"); + visualizer.setPointSize(3, "detected_sphere"); + + while (!visualizer.wasStopped()) { + visualizer.spinOnce(100, false); + + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + } + } } } - - /* - * All natively allocated objects must be freed from the memory using the dispose() method. - */ - - visualizer.dispose(); - detectedSphere.dispose(); - ransac.dispose(); - sphereModel.dispose(); - noisySphere.dispose(); } - + /** - * @return a point cloud in the shape of a sphere with some noisy points - * here and there + * @return a point cloud in the shape of a sphere with some noisy points here + * and there */ private static PointCloud3d createNoisySphere() { PointCloud3d noisySphere = new PointCloud3d(); - - noisySphere.create(); - + for (int i = 0; i < 500; i++) { - Point3d point = new Point3d(); - - point.create(); - point.setX(randomFloat(-1f, 1f)); - point.setY(randomFloat(-1f, 1f)); - - if (i % 5 == 0) { - point.setZ(randomFloat(-1f, 1f)); - } else if (i % 2 == 0) { - point.setZ((float)Math.sqrt(1 - (point.getX() * point.getX()) - (point.getY() * point.getY()))); - } else { - point.setZ((float) -Math.sqrt(1 - (point.getX() * point.getX()) - (point.getY() * point.getY()))); + + // Adding point to noisySphere will copy the reference, so point is closed + // in a try-with-resources block + try (Point3d point = new Point3d()) { + + point.setX(randomFloat(-1f, 1f)); + point.setY(randomFloat(-1f, 1f)); + + if (i % 5 == 0) { + point.setZ(randomFloat(-1f, 1f)); + } else if (i % 2 == 0) { + point.setZ((float) Math.sqrt(1 - (point.getX() * point.getX()) - (point.getY() * point.getY()))); + } else { + point.setZ((float) -Math.sqrt(1 - (point.getX() * point.getX()) - (point.getY() * point.getY()))); + } + + point.setRGB((short) 255, (short) 255, (short) 255); + + noisySphere.add(point); } - - point.setRGB((short)255, (short)255, (short)255); - - noisySphere.add(point); - - /* - * The reference to point created within the loop is not the same as the reference - * to the point within the noisySphere point cloud; as such it needs to be released - * at the end of each loop iteration. - */ - - point.dispose(); } - + return noisySphere; } - + /** * @param min is the minimum float that can be generated * @param max is the maximum float that can be generated * @return a float between min and max */ - private static float randomFloat(float min, float max) { + private static float randomFloat(float min, float max) { return (float) (min + Math.random() * (max - min)); } diff --git a/src/main/c/com_movlad_pcl_Matrix4.cpp b/src/main/c/com_movlad_pcl_Matrix4.cpp new file mode 100644 index 0000000..e0e1716 --- /dev/null +++ b/src/main/c/com_movlad_pcl_Matrix4.cpp @@ -0,0 +1,35 @@ +#include + +#include + +#include "handle.h" + +#include "com_movlad_pcl_Normal.h" + + +void Java_com_movlad_pcl_Matrix4_alloc(JNIEnv* env, jobject obj) { + Eigen::Matrix4d *matrix_ptr = new Eigen::Matrix4d(); + + set_handle(env, obj, matrix_ptr); +} + +void Java_com_movlad_pcl_Matrix4_dispose(JNIEnv* env, jobject obj) { + Eigen::Matrix4d *matrix_ptr = get_handle(env, obj); + + delete matrix_ptr; + + set_handle(env, obj, nullptr); +} + +jdouble Java_com_movlad_pcl_Matrix4_nGet(JNIEnv* env, jobject obj, jint r, jint c) { + Eigen::Matrix4d *matrix_ptr = get_handle(env, obj); + + return (jdouble) (*matrix_ptr)(r, c); +} + +void Java_com_movlad_pcl_Matrix4_nSet(JNIEnv* env, jobject obj, jint r, jint c, jdouble value) { + Eigen::Matrix4d *matrix_ptr = get_handle(env, obj); + + (*matrix_ptr)(r, c) = (double) value; +} + diff --git a/src/main/c/com_movlad_pcl_Matrix4.h b/src/main/c/com_movlad_pcl_Matrix4.h new file mode 100644 index 0000000..a6bb9e6 --- /dev/null +++ b/src/main/c/com_movlad_pcl_Matrix4.h @@ -0,0 +1,45 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_movlad_pcl_Matrix4 */ + +#ifndef _Included_com_movlad_pcl_Matrix4 +#define _Included_com_movlad_pcl_Matrix4 +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_movlad_pcl_Matrix4 + * Method: alloc + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Matrix4_alloc + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Matrix4 + * Method: dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Matrix4_dispose + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Matrix4 + * Method: nGet + * Signature: (II)D + */ +JNIEXPORT jdouble JNICALL Java_com_movlad_pcl_Matrix4_nGet + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_movlad_pcl_Matrix4 + * Method: nSet + * Signature: (IID)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Matrix4_nSet + (JNIEnv *, jobject, jint, jint, jdouble); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/main/c/com_movlad_pcl_Matrix4f.cpp b/src/main/c/com_movlad_pcl_Matrix4f.cpp new file mode 100644 index 0000000..6e91516 --- /dev/null +++ b/src/main/c/com_movlad_pcl_Matrix4f.cpp @@ -0,0 +1,35 @@ +#include + +#include + +#include "handle.h" + +#include "com_movlad_pcl_Normal.h" + + +void Java_com_movlad_pcl_Matrix4f_alloc(JNIEnv* env, jobject obj) { + Eigen::Matrix4f *matrix_ptr = new Eigen::Matrix4f(); + + set_handle(env, obj, matrix_ptr); +} + +void Java_com_movlad_pcl_Matrix4f_dispose(JNIEnv* env, jobject obj) { + Eigen::Matrix4f *matrix_ptr = get_handle(env, obj); + + delete matrix_ptr; + + set_handle(env, obj, nullptr); +} + +jfloat Java_com_movlad_pcl_Matrix4f_nGet(JNIEnv* env, jobject obj, jint r, jint c) { + Eigen::Matrix4f *matrix_ptr = get_handle(env, obj); + + return (jfloat) (*matrix_ptr)(r, c); +} + +void Java_com_movlad_pcl_Matrix4f_nSet(JNIEnv* env, jobject obj, jint r, jint c, jfloat value) { + Eigen::Matrix4f *matrix_ptr = get_handle(env, obj); + + (*matrix_ptr)(r, c) = (float) value; +} + diff --git a/src/main/c/com_movlad_pcl_Matrix4f.h b/src/main/c/com_movlad_pcl_Matrix4f.h new file mode 100644 index 0000000..c88f45c --- /dev/null +++ b/src/main/c/com_movlad_pcl_Matrix4f.h @@ -0,0 +1,45 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_movlad_pcl_Matrix4f */ + +#ifndef _Included_com_movlad_pcl_Matrix4f +#define _Included_com_movlad_pcl_Matrix4f +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_movlad_pcl_Matrix4f + * Method: alloc + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Matrix4f_alloc + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Matrix4f + * Method: dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Matrix4f_dispose + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Matrix4f + * Method: nGet + * Signature: (II)D + */ +JNIEXPORT jdouble JNICALL Java_com_movlad_pcl_Matrix4f_nGet + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_movlad_pcl_Matrix4f + * Method: nSet + * Signature: (IID)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Matrix4f_nSet + (JNIEnv *, jobject, jint, jint, jdouble); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/main/c/com_movlad_pcl_NormalCloud.cpp b/src/main/c/com_movlad_pcl_NormalCloud.cpp index 45c9c14..b3cf51b 100644 --- a/src/main/c/com_movlad_pcl_NormalCloud.cpp +++ b/src/main/c/com_movlad_pcl_NormalCloud.cpp @@ -1,3 +1,5 @@ +#include + #include "com_movlad_pcl_NormalCloud.h" #include "sptr_wrapper.h" #include "handle.h" @@ -35,7 +37,7 @@ void Java_com_movlad_pcl_NormalCloud_add(JNIEnv *env, jobject obj, jobject point void Java_com_movlad_pcl_NormalCloud_remove(JNIEnv *env, jobject obj, jobject point) { - throw "Not yet implemented."; + throw std::runtime_error("Not yet implemented."); } void Java_com_movlad_pcl_NormalCloud_clear(JNIEnv *env, jobject obj) @@ -58,4 +60,4 @@ jboolean Java_com_movlad_pcl_NormalCloud_isOrganized(JNIEnv *env, jobject obj) bool isOrganized = cloud_ptr->isOrganized(); return isOrganized; -} \ No newline at end of file +} diff --git a/src/main/c/com_movlad_pcl_Point3d.cpp b/src/main/c/com_movlad_pcl_Point3d.cpp index e36df8d..b1131bd 100644 --- a/src/main/c/com_movlad_pcl_Point3d.cpp +++ b/src/main/c/com_movlad_pcl_Point3d.cpp @@ -83,4 +83,4 @@ void Java_com_movlad_pcl_Point3d_setB(JNIEnv *env, jobject obj, jshort b) jfloat Java_com_movlad_pcl_Point3d_getRGB(JNIEnv *env, jobject obj) { return get_handle(env, obj)->rgb; -} \ No newline at end of file +} diff --git a/src/main/c/com_movlad_pcl_Point3di.cpp b/src/main/c/com_movlad_pcl_Point3di.cpp new file mode 100644 index 0000000..9b687d8 --- /dev/null +++ b/src/main/c/com_movlad_pcl_Point3di.cpp @@ -0,0 +1,61 @@ +#include + +#include "/usr/java/jdk-11.0.2/include/jni.h" +#include "handle.h" + +void Java_com_movlad_pcl_Point3di_alloc(JNIEnv *env, jobject obj) +{ + pcl::PointXYZI *pt_ptr = new pcl::PointXYZI(); + + set_handle(env, obj, pt_ptr); +} + +void Java_com_movlad_pcl_Point3di_dispose +(JNIEnv *env, jobject obj) +{ + pcl::PointXYZI *pt_ptr = get_handle(env, obj); + + delete pt_ptr; + + set_handle(env, obj, nullptr); +} + +jfloat Java_com_movlad_pcl_Point3di_getX(JNIEnv *env, jobject obj) +{ + return get_handle(env, obj)->x; +} + +void Java_com_movlad_pcl_Point3di_setX(JNIEnv *env, jobject obj, jfloat x) +{ + get_handle(env, obj)->x = x; +} + +jfloat Java_com_movlad_pcl_Point3di_getY(JNIEnv *env, jobject obj) +{ + return get_handle(env, obj)->y; +} + +void Java_com_movlad_pcl_Point3di_setY(JNIEnv *env, jobject obj, jfloat y) +{ + get_handle(env, obj)->y = y; +} + +jfloat Java_com_movlad_pcl_Point3di_getZ(JNIEnv *env, jobject obj) +{ + return get_handle(env, obj)->z; +} + +void Java_com_movlad_pcl_Point3di_setZ(JNIEnv *env, jobject obj, jfloat z) +{ + get_handle(env, obj)->z = z; +} + +jfloat Java_com_movlad_pcl_Point3di_getI(JNIEnv *env, jobject obj) +{ + return get_handle(env, obj)->intensity; +} + +void Java_com_movlad_pcl_Point3di_setI(JNIEnv *env, jobject obj, jfloat i) +{ + get_handle(env, obj)->intensity = i; +} diff --git a/src/main/c/com_movlad_pcl_Point3di.h b/src/main/c/com_movlad_pcl_Point3di.h new file mode 100644 index 0000000..18bbd77 --- /dev/null +++ b/src/main/c/com_movlad_pcl_Point3di.h @@ -0,0 +1,96 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#include "/usr/java/jdk-11.0.2/include/jni.h" +#include "/usr/java/jdk-11.0.2/include/linux/jni_md.h" + +/* Header for class com_movlad_pcl_Point3di */ + +#ifndef _Included_com_movlad_pcl_Point3di +#define _Included_com_movlad_pcl_Point3di +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_movlad_pcl_Point3di + * Method: alloc + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Point3di_alloc + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Point3di + * Method: dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Point3di_dispose + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Point3di + * Method: getX + * Signature: ()F + */ +JNIEXPORT jfloat JNICALL Java_com_movlad_pcl_Point3di_getX + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Point3di + * Method: setX + * Signature: (F)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Point3di_setX + (JNIEnv *, jobject, jfloat); + +/* + * Class: com_movlad_pcl_Point3di + * Method: getY + * Signature: ()F + */ +JNIEXPORT jfloat JNICALL Java_com_movlad_pcl_Point3di_getY + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Point3di + * Method: setY + * Signature: (F)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Point3di_setY + (JNIEnv *, jobject, jfloat); + +/* + * Class: com_movlad_pcl_Point3di + * Method: getZ + * Signature: ()F + */ +JNIEXPORT jfloat JNICALL Java_com_movlad_pcl_Point3di_getZ + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Point3di + * Method: setZ + * Signature: (F)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Point3di_setZ + (JNIEnv *, jobject, jfloat); + +/* + * Class: com_movlad_pcl_Point3dii + * Method: getI + * Signature: ()F + */ +JNIEXPORT jfloat JNICALL Java_com_movlad_pcl_Point3di_getI + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_Point3di + * Method: setI + * Signature: (F)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_Point3di_setI + (JNIEnv *, jobject, jfloat); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/main/c/com_movlad_pcl_PointCloud3d.cpp b/src/main/c/com_movlad_pcl_PointCloud3d.cpp index 145c77a..e8efa48 100644 --- a/src/main/c/com_movlad_pcl_PointCloud3d.cpp +++ b/src/main/c/com_movlad_pcl_PointCloud3d.cpp @@ -1,3 +1,5 @@ +#include + #include "com_movlad_pcl_PointCloud3d.h" #include "sptr_wrapper.h" @@ -34,7 +36,7 @@ void Java_com_movlad_pcl_PointCloud3d_add(JNIEnv *env, jobject obj, jobject poin void Java_com_movlad_pcl_PointCloud3d_remove(JNIEnv *env, jobject obj, jobject point) { - throw "Not yet implemented."; + throw std::runtime_error("Not yet implemented."); } void Java_com_movlad_pcl_PointCloud3d_clear(JNIEnv *env, jobject obj) @@ -57,4 +59,4 @@ jboolean Java_com_movlad_pcl_PointCloud3d_isOrganized(JNIEnv *env, jobject obj) bool isOrganized = cloud_ptr->isOrganized(); return isOrganized; -} \ No newline at end of file +} diff --git a/src/main/c/com_movlad_pcl_PointCloud3d.h b/src/main/c/com_movlad_pcl_PointCloud3d.h index 8d7b822..5eb4f30 100644 --- a/src/main/c/com_movlad_pcl_PointCloud3d.h +++ b/src/main/c/com_movlad_pcl_PointCloud3d.h @@ -26,7 +26,7 @@ JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3d_dispose /* * Class: com_movlad_pcl_PointCloud3d * Method: nGet - * Signature: (ILde/i3mainz/pcl/Point3d;)V + * Signature: (ILcom/movlad/pcl/Point3d;)V */ JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3d_nGet (JNIEnv *, jobject, jint, jobject); @@ -34,7 +34,7 @@ JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3d_nGet /* * Class: com_movlad_pcl_PointCloud3d * Method: add - * Signature: (Lde/i3mainz/pcl/Point3d;)V + * Signature: (Lcom/movlad/pcl/Point3d;)V */ JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3d_add (JNIEnv *, jobject, jobject); @@ -42,7 +42,7 @@ JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3d_add /* * Class: com_movlad_pcl_PointCloud3d * Method: remove - * Signature: (Lde/i3mainz/pcl/Point3d;)V + * Signature: (Lcom/movlad/pcl/Point3d;)V */ JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3d_remove (JNIEnv *, jobject, jobject); diff --git a/src/main/c/com_movlad_pcl_PointCloud3di.cpp b/src/main/c/com_movlad_pcl_PointCloud3di.cpp new file mode 100644 index 0000000..2c203e6 --- /dev/null +++ b/src/main/c/com_movlad_pcl_PointCloud3di.cpp @@ -0,0 +1,62 @@ +#include + +#include "com_movlad_pcl_PointCloud3di.h" +#include "sptr_wrapper.h" + +#include +#include + +void Java_com_movlad_pcl_PointCloud3di_alloc(JNIEnv *env, jobject obj) +{ + sptr_wrapper> *cloud_ptr_w = + new sptr_wrapper>(); + + cloud_ptr_w->instantiate(env, obj); +} + +void Java_com_movlad_pcl_PointCloud3di_dispose +(JNIEnv *env, jobject obj) +{ + sptr_wrapper>::dispose(env, obj); +} + +void Java_com_movlad_pcl_PointCloud3di_nGet(JNIEnv *env, jobject obj, jint i, jobject point) +{ + pcl::PointCloud::Ptr cloud_ptr = sptr_wrapper>::get_sptr(env, obj); + + set_handle(env, point, &(cloud_ptr->at(i))); +} + +void Java_com_movlad_pcl_PointCloud3di_add(JNIEnv *env, jobject obj, jobject point) +{ + pcl::PointCloud::Ptr cloud_ptr = sptr_wrapper>::get_sptr(env, obj); + + cloud_ptr->push_back(*get_handle(env, point)); +} + +void Java_com_movlad_pcl_PointCloud3di_remove(JNIEnv *env, jobject obj, jobject point) +{ + throw std::runtime_error("Not yet implemented."); +} + +void Java_com_movlad_pcl_PointCloud3di_clear(JNIEnv *env, jobject obj) +{ + pcl::PointCloud::Ptr cloud_ptr = sptr_wrapper>::get_sptr(env, obj); + + cloud_ptr->clear(); +} + +jint Java_com_movlad_pcl_PointCloud3di_size(JNIEnv *env, jobject obj) +{ + pcl::PointCloud::Ptr cloud_ptr = sptr_wrapper>::get_sptr(env, obj); + + return cloud_ptr->size(); +} + +jboolean Java_com_movlad_pcl_PointCloud3di_isOrganized(JNIEnv *env, jobject obj) +{ + pcl::PointCloud::Ptr cloud_ptr = sptr_wrapper>::get_sptr(env, obj); + bool isOrganized = cloud_ptr->isOrganized(); + + return isOrganized; +} diff --git a/src/main/c/com_movlad_pcl_PointCloud3di.h b/src/main/c/com_movlad_pcl_PointCloud3di.h new file mode 100644 index 0000000..61cefe5 --- /dev/null +++ b/src/main/c/com_movlad_pcl_PointCloud3di.h @@ -0,0 +1,77 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_movlad_pcl_PointCloud3di */ + +#ifndef _Included_com_movlad_pcl_PointCloud3di +#define _Included_com_movlad_pcl_PointCloud3di +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: alloc + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3di_alloc + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3di_dispose + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: nGet + * Signature: (ILde/i3mainz/pcl/Point3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3di_nGet + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: add + * Signature: (Lde/i3mainz/pcl/Point3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3di_add + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: remove + * Signature: (Lde/i3mainz/pcl/Point3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3di_remove + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: clear + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_PointCloud3di_clear + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: size + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_movlad_pcl_PointCloud3di_size + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_PointCloud3di + * Method: isOrganized + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_movlad_pcl_PointCloud3di_isOrganized + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/main/c/com_movlad_pcl_SampleConsensus.cpp b/src/main/c/com_movlad_pcl_SampleConsensus.cpp index 0e90fca..529006c 100644 --- a/src/main/c/com_movlad_pcl_SampleConsensus.cpp +++ b/src/main/c/com_movlad_pcl_SampleConsensus.cpp @@ -11,7 +11,7 @@ void Java_com_movlad_pcl_SampleConsensus_nSetSampleConsensusModel pcl::SampleConsensus::Ptr sac_ptr = sptr_wrapper>::get_sptr(env, obj); pcl::SampleConsensusModel::Ptr model_ptr - = sptr_wrapper>::get_sptr(env, model);; + = sptr_wrapper>::get_sptr(env, model); sac_ptr->setSampleConsensusModel(model_ptr); } diff --git a/src/main/c/com_movlad_pcl_registration_GeneralizedIterativeClosestPoint.cpp b/src/main/c/com_movlad_pcl_registration_GeneralizedIterativeClosestPoint.cpp new file mode 100644 index 0000000..872a024 --- /dev/null +++ b/src/main/c/com_movlad_pcl_registration_GeneralizedIterativeClosestPoint.cpp @@ -0,0 +1,98 @@ +#include + +#include "sptr_wrapper.h" + +#include +#include + +#include + +void Java_com_movlad_pcl_GeneralizedIterativeClosestPoint_alloc(JNIEnv *env, jobject obj) { + pcl::GeneralizedIterativeClosestPoint *reg_ptr = + new pcl::GeneralizedIterativeClosestPoint; + + set_handle(env, obj, reg_ptr); +} + +void Java_com_movlad_pcl_GeneralizedIterativeClosestPoint_dispose(JNIEnv *env, jobject obj) { + pcl::GeneralizedIterativeClosestPoint *reg_ptr = get_handle< + pcl::GeneralizedIterativeClosestPoint>(env, obj); + + delete reg_ptr; + + set_handle>(env, obj, nullptr); +} + +void Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setInputSource(JNIEnv *env, jobject obj, + jobject input_source) { + pcl::GeneralizedIterativeClosestPoint *reg_ptr = get_handle< + pcl::GeneralizedIterativeClosestPoint>(env, obj); + pcl::PointCloud::ConstPtr input_source_ptr( + sptr_wrapper>::get_sptr(env, input_source)); + + reg_ptr->setInputSource(input_source_ptr); +} + +void Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setInputTarget(JNIEnv *env, jobject obj, + jobject input_target) { + pcl::GeneralizedIterativeClosestPoint *reg_ptr = get_handle< + pcl::GeneralizedIterativeClosestPoint>(env, obj); + pcl::PointCloud::ConstPtr input_target_ptr( + sptr_wrapper>::get_sptr(env, input_target)); + + reg_ptr->setInputSource(input_target_ptr); +} + +void Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setMaximumIterations(JNIEnv *env, + jobject obj, jint nr_iterations) { + pcl::GeneralizedIterativeClosestPoint *reg_ptr = get_handle< + pcl::GeneralizedIterativeClosestPoint>(env, obj); + + reg_ptr->setMaximumIterations(nr_iterations); +} + +void Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setRotationEpsilon(JNIEnv *env, jobject obj, + jdouble rotationEpsilon) { + pcl::GeneralizedIterativeClosestPoint *reg_ptr = get_handle< + pcl::GeneralizedIterativeClosestPoint>(env, obj); + + reg_ptr->setRotationEpsilon(rotationEpsilon); +} + +void Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_estimateRigidTransformationBFGS(JNIEnv *env, + jobject obj, jobject input_source, jintArray input_source_idxs, jobject input_target, + jintArray input_target_idxs, jobject xform_out) { + pcl::GeneralizedIterativeClosestPoint *reg_ptr = get_handle< + pcl::GeneralizedIterativeClosestPoint>(env, obj); + + // TODO: is this needed? + Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setInputSource(env, obj, input_source); + Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setInputTarget(env, obj, input_target); + + std::vector indices_source; + int input_size = env->GetArrayLength(input_source_idxs); + indices_source.resize(input_size); + jint *p_input_source_idxs = env->GetIntArrayElements(input_source_idxs, 0); + for (int i = 0; i < input_size; i++) { + indices_source.push_back(p_input_source_idxs[i]); + } + env->ReleaseIntArrayElements(input_source_idxs, p_input_source_idxs, 0); + + std::vector indices_target; + int target_size = env->GetArrayLength(input_target_idxs); + indices_target.resize(target_size); + jint *p_input_target_idxs = env->GetIntArrayElements(input_target_idxs, 0); + for (int i = 0; i < target_size; i++) { + indices_target.push_back(p_input_target_idxs[i]); + } + env->ReleaseIntArrayElements(input_target_idxs, p_input_target_idxs, 0); + + pcl::PointCloud::ConstPtr input_source_ptr( + sptr_wrapper>::get_sptr(env, input_source)); + pcl::PointCloud::ConstPtr input_target_ptr( + sptr_wrapper>::get_sptr(env, input_target)); + boost::shared_ptr xform_out_ptr = sptr_wrapper::get_sptr(env, xform_out); + + reg_ptr->estimateRigidTransformationBFGS(*input_source_ptr, indices_source, *input_target_ptr, indices_target, + *xform_out_ptr); +} diff --git a/src/main/c/com_movlad_pcl_registration_GeneralizedIterativeClosestPoint.h b/src/main/c/com_movlad_pcl_registration_GeneralizedIterativeClosestPoint.h new file mode 100644 index 0000000..abc759b --- /dev/null +++ b/src/main/c/com_movlad_pcl_registration_GeneralizedIterativeClosestPoint.h @@ -0,0 +1,69 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_movlad_pcl_registration_GeneralizedIterativeClosestPoint */ + +#ifndef _Included_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint +#define _Included_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_movlad_pcl_registration_GeneralizedIterativeClosestPoint + * Method: alloc + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_alloc + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_registration_GeneralizedIterativeClosestPoint + * Method: dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_dispose + (JNIEnv *, jobject); + +/* + * Class: com_movlad_pcl_registration_GeneralizedIterativeClosestPoint + * Method: setInputSource + * Signature: (Lcom/movlad/pcl/PointCloud3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setInputSource + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_registration_GeneralizedIterativeClosestPoint + * Method: setInputTarget + * Signature: (Lcom/movlad/pcl/PointCloud3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setInputTarget + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_registration_GeneralizedIterativeClosestPoint + * Method: setMaximumIterations + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setMaximumIterations + (JNIEnv *, jobject, jint); + +/* + * Class: com_movlad_pcl_registration_GeneralizedIterativeClosestPoint + * Method: setRotationEpsilon + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_setRotationEpsilon + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_movlad_pcl_registration_GeneralizedIterativeClosestPoint + * Method: estimateRigidTransformationBFGS + * Signature: (Lcom/movlad/pcl/PointCloud3d;[ILcom/movlad/pcl/PointCloud3d;[ILcom/movlad/pcl/Matrix4;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_GeneralizedIterativeClosestPoint_estimateRigidTransformationBFGS + (JNIEnv *, jobject, jobject, jintArray, jobject, jintArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/main/c/com_movlad_pcl_registration_IterativeClosestPoint.cpp b/src/main/c/com_movlad_pcl_registration_IterativeClosestPoint.cpp new file mode 100644 index 0000000..f1424af --- /dev/null +++ b/src/main/c/com_movlad_pcl_registration_IterativeClosestPoint.cpp @@ -0,0 +1,101 @@ +#include + +#include "sptr_wrapper.h" + +#include +#include + +#include + +void Java_com_movlad_pcl_IterativeClosestPoint_alloc(JNIEnv *env, jobject obj) { + pcl::IterativeClosestPoint *reg_ptr = new pcl::IterativeClosestPoint< + pcl::PointXYZRGB, pcl::PointXYZRGB>; + + set_handle(env, obj, reg_ptr); +} + +void Java_com_movlad_pcl_IterativeClosestPoint_dispose(JNIEnv *env, jobject obj) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + + delete reg_ptr; + + set_handle>(env, obj, nullptr); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_setInputSource(JNIEnv *env, jobject obj, + jobject input_source) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + pcl::PointCloud::ConstPtr input_source_ptr( + sptr_wrapper>::get_sptr(env, input_source)); + + reg_ptr->setInputSource(input_source_ptr); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_setInputTarget(JNIEnv *env, jobject obj, + jobject input_target) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + pcl::PointCloud::ConstPtr input_target_ptr( + sptr_wrapper>::get_sptr(env, input_target)); + + reg_ptr->setInputSource(input_target_ptr); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_setMaximumIterations(JNIEnv *env, jobject obj, + jint nr_iterations) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + + reg_ptr->setMaximumIterations(nr_iterations); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_setMaxCorrespondenceDistance(JNIEnv *env, jobject obj, + jdouble distance_threshold) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + + reg_ptr->setMaxCorrespondenceDistance(distance_threshold); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_setTransformationEpsilon(JNIEnv *env, jobject obj, + jdouble epsilon) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + + reg_ptr->setTransformationEpsilon(epsilon); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_setEuclideanFitnessEpsilon(JNIEnv *env, jobject obj, + jdouble epsilon) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + + reg_ptr->setEuclideanFitnessEpsilon(epsilon); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_align(JNIEnv *env, jobject obj, jobject output_cloud) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + boost::shared_ptr> output_cloud_ptr = sptr_wrapper>::get_sptr(env, output_cloud); + + reg_ptr->align(*output_cloud_ptr.get()); +} + +void Java_com_movlad_pcl_registration_IterativeClosestPoint_getFinalTransformation(JNIEnv *env, jobject obj, + jobject xform_out) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + boost::shared_ptr xform_out_ptr = sptr_wrapper::get_sptr(env, xform_out); + + Eigen::Matrix4f final_xform = reg_ptr->getFinalTransformation(); + *xform_out_ptr = final_xform; +} + +jboolean Java_com_movlad_pcl_registration_IterativeClosestPoint_hasConverged(JNIEnv *env, jobject obj) { + pcl::IterativeClosestPoint *reg_ptr = get_handle< + pcl::IterativeClosestPoint>(env, obj); + + return reg_ptr->hasConverged(); +} diff --git a/src/main/c/com_movlad_pcl_registration_IterativeClosestPoint.h b/src/main/c/com_movlad_pcl_registration_IterativeClosestPoint.h new file mode 100644 index 0000000..03cc99a --- /dev/null +++ b/src/main/c/com_movlad_pcl_registration_IterativeClosestPoint.h @@ -0,0 +1,85 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_movlad_pcl_registration_IterativeClosestPoint */ + +#ifndef _Included_com_movlad_pcl_registration_IterativeClosestPoint +#define _Included_com_movlad_pcl_registration_IterativeClosestPoint +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: setInputSource + * Signature: (Lcom/movlad/pcl/PointCloud3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_setInputSource + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: setInputTarget + * Signature: (Lcom/movlad/pcl/PointCloud3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_setInputTarget + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: setMaximumIterations + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_setMaximumIterations + (JNIEnv *, jobject, jint); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: setMaxCorrespondenceDistance + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_setMaxCorrespondenceDistance + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: setTransformationEpsilon + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_setTransformationEpsilon + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: setEuclideanFitnessEpsilon + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_setEuclideanFitnessEpsilon + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: align + * Signature: (Lcom/movlad/pcl/PointCloud3d;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_align + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: getFinalTransformation + * Signature: (Lcom/movlad/pcl/Matrix4;)V + */ +JNIEXPORT void JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_getFinalTransformation + (JNIEnv *, jobject, jobject); + +/* + * Class: com_movlad_pcl_registration_IterativeClosestPoint + * Method: hasConverged + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_movlad_pcl_registration_IterativeClosestPoint_hasConverged + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/main/c/com_movlad_pcl_visualization_Visualizer.cpp b/src/main/c/com_movlad_pcl_visualization_Visualizer.cpp index 45e1289..8f15955 100644 --- a/src/main/c/com_movlad_pcl_visualization_Visualizer.cpp +++ b/src/main/c/com_movlad_pcl_visualization_Visualizer.cpp @@ -18,7 +18,7 @@ void Java_com_movlad_pcl_visualization_Visualizer_dispose sptr_wrapper::dispose(env, obj); } -void Java_com_movlad_pcl_visualization_Visualizer_close +void Java_com_movlad_pcl_visualization_Visualizer_stop (JNIEnv *env, jobject obj) { pcl::visualization::PCLVisualizer::Ptr vis_ptr = @@ -115,7 +115,7 @@ void Java_com_movlad_pcl_visualization_Visualizer_addCoordinateSystem__DI pcl::visualization::PCLVisualizer::Ptr vis_ptr = sptr_wrapper::get_sptr(env, obj); - vis_ptr->addCoordinateSystem(scale, viewport); + vis_ptr->addCoordinateSystem(scale, "viewport", viewport); } void Java_com_movlad_pcl_visualization_Visualizer_addCoordinateSystem__DLjava_lang_String_2I @@ -135,7 +135,7 @@ void Java_com_movlad_pcl_visualization_Visualizer_removeCoordinateSystem__I pcl::visualization::PCLVisualizer::Ptr vis_ptr = sptr_wrapper::get_sptr(env, obj); - vis_ptr->removeCoordinateSystem(viewport); + vis_ptr->removeCoordinateSystem("viewport", viewport); } void Java_com_movlad_pcl_visualization_Visualizer_removeCoordinateSystem__Ljava_lang_String_2I diff --git a/src/main/c/com_movlad_pcl_visualization_Visualizer.h b/src/main/c/com_movlad_pcl_visualization_Visualizer.h index 8f4396a..a2186f2 100644 --- a/src/main/c/com_movlad_pcl_visualization_Visualizer.h +++ b/src/main/c/com_movlad_pcl_visualization_Visualizer.h @@ -28,7 +28,7 @@ JNIEXPORT void JNICALL Java_com_movlad_pcl_visualization_Visualizer_dispose * Method: close * Signature: ()V */ -JNIEXPORT void JNICALL Java_com_movlad_pcl_visualization_Visualizer_close +JNIEXPORT void JNICALL Java_com_movlad_pcl_visualization_Visualizer_dispose (JNIEnv *, jobject); /* diff --git a/src/main/c/handle.h b/src/main/c/handle.h index 2695f04..2abd380 100644 --- a/src/main/c/handle.h +++ b/src/main/c/handle.h @@ -1,17 +1,41 @@ +#include #include #ifndef HANDLE_H #define HANDLE_H -inline jfieldID get_handle_field(JNIEnv *env, jobject obj) -{ - jclass cls = env->GetObjectClass(obj); +// Class reference and field id are cached in static fields, so get_handle +// and set_handle can only be used with one type parameter per source file +// (which is the standard usage for JNI anyway -- one C++ source file +// handles one Java class). +static jclass cls = 0; +static jobject cls_ref; +static jfieldID fid; - return env->GetFieldID(cls, "handle", "J"); +inline jfieldID get_handle_field(JNIEnv *env, jobject obj) +{ + if (cls == 0) { + cls = env->GetObjectClass(obj); + if (cls == 0) { + throw std::runtime_error("Could not get object class"); + } + // Hold global ref to class -- see: + // http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/refs.html + // Note that this will disable unloading of the class until the global ref is freed. + cls_ref = env->NewGlobalRef(cls); + if (cls_ref == 0) { + throw std::runtime_error("Could not allocate new global ref for class"); + } + fid = env->GetFieldID(cls, "handle", "J"); + if (fid == 0) { + throw std::runtime_error("Could not get id for 'handle' field"); + } + } + return fid; } template -inline T *get_handle(JNIEnv *env, jobject obj) +inline T *get_handle(JNIEnv *env, jobject obj) { jlong handle = env->GetLongField(obj, get_handle_field(env, obj)); @@ -19,11 +43,11 @@ inline T *get_handle(JNIEnv *env, jobject obj) } template -inline void set_handle(JNIEnv *env, jobject obj, T *ptr) +inline void set_handle(JNIEnv *env, jobject obj, T *ptr) { jlong handle = reinterpret_cast(ptr); env->SetLongField(obj, get_handle_field(env, obj), handle); } -#endif \ No newline at end of file +#endif diff --git a/src/main/c/sptr_wrapper.h b/src/main/c/sptr_wrapper.h index 210ce1c..7671910 100644 --- a/src/main/c/sptr_wrapper.h +++ b/src/main/c/sptr_wrapper.h @@ -32,7 +32,7 @@ class sptr_wrapper void set_from_sptr(boost::shared_ptr sptr) { - this.sptr = sptr; + this->sptr = sptr; } /// \brief{Sets the address of \code{this} wrapper as a handle for a java object within a JNI environment.} @@ -47,18 +47,31 @@ class sptr_wrapper return boost::reinterpret_pointer_cast(this); } - boost::shared_ptr get_sptr() const - { - return sptr; - } + boost::shared_ptr get_sptr() const + { + return sptr; + } - /// @param env The JNI environment. - /// @param java_instance The object for which to find the corresponding wrapper. - // \returns{the \code{shared_ptr} associated to a Java instance within a JNI environment.} - static boost::shared_ptr get_sptr(JNIEnv *env, jobject java_instance) - { - return get_wrapper(env, java_instance)->get_sptr(); - } + void set_sptr(boost::shared_ptr new_sptr_value) const + { + sptr = new_sptr_value; + } + + /// @param env The JNI environment. + /// @param java_instance The object for which to find the corresponding wrapper. + // \returns{the \code{shared_ptr} associated to a Java instance within a JNI environment.} + static boost::shared_ptr get_sptr(JNIEnv *env, jobject java_instance) + { + return get_wrapper(env, java_instance)->get_sptr(); + } + + /// @param env The JNI environment. + /// @param java_instance The object for which to find the corresponding wrapper. + // \returns{the \code{shared_ptr} associated to a Java instance within a JNI environment.} + static void get_sptr(JNIEnv *env, jobject java_instance, boost::shared_ptr ptr) + { + get_wrapper(env, java_instance)->set_sptr(ptr); + } /// @param env The JNI environment. /// @param java_instance The object for which to find the corresponding wrapper. @@ -76,4 +89,4 @@ class sptr_wrapper set_handle>(env, java_instance, nullptr); } -}; \ No newline at end of file +}; diff --git a/src/main/java/com/movlad/pcl/Matrix4.java b/src/main/java/com/movlad/pcl/Matrix4.java new file mode 100644 index 0000000..ec54de6 --- /dev/null +++ b/src/main/java/com/movlad/pcl/Matrix4.java @@ -0,0 +1,73 @@ +package com.movlad.pcl; + +import com.movlad.pcl.math.Comparison; +import com.movlad.pcl.nat.NativeObject; + +/** + * A 4x4 transform matrix with 64-bit double components. + */ +public class Matrix4 extends NativeObject implements Cloneable { + + @Override + protected final native void alloc(); + + @Override + protected final native void dispose(); + + private final native double nGet(int r, int c); + + private final native void nSet(int r, int c, double value); + + public double get(int r, int c) { + if (r < 0 || r > 3 || c < 0 || c > 3) { + throw new ArrayIndexOutOfBoundsException(); + } + return nGet(r, c); + } + + @Override + public Matrix4 clone() { + Matrix4 clone = new Matrix4(); + for (int r = 0; r < 4; r++) { + for (int c = 0; c < 4; c++) { + clone.nSet(r, c, get(r, c)); + } + } + return clone; + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } else if (!(object instanceof Matrix4)) { + return false; + } + Matrix4 other = (Matrix4) object; + for (int r = 0; r < 4; r++) { + for (int c = 0; c < 4; c++) { + if (!Comparison.areEqualDouble(get(r, c), other.get(r, c))) { + return false; + } + } + } + return true; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + for (int r = 0; r < 4; r++) { + buf.append(r == 0 ? "[[" : " ["); + for (int c = 0; c < 4; c++) { + if (c > 0) { + buf.append(", "); + } + buf.append(get(r, c)); + } + buf.append(r < 3 ? "],\n" : "]]"); + } + return buf.toString(); + } + +} diff --git a/src/main/java/com/movlad/pcl/Matrix4f.java b/src/main/java/com/movlad/pcl/Matrix4f.java new file mode 100644 index 0000000..070f4fd --- /dev/null +++ b/src/main/java/com/movlad/pcl/Matrix4f.java @@ -0,0 +1,73 @@ +package com.movlad.pcl; + +import com.movlad.pcl.math.Comparison; +import com.movlad.pcl.nat.NativeObject; + +/** + * A 4x4 transform matrix with 32-bit float components. + */ +public class Matrix4f extends NativeObject implements Cloneable { + + @Override + protected final native void alloc(); + + @Override + protected final native void dispose(); + + private final native float nGet(int r, int c); + + private final native void nSet(int r, int c, float value); + + public float get(int r, int c) { + if (r < 0 || r > 3 || c < 0 || c > 3) { + throw new ArrayIndexOutOfBoundsException(); + } + return nGet(r, c); + } + + @Override + public Matrix4f clone() { + Matrix4f clone = new Matrix4f(); + for (int r = 0; r < 4; r++) { + for (int c = 0; c < 4; c++) { + clone.nSet(r, c, get(r, c)); + } + } + return clone; + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } else if (!(object instanceof Matrix4f)) { + return false; + } + Matrix4f other = (Matrix4f) object; + for (int r = 0; r < 4; r++) { + for (int c = 0; c < 4; c++) { + if (!Comparison.areEqualDouble(get(r, c), other.get(r, c))) { + return false; + } + } + } + return true; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + for (int r = 0; r < 4; r++) { + buf.append(r == 0 ? "[[" : " ["); + for (int c = 0; c < 4; c++) { + if (c > 0) { + buf.append(", "); + } + buf.append(get(r, c)); + } + buf.append(r < 3 ? "],\n" : "]]"); + } + return buf.toString(); + } + +} diff --git a/src/main/java/com/movlad/pcl/Normal.java b/src/main/java/com/movlad/pcl/Normal.java index 596db6f..03255ae 100644 --- a/src/main/java/com/movlad/pcl/Normal.java +++ b/src/main/java/com/movlad/pcl/Normal.java @@ -11,24 +11,24 @@ public class Normal extends NativeObject implements Point, Cloneable { @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); - public native float getX(); + public final native float getX(); - public native void setX(float x); + public final native void setX(float x); - public native float getY(); + public final native float getY(); - public native void setY(float y); + public final native void setY(float y); - public native float getZ(); + public final native float getZ(); - public native void setZ(float z); + public final native void setZ(float z); - public native float getCurvature(); + public final native float getCurvature(); public void setComponents(float x, float y, float z) { setX(x); setY(y); setZ(z); @@ -38,8 +38,6 @@ public void setComponents(float x, float y, float z) { public Normal clone() { Normal clone = new Normal(); - clone.create(); - clone.setComponents(getX(), getY(), getZ()); return clone; @@ -47,6 +45,11 @@ public Normal clone() { @Override public boolean equals(Object object) { + if (object == this) { + return true; + } else if (!(object instanceof Normal)) { + return false; + } Normal normal = (Normal) object; return Comparison.areEqualFloat(getX(), normal.getX(), 0.5f) diff --git a/src/main/java/com/movlad/pcl/NormalCloud.java b/src/main/java/com/movlad/pcl/NormalCloud.java index 675ef8f..b59beb7 100644 --- a/src/main/java/com/movlad/pcl/NormalCloud.java +++ b/src/main/java/com/movlad/pcl/NormalCloud.java @@ -6,10 +6,10 @@ public class NormalCloud extends PointCloud { @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); @Override public Normal get(int i) { @@ -24,27 +24,26 @@ public Normal get(int i) { protected native void nGet(int i, Normal point); @Override - public native void add(Normal point); + public final native void add(Normal point); @Override - public native void remove(Normal point); + public final native void remove(Normal point); @Override - public native void clear(); + public final native void clear(); @Override - public native int size(); + public final native int size(); @Override - public native boolean isOrganized(); + public final native boolean isOrganized(); @Override public NormalCloud clone() { NormalCloud clone = new NormalCloud(); - clone.create(); - for (Normal point : this) { + @SuppressWarnings("resource") Normal pointClone = point.clone(); clone.add(pointClone); diff --git a/src/main/java/com/movlad/pcl/Point2d.java b/src/main/java/com/movlad/pcl/Point2d.java index d42ec9a..81ca03b 100644 --- a/src/main/java/com/movlad/pcl/Point2d.java +++ b/src/main/java/com/movlad/pcl/Point2d.java @@ -11,10 +11,10 @@ public class Point2d extends NativeObject implements Point, Cloneable { @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); public final native float getX(); @@ -33,8 +33,6 @@ public final void setCoordinates(float x, float y) { public Point2d clone() { Point2d clone = new Point2d(); - clone.alloc(); - clone.setCoordinates(getX(), getY()); return clone; @@ -42,9 +40,14 @@ public Point2d clone() { @Override public boolean equals(Object object) { + if (object == this) { + return true; + } else if (!(object instanceof Point2d)) { + return false; + } Point2d point = (Point2d) object; - return Comparison.areEqualFloat(getX(), point.getX(), 0.05f) && Comparison.areEqualFloat(getY(), point.getY(), 0.05f); + return Comparison.areEqualFloat(getX(), point.getX()) && Comparison.areEqualFloat(getY(), point.getY()); } @Override diff --git a/src/main/java/com/movlad/pcl/Point3d.java b/src/main/java/com/movlad/pcl/Point3d.java index 8a4c4e5..ca08f1a 100644 --- a/src/main/java/com/movlad/pcl/Point3d.java +++ b/src/main/java/com/movlad/pcl/Point3d.java @@ -13,22 +13,22 @@ public class Point3d extends NativeObject implements Point, Cloneable { @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); public final native float getX(); - public native void setX(float x); + public final native void setX(float x); - public native float getY(); + public final native float getY(); - public native void setY(float y); + public final native void setY(float y); - public native float getZ(); + public final native float getZ(); - public native void setZ(float z); + public final native void setZ(float z); public void setCoordinates(float x, float y, float z) { setX(x); setY(y); setZ(z); @@ -56,8 +56,6 @@ public void setRGB(short r, short g, short b) { public Point3d clone() { Point3d clone = new Point3d(); - clone.create(); - clone.setCoordinates(getX(), getY(), getZ()); clone.setRGB(getR(), getG(), getB()); @@ -66,11 +64,16 @@ public Point3d clone() { @Override public boolean equals(Object object) { - Point3d point = (Point3d)object; + if (object == this) { + return true; + } else if (!(object instanceof Point3d)) { + return false; + } + Point3d point = (Point3d) object; - return Comparison.areEqualFloat(getX(), point.getX(), 0.1f) && - Comparison.areEqualFloat(getY(), point.getY(), 0.1f) && - Comparison.areEqualFloat(getZ(), point.getZ(), 0.1f) && + return Comparison.areEqualFloat(getX(), point.getX()) && + Comparison.areEqualFloat(getY(), point.getY()) && + Comparison.areEqualFloat(getZ(), point.getZ()) && getR() == point.getR() && getG() == point.getG() && getB() == point.getB(); } diff --git a/src/main/java/com/movlad/pcl/Point3di.java b/src/main/java/com/movlad/pcl/Point3di.java new file mode 100644 index 0000000..50da110 --- /dev/null +++ b/src/main/java/com/movlad/pcl/Point3di.java @@ -0,0 +1,74 @@ +package com.movlad.pcl; + +import com.movlad.pcl.math.Comparison; +import com.movlad.pcl.nat.NativeObject; + +/** + * A point structure representing Euclidean xyz coordinates with an associated + * intensity value. + * + * @see + * pcl::PointXYZI documentation + */ +public class Point3di extends NativeObject implements Point, Cloneable { + + @Override + protected final native void alloc(); + + @Override + protected final native void dispose(); + + public final native float getX(); + + public final native void setX(float x); + + public final native float getY(); + + public final native void setY(float y); + + public final native float getZ(); + + public final native void setZ(float z); + + public void setCoordinates(float x, float y, float z) { + setX(x); + setY(y); + setZ(z); + } + + public final native float getI(); + + public final native void setI(float i); + + @Override + public Point3di clone() { + Point3di clone = new Point3di(); + + clone.setCoordinates(getX(), getY(), getZ()); + clone.setI(getI()); + + return clone; + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } else if (!(object instanceof Point3di)) { + return false; + } + Point3di point = (Point3di) object; + + return Comparison.areEqualFloat(getX(), point.getX(), 1.0e-6f) + && Comparison.areEqualFloat(getY(), point.getY(), 1.0e-6f) + && Comparison.areEqualFloat(getZ(), point.getZ(), 1.0e-6f) + && Comparison.areEqualFloat(getI(), point.getI(), 1.0e-6f); + } + + @Override + public String toString() { + return "x: " + getX() + " y: " + getY() + " z: " + getZ(); + } + +} diff --git a/src/main/java/com/movlad/pcl/PointCloud.java b/src/main/java/com/movlad/pcl/PointCloud.java index a41fd8c..057409a 100644 --- a/src/main/java/com/movlad/pcl/PointCloud.java +++ b/src/main/java/com/movlad/pcl/PointCloud.java @@ -73,23 +73,22 @@ public void remove() { @Override public boolean equals(Object object) { + if (object == this) { + return true; + } else if (!(object instanceof PointCloud)) { + return false; + } PointCloud cloud = (PointCloud) object; - boolean equals = true; - int i = 0; if (size() != cloud.size()) { return false; } - - while (i < size() && equals) { + for (int i = 0, size = size(); i < size; i++) { if (!get(i).equals(cloud.get(i))) { - equals = false; + return false; } - - i++; - } - - return equals; + } + return true; } } diff --git a/src/main/java/com/movlad/pcl/PointCloud3d.java b/src/main/java/com/movlad/pcl/PointCloud3d.java index f110e17..e8386ad 100644 --- a/src/main/java/com/movlad/pcl/PointCloud3d.java +++ b/src/main/java/com/movlad/pcl/PointCloud3d.java @@ -10,10 +10,10 @@ public final class PointCloud3d extends PointCloud { @Override - public native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); @Override public Point3d get(int i) { @@ -28,27 +28,26 @@ public Point3d get(int i) { protected native void nGet(int i, Point3d point); @Override - public native void add(Point3d point); + public final native void add(Point3d point); @Override - public native void remove(Point3d point); + public final native void remove(Point3d point); @Override - public native void clear(); + public final native void clear(); @Override - public native int size(); + public final native int size(); @Override - public native boolean isOrganized(); + public final native boolean isOrganized(); @Override public PointCloud3d clone() { PointCloud3d clone = new PointCloud3d(); - clone.create(); - for (Point3d point : this) { + @SuppressWarnings("resource") Point3d pointClone = point.clone(); clone.add(pointClone); diff --git a/src/main/java/com/movlad/pcl/PointCloud3di.java b/src/main/java/com/movlad/pcl/PointCloud3di.java new file mode 100644 index 0000000..7f563a7 --- /dev/null +++ b/src/main/java/com/movlad/pcl/PointCloud3di.java @@ -0,0 +1,59 @@ +package com.movlad.pcl; + +/** + * The class for storing an array of 3D RGB points. + * + * @see + * pcl::PointCloud documentation + * + */ +public final class PointCloud3di extends PointCloud { + + @Override + protected final native void alloc(); + + @Override + protected final native void dispose(); + + @Override + public Point3di get(int i) { + Point3di point = new Point3di(); + + nGet(i, point); + + return point; + } + + @Override + protected native void nGet(int i, Point3di point); + + @Override + public final native void add(Point3di point); + + @Override + public final native void remove(Point3di point); + + @Override + public final native void clear(); + + @Override + public final native int size(); + + @Override + public final native boolean isOrganized(); + + @Override + public PointCloud3di clone() { + PointCloud3di clone = new PointCloud3di(); + + for (Point3di point : this) { + @SuppressWarnings("resource") + Point3di pointClone = point.clone(); + + clone.add(pointClone); + } + + return clone; + } + +} diff --git a/src/main/java/com/movlad/pcl/RandomSampleConsensus.java b/src/main/java/com/movlad/pcl/RandomSampleConsensus.java index 7a93ece..b519479 100644 --- a/src/main/java/com/movlad/pcl/RandomSampleConsensus.java +++ b/src/main/java/com/movlad/pcl/RandomSampleConsensus.java @@ -3,7 +3,7 @@ /** * RandomSampleConsensus represents an implementation of the RANSAC (RAndom SAmple Consensus) algorithm, as described in: * "Random Sample Consensus: A Paradigm for Model Fitting with Applications to Image Analysis and Automated Cartography", - * Martin A. Fischler and Robert C. Bolles, Comm. Of the ACM 24: 381–395, June 1981. + * Martin A. Fischler and Robert C. Bolles, Comm. Of the ACM 24: 381�395, June 1981. * * @see * pcl::RandomSampleConsensus documentation @@ -16,12 +16,12 @@ public RandomSampleConsensus(SampleConsensusModel model) { } @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); @Override - public native boolean computeModel(int debugVerbosityLevel); + public final native boolean computeModel(int debugVerbosityLevel); } diff --git a/src/main/java/com/movlad/pcl/SampleConsensus.java b/src/main/java/com/movlad/pcl/SampleConsensus.java index 287aeb8..7eec719 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensus.java +++ b/src/main/java/com/movlad/pcl/SampleConsensus.java @@ -19,17 +19,9 @@ public abstract class SampleConsensus extends NativeObject { * @param model a sample consensus model */ public SampleConsensus(SampleConsensusModel model) { + super(); this.model = model; - } - - @Override - public void create() { - if (getHandle() != 0) { - dispose(); - } - - alloc(); - setSampleConsensusModel(model); + nSetSampleConsensusModel(this.model); } public SampleConsensusModel getSampleConsensusModel() { @@ -38,26 +30,25 @@ public SampleConsensusModel getSampleConsensusModel() { public void setSampleConsensusModel(SampleConsensusModel model) { this.model = model; - nSetSampleConsensusModel(this.model); } private native void nSetSampleConsensusModel(SampleConsensusModel model); - public native double getDistanceThreshold(); + public final native double getDistanceThreshold(); - public native void setDistanceThreshold(double threshold); + public final native void setDistanceThreshold(double threshold); - public native int getMaxIterations(); + public final native int getMaxIterations(); - public native void setMaxIterations(int maxIterations); + public final native void setMaxIterations(int maxIterations); - public native double getProbability(); + public final native double getProbability(); - public native void setProbability(double probability); + public final native void setProbability(double probability); public abstract boolean computeModel(int debugVerbosityLevel); - public native boolean refineModel(double sigma, int maxIterations); + public final native boolean refineModel(double sigma, int maxIterations); /** * @param source is the cloud on which RANSAC was applied diff --git a/src/main/java/com/movlad/pcl/SampleConsensusModel.java b/src/main/java/com/movlad/pcl/SampleConsensusModel.java index 9015f15..6f05a29 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensusModel.java +++ b/src/main/java/com/movlad/pcl/SampleConsensusModel.java @@ -14,31 +14,23 @@ public abstract class SampleConsensusModel extends NativeObject { private PointCloud3d input; public SampleConsensusModel(PointCloud3d cloud) { + super(); this.input = cloud; - } - - @Override - public void create() { - if (getHandle() != 0) { - dispose(); - } - - alloc(); setInputCloud(input); } - public native void setInputCloud(PointCloud3d cloud); + public final native void setInputCloud(PointCloud3d cloud); /** * @return the size of a sample from which a model is computed. */ - public native int getSampleSize(); + public final native int getSampleSize(); /** * Compute the variance of the errors to the model from the internally estimated vector of distances. * * @return variance */ - public native double computeVariance(); + public final native double computeVariance(); } diff --git a/src/main/java/com/movlad/pcl/SampleConsensusModelCone.java b/src/main/java/com/movlad/pcl/SampleConsensusModelCone.java index 34d17f8..a66c8c5 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensusModelCone.java +++ b/src/main/java/com/movlad/pcl/SampleConsensusModelCone.java @@ -25,16 +25,16 @@ public SampleConsensusModelCone(PointCloud3d cloud) { } @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); @Override - public native double getNormalDistanceWeight(); + public final native double getNormalDistanceWeight(); @Override - public native void setNormalDistanceWeight(double weight); + public final native void setNormalDistanceWeight(double weight); @Override public NormalCloud getInputNormals() { @@ -48,6 +48,6 @@ public NormalCloud getInputNormals() { private native void nGetInputNormals(NormalCloud normals); @Override - public native void setInputNormals(NormalCloud cloud); + public final native void setInputNormals(NormalCloud cloud); } diff --git a/src/main/java/com/movlad/pcl/SampleConsensusModelCylinder.java b/src/main/java/com/movlad/pcl/SampleConsensusModelCylinder.java index 400ef2c..39b4664 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensusModelCylinder.java +++ b/src/main/java/com/movlad/pcl/SampleConsensusModelCylinder.java @@ -25,16 +25,16 @@ public SampleConsensusModelCylinder(PointCloud3d cloud) { } @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); @Override - public native double getNormalDistanceWeight(); + public final native double getNormalDistanceWeight(); @Override - public native void setNormalDistanceWeight(double weight); + public final native void setNormalDistanceWeight(double weight); @Override public NormalCloud getInputNormals() { @@ -48,6 +48,6 @@ public NormalCloud getInputNormals() { private native void nGetInputNormals(NormalCloud normals); @Override - public native void setInputNormals(NormalCloud cloud); + public final native void setInputNormals(NormalCloud cloud); } diff --git a/src/main/java/com/movlad/pcl/SampleConsensusModelLine.java b/src/main/java/com/movlad/pcl/SampleConsensusModelLine.java index 491ca39..3d1b093 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensusModelLine.java +++ b/src/main/java/com/movlad/pcl/SampleConsensusModelLine.java @@ -24,9 +24,9 @@ public SampleConsensusModelLine(PointCloud3d cloud) { } @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); } diff --git a/src/main/java/com/movlad/pcl/SampleConsensusModelPlane.java b/src/main/java/com/movlad/pcl/SampleConsensusModelPlane.java index 82d75e0..a056912 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensusModelPlane.java +++ b/src/main/java/com/movlad/pcl/SampleConsensusModelPlane.java @@ -21,9 +21,9 @@ public SampleConsensusModelPlane(PointCloud3d cloud) { } @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); } diff --git a/src/main/java/com/movlad/pcl/SampleConsensusModelSphere.java b/src/main/java/com/movlad/pcl/SampleConsensusModelSphere.java index 60d2c06..edb278e 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensusModelSphere.java +++ b/src/main/java/com/movlad/pcl/SampleConsensusModelSphere.java @@ -20,8 +20,8 @@ public SampleConsensusModelSphere(PointCloud3d cloud) { } @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); } diff --git a/src/main/java/com/movlad/pcl/SampleConsensusModelStick.java b/src/main/java/com/movlad/pcl/SampleConsensusModelStick.java index ff7572a..336f229 100644 --- a/src/main/java/com/movlad/pcl/SampleConsensusModelStick.java +++ b/src/main/java/com/movlad/pcl/SampleConsensusModelStick.java @@ -26,9 +26,9 @@ public SampleConsensusModelStick(PointCloud3d cloud) { } @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); } diff --git a/src/main/java/com/movlad/pcl/io/PointCloudReader.java b/src/main/java/com/movlad/pcl/io/PointCloudReader.java index 0f157f5..0e109c7 100644 --- a/src/main/java/com/movlad/pcl/io/PointCloudReader.java +++ b/src/main/java/com/movlad/pcl/io/PointCloudReader.java @@ -36,8 +36,6 @@ public final void read(String fileName) { * @param format establishes the format of the input file. */ public final void read(String fileName, FileFormat format) { - cloud.create(); - switch (format) { case PCD: readPCD(fileName, cloud); diff --git a/src/main/java/com/movlad/pcl/math/Comparison.java b/src/main/java/com/movlad/pcl/math/Comparison.java index bf282eb..b723499 100644 --- a/src/main/java/com/movlad/pcl/math/Comparison.java +++ b/src/main/java/com/movlad/pcl/math/Comparison.java @@ -2,8 +2,20 @@ public class Comparison { + public static final float EPSF = 1.0e-6f; + + public static final double EPS = 1.0e-6; + + public static boolean areEqualFloat(float a, float b) { + return Math.abs(a - b) < EPSF; + } + public static boolean areEqualFloat(float a, float b, float precision) { - return Math.abs(a - b) <= precision; + return Math.abs(a - b) < precision; + } + + public static boolean areEqualDouble(double a, double b) { + return Math.abs(a - b) < EPS; } public static boolean areEqualDouble(double a, double b, double precision) { diff --git a/src/main/java/com/movlad/pcl/nat/NativeObject.java b/src/main/java/com/movlad/pcl/nat/NativeObject.java index e579a3e..f4ae1ee 100644 --- a/src/main/java/com/movlad/pcl/nat/NativeObject.java +++ b/src/main/java/com/movlad/pcl/nat/NativeObject.java @@ -1,47 +1,55 @@ package com.movlad.pcl.nat; +import java.lang.ref.Cleaner; +import java.lang.ref.PhantomReference; + /** * Bridge between a Java object and a native pointer. * * @author Vlad-Adrian Moglan */ -public abstract class NativeObject { +public abstract class NativeObject implements AutoCloseable { - private long handle; - - public NativeObject() { - this.handle = 0; - } - /** - * @return the memory address given by the native pointer associated to this - * object if such an association exists, 0 otherwise. + * Pointer to the native object associated with this {@link NativeObject} + * instance. */ - public long getHandle() { return handle; } - + @SuppressWarnings("unused") + private volatile long handle; + /** - * Associates a native pointer allocated on the native side to this - * object, if no such association exists. + * Construct a new {@link NativeObject} instance, and call {@link #alloc()} to + * instantiate the corresponding native object. */ - public void create() { - if (handle != 0) { - dispose(); - } - + protected NativeObject() { alloc(); } - + /** - * Associates a native pointer allocated on the native side to this - * object. + * Allocate a native object, and store its pointer in {@link #handle}. Called + * automatically by {@link NativeObject}. */ protected abstract void alloc(); - + /** - * Deallocates the memory given to the created object. Called automatically upon - * object destruction, but this may cause unexpected behavior: this should be - * called manually when the object is no longer needed. + * Deallocate the native object associated with this {@link NativeObject} + * instance. This should be called in a try-with-resources block, or manually + * called before the {@link NativeObject} goes out of scope. Failing to call + * this method before this object goes out of scope will result in a resource + * leak. + * + * Finalizers are broken + * in Java, and registering a {@link Cleaner} or a {@link PhantomReference} + * incurs memory and CPU overhead. + * + * Override this method with a public final native dispose() method in subclasses. */ - public abstract void dispose(); + protected abstract void dispose(); + /** Call {@link #dispose()} to free the associated native object. */ + @Override + public void close() { + dispose(); + } } diff --git a/src/main/java/com/movlad/pcl/registration/GeneralizedIterativeClosestPoint.java b/src/main/java/com/movlad/pcl/registration/GeneralizedIterativeClosestPoint.java new file mode 100644 index 0000000..b03ce77 --- /dev/null +++ b/src/main/java/com/movlad/pcl/registration/GeneralizedIterativeClosestPoint.java @@ -0,0 +1,85 @@ +package com.movlad.pcl.registration; + +import com.movlad.pcl.Matrix4; +import com.movlad.pcl.PointCloud3d; +import com.movlad.pcl.nat.NativeObject; + +/** + * Launches the + * {@code pcl::GeneralizedIterativeClosestPoint} to + * register two point clouds. + * + * @see pcl::GeneralizedIterativeClosestPoint + * documentation + */ +public class GeneralizedIterativeClosestPoint extends NativeObject { + + private PointCloud3d source; + private int[] sourceIdxs; + private PointCloud3d target; + private int[] targetIdxs; + + @Override + protected final native void alloc(); + + @Override + protected final native void dispose(); + + private final native void setInputSource(PointCloud3d source); + + private final native void setInputTarget(PointCloud3d target); + + private final native void setMaximumIterations(int maxIterations); + + private final native void setRotationEpsilon(double rotationEpsilon); + + private final native void estimateRigidTransformationBFGS(PointCloud3d source, int[] sourceIdxs, + PointCloud3d target, int[] targetIdxs, Matrix4 transformOut); + + public GeneralizedIterativeClosestPoint(PointCloud3d source, PointCloud3d target) { + super(); + this.source = source; + this.target = target; + sourceIdxs = new int[source.size()]; + for (int i = 0; i < sourceIdxs.length; i++) { + sourceIdxs[i] = i; + } + if (target.size() == source.size()) { + targetIdxs = sourceIdxs; + } else { + targetIdxs = new int[source.size()]; + for (int i = 0; i < targetIdxs.length; i++) { + targetIdxs[i] = i; + } + } + } + + public GeneralizedIterativeClosestPoint(PointCloud3d source, int[] sourceIdxs, PointCloud3d target, + int[] targetIdxs) { + super(); + this.source = source; + this.target = target; + this.sourceIdxs = sourceIdxs; + this.targetIdxs = targetIdxs; + } + + public Matrix4 register(int maxIterations, double rotationEpsilon) { + setInputSource(source); + setInputTarget(target); + setMaximumIterations(maxIterations); + setRotationEpsilon(rotationEpsilon); + Matrix4 transformOut = new Matrix4(); + estimateRigidTransformationBFGS(source, sourceIdxs, target, targetIdxs, transformOut); + return transformOut; + } + + @Override + public void close() { + source.close(); + target.close(); + sourceIdxs = null; + targetIdxs = null; + super.close(); + } +} diff --git a/src/main/java/com/movlad/pcl/registration/IterativeClosestPoint.java b/src/main/java/com/movlad/pcl/registration/IterativeClosestPoint.java new file mode 100644 index 0000000..cfd453b --- /dev/null +++ b/src/main/java/com/movlad/pcl/registration/IterativeClosestPoint.java @@ -0,0 +1,76 @@ +package com.movlad.pcl.registration; + +import com.movlad.pcl.Matrix4f; +import com.movlad.pcl.PointCloud3d; +import com.movlad.pcl.nat.NativeObject; + +/** + * Launches the + * {@code pcl::GeneralizedIterativeClosestPoint} to + * register two point clouds. + * + * @see pcl::GeneralizedIterativeClosestPoint + * documentation + */ +public class IterativeClosestPoint extends NativeObject { + + private PointCloud3d alignedCloud; + + private Matrix4f xform; + + @Override + protected final native void alloc(); + + @Override + protected final native void dispose(); + + private final native void setInputSource(PointCloud3d source); + + private final native void setInputTarget(PointCloud3d target); + + public final native void setMaximumIterations(int maxIterations); + + public final native void setMaxCorrespondenceDistance(double maxCorrespondenceDistance); + + public final native void setTransformationEpsilon(double transformationEpsilon); + + public final native void setEuclideanFitnessEpsilon(double euclideanFitnessEpsilon); + + private final native void align(PointCloud3d alignedCloud); + + private final native void getFinalTransformation(Matrix4f transformOut); + + public final native boolean hasConverged(); + + public IterativeClosestPoint(PointCloud3d source, PointCloud3d target) { + super(); + setInputSource(source); + setInputTarget(target); + } + + public PointCloud3d align() { + if (alignedCloud != null) { + alignedCloud.close(); + } + alignedCloud = new PointCloud3d(); + align(alignedCloud); + return alignedCloud; + } + + public Matrix4f getFinalTransformation() { + if (xform != null) { + xform.close(); + } + xform = new Matrix4f(); + getFinalTransformation(xform); + return xform; + } + + @Override + public void close() { + alignedCloud.close(); + xform.close(); + super.close(); + } +} diff --git a/src/main/java/com/movlad/pcl/visualization/Visualizer.java b/src/main/java/com/movlad/pcl/visualization/Visualizer.java index d71c62c..50171ab 100644 --- a/src/main/java/com/movlad/pcl/visualization/Visualizer.java +++ b/src/main/java/com/movlad/pcl/visualization/Visualizer.java @@ -13,20 +13,20 @@ public abstract class Visualizer extends NativeObject { @Override - protected native void alloc(); + protected final native void alloc(); @Override - public native void dispose(); + protected final native void dispose(); /** * Stop the interaction and close the visualizaton window. */ - public native void close(); + public final native void stop(); /** * @return true when the user tried to close the window. */ - public native boolean wasStopped(); + public final native boolean wasStopped(); /** * Create a new viewport from (xmin,ymin) to (xmax,ymax). @@ -37,12 +37,12 @@ public abstract class Visualizer extends NativeObject { * @param ymax the maximum Y coordinate for the viewport (0.0 lesser or equal 1.0) * @param viewport the id of the new viewport */ - public native void createViewport(double xmin, double ymin, double xmax, double ymax, int viewport); + public final native void createViewport(double xmin, double ymin, double xmax, double ymax, int viewport); /** * Calls the interactor and runs an internal loop. */ - public native void spin(); + public final native void spin(); /** * Calls the interactor and runs an internal loop. @@ -50,11 +50,11 @@ public abstract class Visualizer extends NativeObject { * @param time How long (in ms) should the visualization loop be allowed to run. * @param forceRedraw if false it might return without doing anything if the interactor's framerate does not require a redraw yet. */ - public native void spinOnce(int time, boolean forceRedraw); + public final native void spinOnce(int time, boolean forceRedraw); - public native void setWindowName(String name); + public final native void setWindowName(String name); - public native void setBackgroundColor(float r, float g, float b); + public final native void setBackgroundColor(float r, float g, float b); /** * Adds point cloud to viewport. @@ -66,9 +66,9 @@ public abstract class Visualizer extends NativeObject { */ public abstract boolean addPointCloud(PointCloud cloud, String id, int viewport); - public native boolean removePointCloud(String id, int viewport); + public final native boolean removePointCloud(String id, int viewport); - public native boolean removeAllPointClouds(int viewport); + public final native boolean removeAllPointClouds(int viewport); /** * Add the estimated surface normals of a Point Cloud to screen. @@ -96,7 +96,7 @@ public abstract boolean addPointCloudNormals( * @param scale the scale of the axes (default: 1) * @param viewport the view port where the 3D axes should be added (default: all) */ - public native void addCoordinateSystem(double scale, int viewport); + public final native void addCoordinateSystem(double scale, int viewport); /** * Adds 3D axes describing a coordinate system to screen at 0,0,0. @@ -105,14 +105,14 @@ public abstract boolean addPointCloudNormals( * @param id the coordinate system id * @param viewport the view port where the 3D axes should be added (default: all) */ - public native void addCoordinateSystem(double scale, String id, int viewport); + public final native void addCoordinateSystem(double scale, String id, int viewport); /** * Removes coordinate system from viewport. * * @param viewport the viewport to remove the coordinate system from. */ - public native void removeCoordinateSystem(int viewport); + public final native void removeCoordinateSystem(int viewport); /** * Removes coordinate system from viewport. @@ -120,21 +120,21 @@ public abstract boolean addPointCloudNormals( * @param id is the id of the coordinate system * @param viewport the viewport to remove the coordinate system from. */ - public native void removeCoordinateSystem(String id, int viewport); + public final native void removeCoordinateSystem(String id, int viewport); - public native void removeAllCoordinateSystems(int viewport); + public final native void removeAllCoordinateSystems(int viewport); - public native boolean addText(String text, int xpos, int ypos, String id, int viewport); + public final native boolean addText(String text, int xpos, int ypos, String id, int viewport); - public native boolean addText(String text, int xpos, int ypos, double r, double g, double b, String id, int viewport); + public final native boolean addText(String text, int xpos, int ypos, double r, double g, double b, String id, int viewport); - public native boolean addText(String text, int xpos, int ypos, int fontsize, double r, double g, double b, String id, int viewport); + public final native boolean addText(String text, int xpos, int ypos, int fontsize, double r, double g, double b, String id, int viewport); - public native void setPointSize(int size, String id); + public final native void setPointSize(int size, String id); /** * Initialize camera parameters with some default values. */ - public native void initCameraParameters(); + public final native void initCameraParameters(); } diff --git a/src/main/java/com/movlad/pcl/visualization/Visualizer3d.java b/src/main/java/com/movlad/pcl/visualization/Visualizer3d.java index bde1cc8..078e21c 100644 --- a/src/main/java/com/movlad/pcl/visualization/Visualizer3d.java +++ b/src/main/java/com/movlad/pcl/visualization/Visualizer3d.java @@ -10,10 +10,10 @@ public class Visualizer3d extends Visualizer { @Override - public native boolean addPointCloud(PointCloud cloud, String id, int viewport); + public final native boolean addPointCloud(PointCloud cloud, String id, int viewport); @Override - public native boolean addPointCloudNormals(PointCloud cloud, NormalCloud normals, int level, float scale, String id, + public final native boolean addPointCloudNormals(PointCloud cloud, NormalCloud normals, int level, float scale, String id, int viewport); } diff --git a/src/test/java/com/movlad/pcl/NormalEstimationTest.java b/src/test/java/com/movlad/pcl/NormalEstimationTest.java index b08fef6..aab299b 100644 --- a/src/test/java/com/movlad/pcl/NormalEstimationTest.java +++ b/src/test/java/com/movlad/pcl/NormalEstimationTest.java @@ -13,30 +13,30 @@ class NormalEstimationTest { - static { + static { System.loadLibrary("pcl_java"); } - + @Test void test() { ClassLoader classLoader = getClass().getClassLoader(); File sample = new File(classLoader.getResource("pcl-samples/bunny.pcd").getFile()); PointCloud3dReader reader = new PointCloud3dReader(); - + reader.read(sample.getAbsolutePath()); - - PointCloud3d cloud = reader.getCloud(); - - NormalEstimation ne = new NormalEstimation(cloud, 0.03f); - - ne.run(); - - NormalCloud normals = ne.getNormals(); - - assertEquals(cloud.size(), normals.size()); - - cloud.dispose(); - normals.dispose(); + + try (PointCloud3d cloud = reader.getCloud()) { + + NormalEstimation ne = new NormalEstimation(cloud, 0.03f); + + ne.run(); + + NormalCloud normals = ne.getNormals(); + + assertEquals(cloud.size(), normals.size()); + + normals.close(); + } } } diff --git a/src/test/java/com/movlad/pcl/NormalTest.java b/src/test/java/com/movlad/pcl/NormalTest.java index 96fe58e..f6e0cd0 100644 --- a/src/test/java/com/movlad/pcl/NormalTest.java +++ b/src/test/java/com/movlad/pcl/NormalTest.java @@ -8,26 +8,25 @@ import com.movlad.pcl.math.Comparison; class NormalTest { - + private static final float EX_X = 3; private static final float EX_Y = 4; private static final float EX_Z = 5; - static { + static { System.loadLibrary("pcl_java"); } - + @Test void test() { - Normal normal = new Normal(); - - normal.create(); - - normal.setComponents(EX_X, EX_Y, EX_Z); - - assertTrue(Comparison.areEqualFloat(normal.getX(), EX_X, 0.5f)); - assertTrue(Comparison.areEqualFloat(normal.getY(), EX_Y, 0.5f)); - assertTrue(Comparison.areEqualFloat(normal.getZ(), EX_Z, 0.5f)); + try (Normal normal = new Normal()) { + + normal.setComponents(EX_X, EX_Y, EX_Z); + + assertTrue(Comparison.areEqualFloat(normal.getX(), EX_X, 0.5f)); + assertTrue(Comparison.areEqualFloat(normal.getY(), EX_Y, 0.5f)); + assertTrue(Comparison.areEqualFloat(normal.getZ(), EX_Z, 0.5f)); + } } } diff --git a/src/test/java/com/movlad/pcl/Point3dTest.java b/src/test/java/com/movlad/pcl/Point3dTest.java index e9b8f65..51b6fae 100644 --- a/src/test/java/com/movlad/pcl/Point3dTest.java +++ b/src/test/java/com/movlad/pcl/Point3dTest.java @@ -7,46 +7,36 @@ import com.movlad.pcl.Point3d; public class Point3dTest { - + private static final float EX_X = 3; private static final float EX_Y = 4; private static final float EX_Z = 5; - - static { + + static { System.loadLibrary("pcl_java"); } - + @Test void attributeAccessTest() { - Point3d point = createExample(); - - assertEquals(point.getX(), EX_X); - assertEquals(point.getY(), EX_Y); - assertEquals(point.getZ(), EX_Z); - - point.dispose(); + try (Point3d point = createExample()) { + assertEquals(point.getX(), EX_X); + assertEquals(point.getY(), EX_Y); + assertEquals(point.getZ(), EX_Z); + } } - + @Test void cloneTest() { - Point3d point = createExample(); - Point3d clone = point.clone(); - - assertEquals(clone.getX(), EX_X); - assertEquals(clone.getY(), EX_Y); - assertEquals(clone.getZ(), EX_Z); - - point.dispose(); - clone.dispose(); + try (Point3d point = createExample(); Point3d clone = point.clone()) { + assertEquals(clone.getX(), EX_X); + assertEquals(clone.getY(), EX_Y); + assertEquals(clone.getZ(), EX_Z); + } } private Point3d createExample() { Point3d point = new Point3d(); - - point.create(); - point.setCoordinates(EX_X, EX_Y, EX_Z); - return point; } diff --git a/src/test/java/com/movlad/pcl/TestExampleGenerator.java b/src/test/java/com/movlad/pcl/TestExampleGenerator.java index 3e2998c..f1ba360 100644 --- a/src/test/java/com/movlad/pcl/TestExampleGenerator.java +++ b/src/test/java/com/movlad/pcl/TestExampleGenerator.java @@ -1,4 +1,5 @@ package com.movlad.pcl; + import java.util.concurrent.ThreadLocalRandom; import com.movlad.pcl.Point2d; @@ -6,47 +7,46 @@ import com.movlad.pcl.PointCloud3d; public class TestExampleGenerator { - - private TestExampleGenerator() { } - + + private TestExampleGenerator() { + } + public static Point2d generatePoint2d(Point2d min, Point2d max) { Point2d point = new Point2d(); - - point.create(); + point.setCoordinates(randomFloat(min.getX(), max.getX()), randomFloat(min.getY(), max.getY())); - + return point; } - + public static Point3d generatePoint3d(Point3d min, Point3d max) { Point3d point = new Point3d(); - - point.create(); - point.setCoordinates(randomFloat(min.getX(), max.getX()), randomFloat(min.getY(), max.getY()), + + point.setCoordinates(randomFloat(min.getX(), max.getX()), randomFloat(min.getY(), max.getY()), randomFloat(min.getZ(), max.getZ())); point.setRGB(randomShort(), randomShort(), randomShort()); - + return point; } - + public static PointCloud3d generatePointCloud3d(Point3d min, Point3d max, int size) { PointCloud3d cloud = new PointCloud3d(); - - cloud.create(); - + for (int i = 0; i < size; i++) { - cloud.add(generatePoint3d(min, max)); + try (Point3d point = generatePoint3d(min, max)) { + cloud.add(point); + } } - + return cloud; } - - public static float randomFloat(float min, float max) { + + public static float randomFloat(float min, float max) { return (float) (min + Math.random() * (max - min)); } - + public static short randomShort() { return (short) ThreadLocalRandom.current().nextInt(0, 255 + 1); } - + } diff --git a/src/test/java/com/movlad/pcl/io/PointCloud3dReadWriteTest.java b/src/test/java/com/movlad/pcl/io/PointCloud3dReadWriteTest.java index 3dcc224..a131293 100644 --- a/src/test/java/com/movlad/pcl/io/PointCloud3dReadWriteTest.java +++ b/src/test/java/com/movlad/pcl/io/PointCloud3dReadWriteTest.java @@ -8,11 +8,9 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import com.movlad.pcl.TestExampleGenerator; import com.movlad.pcl.Point3d; import com.movlad.pcl.PointCloud3d; -import com.movlad.pcl.io.PointCloud3dReader; -import com.movlad.pcl.io.PointCloud3dWriter; +import com.movlad.pcl.TestExampleGenerator; class PointCloud3dReadWriteTest { @@ -20,62 +18,57 @@ class PointCloud3dReadWriteTest { private static Point3d minPoint; private static Point3d maxPoint; - static { + static { System.loadLibrary("pcl_java"); } - + @BeforeAll static void init() { minPoint = new Point3d(); maxPoint = new Point3d(); - - minPoint.create(); - maxPoint.create(); - + minPoint.setCoordinates(-5.0f, -5.0f, -5.0f); maxPoint.setCoordinates(5.0f, 5.0f, 5.0f); } - + @AfterAll static void deinit() { - minPoint.dispose(); - maxPoint.dispose(); + minPoint.close(); + maxPoint.close(); } @Test void testReadPCD() { - PointCloud3d pointCloud = TestExampleGenerator.generatePointCloud3d(minPoint, maxPoint, CLOUD_SIZE); - PointCloud3dWriter exporter = new PointCloud3dWriter(pointCloud); - PointCloud3dReader reader = new PointCloud3dReader(); - - exporter.write("cloud-export-test.pcd"); - reader.read("cloud-export-test.pcd"); - - File file = new File("cloud-export-test.pcd"); - - file.deleteOnExit(); - - assertEquals(pointCloud.size(), reader.getCloud().size()); - - pointCloud.dispose(); + try (PointCloud3d pointCloud = TestExampleGenerator.generatePointCloud3d(minPoint, maxPoint, CLOUD_SIZE)) { + PointCloud3dWriter exporter = new PointCloud3dWriter(pointCloud); + PointCloud3dReader reader = new PointCloud3dReader(); + + exporter.write("cloud-export-test.pcd"); + reader.read("cloud-export-test.pcd"); + + File file = new File("cloud-export-test.pcd"); + + file.deleteOnExit(); + + assertEquals(pointCloud.size(), reader.getCloud().size()); + } } - + @Test void testReadPLY() { - PointCloud3d pointCloud = TestExampleGenerator.generatePointCloud3d(minPoint, maxPoint, CLOUD_SIZE); - PointCloud3dWriter exporter = new PointCloud3dWriter(pointCloud); - PointCloud3dReader reader = new PointCloud3dReader(); - - exporter.write("cloud-export-test.ply"); - reader.read("cloud-export-test.ply"); - - File file = new File("cloud-export-test.ply"); - - file.deleteOnExit(); - - assertEquals(pointCloud.size(), reader.getCloud().size()); - - pointCloud.dispose(); + try (PointCloud3d pointCloud = TestExampleGenerator.generatePointCloud3d(minPoint, maxPoint, CLOUD_SIZE)) { + PointCloud3dWriter exporter = new PointCloud3dWriter(pointCloud); + PointCloud3dReader reader = new PointCloud3dReader(); + + exporter.write("cloud-export-test.ply"); + reader.read("cloud-export-test.ply"); + + File file = new File("cloud-export-test.ply"); + + file.deleteOnExit(); + + assertEquals(pointCloud.size(), reader.getCloud().size()); + } } }