/** Transform a bounding box. This is only a rough estimate. */ public Rectangle2D transform(Rectangle2D r) { Point2D.Double in = new Point2D.Double(); Point2D.Double out = new Point2D.Double(); Rectangle2D bounds = null; if (isRectilinear()) { for (int ix = 0; ix < 2; ix++) { double x = r.getX() + r.getWidth() * ix; for (int iy = 0; iy < 2; iy++) { double y = r.getY() + r.getHeight() * iy; in.x = x; in.y = y; transform(in, out); if (ix == 0 && iy == 0) bounds = new Rectangle2D.Double(out.x, out.y, 0, 0); else bounds.add(out.x, out.y); } } } else { for (int ix = 0; ix < 7; ix++) { double x = r.getX() + r.getWidth() * ix / 6; for (int iy = 0; iy < 7; iy++) { double y = r.getY() + r.getHeight() * iy / 6; in.x = x; in.y = y; transform(in, out); if (ix == 0 && iy == 0) bounds = new Rectangle2D.Double(out.x, out.y, 0, 0); else bounds.add(out.x, out.y); } } } return bounds; }
public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; String message = "Hello, World!"; Font f = new Font("Serif", Font.BOLD, 36); g2.setFont(f); FontRenderContext context = g2.getFontRenderContext(); Rectangle2D bounds = f.getStringBounds(message, context); double x = (getWidth() - bounds.getWidth()) / 2; double y = (getHeight() - bounds.getHeight()) / 2; double ascent = -bounds.getY(); double baseY = y + ascent; g2.drawString(message, (int) x, (int) baseY); g2.setPaint(Color.LIGHT_GRAY); g2.draw(new Line2D.Double(x, baseY, x + bounds.getWidth(), baseY)); Rectangle2D rect = new Rectangle2D.Double(x, y, bounds.getWidth(), bounds.getHeight()); g2.draw(rect); }
public void addTriggerToParking(TaxiwayParkingModel model) { Rectangle2D square = ((java.awt.geom.Ellipse2D.Float) model.getParkingCircle()).getBounds2D(); square.setFrame( square.getX() - (double) (20F * scale), square.getY() - (double) (20F * scale), square.getWidth() + (double) (40F * scale), square.getHeight() + (double) (40F * scale)); TriggerModel triggerModel = new TriggerModel(); triggerModel.setShouldNotify(false); triggerModel.setType73("YES"); triggerModel.setTypeJet("YES"); triggerModel.setShouldNotify(true); java.awt.geom.Point2D.Float point = new java.awt.geom.Point2D.Float( (float) (square.getX() + square.getWidth() / 2D), (float) (square.getY() + square.getHeight() / 2D)); java.awt.geom.Point2D.Float vertexPoints[] = new java.awt.geom.Point2D.Float[4]; vertexPoints[0] = Utilities.rotatePoint( point, new java.awt.geom.Point2D.Float((float) square.getX(), (float) square.getY()), model.getHeading()); vertexPoints[1] = Utilities.rotatePoint( point, new java.awt.geom.Point2D.Float( (float) square.getX(), (float) (square.getY() + square.getHeight())), model.getHeading()); vertexPoints[2] = Utilities.rotatePoint( point, new java.awt.geom.Point2D.Float( (float) (square.getX() + square.getWidth()), (float) (square.getY() + square.getHeight())), model.getHeading()); vertexPoints[3] = Utilities.rotatePoint( point, new java.awt.geom.Point2D.Float( (float) (square.getX() + square.getWidth()), (float) square.getY()), model.getHeading()); for (int i = 0; i < 4; i++) { VertexModel vertexModel = new VertexModel(); vertexModel.setShouldNotify(false); vertexModel.setLatLon( Utilities.getLatLonForPixel( model.getCenterPoint().getLat(), model.getCenterPoint().getLon(), vertexPoints[i].getX(), vertexPoints[i].getY(), scale)); vertexModel.setShouldNotify(true); triggerModel.addVertexModel(vertexModel); } addTriggerModel(triggerModel); }
public void addStationToParking(TaxiwayParkingModel model) { Rectangle2D square = ((java.awt.geom.Ellipse2D.Float) model.getParkingCircle()).getBounds2D(); SceneryModel sceneryModel = new SceneryModel(); sceneryModel.setShouldNotify(false); sceneryModel.setName("{0da416ee-c523-4d81-a562-9ce503f28468}"); sceneryModel.setHeading(model.getHeading()); java.awt.geom.Point2D.Float point = new java.awt.geom.Point2D.Float( (float) (square.getX() + square.getWidth() / 2D), (float) (square.getY() + square.getHeight() / 2D)); java.awt.geom.Point2D.Float sceneryPoint = Utilities.rotatePoint( point, new java.awt.geom.Point2D.Float( (float) (square.getX() + square.getWidth() / 2D), (float) (square.getY() - 27.5D * (double) scale)), model.getHeading()); sceneryModel.setLatLon( Utilities.getLatLonForPixel( model.getCenterPoint().getLat(), model.getCenterPoint().getLon(), sceneryPoint.getX(), sceneryPoint.getY(), scale)); sceneryModel.setShouldNotify(true); addSceneryModel(sceneryModel); }
private Paint decodeGradient6(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.0f, 0.03f, 0.06f, 0.33f, 0.6f, 0.65f, 0.7f, 0.825f, 0.95f, 0.975f, 1.0f}, new Color[] { color28, decodeColor(color28, color29, 0.5f), color29, decodeColor(color29, color30, 0.5f), color30, decodeColor(color30, color30, 0.5f), color30, decodeColor(color30, color31, 0.5f), color31, decodeColor(color31, color32, 0.5f), color32 }); }
private Paint decodeGradient10(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.0f, 0.024f, 0.06f, 0.276f, 0.6f, 0.65f, 0.7f, 0.856f, 0.96f, 0.98f, 1.0f}, new Color[] { (Color) componentColors[0], decodeColor((Color) componentColors[0], (Color) componentColors[1], 0.5f), (Color) componentColors[1], decodeColor((Color) componentColors[1], (Color) componentColors[2], 0.5f), (Color) componentColors[2], decodeColor((Color) componentColors[2], (Color) componentColors[2], 0.5f), (Color) componentColors[2], decodeColor((Color) componentColors[2], (Color) componentColors[3], 0.5f), (Color) componentColors[3], decodeColor((Color) componentColors[3], (Color) componentColors[3], 0.5f), (Color) componentColors[3] }); }
/** * Draw labels for picking. * * @param dc Current draw context. * @param pickSupport the PickSupport instance to be used. */ protected void doPick(DrawContext dc, PickSupport pickSupport) { GL gl = dc.getGL(); Angle heading = this.rotation; double headingDegrees; if (heading != null) headingDegrees = heading.degrees; else headingDegrees = 0; int x = this.screenPoint.x; int y = this.screenPoint.y; boolean matrixPushed = false; try { if (headingDegrees != 0) { gl.glPushMatrix(); matrixPushed = true; gl.glTranslated(x, y, 0); gl.glRotated(headingDegrees, 0, 0, 1); gl.glTranslated(-x, -y, 0); } for (int i = 0; i < this.lines.length; i++) { Rectangle2D bounds = this.lineBounds[i]; double width = bounds.getWidth(); double height = bounds.getHeight(); x = this.screenPoint.x; if (this.textAlign.equals(AVKey.CENTER)) x = x - (int) (width / 2.0); else if (this.textAlign.equals(AVKey.RIGHT)) x = x - (int) width; y -= this.lineHeight; Color color = dc.getUniquePickColor(); int colorCode = color.getRGB(); PickedObject po = new PickedObject(colorCode, this.getPickedObject(), this.position, false); pickSupport.addPickableObject(po); // Draw line rectangle gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()); try { gl.glBegin(GL.GL_POLYGON); gl.glVertex3d(x, y, 0); gl.glVertex3d(x + width - 1, y, 0); gl.glVertex3d(x + width - 1, y + height - 1, 0); gl.glVertex3d(x, y + height - 1, 0); gl.glVertex3d(x, y, 0); } finally { gl.glEnd(); } y -= this.lineSpacing; } } finally { if (matrixPushed) { gl.glPopMatrix(); } } }
protected void drawText(Graphics2D g2) { // Find the bounds of the entire string. FontRenderContext frc = g2.getFontRenderContext(); mLayout = new TextLayout(mMessage, mFont, frc); // Find the dimensions of this component. int width = getSize().width; int height = getSize().height; // Place the first full string, horizontally centered, // at the bottom of the component. Rectangle2D bounds = mLayout.getBounds(); double x = (width - bounds.getWidth()) / 2; double y = height - bounds.getHeight(); drawString(g2, x, y, 0); // Now draw a second version, anchored to the right side // of the component and rotated by -PI / 2. drawString(g2, width - bounds.getHeight(), y, -Math.PI / 2); }
public void paintComponent(Graphics g) { // необходиом чтобы текст коректно отрисовывался в окне super.paintComponent(g); // рисуем текст в окне Graphics2D g2 = (Graphics2D) g; AffineTransform t = g2.getTransform(); g.drawString("It is text", 5, 5); // создание шрифта Font f = new Font("SanasSerif", Font.ITALIC, 20); g2.setFont(f); g2.drawString("It is new text", 5, 33); String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); for (int i = 5; i < 20; i++) { g2.rotate(-0.05); g2.setColor( new Color( (int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255))); Font f1 = new Font(fontNames[i], Font.BOLD, 20); g2.setFont(f1); g2.drawString(fontNames[i], 5, 20 * i); } // текст в центре g2.setTransform(t); // возращение к кординатам, которые запонилив начале Font f2 = new Font("SanasSerif", Font.ITALIC, 20); g2.setFont(f2); String s = "It is center!"; FontRenderContext context = g2.getFontRenderContext(); Rectangle2D r = f2.getStringBounds(s, context); double x1 = (getWidth() - r.getWidth()) / 2; double y1 = (getHeight() - r.getHeight()) / 2; double ascent = -r.getY(); // узнаем высоту текста double y2 = y1 + ascent; Rectangle2D rect = new Rectangle2D.Double(x1, y1, r.getWidth(), r.getHeight()); g2.setColor(Color.YELLOW); g2.fill(rect); g2.setColor(Color.red); g2.drawString(s, (int) x1, (int) y2); g2.setColor(Color.blue); g2.draw(new Line2D.Double(x1, y2, x1 + r.getWidth(), y2)); g2.draw(rect); }
/** * Constructs a new arc, initialized to the specified location, size, angular extents, and * closure type. * * @param ellipseBounds The framing rectangle that defines the outer boundary of the full * ellipse of which this arc is a partial section. * @param start The starting angle of the arc in degrees. * @param extent The angular extent of the arc in degrees. * @param type The closure type for the arc: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}. * @since 1.2 */ public Double(Rectangle2D ellipseBounds, double start, double extent, int type) { super(type); this.x = ellipseBounds.getX(); this.y = ellipseBounds.getY(); this.width = ellipseBounds.getWidth(); this.height = ellipseBounds.getHeight(); this.start = start; this.extent = extent; }
/** * Constructs a new arc, initialized to the specified location, size, angular extents, and * closure type. * * @param ellipseBounds The framing rectangle that defines the outer boundary of the full * ellipse of which this arc is a partial section. * @param start The starting angle of the arc in degrees. * @param extent The angular extent of the arc in degrees. * @param type The closure type for the arc: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}. * @since 1.2 */ public Float(Rectangle2D ellipseBounds, float start, float extent, int type) { super(type); this.x = (float) ellipseBounds.getX(); this.y = (float) ellipseBounds.getY(); this.width = (float) ellipseBounds.getWidth(); this.height = (float) ellipseBounds.getHeight(); this.start = start; this.extent = extent; }
protected Angle computeIconRadius(DrawContext dc, double regionPixelSize, Sector drawSector) { double minCosLat = Math.min(drawSector.getMinLatitude().cos(), drawSector.getMaxLatitude().cos()); if (minCosLat < 0.001) return Angle.POS180; Rectangle2D iconDimension = this.computeDrawDimension(regionPixelSize); // Meter double dLat = iconDimension.getHeight() / dc.getGlobe().getRadius(); double dLon = iconDimension.getWidth() / dc.getGlobe().getRadius() / minCosLat; return Angle.fromRadians(Math.sqrt(dLat * dLat + dLon * dLon) / 2); }
/** * Gets the page count of this section. * * @param g2 the graphics context * @param pf the page format * @return the number of pages needed */ public int getPageCount(Graphics2D g2, PageFormat pf) { if (message.equals("")) return 0; FontRenderContext context = g2.getFontRenderContext(); Font f = new Font("Serif", Font.PLAIN, 72); Rectangle2D bounds = f.getStringBounds(message, context); scale = pf.getImageableHeight() / bounds.getHeight(); double width = scale * bounds.getWidth(); int pages = (int) Math.ceil(width / pf.getImageableWidth()); return pages; }
public float getPreferredSpan(int axis) { switch (axis) { case View.X_AXIS: return (float) bounds.getWidth(); case View.Y_AXIS: return (float) bounds.getHeight(); default: throw new IllegalArgumentException("Invalid axis: " + axis); } }
public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; String message = "Hello, World!"; Font f = new Font("Serif", Font.BOLD, 36); g2.setFont(f); // measure the size of the message FontRenderContext context = g2.getFontRenderContext(); Rectangle2D bounds = f.getStringBounds(message, context); // set (x,y) = top left corner of text double x = (getWidth() - bounds.getWidth()) / 2; double y = (getHeight() - bounds.getHeight()) / 2; // add ascent to y to reach the baseline double ascent = -bounds.getY(); double baseY = y + ascent; // draw the message g2.drawString(message, (int) x, (int) baseY); g2.setPaint(Color.LIGHT_GRAY); // draw the baseline g2.draw(new Line2D.Double(x, baseY, x + bounds.getWidth(), baseY)); // draw the enclosing rectangle Rectangle2D rect = new Rectangle2D.Double(x, y, bounds.getWidth(), bounds.getHeight()); g2.draw(rect); }
/** * Helper method, which calculates the top-left co-ordinate of a rectangle given the rectangle's * alignment. */ protected static void getAlignedPoint(Point2D p, Rectangle2D r, int xAlign, int yAlign) { double x = r.getX(), y = r.getY(), w = r.getWidth(), h = r.getHeight(); if (xAlign == Constants.CENTER) { x = x + (w / 2); } else if (xAlign == Constants.RIGHT) { x = x + w; } if (yAlign == Constants.CENTER) { y = y + (h / 2); } else if (yAlign == Constants.BOTTOM) { y = y + h; } p.setLocation(x, y); }
private Paint decodeGradient9(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.09f, 0.52f, 0.95f}, new Color[] {color39, decodeColor(color39, color40, 0.5f), color40}); }
private Paint decodeGradient3(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.0f, 0.49573863f, 0.99147725f}, new Color[] {color8, decodeColor(color8, color9, 0.5f), color9}); }
private Paint decodeGradient10(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.24868421f * w) + x, (0.0014705883f * h) + y, (0.24868421f * w) + x, (1.0f * h) + y, new float[] {0.0f, 0.5f, 1.0f}, new Color[] {color48, decodeColor(color48, color49, 0.5f), color49}); }
private Paint decodeGradient2(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.25f * w) + x, (0.0f * h) + y, (0.25441176f * w) + x, (1.0016667f * h) + y, new float[] {0.0f, 0.5f, 1.0f}, new Color[] {color3, decodeColor(color3, color2, 0.5f), color2}); }
private Paint decodeGradient13(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.26047903f, 0.6302395f, 1.0f}, new Color[] {color62, decodeColor(color62, color63, 0.5f), color63}); }
private Paint decodeGradient4(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.0f, 0.1684492f, 1.0f}, new Color[] {color10, decodeColor(color10, color11, 0.5f), color11}); }
private Paint decodeGradient5(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.1f, 0.49999997f, 0.9f}, new Color[] {color7, decodeColor(color7, color8, 0.5f), color8}); }
public void draw( Graphics2D g, Color stringColor, Color foreground, Color background, String info, double x, double y) { FontMetrics fm = g.getFontMetrics(); int h = fm.getHeight(); int w = fm.stringWidth(info); r1.setRect( x - w / 2 - in.left, y - in.top - h / 2, w + in.right + in.left, h + in.bottom + in.top); g.setColor(background); g.fill(r1); g.setColor(stringColor); g.draw(r1); g.setColor(foreground); r2.setRect(r1.getX() + 1, r1.getY() + 1, r1.getWidth() - 2, r1.getHeight() - 2); g.draw(r2); g.setColor(stringColor); g.drawString( info, (float) (r2.getX() + in.left), (float) (r2.getY() + h - (r2.getHeight() - h) / 2)); }
protected List<Sector> computeSectors(DrawContext dc) { if (this.locations == null || !this.locations.iterator().hasNext()) return null; // Compute all locations bounding sector, then add some padding for the icon half diagonal // extent Sector sector = Sector.boundingSector(this.locations); // Compute padding double minCosLat = Math.min(sector.getMinLatitude().cos(), sector.getMaxLatitude().cos()); minCosLat = Math.max(minCosLat, .01); // avoids division by zero at the poles Rectangle2D iconDimension = this.computeDrawDimension(dc, sector.getCentroid()); double diagonalLength = Math.sqrt( iconDimension.getWidth() * iconDimension.getWidth() + iconDimension.getHeight() * iconDimension.getHeight()); double padLatRadians = diagonalLength / 2 / dc.getGlobe().getRadius(); double padLonRadians = diagonalLength / 2 / dc.getGlobe().getRadius() / minCosLat; // Apply padding to sector Angle minLat = sector.getMinLatitude().subtractRadians(padLatRadians); Angle maxLat = sector.getMaxLatitude().addRadians(padLatRadians); Angle minLon = sector.getMinLongitude().subtractRadians(padLonRadians); Angle maxLon = sector.getMaxLongitude().addRadians(padLatRadians); return this.computeNormalizedSectors(new Sector(minLat, maxLat, minLon, maxLon)); }
/** @see prefuse.render.Renderer#setBounds(prefuse.visual.VisualItem) */ @Override public void setBounds(VisualItem item) { if (!m_manageBounds) { return; } Shape shape = getShape(item); if (shape == null) { item.setBounds(item.getX(), item.getY(), 0, 0); } else if (shape == m_line) { GraphicsLib.setBounds(item, shape, getStroke(item)); } else { m_box.add(m_line.getX1(), m_line.getY1()); m_box.add(m_line.getX2(), m_line.getY2()); item.setBounds(m_box.getMinX(), m_box.getMinY(), m_box.getWidth(), m_box.getHeight()); } }
protected float drawBoxedString(Graphics2D g2, String s, Color c1, Color c2, double x) { // Calculate the width of the string. FontRenderContext frc = g2.getFontRenderContext(); TextLayout subLayout = new TextLayout(s, mFont, frc); float advance = subLayout.getAdvance(); // Fill the background rectangle with a gradient. GradientPaint gradient = new GradientPaint((float) x, 0, c1, (float) (x + advance), 0, c2); g2.setPaint(gradient); Rectangle2D bounds = mLayout.getBounds(); Rectangle2D back = new Rectangle2D.Double(x, 0, advance, bounds.getHeight()); g2.fill(back); // Draw the string over the gradient rectangle. g2.setPaint(Color.white); g2.setFont(mFont); g2.drawString(s, (float) x, (float) -bounds.getY()); return advance; }
private Paint decodeGradient4(Shape s) { Rectangle2D bounds = s.getBounds2D(); float x = (float) bounds.getX(); float y = (float) bounds.getY(); float w = (float) bounds.getWidth(); float h = (float) bounds.getHeight(); return decodeGradient( (0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, new float[] {0.1f, 0.49999997f, 0.9f}, new Color[] { (Color) componentColors[0], decodeColor((Color) componentColors[0], (Color) componentColors[1], 0.5f), (Color) componentColors[1] }); }
@Override public Rectangle2D.Double getDrawingArea() { if (cachedDrawingArea == null) { Rectangle2D rx = getBounds(); Rectangle2D.Double r = (rx instanceof Rectangle2D.Double) ? (Rectangle2D.Double) rx : new Rectangle2D.Double(rx.getX(), rx.getY(), rx.getWidth(), rx.getHeight()); double g = SVGAttributeKeys.getPerpendicularHitGrowth(this); Geom.grow(r, g, g); if (TRANSFORM.get(this) == null) { cachedDrawingArea = r; } else { cachedDrawingArea = new Rectangle2D.Double(); cachedDrawingArea.setRect(TRANSFORM.get(this).createTransformedShape(r).getBounds2D()); } } return (Rectangle2D.Double) cachedDrawingArea.clone(); }
/** Gets the drawing area without taking the decorator into account. */ @Override protected Rectangle2D.Double getFigureDrawingArea() { if (getText() == null) { return getBounds(); } else { TextLayout layout = getTextLayout(); Rectangle2D.Double r = new Rectangle2D.Double(origin.x, origin.y, layout.getAdvance(), layout.getAscent()); Rectangle2D lBounds = layout.getBounds(); if (!lBounds.isEmpty() && !Double.isNaN(lBounds.getX())) { r.add( new Rectangle2D.Double( lBounds.getX() + origin.x, (lBounds.getY() + origin.y + layout.getAscent()), lBounds.getWidth(), lBounds.getHeight())); } // grow by two pixels to take antialiasing into account Geom.grow(r, 2d, 2d); return r; } }