private void calculateGridTranslation() { if (transformCells.getScaleX() >= SHOW_GRID_MIN_SCALE) { @SuppressWarnings("SuspiciousNameCombination") double modX = Math.floorMod(round(transformCells.getTranslateX()), cellWidth); double modY = Math.floorMod(round(transformCells.getTranslateY()), cellHeight); transformGrid.setToTranslation(-cellWidth + modX - 1, -cellHeight + modY - 1); } }
/** * Iterates through the Page's Boxes, drawing to the provided Graphics object * * @see java.awt.print.Printable#print(java.awt.Graphics, java.awt.print.PageFormat, int) */ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { if (pageIndex >= 1) { return Printable.NO_SUCH_PAGE; } Graphics2D graphics2d = (Graphics2D) graphics; AffineTransform at = graphics2d.getTransform(); double dpi = at.getScaleX() * 72; if (PrintingPlugin.isDebugging(TRACE_PRINTING)) { PrintingPlugin.log("Printing page " + pageIndex, null); // $NON-NLS-1$ System.out.println("PageFormat: " + pageFormat); // $NON-NLS-1$ System.out.println("PageFormat height: " + pageFormat.getHeight()); // $NON-NLS-1$ System.out.println("PageFormat width: " + pageFormat.getWidth()); // $NON-NLS-1$ System.out.println( "PageFormat imageableX,Y " + pageFormat.getImageableX() + ", " + pageFormat.getImageableY()); // $NON-NLS-1$ //$NON-NLS-2$ System.out.println( "PageFormat imageable height: " + pageFormat.getImageableHeight()); // $NON-NLS-1$ System.out.println( "PageFormat imageable width: " + pageFormat.getImageableWidth()); // $NON-NLS-1$ System.out.println( "PageFormat orientation (LANDSCAPE=" + PageFormat.LANDSCAPE + ", PORTRAIT=" + PageFormat.PORTRAIT + "): " + pageFormat.getOrientation()); // $NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ System.out.println("Graphics: clip bounds: " + graphics2d.getClipBounds()); // $NON-NLS-1$ System.out.println("Transform: scaleX: " + at.getScaleX()); // $NON-NLS-1$ System.out.println("Transform: scaleY: " + at.getScaleY()); // $NON-NLS-1$ System.out.println("DPI?? : " + dpi); // $NON-NLS-1$ } graphics2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); Iterator<Box> iter = diagram.getBoxes().iterator(); while (iter.hasNext()) { Box box = iter.next(); graphics2d = (Graphics2D) graphics.create( box.getLocation().x, box.getLocation().y, box.getSize().width, box.getSize().height); box.getBoxPrinter().draw(graphics2d, monitor); } return Printable.PAGE_EXISTS; }
/** * @param ls * @param at * @param generalize * @param maxDistance */ public void init(LineString ls, AffineTransform at, boolean generalize, float maxDistance) { _init(ls, at, generalize, maxDistance); xScale = (float) Math.sqrt((at.getScaleX() * at.getScaleX()) + (at.getShearX() * at.getShearX())); yScale = (float) Math.sqrt((at.getScaleY() * at.getScaleY()) + (at.getShearY() * at.getShearY())); }
@Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = ((Graphics2D) g); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); g2d.setRenderingHint( RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); g2d.setRenderingHint( RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); g2d.setColor(Color.BLACK); g2d.fillRect(0, 0, getWidth(), getHeight()); if (bufferedImage != null) { synchronized (LOCKER) { g2d.drawImage(bufferedImage, transformCells, null); } } // draw struct preview if (structurePreview != null) { Composite composite = g2d.getComposite(); g2d.setComposite(compositeStructPreview); g2d.drawImage(structurePreview, previewTransform, null); g2d.setComposite(composite); } // draw grid if (transformCells.getScaleX() > SHOW_GRID_MIN_SCALE) { Composite composite = g2d.getComposite(); g2d.setComposite(compositeGrid); g2d.drawImage(bufferedImageGrid, transformGrid, null); g2d.setComposite(composite); } // draw border for preview if (structurePreview != null && Math.abs(transformCells.getScaleX()) >= 0.95) { Shape shape = new Rectangle(0, 0, structurePreview.getWidth(), structurePreview.getHeight()); shape = previewTransform.createTransformedShape(shape); g2d.setColor(Color.RED); g2d.draw(shape); } // draw border double x = transformCells.getTranslateX(); double y = transformCells.getTranslateY(); g2d.setColor(BORDER_COLOR); g2d.setStroke(new BasicStroke(BORDER_WIDTH)); g2d.drawRect( round(x - BORDER_WIDTH), round(y - BORDER_WIDTH), round(getAutomatonWidth() * transformCells.getScaleX() + 2 * BORDER_WIDTH), round(getAutomatonHeight() * transformCells.getScaleY() + 2 * BORDER_WIDTH)); }
TexturePaintContext(ColorModel cm, AffineTransform xform, int bWidth, int bHeight, int maxw) { this.colorModel = getInternedColorModel(cm); this.bWidth = bWidth; this.bHeight = bHeight; this.maxWidth = maxw; try { xform = xform.createInverse(); } catch (NoninvertibleTransformException e) { xform.setToScale(0, 0); } this.incXAcross = mod(xform.getScaleX(), bWidth); this.incYAcross = mod(xform.getShearY(), bHeight); this.incXDown = mod(xform.getShearX(), bWidth); this.incYDown = mod(xform.getScaleY(), bHeight); this.xOrg = xform.getTranslateX(); this.yOrg = xform.getTranslateY(); this.colincx = (int) incXAcross; this.colincy = (int) incYAcross; this.colincxerr = fractAsInt(incXAcross); this.colincyerr = fractAsInt(incYAcross); this.rowincx = (int) incXDown; this.rowincy = (int) incYDown; this.rowincxerr = fractAsInt(incXDown); this.rowincyerr = fractAsInt(incYDown); }
/** * Cuando soltamos el botón del ratón desplazamos la imagen a la posición de destino calculando el * extent nuevamente. */ public void mouseReleased(MouseEvent e) throws BehaviorException { if (!isActiveTool()) return; if (e.getButton() == MouseEvent.BUTTON1 && isMoveable) { FLyrRasterSE lyr = grBehavior.getLayer(); if (lyr == null) return; ViewPort vp = grBehavior.getMapControl().getMapContext().getViewPort(); ptoFin = vp.toMapPoint(e.getPoint()); // Asignamos la nueva matriz de transformación a la capa AffineTransform atOld = lyr.getAffineTransform(); AffineTransform atNew = null; double distX = ptoFin.getX() - ptoIni.getX(); double distY = ptoFin.getY() - ptoIni.getY(); // La nueva matriz de transformación es la vieja más la distancia desplazada atNew = new AffineTransform( atOld.getScaleX(), atOld.getShearY(), atOld.getShearX(), atOld.getScaleY(), atOld.getTranslateX() + distX, atOld.getTranslateY() + distY); lyr.setAffineTransform(atNew); grBehavior.getMapControl().getMapContext().invalidate(); isMoveable = false; super.mouseReleased(e); } }
public void init(Graphics2D g, float scale, int width, int height) { if (this.METRICS == null) { AffineTransform transform = g.getTransform(); if (Double.compare(transform.getScaleX(), 1) != 0 || Double.compare(transform.getScaleY(), 1) != 0) { throw new IllegalStateException("Illegal Transform"); } this.METRICS = new FontMetrics[FONTS.length]; Font defaultFont = g.getFont(); for (int i = 0; i < FONTS.length; i++) { g.setFont(FONTS[i]); this.METRICS[i] = g.getFontMetrics(); } g.setFont(defaultFont); } this.g = g; this.scale = scale; this.screen.width = width; this.screen.height = height; this.lapList.clear(); this.fixedLabelMap.clear(); this.r = (int) (2 / this.scale + 0.5); this.r2 = (int) (4 / this.scale + 0.5); }
/** * Applique une translation à la perspective selon le mouvement de la souris par rapport au centre * de l'image. * * @param coordSouris Les coordonnées de la souris. */ public void translate(double[] coordSouris) { double largeur; double hauteur; // Garde en mémoire la transformation courant pileTransform.push(new AffineTransform(transformation)); // Calcul des dimensions après le zoom largeur = panneauSource.getImagePlus().getWidth() * panneauSource.getImagePlus().getPerspective().getTransformation().getScaleX(); hauteur = panneauSource.getImagePlus().getHeight() * panneauSource.getImagePlus().getPerspective().getTransformation().getScaleY(); // Déplacement de la perspective selon la position de la souris. transformation.setTransform( transformation.getScaleX(), 0, 0, transformation.getScaleY(), coordSouris[0] - (largeur / 2), coordSouris[1] - (hauteur / 2)); setChanged(); notifyObservers(); }
private Rectangle getScaledRectangle(Rectangle rectangle) { final AffineTransform i2mTransform = ImageManager.getImageToModelTransform(product.getGeoCoding()); final double scaleX = i2mTransform.getScaleX(); final double scaleY = i2mTransform.getScaleY(); double scaleFactorY = Math.abs(scaleY / scaleX); final AffineTransform scaleTransform = AffineTransform.getScaleInstance(1.0, scaleFactorY); return scaleTransform.createTransformedShape(rectangle).getBounds(); }
public synchronized void paintIcon(Component c, Graphics g, int x, int y) { paintFrame(c, g, x, y); if (c != null) { int w = getIconWidth(); int h = getIconHeight(); AffineTransform tx = ((Graphics2D) g).getTransform(); w = (int) (w * tx.getScaleX()); h = (int) (h * tx.getScaleY()); registerRepaintArea(c, x, y, w, h); } }
/** * 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 handleZoom(double zoom) { final int scaleFactor = 1; final double accelerationFactor = 0.05; final double scaleZoom = 0.25; final double scaleFactorDown = 0.8; zoom = scaleZoom * -zoom; zoom += 1; transformCells.translate(zoomCenterX, zoomCenterY); double newScale = transformCells.getScaleX(); int acceleration = round(newScale * accelerationFactor); if (zoom > 1) { if (transformCells.getScaleX() > 0.95) { newScale = (newScale + scaleFactor + acceleration) / newScale; } else { newScale = 1 / scaleFactorDown; } } else if (zoom < 1) { if (transformCells.getScaleX() > 1.05) { newScale = (newScale - scaleFactor - acceleration) / newScale; } else { newScale = scaleFactorDown; } } if (transformCells.getScaleX() * newScale >= MIN_SCALE && transformCells.getScaleX() * newScale <= MAX_SCALE) { transformCells.scale(newScale, newScale); } transformCells.translate(-zoomCenterX, -zoomCenterY); if (previewTransform != null) { calculatePreviewTranslation(); } bufferedImageGrid = createGrid(); repaint(); }
/** Asigna las coordenadas temporales en el dialogo. */ public void assignTransformToDialog() { AffineTransform atNew = null; double distX = ptoFin.getX() - ptoIni.getX(); double distY = ptoFin.getY() - ptoIni.getY(); AffineTransform atOld = grBehavior.getLayer().getAffineTransform(); // La nueva matriz de transformación es la vieja más la distancia desplazada atNew = new AffineTransform( atOld.getScaleX(), atOld.getShearY(), atOld.getShearX(), atOld.getScaleY(), atOld.getTranslateX() + distX, atOld.getTranslateY() + distY); trIO.loadTransform(atNew); }
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); }
/** * Scales current view point transformation. * * @param sx Amount to scale by along the x axis. * @param sy Amount to scale by along the y axis. * @param isLast Flag, indicating that this scale is last in sequence of arbitrary view point * operations. * @throws Exception */ public void scaleView(double sx, double sy, boolean isLast) throws Exception { recalcViewPoint(); double targetScaleX = cartesian2Screen.getScaleX() * sx; double targetScaleY = cartesian2Screen.getScaleY() * sy; if (targetScaleX >= SCALE_MIN_BOUNDARY && targetScaleX <= SCALE_MAX_BOUNDARY && targetScaleY >= SCALE_MIN_BOUNDARY && targetScaleY <= SCALE_MAX_BOUNDARY) { cartesian2Screen.scale(sx, sy); cache.scaleChanged(); lightweightCache.scaleChanged(); if (isLast) { invalidate(); fireViewScaled(sx, sy, aoiToGeoGeometry(), aoiToCartesianGeometry()); } } }
@Override public FGEArea transform(AffineTransform t) { // TODO: not valid for AffineTransform containing rotations FGEPoint p1 = (new FGEPoint(getX(), getY())).transform(t); FGEPoint p2 = (new FGEPoint(getX() + getWidth(), getY() + getHeight())).transform(t); // TODO: if transformation contains a rotation, turn into a regular polygon // arcwidth,archeight must also be computed according to this rotation return new FGERoundRectangle( Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y), arcwidth * t.getScaleX(), archeight * t.getScaleY(), _filling); }
public void mouseDragged(MouseEvent e) { if (e.getModifiers() == modifiers) { Point2D pEndScale = e.getPoint(); double scale = pEndScale.distance(viewOrigin) / pStartScale.distance(viewOrigin); AffineTransform transform = super.plot.getTransform(); transform.setTransform( transform.getScaleX() * scale, transform.getShearY(), transform.getShearX(), transform.getScaleY() * scale, transform.getTranslateX() * scale, transform.getTranslateY() * scale); pStartScale = pEndScale; super.plot.setTransform(transform); } }
public void draw(Graphics2D g2, float x, float y) { AffineTransform transf = g2.getTransform(); Stroke oldStroke = g2.getStroke(); final double sx = transf.getScaleX(); final double sy = transf.getScaleY(); double s = 1; if (sx == sy) { // There are rounding problems due to scale factor: lines could have different // spacing... // So the increment (space+thickness) is done in using integer. s = sx; AffineTransform t = (AffineTransform) transf.clone(); t.scale(1 / sx, 1 / sy); g2.setTransform(t); } g2.setStroke( new BasicStroke((float) (s * thickness), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); float th = thickness / 2.f; final Line2D.Float line = new Line2D.Float(); float xx = x + space; xx = (float) (xx * s + (space / 2.f) * s); final int inc = (int) Math.round((space + thickness) * s); for (int i = 0; i < N; i++) { line.setLine(xx + th * s, (y - height) * s, xx + th * s, y * s); g2.draw(line); xx += inc; } if (strike) { line.setLine( (x + space) * s, (y - height / 2.f) * s, xx - s * space / 2, (y - height / 2.f) * s); g2.draw(line); } g2.setTransform(transf); g2.setStroke(oldStroke); }
void setModelTransformation(final AffineTransform gridToCRS) { // See pag 28 of the spec for an explanation final double[] modelTransformation = new double[16]; modelTransformation[0] = gridToCRS.getScaleX(); modelTransformation[1] = gridToCRS.getShearX(); modelTransformation[2] = 0; modelTransformation[3] = gridToCRS.getTranslateX(); modelTransformation[4] = gridToCRS.getShearY(); modelTransformation[5] = gridToCRS.getScaleY(); modelTransformation[6] = 0; modelTransformation[7] = gridToCRS.getTranslateY(); modelTransformation[8] = 0; modelTransformation[9] = 0; modelTransformation[10] = 0; modelTransformation[11] = 0; modelTransformation[12] = 0; modelTransformation[13] = 0; modelTransformation[14] = 0; modelTransformation[15] = 1; nTransform = createTiffField(getModelTransformationTag()); final Node nValues = createTiffDoubles(modelTransformation); nTransform.appendChild(nValues); }
/** * Constructor creates an instance to be used for fill operations. * * @param shading the shading type to be used * @param colorModel the color model to be used * @param xform transformation for user to device space * @param ctm the transformation matrix * @param dBounds device bounds * @param pageHeight height of the current page */ public RadialShadingContext( PDShadingType3 shading, ColorModel colorModel, AffineTransform xform, Matrix ctm, int pageHeight, Rectangle dBounds) throws IOException { super(shading, colorModel, xform, ctm, pageHeight, dBounds); this.radialShadingType = shading; coords = shading.getCoords().toFloatArray(); if (ctm != null) { // the shading is used in combination with the sh-operator // transform the coords from shading to user space ctm.createAffineTransform().transform(coords, 0, coords, 0, 1); ctm.createAffineTransform().transform(coords, 3, coords, 3, 1); // scale radius to user space coords[2] *= ctm.getXScale(); coords[5] *= ctm.getXScale(); // move the 0,0-reference coords[1] = pageHeight - coords[1]; coords[4] = pageHeight - coords[4]; } else { // the shading is used as pattern colorspace in combination // with a fill-, stroke- or showText-operator float translateY = (float) xform.getTranslateY(); // move the 0,0-reference including the y-translation from user to device space coords[1] = pageHeight + translateY - coords[1]; coords[4] = pageHeight + translateY - coords[4]; } // transform the coords from user to device space xform.transform(coords, 0, coords, 0, 1); xform.transform(coords, 3, coords, 3, 1); // scale radius to device space coords[2] *= xform.getScaleX(); coords[5] *= xform.getScaleX(); // a radius is always positive coords[2] = Math.abs(coords[2]); coords[5] = Math.abs(coords[5]); // domain values if (this.radialShadingType.getDomain() != null) { domain = shading.getDomain().toFloatArray(); } else { // set default values domain = new float[] {0, 1}; } // extend values COSArray extendValues = shading.getExtend(); if (shading.getExtend() != null) { extend = new boolean[2]; extend[0] = ((COSBoolean) extendValues.get(0)).getValue(); extend[1] = ((COSBoolean) extendValues.get(1)).getValue(); } else { // set default values extend = new boolean[] {false, false}; } // calculate some constants to be used in getRaster x1x0 = coords[3] - coords[0]; y1y0 = coords[4] - coords[1]; r1r0 = coords[5] - coords[2]; x1x0pow2 = Math.pow(x1x0, 2); y1y0pow2 = Math.pow(y1y0, 2); r0pow2 = Math.pow(coords[2], 2); denom = x1x0pow2 + y1y0pow2 - Math.pow(r1r0, 2); d1d0 = domain[1] - domain[0]; // get background values if available COSArray bg = shading.getBackground(); if (bg != null) { background = bg.toFloatArray(); rgbBackground = convertToRGB(background); } longestDistance = getLongestDis(); colorTable = calcColorTable(); }
/** * Applique un zoom à la perspective selon la direction de la molette. * * @param facteurZoom La direction de la molette. */ public void zoom(double wheelRotation) { /* * Pour conserver le zoom centrer, on doit d'abord déplacer le coin * supérieur gauche vers le centre, appliquer le zoom, puis revenir * vers la position originale. En utilisant la variation de dimension * avant et après le zoom, l'image ne reviendra pas exactement à sa * position originale, s'ajustant ainsi proportionnellement au zoom * appliqué. */ double largeur; double hauteur; // Garde en mémoire la transformation courant pileTransform.push(new AffineTransform(transformation)); zoom = 1; zoom += (.1 * -wheelRotation); // Calcul des dimensions avant le zoom largeur = panneauSource.getImagePlus().getWidth() * panneauSource.getImagePlus().getPerspective().getTransformation().getScaleX(); hauteur = panneauSource.getImagePlus().getHeight() * panneauSource.getImagePlus().getPerspective().getTransformation().getScaleY(); /* On translate l'image vers le centre. A noter que d'utiliser translate ou setToTranslate ne donne pas le résultat escompté en raison du "state" ou du fonctionnement un peu anodin du mutateur. */ transformation.setTransform( transformation.getScaleX(), 0, 0, transformation.getScaleY(), transformation.getTranslateX() + largeur / 2, transformation.getTranslateY() + hauteur / 2); // On applique le zoom transformation.scale(zoom, zoom); // Calcul des dimensions après le zoom largeur = panneauSource.getImagePlus().getWidth() * panneauSource.getImagePlus().getPerspective().getTransformation().getScaleX(); hauteur = panneauSource.getImagePlus().getHeight() * panneauSource.getImagePlus().getPerspective().getTransformation().getScaleY(); /* On translate l'image vers sa position d'origine. A noter que d'utiliser translate ou setToTranslate ne donne pas le résultat escompté en raison du "state" ou du fonctionnement un peu anodin du mutateur. */ transformation.setTransform( transformation.getScaleX(), 0, 0, transformation.getScaleY(), transformation.getTranslateX() - largeur / 2, transformation.getTranslateY() - hauteur / 2); setChanged(); notifyObservers(); }
private Point2D getCellSizeAfterScale() { return new Point2D.Double(round(transformCells.getScaleX()), round(transformCells.getScaleY())); }
/** * DOCUMENT ME! * * @param graphics DOCUMENT ME! * @param shape DOCUMENT ME! * @param style DOCUMENT ME! */ public static void drawShape(Graphics2D graphics, Shape shape, Style2D style) { if (style instanceof MarkStyle2D) { // get the point onto the shape has to be painted float[] coords = new float[2]; PathIterator iter = shape.getPathIterator(IDENTITY_TRANSFORM); iter.currentSegment(coords); MarkStyle2D ms2d = (MarkStyle2D) style; Shape transformedShape = ms2d.getTransformedShape(coords[0], coords[1]); if (transformedShape != null) { if (ms2d.getFill() != null) { graphics.setPaint(ms2d.getFill()); graphics.setComposite(ms2d.getFillComposite()); graphics.fill(transformedShape); } if (ms2d.getContour() != null) { graphics.setPaint(ms2d.getContour()); graphics.setStroke(ms2d.getStroke()); graphics.setComposite(ms2d.getContourComposite()); graphics.draw(transformedShape); } } } else if (style instanceof GraphicStyle2D) { // get the point onto the shape has to be painted float[] coords = new float[2]; PathIterator iter = shape.getPathIterator(IDENTITY_TRANSFORM); iter.currentSegment(coords); GraphicStyle2D gs2d = (GraphicStyle2D) style; renderImage( graphics, coords[0], coords[1], (Image) gs2d.getImage(), gs2d.getRotation(), gs2d.getOpacity()); } else if (style instanceof TextStyle2D) { // get the point onto the shape has to be painted float[] coords = new float[2]; PathIterator iter = shape.getPathIterator(IDENTITY_TRANSFORM); iter.currentSegment(coords); AffineTransform old = graphics.getTransform(); AffineTransform temp = new AffineTransform(old); TextStyle2D ts2d = (TextStyle2D) style; GlyphVector textGv = ts2d.getTextGlyphVector(graphics); Rectangle2D bounds = textGv.getVisualBounds(); temp.translate(coords[0], coords[1]); double x = 0; double y = 0; x = (ts2d.getAnchorX() * (-bounds.getWidth())) + ts2d.getDisplacementX(); y = (ts2d.getAnchorY() * (bounds.getHeight())) + ts2d.getDisplacementY(); temp.rotate(ts2d.getRotation()); temp.translate(x, y); graphics.setTransform(temp); if (ts2d.getHaloFill() != null) { float radious = ts2d.getHaloRadius(); // graphics.translate(radious, -radious); graphics.setPaint(ts2d.getHaloFill()); graphics.setComposite(ts2d.getHaloComposite()); graphics.fill(ts2d.getHaloShape(graphics)); // graphics.translate(radious, radious); } if (ts2d.getFill() != null) { graphics.setPaint(ts2d.getFill()); graphics.setComposite(ts2d.getComposite()); graphics.drawGlyphVector(textGv, 0, 0); } graphics.setTransform(old); } else { // if the style is a polygon one, process it even if the polyline is // not // closed (by SLD specification) if (style instanceof PolygonStyle2D) { PolygonStyle2D ps2d = (PolygonStyle2D) style; if (ps2d.getFill() != null) { Paint paint = ps2d.getFill(); if (paint instanceof TexturePaint) { TexturePaint tp = (TexturePaint) paint; BufferedImage image = tp.getImage(); Rectangle2D rect = tp.getAnchorRect(); AffineTransform at = graphics.getTransform(); double width = rect.getWidth() * at.getScaleX(); double height = rect.getHeight() * at.getScaleY(); Rectangle2D scaledRect = new Rectangle2D.Double(0, 0, width, height); paint = new TexturePaint(image, scaledRect); } graphics.setPaint(paint); graphics.setComposite(ps2d.getFillComposite()); graphics.fill(shape); } } if (style instanceof LineStyle2D) { LineStyle2D ls2d = (LineStyle2D) style; if (ls2d.getStroke() != null) { // see if a graphic stroke is to be used, the drawing method // is completely // different in this case Paint paint = ls2d.getContour(); if (paint instanceof TexturePaint) { TexturePaint tp = (TexturePaint) paint; BufferedImage image = tp.getImage(); Rectangle2D rect = tp.getAnchorRect(); AffineTransform at = graphics.getTransform(); double width = rect.getWidth() * at.getScaleX(); double height = rect.getHeight() * at.getScaleY(); Rectangle2D scaledRect = new Rectangle2D.Double(0, 0, width, height); paint = new TexturePaint(image, scaledRect); } graphics.setPaint(paint); graphics.setStroke(ls2d.getStroke()); graphics.setComposite(ls2d.getContourComposite()); graphics.draw(shape); } } } }
public int getCollisionRadius() { return (int) (scale.getScaleX() * getRadius()); }
/** * Invoked automatically when a polyline is about to be draw. This implementation paints the * polyline according to the rendered style * * @param graphics The graphics in which to draw. * @param shape The polygon to draw. * @param style The style to apply, or <code>null</code> if none. * @param scale The scale denominator for the current zoom level * @throws FactoryException * @throws TransformException */ public void paint( final Graphics2D graphics, final LiteShape2 shape, final Style2D style, final double scale, boolean isLabelObstacle) { if (style == null) { // TODO: what's going on? Should not be reached... LOGGER.severe("ShapePainter has been asked to paint a null style!!"); return; } // Is the current scale within the style scale range? if (!style.isScaleInRange(scale)) { LOGGER.fine("Out of scale"); return; } if (style instanceof IconStyle2D) { AffineTransform temp = graphics.getTransform(); try { IconStyle2D icoStyle = (IconStyle2D) style; Icon icon = icoStyle.getIcon(); graphics.setComposite(icoStyle.getComposite()); // the displacement to be applied to all points, centers the icon and applies the // Graphic displacement as well float dx = icoStyle.getDisplacementX(); float dy = icoStyle.getDisplacementY(); // iterate over all points float[] coords = new float[2]; PathIterator citer = getPathIterator(shape); AffineTransform at = new AffineTransform(temp); while (!(citer.isDone())) { if (citer.currentSegment(coords) != PathIterator.SEG_MOVETO) { at.setTransform(temp); double x = coords[0] + dx; double y = coords[1] + dy; at.translate(x, y); at.rotate(icoStyle.getRotation()); at.translate( -(icon.getIconWidth() * icoStyle.getAnchorPointX()), (icon.getIconHeight() * (icoStyle.getAnchorPointY() - 1))); graphics.setTransform(at); icon.paintIcon(null, graphics, 0, 0); if (isLabelObstacle) { // TODO: rotation? labelCache.put( new Rectangle2D.Double(x, y, icon.getIconWidth(), icon.getIconHeight())); } } citer.next(); } } finally { graphics.setTransform(temp); } } else if (style instanceof MarkStyle2D) { PathIterator citer = getPathIterator(shape); // get the point onto the shape has to be painted float[] coords = new float[2]; MarkStyle2D ms2d = (MarkStyle2D) style; Shape transformedShape; while (!(citer.isDone())) { if (citer.currentSegment(coords) != PathIterator.SEG_MOVETO) { transformedShape = ms2d.getTransformedShape(coords[0], coords[1]); if (transformedShape != null) { if (ms2d.getFill() != null) { graphics.setPaint(ms2d.getFill()); graphics.setComposite(ms2d.getFillComposite()); graphics.fill(transformedShape); } if (ms2d.getContour() != null) { graphics.setPaint(ms2d.getContour()); graphics.setStroke(ms2d.getStroke()); graphics.setComposite(ms2d.getContourComposite()); graphics.draw(transformedShape); } if (isLabelObstacle) { labelCache.put(transformedShape.getBounds2D()); } } } citer.next(); } } else if (style instanceof GraphicStyle2D) { float[] coords = new float[2]; PathIterator iter = getPathIterator(shape); iter.currentSegment(coords); GraphicStyle2D gs2d = (GraphicStyle2D) style; BufferedImage image = gs2d.getImage(); double dx = gs2d.getDisplacementX() - gs2d.getAnchorPointX() * image.getWidth(); double dy = gs2d.getDisplacementY() - ((1 - gs2d.getAnchorPointY()) * image.getHeight()); while (!(iter.isDone())) { if (iter.currentSegment(coords) != PathIterator.SEG_MOVETO) { renderImage( graphics, coords[0], coords[1], dx, dy, image, gs2d.getRotation(), gs2d.getComposite(), isLabelObstacle); } iter.next(); } } else { if (isLabelObstacle) { labelCache.put(shape.getBounds2D()); } // if the style is a polygon one, process it even if the polyline is // not closed (by SLD specification) if (style instanceof PolygonStyle2D) { PolygonStyle2D ps2d = (PolygonStyle2D) style; if (ps2d.getFill() != null) { Paint paint = ps2d.getFill(); if (paint instanceof TexturePaint) { TexturePaint tp = (TexturePaint) paint; BufferedImage image = tp.getImage(); Rectangle2D cornerRect = tp.getAnchorRect(); Point2D anchorPoint = (Point2D) graphics.getRenderingHint(TEXTURE_ANCHOR_HINT_KEY); Rectangle2D alignedRect = null; if (anchorPoint != null) { alignedRect = new Rectangle2D.Double( Math.round(anchorPoint.getX()), Math.round(anchorPoint.getY()), cornerRect.getWidth(), cornerRect.getHeight()); } else { alignedRect = new Rectangle2D.Double(0.0, 0.0, cornerRect.getWidth(), cornerRect.getHeight()); } paint = new TexturePaint(image, alignedRect); } graphics.setPaint(paint); graphics.setComposite(ps2d.getFillComposite()); fillLiteShape(graphics, shape); } if (ps2d.getGraphicFill() != null) { Shape oldClip = graphics.getClip(); try { paintGraphicFill(graphics, shape, ps2d.getGraphicFill(), scale); } finally { graphics.setClip(oldClip); } } } if (style instanceof LineStyle2D) { LineStyle2D ls2d = (LineStyle2D) style; if (ls2d.getStroke() != null) { // see if a graphic stroke is to be used, the drawing method // is completely // different in this case if (ls2d.getGraphicStroke() != null) { drawWithGraphicsStroke( graphics, dashShape(shape, ls2d.getStroke()), ls2d.getGraphicStroke(), isLabelObstacle); } else { Paint paint = ls2d.getContour(); if (paint instanceof TexturePaint) { TexturePaint tp = (TexturePaint) paint; BufferedImage image = tp.getImage(); Rectangle2D rect = tp.getAnchorRect(); AffineTransform at = graphics.getTransform(); double width = rect.getWidth() * at.getScaleX(); double height = rect.getHeight() * at.getScaleY(); Rectangle2D scaledRect = new Rectangle2D.Double(0, 0, width, height); paint = new TexturePaint(image, scaledRect); } // debugShape(shape); Stroke stroke = ls2d.getStroke(); if (graphics.getRenderingHint(RenderingHints.KEY_ANTIALIASING) == RenderingHints.VALUE_ANTIALIAS_ON) { if (stroke instanceof BasicStroke) { BasicStroke bs = (BasicStroke) stroke; stroke = new BasicStroke( bs.getLineWidth() + 0.5f, bs.getEndCap(), bs.getLineJoin(), bs.getMiterLimit(), bs.getDashArray(), bs.getDashPhase()); } } graphics.setPaint(paint); graphics.setStroke(stroke); graphics.setComposite(ls2d.getContourComposite()); graphics.draw(shape); } } } } }
public int getCollisionBoxWidth() { return (int) (scale.getScaleX() * getWidth()); }
/** * Ipp filter. * * @param src the src. * @param dst the dst. * @param imageType the image type. * @return the int. */ @SuppressWarnings("unused") private int ippFilter(Raster src, WritableRaster dst, int imageType) { int srcStride, dstStride; boolean skipChannel = false; int channels; int offsets[] = null; switch (imageType) { case BufferedImage.TYPE_INT_RGB: case BufferedImage.TYPE_INT_BGR: { channels = 4; srcStride = src.getWidth() * 4; dstStride = dst.getWidth() * 4; skipChannel = true; break; } case BufferedImage.TYPE_INT_ARGB: case BufferedImage.TYPE_INT_ARGB_PRE: case BufferedImage.TYPE_4BYTE_ABGR: case BufferedImage.TYPE_4BYTE_ABGR_PRE: { channels = 4; srcStride = src.getWidth() * 4; dstStride = dst.getWidth() * 4; break; } case BufferedImage.TYPE_BYTE_GRAY: case BufferedImage.TYPE_BYTE_INDEXED: { channels = 1; srcStride = src.getWidth(); dstStride = dst.getWidth(); break; } case BufferedImage.TYPE_3BYTE_BGR: { channels = 3; srcStride = src.getWidth() * 3; dstStride = dst.getWidth() * 3; break; } case BufferedImage.TYPE_USHORT_GRAY: // TODO - could be done in // native code? case BufferedImage.TYPE_USHORT_565_RGB: case BufferedImage.TYPE_USHORT_555_RGB: case BufferedImage.TYPE_BYTE_BINARY: { return slowFilter(src, dst); } default: { SampleModel srcSM = src.getSampleModel(); SampleModel dstSM = dst.getSampleModel(); if (srcSM instanceof PixelInterleavedSampleModel && dstSM instanceof PixelInterleavedSampleModel) { // Check PixelInterleavedSampleModel if (srcSM.getDataType() != DataBuffer.TYPE_BYTE || dstSM.getDataType() != DataBuffer.TYPE_BYTE) { return slowFilter(src, dst); } channels = srcSM.getNumBands(); // Have IPP functions for 1, // 3 and 4 channels if (channels != 1 && channels != 3 && channels != 4) { return slowFilter(src, dst); } int dataTypeSize = DataBuffer.getDataTypeSize(srcSM.getDataType()) / 8; srcStride = ((ComponentSampleModel) srcSM).getScanlineStride() * dataTypeSize; dstStride = ((ComponentSampleModel) dstSM).getScanlineStride() * dataTypeSize; } else if (srcSM instanceof SinglePixelPackedSampleModel && dstSM instanceof SinglePixelPackedSampleModel) { // Check SinglePixelPackedSampleModel SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM; SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM; // No IPP function for this type if (sppsm1.getDataType() == DataBuffer.TYPE_USHORT) { return slowFilter(src, dst); } channels = sppsm1.getNumBands(); // Have IPP functions for 1, 3 and 4 channels if (channels != 1 && channels != 3 && channels != 4) { return slowFilter(src, dst); } // Check compatibility of sample models if (sppsm1.getDataType() != sppsm2.getDataType() || !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) || !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())) { return slowFilter(src, dst); } for (int i = 0; i < channels; i++) { if (sppsm1.getSampleSize(i) != 8) { return slowFilter(src, dst); } } if (channels == 3) { channels = 4; } int dataTypeSize = DataBuffer.getDataTypeSize(sppsm1.getDataType()) / 8; srcStride = sppsm1.getScanlineStride() * dataTypeSize; dstStride = sppsm2.getScanlineStride() * dataTypeSize; } else { return slowFilter(src, dst); } // Fill offsets if there's a child raster if (src.getParent() != null || dst.getParent() != null) { if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0 || dst.getSampleModelTranslateX() != 0 || dst.getSampleModelTranslateY() != 0) { offsets = new int[4]; offsets[0] = -src.getSampleModelTranslateX() + src.getMinX(); offsets[1] = -src.getSampleModelTranslateY() + src.getMinY(); offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX(); offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY(); } } } } double m00 = at.getScaleX(); double m01 = at.getShearX(); double m02 = at.getTranslateX(); double m10 = at.getShearY(); double m11 = at.getScaleY(); double m12 = at.getTranslateY(); Object srcData, dstData; AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance(); try { srcData = dbAccess.getData(src.getDataBuffer()); dstData = dbAccess.getData(dst.getDataBuffer()); } catch (IllegalArgumentException e) { return -1; // Unknown data buffer type } return ippAffineTransform( m00, m01, m02, m10, m11, m12, srcData, src.getWidth(), src.getHeight(), srcStride, dstData, dst.getWidth(), dst.getHeight(), dstStride, iType, channels, skipChannel, offsets); }
/** * 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(); } } } }
@DescribeResult(name = "result", description = "The contours feature collection") public SimpleFeatureCollection execute( @DescribeParameter(name = "data", description = "The raster to be used as the source") GridCoverage2D gc2d, @DescribeParameter( name = "band", description = "The source image band to process", min = 0, max = 1) Integer band, @DescribeParameter(name = "levels", description = "Values for which to generate contours") double[] levels, @DescribeParameter( name = "interval", description = "Interval between contour values (ignored if levels arg is supplied)", min = 0) Double interval, @DescribeParameter( name = "simplify", description = "Values for which to generate contours", min = 0) Boolean simplify, @DescribeParameter( name = "smooth", description = "Values for which to generate contours", min = 0) Boolean smooth, @DescribeParameter( name = "roi", description = "The geometry used to delineate the area of interest in model space", min = 0) Geometry roi, ProgressListener progressListener) throws ProcessException { // // initial checks // if (gc2d == null) { throw new ProcessException("Invalid input, source grid coverage should be not null"); } if (band != null && (band < 0 || band >= gc2d.getNumSampleDimensions())) { throw new ProcessException("Invalid input, invalid band number:" + band); } boolean hasValues = !(levels == null || levels.length == 0); if (!hasValues && interval == null) { throw new ProcessException("One between interval and values must be valid"); } // switch to geophisics if necessary gc2d = gc2d.view(ViewType.GEOPHYSICS); // // GRID TO WORLD preparation // final AffineTransform mt2D = (AffineTransform) gc2d.getGridGeometry().getGridToCRS2D(PixelOrientation.CENTER); // get the list of nodata, if any List<Object> noDataList = new ArrayList<Object>(); for (GridSampleDimension sd : gc2d.getSampleDimensions()) { // grab all the explicit nodata final double[] sdNoData = sd.getNoDataValues(); if (sdNoData != null) { for (double nodata : sdNoData) { noDataList.add(nodata); } } // handle also readers setting up nodata in a category with a specific name if (sd.getCategories() != null) { for (Category cat : sd.getCategories()) { if (cat.getName().equals(NO_DATA)) { final NumberRange<? extends Number> catRange = cat.getRange(); if (catRange.getMinimum() == catRange.getMaximum()) { noDataList.add(catRange.getMinimum()); } else { Range<Double> noData = new Range<Double>( catRange.getMinimum(), catRange.isMinIncluded(), catRange.getMaximum(), catRange.isMaxIncluded()); noDataList.add(noData); } } } } } // get the rendered image final RenderedImage raster = gc2d.getRenderedImage(); // perform jai operation ParameterBlockJAI pb = new ParameterBlockJAI("Contour"); pb.setSource("source0", raster); if (roi != null) { pb.setParameter("roi", CoverageUtilities.prepareROI(roi, mt2D)); } if (band != null) { pb.setParameter("band", band); } if (interval != null) { pb.setParameter("interval", interval); } else { final ArrayList<Double> elements = new ArrayList<Double>(levels.length); for (double level : levels) elements.add(level); pb.setParameter("levels", elements); } if (simplify != null) { pb.setParameter("simplify", simplify); } if (smooth != null) { pb.setParameter("smooth", smooth); } if (noDataList != null) { pb.setParameter("nodata", noDataList); } final RenderedOp dest = JAI.create("Contour", pb); @SuppressWarnings("unchecked") final Collection<LineString> prop = (Collection<LineString>) dest.getProperty(ContourDescriptor.CONTOUR_PROPERTY_NAME); // wrap as a feature collection and return final SimpleFeatureType schema = CoverageUtilities.createFeatureType(gc2d, LineString.class); final SimpleFeatureBuilder builder = new SimpleFeatureBuilder(schema); int i = 0; final ListFeatureCollection featureCollection = new ListFeatureCollection(schema); final AffineTransformation jtsTransformation = new AffineTransformation( mt2D.getScaleX(), mt2D.getShearX(), mt2D.getTranslateX(), mt2D.getShearY(), mt2D.getScaleY(), mt2D.getTranslateY()); for (LineString line : prop) { // get value Double value = (Double) line.getUserData(); line.setUserData(null); // filter coordinates in place line.apply(jtsTransformation); // create feature and add to list builder.set("the_geom", line); builder.set("value", value); featureCollection.add(builder.buildFeature(String.valueOf(i++))); } // return value return featureCollection; }
/** * Executes the raster to vector process. * * @param coverage the input grid coverage * @param band the coverage band to process; defaults to 0 if {@code null} * @param insideEdges whether boundaries between raster regions with data values (ie. not NODATA) * should be returned; defaults to {@code true} if {@code null} * @param roi optional polygonal {@code Geometry} to define a sub-area within which vectorizing * will be done * @param noDataValues optional list of values to treat as NODATA; regions with these values will * not be represented in the returned features; if {@code null}, 0 is used as the single * NODATA value; ignored if {@code classificationRanges} is provided * @param classificationRanges optional list of {@code Range} objects to pre-classify the input * coverage prior to vectorizing; values not included in the list will be treated as NODATA; * values in the first {@code Range} are classified to 1, those in the second {@code Range} to * 2 etc. * @param progressListener an optional listener * @return a feature collection where each feature has a {@code Polygon} ("the_geom") and an * attribute "value" with value of the corresponding region in either {@code coverage} or the * classified coverage (when {@code classificationRanges} is used) * @throws ProcessException */ @DescribeResult(name = "result", description = "The polygon feature collection") public SimpleFeatureCollection execute( @DescribeParameter(name = "data", description = "The raster to be used as the source") GridCoverage2D coverage, @DescribeParameter( name = "band", description = "(Integer, default=0) the source image band to process", min = 0) Integer band, @DescribeParameter( name = "insideEdges", description = "(Boolean, default=true) whether to vectorize boundaries between adjacent regions with non-outside values", min = 0) Boolean insideEdges, @DescribeParameter( name = "roi", description = "The geometry used to delineate the area of interest in model space", min = 0) Geometry roi, @DescribeParameter( name = "nodata", description = "Collection<Number>, default={0}) values to treat as NODATA", collectionType = Number.class, min = 0) Collection<Number> noDataValues, @DescribeParameter( name = "ranges", description = "The list of ranges to be applied. \n" + "Each range is expressed as 'OPEN START ; END CLOSE'\n" + "where 'OPEN:=(|[, CLOSE=)|]',\n " + "START is the low value, or nothing to imply -INF,\n" + "CLOSE is the biggest value, or nothing to imply +INF", collectionType = Range.class, min = 0) List<Range> classificationRanges, ProgressListener progressListener) throws ProcessException { // // initial checks // if (coverage == null) { throw new ProcessException("Invalid input, source grid coverage should be not null"); } if (band == null) { band = 0; } else if (band < 0 || band >= coverage.getNumSampleDimensions()) { throw new ProcessException("Invalid input, invalid band number:" + band); } // do we have classification ranges? boolean hasClassificationRanges = classificationRanges != null && classificationRanges.size() > 0; // apply the classification by setting 0 as the default value and using 1, ..., numClasses for // the other classes. // we use 0 also as the noData for the resulting coverage. if (hasClassificationRanges) { final RangeLookupProcess lookup = new RangeLookupProcess(); coverage = lookup.execute(coverage, band, classificationRanges, progressListener); } // Use noDataValues to set the "outsideValues" parameter of the Vectorize // operation unless classificationRanges are in use, in which case the // noDataValues arg is ignored. List<Number> outsideValues = new ArrayList<Number>(); if (noDataValues != null && !hasClassificationRanges) { outsideValues.addAll(noDataValues); } else { outsideValues.add(0); } // // GRID TO WORLD preparation // final AffineTransform mt2D = (AffineTransform) coverage.getGridGeometry().getGridToCRS2D(PixelOrientation.UPPER_LEFT); // get the rendered image final RenderedImage raster = coverage.getRenderedImage(); // perform jai operation ParameterBlockJAI pb = new ParameterBlockJAI("Vectorize"); pb.setSource("source0", raster); if (roi != null) { pb.setParameter("roi", CoverageUtilities.prepareROI(roi, mt2D)); } pb.setParameter("band", band); pb.setParameter("outsideValues", outsideValues); if (insideEdges != null) { pb.setParameter("insideEdges", insideEdges); } // pb.setParameter("removeCollinear", false); final RenderedOp dest = JAI.create("Vectorize", pb); @SuppressWarnings("unchecked") final Collection<Polygon> prop = (Collection<Polygon>) dest.getProperty(VectorizeDescriptor.VECTOR_PROPERTY_NAME); // wrap as a feature collection and return final SimpleFeatureType featureType = CoverageUtilities.createFeatureType(coverage, Polygon.class); final SimpleFeatureBuilder builder = new SimpleFeatureBuilder(featureType); int i = 0; final ListFeatureCollection featureCollection = new ListFeatureCollection(featureType); final AffineTransformation jtsTransformation = new AffineTransformation( mt2D.getScaleX(), mt2D.getShearX(), mt2D.getTranslateX(), mt2D.getShearY(), mt2D.getScaleY(), mt2D.getTranslateY()); for (Polygon polygon : prop) { // get value Double value = (Double) polygon.getUserData(); polygon.setUserData(null); // filter coordinates in place polygon.apply(jtsTransformation); // create feature and add to list builder.set("the_geom", polygon); builder.set("value", value); featureCollection.add(builder.buildFeature(String.valueOf(i++))); } // return value return featureCollection; }