diff --git a/.gitignore b/.gitignore index b0a9905575783f18d92dd5f505a52d187802980d..57f16fb67c1b1589981416b323d7a9debc728665 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,41 @@ -.idea/ -.settings/ -build/ +/build* +/workspace +setting.xml +release/ target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +icy.log + +### IntelliJ IDEA ### +.idea/ +*.iws *.iml +*.ipr + +### Eclipse ### +.apt_generated .classpath +.factorypath .project -**/.DS_Store \ No newline at end of file +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +**/.DS_Store +Icon? \ No newline at end of file diff --git a/pom.xml b/pom.xml index b5454c536209a709a3ea1bebe7dd073fa0cb9d6e..b3cfb94422f755cb869fe48c57a7dd7fbbeba45c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,13 +7,11 @@ <parent> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>pom-icy</artifactId> - <version>2.2.0</version> + <version>3.0.0-a.1</version> </parent> <artifactId>quickhull</artifactId> - <version>2.0.0</version> - - <packaging>jar</packaging> + <version>2.0.0-a.1</version> <name>QuickHull</name> <description> @@ -30,8 +28,7 @@ <repositories> <repository> <id>icy</id> - <url>https://icy-nexus.pasteur.fr/repository/Icy/</url> + <url>https://nexus-icy.pasteur.cloud/repository/icy/</url> </repository> </repositories> - </project> \ No newline at end of file diff --git a/src/main/java/plugins/adufour/quickhull/Face.java b/src/main/java/plugins/adufour/quickhull/Face.java index 042eea7dd17d6ed255403726a30c6fbff8f6c7e2..2afe11a2eb3e0d862f81a5f8308aa640a39e9a39 100644 --- a/src/main/java/plugins/adufour/quickhull/Face.java +++ b/src/main/java/plugins/adufour/quickhull/Face.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,6 +18,8 @@ package plugins.adufour.quickhull; +import org.jetbrains.annotations.NotNull; + import javax.vecmath.Vector3d; /** @@ -30,7 +32,7 @@ import javax.vecmath.Vector3d; * * @author John E. Lloyd, Fall 2004 */ -class Face { +public class Face { HalfEdge he0; private final Vector3d normal; double area; @@ -49,7 +51,7 @@ class Face { Vertex outside; - public void computeCentroid(final Vector3d centroid) { + public void computeCentroid(final @NotNull Vector3d centroid) { centroid.set(0, 0, 0); HalfEdge he = he0; do { @@ -95,7 +97,7 @@ class Face { } } - public void computeNormal(final Vector3d normal) { + public void computeNormal(final @NotNull Vector3d normal) { HalfEdge he1 = he0.next; HalfEdge he2 = he1.next; @@ -153,7 +155,7 @@ class Face { planeOffset = normal.dot(centroid); } - public static Face createTriangle(final Vertex v0, final Vertex v1, final Vertex v2) { + public static @NotNull Face createTriangle(final Vertex v0, final Vertex v1, final Vertex v2) { return createTriangle(v0, v1, v2, 0); } @@ -164,7 +166,7 @@ class Face { * @param v1 second vertex * @param v2 third vertex */ - public static Face createTriangle(final Vertex v0, final Vertex v1, final Vertex v2, final double minArea) { + public static @NotNull Face createTriangle(final Vertex v0, final Vertex v1, final Vertex v2, final double minArea) { final Face face = new Face(); final HalfEdge he0 = new HalfEdge(v0, face); final HalfEdge he1 = new HalfEdge(v1, face); @@ -184,7 +186,7 @@ class Face { return face; } - public static Face create(final Vertex[] vtxArray, final int[] indices) { + public static @NotNull Face create(final Vertex[] vtxArray, final int @NotNull [] indices) { final Face face = new Face(); HalfEdge hePrev = null; for (final int j : indices) { @@ -261,7 +263,7 @@ class Face { * @param p the point * @return distance from the point to the plane */ - public double distanceToPlane(final Vector3d p) { + public double distanceToPlane(final @NotNull Vector3d p) { return normal.x * p.x + normal.y * p.y + normal.z * p.z - planeOffset; } @@ -297,7 +299,7 @@ class Face { return s.toString(); } - public void getVertexIndices(final int[] idxs) { + public void getVertexIndices(final int @NotNull [] idxs) { HalfEdge he = he0; int i = 0; do { @@ -306,7 +308,7 @@ class Face { } while (he != he0); } - private Face connectHalfEdges(final HalfEdge hedgePrev, final HalfEdge hedge) { + private Face connectHalfEdges(final @NotNull HalfEdge hedgePrev, final @NotNull HalfEdge hedge) { Face discardedFace = null; if (hedgePrev.oppositeFace() == hedge.oppositeFace()) { // then there is a redundant edge that we can get rid off @@ -389,7 +391,7 @@ class Face { } - public int mergeAdjacentFace(final HalfEdge hedgeAdj, final Face[] discarded) { + public int mergeAdjacentFace(final @NotNull HalfEdge hedgeAdj, final Face @NotNull [] discarded) { final Face oppFace = hedgeAdj.oppositeFace(); int numDiscarded = 0; @@ -481,6 +483,5 @@ class Face { for (Face face = face0; face != null; face = face.next) { face.checkConsistency(); } - } } diff --git a/src/main/java/plugins/adufour/quickhull/FaceList.java b/src/main/java/plugins/adufour/quickhull/FaceList.java index 1713a1210f3e7f2a95204e28ae8d411044df3dac..be6d7b2bd91077ffbd2675d079c2af26a152256b 100644 --- a/src/main/java/plugins/adufour/quickhull/FaceList.java +++ b/src/main/java/plugins/adufour/quickhull/FaceList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ package plugins.adufour.quickhull; /** * Maintains a single-linked list of faces for use by QuickHull3D */ -class FaceList { +public class FaceList { private Face head; private Face tail; diff --git a/src/main/java/plugins/adufour/quickhull/HalfEdge.java b/src/main/java/plugins/adufour/quickhull/HalfEdge.java index 1290f57b48b741c00bddc7dfb2856f9357f303a8..e31d21e232f13a407a5bb9027cccf15c320cf6e9 100644 --- a/src/main/java/plugins/adufour/quickhull/HalfEdge.java +++ b/src/main/java/plugins/adufour/quickhull/HalfEdge.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,6 +18,9 @@ package plugins.adufour.quickhull; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import javax.vecmath.Vector3d; /** @@ -25,7 +28,7 @@ import javax.vecmath.Vector3d; * * @author John E. Lloyd, Fall 2004 */ -class HalfEdge { +public class HalfEdge { /** * The vertex associated with the head of this half-edge. */ @@ -58,11 +61,13 @@ class HalfEdge { * @param v head vertex * @param f left-hand triangular face */ + @Contract(pure = true) public HalfEdge(final Vertex v, final Face f) { vertex = v; face = f; } + @Contract(pure = true) public HalfEdge() { } @@ -125,7 +130,7 @@ class HalfEdge { * * @param edge opposite half-edge */ - public void setOpposite(final HalfEdge edge) { + public void setOpposite(final @NotNull HalfEdge edge) { opposite = edge; edge.opposite = this; } diff --git a/src/main/java/plugins/adufour/quickhull/QuickHull.java b/src/main/java/plugins/adufour/quickhull/QuickHull.java index 1be8ced11f2604d7018236dd257eade51d8375f9..5277b47d54fe474a364af75cb1d45163c1c0ec1f 100644 --- a/src/main/java/plugins/adufour/quickhull/QuickHull.java +++ b/src/main/java/plugins/adufour/quickhull/QuickHull.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,8 +18,10 @@ package plugins.adufour.quickhull; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginLibrary; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginLibrary; /** * Main class of the QuickHull library for Icy @@ -29,6 +31,8 @@ import icy.plugin.interface_.PluginLibrary; * * @author Alexandre Dufour */ +@IcyPluginName("QuickHull") +@IcyPluginIcon(path = "/quickhull.png") public class QuickHull extends Plugin implements PluginLibrary { } diff --git a/src/main/java/plugins/adufour/quickhull/QuickHull2D.java b/src/main/java/plugins/adufour/quickhull/QuickHull2D.java index 2f2542b8f2f76c693bed3e76cf24335e41fe4866..df97cf9c6e539cf00dfbe39ac59f780eb4ef22b4 100644 --- a/src/main/java/plugins/adufour/quickhull/QuickHull2D.java +++ b/src/main/java/plugins/adufour/quickhull/QuickHull2D.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,21 +18,24 @@ package plugins.adufour.quickhull; -import icy.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.jetbrains.annotations.NotNull; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; +@IcyPluginName("QuickHull 2D") public class QuickHull2D extends Plugin { - public static List<Point2D> computeConvexEnvelope(final List<Point2D> points) { + public static @NotNull List<Point2D> computeConvexEnvelope(final @NotNull List<Point2D> points) { final ArrayList<Point2D> envelope = new ArrayList<>(); // find two points: right (bottom) and left (top) - Point2D l = points.get(0); - Point2D r = points.get(0); + Point2D l = points.getFirst(); + Point2D r = points.getFirst(); for (int i = 1; i < points.size(); i++) { final Point2D p = points.get(i); @@ -69,8 +72,8 @@ public class QuickHull2D extends Plugin { return envelope; } - private static void quickhull(final ArrayList<Point2D> envelope, final Point2D a, final Point2D b, final ArrayList<Point2D> neighbors) { - if (neighbors.size() == 0) return; + private static void quickhull(final ArrayList<Point2D> envelope, final Point2D a, final Point2D b, final @NotNull ArrayList<Point2D> neighbors) { + if (neighbors.isEmpty()) return; final Point2D c = farthestpoint(a, b, neighbors); @@ -95,7 +98,7 @@ public class QuickHull2D extends Plugin { quickhull(envelope, c, b, al2); } - private static Point2D farthestpoint(final Point2D a, final Point2D b, final ArrayList<Point2D> points) { + private static Point2D farthestpoint(final Point2D a, final Point2D b, final @NotNull ArrayList<Point2D> points) { double maxD = -1; Point2D maxP = null; diff --git a/src/main/java/plugins/adufour/quickhull/QuickHull3D.java b/src/main/java/plugins/adufour/quickhull/QuickHull3D.java index dac0a2f64c73c3a27a01d3b946d9216b37939689..d370f7991c9cbf7d0e0fdb9a732d8dbdb80b6bcd 100644 --- a/src/main/java/plugins/adufour/quickhull/QuickHull3D.java +++ b/src/main/java/plugins/adufour/quickhull/QuickHull3D.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -17,6 +17,10 @@ */ package plugins.adufour.quickhull; +import org.bioimageanalysis.icy.system.logging.IcyLogger; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import java.io.*; @@ -224,7 +228,7 @@ public class QuickHull3D { return explicitTolerance; } - private void addPointToFace(final Vertex vtx, final Face face) { + private void addPointToFace(final @NotNull Vertex vtx, final @NotNull Face face) { vtx.face = face; if (face.outside == null) { @@ -236,7 +240,7 @@ public class QuickHull3D { face.outside = vtx; } - private void removePointFromFace(final Vertex vtx, final Face face) { + private void removePointFromFace(final Vertex vtx, final @NotNull Face face) { if (vtx == face.outside) { if (vtx.next != null && vtx.next.face == face) { face.outside = vtx.next; @@ -248,7 +252,7 @@ public class QuickHull3D { claimed.delete(vtx); } - private Vertex removeAllPointsFromFace(final Face face) { + private @Nullable Vertex removeAllPointsFromFace(final @NotNull Face face) { if (face.outside != null) { Vertex end = face.outside; while (end.next != null && end.next.face == face) { @@ -293,7 +297,7 @@ public class QuickHull3D { build(points, points.length); } - private HalfEdge findHalfEdge(final Vertex tail, final Vertex head) { + private @Nullable HalfEdge findHalfEdge(final Vertex tail, final Vertex head) { // brute force ... OK, since setHull is not used much for (final Face face : faces) { final HalfEdge he = face.findEdge(tail, head); @@ -322,7 +326,7 @@ public class QuickHull3D { } } - private void printQhullErrors(final Process proc) throws IOException { + private void printQhullErrors(final @NotNull Process proc) throws IOException { boolean wrote = false; final InputStream es = proc.getErrorStream(); while (es.available() > 0) { @@ -340,7 +344,7 @@ public class QuickHull3D { commandStr += " -Qt"; } try { - final Process proc = Runtime.getRuntime().exec(commandStr); + final Process proc = Runtime.getRuntime().exec(commandStr); // FIXME change command from String to String[] final PrintStream ps = new PrintStream(proc.getOutputStream()); final StreamTokenizer stok = new StreamTokenizer(new InputStreamReader(proc.getInputStream())); @@ -374,7 +378,7 @@ public class QuickHull3D { System.out.println("Expecting face index"); System.exit(1); } - indexList.add(0, (int) stok.nval); + indexList.addFirst((int) stok.nval); } faceIndices[i] = new int[indexList.size()]; int k = 0; @@ -385,8 +389,9 @@ public class QuickHull3D { setHull(coords, nump, faceIndices, numf); } catch (final Exception e) { - e.printStackTrace(); - System.exit(1); + IcyLogger.fatal(this.getClass(), e, e.getLocalizedMessage()); + //System.exit(1); + throw new RuntimeException(e); } } @@ -878,7 +883,7 @@ public class QuickHull3D { } } - private void getFaceIndices(final int[] indices, final Face face, final int flags) { + private void getFaceIndices(final int[] indices, final @NotNull Face face, final int flags) { final boolean ccw = ((flags & CLOCKWISE) == 0); final boolean indexedFromOne = ((flags & INDEXED_FROM_ONE) != 0); final boolean pointRelative = ((flags & POINT_RELATIVE) != 0); @@ -956,11 +961,11 @@ public class QuickHull3D { private static final int NONCONVEX_WRT_LARGER_FACE = 1; private static final int NONCONVEX = 2; - protected double oppFaceDistance(final HalfEdge he) { + protected double oppFaceDistance(final @NotNull HalfEdge he) { return he.face.distanceToPlane(he.opposite.face.getCentroid()); } - private boolean doAdjacentMerge(final Face face, final int mergeType) { + private boolean doAdjacentMerge(final @NotNull Face face, final int mergeType) { HalfEdge hedge = face.he0; boolean convex = true; @@ -1050,14 +1055,14 @@ public class QuickHull3D { } while (edge != edge0); } - private HalfEdge addAdjoiningFace(final Vertex eyeVtx, final HalfEdge he) { + private HalfEdge addAdjoiningFace(final Vertex eyeVtx, final @NotNull HalfEdge he) { final Face face = Face.createTriangle(eyeVtx, he.tail(), he.head()); faces.add(face); face.getEdge(-1).setOpposite(he.getOpposite()); return face.getEdge(0); } - protected void addNewFaces(final FaceList newFaces, final Vertex eyeVtx, final Vector<HalfEdge> horizon) { + protected void addNewFaces(final @NotNull FaceList newFaces, final Vertex eyeVtx, final @NotNull Vector<HalfEdge> horizon) { newFaces.clear(); HalfEdge hedgeSidePrev = null; @@ -1153,7 +1158,7 @@ public class QuickHull3D { } } - private void markFaceVertices(final Face face, final int mark) { + private void markFaceVertices(final @NotNull Face face, final int mark) { final HalfEdge he0 = face.getFirstEdge(); HalfEdge he = he0; do { @@ -1189,7 +1194,7 @@ public class QuickHull3D { } } - protected boolean checkFaceConvexity(final Face face, final double tol, final PrintStream ps) { + protected boolean checkFaceConvexity(final @NotNull Face face, final double tol, final PrintStream ps) { double dist; HalfEdge he = face.he0; do { diff --git a/src/main/java/plugins/adufour/quickhull/Vertex.java b/src/main/java/plugins/adufour/quickhull/Vertex.java index b652810c483efa49a5b10f856204856ba50a1697..cdbbfc37cc0db3dfc798171e122f98726bf6c73d 100644 --- a/src/main/java/plugins/adufour/quickhull/Vertex.java +++ b/src/main/java/plugins/adufour/quickhull/Vertex.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,6 +18,8 @@ package plugins.adufour.quickhull; +import org.jetbrains.annotations.Contract; + import javax.vecmath.Vector3d; /** @@ -26,7 +28,7 @@ import javax.vecmath.Vector3d; * * @author John E. Lloyd, Fall 2004 */ -class Vertex { +public class Vertex { /** * Spatial point associated with this vertex. */ @@ -55,6 +57,7 @@ class Vertex { /** * Constructs a vertex and sets its coordinates to 0. */ + @Contract(pure = true) public Vertex() { pnt = new Vector3d(); } @@ -63,6 +66,7 @@ class Vertex { * Constructs a vertex with the specified coordinates * and index. */ + @Contract(pure = true) public Vertex(final double x, final double y, final double z, final int idx) { pnt = new Vector3d(x, y, z); index = idx; diff --git a/src/main/java/plugins/adufour/quickhull/VertexList.java b/src/main/java/plugins/adufour/quickhull/VertexList.java index f6d6247b1b9a65228fc201e3635a1461b67ce9e9..2b6816f191a0f48ec14b3dad4bbaf261066dad27 100644 --- a/src/main/java/plugins/adufour/quickhull/VertexList.java +++ b/src/main/java/plugins/adufour/quickhull/VertexList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2023. Institut Pasteur. + * Copyright (c) 2010-2024. Institut Pasteur. * * This file is part of Icy. * Icy is free software: you can redistribute it and/or modify @@ -18,10 +18,12 @@ package plugins.adufour.quickhull; +import org.jetbrains.annotations.NotNull; + /** * Maintains a double-linked list of vertices for use by QuickHull3D */ -class VertexList { +public class VertexList { private Vertex head; private Vertex tail; @@ -67,7 +69,7 @@ class VertexList { /** * Deletes a vertex from this list. */ - public void delete(final Vertex vtx) { + public void delete(final @NotNull Vertex vtx) { if (vtx.prev == null) { head = vtx.next; } @@ -85,7 +87,7 @@ class VertexList { /** * Deletes a chain of vertices from this list. */ - public void delete(final Vertex vtx1, final Vertex vtx2) { + public void delete(final @NotNull Vertex vtx1, final Vertex vtx2) { if (vtx1.prev == null) { head = vtx2.next; } @@ -103,7 +105,7 @@ class VertexList { /** * Inserts a vertex into this list before another specificed vertex. */ - public void insertBefore(final Vertex vtx, final Vertex next) { + public void insertBefore(final @NotNull Vertex vtx, final @NotNull Vertex next) { vtx.prev = next.prev; if (next.prev == null) { head = vtx; diff --git a/src/main/resources/quickhull.png b/src/main/resources/quickhull.png new file mode 100644 index 0000000000000000000000000000000000000000..9c8c783a833888f37d0123b8de62ecbe8cdd7ea6 Binary files /dev/null and b/src/main/resources/quickhull.png differ