Розширення дотичних полігонів


11

Намалюйте щось, що виглядає приблизно так:

введіть тут опис зображення

Точніше, намалюйте коло радіуса r з n рівномірно проміжками дотичних ліній довжиною l. З’єднайте кінці цих ліній, щоб утворити новий n-однобічний регулярний багатокутник.

Правила

r = радіус кола
n = кількість дотичних ліній - повинні бути рівномірно розташовані навколо кола (n> = 3)
l = довжина сторони дотичних ліній

Створіть програму, яка приймає аргументи {r, n, l} і малює необхідний вихід.

Одиниці є в пікселях.

Немає обмежень щодо розташування креслення, якщо все це видно.

Малюнок досить зрозумілий.

Це код-гольф, тому найкоротший код у байтах виграє!


Я припускаю, що n буде> = 3, чи є максимум? Ви також хочете дотичних і кола?
MickyT

Так, n> = 3, (перетин у порядку, якщо l недостатньо довгий). Вам слід намалювати коло і дотичні. Я думаю, що максимум в основному, коли на виході є затінене коло. Іншими словами, максимум - це реалістичний максимум для такого малюнка.
Стретч-маніяк

Чи застосовуються піксельні одиниці, навіть якщо ми створюємо векторну графіку? Тому що в такому випадку пікселі насправді досить чітко визначені. Або нам доводиться виробляти растеризовану графіку?
Мартін Ендер

@ MartinBüttner, ви можете ігнорувати піксельну одиницю зі своєю (фантазійною) векторною графікою, якщо є якась шкала (наприклад, вісь).
Стретч-маніяк

Відповіді:


5

Математика, 135 132 131 123 байт

{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]

Цей код очікує введення (через підказку) точно так, як зазначено у запитанні: напр {100, 6, 150}. Він створює векторну графіку, тому я включаю вісь, як зазначено в коментарях ОП.

І дотичні, і багатокутник - це фактично смуга однієї лінії, проїжджаючи "полігон-кут, дотична точка, полігон-кут, наступний багатокутник-кут, дотична точка, полігон-кут ..."

введіть тут опис зображення

Якби не вісь, я б навіть це зробив у 107 байтах:

{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]]}

Додаткові заощадження (крім Axes->1>0) випливають з того, що я тепер можу змінити масштаб все r, що спрощує виклик, щоб Circleотримати одиничне коло.


{0,0}~Circle~r
DavidC

@DavidCarraher, так, я вже зробив це в 135 байтах, але забув скопіювати його в свій ноутбук, тому він повернувся, коли я змінив Unicode. Дякую!
Мартін Ендер

8

Пітон, 133 байти

Єдина відповідь поки що відповідати правилу "Одиниці в пікселях" ...

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)

Додайте exitonclick()до кінця, якщо ви не хочете, щоб вікно негайно закрилося.

Вихід:

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

введіть тут опис зображення

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

введіть тут опис зображення


1
for i in n*[0]:c(r,360/n);fd(l);bk(l)->exec'c(r,360/n);fd(l);bk(l)'*n;
isaacg


7

T-SQL 440 483

З цим не збираюся вигравати жодних призів, але мені подобається малювати картини :)

Редагувати Expletive! Щойно помітив, я заплутався для багатокутників, намальованих по колу. Виправлено за вартістю.

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

Виконується із наступними змінними

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

Запустивши в Sql Server Management Studio 2012+, він поверне наступне на вкладці просторових результатів. введіть тут опис зображення

З

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

введіть тут опис зображення

з

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

введіть тут опис зображення

Розширений

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 

5

MATLAB - 233 байт

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);

Вибір зразкової функції для n = 8, r = 4, l = 6(осі включені для позначення одиниці довжини): циркулярний вихід

Вибір вибір функції для n = 1024, r = 4, l = 2: циркулярний вихід


Я збираю ніт, але одиниці знаходяться в пікселях
Digital Trauma

3
@DigitalTrauma: Ага. Не помічав цього. Фігури MATLAB не мають фіксованих одиниць; вони масштабуються до вікна. І це все-таки суперечка. Ваше рішення, засноване на LOGO в Python, моє міцно перемогло. До сьогодні я б не здогадувався, що хтось переведе LOGO в Python, але це так. Я навчаюсь, коли йду разом. : P
COTO

Ну +1 все одно :)
Цифрова травма

Зображення - це майже логотип діафрагми.
гордий haskeller

4

HTML + JavaScript (E6) 298

Для перевірки збережіть як файл html та відкрийте за допомогою FireFox. Вставте параметри r, n, l у поле введення, розділені комами, а потім вкладіть.

Або спробуйте 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>

Вибірка зразка

50,20140

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.