Kafelek płaszczyzny z tym zmodyfikowanym okręgiem

22

Weź koło jednostki wyśrodkowane na początku. W dowolnych dwóch sąsiednich kwadrantach odbij krzywą okręgu wzdłuż linii łączących przecięcia xiy koła.

Dzięki uzyskanemu kształtowi możesz kafelkować płaszczyznę:

teselacja koła

Zrobiłem ten obraz z niesamowitą piaskownicą fizyki 2D Algodoo !

Napisz program, który wyświetla obraz podobny do tego w popularnym formacie plików bezstratnych. Możesz zapisać obraz jako plik o wybranej nazwie lub możesz go po prostu wyświetlić. Nie należy pobierać żadnych danych wejściowych.

Zasady:

  • Cały obraz musi być poddawana tesselacji z płytek zmodyfikowanym koła przez jakiekolwiek dwa optycznie różnych kolorów RGB: jeden z pionowo skierowanymi płytek, jednej na płytki poziomo wskazującego.

  • Promień płytek koła powinien wynosić co najmniej 32 piksele. (Promień na powyższym obrazku wynosi około 110 pikseli.)

  • Obraz powinien mieć co najmniej 4 płytki szerokości i 4 płytki wysokości. W połączeniu z powyższą regułą oznacza to, że obrazy mogą mieć minimalny rozmiar 256 x 256 pikseli. (Zdjęcie powyżej to 4 kafelki na 4 kafelki).

  • Teselacja może być przetłumaczona na dowolną kwotę. Na przykład lewy górny róg obrazu nie musi być wierzchołkiem, w którym stykają się kafelki. (Teselacji nie należy jednak obracać.)

  • Możesz używać zewnętrznych bibliotek graficznych, które mają polecenia do rysowania okręgów i wysyłania obrazów itp.

  • Krzywe naprawdę powinny aproksymować koła, co można zrobić za pomocą algorytmu okręgu punktu środkowego , co zrobi większość bibliotek graficznych.

  • Wygładzanie wokół krawędzi płytek jest dozwolone, ale nie wymagane.

Najkrótsze przesłanie w bajtach wygrywa.

Hobby Calvina
źródło

Odpowiedzi:

4

gs2, 49 bajtów

50 31 05 0d 1f 2a 48 0a 1e 2e 40 83 2c e8 64 2d
1e 73 ed 1e 33 40 20 30 9a a2 22 e8 e9 40 20 30
9a 30 40 20 30 ee 40 20 30 12 32 e9 12 32 55 e8
2b

Generuje obraz PBM:

wydajność

Mnemonika:

# Print header
"P1" space 256 double
2dup new-line

# Make 1/4 circle
64 range dup cartesian-product
square m1 sum sqrt 64 >= m6
64 /

# Make tile
dup reverse + transpose
@2 not m1 m2
dup reverse + transpose
+

# Make quarter of image
dup reverse + z1
dup reverse +

# Loop
2 * m2
2 *

# Format
show-words m1
unlines
Lynn
źródło
36

POV-Ray, 199 163

Old version
camera{location -9*z}light_source{-9*z}#declare L=union{#for(X,-9,9,2)#for(Y,-9,9,2)cylinder{X*x+x+Y*y,<.001*pow(-1,(X+Y)/2),0,.1>+X*x+x+Y*y,1}#end#end}object{L pigment{color x}}object{L rotate z*90}

Same output, but golfed down further by using default light/camera, so I dont even need to specify them
#declare L=union{#for(X,-9,9,2)#for(Y,-9,9,2)cylinder{<X+1,Y,9>,<.001*pow(-1,(X+Y)/2),0,.1>+<X+1,Y,9>,1}#end#end}object{L pigment{color rgb x}rotate z*90}object{L}

wprowadź opis zdjęcia tutaj
Używam jak największej liczby domyślnych parametrów kamery i źródła światła, dlatego jest trochę ciemno. Pozwala najpierw go rozegrać

camera{location 9*z look_at 0}
light_source{9*z color 1} 
#declare L=union{
    #for(X,-9,9,2)
        #for(Y,-9,9,2)
            cylinder{<1+X,Y,0>,                                 //central axis, start
                     <1+X,Y,0> + <.001*pow(-1,(X+Y)/2), 0, .1>, //central axis, end
                      1}                                        //radius
        #end         
    #end
}                         
object{L pigment{color x}} // x is the <1,0,0> vector, here interpreted as RGB
object{L rotate<0,0,90>}

Oczywiste jest, co się stanie, gdy zwiększymy przesunięcie osi cylindra i zmienimy perspektywę

wprowadź opis zdjęcia tutaj

DenDenDo
źródło
1
Czy krawędzie nie będą lekko zniekształcone dzięki perspektywie 3D?
orlp
6
Przy wysokości 0.1i przesunięciu 0.001dysku jest przechylony o $ \ phi = \ arctan (0,01) = 0,57 ° $, patrząc od góry dyski wydają się ściśnięte współczynnikiem $ \ cos (\ phi) = 0,99995 $, to znacznie mniej niż piksel.
DenDenDo
@DenDenDo czy pov-ray nie jest w stanie ustawić kamery w nieskończoności?
Random832
@ Random832 może, z camera{orthographic location -9z}. Ale ponieważ scena jest w zasadzie 2D, nie ma znaczenia, możesz nawet renderować ją podczas oglądania angle 170bez zniekształceń rybiego oka w wyniku.
DenDenDo
11

Gnuplot, 182

Zauważyłem, że granice między komórkami wyglądają bardzo sinusoidalnie, więc wybrałem rozwiązanie analityczne z bardzo prostym równaniem rdzenia
wprowadź opis zdjęcia tutaj

set view map
set isosamples 900
f(x,y)=.3*sin(x*3.14)+y
splot(ceil(f(x,y))+ceil(f(y,x)))%2?1:NaN   #can only modulo integers

wprowadź opis zdjęcia tutaj
Wygląda podobnie, ale koła są zbyt kwadratowe. Z tej samej idei, zastąpić sinprzez krzywą wykonane z łączonych quartercircle łuków elektrycznych i obrócić o 45 ° w zastępując xa yz x+yax-y

set view map
set samples 800
set isosamples 800
d=.5**.5
c(x,k)=(-1)**k*sqrt(1-(x-d*(1+2*k))**2)-(-1)**k*d  # k-th circle arc
# s(x)=c(x,floor(x/d/2))                           # circlified sinus
# f(x,y)=d*s(x/d)+y
f(x,y)=d*c(x/d,floor(x))+y                         # combined commented functions
splot(ceil(f(x+y,x-y))+ceil(f(x-y,x+y)))%2?1:NaN

wprowadź opis zdjęcia tutaj

DenDenDo
źródło
9

Bezkontekstowy, 99 bajtów

startshape d CF::Tile=[s 4]CF::Symmetry=CF::pmg,0,1,0path d{ARCTO(-1,1,1)ARCTO(1,1,-1)ARCTO(0,0,1)}

Możesz zobaczyć wynik w Context Free Gallery .

MtnViewJohn
źródło
Fajnie, to niesamowite wykorzystanie bezkontekstowego. :)
Martin Ender
7

HTML + JavaScript, 277

<canvas id=C></canvas><script>r=50,C.width=C.height=9*r,T=C.getContext('2d');
for(f=1,P=Math.PI,i=0;i<45;f=-f,i+=i&7?1:2)x=2*r*(i%8-2),y=2*r*(i>>3),T.moveTo(x,y+f*r),
T.arc(x+r,y+f*r,r,P,-f*P/2,f<0),T.arc(x,y,r,0,P,f>0),T.arc(x-r,y+f*r,r,-f*P/2,0,f<0);
T.fill()</script>

Aby przetestować, zapisz jako plik HTML i otwórz w przeglądarce. Albo uruchom fragment kodu

r=50,C.width=C.height=9*r,T=C.getContext('2d')
for(f=1,P=Math.PI,i=0;i<45;f=-f,i+=i&7?1:2)
  x=2*r*(i%8-2),y=2*r*(i>>3),
  T.moveTo(x,y+f*r),
  T.arc(x+r,y+f*r,r,P,-f*P/2,f<0),
  T.arc(x,y,r,0,P,f>0),
  T.arc(x-r,y+f*r,r,-f*P/2,0,f<0)
T.fill()
<canvas id=C></canvas>

Ze względu na popularny popyt, oto obraz wyjściowy. W końcu nie takie ekscytujące ...

Płytki

edc65
źródło
1
Możesz opublikować obraz, aby kod nie musiał być uruchamiany za każdym razem, gdy ktoś chce zobaczyć wynik.
Calvin's Hobbies
@ Calvin'sHobbies, no cóż, jest wystarczająco szybki i działa w każdej nowoczesnej przeglądarce. Zamiast tego powiększę obraz
edc65
To prawda. Myślałem, że używał =>wielu twoich postów i działałby tylko w Firefoksie. Ale nie martw się.
Calvin's Hobbies
1
Lepszy powód opublikowania obrazu: Te fragmenty nie działają zbyt dobrze na urządzeniach mobilnych :(
Sp3000
6

IDL 8.3, 201 193 183 bajtów

Obraz jest wyprowadzany do okna graficznego IDL; Zrobiłem zrzut ekranu poniżej.

EDYCJA: dzięki @AlexA. i @ Sp3000 za pomoc w goleniu niektórych bajtów

p=!pi/99*[0:99]
q=p[49:0:-1]
o=p[99:50:-1]
window,xs=(ys=400)
for i=0,24 do cgpolygon,i mod 5*100+50*[cos(p),cos(q)-1,cos(o)+1],i/5*100+(-1)^i*50*[sin(p),sin(q)-1,sin(o)-1],/d,/fi
end

wprowadź opis zdjęcia tutaj

sirpercival
źródło
6

Mathematica: 86 bajtów (lub 82 bajtów)

Dzięki nieskończonemu @alephalpha za sprytną metodę opartą na tablicy:

Image@ArrayFlatten@Array[DiskMatrix@32~RotateLeft~32/.a_/;OddQ@+##:>1-Thread@a&,{5,5}]

Wewnątrz tablicy znajduje się anonimowa funkcja, która wykorzystuje sprytną sztuczkę, aby dodać swoje argumenty ( +##) i ustalić, czy suma jest nieparzysta. Ta wartość logiczna jest używana jako warunek wzoru, który zastępuje całą „białą” płytkę transformowaną, „czarną” płytką. Stamtąd ArrayFlattenłączy płytki i Imagewyświetla je.

Zwróć uwagę na użycie krótszego Threaddo zastąpienia Transpose. Nadal możemy zapisać 4 bajty, używając zamiast tego symbolu transpozycji.

Poprzedni: 97 bajtów (lub 90 bajtów)

Image@ArrayFlatten@Partition[
 Join@@Table[{#,1-Transpose@#}&@RotateLeft[DiskMatrix@32,32],{13}],5]

Można zmniejszyć liczbę bajtów, zastępując Transpose@#symbol indeksu górnego t (punkt kodowy U + F3C7, skrót ESCtrESC). W UTF-8 daje to w sumie 90 bajtów w 88 znakach .

wprowadź opis zdjęcia tutaj

Zaczynamy od DiskMatrix, który generuje macierz binarną:

DiskMatrix@32 // Image

wprowadź opis zdjęcia tutaj

Następnie przesuwamy kołowo rzędy macierzy, aby utworzyć komórkę elementarną dla kafelków:

RotateLeft[DiskMatrix@32, 32] // Image

wprowadź opis zdjęcia tutaj

Jeśli samolot jest szachownicą, są to „białe” kwadraty. W przypadku „czarnych” kwadratów musimy odwrócić kolory i obrócić o 90 stopni. Możemy odwrócić, odejmując od 1 ( 1 - 1 -> 0i 1 - 0 -> 1), i obracać, wykonując transpozycję:

Image /@ {#, 1 - Transpose@#} &@RotateLeft[DiskMatrix@32, 32]

wprowadź opis zdjęcia tutaj

Jeśli wymiary obrazu są równe (jak minimalny rozmiar 4), to kafelek na prawej krawędzi będzie taki sam jak następny na lewej krawędzi. Jednak dodanie jednego kafelka, aby uzyskać nieparzysty rozmiar (5), a następnie konkatenacja wierszy tworzy regularny naprzemienny wzór.

Sugeruje to, że możemy uzyskać pełny obraz, owijając jeden rząd naprzemiennie płytek Partition. Używamy Tabledo tworzenia listy 13czarnych / białych par płytek i Joinspłaszczania listy par do listy 26 płytek. Następnie Partitionotrzymaną listę w 5przez 5matrycę płytek ( Partitionodrzuty spływu 26 th dachówka):

Map[Image] /@ 
  Partition[
   Join @@ Table[{#, 1 - #\[Transpose]} &@
      RotateLeft[DiskMatrix@32, 32], {13}], 5] // MatrixForm

wprowadź opis zdjęcia tutaj

Na koniec ArrayFlattenzamienia macierz macierzy kafelków w płaską macierz i Imagewyświetla wynik.

Poprzedni: 111 bajtów

Image[ArrayFlatten[{{#, #}, {#, #}}] &[
  Join[#, Reverse@#, 2] &[
   Join[1 - Transpose@#, #] &@RotateLeft[DiskMatrix[32], 32]]]]

wprowadź opis zdjęcia tutaj

2012 rcampion
źródło
Image@ArrayFlatten@Array[RotateLeft[DiskMatrix@32,32]/.a_/;OddQ[+##]:>1-Thread@a&,{5,5}]
alephalpha
4

Java, 550 540 508 504 bajtów

To jest aplet Java.

import java.awt.*;public class T extends java.applet.Applet{int a=98,b=49,x,y;public void paint(Graphics g){for(x=0;x<5;x++)for(y=0;y<5;y++)a(g.create(x*a,y*a,a,a),x%2^y%2);}void a(Graphics g,int c){if(c>0){g.translate(a,0);((Graphics2D)g).scale(-1,1);}g.setColor(Color.red);g.fillRect(0,0,b,b);g.fillRect(b,b,b,b);g.setColor(Color.blue);g.fillRect(b,0,b,b);g.fillRect(0,b,b,b);g.fillArc(0,-b,a,a,180,90);g.fillArc(0,b,a,a,0,90);g.setColor(Color.red);g.fillArc(-b,0,a,a,0,-90);g.fillArc(b,0,a,a,90,90);}}

Rozszerzony o płytę grzewczą:

import java.awt.*;
public class T extends java.applet.Applet{
    int a = 98, b = 49, x, y; //Make these larger for better quality pictures. a = b * 2
    public void paint(Graphics g) {
        for (x=0; x < 5; x++)      //Make these larger for more tiles.
            for (y=0; y < 5; y++)  //
                a(g.create(x * a, y * a, a, a), x % 2 ^ y % 2);
    }

    void a(Graphics g, int c) {
        if (c > 0) {
            g.translate(a, 0);
            ((Graphics2D) g).scale(-1, 1);
        }
        g.setColor(Color.red);            //Change colors for nicer looking colors.
        g.fillRect(0, 0, b, b);
        g.fillRect(b, b, b, b);
        g.setColor(Color.blue);
        g.fillRect(b, 0, b, b);
        g.fillRect(0, b, b, b);
        g.fillArc(0, -b, a, a, 180, 90);
        g.fillArc(0, b, a, a, 0, 90);
        g.setColor(Color.red);
        g.fillArc(-b, 0, a, a, 0, -90);
        g.fillArc(b, 0, a, a, 90, 90);
    }
}

Aplet: mały program, który można wywołać w celu użycia podczas pracy w innej aplikacji.

Przykładowy obraz:

wprowadź opis zdjęcia tutaj

Wyjaśnienie:

Działa to przy użyciu metody drukowania każdego kafelka. Przed utworzeniem metody otrzymuje obiekt graficzny, który wykorzystuje układ współrzędnych wyśrodkowany w lewym górnym rogu każdej płytki:

Aby utworzyć kafelek, używamy następującej metody:

void a(Graphics g, int c) {
    g.setColor(Color.red);
    g.fillRect(0, 0, b, b);
    g.fillRect(b, b, b, b);
    g.setColor(Color.blue);
    g.fillRect(b, 0, b, b);
    g.fillRect(0, b, b, b);
    g.fillArc(0, -b, a, a, 180, 90);
    g.fillArc(0, b, a, a, 0, 90);
    g.setColor(Color.red);
    g.fillArc(-b, 0, a, a, 270, 90);
    g.fillArc(b, 0, a, a, 90, 90);
}

Jednak każda inna płytka musi być odbijana poziomo, aby uzyskać prawidłowy obraz.

Aby odzwierciedlić kafelek, po prostu modyfikujemy dostarczony graphicsobiekt za pomocą tego kodu:

g.translate(a, 0);
((Graphics2D) g).scale(-1, 1);

Dzięki @CoolGuy za 4 bajty.

Numer jeden
źródło
1
Możesz xyint a = 98, b = 49,x,y;
zagrać w
4

Mathematica 299 256

Wordy, ale miło było to rozgryźć.

Podstawowym kafelkiem jest r (pokazany poniżej), który jest regionem wyświetlanym przez RegionPlot. Odbicie lewej i prawej płytki jest wykonywane i łączone za pomocą r. Figurka złożona z dwóch kafelków jest następnie powtarzana, aby kafelkować przestrzeń.

r

a_~f~b_ := (x + a)^2 + (y + b)^2 <= 1;
a = ImageAssemble;
r = RegionPlot[(0~f~0 && y <= 0 && ! f[-1, 1]) \[Or] (0~f~2 && 
      y >= -2 && ! f[1, 1]), {x, -1, 1}, {y, -2, 0}, Frame -> False,
    BoundaryStyle -> None];
s = ImageCrop@Rasterize@r;
t = s~ImageReflect~Right;
i = a@{s, t};
j = a@{t, s};
a@{k = {i, i, i, i}, m = {j, j, j, j}, k, m, k, m}

dachówka

DavidC
źródło
1

C, 237 209 180 bajtów

180 bajtów. Ta wersja zawiera zmiany sugerowane przez edc65 w komentarzu. Daje 9 ostrzeżeń kompilatora podczas budowania na komputerze Mac z opcją clang i domyślnymi:

a,b,c,d,x,y;main(){for(puts("P1 256 256");b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c++<256;)putchar(48+(x*x+y*y<962^b==d));puts("");}}

209 bajtów, korzystając z sugestii z komentarzy Martina. Kompiluje bez ostrzeżeń z clang:

#include <stdio.h>
int a,b,c,d,x,y;int main(){puts("P1 256 256");for(;b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c<256;++c)putchar(48+(x*x+y*y<962^b==d));puts("");}}

Wersja oryginalna, 237 bajtów:

#include <stdio.h>
int main(){puts("P1 256 256");for(int a=0;a<256;++a){int b=a+32&64;for(int c=0;c<256;++c){int d=c+32&64;int x=(a&64)-d?31-a&31:a&31;int y=(c&64)-b?c&31:31-c&31;putchar(48+(x*x+y*y<962^b==d));}puts("");}}

Wynik (256 x 256):

wprowadź opis zdjęcia tutaj

Oryginalny kod z białymi spacjami dla lepszej czytelności:

#include <stdio.h>
int main()
{
    puts("P1 256 256");
    for (int a = 0; a < 256; ++a)
    {
        int b = a + 32 & 64;
        for (int c = 0; c < 256; ++c)
        {
            int d = c + 32 & 64;
            int x = (a & 64) - d ? 31 - a & 31 : a & 31;
            int y = (c & 64) - b ? c & 31 : 31 - c & 31;
            putchar(48 + (x * x + y * y < 962 ^ b == d));
        }
        puts("");
    }
}

Nie korzysta z żadnej biblioteki graficznej, rendering jest całkowicie zawarty w kodzie.

Podstawową ideą jest po prostu zapętlenie wszystkich 256 x 256 pikseli i sprawdzenie, czy znajdują się one wewnątrz / na zewnątrz okrągłego łuku kwadratu 32 x 32, w którym się znajdują. Dolne 5 bitów ogólnych współrzędnych pikseli określa względne współrzędne piksela w obrębie pod-kwadrat. Test wewnątrz / na zewnątrz (x, y)przebywania wewnątrz łuku o promieniu rjest wówczas standardem:

x * x + y * y < r * r

Większość logiki polega na umieszczeniu środka łuku w odpowiednim rogu kwadratu i określeniu, który kolor znajduje się wewnątrz / na zewnątrz.

Kilka uwag na temat rozwiązania:

  • Kod generuje obraz w formacie PBM ASCII. Załadowałem wynik do GIMP i zrobiłem kopiowanie i wklejanie do Paint, aby wygenerować plik, który tutaj opublikowałem. Tak więc format został przekonwertowany, ale treść jest dokładnie taka jak oryginalny wynik.
  • Jeśli przyjrzysz się uważnie, zauważysz, że jakość nie jest świetna. Wynika to z tego, że obliczanie wewnątrz / na zewnątrz jest wykonywane dla rogu piksela zamiast środka piksela, co powoduje, że całość jest oddalona o 1/2 piksela. Nie sądzę, że byłoby to trudne do zrobienia lepiej, ale wydłużyłoby to kod. A ponieważ nie było określonych wymagań jakościowych, uważam, że to wystarczy.
  • Kod został skompilowany przy użyciu clang na komputerze Mac. Najnowsza wersja zawiera ostrzeżenia, początkowa wersja nie.
  • To pierwszy raz, kiedy spróbowałem jednego z nich, więc prawdopodobnie przegapiłem kilka sztuczek, aby zapisać ostatni możliwy bajt.
Reto Koradi
źródło
3
Witamy w PPCG! Nie jestem wielkim golfistą C, ale myślę, że widzę kilka ulepszeń: pogrupuj swoje deklaracje jak int a,b,c,d,x,y;... Myślę, że możesz to zrobić main(a,b,c,d,x,y), pamiętam coś, że domyślnym typem jest int. Kiedy już się tego pozbędziesz, możesz przenieść przypisania do d, x i y do forinstrukcji inkrementacji wewnętrznej , np. d=c+32&64,...,++c(Prawdopodobnie nawet przenieść ++w inne miejsce, o którym i ctak wspominasz ), a następnie możesz pominąć nawiasy klamrowe wewnętrzny for. Dobra robota, btw! :)
Martin Ender
Dzięki! Widziałem sztuczkę polegającą na deklarowaniu argumentów bez typów na liście wskazówek, ale wydawało mi się to tak brudne, że nie mogłem się tam dostać. ;) Nie sądzę, aby niestandardowe argumenty były main()zgodne ze standardem. Z pewnością powinienem pogrupować deklaracje. Przesunięcie przyrostów pozwoli również zaoszczędzić kilka bajtów. Nowa puts()linia znajduje się w zewnętrznej pętli, więc nie jestem pewien, czy uda mi się pozbyć nawiasów klamrowych.
Reto Koradi
Zwykle nie mamy nic przeciwko temu, o ile kompiluje się w jakimś popularnym kompilatorze (więc nie musi to być całkowicie standardowy C). Również tak, nie sądzę, że możesz pozbyć się zewnętrznych aparatów ortodontycznych, ale powinieneś być w stanie usunąć wewnętrzne.
Martin Ender,
Sprowadziłem to do 210 bajtów. Dzięki za pomysły.
Reto Koradi
1
Wskazówki: stdioniepotrzebne, użyj domyślnej deklaracji funkcji. intjest domyślny dla globałów i można go pominąć (zmienne i główny). Najpierw putsmoże wejść do środka. Zmienna nie jest używana w wewnętrznej pętli, więc należy zwiększyć jej wartość. 180: a,b,c,d,x,y;main(){for(puts("P1 256 256");b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c++<256;)putchar(48+(x*x+y*y<962^b==d));puts("");}}(kompiluje się z wieloma ostrzeżeniami, ale działa)
edc65