Reputation: 1834
I am attempting to run http://www.savarese.com/software/libssrckdtree-j/ inside a Jruby file.
my code looks something like this:
require 'java'
require 'libssrckdtree-j-1.0.2.jar'
GenericPoint = Java::com.savarese.spatial.GenericPoint
KDTree = Java::com.savarese.spatial.KDTree
NearestNeighbors = Java::com.savarese.spatial.NearestNeighbors
tree = KDTree.new
def generate_points(tree, size)
size.times do
x = rand(100)
y = rand(100)
point = GenericPoint.new(x, y)
tree.put(point, point.to_s)
end
end
generate_points(tree, 20000)
nearest = NearestNeighbors.new()
point = [1,1]
nearest.get(tree, point, 1, false)
However when I run this code I get
NameError: no method 'get' for arguments (com.savarese.spatial.KDTree,org.jruby.RubyArray,org.jruby.RubyFixnum,org.jruby.RubyBoolean) on Java::ComSavareseSpatial::NearestNeighbors
(root) at kdjava.rb:25
Which I dont get as the documentation for the library says to use get, and i use put on tree for the KDtree and it worked.
What I am trying to do is construct a series of lat lngs into a kd tree using this library and then query another set of lat lngs to see their nearest neighbor inside the KD tree.
I am okay at Ruby - but I suck at Java. I am using Jruby to take advantage of these faster libraries.
Upvotes: 1
Views: 735
Reputation: 5994
The api documentation for NearestNeighbor#get() indicates that the method takes four arguments of types KDTree, P, int, boolean, which are all Java types.
Your error message indicates that you passed in KDTree, RubyArray, RubyFixnum, RubyBoolean. So, KDTree looks ok. I believe JRuby will automatically coerce Fixnum and Boolean to the appropriate Java types. That leaves the second arg where you are passing RubyArray where the method expects P.
The documentation of NearestNeighbors indicates that P is a generic type, P extends Point<Coord>
. Point
is an interface. GenericPoint
implements that interface. So instead of passing [1,1]
, try passing Java::com.savarese.spatial.GenericPoint.new(1,1)
edit:
Looking a bit further, GenericPoint
must be created with Coord
, another generic type Coord extends java.lang.Comparable<? super Coord>
. In Java, there are two kinds of ints, the primitive type int
(fast), and the "boxed" object java.lang.Integer
. Integer
implements the Comparable
interface, which is required by GenericPoint
. I did not get any errors running the following:
require 'java'
require 'libssrckdtree-j-1.0.2.jar'
GenericPoint = Java::com.savarese.spatial.GenericPoint
KDTree = Java::com.savarese.spatial.KDTree
NearestNeighbors = Java::com.savarese.spatial.NearestNeighbors
def box(i)
java.lang.Integer.new(i)
end
tree = KDTree.new
def generate_points(tree, size)
size.times do
x = box(rand(100))
y = box(rand(100))
point = GenericPoint.new(x, y)
tree.put(point, point.to_s)
end
end
generate_points(tree, 20000)
nearest = NearestNeighbors.new()
point = GenericPoint.new(box(1), box(1))
nearest.get(tree, point, 1, false)
A note about the above, normally in Java to create a boxed Integer
, one uses java.lang.Integer.valueOf(int)
. For reasons beyond me, this resulted in the same error one gets when using int
: NativeException: java.lang.ClassCastException: org.jruby.RubyFixnum cannot be cast to java.lang.Number
. So I instead used the constructor, java.lang.Integer.new
.
Upvotes: 2