11
\$\begingroup\$

Draw something that looks like this:

enter image description here

In more precise terms, draw a circle of radius r, with n evenly-spaces tangent lines of length l. Connect the ends of these lines to form a new n-sided regular polygon.

Rules

r = circle radius
n = number of tangent lines - must be evenly spaced around circle (n>=3)
l = side length of tangent lines

Create a program that accepts the arguments { r, n, l } and draws the required output.

Units are in pixels.

There is no restrictions to the location of the drawing, as long as all of it is visible.

The picture is pretty self-explanatory.

This is code-golf, so shortest code in bytes wins!

\$\endgroup\$
4
  • \$\begingroup\$ I assume n will be >= 3, is there a maximum? Do you want the tangents and circle as well? \$\endgroup\$
    – MickyT
    Oct 1, 2014 at 2:38
  • \$\begingroup\$ Yes, n>=3, (intersection in ok if l is not long enough). You should draw the circle and tangents. I think the maximum is basically when the output is a shaded circle. In other words, the maximum is the realistic maximum for a drawing like this. \$\endgroup\$ Oct 1, 2014 at 2:43
  • \$\begingroup\$ Do the pixel units even apply if we produce a vector graphic? Because in such a case pixels are actually quite ill-defined. Or do we have to produce rasterised graphics? \$\endgroup\$ Oct 1, 2014 at 9:20
  • \$\begingroup\$ @MartinBüttner, you may ignore the pixel unit with your (fancy) vector graphics if there is some sort of scale (like an axis). \$\endgroup\$ Oct 1, 2014 at 11:13

5 Answers 5

8
\$\begingroup\$

Python, 133 bytes

The only answer so far to comply with the "Units are in pixels" rule...

from turtle import*
c=circle
r,n,l=input()
lt(90)
exec'c(r,360/n);fd(l);bk(l);'*n
fd(l)
lt(towards(-r,0)-180)
c(distance(-r,0),360,n)

Add exitonclick() to the end if you don't want the window to close immediately.

Output:

python tangentpoly.py <<< "20, 6, 30":

enter image description here

python tangentpoly.py <<< "100, 8, 200":

enter image description here

\$\endgroup\$
2
  • 1
    \$\begingroup\$ for i in n*[0]:c(r,360/n);fd(l);bk(l) -> exec'c(r,360/n);fd(l);bk(l)'*n; \$\endgroup\$
    – isaacg
    Oct 1, 2014 at 12:20
  • 1
    \$\begingroup\$ Try it online \$\endgroup\$
    – mbomb007
    Sep 16, 2016 at 20:29
7
\$\begingroup\$

T-SQL 440 483

Not going to win any prizes with this one, but I like drawing pictures :)

Edit Expletive! Just noticed I messed up for polygons drawn across the circle. Fixed at a cost.

SELECT Geometry::UnionAggregate(Geometry::Point(0,0,0).STBuffer(@r).STExteriorRing().STUnion(Geometry::STGeomFromText(CONCAT('LINESTRING(',@r*SIN(a),' ',@r*COS(a),',',@r*SIN(a)+@l*SIN(b),' ',@r*COS(a)+@l*COS(b),')'),0))).STUnion(Geometry::ConvexHullAggregate(Geometry::Point(@r*SIN(a)+@l*SIN(b),@r*COS(a)+@l*COS(b),0)).STExteriorRing())p FROM(SELECT RADIANS(360./@*N)a,RADIANS((360./@*N)-90)b FROM(SELECT TOP(@)row_number()OVER(ORDER BY(SELECT\))-1N FROM sys.types a,sys.types b)t)r

Executed with the following variables

declare @r float = 1.0
declare @ int = 10
declare @l float = 3.0

Run in Sql Server Management Studio 2012+ it will return the following in the spatial results tab. enter image description here

With

declare @r float = 1.0
declare @ int = 360
declare @l float = 3.0

enter image description here

with

declare @r float = 10.0
declare @ int = 3
declare @l float = 10.0

enter image description here

Expanded out

SELECT Geometry::UnionAggregate(    --group together lines
    Geometry::Point(0,0,0)          --Set origin
    .STBuffer(@r)                   --Buffer to @r
    .STExteriorRing()               --Make it a line
    .STUnion(                       --Join to the floowing tangent
        Geometry::STGeomFromText(   --Create a tangent line
            CONCAT('LINESTRING(',@r*SIN(a),' ',@r*COS(a),',',@r*SIN(a)+@l*SIN(b),' ',@r*COS(a)+@l*COS(b),')'),0)
        )
    ).STUnion( --Generate polygon around exterior points
    Geometry::ConvexHullAggregate(Geometry::Point(@r*SIN(a)+@l*SIN(b),@r*COS(a)+@l*COS(b),0)).STExteriorRing()
    )
    p
FROM(
    SELECT RADIANS(360./@*N)a,      --calclate bearings
        RADIANS((360./@*N)-90)b
    FROM(                           --make enough rows to draw tangents
        SELECT TOP(@)row_number()OVER(ORDER BY(SELECT\))-1N 
        FROM sys.types a,sys.types b
        )t
    )r 
\$\endgroup\$
5
\$\begingroup\$

Mathematica, 135 132 131 123 bytes

{r,n,l}=Input[];Graphics[{{0,0}~Circle~r,Line[Join@@Array[{b=(a=r{c=Cos[t=2Pi#/n],s=Sin@t})-l{s,-c},a,b}&,n+1]]},Axes->1>0]

This code expects the input (via a prompt) exactly as specified in the question: e.g. {100, 6, 150}. It produces a vector graphic, so I'm including an axis, as specified in the comments by the OP.

Both the tangents and the polygon are actually a single line strip, by traversing "polygon-corner, tangent point, polygon-corner, next polygon-corner, tangent point, polygon-corner..."

enter image description here

If it wasn't for the axis, I could even do this in 107 bytes:

{r,n,l}=Input[];Graphics@{Circle[],Line[Join@@Array[{b=(a={c=Cos[t=2Pi#/n],s=Sin@t})-l/r{s,-c},a,b}&,n+1]]}

Additional savings (apart from Axes->1>0) come from the fact that I can now rescale everything by r, which simplifies the call to Circle yielding a unit circle.

\$\endgroup\$
2
  • \$\begingroup\$ {0,0}~Circle~r \$\endgroup\$
    – DavidC
    Oct 1, 2014 at 16:59
  • \$\begingroup\$ @DavidCarraher heh, I had actually already done that in the 135 bytes, but forgot to copy it back into my notebook, so it got reverted when I made the Unicode change. thanks! \$\endgroup\$ Oct 1, 2014 at 17:00
5
\$\begingroup\$

MATLAB - 233 bytes

function C(n,r,l),t=2*pi/n;c=cos(t);s=sin(t);M=[c,s;-s,c];F=@(y)cell2mat(arrayfun(@(x){M^x*y},1:n));P=F([0;r]);Q=F([l;r]);v='k';t=1e3;t=2*pi/t*(0:t);R=[1:n 1];q=Q(1,R);s=Q(2,R);plot(r*cos(t),r*sin(t),v,[P(1,R);q],[P(2,R);s],v,q,s,v);

Sample function output for n = 8, r = 4, l = 6 (axes included to indicate unit length): circpoly output

Sample function output for n = 1024, r = 4, l = 2: circpoly output

\$\endgroup\$
4
  • \$\begingroup\$ I'm nit-picking, but Units are in pixels \$\endgroup\$ Oct 1, 2014 at 4:37
  • 3
    \$\begingroup\$ @DigitalTrauma: Ah. Didn't notice that. MATLAB figures don't have fixed units; they scale to the window. And it's a moot point anyway. Your LOGO based solution in Python has mine soundly beat. Before today I wouldn't have conceived somebody would port LOGO into Python, but there it is. I'm learning as I go along. :P \$\endgroup\$
    – COTO
    Oct 1, 2014 at 4:53
  • \$\begingroup\$ Well +1 anyway :) \$\endgroup\$ Oct 1, 2014 at 5:01
  • \$\begingroup\$ The image is almost aperture's logo. \$\endgroup\$ Oct 1, 2014 at 5:27
4
\$\begingroup\$

HTML + JavaScript (E6) 298

To test, save as an html file and open with FireFox. Insert the parameters r,n,l into the input field, comma separated, then tab out.

Or try jsfiddle

<input onblur="
[r,n,l]=this.value.split(','),
z=r-~l,t=D.getContext('2d'),w='lineTo',
D.width=D.height=z*2,
t.arc(z,z,r,0,7);
for(C=1,S=i=0;i++<n;)
  t[w](x=z+r*C,y=z+r*S),
  t[w](x-l*S,y+l*C),
  C=Math.cos(a=6.283*i/n),
  S=Math.sin(a),
  t[w](z+r*C-l*S,z+r*S+l*C);
t.stroke()">
<canvas id=D>

Sample output

50,20,140

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.