Mathematica, 193 183 177 173 169 166 bytes
Yay, maths! I'm plotting the region that satisfies a certain (rather complicated) set of inequalities:
e=RegionPlot[(1<Abs@y<3||c)&&{x,y+12}.(d=2{-5Sin@40°-6,m=5Cos@40°})*{x+15,y+1-2Sign@y}.d<0||c&&x<2m/.c->100<x^2+y^2<144,{x,-15,9},{y,-12,12},Frame->0>1,ImageSize->#]&
Usage is e[height]
, e.g. e[100]
:
Or e[200]
:
You may notice, that the sharper edges are slightly rounded off. That's because the region can only be plotted by sampling the points in space, and Mathematica doesn't sample each pixel by default. The sampling resolution can be increased by adding another option PlotPoints->#
(which uses one sample per pixel), which adds 14 characters. I don't recommend running it with that option, because it significantly increases runtime and barely increases visual appeal beyond #/4
or so. Hence, (after approval of the OP) it is not included in the score.
Here is a slightly ungolfed version:
e[height_] := (
angle = 40°;
d = {-5 Sin[angle] - 6, 5 Cos[angle]};
RegionPlot[
(Abs[y] > .5 && Abs[y] < 1.5
||
r > 25 && r < 36)
&&
{x, y + 6}.d > 0
&&
{x + 7.5, y + .5 - Sign[y]}.d < 0
||
r > 25 && r < 36 && x < 5 Cos[angle]
/. r -> x^2 + y^2
,
{x, -7.5, 4.5},
{y, -6, 6},
Frame -> False,
ImageSize -> height
]
);
Note that in the golfed version, I've scaled the coordinate system by a factor of 2 to avoid the .5
s, but it turns out that the character count is actually identical.
Here is an explanation for how I worked out the formula. I divided the shape into two regions. One contains the ring and the stripes and is cut off to the right with the BCDE
slope and to the left with the IJ
and GH
slopes (more on that later). The other contains the same ring, but is simply cut off at the x coordinate of point D
. The conditions for the two regions are combined with ||
, which acts as a set union here.
The ring is just defined as 5 < r < 6
, where r
is the distance from the origin. r²
is easier to work out though (x²+y²
), so I'm using 25 < x² + y² < 36
to get all the points in the ring.
The stripes are between ±.5
and ±1.5
. We can handle both stripes at the same time, by taking the modulus of y, so the stripes (of infinite length) just fulfil .5 < |y| < 1.5
. Again, to take the union of the stripes and the ring, I'm just using ||
.
The interesting thing is probably how to get the "masks" though. Point D
has an x coordinate of 5 cos 40°
, so the mask taking care of lower edge (combined with the ring only) is just x < 5 cos 40°
. This can be applied via set intersection which translates to &&
in logic.
The other masks are the really tricky part. First, let's get the slope of BCDE
. We can easily construct points C
and D
, as (0, -6)
and 5 (cos 40°, sin 40°)
, respectively. The vector pointing along the line is then just D - C = (5 cos 40°, 5 sin 40° + 6)
. To apply the mask on the right, I only need to figure out if a point lies to the left or the right of that line (let's call line vector p
). I can figure this out by taking the vector from C
to my point of interest and projecting it onto a vector perpendicular to p
. The sign of the projection will tell me the side the point is on. Obtaining the perpendicular vector is pretty simple in 2D: flip the coordinates and reverse the sign of one of them. That's the variable d
in my code: (-5 sin 40° - 6, 5 cos 40°)
. The vector from C
to a point of interest q = (x, y)
is q - C = (x, y + 6)
. The projection is just the scalar product (or dot product) between q
and d
. The way I chose d
it happens to point to the left, so I want d.(q-C) > 0
. This condition applies the right-hand mask.
For the left-hand mask I can use basically the same idea. The slope is the same and therefore so is d
. I just need offset my point from the lower-left corners of stripes instead of from C
. Those have coordinates (-7.5, 0.5)
(upper stripe) and (-7.5, -1.5)
(lower stripe). So that would call for two independent rules for the two stripes. However, note that all points affected by the lower mask are in the lower stripe and hence have negative y. And all points affected by the upper mask have positive y. So I can simply switch my offset using Sign[y]
which is 1
for positive and -1
for negative y
. So my offset point becomes (-7.5, -0.5 + Sign[y])
. Otherwise the mask works just like the right-hand mask. Of course, this time the projection needs to be negative. So, naively that would be something like RH-projection > 0 && LH-projection < 0
(which is also what I originally had in the code). But we can shorten this, because multiplying a positive and a negative number has to give a negative number, so it's just RH * LH < 0
(where RH
and LH
are the respective projections).
That's it. Putting it all together leads to the following logical structure:
(
(is_in_circle || is_in_stripe)
&&
is_between_left_and_right_mask
)
||
(
is_in_circle && left_of_edge
)
Just to be clear, the coordinates in my explanation refer to the construction diagram given in the challenge. As mentioned above my code actually multiplies all of them by 2
- I changed it to save bytes, but the byte count is actually identical, and I couldn't be bothered to revert the change again. Also integers look nicer.
7Tricky ! It's time to review my geometry/trigonometry. I see some coordinates quite difficult to deduce. – Michael M. – 2014-05-06T17:01:22.830
5I had to look up "facultative" – Digital Trauma – 2014-05-06T23:08:39.600
Oops, I used a French word by mistake. Thanks for pointing it. – A.L – 2014-05-07T00:39:54.113
2I'm really hoping for a LaTeX + TikZ answer :) – Cole Johnson – 2014-05-07T00:57:15.983
12Without the Euro, this problem wouldn't exist, thereby once again demonstrating the truth of "Mo money mo problems" – Thomas Johnson – 2014-05-08T19:07:30.837
Guys there is a huge issue with this question.... The question should specify whether or not the result is typographically usable - or whether the result is just a raster (or other) approximation The two things are of course entirely different. Note that the mathematica answer (while incredibly awesomely clever), is totally unusable. (The result image printed on the screen is, well ... totally wrong! - ask any typographer. There's no point saying "oh maybe if you increase the pixel" .. etc.) At the other extreme the P.S code is (of course) 100% usable typographically. – None – 2014-05-10T15:58:30.457
1I don't know what is typographically usable and I'm not a typographer. If you want a perfect € sign, just use the € character. But that's not the goal of this question. I didn't expect pixel perfect images. Feel free to add another question with different rules if you don't like this one. – A.L – 2014-05-10T16:07:16.120