Closed. This question needs to be more focused。它当前不接受答案。
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
                        
                        5年前关闭。
                                                                                            
                
        
(此TED Talk启发的问题-更多信息here

我正在开发一个jQuery插件,以在画布上绘制图像的方式来建议某些非洲村庄的分形布局:

javascript - 用JavaScript模拟非洲乡村的分形-LMLPHP
(来源:eglash at homepages.rpi.edu

给定图像源列表,该插件的工作方式如下:


生成类似于上图的正交取向的,类似分形的结构。
对于结构中的每个离散区域(矩形),从该区域的列表中绘制图像。


绘制每个图像非常容易,但是我仍然坚持如何生成结构。描述分形的数学知识远远超出了我的脑海。

理想情况下,获得分形表示就像将画布尺寸传递给函数一样简单,该函数将返回矩形列表。每个矩形将表示为:


左上角的X / Y坐标(相对于画布)
宽度
高度


我应该如何实现这样的功能?

最佳答案

有一个重要的分形类别称为L-system。大概的想法是不要过多地考虑整个结构,而只考虑其中的一小部分,以及如何将同一事物的较小版本附加到自身上。

一个很好的例子是一棵树。也许直到现在,当您描述一棵树时,您都会说:“好吧,它是一棵树。它有一棵根。从根开始,树枝长成。从叶子长出来”。但是还有另一种通过规则描述树的方法:

首先定义一个棍子。一根棍子在空间中有一定位置,有一定长度,并沿某个方向旋转。现在到规则:坚持。左右交替旋转5至10条。对新棒重复该过程。继续这样做,直到您累了。令人难以置信的是,您最终得到的东西看起来像某种植物。



不同的参数会影响数字工厂的外观。一根棍子与另一根棍子的旋转可能会使树显得更茂密或更窄。附属的木棍的位置将改变您获得哪种植物。将所有“儿童摇杆”连接到远端将使其看起来像一棵普通的树。将事物更均匀地隔开会使它看起来更像是蕨类植物(如图所示)。等等。好处是您不受现实的限制。

无论如何,所有这些都是理论。我已经写了一堆代码并在其中添加了一些注释,但是希望它是我上面用盒子而不是木棍解释的非常简单的实现。

click here to play with a jsfiddle of this code。点击运行几次,以查看其产生的不同结果。

// a ton of colors. always handy!
var colors = ["AliceBlue","AntiqueWhite","Aqua","Aquamarine","Azure","Beige","Bisque","Black","BlanchedAlmond","Blue","BlueViolet","Brown","BurlyWood","CadetBlue","Chartreuse","Chocolate","Coral","CornflowerBlue","Cornsilk","Crimson","Cyan","DarkBlue","DarkCyan","DarkGoldenRod","DarkGray","DarkGreen","DarkKhaki","DarkMagenta","DarkOliveGreen","DarkOrange","DarkOrchid","DarkRed","DarkSalmon","DarkSeaGreen","DarkSlateBlue","DarkSlateGray","DarkTurquoise","DarkViolet"];

// store base structure here
// in the end this will contain a nested representation of your village
base = {
    x: 0,
    y: 0,
    width: 400,
    height: 400,
    children: []
};

// and a flat structure here, that's always handy too
var boxes = [base];

// add some children to the base recursively.
addChildren( base, 0 );

// now create a div for each
for( var i in boxes ){
    var box = boxes[i];
    var el = document.createElement("div");
    el.className = "box";
    el.style.left = box.x + "px";
    el.style.top = box.y + "px";
    el.style.width = box.width + "px";
    el.style.height = box.height + "px";
    el.style.backgroundColor = colors[i%colors.length];
    document.body.appendChild( el );
}


// randomly add children to a box recursively
function addChildren( box, level ){
    // maybe... split vertically? (two next to each other)
    if( Math.random() < 0.5 ){
        // maybe... nest further in the top?
        if( Math.random() < 1-level/10.0 ){
            box.children.push( {
                x: box.x,
                y: box.y,
                width: box.width/2,
                height: box.height,
                children: []
            } );
        }
        // maybe bottom too?
        if( Math.random() < 1-level/10.0 ){
            box.children.push( {
                x: box.x + box.width/2,
                y: box.y,
                width: box.width/2,
                height: box.height,
                children: []
            } );
        }
    }
    // ah. maybe we split horizontally instead
    else{
        // maybe... nest further in the top?
        if( Math.random() < 1-level/10.0 ){
            box.children.push( {
                x: box.x,
                y: box.y,
                width: box.width,
                height: box.height/2,
                children: []
            } );
        }
        // maybe bottom too?
        if( Math.random() < 1-level/10.0 ){
            box.children.push( {
                x: box.x,
                y: box.y + box.height/2,
                width: box.width,
                height: box.height/2,
                children: []
            } );
        }
    }

    // also add all the children to our
    // flat list of boxes
    for( var i in box.children ){
        boxes.push( box.children[i] );
    }

    // unless we reach level 5 subdivide further!
    if( level < 5 ){

        for( var i in box.children ){
            // nest deeper!
            addChildren( box.children[i], level+1 );
        }
    }
}


addChildren功能就是神奇的地方。它随机决定是将水平框还是垂直框一分为二。然后随机决定是否在顶部/左侧和/或底部/右侧添加一个框。这是您要进行一些修改并使用不同条件的地方。例如,如果在level是偶数时始终水平分割,而在奇数时垂直分割,则可能会得到有趣的结果。等等等等。

无底的奇迹源于简单的规则,无休止地重复着。
正如benoit mandelbrot所说的:)

祝你好运,分形很棒!



ps。我知道这段代码不会像您的图片那样产生结果。您可能会花费数小时来调整if条件,以使其达到您想要的目的,并且使自己成为一个带有几个滑块的界面以尝试不同设置的方法可能是一个好主意。或有时您想分成三个框而不是一两个框。对于已经很长的答案来说,可能性是无穷无尽的:)

09-17 11:28