use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class Polyline method generateTriangles.
/**
* Returns a list of Point3f that define a polyline in 3D, for usage with an ij3d CustomLineMesh CONTINUOUS. @param parallels is ignored.
*/
public synchronized List<Point3f> generateTriangles(final double scale, final int parallels, final int resample, final Calibration cal) {
if (-1 == n_points)
setupForDisplay();
if (0 == n_points)
return null;
// local pointers, since they may be transformed
final int n_points;
final double[][] p;
if (!this.at.isIdentity()) {
final Object[] ob = getTransformedData();
p = (double[][]) ob[0];
n_points = p[0].length;
} else {
n_points = this.n_points;
p = this.p;
}
final ArrayList<Point3f> list = new ArrayList<Point3f>();
final double KW = scale * cal.pixelWidth * resample;
final double KH = scale * cal.pixelHeight * resample;
for (int i = 0; i < n_points; i++) {
list.add(new Point3f((float) (p[0][i] * KW), (float) (p[1][i] * KH), (float) (layer_set.getLayer(p_layer[i]).getZ() * KW)));
}
if (n_points < 2) {
// Duplicate first point
list.add(list.get(0));
}
return list;
}
use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class Profile method generateTriangles.
/**
* Takes a profile_list, scans for its Profile children, makes sublists of continuous profiles (if they happen to be branched), and then creates triangles for them using weighted vector strings.
*/
public static List<Point3f> generateTriangles(final ProjectThing pt, final double scale) {
if (!pt.getType().equals("profile_list")) {
Utils.log2("Profile: ignoring unhandable ProjectThing type.");
return null;
}
// should be sorted by Z already
final ArrayList<ProjectThing> al = pt.getChildren();
if (al.size() < 2) {
Utils.log("profile_list " + pt + " has less than two profiles: can't render in 3D.");
return null;
}
// collect all Profile
final HashSet<Profile> hs = new HashSet<Profile>();
for (final ProjectThing child : al) {
final Object ob = child.getObject();
if (ob instanceof Profile) {
hs.add((Profile) ob);
} else {
Utils.log2("Render: skipping non Profile class child");
}
}
// Create sublists of profiles, following the chain of links.
final Profile[] p = new Profile[hs.size()];
hs.toArray(p);
// find if at least one is visible
boolean hidden = true;
for (int i = 0; i < p.length; i++) {
if (p[i].visible) {
hidden = false;
break;
}
if (null == p[i] || 0 == p[i].n_points) {
Utils.log("Cannot generate triangle mesh: empty profile " + p[i] + (null != p[i] ? " at layer " + p[i].getLayer() : ""));
return null;
}
}
if (hidden)
return null;
// collect starts and ends
final HashSet<Profile> hs_bases = new HashSet<Profile>();
final HashSet<Profile> hs_done = new HashSet<Profile>();
final List<Point3f> triangles = new ArrayList<Point3f>();
do {
Profile base = null;
// choose among existing bases
if (hs_bases.size() > 0) {
base = hs_bases.iterator().next();
} else {
// find a new base, simply by taking the lowest Z or remaining profiles
double min_z = Double.MAX_VALUE;
for (int i = 0; i < p.length; i++) {
if (hs_done.contains(p[i]))
continue;
final double z = p[i].getLayer().getZ();
if (z < min_z) {
min_z = z;
base = p[i];
}
}
// add base
if (null != base)
hs_bases.add(base);
}
if (null == base) {
Utils.log2("No more bases.");
break;
}
// crawl list to get a sequence of profiles in increasing or decreasing Z order, but not mixed z trends
final ArrayList<Profile> al_profiles = new ArrayList<Profile>();
// Utils.log2("Calling accumulate for base " + base);
al_profiles.add(base);
final Profile last = accumulate(hs_done, al_profiles, base, 0);
// if the trend was not empty, add it
if (last != base) {
// count as done
hs_done.addAll(al_profiles);
// add new possible base (which may have only 2 links if it was from a broken Z trend)
hs_bases.add(last);
// create 3D object from base to base
final Profile[] profiles = new Profile[al_profiles.size()];
al_profiles.toArray(profiles);
final List<Point3f> tri = makeTriangles(profiles, scale);
if (null != tri)
triangles.addAll(tri);
} else {
// remove base
hs_bases.remove(base);
}
} while (0 != hs_bases.size());
return triangles;
}
use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class MCCube method getTriangles.
/**
* Create a list of triangles from the specified image data and the
* given isovalue.
* @param volume
* @param thresh
* @return
*/
public static final List<Point3f> getTriangles(final Volume volume, final int thresh) {
final List<Point3f> tri = new ArrayList<Point3f>();
final Carrier car = new Carrier();
car.w = volume.xDim;
car.h = volume.yDim;
car.d = volume.zDim;
car.threshold = thresh + 0.5f;
car.volume = volume;
if (volume instanceof ImgLibVolume && ((ImgLibVolume) volume).getImage().getContainer() instanceof ShapeList) {
getShapeListImageTriangles((ImgLibVolume) volume, car, tri);
} else {
final MCCube cube = new MCCube();
for (int z = -1; z < car.d + 1; z += 1) {
for (int x = -1; x < car.w + 1; x += 1) {
for (int y = -1; y < car.h + 1; y += 1) {
cube.init(x, y, z);
cube.computeEdges(car);
cube.getTriangles(tri, car);
}
}
IJ.showProgress(z, car.d - 2);
}
}
// convert pixel coordinates
for (int i = 0; i < tri.size(); i++) {
final Point3f p = (Point3f) tri.get(i);
p.x = (float) (p.x * volume.pw + volume.minCoord.x);
p.y = (float) (p.y * volume.ph + volume.minCoord.y);
p.z = (float) (p.z * volume.pd + volume.minCoord.z);
}
return tri;
}
use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class MCCube method getTriangles.
private void getTriangles(final List<Point3f> list, final Carrier car) {
final int cn = caseNumber(car);
boolean directTable = !(isAmbigous(cn));
directTable = true;
// address in the table
int offset = directTable ? cn * 15 : (255 - cn) * 15;
for (int index = 0; index < 5; index++) {
// if there's a triangle
if (faces[offset] != -1) {
// pick up vertexes of the current triangle
list.add(new Point3f(this.e[faces[offset + 0]]));
list.add(new Point3f(this.e[faces[offset + 1]]));
list.add(new Point3f(this.e[faces[offset + 2]]));
}
offset += 3;
}
}
use of org.scijava.vecmath.Point3f in project TrakEM2 by trakem2.
the class AreaTree method generateMesh.
public MeshData generateMesh(final double scale, final int resample) {
final HashMap<Layer, Area> areas = new HashMap<Layer, Area>();
synchronized (node_layer_map) {
for (final Map.Entry<Layer, Set<Node<Area>>> e : node_layer_map.entrySet()) {
final Area a = new Area();
for (final AreaNode nd : (Collection<AreaNode>) (Collection) e.getValue()) {
if (null != nd.aw)
a.add(nd.aw.getArea());
}
areas.put(e.getKey(), a);
}
}
final List<Point3f> ps = AreaUtils.generateTriangles(this, scale, resample, areas);
final List<Color3f> colors = new ArrayList<Color3f>();
// Determine colors by proximity to a node, since there isn't any other way.
// TODO
Utils.log("WARNING: AreaTree multicolor 3D mesh is not yet implemented.");
final Color3f cf = new Color3f(color);
for (int i = 0; i < ps.size(); i++) colors.add(cf);
return new MeshData(ps, colors);
}
Aggregations