use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class Profile method measure.
/**
* Assumes Z-coord sorted list of profiles, as stored in a "profile_list" ProjectThing type. .
*/
public static ResultsTable measure(final Profile[] profiles, ResultsTable rt, final long profile_list_id) {
Utils.log2("profiles.length" + profiles.length);
if (null == profiles || 0 == profiles.length)
return null;
if (1 == profiles.length) {
// don't measure if there is only one
return rt;
}
for (final Profile p : profiles) {
if (null == p || 0 == p.n_points) {
Utils.log("Cannot measure: empty profile " + p + (null != p ? " at layer " + p.getLayer() : ""));
return rt;
}
}
if (null == rt)
rt = Utils.createResultsTable("Profile list results", new String[] { "id", "interpolated surface", "surface: sum of length x thickness", "volume", "name-id" });
final Calibration cal = profiles[0].getLayerSet().getCalibration();
// else, interpolate skin and measure each triangle
// already calibrated
final List<Point3f> tri = makeTriangles(profiles, 1.0);
final int n_tri = tri.size();
if (0 != n_tri % 3) {
Utils.log("Profile.measure error: triangle verts list not a multiple of 3 for profile list id " + profile_list_id);
return rt;
}
// Surface: calibrated sum of the area of all triangles in the mesh.
double surface = 0;
for (int i = 2; i < n_tri; i += 3) {
surface += M.measureArea(tri.get(i - 2), tri.get(i - 1), tri.get(i));
}
// add capping ends
final double area_first = profiles[0].computeArea();
final double area_last = profiles[profiles.length - 1].computeArea();
if (profiles[0].closed)
surface += area_first;
if (profiles[profiles.length - 1].closed)
surface += area_last;
// Surface flat: sum of the perimeter lengths times the layer thickness
double surface_flat = 0;
for (int i = 0; i < profiles.length; i++) {
if (0 == profiles[i].p_i[0].length)
profiles[i].generateInterpolatedPoints(0.05);
surface_flat += profiles[i].computeLength() * profiles[i].layer.getThickness() * cal.pixelWidth;
}
// Volume: area times layer thickness
double volume = area_first * profiles[0].layer.getThickness();
for (int i = 1; i < profiles.length - 1; i++) {
volume += profiles[i].computeArea() * profiles[i].layer.getThickness();
}
volume += area_last * profiles[profiles.length - 1].layer.getThickness();
// calibrate volume: the Z is still in pixels
volume *= cal.pixelWidth;
rt.incrementCounter();
rt.addLabel("units", cal.getUnit());
rt.addValue(0, profile_list_id);
rt.addValue(1, surface);
rt.addValue(2, surface_flat);
rt.addValue(3, volume);
double nameid = 0;
try {
nameid = Double.parseDouble(profiles[0].project.findProjectThing(profiles[0]).getParent().getTitle());
} catch (final NumberFormatException nfe) {
}
rt.addValue(4, nameid);
return rt;
}
use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class Tree method generateSkeleton.
/**
* @return a CustomLineMesh.PAIRWISE list for a LineMesh.
*/
public MeshData generateSkeleton(final double scale_, final int parallels, final int resample) {
if (null == root)
return null;
final ArrayList<Point3f> list = new ArrayList<Point3f>();
final ArrayList<Color3f> colors = new ArrayList<Color3f>();
// Simulate recursion
final LinkedList<Node<T>> todo = new LinkedList<Node<T>>();
todo.add(root);
final float scale = (float) scale_;
final Calibration cal = layer_set.getCalibration();
final float pixelWidthScaled = (float) cal.pixelWidth * scale;
final float pixelHeightScaled = (float) cal.pixelHeight * scale;
final int sign = cal.pixelDepth < 0 ? -1 : 1;
final float[] fps = new float[2];
final Map<Node<T>, Point3f> points = new HashMap<Node<T>, Point3f>();
// A few performance tests are needed:
// 1 - if the map caching of points helps or recomputing every time is cheaper than lookup
// 2 - if removing no-longer-needed points from the map helps lookup or overall slows down
//
// The method, by the way, is very parallelizable: each is independent.
final HashMap<Color, Color3f> cached_colors = new HashMap<Color, Color3f>();
final Color3f cf = new Color3f(this.color);
cached_colors.put(this.color, cf);
boolean go = true;
while (go) {
final Node<T> node = todo.removeFirst();
// Add children to todo list if any
if (null != node.children) {
for (final Node<T> nd : node.children) todo.add(nd);
}
go = !todo.isEmpty();
// Get node's 3D coordinate
Point3f p = points.get(node);
if (null == p) {
fps[0] = node.x;
fps[1] = node.y;
this.at.transform(fps, 0, fps, 0, 1);
p = new Point3f(fps[0] * pixelWidthScaled, fps[1] * pixelHeightScaled, (float) node.la.getZ() * pixelWidthScaled * sign);
points.put(node, p);
}
if (null != node.parent) {
// Create a line to the parent
list.add(points.get(node.parent));
list.add(p);
if (null == node.color) {
colors.add(cf);
// twice: a line segment
colors.add(cf);
} else {
Color3f c = cached_colors.get(node.color);
if (null == c) {
c = new Color3f(node.color);
cached_colors.put(node.color, c);
}
colors.add(c);
// twice: a line segment
colors.add(c);
}
if (go && node.parent != todo.getFirst().parent) {
// node.parent point no longer needed (last child just processed)
points.remove(node.parent);
}
}
}
// Utils.log2("Skeleton MeshData lists of same length: " + (list.size() == colors.size()));
return new MeshData(list, colors);
}
use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class Treeline method addTriangles.
private static final void addTriangles(final List<Point3f> ps, final List<Point3f> parent_verts, final List<Point3f> child_verts, final int i0, final int i1) {
// one triangle
ps.add(new Point3f(parent_verts.get(i0)));
ps.add(new Point3f(parent_verts.get(i1)));
ps.add(new Point3f(child_verts.get(i0)));
// another
ps.add(new Point3f(parent_verts.get(i1)));
ps.add(new Point3f(child_verts.get(i1)));
ps.add(new Point3f(child_verts.get(i0)));
}
Aggregations