1

I'm trying to draw a triangle with a border using the Graphics.drawPolygon() method

The triangle is properly drawn, but how can I calculate the 3 points of the border?

I already did it with a circle, but I can't seem to find a solution for triangle.

A requirement of the instructor as that it cannot use Graphics2D.

My code:

if (xPoints != null && yPoints != null) {
    int[] nXPoints = new int[] { xPoints[0] - borderThickness, xPoints[1] - borderThickness,
            xPoints[2] - borderThickness };
    int[] nYPoints = new int[] { yPoints[0] - borderThickness, yPoints[1] - borderThickness,
            yPoints[2] - borderThickness };

    g.setColor(borderColor);
    g.fillPolygon(nXPoints, nYPoints, 3);

    g.setColor(fillColor);
    g.fillPolygon(xPoints, yPoints, 3);
}

Edit: Expected result

Expected result

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Jahir Fiquitiva
  • 1,459
  • 3
  • 23
  • 47
  • I'm confused. How can you possibly draw the triangle without these points? – Joe C Oct 01 '16 at 21:45
  • `how can I calculate the 3 points of the border?` - . The draw/fill methods work on the same set of points. – camickr Oct 01 '16 at 21:49
  • @JoeC .. I know is not possible to draw it without the points. I'm looking for a way to calculate the points of the border. – Jahir Fiquitiva Oct 01 '16 at 22:50
  • @camickr No, they don't, check the code again. – Jahir Fiquitiva Oct 01 '16 at 22:51
  • @camickr is correct; the signatures are compatible; but you need to use the correct methods, as shown [below](http://stackoverflow.com/a/39812618/230513). – trashgod Oct 02 '16 at 00:03
  • @trashgod I can't use the same points, because I need the border to have custom thickness – Jahir Fiquitiva Oct 02 '16 at 00:25
  • ***"Better if it doesn't needs the use of Graphics2D."*** ..Why? "How to draw a triangle with border with Java Graphics" Show an image of the intended result. – Andrew Thompson Oct 02 '16 at 04:26
  • 2
    My interpretation of this question is that you want to compute some sort of "offset". From the original points, you want to compute 3 new points that describe a triangle that is "larger" than the original one (larger by the `borderThickness`), so that when you paint them one over the other, it *looks like* a triangle with a border. **If** this is right: Don't do this. It would be fiddly to get this right, and even if you get it working, it's a crude hack. Swing (and particularly `Graphics2D`) offers **so** many nice and easy ways to achieve cool effects. Use them. – Marco13 Oct 02 '16 at 04:27
  • @AndrewThompson Updated the post with a picture of expected result. @Marco13 you're right, that's basically what I want. I'm sure it will be a bad hack, but the things is teacher haven't taught me `Graphics2D` so I'm not supposed to use it. – Jahir Fiquitiva Oct 02 '16 at 15:26
  • OK.. so how does the code calculate the x/y positions of the points for the initial triangle? For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). Leave out the code for the circle that is already working - it is irrelevant. – Andrew Thompson Oct 02 '16 at 15:33

1 Answers1

1

Use the Graphics methods drawPolygon() to render the outline and fillPolygon() to fill its interior; both have the required signature, as shown here.

image1

Because "operations that draw the outline of a figure operate by traversing an infinitely thin path between pixels with a pixel-sized pen," cast the graphics context to Graphics2D so that you can use draw() and fill() on the corresponding Shape. This will allow you to specify the outline using setStroke(), illustrated here.

image2

I need it to have a custom thickness…I also don't want to use Graphics2D.

Custom thickness is not supported in the Graphics API. As suggested here, the actual graphics context received by paintComponent() is an instance of Graphics2D, which does support custom stroke geometry.

The things is teacher haven't taught me Graphics2D, so I'm not supposed to use it.

Then simply paint the larger triangle and then the smaller. If this isn't working, then you have an error in you calculation of the larger triangle, and you should edit your question to include a complete example.

I'm looking for a way to do it without Graphics2D…a guy has interpreted the question properly in this comment.

As @Marco13 observes, you need a triangle that is larger than the original one by the borderThickness. You can use AffineTransform to do the scaling. While Graphics can't fill() an arbitrary Shape, such as one created by AffineTransform, it can clip the rendering as required. In the example below, a unit triangle is translated and scaled to the center of an N x N panel; a copy is enlarged by delta. Note how rendering is clipped first to the larger background figure and then to the smaller foreground figure.

GraphicsBorder

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * @see https://stackoverflow.com/a/39812618/230513
 */
public class GraphicsBorder {

    private static class GraphicsPanel extends JPanel {

        private static final int N = 256;
        private static final Color FILL = new Color(0x990099);
        private static final Color BORDER = new Color(0x66FFB2);
        private final Shape fore;
        private final Shape back;

        public GraphicsPanel(Polygon polygon, int delta) {
            AffineTransform a1 = new AffineTransform();
            a1.translate(N / 2, N / 2);
            a1.scale(N / 3, N / 3);
            fore = a1.createTransformedShape(polygon);
            AffineTransform a2 = new AffineTransform();
            a2.translate(N / 2, N / 2 - delta / 3);
            a2.scale(N / 3 + delta, N / 3 + delta);
            back = a2.createTransformedShape(polygon);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(BORDER);
            g.setClip(back);
            g.fillRect(0, 0, N, N);
            g.setColor(FILL);
            g.setClip(fore);
            g.fillRect(0, 0, N, N);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(N, N);
        }
    }

    private void display() {
        JFrame f = new JFrame("GraphicsBorder");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Polygon p = new Polygon();
        p.addPoint(0, -1);
        p.addPoint(1, 1);
        p.addPoint(-1, 1);
        f.add(new GraphicsPanel(p, 16));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new GraphicsBorder()::display);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thanks for the help, but I can use the same points for the border, because I need it to have a custom thickness – Jahir Fiquitiva Oct 02 '16 at 00:26
  • These two requirements conflict; I've elaborated above. – trashgod Oct 02 '16 at 06:43
  • thanks for the help, but I'm looking for a way to do it without `Graphics2D`... I know `Graphics` doesn't support stroke, but there should be a way to do it. A guy has interpreted the question properly in [this comment](https://stackoverflow.com/questions/39811618/how-to-draw-a-triangle-with-border-with-java-graphics#comment66918514_39811618) – Jahir Fiquitiva Oct 02 '16 at 15:30
  • @JahirFiquitiva: I've added an example above. – trashgod Oct 10 '19 at 05:20