Google Tag Manager

Showing posts with label Graphics. Show all posts
Showing posts with label Graphics. Show all posts

2024/05/31

Rounding the corners of a rectilinear polygon generated by node selection in a JTree

Code

public static List<Point2D> flatteningStepsOnRightSide(
    List<Point2D> list, double arc) {
  int sz = list.size();
  for (int i = 0; i < sz; i++) {
    int i1 = (i + 1) % sz;
    int i2 = (i + 2) % sz;
    int i3 = (i + 3) % sz;
    Point2D pt0 = list.get(i);
    Point2D pt1 = list.get(i1);
    Point2D pt2 = list.get(i2);
    Point2D pt3 = list.get(i3);
    double dx1 = pt2.getX() - pt1.getX();
    if (Math.abs(dx1) > 1.0e-1 && Math.abs(dx1) < arc) {
      double max = Math.max(pt0.getX(), pt2.getX());
      replace(list, i, max, pt0.getY());
      replace(list, i1, max, pt1.getY());
      replace(list, i2, max, pt2.getY());
      replace(list, i3, max, pt3.getY());
    }
  }
  return list;
}

private static void replace(List<Point2D> list, int i, double x, double y) {
  list.remove(i);
  list.add(i, new Point2D.Double(x, y));
}

/**
 * Rounding the corners of a Rectilinear Polygon.
 */
public static Path2D convertRoundedPath(List<Point2D> list, double arc) {
  double kappa = 4d * (Math.sqrt(2d) - 1d) / 3d; // = 0.55228...;
  double akv = arc - arc * kappa;
  int sz = list.size();
  Point2D pt0 = list.get(0);
  Path2D path = new Path2D.Double();
  path.moveTo(pt0.getX() + arc, pt0.getY());
  for (int i = 0; i < sz; i++) {
    Point2D prv = list.get((i - 1 + sz) % sz);
    Point2D cur = list.get(i);
    Point2D nxt = list.get((i + 1) % sz);
    double dx0 = signum(cur.getX() - prv.getX(), arc);
    double dy0 = signum(cur.getY() - prv.getY(), arc);
    double dx1 = signum(nxt.getX() - cur.getX(), arc);
    double dy1 = signum(nxt.getY() - cur.getY(), arc);
    path.curveTo(
        cur.getX() - dx0 * akv, cur.getY() - dy0 * akv,
        cur.getX() + dx1 * akv, cur.getY() + dy1 * akv,
        cur.getX() + dx1 * arc, cur.getY() + dy1 * arc);
    path.lineTo(nxt.getX() - dx1 * arc, nxt.getY() - dy1 * arc);
  }
  path.closePath();
  return path;
}

private static double signum(double v, double arc) {
  return Math.abs(v) < arc ? 0d : Math.signum(v);
}

References

2024/04/30

Rounding the corners of a rectilinear polygon generated by a selection of calendar made with JList

Code

public static Path2D convertRoundedPath(List<Point2D> list, double arc) {
  double kappa = 4d * (Math.sqrt(2d) - 1d) / 3d; // = 0.55228...;
  double akv = arc - arc * kappa;
  int sz = list.size();
  Point2D pt0 = list.get(0);
  Path2D path = new Path2D.Double();
  path.moveTo(pt0.getX() + arc, pt0.getY());
  for (int i = 0; i < sz; i++) {
    Point2D prv = list.get((i - 1 + sz) % sz);
    Point2D cur = list.get(i);
    Point2D nxt = list.get((i + 1) % sz);
    double dx0 = Math.signum(cur.getX() - prv.getX());
    double dy0 = Math.signum(cur.getY() - prv.getY());
    double dx1 = Math.signum(nxt.getX() - cur.getX());
    double dy1 = Math.signum(nxt.getY() - cur.getY());
    path.curveTo(
        cur.getX() - dx0 * akv, cur.getY() - dy0 * akv,
        cur.getX() + dx1 * akv, cur.getY() + dy1 * akv,
        cur.getX() + dx1 * arc, cur.getY() + dy1 * arc);
    path.lineTo(nxt.getX() - dx1 * arc, nxt.getY() - dy1 * arc);
  }
  path.closePath();
  return path;
}

References

2019/05/28

Draw a color wheel on JPanel

Code

// Colors: a Color Dialog | Java Graphics
// https://javagraphics.blogspot.com/2007/04/jcolorchooser-making-alternative.html
private BufferedImage updateImage() {
  BufferedImage image = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
  int[] row = new int[SIZE];
  float size = (float) SIZE;
  float radius = size / 2f;
  for (int yidx = 0; yidx < SIZE; yidx++) {
    float y = yidx - radius;
    for (int xidx = 0; xidx < SIZE; xidx++) {
      float x = xidx - radius;
      double theta = Math.atan2(y, x) - 3d * Math.PI / 2d;
      if (theta < 0) {
        theta += 2d * Math.PI;
      }
      double r = Math.hypot(x, y); // Math.sqrt(x * x + y * y);
      float hue = (float) (theta / (2d * Math.PI));
      float sat = Math.min((float) (r / radius), 1f);
      float bri = 1f;
      row[xidx] = Color.HSBtoRGB(hue, sat, bri);
    }
    image.getRaster().setDataElements(0, yidx, SIZE, 1, row);
  }
  return image;
}

// campbell: Java 2D Trickery: Soft Clipping Blog | Oracle Community
// https://community.oracle.com/blogs/campbell/2006/07/19/java-2d-trickery-soft-clipping
GraphicsConfiguration gc = g2.getDeviceConfiguration();
BufferedImage buf = gc.createCompatibleImage(s, s, Transparency.TRANSLUCENT);
Graphics2D g2d = buf.createGraphics();

g2d.setComposite(AlphaComposite.Src);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fill(new Ellipse2D.Float(0f, 0f, s, s));

g2d.setComposite(AlphaComposite.SrcAtop);
g2d.drawImage(colorWheelImage, 0, 0, null);
g2d.dispose();

g2.drawImage(buf, null, (getWidth() - s) / 2, (getHeight() - s) / 2);
g2.dispose();

References

2019/03/27

Perform hover effect animation using RadialGradientPaint on soft clipped JButton

Code

protected void update() {
  if (!getBounds().equals(base)) {
    base = getBounds();
    int w = getWidth();
    int h = getHeight();
    if (w > 0 && h > 0) {
      buf = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    }
    shape = new RoundRectangle2D.Double(
      0, 0, w - 1, h - 1, ARC_WIDTH, ARC_HEIGHT);
  }
  if (buf == null) {
    return;
  }

  Graphics2D g2 = buf.createGraphics();
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                      RenderingHints.VALUE_ANTIALIAS_ON);
  Color c1 = new Color(0x00_F7_23_59, true);
  Color c2 = new Color(0x64_44_05_F7, true);

  g2.setComposite(AlphaComposite.Clear);
  g2.fillRect(0, 0, getWidth(), getHeight());

  g2.setComposite(AlphaComposite.Src);
  g2.setPaint(new Color(getModel().isArmed() ? 0xFF_AA_AA : 0xF7_23_59));
  g2.fill(shape);

  if (radius > 0) {
    int cx = pt.x - radius;
    int cy = pt.y - radius;
    int r2 = radius + radius;
    float[] dist = { 0f, 1f };
    Color[] colors = { c2, c1 };
    g2.setPaint(new RadialGradientPaint(pt, r2, dist, colors));
    g2.setComposite(AlphaComposite.SrcAtop);
    // g2.setClip(shape);
    g2.fill(new Ellipse2D.Double(cx, cy, r2, r2));
  }
  g2.dispose();
}

References

2008/11/05

Rounded Corner JButton

Code

class RoundedCornerButton extends JButton {
  private static final float ARC_WIDTH = 16f;
  private static final float ARC_HEIGHT = 16f;
  protected static final int FOCUS_STROKE = 2;
  protected final Color fc = new Color(100, 150, 255, 200);
  protected final Color ac = new Color(230, 230, 230);
  protected final Color rc = Color.ORANGE;
  protected Shape shape;
  protected Shape border;
  protected Shape base;
  public RoundedCornerButton() {
    super();
  }

  public RoundedCornerButton(Icon icon) {
    super(icon);
  }

  public RoundedCornerButton(String text) {
    super(text);
  }

  public RoundedCornerButton(Action a) {
    super(a);
    // setAction(a);
  }

  public RoundedCornerButton(String text, Icon icon) {
    super(text, icon);
    // setModel(new DefaultButtonModel());
    // init(text, icon);
    // setContentAreaFilled(false);
    // setBackground(new Color(250, 250, 250));
    // initShape();
  }

  @Override public void updateUI() {
    super.updateUI();
    setContentAreaFilled(false);
    setFocusPainted(false);
    setBackground(new Color(250, 250, 250));
    initShape();
  }

  protected void initShape() {
    if (!getBounds().equals(base)) {
      base = getBounds();
      shape = new RoundRectangle2D.Float(
          0, 0, getWidth() - 1, getHeight() - 1, ARC_WIDTH, ARC_HEIGHT);
      border = new RoundRectangle2D.Float(
          FOCUS_STROKE, FOCUS_STROKE, getWidth() - 1 - FOCUS_STROKE * 2,
          getHeight() - 1 - FOCUS_STROKE * 2, ARC_WIDTH, ARC_HEIGHT);
    }
  }

  private void paintFocusAndRollover(Graphics2D g2, Color color) {
    g2.setPaint(new GradientPaint(
        0, 0, color, getWidth() - 1, getHeight() - 1,
        color.brighter(), true));
    g2.fill(shape);
    g2.setColor(getBackground());
    g2.fill(border);
  }

  @Override protected void paintComponent(Graphics g) {
    initShape();
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    if (getModel().isArmed()) {
      g2.setColor(ac);
      g2.fill(shape);
    } else if (isRolloverEnabled() && getModel().isRollover()) {
      paintFocusAndRollover(g2, rc);
    } else if (hasFocus()) {
      paintFocusAndRollover(g2, fc);
    } else {
      g2.setColor(getBackground());
      g2.fill(shape);
    }
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_OFF);
    g2.setColor(getBackground());
    super.paintComponent(g2);
    g2.dispose();
  }

  @Override protected void paintBorder(Graphics g) {
    initShape();
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getForeground());
    g2.draw(shape);
    g2.dispose();
  }

  @Override public boolean contains(int x, int y) {
    initShape();
    return shape == null ? false : shape.contains(x, y);
  }
}

References