Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

Рекурсия присутствует?
И где эти прикрепленные файлы?
Я код на C++ набрал сам. Строил кривую Безье, но "прилипал" к нулю. То есть я задаю точки далеко от нуля, а он строил из нуля, а потом только обходил предложенные точки. Потом я нашёл Ваш сайт и эту статью. Оказалось, что я забыл возвести t в...
просто я не так понял, здесь мы вращаем точки куба что вращает сам куб. Мне нужно вращать просто 3д объект , данный способ не подходит
Задавайте объект в мировых координатах. Вращайте его относительно мировой системы координат. А при отрисовке преобразуйте в экранные координаты. Посмотрите пример преобразования в экранные координаты.

Счетчики и рейтинг

Рейтинг@Mail.ru Яндекс.Метрика
Скриншот к примеру
Среда программирования: 
Eclipce
Статья по теме: 

Программа строит фрактальные деревья по заданным параметрам.

  1. Поля Х и Y отвечают за позицию центра на экране.
  2. Поле Distance отвечает за дистанцию корня дерева от центра.
  3. Поле Number отвечает за количество деревьев, растущих вокруг центра.
  4. Поле Rotation отвечает за поворот деревьев относительно позиции дерева.
  5. В третьем столбике находится спиннер, которым задаётся количество поддеревьев.
  6. В четвёртом столбике в выпадающем меню выбирается параметры какой ветви будут изменяться слайдерами.
  7. Слайдеры изменяют соответствующий параметр ветви.

Фрактальное дерево в данной программе рисуется рекурсивно, отдельно от вычисления координат вершин ветвей.

Код программы: 

package canvas;
 
import java.awt.*;
import java.awt.event.*;
 
import javax.swing.*;
import javax.swing.event.*;
 
 
 
@SuppressWarnings("serial")
public class Fractal extends JFrame{
 
	/*
	 * JSlider - три слайдера, настраивающие изменение дерева, в процессе рисования
	 * s - Строка для выпадающего меню
	 * jchoose - выпадающее меню
	 * JTextField - поля для ввода информациио позиции прсиа дерева
	 * Canvas - место в окне, выделенное под рисование дерева 
	 * */
	JSlider decrease=new JSlider(),turn=new JSlider(),start_len=new JSlider();
	String s[]={"0","1","2"};
	JComboBox<String> jchoose=new JComboBox<String>(s);
	JSpinner how_branches=new JSpinner();
	JTextField coordX= new JTextField(3), 
			   coordY= new JTextField(3),
			   distance_from_center= new JTextField(3),
			   rotate_by_round= new JTextField(3),
			   number_of_roots= new JTextField(3) ;
	Canvas canvas=new Canvas();
	boolean isDone = false, is_set_sliders=false;
	/*
	 * Метод, создающий окно и расставляющий элементы на нём
	 * В данном методе указывается поведение объектов, 
	 * при взаимодействии пользователя с ними
	 * */
	Fractal(){
 
		/*
		 * Для более гибкой расстановки элементов используются панели элементов
		 * */
		JPanel  se=new JPanel(),
				coords=new JPanel(), 
				X=new JPanel(), 
				Y=new JPanel(),
				pos_by_canv_center=new JPanel(), 
				dist=new JPanel(), 
				num=new JPanel(), 
				rot=new JPanel(),
				slide_panel=new JPanel(),
				slide_start=new JPanel(), 
				slide_dec=new JPanel(), 
				slide_turn=new JPanel();
		/*
		 * Неизменяемый текст около полей.
		 * Подсказки для полей ввода и слайдеров
		 * */
 
		JTextArea textX=new JTextArea("X"),	
				textY=new JTextArea("Y"), 
				textNum=new JTextArea("Number"),
				textDist=new JTextArea("Distance"),
				textRot=new JTextArea("Rotation"),
				text_start=new JTextArea("Длина корня"),
				text_dec=new JTextArea("Убывание длины ветви"),
				text_turn=new JTextArea("Поворот ветви");			
 
		/*
		 * Слушающий класс, который будет вызывать 
		 * обновление полей при нажатии клавиш,
		 * когда текстовое поле находится в фокусе
		 * */
 
		KeyListener checkWhenType=new KeyListener() {
			public void keyReleased(KeyEvent e) {changeToCorrect();canvas.repaint();}
			public void keyPressed(KeyEvent e) {changeToCorrect();canvas.repaint();}
			public void keyTyped(KeyEvent e) {changeToCorrect();canvas.repaint();}
		};
 
		/*
		 * Слушающий класс, вызывающий обновление
		 * дерева при сдвиге слайдера
		 * */
		ChangeListener chekWhenSlide=new ChangeListener() {
 
			public void stateChanged(ChangeEvent e) {
				changeToCorrect();
				canvas.reload();
				canvas.repaint();
			}
		};
 
		/*
		 * Слушающий класс, вызывающий обноелние
		 * при выборе числа из выпадающего списка
		 * */
 
		ActionListener chooseListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				is_set_sliders=true;
				if(jchoose.getSelectedIndex() <0 )return;
				start_len.setValue(canvas.len);
				turn.setValue((int)(canvas.rb[jchoose.getSelectedIndex()]*100f) );
				decrease.setValue( (int)(canvas.ld[jchoose.getSelectedIndex()]*100f) );
				is_set_sliders=false;
			}
		};
 
		/* Определяет расположение обьектов в окне*/
		setLayout(new BorderLayout(1,1));
 
 
 
		/* Layout manager-ы будут определять расположение групп обьектов*/
		pos_by_canv_center.setLayout(new BoxLayout(pos_by_canv_center, BoxLayout.Y_AXIS));
		slide_panel.setLayout(new BoxLayout(slide_panel,  BoxLayout.Y_AXIS));
		coords.setLayout(new BoxLayout(coords, BoxLayout.Y_AXIS));	
		slide_start.setLayout(new FlowLayout(0));
		slide_turn.setLayout(new FlowLayout(0));
		slide_dec.setLayout(new FlowLayout(0));
		dist.setLayout(new FlowLayout(0));
		num.setLayout(new FlowLayout(0));
		rot.setLayout(new FlowLayout(0));
		se.setLayout(new FlowLayout(0));
		X.setLayout(new FlowLayout(0));
		Y.setLayout(new FlowLayout(0));
 
		/* Добавление обработчика событий к объектам */
		distance_from_center.addKeyListener(checkWhenType);
		number_of_roots.addKeyListener(checkWhenType);
		rotate_by_round.addKeyListener(checkWhenType);
		start_len.addChangeListener(chekWhenSlide);
		jchoose.addActionListener(chooseListener);
		decrease.addChangeListener(chekWhenSlide);
		turn.addChangeListener(chekWhenSlide);
		coordX.addKeyListener(checkWhenType);
		coordY.addKeyListener(checkWhenType);
		how_branches.addChangeListener(new ChangeListener() {
 
			public void stateChanged(ChangeEvent arg0) {
				int val=how_branches.getValue().hashCode();
				System.out.println(val);
				if(val<1)how_branches.setValue(1);
				changeToCorrect();
				canvas.reload();
				//canvas.repaint();
			}
		});
 
		/* Всплывающие подсказки текстовых полей*/
		rotate_by_round.setToolTipText("Наклон относительно окружности");
		distance_from_center.setToolTipText("Расстояние от центра");
		number_of_roots.setToolTipText("Количество деревьев");
		coordX.setToolTipText("Позиция по X");
		coordY.setToolTipText("Позиция по Y");
 
		/* Цвет рамки текстовых полей */
		distance_from_center.setBorder(BorderFactory.createLineBorder(Color.blue, 3, true));
		number_of_roots.setBorder(BorderFactory.createLineBorder(Color.blue, 3, true));
		rotate_by_round.setBorder(BorderFactory.createLineBorder(Color.blue, 3, true));
		coordX.setBorder(BorderFactory.createLineBorder(Color.green, 2, true));
		coordY.setBorder(BorderFactory.createLineBorder(Color.green, 2, true));
 
		/* Настройка значений обектов в значения по-умолчанию */
		decrease.setValue((int)(canvas.ld[0]*100.0));
		coordX.setText(Integer.toString(canvas.x));
		coordY.setText(Integer.toString(canvas.y));
		turn.setValue((int)(canvas.rb[0]*100.0));
		distance_from_center.setText("0");
		rotate_by_round.setText("0.0");
		number_of_roots.setText("1");
		how_branches.setValue(3);
		start_len.setValue(200);
 
		/* Настройки максимального значения для слайдеров*/
		start_len.setMaximum(1000);
		decrease.setMaximum(95);
		turn.setMaximum(628);
 
		/* Поля с подсказками для обьектов
		 * Настройка видимости фона 
		 * и возможности ввода в них */
		text_start.setEditable(false);
		text_turn.setEditable(false);
		textDist.setEditable(false);
		text_dec.setEditable(false);
		text_start.setOpaque(false);
		textRot.setEditable(false);
		textNum.setEditable(false);
		text_turn.setOpaque(false);
		textDist.setOpaque(false);
		text_dec.setOpaque(false);
		textX.setEditable(false);
		textY.setEditable(false);
		textNum.setOpaque(false);
		textRot.setOpaque(false);
		textX.setOpaque(false);
		textY.setOpaque(false);
		se.setOpaque(true);
 
 
 
		/* Обьединение обьектов в группы и добавление их в окно */		
		dist.add(distance_from_center);
		pos_by_canv_center.add(dist);
		pos_by_canv_center.add(num);
		pos_by_canv_center.add(rot);
		slide_panel.add(slide_start);
		slide_panel.add(slide_turn);
		slide_panel.add(slide_dec);	
		slide_start.add(start_len);
		slide_dec.add(decrease);
		slide_turn.add(turn);
		slide_dec.add(text_dec);
		slide_turn.add(text_turn);
		slide_start.add(text_start);
		num.add(number_of_roots);
		rot.add(rotate_by_round);
		num.add(textNum);
		rot.add(textRot);
		dist.add(textDist);
		X.add(coordX);
		Y.add(coordY);
		coords.add(X);
		coords.add(Y);
		X.add(textX);
		Y.add(textY);
		se.add(coords);
		se.add(pos_by_canv_center);
		se.add(how_branches);
		se.add(jchoose);
		se.add(slide_panel);
 
		/* Добавляет в окно в центр холст и к нижней части окна*/
		add(canvas,BorderLayout.CENTER);
		add(se,BorderLayout.SOUTH);	
		isDone=true;
		setSize(1100,600);
		setDefaultCloseOperation(3);
		setVisible(true);
	}
 
 
	/* 
	 * Метод, проверяющий правильность ввода в поля, во время ввода
	 * В некоторых случаях может не давать стереть последнюю цифру
	 * */
	void changeToCorrect(){
		if(!isDone)return;
		if(is_set_sliders)return;
		/*    Проверка сдвига центра холста */		
		if(coordX.getText().matches("\\d+"))
			canvas.x=Integer.parseInt(coordX.getText());
		else coordX.setText(canvas.x+"");
		if(coordY.getText().matches("\\d+"))
			canvas.y=Integer.parseInt(coordY.getText());
		else coordY.setText(canvas.y+"");	
 
		/*    Проверка изменения относительно центра */	   
		if(distance_from_center.getText().matches("\\d+"))
			canvas.lfromCenter=Integer.parseInt(distance_from_center.getText());
		else distance_from_center.setText(canvas.lfromCenter+"");
		if(rotate_by_round.getText().matches("\\d+\\.?\\d*"))
			if(canvas.rotC == Double.valueOf( rotate_by_round.getText()));
			else
				canvas.rotC=Double.valueOf(rotate_by_round.getText());
		else rotate_by_round.setText(String.valueOf(canvas.rotC));
		if(number_of_roots.getText().matches("\\d+"))canvas.count=Integer.parseInt(number_of_roots.getText());
		else number_of_roots.setText(canvas.count+"");
 
		canvas.len=start_len.getValue();
		/*    Настройки ветвей */
		int var=how_branches.getValue().hashCode();
		int indexVar=jchoose.getSelectedIndex();
 
		if(indexVar>=0 && indexVar < canvas.ld.length){
			canvas.ld[indexVar]=decrease.getValue()/100.0;
			canvas.rb[indexVar]=turn.getValue()/100.0;
		}
 
		if(var != canvas.ld.length){
			String str[]=new String[var];
			jchoose.removeAllItems();
 
			for(int i=0;i<var;i++){
				str[i]=i+"";
				jchoose.addItem(str[i]);
			}		
 
			jchoose.setSelectedIndex(0);
			boolean is_gt=(var>canvas.ld.length);
			double ld[]=new double[var], rb[]=new double[var];
			for(int i=0; ( i< var && !is_gt) || (i < canvas.ld.length && is_gt); i++){
				ld[i]=canvas.ld[i];
				rb[i]=canvas.rb[i];
			}
			if(is_gt){
				for(int i=canvas.ld.length;i<var;i++){
					ld[i]=Math.random()*0.5+0.1;
					rb[i]=Math.random()*6;
				}
			}
			canvas.ld=ld;
			canvas.rb=rb;
			canvas.countBranches=var;
			repaint();
		}
 
	}
	public static void main(String[] args) {
		new Fractal();	
	}
 
}
 
/* Класс, описывающий фрактальное дерево как множество корней*/
class Branch{
 
 
	static final double M_PI=3.1415;
	static final int MAXBRANCHES=3;
	static final int MAXDEPH=100;
	static final double MAXROTATION=M_PI*2;
	static final double MAXLENDECREESE=1;
	static final int MINNUMOFBRANCHES=1;
 
	/* xpos, ypos -Координаты ветви в пространстве
	 * length - Длина ветви
	 * rotate - Поворот ветви
	 * numOfBranches - количество ветвей у каждой ветки
	 * next - Ветви, находящиеся глубже, относительно корня
	 * len_Decr - Параметр убывания длины, на который изменяется i-тая ветка
	 * br_Rot - Параметр кручения, на который изменяется i-тая ветка
	 * */
	int xpos;
	int ypos;
	int length;
	double rotate;
	static int numOfBranches;	// 1 >
	Branch next[]=null;
	static double len_Decr[];
	static double br_Rot[];
 
	/* Функция создаёт дерево по заданным входным данным, 
	 * но не больше чем на 100 ветвей в глубину                 */
	public Branch(int x, int y, double rotate, int len, int deph) {
		xpos=x;
		ypos=y;
		length=len;
		if(rotate<MAXROTATION && rotate>0)(this).rotate=rotate;
		else if(rotate < 0)(this).rotate=rotate+MAXROTATION;
		else (this).rotate=rotate-MAXROTATION;	
		if(deph+1<MAXDEPH && len>2){
			next=new Branch[len_Decr.length];
			for(int i=0;i<len_Decr.length;i++){
				next[i]=new Branch(getX2(),getY2(),br_Rot[i]+rotate,(int)(len*len_Decr[i]),deph+1);
			}
		}
	}
 
	/* Второй конструктор, в который передаются параметры для ветвей
	 * Параметры ветвей записываются в статическую переменную и дальнейшие
	 * параметры берутся уже из класса  */
	public Branch(int x, int y,double rotate,int len, double lenDecr[], double brRot[],int numOfBr, int deph){	
		br_Rot=brRot;
		len_Decr=lenDecr;
		xpos=x;
		ypos=y;
		length=len;
		if(rotate<MAXROTATION && rotate>0)(this).rotate=rotate;
		else if(rotate < 0)(this).rotate=rotate+MAXROTATION;
		else (this).rotate=rotate-MAXROTATION;
		if(deph+1<MAXDEPH && len>2){
			next=new Branch[len_Decr.length];
			for(int i=0;i<len_Decr.length;i++){
				next[i]=new Branch(getX2(),getY2(),br_Rot[i]+rotate,(int) (len*len_Decr[i]),deph+1);
			}
		}		
	}
 
 
	int getX2(){
		return (int)(xpos+length*Math.cos(rotate));
	}
 
	int getY2(){
		return (int)(ypos+length*Math.sin(rotate));
	}
 
	/* Рисует дерево по уже заданным параметрам. */
	void draw(Graphics g){
		Graphics2D g2=(Graphics2D)g;
		g2.drawLine(xpos, ypos, getX2(), getY2());
		if(next!=null)
			for(int i=0;i<next.length;i++){
				if(next[i]!=null)
					next[i].draw(g);
			}
	}
}
/* олст для рисования дерева */
@SuppressWarnings("serial")
class Canvas extends JComponent{
 
	int x=200;
	int y=200;
	double rot=0;
	int len=200;
	int lfromCenter=0;
	double rotC=0;
	int count =1;
	Branch root;
	int countBranches=3;
	double ld[]={0.5,0.4,0.2};
	double rb[]={-0.7,0.5,0.3};
 
	/* При создании холста создаётся дерево*/
	Canvas(){
		root=new Branch(0, 0, 0, 200,ld,rb,3,55);	
	}
 
	/* Создаёт новое дерево, поновым характеристикам */
	void reload(){
		root=new Branch(0, 0, rot, len,ld,rb,countBranches,0);	
 
	}
 
	/* Прорисовка холста */
	public void paintComponent(Graphics g){
		paintComponents(g);
		Graphics2D g2d=(Graphics2D)g;
		g2d.setPaint(new Color(1f,0,1f));
		g2d.translate(x, y);
 
		/* Рисование n деревьев со сдвигом и поворотом холста. 
		 * В итоге холст назодится в исходном положении */
		for(double i=0;i<6.28;i+=6.28/count){
			g2d.rotate(i);
			g2d.translate(lfromCenter, 0);
			g2d.rotate(rotC);
			root.draw(g);
			g2d.rotate(-rotC);
			g2d.translate(-lfromCenter, 0);
			g2d.rotate(-i);
		}
	}	
}

Прикрепленный файлРазмер
fractalBuilder.zip13.91 кб