Skip to content

Commit

Permalink
More Ops
Browse files Browse the repository at this point in the history
  • Loading branch information
gselzer committed Jul 22, 2024
1 parent abb1917 commit 232a976
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 12 deletions.
24 changes: 24 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@
<releaseProfiles>sign,deploy-to-scijava</releaseProfiles>

<imageio-tiff.version>3.9.4</imageio-tiff.version>

<scijava.ops.parse>true</scijava.ops.parse>
</properties>

<repositories>
Expand All @@ -131,6 +133,28 @@
</repository>
</repositories>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.scijava</groupId>
<artifactId>scijava-ops-indexer</artifactId>
<version>1.0.1-SNAPSHOT</version>
</path>
</annotationProcessorPaths>
<fork>true</fork>
<compilerArgs>
<arg>-Ascijava.ops.parse=${scijava.ops.parse}</arg>
<arg>-Ascijava.ops.opVersion=${project.version}</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<!-- ImgLib2 dependencies -->
<dependency>
Expand Down
13 changes: 10 additions & 3 deletions src/main/java/net/imglib2/mesh/MeshStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,19 @@
package net.imglib2.mesh;

import net.imglib2.mesh.alg.InertiaTensor;
import net.imglib2.type.numeric.real.DoubleType;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;

import net.imglib2.RealPoint;
import net.imglib2.mesh.alg.hull.ConvexHull;
import net.imglib2.mesh.util.MeshUtil;
import org.apache.commons.math3.linear.BlockRealMatrix;
import org.apache.commons.math3.linear.EigenDecomposition;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;

import java.util.ArrayList;
import java.util.List;

/**
* Static utilities that compute various shape descriptors of a mesh.
*/
Expand All @@ -48,6 +51,7 @@ public class MeshStats
/**
* Computes the volume of the specified mesh.
*
* @param mesh the input {@link Mesh}
* @return the volume in physical units.
* @implNote op names='geom.size', label='Geometric (3D): Volume',
* priority='9999.'
Expand Down Expand Up @@ -282,7 +286,7 @@ public static double compactness( final Mesh mesh )
* @param input
* the input mesh.
* @return the centroid of the mesh.
* @implNote op names='geom.centerOfGravity', priority='10000.'
* @implNote op names='geom.centroid', priority='10000.'
*/
public static RealPoint centroid( final Mesh input )
{
Expand Down Expand Up @@ -433,8 +437,11 @@ public static long convexHullVerticesCount(final Mesh input) {


/**
* Describes the spareness of {@code geom.spareness}. Based on ImageJ.
* Describes the spareness of a {@link Mesh}. Spareness is defined as the ratio of the {@code Mesh}'s volume to that of a best-fit ellipsoid.
* Inspiration drawn from ImageJ.
*
* @param input the input {@link Mesh}
* @return the ellipse variance
* @author Tim-Oliver Buchholz (University of Konstanz)
* @implNote op names='geom.spareness', label='Geometric (3D): Spareness',
* priority='10000.'
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/imglib2/mesh/Meshes.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ public static Mesh boundingBoxMesh(final Mesh input) {
* @param src
* Source mesh, from which data will be copied.
* @param dest
* Destination mesh, into which source will be copied.
* Destination mesh, into which source will be copied. (container)
* @implNote op names="engine.copy, copy.mesh"
*/
public static void copy( final net.imglib2.mesh.Mesh src, final net.imglib2.mesh.Mesh dest )
{
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/net/imglib2/mesh/alg/InertiaTensor.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
*/
package net.imglib2.mesh.alg;

import net.imglib2.mesh.Meshes;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.linear.BlockRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
Expand All @@ -54,11 +55,14 @@ public class InertiaTensor
{

/**
* Computes the inertia tensor.
* @param input the input {@link Mesh}
* @return a {@link RealMatrix} whose entries form the inertia tensor
* @implNote op names='geom.secondMoment'
*/
public static RealMatrix calculate( final Mesh input )
{
final RealLocalizable cent = MeshStats.centroid( input );
final RealLocalizable cent = MeshStats.centroid(input);
final double originX = cent.getDoublePosition( 0 );
final double originY = cent.getDoublePosition( 1 );
final double originZ = cent.getDoublePosition( 2 );
Expand Down
39 changes: 32 additions & 7 deletions src/main/java/net/imglib2/mesh/alg/Voxelization.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,13 @@
*/
package net.imglib2.mesh.alg;

import net.imglib2.FinalDimensions;
import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.RealLocalizable;
import net.imglib2.RealPoint;
import net.imglib2.*;
import net.imglib2.img.Img;
import net.imglib2.mesh.Mesh;
import net.imglib2.mesh.Triangle;
import net.imglib2.mesh.Vertices;
import net.imglib2.type.BooleanType;
import net.imglib2.type.logic.BitType;

import net.imglib2.util.Util;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;

Expand All @@ -62,13 +57,43 @@ private Voxelization()
// NB: Prevent instantiation of utility class.
}

/**
* Voxelizes {@code mesh}
*
* @param mesh the input {@link Mesh}
* @param width the width of the resulting image
* @param height the height of the resulting image
* @param depth the depth of the resulting image
* @return an {@link Img} containing a voxelization of {@code mesh}
* @implNote op names="geom.voxelization"
*/
public static Img< BitType > voxelize( Mesh mesh, int width, int height, int depth )
{
Img< BitType > outImg = Util.getSuitableImgFactory( new FinalDimensions( width, height, depth ), new BitType() ).create( width, height, depth );
return voxelize(mesh, new FinalDimensions(width, height, depth));
}

/**
* Voxelizes {@code mesh}
*
* @param mesh the input {@link Mesh}
* @param dims the {@link Dimensions} of the output image
* @return an {@link Img} containing a voxelization of {@code mesh}
* @implNote op names="geom.voxelization"
*/
public static Img< BitType > voxelize( Mesh mesh, Dimensions dims )
{
Img< BitType > outImg = Util.getSuitableImgFactory(dims , new BitType() ).create(dims.dimensionsAsLongArray());
voxelize( mesh, outImg );
return outImg;
}

/**
* Voxelizes {@code mesh}
*
* @param mesh the input {@link Mesh}
* @param out an output buffer in which the voxelization will be stored (container)
* @implNote op names="geom.voxelization"
*/
public static < B extends BooleanType< B > > void voxelize( Mesh mesh, RandomAccessibleInterval< B > out )
{
final long[] dims = out.dimensionsAsLongArray();
Expand Down
63 changes: 63 additions & 0 deletions src/test/java/net/imglib2/mesh/MeshStatsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,60 @@ public void centroid()
}
}

@Test
public void elongation()
{
// The below code creates an octahedron, with all points on an axis.
// The octahedron is stretched on the x-axis, such that the
// elongation on the x-z and x-y principal planes is 0.5
// and the elongation on the y-z plane is 0
Mesh mesh2 = new NaiveDoubleMesh();
mesh2.vertices().add(2, 0, 0);
mesh2.vertices().add(0, 1, 0);
mesh2.vertices().add(0, 0, 1);
mesh2.vertices().add(-2, 0, 0);
mesh2.vertices().add(0, -1, 0);
mesh2.vertices().add(0, 0, -1);
mesh2.triangles().add(0, 2, 1);
mesh2.triangles().add(4, 2, 0);
mesh2.triangles().add(3, 2, 4);
mesh2.triangles().add(1, 2, 3);
mesh2.triangles().add(5, 0, 1);
mesh2.triangles().add(5, 4, 0);
mesh2.triangles().add(5, 3, 4);
mesh2.triangles().add(5, 1, 3);
final double[] expected = { //
0.0, 0.5, 0.5, //
0.5, 0.0, 0.0, //
0.5, 0.0, 0.0 //
};
final RealMatrix actual = MeshStats.elongation(mesh2);
actual.walkInRowOrder( new RealMatrixChangingVisitor()
{

private int i = 0;

@Override
public double visit( final int row, final int column, final double value )
{
final double e = expected[ i++ ];
assertEquals( "Incorrect inertia tensor value returned for row " + row + " and column " + column,
e, value, EPSILON );
return 0;
}

@Override
public void start( final int rows, final int columns, final int startRow, final int endRow, final int startColumn, final int endColumn )
{}

@Override
public double end()
{
return 0;
}
} );
}

@Test
public void inertiaTensor()
{
Expand Down Expand Up @@ -168,6 +222,15 @@ public void solidityMesh()
assertEquals( "Incorrect solidity returned.", expected, actual, EPSILON );
}

@Test
public void spareness()
{
final double actual = MeshStats.spareness(mesh);
// ground truth computed with matlab
final double expected = 0.9838757743034947;
assertEquals( "Incorrect sphericity returned.", expected, actual, EPSILON );
}

@Test
public void sphericity()
{
Expand Down

0 comments on commit 232a976

Please sign in to comment.