ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

分形树(Fractal tree)【代码实现】

2019-09-11 09:41:05  阅读:314  来源: 互联网

标签:angle int tree depth y1 分形 x2 y2 Fractal


C

#include <SDL/SDL.h>
#ifdef WITH_CAIRO
#include <cairo.h>
#else
#include <SDL/sge.h>
#endif
#include <cairo.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
 
#ifdef WITH_CAIRO
#define PI 3.1415926535
#endif
 
#define SIZE           800   // determines size of window
#define SCALE          5     // determines how quickly branches shrink (higher value means faster shrinking)
#define BRANCHES       14    // number of branches
#define ROTATION_SCALE 0.75  // determines how slowly the angle between branches shrinks (higher value means slower shrinking)
#define INITIAL_LENGTH 50    // length of first branch
 
double rand_fl(){
  return (double)rand() / (double)RAND_MAX;
}
 
void draw_tree(SDL_Surface * surface, double offsetx, double offsety,
               double directionx, double directiony, double size,
               double rotation, int depth) {
#ifdef WITH_CAIRO
  cairo_surface_t *surf = cairo_image_surface_create_for_data( surface->pixels,
                                                               CAIRO_FORMAT_RGB24,
							       surface->w, surface->h,
							       surface->pitch );
  cairo_t *ct = cairo_create(surf);
 
  cairo_set_line_width(ct, 1);
  cairo_set_source_rgba(ct, 0,0,0,1);
  cairo_move_to(ct, (int)offsetx, (int)offsety);
  cairo_line_to(ct, (int)(offsetx + directionx * size), (int)(offsety + directiony * size));
  cairo_stroke(ct);
#else
  sge_AALine(surface,
      (int)offsetx, (int)offsety,
      (int)(offsetx + directionx * size), (int)(offsety + directiony * size),
      SDL_MapRGB(surface->format, 0, 0, 0));
#endif
  if (depth > 0){
    // draw left branch
    draw_tree(surface,
        offsetx + directionx * size,
        offsety + directiony * size,
        directionx * cos(rotation) + directiony * sin(rotation),
        directionx * -sin(rotation) + directiony * cos(rotation),
        size * rand_fl() / SCALE + size * (SCALE - 1) / SCALE,
        rotation * ROTATION_SCALE,
        depth - 1);
 
    // draw right branch
    draw_tree(surface,
        offsetx + directionx * size,
        offsety + directiony * size,
        directionx * cos(-rotation) + directiony * sin(-rotation),
        directionx * -sin(-rotation) + directiony * cos(-rotation),
        size * rand_fl() / SCALE + size * (SCALE - 1) / SCALE,
        rotation * ROTATION_SCALE,
        depth - 1);
  }
}
 
void render(SDL_Surface * surface){
  SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 255, 255, 255));
  draw_tree(surface,
      surface->w / 2.0,
      surface->h - 10.0,
      0.0, -1.0,
      INITIAL_LENGTH,
      PI / 8,
      BRANCHES);
  SDL_UpdateRect(surface, 0, 0, 0, 0);
}
 
int main(){
  SDL_Surface * screen;
  SDL_Event evt;
 
  SDL_Init(SDL_INIT_VIDEO);
 
  srand((unsigned)time(NULL));
 
  screen = SDL_SetVideoMode(SIZE, SIZE, 32, SDL_HWSURFACE);
 
  render(screen);
  while(1){
    if (SDL_PollEvent(&evt)){
      if(evt.type == SDL_QUIT) break;
    }
    SDL_Delay(1);
  }
  SDL_Quit();
  return 0;
}

C++

#include <windows.h>
#include <string>
#include <math.h>
 
//--------------------------------------------------------------------------------------------------
using namespace std;
 
//--------------------------------------------------------------------------------------------------
const float PI = 3.1415926536f;
 
//--------------------------------------------------------------------------------------------------
class myBitmap
{
public:
    myBitmap() : pen( NULL ) {}
    ~myBitmap()
    {
	DeleteObject( pen );
	DeleteDC( hdc );
	DeleteObject( bmp );
    }
 
    bool create( int w, int h )
    {
	BITMAPINFO	bi;
	void		*pBits;
	ZeroMemory( &bi, sizeof( bi ) );
	bi.bmiHeader.biSize	   = sizeof( bi.bmiHeader );
	bi.bmiHeader.biBitCount	   = sizeof( DWORD ) * 8;
	bi.bmiHeader.biCompression = BI_RGB;
	bi.bmiHeader.biPlanes	   = 1;
	bi.bmiHeader.biWidth	   =  w;
	bi.bmiHeader.biHeight	   = -h;
 
	HDC dc = GetDC( GetConsoleWindow() );
	bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
	if( !bmp ) return false;
 
	hdc = CreateCompatibleDC( dc );
	SelectObject( hdc, bmp );
	ReleaseDC( GetConsoleWindow(), dc ); 
 
	width = w; height = h;
 
	return true;
    }
 
    void setPenColor( DWORD clr )
    {
	if( pen ) DeleteObject( pen );
	pen = CreatePen( PS_SOLID, 1, clr );
	SelectObject( hdc, pen );
    }
 
    void saveBitmap( string path )
    {
	BITMAPFILEHEADER	fileheader;
	BITMAPINFO			infoheader;
	BITMAP				bitmap;
	DWORD*				dwpBits;
	DWORD				wb;
	HANDLE				file;
 
	GetObject( bmp, sizeof( bitmap ), &bitmap );
 
	dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
	ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
	ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
	ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
 
	infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
	infoheader.bmiHeader.biCompression = BI_RGB;
	infoheader.bmiHeader.biPlanes = 1;
	infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
	infoheader.bmiHeader.biHeight = bitmap.bmHeight;
	infoheader.bmiHeader.biWidth = bitmap.bmWidth;
	infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
 
	fileheader.bfType    = 0x4D42;
	fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
	fileheader.bfSize    = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
 
	GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
 
	file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
	WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
	WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
	WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
	CloseHandle( file );
 
	delete [] dwpBits;
    }
 
    HDC getDC()     { return hdc; }
    int getWidth()  { return width; }
    int getHeight() { return height; }
 
private:
    HBITMAP bmp;
    HDC	    hdc;
    HPEN    pen;
    int     width, height;
};
//--------------------------------------------------------------------------------------------------
class vector2
{
public:
    vector2() { x = y = 0; }
    vector2( int a, int b ) { x = a; y = b; }
    void set( int a, int b ) { x = a; y = b; }
    void rotate( float angle_r )
    {
	float _x = static_cast<float>( x ),
	      _y = static_cast<float>( y ),
	       s = sinf( angle_r ), 
	       c = cosf( angle_r ),
	       a = _x * c - _y * s, 
	       b = _x * s + _y * c;
 
	x = static_cast<int>( a ); 
	y = static_cast<int>( b );
    }
 
    int x, y;
};
//--------------------------------------------------------------------------------------------------
class fractalTree
{
public:
    fractalTree()		      { _ang = DegToRadian( 24.0f ); }
    float DegToRadian( float degree ) { return degree * ( PI / 180.0f ); }
 
    void create( myBitmap* bmp )
    {
	_bmp = bmp;
	float line_len = 130.0f;
 
	vector2 sp( _bmp->getWidth() / 2, _bmp->getHeight() - 1 );
	MoveToEx( _bmp->getDC(), sp.x, sp.y, NULL );
	sp.y -= static_cast<int>( line_len );
	LineTo( _bmp->getDC(), sp.x, sp.y);
 
	drawRL( &sp, line_len, 0, true );
	drawRL( &sp, line_len, 0, false );
    }
 
private:
    void drawRL( vector2* sp, float line_len, float a, bool rg )
    {
	line_len *= .75f;
	if( line_len < 2.0f ) return;
 
	MoveToEx( _bmp->getDC(), sp->x, sp->y, NULL );
	vector2 r( 0, static_cast<int>( line_len ) );
 
        if( rg ) a -= _ang;
        else a += _ang; 
 
	r.rotate( a );
	r.x += sp->x; r.y = sp->y - r.y;
 
	LineTo( _bmp->getDC(), r.x, r.y );
 
	drawRL( &r, line_len, a, true );
	drawRL( &r, line_len, a, false );
    }
 
    myBitmap* _bmp;
    float     _ang;
};
//--------------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
    ShowWindow( GetConsoleWindow(), SW_MAXIMIZE );
 
    myBitmap bmp;
    bmp.create( 640, 512 );
    bmp.setPenColor( RGB( 255, 255, 0 ) );
 
    fractalTree tree;
    tree.create( &bmp );
 
    BitBlt( GetDC( GetConsoleWindow() ), 0, 20, 648, 512, bmp.getDC(), 0, 0, SRCCOPY );
 
    bmp.saveBitmap( "f://rc//fracTree.bmp" );
 
    system( "pause" );
 
    return 0;
}

Go

package main
 
// Files required to build supporting package raster are found in:
// * Bitmap
// * Grayscale image
// * Xiaolin Wu's line algorithm
// * Write a PPM file
 
import (
    "math"
    "raster"
)
 
const (
    width  = 400
    height = 300
    depth  = 8
    angle  = 12
    length = 50
    frac   = .8
)
 
func main() {
    g := raster.NewGrmap(width, height)
    ftree(g, width/2, height*9/10, length, 0, depth)
    g.Bitmap().WritePpmFile("ftree.ppm")
}
 
func ftree(g *raster.Grmap, x, y, distance, direction float64, depth int) {
    x2 := x + distance*math.Sin(direction*math.Pi/180)
    y2 := y - distance*math.Cos(direction*math.Pi/180)
    g.AaLine(x, y, x2, y2)
    if depth > 0 {
        ftree(g, x2, y2, distance*frac, direction-angle, depth-1)
        ftree(g, x2, y2, distance*frac, direction+angle, depth-1)
    }
}

Java

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
 
public class FractalTree extends JFrame {
 
    public FractalTree() {
        super("Fractal Tree");
        setBounds(100, 100, 800, 600);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
 
    private void drawTree(Graphics g, int x1, int y1, double angle, int depth) {
        if (depth == 0) return;
        int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0);
        int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0);
        g.drawLine(x1, y1, x2, y2);
        drawTree(g, x2, y2, angle - 20, depth - 1);
        drawTree(g, x2, y2, angle + 20, depth - 1);
    }
 
    @Override
    public void paint(Graphics g) {
        g.setColor(Color.BLACK);
        drawTree(g, 400, 500, -90, 9);
    }
 
    public static void main(String[] args) {
        new FractalTree().setVisible(true);
    }
}

JavaScript

html>
<body>
<canvas id="canvas" width="600" height="500"></canvas>
 
<script type="text/javascript">
var elem = document.getElementById('canvas');
var context = elem.getContext('2d');
 
context.fillStyle = '#C0C0C0';
context.lineWidth = 1;
 
var deg_to_rad = Math.PI / 180.0;
var depth = 9;
 
function drawLine(x1, y1, x2, y2, brightness){
  context.moveTo(x1, y1);
  context.lineTo(x2, y2);
}
 
function drawTree(x1, y1, angle, depth){
  if (depth !== 0){
    var x2 = x1 + (Math.cos(angle * deg_to_rad) * depth * 10.0);
    var y2 = y1 + (Math.sin(angle * deg_to_rad) * depth * 10.0);
    drawLine(x1, y1, x2, y2, depth);
    drawTree(x2, y2, angle - 20, depth - 1);
    drawTree(x2, y2, angle + 20, depth - 1);
  }
}
 
context.beginPath();
drawTree(300, 500, -90, depth);
context.closePath();
context.stroke();
</script>
 
</body>
</html>

Kotlin

// version 1.1.2
 
import java.awt.Color
import java.awt.Graphics
import javax.swing.JFrame
 
class FractalTree : JFrame("Fractal Tree") {
    init {
        background = Color.black
        setBounds(100, 100, 800, 600)
        isResizable = false
        defaultCloseOperation = EXIT_ON_CLOSE
    }
 
    private fun drawTree(g: Graphics, x1: Int, y1: Int, angle: Double, depth: Int) {
        if (depth == 0) return
        val x2 = x1 + (Math.cos(Math.toRadians(angle)) * depth * 10.0).toInt()
        val y2 = y1 + (Math.sin(Math.toRadians(angle)) * depth * 10.0).toInt()
        g.drawLine(x1, y1, x2, y2)
        drawTree(g, x2, y2, angle - 20, depth - 1)
        drawTree(g, x2, y2, angle + 20, depth - 1)
    }
 
    override fun paint(g: Graphics) {
        g.color = Color.white
        drawTree(g, 400, 500, -90.0, 9)
    }
}
 
fun main(args: Array<String>) {
    FractalTree().isVisible = true
}

PHP

<?php
header("Content-type: image/png");
 
$width = 512;
$height = 512;
$img = imagecreatetruecolor($width,$height);
$bg = imagecolorallocate($img,255,255,255);
imagefilledrectangle($img, 0, 0, $width, $width, $bg);
 
$depth = 8;
function drawTree($x1, $y1, $angle, $depth){
 
    global $img;
 
    if ($depth != 0){
        $x2 = $x1 + (int)(cos(deg2rad($angle)) * $depth * 10.0);
        $y2 = $y1 + (int)(sin(deg2rad($angle)) * $depth * 10.0);
 
        imageline($img, $x1, $y1, $x2, $y2, imagecolorallocate($img,0,0,0));
 
        drawTree($x2, $y2, $angle - 20, $depth - 1);
        drawTree($x2, $y2, $angle + 20, $depth - 1);
    }
}
 
drawTree($width/2, $height, -90, $depth);
 
imagepng($img);
imagedestroy($img);
?>

Python

import pygame, math
 
pygame.init()
window = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Fractal Tree")
screen = pygame.display.get_surface()
 
def drawTree(x1, y1, angle, depth):
    if depth:
        x2 = x1 + int(math.cos(math.radians(angle)) * depth * 10.0)
        y2 = y1 + int(math.sin(math.radians(angle)) * depth * 10.0)
        pygame.draw.line(screen, (255,255,255), (x1, y1), (x2, y2), 2)
        drawTree(x2, y2, angle - 20, depth - 1)
        drawTree(x2, y2, angle + 20, depth - 1)
 
def input(event):
    if event.type == pygame.QUIT:
        exit(0)
 
drawTree(300, 550, -90, 9)
pygame.display.flip()
while True:
    input(pygame.event.wait())

Ruby

Shoes.app(:title => "Fractal Tree", :width => 600, :height => 600) do
  background "#fff"
  stroke "#000"
  @deg_to_rad = Math::PI / 180.0
 
  def drawTree(x1, y1, angle, depth)
    if depth != 0
      x2 = x1 + (Math.cos(angle * @deg_to_rad) * depth * 10.0).to_i
      y2 = y1 + (Math.sin(angle * @deg_to_rad) * depth * 10.0).to_i
 
      line x1, y1, x2, y2
 
      drawTree(x2, y2, angle - 20, depth - 1)
      drawTree(x2, y2, angle + 20, depth - 1)      
    end
  end
 
  drawTree(300,550,-90,9)
end

Swift

extension CGFloat {
  func degrees_to_radians() -> CGFloat {
    return CGFloat(M_PI) * self / 180.0
  }
}
 
extension Double {
  func degrees_to_radians() -> Double {
    return Double(M_PI) * self / 180.0
  }
}
 
 
class Tree: UIView {
 
 
  func drawTree(x1: CGFloat, y1: CGFloat, angle: CGFloat, depth:Int){
    if depth == 0 {
      return
    }
    let ang = angle.degrees_to_radians()
    let x2:CGFloat = x1 + ( cos(ang) as CGFloat) * CGFloat(depth) * (self.frame.width / 60)
    let y2:CGFloat = y1 + ( sin(ang) as CGFloat) * CGFloat(depth) * (self.frame.width / 60)
 
    let line = drawLine(x1, y1: y1, x2: x2, y2: y2)
 
    line.stroke()
    drawTree(x2, y1: y2, angle: angle - 20, depth: depth - 1)
    drawTree(x2, y1: y2, angle: angle + 20, depth: depth - 1)
  }
 
  func drawLine(x1:CGFloat, y1:CGFloat, x2:CGFloat, y2:CGFloat) -> UIBezierPath
  {
 
    let path = UIBezierPath()
    path.moveToPoint(CGPoint(x: x1,y: y1))
    path.addLineToPoint(CGPoint(x: x2,y: y2))
    path.lineWidth = 1
    return path
  }
 
  override func drawRect(rect: CGRect) {
 
    let color = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
    color.set()
    drawTree(self.frame.width / 2 , y1: self.frame.height * 0.8, angle: -90 , depth: 9 )
  }
}
 
 
let tree = Tree(frame: CGRectMake(0, 0, 300, 300))
tree

标签:angle,int,tree,depth,y1,分形,x2,y2,Fractal
来源: https://blog.csdn.net/qq_36721220/article/details/100699082

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有