// // FILE : ifs.java // // AUTHOR : Generated automaticaly by Aleksey's automatic // source code generator:) Novosibirsk, Russia 1999y // // DESCRIPTION : Self-similar fractals editor (IFS editor). // The last version of applet is able on the page // http://chat.ru/~fractals/english.htm // import java.awt.*; import java.applet.*; import java.awt.event.*; // // CLASS : ifs // // DESCRIPTION : This class draws one of tree aviable zippers. // public final class ifs extends Applet implements Runnable, ItemListener, ActionListener, MouseListener, MouseMotionListener { private Choice examples; // samples box private Choice it_box; // iteration value box private Checkbox points_box; // algoritm by points private Checkbox hide_first; // hide first level lines private Checkbox refl_box; // map reflection (conjugation) checkbox private int user_item; // index of last choice box item private Button rev_button; // reverse map button private Button add_button; // add map button private Button del_button; // delete map button private Color colors1[]; // colors to draw lines of the maps private Color colors2[]; // dark colors array to draw the fractal private int px,py; // last mouse pressed position private boolean dragged; // on mouse dragged private int next_point; // points to select if mouse not dragged private final int start_it=2; // starting iteration value in it_box private final int flags = (MouseEvent.SHIFT_MASK|MouseEvent.ALT_MASK |MouseEvent.BUTTON2_MASK|MouseEvent.BUTTON3_MASK); // disconnecting mouse flags private Thread the_thread; // the thread of the drawing process private boolean corrupted; // if there exist non contractive map private volatile boolean drawing; // true if fractal must be redrawed private volatile boolean redraw_maps; // if maps have to be repainted private volatile boolean suspended; // current state of drawing thread private volatile Graphics graph; // current drawing place private volatile Rectangle cur_rect; // current drawing rectangle private volatile Rectangle next_rect; // next drawing rectangle private int maps_number; // number of maps private int seg_number; // number of segments private int points_number; // number of points (=seg_number*2) private int deep_of_tree; // deep of lines tree (=-1 if is unused) private int connected[]; // connected points (-1=not connected,-2=selected) private boolean conjugated[]; // array of maps states (=true if conjugated) private boolean reversed[]; // array of maps states (=true if reversed) private Point points[]; // array of mooving points private int hot_point; // the first selected point of connected points private int selected_point; // (=-1 if no points selected) private int selected_seg; // (=-1 if no maps selected) private double maps[][]; // calculated array of maps (6 numbers per every map) public void init(){ stop_the_thread(); // start and suspend the thread setLayout(new FlowLayout()); setBackground(Color.white); graph = getGraphics(); graph.setPaintMode(); cur_rect = graph.getClipBounds(); examples = new Choice(); it_box = new Choice(); rev_button = new Button("Reverse map"); add_button = new Button("Add map"); del_button = new Button("Delete map"); refl_box = new Checkbox("Reflection"); points_box = new Checkbox("By points"); hide_first = new Checkbox("Hide first"); examples.addItem("Koch curve"); examples.addItem("Sierpinsky triangle"); examples.addItem("Dragon curve"); examples.addItem("Levy curve"); examples.addItem("Branch"); examples.addItem("4 maps rectangle"); examples.addItem("User ..."); user_item = examples.getItemCount()-1; for(int i=start_it;i<=12;i++) it_box.addItem(Integer.toString(i)); add(examples); add(it_box); add(hide_first); add(points_box); add(add_button); add(del_button); add(rev_button); add(refl_box); load_set(0); examples.addItemListener(this); it_box.addItemListener(this); hide_first.addItemListener(this); points_box.addItemListener(this); rev_button.addActionListener(this); add_button.addActionListener(this); del_button.addActionListener(this); refl_box.addItemListener(this); addMouseListener(this); addMouseMotionListener(this); } public static void main(String args[]) { Frame f = new Frame("ifs"); ifs the_applet = new ifs(); the_applet.init(); the_applet.start(); f.add("Center", the_applet); f.setSize(400, 400); f.show(); } // information about fractal /* private String cur_map_info() { String s; s = "{"+maps_number+","+deep_of_tree+","; int cn=0,rv=0; // conjugation, reversing for(int i=0; i=0){ connect_current_to(index); rebuild(); } } examples.select(user_item); dragged = false; } else { // if next point must be selected if(0<=next_point && next_point=points_number){ beg = selected_seg*2; end = beg+1; } else { // if a point was selected beg = end = selected_point; } } Rectangle r = getBounds(); // applet's rectangle // try to move all points of moving segments for(int i=beg; i<=end; i++) { points[i].translate(dx,dy); // if can't move the i-th point if(!r.contains(points[i])){ // restore coordinates while(i>=beg){ points[i--].translate(-dx,-dy); } return; } } // if there is any selected point if(next_point>=0) { // if mouse dragging just has been started if((e.getModifiers()&flags)!=0 && !dragged){ // disconnect moved points from other for(int i=end; i>=beg; i--) { disconnect(i); } hot_point = hot_point_of(selected_point); } else { // move points connected to already moved points for(int i=beg; i<=end; i++) { points[hot_point_of(i)].setLocation(points[i]); } // I think following loop have to be a function for(int i=0; i0 && (vx*(vx-x)+vy*(vy-y))>0 && Math.abs(vy*x-vx*y)<(Math.sqrt(vx*vx+vy*vy)*3) ); } // find selected object private final int find_point(){ int i; // loop counter int n=0; // if end of current segment was selected if(0<=selected_seg && (check_point(n=selected_seg*2) || check_point(++n))) select_point(n); // find next point to select for(i=1; i<=points_number && !check_point(n=(i+selected_point)%points_number); i++); if(i=r2) corrupted=true; if( reversed[i+1]) { f1=-f1; f2=-f2; } if(conjugated[i+1]) { maps[i][0] = (vx*f1-vy*f2)/r2; maps[i][2] = (vx*f2+vy*f1)/r2; } else { maps[i][0] = (vx*f1+vy*f2)/r2; maps[i][2] = (vx*f2-vy*f1)/r2; } maps[i][1] = (conjugated[i+1]? maps[i][2] :-maps[i][2]); maps[i][3] = (conjugated[i+1]?-maps[i][0] : maps[i][0]); // A*z+b=w & A*(z-e)+f=w ==> b=f-A*e f1 = points[i*2+(reversed[i+1]?3:2)].x; f2 = points[i*2+(reversed[i+1]?3:2)].y; maps[i][4] = f1-maps[i][0]*x-maps[i][1]*y; maps[i][5] = f2-maps[i][2]*x-maps[i][3]*y; } } private void draw_maps(){ redraw_maps = false; int i; // loop counter // loop by points for(i=0;i0 && (m[l]--)==0 ); if(l<=0)break; // jump to next way int c=m[l]; p[0][l]=maps[c][0]*p[0][l-1]+maps[c][1]*p[1][l-1]+maps[c][4]; p[1][l]=maps[c][2]*p[0][l-1]+maps[c][3]*p[1][l-1]+maps[c][5]; p[2][l]=maps[c][0]*p[2][l-1]+maps[c][1]*p[3][l-1]+maps[c][4]; p[3][l]=maps[c][2]*p[2][l-1]+maps[c][3]*p[3][l-1]+maps[c][5]; } } private void draw_points(Color[] colors){ int x = points[0].x; int y = points[0].y; double r = maps_number-(1e-9); // main drawing circle for(;drawing;){ if(redraw_maps) draw_maps(); int i=(int)(Math.random()*r); int z = (int)(maps[i][0]*x+maps[i][1]*y+maps[i][4]); y = (int)(maps[i][2]*x+maps[i][3]*y+maps[i][5]); x = z; if(drawing) { graph.setColor(colors[i]); graph.drawLine(x,y,x,y); } } } public void run(){ // main cicle for(;;) { // suspend cicle (waiting for new drawing task) while(next_rect == null){ suspended = true; // sleep for 0.1 second try{ Thread.sleep(100); } catch(InterruptedException e){} } try{ cur_rect = next_rect; // consume drawing task next_rect = null; // clear future tasks drawing = true; // set drawing flag redraw_maps = true; // redraw maps flag suspended = false; // thread was resumed graph.setClip(cur_rect); if(redraw_maps) draw_maps(); if(drawing) calculate_maps(); if(!corrupted && drawing) { if(points_box.getState()) draw_points(colors2); else draw_curve(colors2,deep_of_tree); } } catch(Exception e) { showStatus("Exeption while drawing: "+e); }; } } private void stop_the_thread(){ drawing = false; // notification to stop drawing next_rect = null; // notification don't resume drawing // start thread if its does not exist yet if(the_thread==null || !the_thread.isAlive()){ the_thread = new Thread(this); the_thread.setPriority(Thread.MAX_PRIORITY); the_thread.start(); } // wait for the other thread for(int i=1; i<=10 && !suspended;i++){ Thread.yield(); try{ if(!suspended) Thread.sleep(100); } catch(InterruptedException e){}; } // for(int i=0; i<100 && !suspended; i++) Thread.yield(); // debuging // if(!suspended) { // System.out.println("Not suspended in stop_the_thread()! "+the_thread); // System.out.println("the_thread.isAlive()="+the_thread.isAlive()); // showStatus("Mmm... Not suspended!"+the_thread); // } } private final void rebuild(){ stop_the_thread(); repaint(); } // number of sets, best deep_of_tree, (x1,y1,x2,y2...), conjugation, reversing private final int example_sets[][] = { {2,6, 20,250,380,250, 20,250,200,130, 200,130,380,250, 6, 0}, // Koch {3,5, 20,380,380,380, 20,380,110,224, 110,224,290,224, 290,224,380,380, 10, 0}, // Sierpinsky {2,6,100,250,300,250, 100,250,200,150, 200,150,300,250, 0, 4}, // Dragon {2,8,100,150,300,150, 100,150,200,250, 200,250,300,150, 0, 0}, // Levy {2,8, 20,250,380,250, 20,250,200,130, 152,250,380,250, 6, 0}, // White willow branch {4,5, 80,280,320,280, 80,280, 80,182, 80,182,200,182, 200,182,320,182, 320,182,320,280, 18,0} // 4 map rectangle //---------------------------------------------------------------------------------- // {4,4, 20,250,110,250, 110,250,200,250, // 200,250,290,250, 290,250,380,250, 0, 0} // 4 segments }; void load_set(int n){ stop_the_thread(); maps_number = example_sets[n][0]; seg_number = maps_number+1; points_number = seg_number*2; deep_of_tree = example_sets[n][1]; selected_point= -1; // deselect point hot_point = -1; // deselect point points = new Point[points_number]; connected = new int[points_number]; conjugated = new boolean[seg_number]; reversed = new boolean[seg_number]; maps = new double[points_number][6]; set_colors(); // fill color arrays it_box.select(deep_of_tree-start_it); int i,j; for( i=2,j=0; j>j)&1) != 0; reversed[j] = ((example_sets[n][i+1]>>j)&1) != 0; } select_seg(-1); // deselect any map showStatus("IFS Editor: "+maps_number+" maps generated fractal"); repaint(); } }