用这个修改后的圆平铺平面


22

取一个以原点为中心的单位圆。在任何两个相邻的象限中,将圆的曲线跨连接圆的x和y截距的线镜像。

使用生成的形状,可以平铺平面:

圆镶嵌

我用了不起的2D物理沙箱Algodoo制作了这张图片!

编写一个程序,以某种常见的无损图像文件格式输出与此图像相似的图像。您可以将图像另存为具有您选择的名称的文件,也可以只显示它。请勿输入任何内容。

规则:

  • 必须使用任何两种视觉上不同的RGB颜色将整个图像与修改后的圆形图块进行镶嵌处理:一种用于垂直指向的图块,一种用于水平指向的图块。

  • 圆形图块的半径至少应为32个像素。(上图中的半径大约为110像素。)

  • 图像至少应宽4格,高4格。结合上面的规则,这意味着图像可以具有256×256像素的最小尺寸。(上图是4块x 4块。)

  • 镶嵌可以任意转换。例如,图像的左上角不必是图块相交的顶点。(但是,不应旋转镶嵌。)

  • 您可以使用具有用于绘制圆形和输出图像等命令的外部图形库。

  • 曲线确实应该近似圆,就像使用中点圆算法可以做到的那样,大多数图形库都可以为您做到。

  • 允许但不要求在图块边缘周围进行抗锯齿。

以字节为单位的最短提交获胜。

Answers:


4

gs2,49个字节

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

生成PBM图像:

输出

助记符:

# 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

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}

在此处输入图片说明
我正在使用尽可能多的相机和光源默认参数,这就是为什么它有点暗的原因。让我们先取消高尔夫

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

很明显,一旦增加圆柱轴的偏移量并更改视角,将会发生什么情况

在此处输入图片说明


1
借助3D透视,边缘是否会略微变形?
orlp 2015年

6
当磁盘的高度为0.1且偏移量为0.001$ \ phi = \ arctan(0.01)= 0.57°$时,从顶部看,磁盘的显示压缩量为$ \ cos(\ phi)= 0.99995 $,多数民众赞成在远远小于一个像素。
DenDenDo'5

@DenDenDo pov-ray无法将相机置于无限远吗?
Random832

@ Random832可以camera{orthographic location -9z}。但是,由于场景基本上是2D的,因此没有什么区别,因此您甚至可以在观看时渲染它,angle 170而结果中不会出现任何鱼眼失真。
DenDenDo 2015年

11

努普洛特182

我注意到单元格之间的边界看起来很正弦,所以我去了一个非常简单的核心方程的解析解
在此处输入图片说明

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

在此处输入图片说明
虽然看起来很相似,但圆圈太方形了。sin出于同样的想法,我用由连接的四分之一圆弧制成的曲线替换,并通过将x和替换为和将其旋转45°yx+yx-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

在此处输入图片说明



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>

要进行测试,请另存为html文件并使用浏览器打开。否则,运行代码段

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>

由于需求旺盛,以下是输出图像。毕竟不那么令人兴奋...

瓷砖


1
您可能要发布图像,这样不必每次有人想查看输出时都运行代码。
加尔文的业余爱好

@ Calvin'sHobbies哦,它足够快并且可以在每种现代浏览器中运行。我会放大图像
edc65

确实如此。我认为它=>像您的许多帖子一样使用,并且只能在Firefox中使用。但是不用担心。
加尔文的爱好2015年

1
张贴图片的更好理由:这些摘要在移动设备上效果不佳:(
Sp3000,2015年

6

IDL 8.3,201个 193 183字节

图像输出到IDL图形窗口;我拍了下面的截图。

编辑:感谢@AlexA。和@ Sp3000帮助我剃了一些字节

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

在此处输入图片说明


6

Mathematica:86个字节(或82个字节)

感谢无限@alephalpha提供了一个聪明的基于数组的方法:

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

数组内部是一个匿名函数,该函数使用巧妙的技巧添加其参数(+##)并确定总和是否为奇数。该布尔值用作将转换后的“黑色”图块替换为整个“白色”图块的模式的条件。从那里,ArrayFlatten将图块连接在一起并Image显示它们。

注意使用较短的Thread来代替Transpose。通过使用转置符号,我们仍然可以节省4个字节。

上一个:97个字节(或90个字节)

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

您可以通过替换Transpose@#上标-t符号(代码点U + F3C7,shortcut ESCtrESC)来减少字节数。在UTF-8中,总共88个字符中的90个字节

在此处输入图片说明

我们从开始DiskMatrix,它会生成一个二进制矩阵:

DiskMatrix@32 // Image

在此处输入图片说明

然后,我们将矩阵的行循环移位以生成用于切片的单位单元:

RotateLeft[DiskMatrix@32, 32] // Image

在此处输入图片说明

如果飞机是棋盘,则为“白色”正方形。对于“黑色”正方形,我们需要反转颜色并旋转90度。我们可以通过减去1(1 - 1 -> 01 - 0 -> 1)来求逆,并通过转置来旋转:

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

在此处输入图片说明

如果图像尺寸均匀(如最小尺寸4),则右侧边缘上的图块将与左侧边缘上的下一个图块相同。但是,添加一个图块以得到奇数大小(5),然后将行连接起来会产生规则的交替模式。

这表明我们可以通过用包裹一行交替的图块来获得完整的图像Partition。我们使用Table,使清单13黑色/白色瓷砖对,Join对对的列表拉平至26瓦的列表。然后我们Partition将列表放入图块的5by 5矩阵(Partition丢弃尾随的 26 图块):

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

在此处输入图片说明

最后,ArrayFlatten将图块矩阵的矩阵转换为平面矩阵,并Image显示结果。

上一个:111字节

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

在此处输入图片说明


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

4

Java中,550个 540 508 504字节

这是一个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);}}

扩展了样板:

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

Applet:一个小型应用程序,可以在另一个应用程序中工作时调用使用。

示例图片:

在此处输入图片说明

说明:

通过使用一种打印每个图块的方法来工作。在创建方法之前,将为它提供一个图形对象,该对象使用以每个图块的左上角为中心的坐标系:

要创建图块,我们使用以下方法:

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

但是,每隔一块瓷砖必须水平反射以产生正确的图像。

为了反映图块,我们只需graphics使用以下代码修改提供的对象:

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

感谢@CoolGuy 4个字节。


1
你可以打高尔夫球更通过声明xy作为类的字段:int a = 98, b = 49,x,y;
Spikatrix

4

数学299 256

罗y的,但很高兴找出来。

基本图块是r(如下所示),它是RegionPlot显示的区域。进行图块的左右反射,并与r合并。然后重复两次组装的图形,以平铺该空间。

[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}

瓦


1

C,237个 209 180字节

180个字节 此版本包含edc65在注释中建议的更改。在具有clang和默认选项的Mac上构建时,它会给出9个编译器警告:

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字节,使用了马丁评论中的一些建议。用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("");}}

原始版本,237字节:

#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("");}}

结果(256x256):

在此处输入图片说明

带有空格的原始代码可提高可读性:

#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("");
    }
}

这不使用任何图形库,渲染完全包含在代码中。

基本思想是简单地遍历所有256x256像素,并查看它们是否在其所在的32x32子正方形的圆弧的内部/外部。总像素坐标的底部5位定义了其中的像素的相对坐标子正方形。那么,在(x, y)半径内的圆弧内部进行的内部/外部测试r就是标准:

x * x + y * y < r * r

大多数逻辑是将圆弧的中心放置在子正方形的正确角上,并确定内部/外部的颜色。

有关解决方案的一些评论:

  • 该代码以PBM ASCII格式生成图像。我将结果加载到GIMP中,并复制并粘贴到Paint中以生成我在此处发布的实际文件。因此,转换了格式,但内容与原始输出完全相同。
  • 如果仔细观察,可能会发现质量不佳。这是因为对像素的角部而不是像素中心进行了内部/外部计算,从而导致整个像素偏离了1/2个像素。我认为做得更好不是很难,但是会使代码更长一些。并且由于没有特定的质量要求,我相信这已经足够。
  • 在Mac上使用clang编译代码。最新版本给出警告,初始版本未给出警告。
  • 这是我第一次尝试其中的一种,因此我可能错过了一些技巧来保存最后一个字节。

3
欢迎来到PPCG!我不是C球手,但我认为我可以看到一些改进:将您的声明分组为int a,b,c,d,x,y;...。我想您甚至可以main(a,b,c,d,x,y)记住默认类型为int的内容。摆脱了这一点之后,您可以将d,x和y的赋值移动到内部for的递增语句中d=c+32&64,...,++c(例如,甚至可以将in移至++您提到的其他位置c),然后可以省略括号内部for。干得好,顺便说一句!:)
马丁·恩德

谢谢!我看到了在提示列表中声明不带参数的自变量的技巧,但是它似乎太脏了,以至于我无法让自己去那儿。;)我认为非标准参数不main()符合标准。我当然应该对声明进行分组。移动增量也会节省几个字节。在puts()为新行是在外环,所以我不知道如果我能摆脱牙套。
Reto Koradi 2015年

只要它可以在某些常见的编译器中进行编译,我们通常就可以接受它(因此它不必完全是标准C语言)。另外,是的,我认为您无法摆脱外侧的牙套,但是您应该能够去除内侧的牙套。
马丁·恩德

减少到210字节。感谢您的想法。
Reto Koradi 2015年

1
提示:stdio不需要,使用默认的函数声明。int全局变量的默认设置,可以省略(变量和main)。首先puts可以进入里面。c var不在内部循环内使用,因此条件递增。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("");}}编译时会发出很多警告,但会运行)
edc65
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.