Skip to content

Commit

Permalink
Filter out redundant surface mesh vertices (#340)
Browse files Browse the repository at this point in the history
Triangles in the surface mesh share vertices but the vertices are
repeated for every triangle in the mesh. This change reduces the number
of points for the surface by 4-6× and should in principle reduce the
time for brute-force all-to-all calculations used by Feret max by
16-36×.
  • Loading branch information
mdoube committed Apr 5, 2024
1 parent 8faa059 commit d3618cd
Showing 1 changed file with 30 additions and 4 deletions.
34 changes: 30 additions & 4 deletions Legacy/bonej/src/main/java/org/bonej/plugins/ParticleAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -970,6 +971,7 @@ static double[] getSurfaceVolume(final Collection<List<Point3f>> surfacePoints)
* points' coordinates are in the following 6 positions in ax, ay, az, bx, by, bz order.
*/
static double[][] getFerets(final List<List<Point3f>> surfacePoints) {

Thread[] threads = Multithreader.newThreads();
final int nSurfaces = surfacePoints.size();
//distance, xa, ya, za, xb, yb, zb
Expand All @@ -978,8 +980,8 @@ static double[][] getFerets(final List<List<Point3f>> surfacePoints) {
for (int thread = 0; thread < threads.length; thread++) {
threads[thread] = new Thread(() -> {
for (int i = ai.getAndIncrement(); i < nSurfaces; i = ai.getAndIncrement()) {
final List<Point3f> surface = surfacePoints.get(i);


final List<Point3f> surface = filterSurfacePoints(surfacePoints.get(i));

if (surface == null) {
Arrays.fill(ferets[i], Double.NaN);
Expand All @@ -988,8 +990,8 @@ static double[][] getFerets(final List<List<Point3f>> surfacePoints) {

final int nPoints = surface.size();

//4 triangles * 3 points for the minimal tetrahedron
if (nPoints < 12) {
//4 points for the minimal tetrahedron
if (nPoints < 4) {
Arrays.fill(ferets[i], Double.NaN);
}

Expand Down Expand Up @@ -1039,6 +1041,8 @@ static Object[] getEllipsoids(final Collection<List<Point3f>> surfacePoints) {
if (surface == null)
return null;

surface = filterSurfacePoints(surface);

final Iterator<Point3f> pointIter = surface.iterator();
final double[][] coOrdinates = new double[surface.size()][3];
int i = 0;
Expand Down Expand Up @@ -1087,4 +1091,26 @@ private static Point3f crossProduct(final Point3f point0,
crossVector.z = (float) (x1 * y2 - y1 * x2);
return crossVector;
}

/**
* Remove redundant vertices from the surface point list that occur because
* triangles in the surface mesh share vertices.
*
* It cuts down the number of points by a factor of 4-6, which should
* speed up O(n²) processes like Feret max by a factor of 16-36×
*
* @param surface list of surface points, in Point3f format
* @return the same points but with duplicates removed
*/
private static List<Point3f> filterSurfacePoints(final List<Point3f> surface){
if (surface == null)
return null;

HashSet<Point3f> filteredSurface = new HashSet<>();
final int nPoints = surface.size();
for (int i = 0; i < nPoints; i++) {
filteredSurface.add(surface.get(i));
}
return new ArrayList<>(filteredSurface);
}
}

0 comments on commit d3618cd

Please sign in to comment.