/** * Writes the <code>shape</code>, <code>coords</code>, <code>href</code>, * <code>nohref</code> Attribute for the specified figure and shape. * * @return Returns true, if the polygon is inside of the image bounds. */ private boolean writePolyAttributes(IXMLElement elem, SVGFigure f, Shape shape) { AffineTransform t = TRANSFORM.getClone(f); if (t == null) { t = drawingTransform; } else { t.preConcatenate(drawingTransform); } StringBuilder buf = new StringBuilder(); float[] coords = new float[6]; GeneralPath path = new GeneralPath(); for (PathIterator i = shape.getPathIterator(t, 1.5f); ! i.isDone(); i.next()) { switch (i.currentSegment(coords)) { case PathIterator.SEG_MOVETO : if (buf.length() != 0) { throw new IllegalArgumentException("Illegal shape "+shape); } if (buf.length() != 0) { buf.append(','); } buf.append((int) coords[0]); buf.append(','); buf.append((int) coords[1]); path.moveTo(coords[0], coords[1]); break; case PathIterator.SEG_LINETO : if (buf.length() != 0) { buf.append(','); } buf.append((int) coords[0]); buf.append(','); buf.append((int) coords[1]); path.lineTo(coords[0], coords[1]); break; case PathIterator.SEG_CLOSE : path.closePath(); break; default : throw new InternalError("Illegal segment type "+i.currentSegment(coords)); } } elem.setAttribute("shape", "poly"); elem.setAttribute("coords", buf.toString()); writeHrefAttribute(elem, f); return path.intersects(new Rectangle2D.Float(bounds.x, bounds.y, bounds.width, bounds.height)); }
/** * returns the skew transform * * @param svgHandle a svg handle * @param bounds the bounds of the area to transform * @param firstPoint the first clicked point by the user * @param currentPoint the current point of the drag action by the user * @param item the selection item * @return the skew transform */ protected AffineTransform getSkewTransform( SVGHandle svgHandle, Rectangle2D bounds, Point2D firstPoint, Point2D currentPoint, SelectionItem item) { // getting the skew factor double skewX = 0, skewY = 0; boolean isHorizontal = (item.getType() == SelectionItem.NORTH || item.getType() == SelectionItem.SOUTH); if (bounds.getWidth() > 0 && bounds.getHeight() > 0) { if (isHorizontal) { skewX = (currentPoint.getX() - firstPoint.getX()) / bounds.getHeight(); } else { skewY = (currentPoint.getY() - firstPoint.getY()) / bounds.getWidth(); } } // getting the center point Point2D centerPoint = getRotationSkewCenterPoint(svgHandle, bounds); // creating the affine transform AffineTransform af = AffineTransform.getTranslateInstance(-centerPoint.getX(), -centerPoint.getY()); af.preConcatenate(AffineTransform.getShearInstance(skewX, skewY)); af.preConcatenate(AffineTransform.getTranslateInstance(centerPoint.getX(), centerPoint.getY())); return af; }
/** * Perform a zooming operation centered on the given point (dx, dy) and using the given scale * factor. The given AffineTransform instance is preconcatenated. * * @param dx center x * @param dy center y * @param scale zoom rate * @param af original affinetransform */ public void centerZoom(double dx, double dy, double scale, AffineTransform af) { af.preConcatenate(AffineTransform.getTranslateInstance(-dx, -dy)); af.preConcatenate(AffineTransform.getScaleInstance(scale, scale)); af.preConcatenate(AffineTransform.getTranslateInstance(dx, dy)); transform = af; syncScrollBars(); }
public GranuleOverviewLevelDescriptor( final double scaleX, final double scaleY, final int width, final int height) { this.scaleX = scaleX; this.scaleY = scaleY; this.baseToLevelTransform = new AffineTransform2D(XAffineTransform.getScaleInstance(scaleX, scaleY, 0, 0)); final AffineTransform gridToWorldTransform_ = new AffineTransform(baseToLevelTransform); gridToWorldTransform_.preConcatenate(CoverageUtilities.CENTER_TO_CORNER); gridToWorldTransform_.preConcatenate(baseGridToWorld); this.gridToWorldTransformCorner = new AffineTransform2D(gridToWorldTransform_); this.width = width; this.height = height; this.rasterDimensions = new Rectangle(0, 0, width, height); }
/** * Writes the <code>shape</code>, <code>coords</code>, <code>href</code>, * <code>nohref</code> Attribute for the specified figure and ellipse. * * @return Returns true, if the circle is inside of the image bounds. */ private boolean writeCircleAttributes(IXMLElement elem, SVGFigure f, Ellipse2D.Double ellipse) { AffineTransform t = TRANSFORM.getClone(f); if (t == null) { t = drawingTransform; } else { t.preConcatenate(drawingTransform); } if ((t.getType() & (AffineTransform.TYPE_UNIFORM_SCALE | AffineTransform.TYPE_TRANSLATION)) == t.getType() && ellipse.width == ellipse.height ) { Point2D.Double start = new Point2D.Double(ellipse.x, ellipse.y); Point2D.Double end = new Point2D.Double(ellipse.x + ellipse.width, ellipse.y + ellipse.height); t.transform(start, start); t.transform(end, end); ellipse.x = Math.min(start.x, end.x); ellipse.y = Math.min(start.y, end.y); ellipse.width = Math.abs(start.x - end.x); ellipse.height = Math.abs(start.y - end.y); elem.setAttribute("shape", "circle"); elem.setAttribute("coords", (int) (ellipse.x + ellipse.width / 2d)+","+ (int) (ellipse.y + ellipse.height / 2d)+","+ (int) (ellipse.width / 2d) ); writeHrefAttribute(elem, f); return bounds.intersects(ellipse.getBounds()); } else { return writePolyAttributes(elem, f, (Shape) ellipse); } }
@Override public void paintPreview(JEnvironment env, JRequest req, Graphics2D g) { g.setColor(getPreviewColor()); AffineTransform af = new AffineTransform(totalTransform); if (addingTransform != null) af.preConcatenate(addingTransform); Shape s = getShape(); if (addingTransform != null) s = addingTransform.createTransformedShape(s); s = env.getToScreenTransform().createTransformedShape(s); g.draw(s); PathIterator path = s.getPathIterator(null); double radius = JEnvironment.PATH_SELECTOR_SIZE / 2; Rectangle2D.Double sr = new Rectangle2D.Double(0, 0, radius * 2, radius * 2); double[] coords = new double[6]; while (!path.isDone()) { int type = path.currentSegment(coords); if (type == path.SEG_MOVETO || type == path.SEG_LINETO) { sr.x = coords[0] - radius; sr.y = coords[1] - radius; g.fill(sr); } else if (type == path.SEG_CUBICTO) { sr.x = coords[4] - radius; sr.y = coords[5] - radius; g.fill(sr); } else if (type == path.SEG_QUADTO) { sr.x = coords[2] - radius; sr.y = coords[3] - radius; g.fill(sr); } path.next(); } }
/** * Transforms the figure. * * @param tx the transformation. */ public void transform(AffineTransform tx) { if (TRANSFORM.get(this) != null || tx.getType() != (tx.getType() & AffineTransform.TYPE_TRANSLATION)) { if (TRANSFORM.get(this) == null) { TRANSFORM.basicSet(this, (AffineTransform) tx.clone()); } else { AffineTransform t = TRANSFORM.getClone(this); t.preConcatenate(tx); TRANSFORM.basicSet(this, t); } } else { for (int i = 0; i < coordinates.length; i++) { tx.transform(coordinates[i], coordinates[i]); } if (FILL_GRADIENT.get(this) != null && !FILL_GRADIENT.get(this).isRelativeToFigureBounds()) { Gradient g = FILL_GRADIENT.getClone(this); g.transform(tx); FILL_GRADIENT.basicSet(this, g); } if (STROKE_GRADIENT.get(this) != null && !STROKE_GRADIENT.get(this).isRelativeToFigureBounds()) { Gradient g = STROKE_GRADIENT.getClone(this); g.transform(tx); STROKE_GRADIENT.basicSet(this, g); } } invalidate(); }
public static BufferedImage rotateImage(BufferedImage image, double theta) { int degrees = (int) Math.abs(Math.toDegrees(theta)); double xCenter = image.getWidth() / 2; double yCenter = image.getHeight() / 2; AffineTransform rotateTransform = AffineTransform.getRotateInstance(-theta, xCenter, yCenter); // Translation adjustments so image still centered after rotate width/height changes if (image.getHeight() != image.getWidth() && degrees != 180 && degrees != 0) { Point2D origin = new Point2D.Double(0.0, 0.0); origin = rotateTransform.transform(origin, null); double yTranslate = origin.getY(); Point2D yMax = new Point2D.Double(0, image.getHeight()); yMax = rotateTransform.transform(yMax, null); double xTranslate = yMax.getX(); AffineTransform translationAdjustment = AffineTransform.getTranslateInstance(-xTranslate, -yTranslate); rotateTransform.preConcatenate(translationAdjustment); } AffineTransformOp op = new AffineTransformOp(rotateTransform, AffineTransformOp.TYPE_BILINEAR); // Have to recopy image because of JDK bug #4723021, AffineTransformationOp throwing exception // sometimes image = copyImage(image, BufferedImage.TYPE_INT_ARGB); // Need to create filter dest image ourselves since AffineTransformOp's own dest image creation // throws exceptions in some cases. Rectangle bounds = op.getBounds2D(image).getBounds(); BufferedImage finalImage = new BufferedImage( (int) bounds.getWidth(), (int) bounds.getHeight(), BufferedImage.TYPE_INT_ARGB); return op.filter(image, finalImage); }
/** * @param drop * @param i * @return */ public static BufferedImage rotate(final BufferedImage src, final int degree) { final int w = src.getWidth(null); final int h = src.getHeight(null); // final Graphics2D g = image.createGraphics(); // g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); final AffineTransform at = new AffineTransform(); at.rotate(degree * Math.PI / 180.0); Point2D p2din, p2dout; p2din = new Point2D.Double(0.0, 0.0); p2dout = at.transform(p2din, null); double ytrans = p2dout.getY(); double xtrans = p2dout.getX(); p2din = new Point2D.Double(0, h); p2dout = at.transform(p2din, null); ytrans = Math.min(ytrans, p2dout.getY()); xtrans = Math.min(xtrans, p2dout.getX()); p2din = new Point2D.Double(w, h); p2dout = at.transform(p2din, null); ytrans = Math.min(ytrans, p2dout.getY()); xtrans = Math.min(xtrans, p2dout.getX()); p2din = new Point2D.Double(w, 0); p2dout = at.transform(p2din, null); ytrans = Math.min(ytrans, p2dout.getY()); xtrans = Math.min(xtrans, p2dout.getX()); final AffineTransform tat = new AffineTransform(); tat.translate(-xtrans, -ytrans); at.preConcatenate(tat); final AffineTransformOp bio = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); final Rectangle r = bio.getBounds2D(src).getBounds(); BufferedImage image = new BufferedImage(r.width, r.height, BufferedImage.TYPE_INT_ARGB); image = bio.filter(src, image); // final Graphics g = image.getGraphics(); // g.setColor(Color.RED); // g.drawRect(0, 0, image.getWidth() - 1, image.getHeight() - 1); // g.dispose(); // try { // Dialog.getInstance().showConfirmDialog(0, "", "", new // ImageIcon(image), null, null); // } catch (final DialogClosedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (final DialogCanceledException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } return image; }
/* Scroll horizontally */ private void scrollHorizontally(ScrollBar scrollBar) { if (sourceImage == null) return; AffineTransform af = transform; double tx = af.getTranslateX(); double select = -scrollBar.getSelection(); af.preConcatenate(AffineTransform.getTranslateInstance(select - tx, 0)); transform = af; syncScrollBars(); }
/* Scroll vertically */ private void scrollVertically(ScrollBar scrollBar) { if (sourceImage == null) return; AffineTransform af = transform; double ty = af.getTranslateY(); double select = -scrollBar.getSelection(); af.preConcatenate(AffineTransform.getTranslateInstance(0, select - ty)); transform = af; syncScrollBars(); }
/** * Performs a translation using the "Resample" operation. * * @param grid the {@link GridCoverage2D} to apply the translation on. * @throws NoninvertibleTransformException If a "grid to CRS" transform is not invertible. */ private void doTranslation(GridCoverage2D grid) throws NoninvertibleTransformException { final int transX = -253; final int transY = -456; final double scaleX = 0.04; final double scaleY = -0.04; final ParameterBlock block = new ParameterBlock() .addSource(grid.getRenderedImage()) .add((float) transX) .add((float) transY); RenderedImage image = JAI.create("Translate", block); assertEquals("Incorrect X translation", transX, image.getMinX()); assertEquals("Incorrect Y translation", transY, image.getMinY()); /* * Create a grid coverage from the translated image but with the same envelope. * Consequently, the 'gridToCoordinateSystem' should be translated by the same * amount, with the opposite sign. */ AffineTransform expected = getAffineTransform(grid); assertNotNull(expected); expected = new AffineTransform(expected); // Get a mutable instance. final GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null); grid = factory.create( "Translated", image, grid.getEnvelope(), grid.getSampleDimensions(), new GridCoverage2D[] {grid}, grid.getProperties()); expected.translate(-transX, -transY); assertTransformEquals(expected, getAffineTransform(grid)); /* * Apply the "Resample" operation with a specific 'gridToCoordinateSystem' transform. * The envelope is left unchanged. The "Resample" operation should compute automatically * new image bounds. */ final AffineTransform at = AffineTransform.getScaleInstance(scaleX, scaleY); final MathTransform tr = ProjectiveTransform.create(at); // account for the half pixel correction between the two spaces since we are talking raster here // but the resample will talk model! final MathTransform correctedTransform = PixelTranslation.translate(tr, PixelInCell.CELL_CORNER, PixelInCell.CELL_CENTER); final GridGeometry2D geometry = new GridGeometry2D(null, correctedTransform, null); final GridCoverage2D newGrid = (GridCoverage2D) Operations.DEFAULT.resample(grid, grid.getCoordinateReferenceSystem(), geometry, null); assertEquals(correctedTransform, getAffineTransform(newGrid)); image = newGrid.getRenderedImage(); expected.preConcatenate(at.createInverse()); final Point point = new Point(transX, transY); assertSame(point, expected.transform(point, point)); // Round toward neareast integer }
/** * Returns a Filter that represents a svg document or element as an image. * * @param ctx the bridge context * @param primitiveRegion the primitive region * @param refElement the referenced element * @param toBBoxNeeded true if there is a need to transform to ObjectBoundingBox space * @param filterElement parent filter element * @param filteredNode node to which the filter applies */ protected static Filter createSVGFeImage( BridgeContext ctx, Rectangle2D primitiveRegion, Element refElement, boolean toBBoxNeeded, Element filterElement, GraphicsNode filteredNode) { // // <!> FIX ME // Unresolved issue on the feImage behavior when referencing an // image (PNG, JPEG or SVG image). // VH & TK, 03/08/2002 // Furthermore, for feImage referencing doc fragment, should act // like a <use>, i.e., CSS cascading and the whole zing bang. // GraphicsNode node = ctx.getGVTBuilder().build(ctx, refElement); Filter filter = node.getGraphicsNodeRable(true); AffineTransform at = new AffineTransform(); if (toBBoxNeeded) { // 'primitiveUnits' attribute - default is userSpaceOnUse short coordSystemType; Element filterDefElement = (Element) (filterElement.getParentNode()); String s = SVGUtilities.getChainableAttributeNS( filterDefElement, null, SVG_PRIMITIVE_UNITS_ATTRIBUTE, ctx); if (s.length() == 0) { coordSystemType = SVGUtilities.USER_SPACE_ON_USE; } else { coordSystemType = SVGUtilities.parseCoordinateSystem( filterDefElement, SVG_PRIMITIVE_UNITS_ATTRIBUTE, s, ctx); } if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) { at = SVGUtilities.toObjectBBox(at, filteredNode); } Rectangle2D bounds = filteredNode.getGeometryBounds(); at.preConcatenate( AffineTransform.getTranslateInstance( primitiveRegion.getX() - bounds.getX(), primitiveRegion.getY() - bounds.getY())); } else { // Need to translate the image to the x, y coordinate to // have the same behavior as the <use> element at.translate(primitiveRegion.getX(), primitiveRegion.getY()); } return new AffineRable8Bit(filter, at); }
/** * Synchronize the scrollbar with the image. If the transform is out of range, it will correct it. * This function considers only following factors :<b> transform, image size, client area</b>. */ public void syncScrollBars() { if (sourceImage == null) { redraw(); return; } AffineTransform af = transform; double sx = af.getScaleX(), sy = af.getScaleY(); double tx = af.getTranslateX(), ty = af.getTranslateY(); if (tx > 0) tx = 0; if (ty > 0) ty = 0; ScrollBar horizontal = getHorizontalBar(); horizontal.setIncrement((int) (getClientArea().width / 20)); horizontal.setPageIncrement(getClientArea().width); Rectangle imageBound = sourceImage.getBounds(); int cw = getClientArea().width, ch = getClientArea().height; if (imageBound.width * sx > cw) { /* image is wider than client area */ horizontal.setMaximum((int) (imageBound.width * sx)); horizontal.setEnabled(true); if (((int) -tx) > horizontal.getMaximum() - cw) tx = -horizontal.getMaximum() + cw; } else { /* image is narrower than client area */ horizontal.setEnabled(false); tx = (cw - imageBound.width * sx) / 2; // center if too small. } horizontal.setSelection((int) (-tx)); horizontal.setThumb((int) (getClientArea().width)); ScrollBar vertical = getVerticalBar(); vertical.setIncrement((int) (getClientArea().height / 20)); vertical.setPageIncrement((int) (getClientArea().height)); if (imageBound.height * sy > ch) { /* image is higher than client area */ vertical.setMaximum((int) (imageBound.height * sy)); vertical.setEnabled(true); if (((int) -ty) > vertical.getMaximum() - ch) ty = -vertical.getMaximum() + ch; } else { /* image is less higher than client area */ vertical.setEnabled(false); ty = (ch - imageBound.height * sy) / 2; // center if too small. } vertical.setSelection((int) (-ty)); vertical.setThumb((int) (getClientArea().height)); /* update transform. */ af = AffineTransform.getScaleInstance(sx, sy); af.preConcatenate(AffineTransform.getTranslateInstance(tx, ty)); transform = af; redraw(); }
private void inspectCoordinateReferenceSystems() throws DataSourceException { // get the crs for the requested bbox requestCRS = CRS.getHorizontalCRS(requestedBBox.getCoordinateReferenceSystem()); // // Check if the request CRS is different from the coverage native CRS // if (!CRS.equalsIgnoreMetadata(requestCRS, coverageProperties.crs2D)) try { destinationToSourceTransform = CRS.findMathTransform(requestCRS, coverageProperties.crs2D, true); } catch (FactoryException e) { throw new DataSourceException("Unable to inspect request CRS", e); } // now transform the requested envelope to source crs if (destinationToSourceTransform != null && destinationToSourceTransform.isIdentity()) { destinationToSourceTransform = null; // the CRS is basically the same } else if (destinationToSourceTransform instanceof AffineTransform) { needsReprojection = true; // // k, the transformation between the various CRS is not null or the // Identity, let's see if it is an affine transform, which case we // can incorporate it into the requested grid to world // // we should not have any problems with regards to BBOX reprojection // update the requested grid to world transformation by pre concatenating the destination to // source transform AffineTransform mutableTransform = (AffineTransform) requestedGridToWorld.clone(); mutableTransform.preConcatenate((AffineTransform) destinationToSourceTransform); // update the requested envelope try { final MathTransform tempTransform = PixelTranslation.translate( ProjectiveTransform.create(mutableTransform), PixelInCell.CELL_CENTER, PixelInCell.CELL_CORNER); requestedBBox = new ReferencedEnvelope( CRS.transform(tempTransform, new GeneralEnvelope(requestedRasterArea))); } catch (MismatchedDimensionException e) { throw new DataSourceException("Unable to inspect request CRS", e); } catch (TransformException e) { throw new DataSourceException("Unable to inspect request CRS", e); } // now clean up all the traces of the transformations destinationToSourceTransform = null; } }
@Override public void transform(AffineTransform tx) { if (get(TRANSFORM) != null || (tx.getType() & (AffineTransform.TYPE_TRANSLATION)) != tx.getType()) { if (get(TRANSFORM) == null) { TRANSFORM.setClone(this, tx); } else { AffineTransform t = TRANSFORM.getClone(this); t.preConcatenate(tx); set(TRANSFORM, t); } } else { super.transform(tx); } }
@Override public AffineTransform convertViewCoordinatesToNormalizedPointAT(double scale) { Rectangle bounds = getNormalizedBounds(scale); // return AffineTransform.getScaleInstance(1.0/bounds.width, 1.0/bounds.height); AffineTransform returned = AffineTransform.getTranslateInstance( minX < 0 ? minX * bounds.width : 0, minY < 0 ? minY * bounds.height : 0); returned.preConcatenate( AffineTransform.getScaleInstance(1.0 / bounds.width, 1.0 / bounds.height)); return returned; }
public void mouseWheelMoved(MouseWheelEvent event) { JGVTComponent component = (JGVTComponent) event.getSource(); double scale = 1 - 0.2 * event.getWheelRotation(); int x = event.getX(); int y = event.getY(); AffineTransform at = AffineTransform.getTranslateInstance(x, y); at.scale(scale, scale); at.translate(-x, -y); AffineTransform rt = (AffineTransform) component.getRenderingTransform().clone(); rt.preConcatenate(at); if (rt.getDeterminant() < MAX_ZOOM_DETERMINANT) { return; } component.setRenderingTransform(rt); calculator.reset(); }
/** * Derives the "magic" transform that can transform source points to destination points. * * @param srcPoints Three points representing the source parallelogram. * @param destPoints Three points representing the destination parallelogram. * <p>Matrix is represent [m00 m01 m02] [m10 m11 m12] [ 0 0 1 ] * @return A transform as described above. */ public static AffineTransform deriveTransform(Point2D[] srcPoints, Point2D[] destPoints) throws NoninvertibleTransformException { if ((srcPoints == null) || (srcPoints.length != 3)) { throw new IllegalArgumentException("Source points must contain three points!"); } else if ((destPoints == null) || (destPoints.length != 3)) { throw new IllegalArgumentException("Destination points must contain three points!"); } AffineTransform returnTransform = null; // System.out.println(srcPoints[0]+","+srcPoints[1]+","+srcPoints[2]); final double m00 = srcPoints[1].getX() - srcPoints[0].getX(); final double m10 = srcPoints[1].getY() - srcPoints[0].getY(); final double m01 = srcPoints[2].getX() - srcPoints[0].getX(); final double m11 = srcPoints[2].getY() - srcPoints[0].getY(); final double m02 = srcPoints[0].getX(); final double m12 = srcPoints[0].getY(); final double n00 = destPoints[1].getX() - destPoints[0].getX(); final double n10 = destPoints[1].getY() - destPoints[0].getY(); final double n01 = destPoints[2].getX() - destPoints[0].getX(); final double n11 = destPoints[2].getY() - destPoints[0].getY(); final double n02 = destPoints[0].getX(); final double n12 = destPoints[0].getY(); // Build the transform based on the source points. final AffineTransform srcTransform = new AffineTransform(new double[] {m00, m10, m01, m11, m02, m12}); // System.out.println("src Tran "+srcTransform); final AffineTransform destTransform = new AffineTransform(new double[] {n00, n10, n01, n11, n02, n12}); // System.out.println("destTran "+destTransform); try { returnTransform = srcTransform.createInverse(); returnTransform.preConcatenate(destTransform); } catch (NoninvertibleTransformException e) { NaviLogger.logger.severe(e.getMessage()); } // System.out.println("retTran "+returnTransform); return returnTransform; }
/** * computes the new coordinates of the element according to the transform a returns an undo/redo * action * * @param handle a svg handle * @param element the element that will be transformed * @param transform the transform to apply * @param actionUndoRedoLabel the action undo/redo label * @return an undo/redo action */ protected UndoRedoAction applyTransform( final SVGHandle handle, final Element element, AffineTransform transform, String actionUndoRedoLabel) { // getting the initial transform final AffineTransform initialTransform = handle.getSvgElementsManager().getTransform(element); // getting the new transform final AffineTransform newTransform = new AffineTransform(initialTransform); newTransform.preConcatenate(transform); // setting the new x and y attributes for the elements Runnable executeRunnable = new Runnable() { @Override public void run() { handle.getSvgElementsManager().setTransform(element, newTransform); } }; // the undo runnable Runnable undoRunnable = new Runnable() { @Override public void run() { handle.getSvgElementsManager().setTransform(element, initialTransform); } }; // executing the action and creating the undo/redo action HashSet<Element> elements = new HashSet<Element>(); elements.add(element); UndoRedoAction undoRedoAction = ShapeToolkit.getUndoRedoAction( actionUndoRedoLabel, executeRunnable, undoRunnable, elements); return undoRedoAction; }
/** * Función de pintado del canvas. Pintamos un marco a la imagen para saber donde la movemos. * * <p>Para dibujar el marco alrededor del raster hacemos lo mismo que para pintar el raster * rotado. En realidad dibujamos un cuadrado y luego le aplicamos las transformaciones necesarias * para que se vea con la misma forma del raster al que representa. */ public void paintComponent(Graphics g) { if (isMoveable && lyr != null && ptoFin != null && ptoIni != null) { try { ViewPort vp = grBehavior.getMapControl().getMapContext().getViewPort(); AffineTransform at = (AffineTransform) lyr.getAffineTransform().clone(); at.preConcatenate(vp.getAffineTransform()); Extent ext = lyr.getFullRasterExtent(); Point2D pt = new Point2D.Double(ext.getULX(), ext.getULY()); vp.getAffineTransform().transform(pt, pt); at.inverseTransform(pt, pt); Point2D size = new Point2D.Double(ext.getLRX(), ext.getLRY()); vp.getAffineTransform().transform(size, size); at.inverseTransform(size, size); double distX = ptoFin.getX() - ptoIni.getX(); double distY = ptoFin.getY() - ptoIni.getY(); Point2D d = new Point2D.Double(ext.getULX() + distX, ext.getULY() + distY); vp.getAffineTransform().transform(d, d); at.inverseTransform(d, d); // Giramos el graphics se dibuja y se vuelve a dejar como estaba ((Graphics2D) g).transform(at); g.setColor(rectangleColor); AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f); ((Graphics2D) g).setComposite(alpha); g.fillRect( (int) pt.getX() + (int) d.getX(), (int) pt.getY() + (int) d.getY(), (int) size.getX(), (int) size.getY()); ((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); g.drawRect( (int) pt.getX() + (int) d.getX(), (int) pt.getY() + (int) d.getY(), (int) size.getX(), (int) size.getY()); ((Graphics2D) g).transform(at.createInverse()); } catch (NoninvertibleTransformException e1) { RasterToolsUtil.messageBoxError("error_transformacion1", this, e1); } } }
/** {@inheritDoc } */ @Override public void setGraphicsCRS(CoordinateReferenceSystem crs) throws TransformException { if (crs == displayCRS) { switchToDisplayCRS(); } else if (crs == objectiveCRS || crs == objectiveCRS2D) { switchToObjectiveCRS(); } else try { crs = CRSUtilities.getCRS2D(crs); AffineTransform at = getAffineTransform(crs, displayCRS); at.preConcatenate(displayToDevice); current = OTHER_TRS; graphics.setTransform(at); } catch (FactoryException e) { throw new TransformException( Errors.format(Errors.Keys.ILLEGAL_COORDINATE_REFERENCE_SYSTEM), e); } }
@Override public void draw(Graphics2D g2d) { double radius = facade.getShipRadius(getObject()); double angle = -facade.getShipDirection(getObject()); double x = facade.getShipX(getObject()); double y = facade.getWorldHeight(world) - facade.getShipY(getObject()); g2d.setColor(getColor()); if (getImage() == null) { g2d.drawOval( (int) (x - radius), (int) (y - radius), (int) (2 * radius), (int) (2 * radius)); } else { AffineTransform T = AffineTransform.getTranslateInstance(radius, radius); T.rotate(angle); T.translate(-radius, -radius); T.preConcatenate(AffineTransform.getTranslateInstance(x - radius, y - radius)); g2d.drawImage(getImage(), T, null); } g2d.drawLine( (int) x, (int) y, (int) (x + Math.cos(angle) * radius), (int) (y + sin(angle) * radius)); }
@Override public void draw(Graphics2D g2d) { World world = facade.getAsteroidWorld(getObject()); if (world != null) { double radius = facade.getAsteroidRadius(getObject()); double x = facade.getAsteroidX(getObject()); double y = facade.getWorldHeight(world) - facade.getAsteroidY(getObject()); if (getImage() == null) { g2d.setColor(getColor()); g2d.drawOval( (int) (x - radius), (int) (y - radius), (int) (2 * radius), (int) (2 * radius)); } else { AffineTransform T = AffineTransform.getScaleInstance( 2 * radius / getImage().getWidth(null), 2 * radius / getImage().getHeight(null)); T.preConcatenate(AffineTransform.getTranslateInstance(x - radius, y - radius)); g2d.drawImage(this.getImage(), T, null); } } }
public synchronized void paint(Graphics gin) { Graphics2D g = (Graphics2D) gin; if (im == null) return; int height = getHeight(); int width = getWidth(); if (fit) { t = new AffineTransform(); double scale = Math.min(((double) width) / im.getWidth(), ((double) height) / im.getHeight()); // we'll re-center the transform in a moment. t.scale(scale, scale); } // if the image (in either X or Y) is smaller than the view port, then center // the image with respect to that axis. double mwidth = im.getWidth() * t.getScaleX(); double mheight = im.getHeight() * t.getScaleY(); if (mwidth < width) t.preConcatenate( AffineTransform.getTranslateInstance((width - mwidth) / 2.0 - t.getTranslateX(), 0)); if (mheight < height) t.preConcatenate( AffineTransform.getTranslateInstance(0, (height - mheight) / 2.0 - t.getTranslateY())); // if we're allowing panning (because only a portion of the image is visible), // don't allow translations that show less information that is possible. Point2D topleft = t.transform(new Point2D.Double(0, 0), null); Point2D bottomright = t.transform(new Point2D.Double(im.getWidth(), im.getHeight()), null); if (mwidth > width) { if (topleft.getX() > 0) t.preConcatenate(AffineTransform.getTranslateInstance(-topleft.getX(), 0)); if (bottomright.getX() < width) t.preConcatenate(AffineTransform.getTranslateInstance(width - bottomright.getX(), 0)); // t.translate(width-bottomright.getX(), 0); } if (mheight > height) { if (topleft.getY() > 0) t.preConcatenate(AffineTransform.getTranslateInstance(0, -topleft.getY())); if (bottomright.getY() < height) t.preConcatenate(AffineTransform.getTranslateInstance(0, height - bottomright.getY())); } g.drawImage(im, t, null); }
/** * Writes the <code>shape</code>, <code>coords</code>, <code>href</code>, * <code>nohref</code> Attribute for the specified figure and rectangle. * * @return Returns true, if the rect is inside of the image bounds. */ private boolean writeRectAttributes(IXMLElement elem, SVGFigure f, Rectangle2D.Double rect) { AffineTransform t = TRANSFORM.getClone(f); if (t == null) { t = drawingTransform; } else { t.preConcatenate(drawingTransform); } if ((t.getType() & (AffineTransform.TYPE_UNIFORM_SCALE | AffineTransform.TYPE_TRANSLATION)) == t.getType() ) { Point2D.Double start = new Point2D.Double(rect.x, rect.y); Point2D.Double end = new Point2D.Double(rect.x + rect.width, rect.y + rect.height); t.transform(start, start); t.transform(end, end); Rectangle r = new Rectangle( (int) Math.min(start.x, end.x), (int) Math.min(start.y, end.y), (int) Math.abs(start.x - end.x), (int) Math.abs(start.y - end.y) ); elem.setAttribute("shape", "rect"); elem.setAttribute("coords", r.x + ","+ r.y + ","+ (r.x + r.width) + ","+ (r.y + r.height) ); writeHrefAttribute(elem, f); return bounds.intersects(r); } else { return writePolyAttributes(elem, f, (Shape) rect); } }
public void genRect(WritableRaster wr) { if (me2src == null) return; Rectangle srcR = me2src.createTransformedShape(wr.getBounds()).getBounds(); // System.out.println("Affine wrR: " + wr.getBounds()); // System.out.println("Affine srcR: " + srcR); // Outset by two pixels so we get context for interpolation... srcR.setBounds(srcR.x - 1, srcR.y - 1, srcR.width + 2, srcR.height + 2); // Don't try and get data from src that it doesn't have... CachableRed src = (CachableRed) getSources().get(0); // Raster srcRas = src.getData(srcR); if (!srcR.intersects(src.getBounds())) return; Raster srcRas = src.getData(srcR.intersection(src.getBounds())); if (srcRas == null) return; // This works around the problem that the buffered ops // completely ignore the coords of the Rasters passed in. AffineTransform aff = (AffineTransform) src2me.clone(); // Translate what is at 0,0 (which will be what our current // minX/Y is) to our current minX,minY. aff.concatenate(AffineTransform.getTranslateInstance(srcRas.getMinX(), srcRas.getMinY())); Point2D srcPt = new Point2D.Float(wr.getMinX(), wr.getMinY()); srcPt = me2src.transform(srcPt, null); Point2D destPt = new Point2D.Double(srcPt.getX() - srcRas.getMinX(), srcPt.getY() - srcRas.getMinY()); destPt = aff.transform(destPt, null); // Translate what will be at minX,minY to zero, zero // which where java2d will think the real minX,minY is. aff.preConcatenate(AffineTransform.getTranslateInstance(-destPt.getX(), -destPt.getY())); AffineTransformOp op = new AffineTransformOp(aff, hints); BufferedImage srcBI, myBI; ColorModel srcCM = src.getColorModel(); ColorModel myCM = getColorModel(); WritableRaster srcWR = (WritableRaster) srcRas; // If the output buffer is not premultiplied in certain cases // it fails to properly divide out the Alpha (it always does // the affine on premultiplied data). We help it out by // premultiplying for it. srcCM = GraphicsUtil.coerceData(srcWR, srcCM, true); srcBI = new BufferedImage( srcCM, srcWR.createWritableTranslatedChild(0, 0), srcCM.isAlphaPremultiplied(), null); myBI = new BufferedImage( myCM, wr.createWritableTranslatedChild(0, 0), myCM.isAlphaPremultiplied(), null); op.filter(srcBI, myBI); // if ((count % 40) == 0) { // org.apache.batik.ImageDisplay.showImage("Src: " , srcBI); // org.apache.batik.ImageDisplay.showImage("Dst: " , myBI); // } // count++; }
public AffineTransform getAffineTransform( int width, int height, double[] _xyzSW, double[] _xyzSE, double[] _xyzNW) { int[] cornerNW = projection.screenProjection(_xyzNW); int[] cornerSE = projection.screenProjection(_xyzSE); int[] cornerSW = projection.screenProjection(_xyzSW); double[] vectWE = { (double) cornerSE[0] - (double) cornerSW[0], (double) cornerSE[1] - (double) cornerSW[1] }; double normvectWE = sqrt(sqr(vectWE[0]) + sqr(vectWE[1])); double[] vectSN = { (double) cornerNW[0] - (double) cornerSW[0], (double) cornerNW[1] - (double) cornerSW[1] }; double normvectSN = sqrt(sqr(vectSN[0]) + sqr(vectSN[1])); double angleSW = acos((vectWE[0] * vectSN[0] + vectWE[1] * vectSN[1]) / (normvectWE * normvectSN)); if (angleSW == 0.0) { return null; } AffineTransform t = new AffineTransform(); t.translate(cornerNW[0], cornerNW[1]); t.scale(sign(vectWE[0]), -sign(vectSN[1])); t.rotate(-atan(vectSN[0] / vectSN[1])); t.shear(0, 1 / tan(PI - angleSW)); t.scale(normvectWE * cos(angleSW - PI / 2) / (double) width, normvectSN / (double) height); double[] _cornerSE_tr = new double[2]; double[] _cornerSE = {width, height}; t.transform(_cornerSE, 0, _cornerSE_tr, 0, 1); if (isDiff(_cornerSE_tr, cornerSE)) { double[] vectSE_NW_1 = { (double) cornerNW[0] - (double) cornerSE[0], (double) cornerNW[1] - (double) cornerSE[1] }; double[] vectSE_NW_2 = { (double) cornerNW[0] - (double) _cornerSE_tr[0], (double) cornerNW[1] - (double) _cornerSE_tr[1] }; double normvect_1 = sqrt(sqr(vectSE_NW_1[0]) + sqr(vectSE_NW_1[1])); double normvect_2 = sqrt(sqr(vectSE_NW_1[0]) + sqr(vectSE_NW_1[1])); double cos_angle = (((vectSE_NW_1[0] * vectSE_NW_2[0] + vectSE_NW_1[1] * vectSE_NW_2[1]) / (normvect_1 * normvect_2))); double vect = (vectSE_NW_1[0] * vectSE_NW_2[1] - vectSE_NW_1[1] * vectSE_NW_2[0]); AffineTransform t2 = new AffineTransform(); if (vect < 0) { t2.rotate(acos(cos_angle), cornerNW[0], cornerNW[1]); } else { t2.rotate(-acos(cos_angle), cornerNW[0], cornerNW[1]); } t.preConcatenate(t2); } // TODO patch for many cases... /*double[] _cornerSW_tr = new double[2]; double[] _cornerSW = { 0, img.getHeight(canvas) }; t.transform(_cornerSW, 0, _cornerSW_tr, 0, 1); if (isDiff(_cornerSW_tr, cornerSW)) { double[] vectSW_NW_1 = { (double) cornerNW[0] - (double) cornerSW[0], (double) cornerNW[1] - (double) cornerSW[1] }; double[] vectSW_NW_2 = { (double) cornerNW[0] - (double) _cornerSW_tr[0], (double) cornerNW[1] - (double) _cornerSW_tr[1] }; double normvect_1 = sqrt(sqr(vectSW_NW_1[0]) + sqr(vectSW_NW_1[1])); double normvect_2 = sqrt(sqr(vectSW_NW_1[0]) + sqr(vectSW_NW_1[1])); double cos_angle = (((vectSW_NW_1[0] * vectSW_NW_2[0] + vectSW_NW_1[1] * vectSW_NW_2[1]) / (normvect_1 * normvect_2))); double vect = (vectSW_NW_1[0] * vectSW_NW_2[1] - vectSW_NW_1[1] * vectSW_NW_2[0]); System.out.println(cos_angle + " " + vect + " -> " + toDegrees(acos(cos_angle))); //System.out.println(" "+vectSE_NW_1[0]+","+vectSE_NW_1[1]+" "+vectSE_NW_2[0]+","+vectSE_NW_2[1]); AffineTransform t2 = new AffineTransform(); if (vect > 0) t2.rotate(acos(cos_angle), cornerNW[0], cornerNW[1]); else t2.rotate(-acos(cos_angle), cornerNW[0], cornerNW[1]); t.preConcatenate(t2); }*/ return t; }
/** * Load a specified a raster as a portion of the granule describe by this {@link * GranuleDescriptor}. * * @param imageReadParameters the {@link ImageReadParam} to use for reading. * @param index the index to use for the {@link ImageReader}. * @param cropBBox the bbox to use for cropping. * @param mosaicWorldToGrid the cropping grid to world transform. * @param request the incoming request to satisfy. * @param hints {@link Hints} to be used for creating this raster. * @return a specified a raster as a portion of the granule describe by this {@link * GranuleDescriptor}. * @throws IOException in case an error occurs. */ public GranuleLoadingResult loadRaster( final ImageReadParam imageReadParameters, final int index, final ReferencedEnvelope cropBBox, final MathTransform2D mosaicWorldToGrid, final RasterLayerRequest request, final Hints hints) throws IOException { if (LOGGER.isLoggable(java.util.logging.Level.FINER)) { final String name = Thread.currentThread().getName(); LOGGER.finer( "Thread:" + name + " Loading raster data for granuleDescriptor " + this.toString()); } ImageReadParam readParameters = null; int imageIndex; final ReferencedEnvelope bbox = inclusionGeometry != null ? new ReferencedEnvelope( granuleBBOX.intersection(inclusionGeometry.getEnvelopeInternal()), granuleBBOX.getCoordinateReferenceSystem()) : granuleBBOX; boolean doFiltering = false; if (filterMe) { doFiltering = Utils.areaIsDifferent(inclusionGeometry, baseGridToWorld, granuleBBOX); } // intersection of this tile bound with the current crop bbox final ReferencedEnvelope intersection = new ReferencedEnvelope( bbox.intersection(cropBBox), cropBBox.getCoordinateReferenceSystem()); if (intersection.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.fine( new StringBuilder("Got empty intersection for granule ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString()); } return null; } ImageInputStream inStream = null; ImageReader reader = null; try { // // get info about the raster we have to read // // get a stream assert cachedStreamSPI != null : "no cachedStreamSPI available!"; inStream = cachedStreamSPI.createInputStreamInstance( granuleUrl, ImageIO.getUseCache(), ImageIO.getCacheDirectory()); if (inStream == null) return null; // get a reader and try to cache the relevant SPI if (cachedReaderSPI == null) { reader = ImageIOExt.getImageioReader(inStream); if (reader != null) cachedReaderSPI = reader.getOriginatingProvider(); } else reader = cachedReaderSPI.createReaderInstance(); if (reader == null) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.warning( new StringBuilder("Unable to get s reader for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString()); } return null; } // set input reader.setInput(inStream); // Checking for heterogeneous granules if (request.isHeterogeneousGranules()) { // create read parameters readParameters = new ImageReadParam(); // override the overviews controller for the base layer imageIndex = ReadParamsController.setReadParams( request.getRequestedResolution(), request.getOverviewPolicy(), request.getDecimationPolicy(), readParameters, request.rasterManager, overviewsController); } else { imageIndex = index; readParameters = imageReadParameters; } // get selected level and base level dimensions final GranuleOverviewLevelDescriptor selectedlevel = getLevel(imageIndex, reader); // now create the crop grid to world which can be used to decide // which source area we need to crop in the selected level taking // into account the scale factors imposed by the selection of this // level together with the base level grid to world transformation AffineTransform2D cropWorldToGrid = new AffineTransform2D(selectedlevel.gridToWorldTransformCorner); cropWorldToGrid = (AffineTransform2D) cropWorldToGrid.inverse(); // computing the crop source area which lives into the // selected level raster space, NOTICE that at the end we need to // take into account the fact that we might also decimate therefore // we cannot just use the crop grid to world but we need to correct // it. final Rectangle sourceArea = CRS.transform(cropWorldToGrid, intersection).toRectangle2D().getBounds(); // gutter if (selectedlevel.baseToLevelTransform.isIdentity()) sourceArea.grow(2, 2); XRectangle2D.intersect( sourceArea, selectedlevel.rasterDimensions, sourceArea); // make sure roundings don't bother us // is it empty?? if (sourceArea.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.fine( "Got empty area for granuleDescriptor " + this.toString() + " with request " + request.toString() + " Resulting in no granule loaded: Empty result"); } return null; } else if (LOGGER.isLoggable(java.util.logging.Level.FINER)) { LOGGER.finer( "Loading level " + imageIndex + " with source region: " + sourceArea + " subsampling: " + readParameters.getSourceXSubsampling() + "," + readParameters.getSourceYSubsampling() + " for granule:" + granuleUrl); } // Setting subsampling int newSubSamplingFactor = 0; final String pluginName = cachedReaderSPI.getPluginClassName(); if (pluginName != null && pluginName.equals(ImageUtilities.DIRECT_KAKADU_PLUGIN)) { final int ssx = readParameters.getSourceXSubsampling(); final int ssy = readParameters.getSourceYSubsampling(); newSubSamplingFactor = ImageIOUtilities.getSubSamplingFactor2(ssx, ssy); if (newSubSamplingFactor != 0) { if (newSubSamplingFactor > maxDecimationFactor && maxDecimationFactor != -1) { newSubSamplingFactor = maxDecimationFactor; } readParameters.setSourceSubsampling(newSubSamplingFactor, newSubSamplingFactor, 0, 0); } } // set the source region readParameters.setSourceRegion(sourceArea); final RenderedImage raster; try { // read raster = request .getReadType() .read( readParameters, imageIndex, granuleUrl, selectedlevel.rasterDimensions, reader, hints, false); } catch (Throwable e) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.log( java.util.logging.Level.FINE, "Unable to load raster for granuleDescriptor " + this.toString() + " with request " + request.toString() + " Resulting in no granule loaded: Empty result", e); } return null; } // use fixed source area sourceArea.setRect(readParameters.getSourceRegion()); // // setting new coefficients to define a new affineTransformation // to be applied to the grid to world transformation // ----------------------------------------------------------------------------------- // // With respect to the original envelope, the obtained planarImage // needs to be rescaled. The scaling factors are computed as the // ratio between the cropped source region sizes and the read // image sizes. // // place it in the mosaic using the coords created above; double decimationScaleX = ((1.0 * sourceArea.width) / raster.getWidth()); double decimationScaleY = ((1.0 * sourceArea.height) / raster.getHeight()); final AffineTransform decimationScaleTranform = XAffineTransform.getScaleInstance(decimationScaleX, decimationScaleY); // keep into account translation to work into the selected level raster space final AffineTransform afterDecimationTranslateTranform = XAffineTransform.getTranslateInstance(sourceArea.x, sourceArea.y); // now we need to go back to the base level raster space final AffineTransform backToBaseLevelScaleTransform = selectedlevel.baseToLevelTransform; // now create the overall transform final AffineTransform finalRaster2Model = new AffineTransform(baseGridToWorld); finalRaster2Model.concatenate(CoverageUtilities.CENTER_TO_CORNER); final double x = finalRaster2Model.getTranslateX(); final double y = finalRaster2Model.getTranslateY(); if (!XAffineTransform.isIdentity(backToBaseLevelScaleTransform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(backToBaseLevelScaleTransform); if (!XAffineTransform.isIdentity(afterDecimationTranslateTranform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(afterDecimationTranslateTranform); if (!XAffineTransform.isIdentity(decimationScaleTranform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(decimationScaleTranform); // keep into account translation factors to place this tile finalRaster2Model.preConcatenate((AffineTransform) mosaicWorldToGrid); final Interpolation interpolation = request.getInterpolation(); // paranoiac check to avoid that JAI freaks out when computing its internal layouT on images // that are too small Rectangle2D finalLayout = ImageUtilities.layoutHelper( raster, (float) finalRaster2Model.getScaleX(), (float) finalRaster2Model.getScaleY(), (float) finalRaster2Model.getTranslateX(), (float) finalRaster2Model.getTranslateY(), interpolation); if (finalLayout.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.INFO)) LOGGER.info( "Unable to create a granuleDescriptor " + this.toString() + " due to jai scale bug creating a null source area"); return null; } ROI granuleLoadingShape = null; if (granuleROIShape != null) { final Point2D translate = mosaicWorldToGrid.transform(new DirectPosition2D(x, y), (Point2D) null); AffineTransform tx2 = new AffineTransform(); tx2.preConcatenate( AffineTransform.getScaleInstance( ((AffineTransform) mosaicWorldToGrid).getScaleX(), -((AffineTransform) mosaicWorldToGrid).getScaleY())); tx2.preConcatenate( AffineTransform.getScaleInstance( ((AffineTransform) baseGridToWorld).getScaleX(), -((AffineTransform) baseGridToWorld).getScaleY())); tx2.preConcatenate( AffineTransform.getTranslateInstance(translate.getX(), translate.getY())); granuleLoadingShape = (ROI) granuleROIShape.transform(tx2); } // apply the affine transform conserving indexed color model final RenderingHints localHints = new RenderingHints( JAI.KEY_REPLACE_INDEX_COLOR_MODEL, interpolation instanceof InterpolationNearest ? Boolean.FALSE : Boolean.TRUE); if (XAffineTransform.isIdentity(finalRaster2Model, Utils.AFFINE_IDENTITY_EPS)) { return new GranuleLoadingResult(raster, granuleLoadingShape, granuleUrl, doFiltering); } else { // // In case we are asked to use certain tile dimensions we tile // also at this stage in case the read type is Direct since // buffered images comes up untiled and this can affect the // performances of the subsequent affine operation. // final Dimension tileDimensions = request.getTileDimensions(); if (tileDimensions != null && request.getReadType().equals(ReadType.DIRECT_READ)) { final ImageLayout layout = new ImageLayout(); layout.setTileHeight(tileDimensions.width).setTileWidth(tileDimensions.height); localHints.add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout)); } else { if (hints != null && hints.containsKey(JAI.KEY_IMAGE_LAYOUT)) { final Object layout = hints.get(JAI.KEY_IMAGE_LAYOUT); if (layout != null && layout instanceof ImageLayout) { localHints.add( new RenderingHints(JAI.KEY_IMAGE_LAYOUT, ((ImageLayout) layout).clone())); } } } if (hints != null && hints.containsKey(JAI.KEY_TILE_CACHE)) { final Object cache = hints.get(JAI.KEY_TILE_CACHE); if (cache != null && cache instanceof TileCache) localHints.add(new RenderingHints(JAI.KEY_TILE_CACHE, (TileCache) cache)); } if (hints != null && hints.containsKey(JAI.KEY_TILE_SCHEDULER)) { final Object scheduler = hints.get(JAI.KEY_TILE_SCHEDULER); if (scheduler != null && scheduler instanceof TileScheduler) localHints.add(new RenderingHints(JAI.KEY_TILE_SCHEDULER, (TileScheduler) scheduler)); } boolean addBorderExtender = true; if (hints != null && hints.containsKey(JAI.KEY_BORDER_EXTENDER)) { final Object extender = hints.get(JAI.KEY_BORDER_EXTENDER); if (extender != null && extender instanceof BorderExtender) { localHints.add(new RenderingHints(JAI.KEY_BORDER_EXTENDER, (BorderExtender) extender)); addBorderExtender = false; } } // border extender if (addBorderExtender) { localHints.add(ImageUtilities.BORDER_EXTENDER_HINTS); } // boolean hasScaleX=!(Math.abs(finalRaster2Model.getScaleX()-1) < // 1E-2/(raster.getWidth()+1-raster.getMinX())); // boolean hasScaleY=!(Math.abs(finalRaster2Model.getScaleY()-1) < // 1E-2/(raster.getHeight()+1-raster.getMinY())); // boolean hasShearX=!(finalRaster2Model.getShearX() == 0.0); // boolean hasShearY=!(finalRaster2Model.getShearY() == 0.0); // boolean hasTranslateX=!(Math.abs(finalRaster2Model.getTranslateX()) < // 0.01F); // boolean hasTranslateY=!(Math.abs(finalRaster2Model.getTranslateY()) < // 0.01F); // boolean isTranslateXInt=!(Math.abs(finalRaster2Model.getTranslateX() - // (int) finalRaster2Model.getTranslateX()) < 0.01F); // boolean isTranslateYInt=!(Math.abs(finalRaster2Model.getTranslateY() - // (int) finalRaster2Model.getTranslateY()) < 0.01F); // // boolean isIdentity = finalRaster2Model.isIdentity() && // !hasScaleX&&!hasScaleY &&!hasTranslateX&&!hasTranslateY; // // TODO how can we check that the a skew is harmelss???? // if(isIdentity){ // // TODO check if we are missing anything like tiling or such that // comes from hints // return new GranuleLoadingResult(raster, granuleLoadingShape, // granuleUrl, doFiltering); // } // // // TOLERANCE ON PIXELS SIZE // // // Check and see if the affine transform is in fact doing // // a Translate operation. That is a scale by 1 and no rotation. // // In which case call translate. Note that only integer translate // // is applicable. For non-integer translate we'll have to do the // // affine. // // If the hints contain an ImageLayout hint, we can't use // // TranslateIntOpImage since it isn't capable of dealing with that. // // Get ImageLayout from renderHints if any. // ImageLayout layout = RIFUtil.getImageLayoutHint(localHints); // if ( !hasScaleX && // !hasScaleY && // !hasShearX&& // !hasShearY&& // isTranslateXInt&& // isTranslateYInt&& // layout == null) { // // It's a integer translate // return new GranuleLoadingResult(new TranslateIntOpImage(raster, // localHints, // (int) finalRaster2Model.getShearX(), // (int) // finalRaster2Model.getShearY()),granuleLoadingShape, granuleUrl, doFiltering); // } ImageWorker iw = new ImageWorker(raster); iw.setRenderingHints(localHints); iw.affine(finalRaster2Model, interpolation, request.getBackgroundValues()); return new GranuleLoadingResult( iw.getRenderedImage(), granuleLoadingShape, granuleUrl, doFiltering); } } catch (IllegalStateException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log( java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString(), e); } return null; } catch (org.opengis.referencing.operation.NoninvertibleTransformException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log( java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString(), e); } return null; } catch (TransformException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log( java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString(), e); } return null; } finally { try { if (request.getReadType() != ReadType.JAI_IMAGEREAD && inStream != null) { inStream.close(); } } finally { if (request.getReadType() != ReadType.JAI_IMAGEREAD && reader != null) { reader.dispose(); } } } }
@Override public CanvasPainter showAction( SVGHandle handle, int level, Set<Element> elementSet, SelectionItem item, Point2D firstPoint, Point2D currentPoint) { // getting the element that will undergo the action Element element = elementSet.iterator().next(); // the canvas painter that should be returned CanvasPainter painter = null; // whether the shape should be painted boolean canPaintShape = true; // the shape that will be painted Shape shape = null; // getting the action transform AffineTransform actionTransform = null; switch (level) { case 0: // getting the resize transform actionTransform = getResizeTransform(handle, element, item, firstPoint, currentPoint); break; case 1: if (item.getType() == SelectionItem.CENTER) { // storing the center point for the rotate action rotationSkewSelectionItemCenterPoint = currentPoint; item.setPoint(currentPoint); canPaintShape = false; } else if (item.getType() == SelectionItem.NORTH_WEST || item.getType() == SelectionItem.NORTH_EAST || item.getType() == SelectionItem.SOUTH_EAST || item.getType() == SelectionItem.SOUTH_WEST) { // getting the rotation transform actionTransform = getRotationTransform(handle, element, firstPoint, currentPoint); } else { // getting the skew transform actionTransform = getSkewTransform(handle, element, firstPoint, currentPoint, item); } break; } if (actionTransform != null) { // getting the initial shape shape = getShape(handle, element, true); // getting the element's transform AffineTransform transform = handle.getSvgElementsManager().getTransform(element); // concatenating the action transform to the element's transform transform.preConcatenate(actionTransform); // computing the screen scaled shape shape = handle.getTransformsManager().getScaledShape(shape, false, transform); } if (canPaintShape && shape != null) { final Shape fshape = shape; // creating the set of the clips final HashSet<Rectangle2D> fclips = new HashSet<Rectangle2D>(); fclips.add(fshape.getBounds2D()); painter = new CanvasPainter() { @Override public void paintToBeDone(Graphics2D g) { g = (Graphics2D) g.create(); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(strokeColor); g.draw(fshape); g.dispose(); } @Override public Set<Rectangle2D> getClip() { return fclips; } }; } return painter; }