Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/split kdtree #334

Closed
wants to merge 13 commits into from
Closed
736 changes: 148 additions & 588 deletions src/main/java/net/imglib2/KDTree.java

Large diffs are not rendered by default.

185 changes: 68 additions & 117 deletions src/main/java/net/imglib2/KDTreeNode.java
Original file line number Diff line number Diff line change
@@ -1,107 +1,80 @@
/*
* #%L
* ImgLib2: a general-purpose, multidimensional image processing library.
* %%
* Copyright (C) 2009 - 2023 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld,
* John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke,
* Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner,
* Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert,
* Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin,
* Jean-Yves Tinevez and Michael Zinsmaier.
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/

package net.imglib2;

import java.util.function.IntFunction;

/**
* Abstract base class for nodes in a KDTree. A KDTreeNode has coordinates and a
* value. It provides the coordinates via the {@link RealLocalizable} interface.
* It provides the value via {@link Sampler#get()}.
* Proxy for a node in a KDTree. A KDTreeNode has coordinates and a value. It
* provides the coordinates via the {@link RealLocalizable} interface. It
* provides the value via {@link Sampler#get()}.
*
* @param <T>
* value type.
*
*
* @author Tobias Pietzsch
*/
public abstract class KDTreeNode< T > implements RealLocalizable, Sampler< T >
public class KDTreeNode< T > implements RealLocalizable, Sampler< T >
{
/**
* number of dimensions of the space (that is, k).
*/
protected final int n;
private final KDTree< T > tree;

private int nodeIndex;

private IntFunction< T > values;

KDTreeNode( final KDTree< T > tree )
{
this.tree = tree;
}

/**
* coordinates of the node.
* Make this proxy refer to the given {@code nodeIndex} in the associated tree.
*
* @return {@code this}
*/
protected final double[] pos;
public KDTreeNode< T > setNodeIndex( final int nodeIndex )
{
this.nodeIndex = nodeIndex;
return this;
}

/**
* dimension along which this node divides the space.
* Get the {@code nodeIndex} which this proxy currently refers to.
*/
protected final int splitDimension;
public int nodeIndex() {
return nodeIndex;
}

/**
* Left child of this node. All nodes x in the left subtree have
* {@code x.pos[splitDimension] <= this.pos[splitDimension]}.
*
* @deprecated
* {@link KDTreeNode} is now a re-usable proxy (like {@code NativeType}).
* To work with existing code, {@link KDTreeNode#left()}, {@link
* KDTreeNode#right()}, {@link KDTree#getRoot()} etc create new objects in each
* call, instead of re-using existing proxies.
* Code using that should be rewritten to reuse proxies, if possible.
*/
public final KDTreeNode< T > left;
@Deprecated
public KDTreeNode< T > left()
{
return tree.left( this );
}

/**
* Right child of this node. All nodes x in the right subtree have
* {@code x.pos[splitDimension] >= this.pos[splitDimension]}.
*
* @deprecated
* {@link KDTreeNode} is now a re-usable proxy (like {@code NativeType}).
* To work with existing code, {@link KDTreeNode#left()}, {@link
* KDTreeNode#right()}, {@link KDTree#getRoot()} etc create new objects in each
* call, instead of re-using existing proxies.
* Code using that should be rewritten to reuse proxies, if possible.
*/
public final KDTreeNode< T > right;

/**
* @param position
* coordinates of this node
* @param dimension
* dimension along which this node divides the space
* @param left
* left child node
* @param right
* right child node
*/
public KDTreeNode( final RealLocalizable position, final int dimension, final KDTreeNode< T > left, final KDTreeNode< T > right )
@Deprecated
public KDTreeNode< T > right()
{
this.n = position.numDimensions();
this.pos = new double[ n ];
position.localize( pos );
this.splitDimension = dimension;
this.left = left;
this.right = right;
}

protected KDTreeNode( final KDTreeNode< T > node )
{
this.n = node.n;
this.pos = node.pos.clone();
this.splitDimension = node.splitDimension;
this.left = node.left;
this.right = node.right;
return tree.right( this );
}

/**
Expand All @@ -111,91 +84,69 @@ protected KDTreeNode( final KDTreeNode< T > node )
*/
public final int getSplitDimension()
{
return splitDimension;
return tree.impl.splitDimension( nodeIndex );
}

/**
* Get the position along {@link KDTreeNode#getSplitDimension()} where this
* Get the position along {@link net.imglib2.KDTreeNode#getSplitDimension()} where this
* node divides the space.
*
* @return splitting position.
*/
public final double getSplitCoordinate()
{
return pos[ splitDimension ];
return getDoublePosition( getSplitDimension() );
}

@Override
public final int numDimensions()
public int numDimensions()
{
return n;
return tree.numDimensions();
}

@Override
public final void localize( final float[] position )
public double getDoublePosition( final int d )
{
for ( int d = 0; d < n; ++d )
position[ d ] = ( float ) pos[ d ];
return tree.impl.getDoublePosition( nodeIndex, d );
}

@Override
public final void localize( final double[] position )
public T get()
{
for ( int d = 0; d < n; ++d )
position[ d ] = pos[ d ];
if ( values == null )
values = tree.treeData().valuesSupplier().get();
return values.apply( nodeIndex );
}

@Override
public final float getFloatPosition( final int d )
public KDTreeNode< T > copy()
{
return ( float ) pos[ d ];
final KDTreeNode< T > copy = new KDTreeNode<>( tree );
copy.setNodeIndex( nodeIndex );
return copy;
}

@Override
public final double getDoublePosition( final int d )
{
return pos[ d ];
}

@Override
public abstract KDTreeNode< T > copy();

/**
* Compute the squared distance from p to this node.
*/
public final float squDistanceTo( final float[] p )
{
float sum = 0;
for ( int d = 0; d < n; ++d )
{
sum += ( pos[ d ] - p[ d ] ) * ( pos[ d ] - p[ d ] );
}
return sum;
return tree.impl.squDistance( nodeIndex, p );
}

/**
* Compute the squared distance from p to this node.
*/
public final double squDistanceTo( final double[] p )
public double squDistanceTo( final double[] p )
{
double sum = 0;
for ( int d = 0; d < n; ++d )
{
sum += ( pos[ d ] - p[ d ] ) * ( pos[ d ] - p[ d ] );
}
return sum;
return tree.impl.squDistance( nodeIndex, p );
}

/**
* Compute the squared distance from p to this node.
*/
public final double squDistanceTo( final RealLocalizable p )
{
double sum = 0;
for ( int d = 0; d < n; ++d )
{
sum += ( pos[ d ] - p.getDoublePosition( d ) ) * ( pos[ d ] - p.getDoublePosition( d ) );
}
return sum;
return tree.impl.squDistance( nodeIndex, p );
}
}
20 changes: 17 additions & 3 deletions src/main/java/net/imglib2/img/list/ListImg.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.Collection;

import java.util.List;
import net.imglib2.img.Img;
import net.imglib2.type.Type;

Expand All @@ -61,7 +62,7 @@
*/
public class ListImg< T > extends AbstractListImg< T >
{
final private ArrayList< T > pixels;
final private List< T > pixels;

public ListImg( final long[] dim, final T type )
{
Expand All @@ -86,9 +87,9 @@ public ListImg( final long[] dim, final T type )
public ListImg( final Collection< T > collection, final long... dim )
{
super( dim );

assert numPixels == collection.size() : "Dimensions do not match number of pixels.";

pixels = new ArrayList< T >( ( int ) numPixels );
pixels.addAll( collection );
}
Expand Down Expand Up @@ -130,4 +131,17 @@ public ListImg< T > copy()
}
return new ListImg< T >( this.pixels, dimension );
}

private ListImg( final List< T > pixels, final boolean dummy, final long... dim )
{
super( dim );

assert numPixels == pixels.size() : "Dimensions do not match number of pixels.";
this.pixels = pixels;
}

public static < T > ListImg< T > wrap( List< T > pixels, final long... dim )
{
return new ListImg<>( pixels, false, dim );
}
}
Loading