Skip to content

Commit 192fbac

Browse files
committed
WIP
1 parent abb1917 commit 192fbac

File tree

6 files changed

+152
-17
lines changed

6 files changed

+152
-17
lines changed

pom.xml

+24
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@
122122
<releaseProfiles>sign,deploy-to-scijava</releaseProfiles>
123123

124124
<imageio-tiff.version>3.9.4</imageio-tiff.version>
125+
126+
<scijava.ops.parse>true</scijava.ops.parse>
125127
</properties>
126128

127129
<repositories>
@@ -131,6 +133,28 @@
131133
</repository>
132134
</repositories>
133135

136+
<build>
137+
<plugins>
138+
<plugin>
139+
<artifactId>maven-compiler-plugin</artifactId>
140+
<configuration>
141+
<annotationProcessorPaths>
142+
<path>
143+
<groupId>org.scijava</groupId>
144+
<artifactId>scijava-ops-indexer</artifactId>
145+
<version>1.0.1-SNAPSHOT</version>
146+
</path>
147+
</annotationProcessorPaths>
148+
<fork>true</fork>
149+
<compilerArgs>
150+
<arg>-Ascijava.ops.parse=${scijava.ops.parse}</arg>
151+
<arg>-Ascijava.ops.opVersion=${project.version}</arg>
152+
</compilerArgs>
153+
</configuration>
154+
</plugin>
155+
</plugins>
156+
</build>
157+
134158
<dependencies>
135159
<!-- ImgLib2 dependencies -->
136160
<dependency>

src/main/java/net/imglib2/mesh/MeshStats.java

+81-8
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class MeshStats
4848
/**
4949
* Computes the volume of the specified mesh.
5050
*
51+
* @param mesh the input {@link Mesh}
5152
* @return the volume in physical units.
5253
* @implNote op names='geom.size', label='Geometric (3D): Volume',
5354
* priority='9999.'
@@ -282,7 +283,7 @@ public static double compactness( final Mesh mesh )
282283
* @param input
283284
* the input mesh.
284285
* @return the centroid of the mesh.
285-
* @implNote op names='geom.centerOfGravity', priority='10000.'
286+
* @implNote op names='geom.centroid', priority='10000.'
286287
*/
287288
public static RealPoint centroid( final Mesh input )
288289
{
@@ -340,6 +341,75 @@ public static RealPoint centroid( final Mesh input )
340341
return new RealPoint( m100 / v, m010 / v, m001 / v );
341342
}
342343

344+
/**
345+
* Returns the centroid of the mesh, that is the center of gravity of its
346+
* volume.
347+
* <p>
348+
* (As a side note, {@link Meshes#center(Mesh)} returns the center of
349+
* gravity of the mesh's surface.)
350+
*
351+
* @author Jean-Yves Tinevez
352+
* @param input
353+
* the input mesh.
354+
* @return the centroid of the mesh.
355+
* @implNote op names='geom.centerOfGravity', priority='10000.'
356+
*/
357+
public static RealPoint centroid2( final Mesh input )
358+
{
359+
// Variable names from moment definition.
360+
double m100 = 0.;
361+
double m010 = 0.;
362+
double m001 = 0.;
363+
for ( int i = 0; i < input.triangles().size(); i++ )
364+
{
365+
final long v0 = input.triangles().vertex0( i );
366+
final long v1 = input.triangles().vertex1( i );
367+
final long v2 = input.triangles().vertex2( i );
368+
369+
final double x1 = input.vertices().x( v0 );
370+
final double y1 = input.vertices().y( v0 );
371+
final double z1 = input.vertices().z( v0 );
372+
final double x2 = input.vertices().x( v1 );
373+
final double y2 = input.vertices().y( v1 );
374+
final double z2 = input.vertices().z( v1 );
375+
final double x3 = input.vertices().x( v2 );
376+
final double y3 = input.vertices().y( v2 );
377+
final double z3 = input.vertices().z( v2 );
378+
final double[] normals = new double[3];
379+
// If
380+
MeshUtil.cross(
381+
// v1 - v0
382+
x2 - x1, //
383+
y2 - y1, //
384+
z2 - z1, //
385+
// v2 - v0
386+
x3 - x1, //
387+
y3 - y1, //
388+
z3 - z1, //
389+
normals);
390+
final double normalDot =
391+
input.triangles().nx(i) * normals[0] +
392+
input.triangles().ny(i) * normals[1] +
393+
input.triangles().nz(i) * normals[2];
394+
if (normalDot < 0) {
395+
throw new IllegalStateException("foooooo");
396+
}
397+
398+
399+
final double detA = //
400+
x1 * (y2 * z3 - y3 * z2) - //
401+
x2 * (y1 * z3 - y3 * z1) + //
402+
x3 * (y1 * z2 - y2 * z1);
403+
404+
m100 += (1d / 24) * detA * (x1 + x2 + x3);
405+
m010 += (1d / 24) * detA * (y1 + y2 + y3);
406+
m001 += (1d / 24) * detA * (z1 + z2 + z3);
407+
}
408+
409+
final double v = volume( input );
410+
return new RealPoint( m100 / v, m010 / v, m001 / v );
411+
}
412+
343413
/**
344414
* Describes the elogation of a {@link Mesh}. As elongation is a metric of a
345415
* two-dimensional object, this functionality describes elongation as a
@@ -433,13 +503,16 @@ public static long convexHullVerticesCount(final Mesh input) {
433503

434504

435505
/**
436-
* Describes the spareness of {@code geom.spareness}. Based on ImageJ.
437-
*
438-
* @author Tim-Oliver Buchholz (University of Konstanz)
439-
* @implNote op names='geom.spareness', label='Geometric (3D): Spareness',
440-
* priority='10000.'
441-
*/
442-
public static double spareness(final Mesh input) {
506+
* Describes the ellipse variance of a {@link Mesh}. Ellipse variance is defined as the ratio of the {@code Mesh}'s volume to that of an ellipsoid with an identical bounding box.
507+
* Inspiration drawn from <a href="https://hal.science/hal-00446037/PDF/ARS-Journal-SurveyPatternRecognition.pdf">here<a>
508+
*
509+
* @param input the input {@link Mesh}
510+
* @return the ellipse variance
511+
* @author Tim-Oliver Buchholz (University of Konstanz)
512+
* @implNote op names='geom.ellipseVariance, geom.ellipticity, geom.spareness', label='Geometric (3D): Spareness',
513+
* priority='10000.'
514+
*/
515+
public static double ellipseVariance(final Mesh input) {
443516
final RealMatrix it = InertiaTensor.calculate(input);
444517
final EigenDecomposition ed = new EigenDecomposition(it);
445518

src/main/java/net/imglib2/mesh/Meshes.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ public static Mesh boundingBoxMesh(final Mesh input) {
152152
* @param src
153153
* Source mesh, from which data will be copied.
154154
* @param dest
155-
* Destination mesh, into which source will be copied.
155+
* Destination mesh, into which source will be copied. (container)
156+
* @implNote op names="engine.copy, copy.mesh"
156157
*/
157158
public static void copy( final net.imglib2.mesh.Mesh src, final net.imglib2.mesh.Mesh dest )
158159
{

src/main/java/net/imglib2/mesh/alg/InertiaTensor.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
*/
2929
package net.imglib2.mesh.alg;
3030

31+
import net.imglib2.mesh.Meshes;
3132
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
3233
import org.apache.commons.math3.linear.BlockRealMatrix;
3334
import org.apache.commons.math3.linear.RealMatrix;
@@ -54,11 +55,14 @@ public class InertiaTensor
5455
{
5556

5657
/**
58+
* Computes the inertia tensor.
59+
* @param input the input {@link Mesh}
60+
* @return a {@link RealMatrix} whose entries form the inertia tensor
5761
* @implNote op names='geom.secondMoment'
5862
*/
5963
public static RealMatrix calculate( final Mesh input )
6064
{
61-
final RealLocalizable cent = MeshStats.centroid( input );
65+
final RealLocalizable cent = MeshStats.centroid(input);
6266
final double originX = cent.getDoublePosition( 0 );
6367
final double originY = cent.getDoublePosition( 1 );
6468
final double originZ = cent.getDoublePosition( 2 );

src/main/java/net/imglib2/mesh/alg/Voxelization.java

+32-7
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,13 @@
2828
*/
2929
package net.imglib2.mesh.alg;
3030

31-
import net.imglib2.FinalDimensions;
32-
import net.imglib2.RandomAccess;
33-
import net.imglib2.RandomAccessibleInterval;
34-
import net.imglib2.RealLocalizable;
35-
import net.imglib2.RealPoint;
31+
import net.imglib2.*;
3632
import net.imglib2.img.Img;
3733
import net.imglib2.mesh.Mesh;
3834
import net.imglib2.mesh.Triangle;
3935
import net.imglib2.mesh.Vertices;
4036
import net.imglib2.type.BooleanType;
4137
import net.imglib2.type.logic.BitType;
42-
4338
import net.imglib2.util.Util;
4439
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
4540

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

60+
/**
61+
* Voxelizes {@code mesh}
62+
*
63+
* @param mesh the input {@link Mesh}
64+
* @param width the width of the resulting image
65+
* @param height the height of the resulting image
66+
* @param depth the depth of the resulting image
67+
* @return an {@link Img} containing a voxelization of {@code mesh}
68+
* @implNote op names="geom.voxelization"
69+
*/
6570
public static Img< BitType > voxelize( Mesh mesh, int width, int height, int depth )
6671
{
67-
Img< BitType > outImg = Util.getSuitableImgFactory( new FinalDimensions( width, height, depth ), new BitType() ).create( width, height, depth );
72+
return voxelize(mesh, new FinalDimensions(width, height, depth));
73+
}
74+
75+
/**
76+
* Voxelizes {@code mesh}
77+
*
78+
* @param mesh the input {@link Mesh}
79+
* @param dims the {@link Dimensions} of the output image
80+
* @return an {@link Img} containing a voxelization of {@code mesh}
81+
* @implNote op names="geom.voxelization"
82+
*/
83+
public static Img< BitType > voxelize( Mesh mesh, Dimensions dims )
84+
{
85+
Img< BitType > outImg = Util.getSuitableImgFactory(dims , new BitType() ).create(dims.dimensionsAsLongArray());
6886
voxelize( mesh, outImg );
6987
return outImg;
7088
}
7189

90+
/**
91+
* Voxelizes {@code mesh}
92+
*
93+
* @param mesh the input {@link Mesh}
94+
* @param out an output buffer in which the voxelization will be stored (container)
95+
* @implNote op names="geom.voxelization"
96+
*/
7297
public static < B extends BooleanType< B > > void voxelize( Mesh mesh, RandomAccessibleInterval< B > out )
7398
{
7499
final long[] dims = out.dimensionsAsLongArray();

src/test/java/net/imglib2/mesh/MeshStatsTest.java

+8
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ public void convexityMesh()
141141
assertEquals( "Incorrect convexity returned.", expected, actual, EPSILON );
142142
}
143143

144+
@Test
145+
public void ellipseVariance()
146+
{
147+
final double actual = MeshStats.ellipseVariance( mesh );
148+
final double expected = 0.9838757743034947;
149+
assertEquals( "Incorrect ellipse variance returned.", expected, actual, EPSILON );
150+
}
151+
144152
@Test
145153
public void sizeConvexHullMesh()
146154
{

0 commit comments

Comments
 (0)