Drawing X inside a circle, can't seem to figure it out

image

Trying to draw an X inside a red circle, and it has several issues.

  1. Why is my translation transform incorrect?
  2. Why is it not being rotated?
  3. Why is there an opacity?

image

void paint(Graphics& g) override
{
	{// background
		g.setColour(Colours::black);
		g.fillRect(getLocalBounds());
	}

	{// cirlcle
		int size = 25;
		redCircle_area = { 0, 0, size, size };
		g.setColour({ 206, 84, 89 });
		g.fillEllipse(redCircle_area.toFloat());
	}

	{ // X
		int size = 14;

		Path p;

		p.addLineSegment({ 0.f, 7.f, (float)size, 7.f }, 1.5f);
		p.addLineSegment({ 7.f, 0.f, 7.f, (float)size }, 1.5f);

		AffineTransform transform;
		transform = transform.rotated(degreesToRadians(45), size / 2, size / 2);
		transform = transform.translated(juce::Point<int>{25/2, 25/2});
		p.applyTransform(transform);

		g.setColour({ 255, 255, 255 });
		g.fillPath(p);
	}
}

ok, figured out the opacity problem, it’s due to antialiasing

Use floating point positions and angles.

I think transform is not getting applied to line segments. Seems like a mistake in JUCE code, not my user error.

size is an int in your code and 45 is an int right?

Point<int> etc.

1 Like

Yes. 25/2 == 12, not 12.5 as it looks like you’re expecting. Same deal with the degreesToRadians function - if you give it an integer argument it’ll return an integer result, which for 45 degrees will be 0.

Here’s code for drawing a plus properly, then you use rotation to get an X.

static Path plus(juce::Rectangle<float> bounds, float thickness)
	{
		float x = bounds.getX();
		float y = bounds.getY();
		float w = bounds.getWidth();
		float h = bounds.getHeight();
		float wHalf = bounds.getWidth() / 2.f;
		float hHalf = bounds.getHeight() / 2.f;
		float tHalf = thickness / 2.f;

		vector<juce::Point<float>> plus_points
		{
			{x + wHalf - tHalf, y},
			{x + wHalf + tHalf, y},

			{x + wHalf + tHalf, y + hHalf - tHalf},

			{x + w, y + hHalf - tHalf},
			{x + w, y + hHalf + tHalf},

			{x + wHalf + tHalf, y + hHalf + tHalf},

			{x + wHalf + tHalf, y + h},
			{x + wHalf - tHalf, y + h},

			{x + wHalf - tHalf, y + hHalf + tHalf},

			{x, y + hHalf + tHalf},
			{x, y + hHalf - tHalf},

			{x + wHalf - tHalf, y + hHalf - tHalf}
		};

		Path p;

		p.startNewSubPath(plus_points[0]);

		for (size_t i = 1; i < plus_points.size(); ++i)
			p.lineTo(plus_points[i]);

		p.closeSubPath();

		return p;
	}

If anyone might suggest improvements to the code let me know, I’d like to learn better how to do more drawing in code and rely less on png and vector.

Basically you need to use float types not int in your calculations.

Dividing integers gives you truncation (rounding basically). This is why your center is not correct because it is rounding to a whole number.

To get the X in the center it will almost always be a decimal to place it sub pixel wise.

You can cut that function down by a lot:

Path plus(Rectangle<float> b, float thickness)
{
    Path p;
    p.addRectangle(b.reduced((b.getWidth() - thickness) / 2.f, 0.f));
    p.addRectangle(b.reduced(0.f, (b.getHeight() - thickness) / 2.f));
    return p;
}
2 Likes

Tony, no, it will have antialiasing issues. See first post. Or if not that, then you will have issues using opacity in general.

The opacity has nothing to do with the path, unless you’re drawing each rectangle individually (which is where you’ll get the overlap in the center of the cross)

As for anti-aliasing I’m not sure what you mean, it shouldn’t have anything to do with whether the path is constructed via lines or rectangles. Here’s an example that uses a white (with 50% alpha) rotated plus over a red circle:

15%20PM

2 Likes

ok makes sense