下面列出了java.awt.geom.Area#createTransformedArea ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
synchronized public boolean apply(final Layer la, final Area roi, final mpicbg.models.CoordinateTransform ict) throws Exception {
double[] fp = null;
mpicbg.models.CoordinateTransform chain = null;
Area localroi = null;
AffineTransform inverse = null;
for (int i=0; i<n_points; i++) {
if (p_layer[i] == la.getId()) {
if (null == localroi) {
inverse = this.at.createInverse();
localroi = roi.createTransformedArea(inverse);
}
if (localroi.contains(p[0][i], p[1][i])) {
if (null == chain) {
chain = M.wrap(this.at, ict, inverse);
fp = new double[2];
}
M.apply(chain, p, i, fp);
}
}
}
if (null != chain) calculateBoundingBox(true, la); // may be called way too many times, but avoids lots of headaches.
return true;
}
@Override
public boolean apply(final Layer la, final Area roi, final mpicbg.models.CoordinateTransform ict) throws Exception {
mpicbg.models.CoordinateTransform chain = null;
synchronized (node_layer_map) {
if (null == root) return true;
final Set<Node<T>> nodes = node_layer_map.get(la);
if (null == nodes || nodes.isEmpty()) return true;
final AffineTransform inverse = this.at.createInverse();
final Area localroi = roi.createTransformedArea(inverse);
for (final Node<T> nd : nodes) {
if (nd.intersects(localroi)) {
if (null == chain) {
chain = M.wrap(this.at, ict, inverse);
}
}
nd.apply(chain, roi);
}
}
if (null != chain) calculateBoundingBox(la);
return true;
}
/** For each area that ali contains, add it to the corresponding area here.*/
private void add(final AreaList ali) {
for (final Map.Entry<Long,Area> entry : ali.ht_areas.entrySet()) {
Area ob_area = entry.getValue();
final long lid = entry.getKey();
if (UNLOADED == ob_area) ob_area = ali.loadLayer(lid);
Area area = (Area)ob_area;
area = area.createTransformedArea(ali.at);
// now need to inverse transform it by this.at
try {
area = area.createTransformedArea(this.at.createInverse());
} catch (final NoninvertibleTransformException nte) {
IJError.print(nte);
// do what?
}
Object this_area = this.ht_areas.get(entry.getKey());
if (UNLOADED == this_area) { this_area = loadLayer(lid); }
if (null == this_area) this.ht_areas.put(entry.getKey(), (Area)area.clone());
else ((Area)this_area).add(area);
updateInDatabase("points=" + ((Long)entry.getKey()).intValue());
}
}
/** Subtracts the given ROI, and then creates a new AreaList with identical properties and the content of the subtracted part. Returns null if there is no intersection between sroi and the Area for layer_id. */
public AreaList part(final long layer_id, final ShapeRoi sroi) throws NoninvertibleTransformException {
// The Area to subtract, in world coordinates:
final Area sub = M.getArea(sroi);
// The area to subtract from:
final Area a = getArea(layer_id);
if (null == a || M.isEmpty(a)) return null;
// The intersection:
final Area inter = a.createTransformedArea(this.at);
inter.intersect(sub);
if (M.isEmpty(inter)) return null;
// Subtract from this:
this.subtract(layer_id, sroi);
// Create new AreaList with the intersection area, and add it to the same LayerSet as this:
final AreaList ali = new AreaList(this.project, this.title, 0, 0);
ali.color = new Color(color.getRed(), color.getGreen(), color.getBlue());
ali.visible = this.visible;
ali.alpha = this.alpha;
ali.addArea(layer_id, inter);
this.layer_set.add(ali); // needed to call updateBucket
ali.calculateBoundingBox(null != layer_set ? layer_set.getLayer(layer_id) : null);
return ali;
}
@Override
synchronized public boolean apply(final Layer la, final Area roi, final mpicbg.models.CoordinateTransform ict) throws Exception {
double[] fp = null;
mpicbg.models.CoordinateTransform chain = null;
Area localroi = null;
AffineTransform inverse = null;
for (int i=0; i<n_points; i++) {
if (p_layer[i] == la.getId()) {
if (null == localroi) {
inverse = this.at.createInverse();
localroi = roi.createTransformedArea(inverse);
}
if (localroi.contains(p[0][i], p[1][i])) {
if (null == chain) {
chain = M.wrap(this.at, ict, inverse);
fp = new double[2];
}
// Keep point copy
final double ox = p[0][i],
oy = p[1][i];
// Transform the point
M.apply(chain, p, i, fp);
// For radius, assume it's a point to the right of the center point
fp[0] = (float)(ox + p_width[i]);
fp[1] = (float)oy;
chain.applyInPlace(fp);
p_width[i] = Math.abs(fp[0] - p[0][i]);
}
}
}
if (null != chain) calculateBoundingBox(true, la); // may be called way too many times, but avoids lots of headaches.
return true;
}
@Override
synchronized public boolean apply(final Layer la, final Area roi, final mpicbg.models.CoordinateTransform ict) throws Exception {
if (this.layer != la) return true;
double[] fp = null;
mpicbg.models.CoordinateTransform chain = null;
Area localroi = null;
AffineTransform inverse = null;
for (int i=0; i<n_points; i++) {
if (null == localroi) {
inverse = this.at.createInverse();
localroi = roi.createTransformedArea(inverse);
}
if (localroi.contains(p[0][i], p[1][i])) {
if (null == chain) {
chain = M.wrap(this.at, ict, inverse);
fp = new double[2];
}
// The point and its two associated control points:
M.apply(chain, p, i, fp);
M.apply(chain, p_l, i, fp);
M.apply(chain, p_r, i, fp);
}
}
if (null != chain) {
generateInterpolatedPoints(0.05);
calculateBoundingBox(true);
}
return true;
}
static public Area makeMouseBrush(int diameter, double mag) {
Display front = Display.getFront();
Area brush = makeBrush(diameter, mag);
if (null == front) return brush;
Point p = front.getCanvas().getCursorLoc();
return brush.createTransformedArea(new AffineTransform(1, 0, 0, 1, p.x, p.y));
}
/** This method could get tones of improvement, which should be pumped upstream into ImageJ's RoiBrush class which is creating it at every while(true) {} iteration!!!
* The returned area has its coordinates centered around 0,0
*/
static public Area makeBrush(int diameter, double mag) {
if (diameter < 1) return null;
if (mag >= 1) return new Area(new OvalRoi(-diameter/2, -diameter/2, diameter, diameter).getPolygon());
// else, create a smaller brush and transform it up, i.e. less precise, less points to store -but precision matches what the eye sees, and allows for much better storage -less points.
int screen_diameter = (int)(diameter * mag);
if (0 == screen_diameter) return null; // can't paint at this mag with this diameter
Area brush = new Area(new OvalRoi(-screen_diameter/2, -screen_diameter/2, screen_diameter, screen_diameter).getPolygon());
// scale to world coordinates
AffineTransform at = new AffineTransform();
at.scale(1/mag, 1/mag);
return brush.createTransformedArea(at);
// smooth out edges
/*
Polygon pol = new OvalRoi(-diameter/2, -diameter/2, diameter, diameter).getPolygon();
Polygon pol2 = new Polygon();
// cheap and fast: skip every other point, since all will be square angles
for (int i=0; i<pol.npoints; i+=2) {
pol2.addPoint(pol.xpoints[i], pol.ypoints[i]);
}
return new Area(pol2);
// the above works nice, but then the fill and fill-remove don't work properly (there are traces in the edges)
// Needs a workround: before adding/substracting, enlarge the polygon to have square edges
*/
}
@Override
synchronized public boolean apply(final Layer la, final Area roi, final mpicbg.models.CoordinateTransform ict) throws Exception {
double[] fp = new double[2];
mpicbg.models.CoordinateTransform chain = null;
Area localroi = null;
AffineTransform inverse = null;
for (int i=0; i<n_points; i++) {
if (p_layer[i] == la.getId()) {
if (null == localroi) {
inverse = this.at.createInverse();
localroi = roi.createTransformedArea(inverse);
}
if (localroi.contains(p[0][i], p[1][i])) {
if (null == chain) {
chain = M.wrap(this.at, ict, inverse);
fp = new double[2];
}
// Keep point copy
final double ox = p[0][i],
oy = p[1][i];
// Transform the point
M.apply(chain, p, i, fp);
// For radius, assume it's a point to the right of the center point
fp[0] = ox + p_width[i];
fp[1] = oy;
chain.applyInPlace(fp);
p_width[i] = Math.abs(fp[0] - p[0][i]);
// The two associated control points:
M.apply(chain, p_l, i, fp);
M.apply(chain, p_r, i, fp);
}
}
}
if (null != chain) {
generateInterpolatedPoints(0.05);
calculateBoundingBox(true, la);
}
return true;
}
@Override
public Collection<Displayable> findLinkTargets(final AffineTransform aff) {
if (null == aw) return super.findLinkTargets(aff);
Area a = aw.getArea();
if (!aff.isIdentity()) {
a = a.createTransformedArea(aff);
}
return this.la.getDisplayables(Patch.class, a, true);
}
/** Returns whether the point x,y is contained in this object at the given Layer. */
@Override
public boolean contains(final Layer layer, final double x, final double y) {
Object ob = ht_areas.get(new Long(layer.getId()));
if (null == ob) return false;
if (AreaList.UNLOADED == ob) {
ob = loadLayer(layer.getId());
if (null == ob) return false;
}
Area area = (Area)ob;
if (!this.at.isIdentity()) area = area.createTransformedArea(this.at);
return area.contains(x, y);
}
/** In world coordinates, a copy of the area at {@code layer}. May be null. */
@Override
public Area getAreaAt(final Layer layer) {
final Area a = getArea(layer);
if (null == a) return null;
return a.createTransformedArea(this.at);
}
@Override
public boolean intersects(final Area area, final double z_first, final double z_last) {
Area ai;
try {
ai = area.createTransformedArea(this.at.createInverse());
} catch (final NoninvertibleTransformException nite) {
nite.printStackTrace();
return false;
}
for (final Item item : al_items) {
if (item.intersects(ai, z_first, z_last)) return true;
}
return false;
}
@Override
public boolean apply(final Layer la, final Area roi, final mpicbg.models.CoordinateTransform ict) throws Exception {
double[] fp = null;
mpicbg.models.CoordinateTransform chain = null;
Area localroi = null;
AffineTransform inverse = null;
for (final Item item : al_items) {
final long[] p_layer = item.p_layer;
final double[][] p = item.p;
for (int i=0; i<item.n_points; i++) {
if (p_layer[i] == la.getId()) {
if (null == localroi) {
inverse = this.at.createInverse();
localroi = roi.createTransformedArea(inverse);
}
if (localroi.contains(p[0][i], p[1][i])) {
if (null == chain) {
chain = M.wrap(this.at, ict, inverse);
fp = new double[2];
}
// Transform the point
M.apply(chain, p, i, fp);
}
}
}
}
if (null != chain) calculateBoundingBox(la);
return true;
}
/** Returns the approximated area of the given Area object; Loader can be null; if not, it's used to secure memory space. */
static public final double measureArea(Area area, final Loader loader) {
double sum = 0;
try {
Rectangle bounds = area.getBounds();
double scale = 1;
if (bounds.width > 2048 || bounds.height > 2048) { // TODO value 2048 should be reconsidered as a project property
scale = 2048.0 / bounds.width;
}
if (0 == scale) {
Utils.log("Can't measure: area too large, out of scale range for approximation.");
return sum;
}
final AffineTransform at = new AffineTransform();
at.translate(-bounds.x, -bounds.y);
at.scale(scale, scale);
area = area.createTransformedArea(at);
bounds = area.getBounds();
if (0 == bounds.width || 0 == bounds.height) {
Utils.log("Can't measure: area too large, approximates zero.");
return sum;
}
if (null != loader) loader.releaseToFit(bounds.width * bounds.height * 3);
final BufferedImage bi = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_BYTE_INDEXED);
final Graphics2D g = bi.createGraphics();
g.setColor(Color.white);
g.fill(area);
final byte[] pixels = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData(); // buffer.getData();
for (int i=pixels.length-1; i>-1; i--) {
//if (255 == (pixels[i]&0xff)) sum++;
if (0 != pixels[i]) sum++;
}
bi.flush();
g.dispose();
if (1 != scale) sum = sum / (scale * scale);
} catch (final Throwable e) {
IJError.print(e);
}
return sum;
}
/** Find the nearest parent with a non-null, non-empty Area, and interpolate from {@code nd} to it.
*
* @param nd The node to start interpolating from, towards its nearest parent with an area.
* @param node_centric If true, consider areas relative to the node coordinates. If false, relative to the overall AreaTree.
*
* @throws Exception */
public boolean interpolateTowardsParent(final Node<Area> nd, final boolean node_centric, final boolean always_use_distance_map) throws Exception {
if (null == nd || null == nd.parent) return false;
Area first = nd.getData();
if (null == first || first.isEmpty()) {
return false;
}
final LinkedList<Node<Area>> chain = new LinkedList<Node<Area>>();
Node<Area> p = nd.parent;
while (null != p && (null == p.getData() || p.getData().isEmpty())) {
chain.add(p);
p = p.parent;
}
if (p == nd.parent) {
// Nothing to interpolate
return false;
}
Area last = p.getData();
int minx = 0, miny = 0;
if (node_centric) {
// Make areas relative to the nodes:
first = first.createTransformedArea(new AffineTransform(1, 0, 0, 1, -nd.x, -nd.y));
last = last.createTransformedArea(new AffineTransform(1, 0, 0, 1, -p.x, -p.y));
// Remove translations
final Rectangle bfirst = first.getBounds();
final Rectangle blast = last.getBounds();
minx = Math.min(bfirst.x, blast.x);
miny = Math.min(bfirst.y, blast.y);
final AffineTransform rmtrans = new AffineTransform(1, 0, 0, 1, -minx, -miny);
first = first.createTransformedArea(rmtrans);
last = last.createTransformedArea(rmtrans);
}
// Interpolate
final Area[] as;
if (!always_use_distance_map && first.isSingular() && last.isSingular()) {
as = AreaUtils.singularInterpolation(first, last, chain.size());
} else {
as = AreaUtils.manyToManyInterpolation(first, last, chain.size());
}
// Assign each area
for (final Area interpolated : as) {
final Node<Area> target = chain.removeFirst();
if (node_centric) {
interpolated.transform(new AffineTransform(1, 0, 0, 1, minx + target.x, miny + target.y));
}
target.setData(interpolated);
}
return true;
}
/** Returns a stack of images representing the pixel data of this LayerSet inside this AreaList. */
public ImagePlus getStack(final int type, final double scale) {
final ImageProcessor ref_ip = Utils.createProcessor(type, 2, 2);
if (null == ref_ip) {
Utils.log("AreaList.getStack: Unknown type " + type);
return null;
}
final Rectangle b = getBoundingBox();
final int w = (int)(0.5 + b.width * scale);
final int h = (int)(0.5 + b.height * scale);
final ImageStack stack = new ImageStack(w, h);
for (final Layer la : getLayerRange()) {
final Area area = getArea(la);
final double z = layer.getZ();
project.getLoader().releaseToFit(w * h * 10);
final ImageProcessor ip = ref_ip.createProcessor(w, h);
if (null == area) {
stack.addSlice(Double.toString(z), ip);
continue;
}
// Create a ROI from the area at Layer la:
final AffineTransform aff = getAffineTransformCopy();
aff.translate(-b.x, -b.y);
aff.scale(scale, scale);
final ShapeRoi roi = new ShapeRoi(area.createTransformedArea(aff));
// Create a cropped snapshot of the images at Layer la under the area:
final ImageProcessor flat = Patch.makeFlatImage(type, la, b, scale, la.getAll(Patch.class), Color.black);
flat.setRoi(roi);
final Rectangle rb = roi.getBounds();
ip.insert(flat.crop(), rb.x, rb.y);
// Clear the outside
final ImagePlus bimp = new ImagePlus("", ip);
bimp.setRoi(roi);
ip.setValue(0);
ip.setBackgroundValue(0);
IJ.run(bimp, "Clear Outside", "");
stack.addSlice(Double.toString(z), ip);
}
final ImagePlus imp = new ImagePlus("AreaList stack for " + this, stack);
imp.setCalibration(layer_set.getCalibrationCopy());
return imp;
}