HandleReduction.java 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519
  1. import javax.swing.*;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.awt.geom.*;
  5. import java.net.*;
  6. import java.io.*;
  7. import java.applet.*;
  8. class Node {
  9. //*********************************************
  10. //* *
  11. //* This class is needed for the class list. *
  12. //* A Node looks like an element of the list. *
  13. //* *
  14. //*********************************************
  15. private int value; //Value of the Node
  16. private Node next; //The next Node in the list
  17. private Node previous; //The previous Node in the list
  18. public Node(){
  19. value=0;
  20. }
  21. public Node(int _value){
  22. value=_value;
  23. }
  24. public void setValue(int _value){
  25. value=_value;
  26. }
  27. public void setPrevious(Node _previous){
  28. previous=_previous;
  29. }
  30. public void setNext(Node _next){
  31. next=_next;
  32. }
  33. public int getValue(){
  34. return value;
  35. }
  36. public Node getPrevious(){
  37. return previous;
  38. }
  39. public Node getNext(){
  40. return next;
  41. }
  42. }
  43. class List {
  44. //******************************************
  45. //* *
  46. //* This class decribe a bichained list. *
  47. //* I don't use the linkedList of java *
  48. //* because it need use of complex Object. *
  49. //* *
  50. //******************************************
  51. private Node first; //The first Node of the list
  52. private Node last; //The last Node of the list
  53. public Node current; //A Node we play the game of an iterator
  54. public int length; //The length of the list
  55. public List(){
  56. length=0;
  57. }
  58. public Node getFirst(){
  59. return first;
  60. }
  61. public Node getLast(){
  62. return last;
  63. }
  64. public void initCurrent(){
  65. current=first;
  66. }
  67. public void setCurrent(Node _current){
  68. current=_current;
  69. }
  70. public Node getCurrent(){
  71. return current;
  72. }
  73. public boolean isEnd(){
  74. return current==last;
  75. }
  76. public void shift(){
  77. // ---------------------------------------
  78. //| Change the current node with the next |
  79. // ---------------------------------------
  80. current=current.getNext();
  81. }
  82. public void addFirst(int value){
  83. // ----------------------------------------------------
  84. //| Add a Node of value 'value' at the end of the list |
  85. // ----------------------------------------------------
  86. Node node=new Node(value);
  87. if(length==0){
  88. first=node;
  89. last=node;
  90. }
  91. else{
  92. first.setPrevious(node);
  93. node.setNext(first);
  94. first=node;
  95. }
  96. length++;
  97. }
  98. public void addLast(int value){
  99. // ----------------------------------------------------
  100. //| Add a Node of value 'value' at the end of the list |
  101. // ----------------------------------------------------
  102. Node node=new Node(value);
  103. if(length==0){
  104. first=node;
  105. last=node;
  106. }
  107. else{
  108. last.setNext(node);
  109. node.setPrevious(last);
  110. last=node;
  111. }
  112. length++;
  113. }
  114. public Node addBefore(int value){
  115. // -----------------------------------------------------------------
  116. //| Add a Node of value 'value' before the current Node of the list |
  117. //| and return the new Node |
  118. // -----------------------------------------------------------------
  119. Node node=new Node(value);
  120. if(current==first){
  121. first=node;
  122. node.setNext(current);
  123. current.setPrevious(node);
  124. }
  125. else {
  126. Node temp=current.getPrevious();
  127. temp.setNext(node);
  128. node.setPrevious(temp);
  129. current.setPrevious(node);
  130. node.setNext(current);
  131. }
  132. length++;
  133. return node;
  134. }
  135. public Node addAfter(int value){
  136. // ----------------------------------------------------------------
  137. //| Add a Node of value 'value' after the current Node of the list |
  138. //| and return the new Node |
  139. // ----------------------------------------------------------------
  140. Node node=new Node(value);
  141. if(current==last){
  142. last=node;
  143. node.setPrevious(current);
  144. current.setNext(node);
  145. }
  146. else{
  147. Node temp=current.getNext();
  148. temp.setPrevious(node);
  149. node.setNext(temp);
  150. current.setNext(node);
  151. node.setPrevious(current);
  152. }
  153. length++;
  154. return node;
  155. }
  156. public void remove(Node node){
  157. // ----------------------------------
  158. //| Remove the Node node of the list |
  159. // ----------------------------------
  160. if(length!=0){
  161. if(length==1){
  162. length=0;
  163. }
  164. else{
  165. if(node==first){
  166. first=node.getNext();
  167. node=first;
  168. }
  169. else if(node==last){
  170. last=node.getPrevious();
  171. current=last;
  172. }
  173. else{
  174. (node.getPrevious()).setNext(node.getNext());
  175. (node.getNext()).setPrevious(node.getPrevious());
  176. }
  177. length--;
  178. }
  179. }
  180. }
  181. public int value(){
  182. return current.getValue();
  183. }
  184. public int length(){
  185. return length;
  186. }
  187. }
  188. public class HandleReduction extends JApplet implements ActionListener{
  189. //*******************************************************
  190. //* *
  191. //* This class represent the window of the application. *
  192. //* *
  193. //*******************************************************
  194. public static final long serialVersionUID = 0;
  195. private Panel panel; //Will draw graphics on the panel
  196. private JTextField textFieldDraw;
  197. private JTextField textFieldReduce;
  198. private JTextField textFieldCompare1;
  199. private JTextField textFieldCompare2;
  200. private JButton draw;
  201. private JButton reduce;
  202. private JButton compare;
  203. private JButton option;
  204. private JButton startDraw;
  205. private JButton startReduce;
  206. private JButton startCompare;
  207. private JButton applyOption;
  208. private JButton cancelDraw;
  209. private JButton cancelReduce;
  210. private JButton cancelCompare;
  211. private JButton cancelOption;
  212. private JFrame drawFrame;
  213. private JFrame reduceFrame;
  214. private JFrame compareFrame;
  215. private JFrame optionFrame;
  216. private JScrollBar delay;
  217. private JLabel speed;
  218. private JRadioButton continuous;
  219. private JRadioButton stepbystep;
  220. public JLabel currentWord;
  221. public int speedValue=100;
  222. public boolean continuousAnimation=true;
  223. public int speedValue2;
  224. public boolean continuousAnimation2;
  225. public void init(){
  226. panel=new Panel();
  227. panel.setBackground(Color.darkGray);
  228. panel.setBounds(0,20,480,600);
  229. add(panel);
  230. currentWord=new JLabel("No braid word");
  231. currentWord.setBounds(0,0,480,20);
  232. add(currentWord);
  233. draw=new JButton("Draw");
  234. draw.addActionListener(this);
  235. draw.setBounds(0,620,120,20);
  236. add(draw);
  237. reduce=new JButton("Reduce");
  238. reduce.addActionListener(this);
  239. reduce.setBounds(120,620,120,20);
  240. add(reduce);
  241. compare=new JButton("Compare");
  242. compare.addActionListener(this);
  243. compare.setBounds(240,620,120,20);
  244. add(compare);
  245. option=new JButton("Controls");
  246. option.addActionListener(this);
  247. option.setBounds(360,620,120,20);
  248. add(option);
  249. add(new JLabel(""));
  250. }
  251. public void start(){
  252. update(getGraphics());
  253. validate();
  254. }
  255. public void lock(){
  256. draw.setEnabled(false);
  257. reduce.setEnabled(false);
  258. compare.setEnabled(false);
  259. option.setEnabled(false);
  260. }
  261. public void unlock(){
  262. draw.setEnabled(true);
  263. reduce.setEnabled(true);
  264. compare.setEnabled(true);
  265. option.setEnabled(true);
  266. }
  267. public void actionPerformed(ActionEvent event){
  268. // ----------------------------------------------------------
  269. //| Specify what the action on the element of the windows do |
  270. // ----------------------------------------------------------
  271. //===> Draw
  272. If(event.getSource()==draw){
  273. drawFrame=new JFrame("Draw");
  274. drawFrame.setSize(300,105);
  275. drawFrame.setLocationRelativeTo(null);
  276. drawFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  277. drawFrame.setResizable(false);
  278. lock();
  279. JLabel message=new JLabel("Enter a braid word : ");
  280. message.setBounds(5,5,290,20);
  281. textFieldDraw=new JTextField(10);
  282. textFieldDraw.setBounds(5,25,290,20);
  283. textFieldDraw.addActionListener(this);
  284. startDraw=new JButton("Draw");
  285. startDraw.addActionListener(this);
  286. startDraw.setBounds(20,55,120,20);
  287. cancelDraw=new JButton("Cancel");
  288. cancelDraw.addActionListener(this);
  289. cancelDraw.setBounds(160,55,120,20);
  290. drawFrame.add(message);
  291. drawFrame.add(textFieldDraw);
  292. drawFrame.add(startDraw);
  293. drawFrame.add(cancelDraw);
  294. drawFrame.add(new JLabel(""));
  295. drawFrame.setVisible(true);
  296. }
  297. else if(event.getSource()==startDraw){
  298. panel.init(this,speedValue,continuousAnimation);
  299. panel.writeBraidWord(textFieldDraw.getText());
  300. unlock();
  301. drawFrame.dispose();
  302. }
  303. else if(event.getSource()==cancelDraw){
  304. unlock();
  305. drawFrame.dispose();
  306. }
  307. //===> Reduce
  308. else if(event.getSource()==reduce){
  309. reduceFrame=new JFrame("Reduce");
  310. reduceFrame.setSize(300,105);
  311. reduceFrame.setLocationRelativeTo(null);
  312. reduceFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  313. reduceFrame.setResizable(false);
  314. lock();
  315. JLabel message=new JLabel("Enter a braid word : ");
  316. message.setBounds(5,5,290,20);
  317. textFieldReduce=new JTextField(10);
  318. textFieldReduce.setBounds(5,25,290,20);
  319. textFieldReduce.addActionListener(this);
  320. startReduce=new JButton("Reduce");
  321. startReduce.addActionListener(this);
  322. startReduce.setBounds(20,55,120,20);
  323. cancelReduce=new JButton("Cancel");
  324. cancelReduce.addActionListener(this);
  325. cancelReduce.setBounds(160,55,120,20);
  326. reduceFrame.add(message);
  327. reduceFrame.add(textFieldReduce);
  328. reduceFrame.add(startReduce);
  329. reduceFrame.add(cancelReduce);
  330. reduceFrame.add(new JLabel(""));
  331. reduceFrame.setVisible(true);
  332. }
  333. else if(event.getSource()==startReduce){
  334. textFieldReduce.setEnabled(false);
  335. if(!panel.working){
  336. panel.init(this,speedValue,continuousAnimation);
  337. panel.writeBraidWord(textFieldReduce.getText());
  338. panel.working=true;
  339. startReduce.setText("Continue");
  340. startReduce.updateUI();
  341. }
  342. startReduce.setEnabled(false);
  343. boolean red=panel.reduce();
  344. String message;
  345. int ind=panel.indice();
  346. if(red){
  347. if(ind==0){
  348. message="The final word is empty, so your initial braid word \n"+textFieldReduce.getText()+" is trivial.";
  349. }
  350. else{
  351. message="There is no more handle and the final word is nonempty, so your initial braid word\n "+textFieldReduce.getText()+" is not trivial.";
  352. }
  353. JOptionPane.showMessageDialog(null,message);
  354. unlock();
  355. panel.working=false;
  356. reduceFrame.dispose();
  357. }
  358. else{
  359. startReduce.setEnabled(true);
  360. }
  361. }
  362. else if(event.getSource()==cancelReduce){
  363. reduceFrame.dispose();
  364. unlock();
  365. panel.working=false;
  366. }
  367. //===> Compare
  368. else if(event.getSource()==compare){
  369. compareFrame=new JFrame("Compare");
  370. compareFrame.setSize(300,145);
  371. compareFrame.setLocationRelativeTo(null);
  372. compareFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  373. compareFrame.setResizable(false);
  374. lock();
  375. JLabel message1=new JLabel("Enter a first braid word : ");
  376. message1.setBounds(5,5,290,20);
  377. textFieldCompare1=new JTextField(10);
  378. textFieldCompare1.setBounds(5,25,290,20);
  379. JLabel message2=new JLabel("Enter a second braid word : ");
  380. message2.setBounds(5,45,290,20);
  381. textFieldCompare2=new JTextField(10);
  382. textFieldCompare2.setBounds(5,65,290,20);
  383. startCompare=new JButton("Compare");
  384. startCompare.addActionListener(this);
  385. startCompare.setBounds(20,95,120,20);
  386. cancelCompare=new JButton("Cancel");
  387. cancelCompare.addActionListener(this);
  388. cancelCompare.setBounds(160,95,120,20);
  389. compareFrame.add(message1);
  390. compareFrame.add(textFieldCompare1);
  391. compareFrame.add(message2);
  392. compareFrame.add(textFieldCompare2);
  393. compareFrame.add(startCompare);
  394. compareFrame.add(cancelCompare);
  395. compareFrame.add(new JLabel(""));
  396. compareFrame.setVisible(true);
  397. }
  398. else if(event.getSource()==startCompare){
  399. if(!panel.working){
  400. String word1,word2;
  401. word1=textFieldCompare1.getText();
  402. word2=textFieldCompare2.getText();
  403. textFieldCompare1.setEnabled(false);
  404. textFieldCompare2.setEnabled(false);
  405. panel.init(this,speedValue,continuousAnimation);
  406. panel.compare(word1,word2);
  407. startCompare.setText("Continue");
  408. startCompare.updateUI();
  409. }
  410. boolean red;
  411. startCompare.setEnabled(false);
  412. red=panel.reduce();
  413. if(red){
  414. String message;
  415. int ind=panel.indice();
  416. if(ind==0){
  417. message="The final word is empty,\nso your initial braid words "+textFieldCompare1.getText()+" and "+textFieldCompare2.getText()+" are equivalent.";
  418. }
  419. else if(ind>0){
  420. //smaller
  421. message="There is no more handle and the final word is nonempty,\nso your initial braid words "+textFieldCompare1.getText()+" and "+textFieldCompare2.getText()+" are not equivalent.";
  422. }
  423. else{
  424. //larger
  425. message="There is no more handle and the final word is nonempty,\nso your initial braid words "+textFieldCompare1.getText()+" and "+textFieldCompare2.getText()+" are not equivalent.";
  426. }
  427. JOptionPane.showMessageDialog(null,message);
  428. compareFrame.dispose();
  429. panel.working=false;
  430. unlock();
  431. }
  432. else{
  433. startCompare.setEnabled(true);
  434. }
  435. }
  436. else if(event.getSource()==cancelCompare){
  437. compareFrame.dispose();
  438. unlock();
  439. panel.working=false;
  440. }
  441. //===> Option
  442. else if(event.getSource()==option){
  443. optionFrame=new JFrame("Controls");
  444. optionFrame.setSize(300,110);
  445. optionFrame.setLocationRelativeTo(null);
  446. optionFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  447. optionFrame.setResizable(false);
  448. lock();
  449. continuous=new JRadioButton();
  450. stepbystep=new JRadioButton();
  451. ButtonGroup group = new ButtonGroup();
  452. continuous.setText("Continuous");
  453. stepbystep.setText("Step-by-step");
  454. continuous.addActionListener(this);
  455. stepbystep.addActionListener(this);
  456. continuousAnimation2=continuousAnimation;
  457. speedValue2=speedValue;
  458. if(continuousAnimation){
  459. continuous.setSelected(true);
  460. }
  461. else{
  462. stepbystep.setSelected(true);
  463. }
  464. group.add(continuous);
  465. group.add(stepbystep);
  466. JLabel label1=new JLabel("Mode :");
  467. delay=new JScrollBar(JScrollBar.HORIZONTAL,speedValue,0,0,100);
  468. delay.addAdjustmentListener(new java.awt.event.AdjustmentListener(){
  469. public void adjustmentValueChanged(AdjustmentEvent event){
  470. scrollBarValueChanged(event);
  471. }
  472. });
  473. speed=new JLabel("Speed : "+speedValue);
  474. label1.setBounds(5,5,60,20);
  475. continuous.setBounds(65,5,100,20);
  476. stepbystep.setBounds(165,5,120,20);
  477. speed.setBounds(5,30,80,20);
  478. delay.setBounds(85,30,200,20);
  479. applyOption=new JButton("Apply");
  480. applyOption.addActionListener(this);
  481. applyOption.setBounds(20,60,120,20);
  482. cancelOption=new JButton("Cancel");
  483. cancelOption.addActionListener(this);
  484. cancelOption.setBounds(160,60,120,20);
  485. optionFrame.add(label1);
  486. optionFrame.add(continuous);
  487. optionFrame.add(stepbystep);
  488. optionFrame.add(speed);
  489. optionFrame.add(delay);
  490. optionFrame.add(applyOption);
  491. optionFrame.add(cancelOption);
  492. optionFrame.add(new JLabel(""));
  493. optionFrame.setVisible(true);
  494. }
  495. else if(event.getSource()==continuous){
  496. if(continuous.isSelected()){
  497. continuousAnimation2=true;
  498. }
  499. }
  500. else if(event.getSource()==stepbystep){
  501. if(stepbystep.isSelected()){
  502. continuousAnimation2=false;
  503. }
  504. }
  505. else if(event.getSource()==applyOption){
  506. continuousAnimation=continuousAnimation2;
  507. speedValue=speedValue2;
  508. unlock();
  509. optionFrame.dispose();
  510. }
  511. else if(event.getSource()==cancelOption){
  512. optionFrame.dispose();
  513. unlock();
  514. }
  515. }
  516. public void scrollBarValueChanged(AdjustmentEvent event){
  517. if(event.getSource()==delay){
  518. speedValue2=delay.getValue();
  519. speed.setText("Speed : "+speedValue2);
  520. }
  521. }
  522. public String getAppletInfo() {
  523. return "Handle reduction algorithm.";
  524. }
  525. }
  526. class Pause extends Thread{
  527. //*********************************
  528. //* *
  529. //* This class pause the program. *
  530. //* *
  531. //*********************************
  532. public void pause(int delayValue){
  533. try {
  534. sleep(delayValue);
  535. }
  536. catch (InterruptedException ex) {}
  537. }
  538. }
  539. class Panel extends JPanel{
  540. //************************************************
  541. //* *
  542. //* This class is the key class of this program. *
  543. //* It contains algoritms and drawing tools. *
  544. //* *
  545. //************************************************
  546. public static final long serialVersionUID = 0;
  547. //Word variable
  548. private HandleReduction myWindow;
  549. private JLabel currentBraidWord;
  550. //=====> Braid variable
  551. private String braidWord; //The initial braid word
  552. private boolean braidWordSet=false;
  553. private List braid; //The braid word as a list
  554. public String currentWord="";
  555. public boolean working=false;
  556. private String compareWord1;
  557. private String compareWord2;
  558. //=====> Strand variable
  559. private int strandNumber=5; //The number of strand
  560. private float strandStep; //The distance between two strand
  561. private float strandWidth; //The width of a strand
  562. private float strandLeft; //The x position of the leftmost strand
  563. private float[] xPos; //The x postion of strands
  564. private float[] xPosNext; //The next x position of strands
  565. private float yUp; //The y position of the first element of the braid
  566. //=====> Handle variable
  567. private Node handleBegin; //The first node of the handle
  568. private Node handleEnd; //The last node of the handle
  569. private int handleStrand; //The current strand of the handle
  570. private int handleType; //The type of the handle, is 1 if the handle start with a positive element
  571. private boolean handleNormalDraw; //This variable is true if we draw the handle with the classic metod
  572. private boolean onHandle; //This variable is true if we are in between the handleBegin Node and the handleEnd node
  573. private float handleBeginYPos; //The y position of the begin of the handle
  574. private float handleEndYPos; //The y position of the end of the handle
  575. //======> Trivial variable
  576. private int trivialNumber; //The number of trivial element without the extremity
  577. private float trivialHeight; //The height of a trivial element
  578. //======> Animation variable
  579. private int animationStep; //The current animation step
  580. private float parameterAnimationStep2; // \
  581. private float parameterAnimationStep4; // | Parameters for the animation
  582. private float parameterAnimationStep5; // /
  583. private boolean continuousAnimation;
  584. private int delayValue;
  585. private Pause pause=new Pause(); //For make pause during animation
  586. //======> Color variable
  587. private Color[] strandColor; //The color of different strand
  588. private Color handleColor=Color.black; //The color of the handle
  589. private Color originalHandleStrandColor; //The original color of the handle strand
  590. //======> Way variable
  591. private GeneralPath[] continuousWay; //The currant continuous way of strands
  592. //======> Double Buffering variable
  593. private Image offScreenBuffer; //A buffer in wich we draw and after drawing we will show this buffer
  594. private boolean isDraw; //For not repeat drawing
  595. // =================
  596. //I I
  597. //I Braid functions I
  598. //I I
  599. // =================
  600. private void initBraid(){
  601. // -----------------------------------------------------
  602. //| Iniliasition of braid as a list and of strandNumber |
  603. // -----------------------------------------------------
  604. int length;
  605. int value;
  606. char letter;
  607. strandNumber=2;
  608. value=0;
  609. braid=new List();
  610. length=braidWord.length(); //get the length of the braid word
  611. braid.addLast(0); //add a trivial at the begin
  612. for(int i=0;i<length;i++){
  613. letter=braidWord.charAt(i);
  614. if(letter>='a' && letter<='z'){ //if we have a lower case letter
  615. value=(int)(letter-'a')+1; //value is 1 for 'a', 2 for 'b', ...
  616. if(value+1>strandNumber){ //update the strand number
  617. strandNumber=value+1;
  618. }
  619. }
  620. else if(letter>='A' && letter<='Z'){ //if we have an upper case letter
  621. value=-(int)(letter-'A')-1; //value is -1 for 'A', -2 for 'B', ...
  622. if(-value+1>strandNumber){ //update the strand number
  623. strandNumber=-value+1;
  624. }
  625. }
  626. else{
  627. value=0;
  628. }
  629. braid.addLast(value); //add the value at the list of the braid
  630. }
  631. braid.addLast(0); //add a trivial at th end
  632. }
  633. public void init(HandleReduction _myWindow,int _delayValue,boolean _continuousAnimation){
  634. myWindow=_myWindow;
  635. delayValue=100-_delayValue;
  636. continuousAnimation=_continuousAnimation;
  637. }
  638. public void writeBraidWord(String buffer){
  639. // -----------------------------------------------------
  640. //| Initialise the braid word and some other parameters |
  641. //------------------------------------------------------
  642. braidWord=buffer;
  643. initBraid(); //initialise the braid list
  644. animationStep=0; //initialise the animation step
  645. trivialNumber=0; // \
  646. trivialHeight=0; // Initilise the trivial parameters
  647. handleNormalDraw=true; //we draw the handle with the classic method for the moment
  648. updateCurrentBraidWord();
  649. braidWordSet=true;
  650. isDraw=false; //we draw a new image
  651. update(super.getGraphics()); //update draw
  652. }
  653. public void compare(String word1, String word2){
  654. int length;
  655. int value;
  656. char letter;
  657. compareWord1=word1;
  658. compareWord2=word2;
  659. strandNumber=2;
  660. value=0;
  661. braid=new List();
  662. length=word2.length(); //get the length of the braid word
  663. for(int i=0;i<length;i++){
  664. letter=word2.charAt(i);
  665. if(letter>='a' && letter<='z'){ //if we have a lower case letter
  666. value=(int)(letter-'a')+1; //value is 1 for 'a', 2 for 'b', ...
  667. if(value+1>strandNumber){ //update the strand number
  668. strandNumber=value+1;
  669. }
  670. }
  671. else if(letter>='A' && letter<='Z'){ //if we have an upper case letter
  672. value=-(int)(letter-'A')-1; //value is -1 for 'A', -2 for 'B', ...
  673. if(-value+1>strandNumber){ //update the strand number
  674. strandNumber=-value+1;
  675. }
  676. }
  677. else{
  678. value=24;
  679. }
  680. braid.addLast(value); //add the value at the list of the braid
  681. }
  682. braid.addLast(0);
  683. length=word1.length();
  684. for(int i=0;i<length;i++){
  685. letter=word1.charAt(i);
  686. if(letter>='a' && letter<='z'){
  687. value=-(int)(letter-'a')-1;
  688. if(-value+1>strandNumber){
  689. strandNumber=-value+1;
  690. }
  691. }
  692. else if(letter>='A' && letter<='Z'){
  693. value=(int)(letter-'A')+1;
  694. if(value+1>strandNumber){
  695. strandNumber=value+1;
  696. }
  697. }
  698. else{
  699. value=24;
  700. }
  701. braid.addFirst(value);
  702. }
  703. braid.addFirst(0);
  704. animationStep=0;
  705. trivialNumber=0;
  706. trivialHeight=0;
  707. handleNormalDraw=true;
  708. updateCurrentBraidWord();
  709. braidWordSet=true;
  710. isDraw=false; //we draw a new image
  711. working=true;
  712. update(super.getGraphics()); //update draw
  713. }
  714. public void updateCurrentBraidWord(){
  715. boolean stop;
  716. int value;
  717. String res="";
  718. braid.initCurrent();
  719. stop=false;
  720. while(!stop){
  721. value=braid.value();
  722. if(value>0){
  723. res+=(char)((value-1)+'a');
  724. }
  725. else if(value<0){
  726. res+=(char)((-value-1)+'A');
  727. }
  728. if(braid.isEnd()){
  729. stop=true;
  730. }
  731. if(!stop){
  732. braid.shift();
  733. }
  734. }
  735. if(res==""){
  736. res="1";
  737. }
  738. currentWord=res;
  739. (myWindow.currentWord).setText("Current braid word: "+res);
  740. myWindow.update(myWindow.getGraphics());
  741. myWindow.validate();
  742. }
  743. // ===============================
  744. //I I
  745. //I Handle reduction algorithms I
  746. //I I
  747. // ===============================
  748. public void findHandle(){
  749. // -----------------------------------
  750. //| Search a handle in the braid word |
  751. //| with no intricated handle |
  752. // -----------------------------------
  753. Node handles[]=new Node[strandNumber]; //We stock information of potential handle
  754. int signs[]=new int[strandNumber]; //We stock the sign of the last n generato in signs[n];
  755. int sign,value;
  756. boolean stop; //A flag for stop the main while
  757. for(int i=0;i<strandNumber;i++){
  758. signs[i]=0;
  759. }
  760. stop=false;
  761. value=0;
  762. sign=0;
  763. braid.initCurrent(); //Initiliastion of braid current
  764. while(!stop){
  765. value=braid.value();
  766. sign=1;
  767. if(value<0){ //We compte the sign
  768. value=-value;
  769. sign=-1;
  770. }
  771. else if(value==0){
  772. sign=0;
  773. }
  774. if(signs[value]*sign<0){ //We have found the first handle with no imbricated handle
  775. stop=true;
  776. }
  777. else{
  778. signs[value]=sign; //Update signs
  779. handles[value]=braid.getCurrent(); //Update value
  780. for(int j=1;j<value;j++){ //Clear the potentialy imbricated handle
  781. signs[j]=0;
  782. }
  783. }
  784. if(braid.isEnd()){ //End of the braid ?
  785. stop=true;
  786. }
  787. if(!stop){ //Restart with the ext generator
  788. braid.shift();
  789. }
  790. }
  791. if(signs[value]*sign<0){ //If we have found a handle
  792. handleBegin=handles[value];
  793. handleEnd=braid.getCurrent();
  794. handleStrand=value;
  795. handleType=-sign;
  796. }
  797. else{
  798. handleStrand=0; //If we haven't found handle
  799. }
  800. }
  801. private void insertTrivials(){
  802. // -----------------------------------------------------
  803. //| This fonction insert trivials generato in the braid |
  804. //| in order to make some space for the animation. |
  805. // -----------------------------------------------------
  806. int value;
  807. boolean stop;
  808. stop=false;
  809. braid.setCurrent(handleBegin); //We start at the begin of the handle
  810. trivialNumber=0;
  811. while(!stop){
  812. value=braid.value();
  813. if(Math.abs(value)==handleStrand-1){ //If the generator is handleStrand-1 or -(handleStrand-1)
  814. braid.addBefore(0); //We add a trivial before
  815. braid.setCurrent(braid.addAfter(0)); //We add a trivial after
  816. trivialNumber+=2; //Update the number of trivials
  817. }
  818. braid.shift();
  819. if(braid.getCurrent()==handleEnd){ //If we are at the end of the handlee
  820. stop=true; //we stop the main while
  821. }
  822. }
  823. }
  824. public void removeHandle(){
  825. // -------------------------------------------
  826. //| This function remove the handle was found |
  827. // -------------------------------------------
  828. int sign;
  829. int value;
  830. boolean stop;
  831. sign=-handleType; //sign is a variable for alternating sign of new handleStrand generator
  832. stop=false;
  833. braid.setCurrent(handleBegin); //We strat at the begin of the handle
  834. while(!stop){
  835. value=braid.value();
  836. if(Math.abs(value)==handleStrand){ //If the generator is handleStrand or -handleStrand
  837. (braid.getCurrent()).setValue(0); //we replace it with a trivial generator
  838. }
  839. if(value==0){
  840. (braid.getCurrent()).setValue((handleStrand-1)*sign); //If the generator is a trivial we replace it
  841. sign=-sign; //with (handleStrand-1)*sign
  842. }
  843. if(value==handleStrand-1){ //If the genertaor is handleStrand-1
  844. (braid.getCurrent()).setValue(value+1); //we replace it with handleStrand
  845. }
  846. if(value==-(handleStrand-1)){ //If the generator is -(handleStand-1)
  847. (braid.getCurrent()).setValue(value-1); //we replace it with -handleStrand
  848. }
  849. if(braid.getCurrent()==handleEnd){ //If we are at he end of te endle
  850. stop=true; //we stop the main while
  851. }
  852. else{
  853. braid.shift(); //else we restart with the next generator
  854. }
  855. }
  856. trivialNumber=2; //At the end trivial numbers must be 2
  857. }
  858. private void removeTrivials(){
  859. // -------------------------------------------
  860. //| Remove the not extreme trivials generator |
  861. // -------------------------------------------
  862. braid.remove(handleBegin);
  863. braid.remove(handleEnd);
  864. trivialNumber=0;
  865. }
  866. public int indice(){
  867. int value;
  868. int indice=0;
  869. boolean stop=false;
  870. braid.initCurrent();
  871. while(!stop){
  872. value=braid.value();
  873. if(Math.abs(value)>Math.abs(indice)){
  874. indice=value;
  875. }
  876. if(braid.isEnd()){
  877. stop=true;
  878. }
  879. else{
  880. braid.shift();
  881. }
  882. }
  883. return indice;
  884. }
  885. // =================
  886. //I I
  887. //I Color functions I
  888. //I I
  889. // =================
  890. public void initStrandColor(){
  891. // ---------------------------
  892. //| Init the color of strands |
  893. // ---------------------------
  894. strandColor=new Color[strandNumber]; //Make the table of strand color
  895. for(int strand=1;strand<strandNumber+1;strand++){
  896. if(strandNumber<10){
  897. strandColor[strand-1]=Color.getHSBColor((float)1-(float)strand/(float)10,(float)0.8,1);
  898. }
  899. else {
  900. strandColor[strand-1]=Color.getHSBColor((float)1-(float)strand/(float)strandNumber,(float)0.8,1);
  901. }
  902. }
  903. }
  904. // ==================
  905. //I I
  906. //I Handle functions I
  907. //I I
  908. // ==================
  909. public void colorizeHandle(Graphics2D g,float yPos){
  910. // --------------------------------------
  911. //| Colorize the handle if we are on her |
  912. // --------------------------------------
  913. if(handleStrand!=0){ //We verify we have found a handle
  914. if(braid.getCurrent()==handleBegin){ //If we are at the begin of the handle
  915. handleBeginYPos=yPos; //Initialize the y position of the begin of the handle
  916. onHandle=true; //We are on the handle
  917. closeContinuousWay(g,handleStrand); //Close the conitnuous way of handleStrand
  918. originalHandleStrandColor=strandColor[handleStrand-1]; //Save the original color of the strand handleStrand
  919. strandColor[handleStrand-1]=handleColor; //Change color of the strand handleStrand
  920. continuousWay[handleStrand-1].moveTo(xPos[handleStrand-1],yPos); //Start position of the new continuous way of handleStrand
  921. }
  922. else if(braid.getCurrent()==handleEnd.getNext()){ //If we are at the end of the handle
  923. handleEndYPos=yPos; //Initailaize the y position of the end of the handle
  924. closeContinuousWay(g,handleStrand); //Close the continuous way of handleStrand
  925. strandColor[handleStrand-1]=originalHandleStrandColor; //The original color of strand handleStrand
  926. continuousWay[handleStrand-1].moveTo(xPos[handleStrand-1],yPos); //Start position of the new continuous way
  927. onHandle=false; //We are no longer in the handle
  928. }
  929. }
  930. }
  931. public void changeHandleStrand(int generator){
  932. // ------------------------------------------------------
  933. //| Update the value of the strand on wich the handle is |
  934. // ------------------------------------------------------
  935. if(handleStrand!=0 && onHandle){
  936. if(generator==handleStrand){
  937. handleStrand++;
  938. }
  939. else if(generator+1==handleStrand){
  940. handleStrand--;
  941. }
  942. }
  943. }
  944. // ==========================
  945. //I I
  946. //I Continuous way functions I
  947. //I I
  948. // ==========================
  949. public void initContinuousWay(){
  950. // -----------------------------------------
  951. //| Start the continuous way for all strand |
  952. // -----------------------------------------
  953. continuousWay=new GeneralPath[strandNumber]; //Make the table of continuous way
  954. xPos=new float[strandNumber]; //Make the table of x position of strands
  955. xPosNext=new float[strandNumber]; //Make the table of next x position of strands
  956. for(int strand=1;strand<strandNumber+1;strand++){
  957. continuousWay[strand-1]=new GeneralPath();
  958. xPos[strand-1]=strandLeft+strand*strandStep; //The xPos of n is strandLeft+n*strandStep
  959. continuousWay[strand-1].moveTo(xPos[strand-1],yUp); //Start the continuous way at the y position yUp
  960. }
  961. }
  962. public void closeContinuousWay(Graphics2D g,int strand){
  963. // -------------------------------------------
  964. //| Stop and draw the continous way of strand |
  965. // -------------------------------------------
  966. GeneralPath gp;
  967. gp=continuousWay[strand-1];
  968. g.setColor(strandColor[strand-1]); //Apply the color of strand
  969. if(strand!=handleStrand || handleNormalDraw || strandColor[handleStrand-1]!=handleColor){
  970. //We verify we must draw the continuous way or not
  971. //We don't draw this way if we are on the handle and the value of handleNormalDraw is 0
  972. g.draw(gp);
  973. }
  974. gp=new GeneralPath(); //Make a new general path
  975. continuousWay[strand-1]=gp; //Start the new continuous way
  976. }
  977. public void permuteContinuousWay(int strand){
  978. // -----------------------------------------------------------------
  979. //| Echange the continuous way and the color of strand and strand+1 |
  980. // -----------------------------------------------------------------
  981. GeneralPath gp;
  982. Color color;
  983. //Echange continuous way
  984. gp=continuousWay[strand-1];
  985. continuousWay[strand-1]=continuousWay[strand];
  986. continuousWay[strand]=gp;
  987. //Echange color
  988. color=strandColor[strand-1];
  989. strandColor[strand-1]=strandColor[strand];
  990. strandColor[strand]=color;
  991. }
  992. // ================
  993. //I I
  994. //I Math functions I
  995. //I I
  996. // ================
  997. public double min(double a,double b){
  998. if(a<b){
  999. return a;
  1000. }
  1001. else{
  1002. return b;
  1003. }
  1004. }
  1005. public double max(double a,double b){
  1006. if(a>b){
  1007. return a;
  1008. }
  1009. else{
  1010. return b;
  1011. }
  1012. }
  1013. public double square(double a){
  1014. return a*a;
  1015. }
  1016. // ===================
  1017. //I I
  1018. //I Position function I
  1019. //I I
  1020. // ===================
  1021. public void calcXPosNext(){
  1022. // ----------------------------------------
  1023. //| Compute the nex x position of strands. |
  1024. //| It's a key function for animation. |
  1025. // ----------------------------------------
  1026. for(int strand=0;strand<strandNumber;strand++){
  1027. xPosNext[strand]=strandLeft+(strand+1)*strandStep; //The general case
  1028. }
  1029. if(braid.getCurrent()==handleBegin){ //If we have at the begin of the handle
  1030. if(animationStep==2){ //If the step of animation is 2
  1031. xPosNext[handleStrand]=(strandLeft+(handleStrand+parameterAnimationStep2)*strandStep);
  1032. }
  1033. else if(animationStep==4){ //If the step ofanimation is 4
  1034. xPosNext[handleStrand-1]+=parameterAnimationStep4*(float)strandStep;
  1035. }
  1036. }
  1037. else if(braid.getCurrent()==handleEnd){ //If we are at the end of the handle
  1038. }
  1039. else if(onHandle){ //If we are on the interior of the handle
  1040. if(animationStep==2){ //If the step of animation is 2
  1041. xPosNext[handleStrand-1]=(strandLeft+(handleStrand+parameterAnimationStep2-1)*strandStep);
  1042. }
  1043. else if(animationStep==4){ //If the step of animation is 4
  1044. xPosNext[handleStrand-2]+=parameterAnimationStep4*(float)strandStep;
  1045. if(Math.abs(((braid.getCurrent()).getNext()).getValue())==handleStrand-2 ||
  1046. Math.abs((braid.getCurrent()).getValue())==handleStrand-2){
  1047. xPosNext[handleStrand-3]+=parameterAnimationStep4*(float)strandStep;
  1048. }
  1049. }
  1050. else if(animationStep==5){ //If the step of animation is 5
  1051. if(Math.abs((braid.getCurrent()).getValue())==handleStrand-1){
  1052. xPosNext[handleStrand-2]+=parameterAnimationStep5*(float)strandStep;
  1053. }
  1054. else if(Math.abs((braid.getCurrent()).getValue())==handleStrand+1){
  1055. xPosNext[handleStrand-1]+=parameterAnimationStep5*(float)strandStep;
  1056. }
  1057. }
  1058. }
  1059. }
  1060. public void updateXPos(){
  1061. // ------------------------------------------------------------------
  1062. //| Update the x postion of strand with the nex x position of strand |
  1063. // ------------------------------------------------------------------
  1064. for(int strand=0;strand<strandNumber;strand++){
  1065. xPos[strand]=xPosNext[strand];
  1066. }
  1067. }
  1068. public float[] calculIntersection(int strand,float yPos,int type){
  1069. // -----------------------------------------------------------------------
  1070. //| Compute the two key point for draw the generator strand |
  1071. // -----------------------------------------------------------------------
  1072. float []res=new float[4];
  1073. //res[0]<=res[1] is the x position of this points
  1074. //res[2]<=res[3] is the y position of this points
  1075. if(!handleNormalDraw && braid.getCurrent()==handleBegin){
  1076. //If we are at the begin of handle and then handleNormal draw is 0 we send special values
  1077. res[0]=xPosNext[strand-1];
  1078. res[1]=xPosNext[strand-1];
  1079. res[2]=yPos+strandStep;
  1080. res[3]=yPos+strandStep;
  1081. return res;
  1082. }
  1083. else if(!handleNormalDraw && braid.getCurrent()==handleEnd){
  1084. //If we are at the end of handle and then handleNormal draw is 0 we send special value
  1085. res[0]=xPosNext[strand];
  1086. res[1]=xPosNext[strand];
  1087. res[2]=yPos+strandStep;
  1088. res[3]=yPos+strandStep;
  1089. return res;
  1090. }
  1091. else{
  1092. double decale=1.5*strandWidth; //Is distance of a strand with the other in the crossing
  1093. double distance;
  1094. if(type==1){ //If the crossing is positive
  1095. //We compute the distance between the left-up point and then right-down
  1096. distance=Math.sqrt(square(xPosNext[strand]-xPos[strand-1])+square(strandStep));
  1097. }
  1098. else { //If the crossing is negative
  1099. //We compute the distance between the right-up and the left-down
  1100. distance=Math.sqrt(square(xPos[strand]-xPosNext[strand-1])+square(strandStep));
  1101. }
  1102. double alpha=Math.acos(strandStep/distance); //The angle of the crossing
  1103. double decalX=Math.sin(alpha)*decale; //The x coords of decale
  1104. double decalY=Math.cos(alpha)*decale; //The y coords of decale
  1105. //The straight line D1 of equation x=m1*y+p1 contains the left-up and the right-down point
  1106. double m1=((double)strandStep)/((double)(xPosNext[strand]-xPos[strand-1]));
  1107. double p1=yPos-m1*((double)xPos[strand-1]);
  1108. //The straight line D2 of equation x=m2*y+p2 contains the right-up and the left-down point
  1109. double m2=((double)strandStep)/((double)(xPosNext[strand-1]-xPos[strand]));
  1110. double p2=yPos-m2*((double)xPos[strand]);
  1111. double xInter=(p2-p1)/(m1-m2); //x coord of D1 inter D2
  1112. double yInter=m1*xInter+p1; //y coord of D1 inter D2
  1113. //Computaion of values of res, the min and max fonction are usefull for a good drawing
  1114. res[0]=(float)max(xInter-decalX,xPosNext[strand-1]);
  1115. res[1]=(float)min(xInter+decalX,xPosNext[strand]);
  1116. res[2]=(float)max(yInter-decalY,yPos);
  1117. res[3]=(float)min(yInter+decalY,yPos+strandStep);
  1118. return res;
  1119. }
  1120. }
  1121. // ===================
  1122. //I I
  1123. //I Drawing functions I
  1124. //I I
  1125. // ===================
  1126. public void drawHandle(Graphics2D g){
  1127. // -------------------------------------------
  1128. //| Draw the handle if handleNormal draw is 0 |
  1129. // -------------------------------------------
  1130. GeneralPath gp=new GeneralPath();
  1131. gp.moveTo(strandLeft+handleStrand*strandStep,handleBeginYPos);
  1132. gp.lineTo(strandLeft+handleStrand*strandStep,handleEndYPos);
  1133. g.setColor(handleColor); //Apply the color of the handle
  1134. g.draw(gp);
  1135. }
  1136. public void drawTrivial(float yPos){
  1137. // -------------------------------------
  1138. //| Draw a not extrem trivial generator |
  1139. // -------------------------------------
  1140. for(int strand=0;strand<strandNumber;strand++){
  1141. continuousWay[strand].lineTo(xPosNext[strand],yPos+trivialHeight*strandStep);
  1142. }
  1143. }
  1144. public void drawNoCrossing(Graphics2D g,int strand,float yPos){
  1145. // ----------------------
  1146. //| Draw straight strand |
  1147. // ----------------------
  1148. continuousWay[strand-1].lineTo(xPosNext[strand-1],yPos+strandStep);
  1149. }
  1150. public void drawPositiveCrossing(Graphics2D g,int strand,float yPos){
  1151. // --------------------------
  1152. //| Draw a positive crossing |
  1153. // --------------------------
  1154. float inter[]=calculIntersection(strand,yPos,1);
  1155. continuousWay[strand-1].lineTo(inter[0],inter[2]);
  1156. closeContinuousWay(g,strand);
  1157. continuousWay[strand-1].moveTo(inter[1],inter[3]);
  1158. continuousWay[strand-1].lineTo(xPosNext[strand],yPos+strandStep);
  1159. continuousWay[strand].lineTo(xPosNext[strand-1],yPos+strandStep);
  1160. permuteContinuousWay(strand);
  1161. }
  1162. public void drawNegativeCrossing(Graphics2D g,int strand,float yPos){
  1163. // --------------------------
  1164. //| Draw a negative crossing |
  1165. // --------------------------
  1166. float inter[]=calculIntersection(strand,yPos,-1);
  1167. continuousWay[strand].lineTo(inter[1],inter[2]);
  1168. closeContinuousWay(g,strand+1);
  1169. continuousWay[strand].moveTo(inter[0],inter[3]);
  1170. continuousWay[strand].lineTo(xPosNext[strand-1],yPos+strandStep);
  1171. continuousWay[strand-1].lineTo(xPosNext[strand],yPos+strandStep);
  1172. permuteContinuousWay(strand);
  1173. }
  1174. public void draw(Graphics g){
  1175. // --------------------------------------------
  1176. //| The main and first called drawing function |
  1177. // --------------------------------------------
  1178. Graphics2D g2=(Graphics2D) g; //A Graphics2D context is needed
  1179. Rectangle r;
  1180. int generator; //The absolute value of generator
  1181. int exponent; //The sign of generator 1 or -1
  1182. float yPos; //The current y position
  1183. r=getBounds(); //The dimension of the graphics window
  1184. g.setColor(Color.darkGray); //Background color
  1185. g.clearRect(0,0,r.width,r.height); //Clear the drawing window
  1186. g.drawRect(0,0,r.width-1,r.height-1); //Aply background color
  1187. //Defintion of some strand parameter
  1188. strandStep=(float)min((double)r.width/(double)(strandNumber+1),(double)r.height/((double)(braid.length())-((double)1-(double)trivialHeight)*(double)trivialNumber));
  1189. strandWidth=strandStep/(float)5;
  1190. strandLeft=((float)r.width-((float)(strandNumber+1)*(float)strandStep+strandWidth))/(float)2;
  1191. yUp=(float)max((double)0,(double)((double)r.height-(double)strandStep*((double)(braid.length())-((double)1-(double)trivialHeight)*(double)trivialNumber))/(double)2);
  1192. braid.initCurrent(); //Set current as braid.first
  1193. initStrandColor(); //Init the strand color
  1194. initContinuousWay(); //Init then continuous way
  1195. g2.setStroke(new BasicStroke(strandWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_BEVEL)); //Type of general path
  1196. yPos=yUp; //Init current y position
  1197. int stop=0; //stop is a flag for break the main while
  1198. if(!handleNormalDraw && handleType==1){
  1199. //If handleNormalDraw is 0 and hande type is 1 we draw the handle first
  1200. drawHandle(g2);
  1201. }
  1202. while(stop==0){
  1203. generator=braid.value(); //Get braid value
  1204. exponent=1;
  1205. if(generator<0){ // \
  1206. exponent=-1; // Computation of generato and exponent
  1207. generator=-generator; // /
  1208. }
  1209. colorizeHandle(g2,yPos);
  1210. calcXPosNext();
  1211. if(onHandle && generator==0){ //If the generator is trivial and we are on the handle
  1212. drawTrivial(yPos);
  1213. yPos+=trivialHeight*strandStep; //Update yPos
  1214. }
  1215. else{
  1216. for(int strand=1;strand<strandNumber+1;strand++){
  1217. if(strand==generator && exponent==1){ //If the generator is positive
  1218. drawPositiveCrossing(g2,strand,yPos);
  1219. strand++;
  1220. }
  1221. else if(strand==generator && exponent==-1){ //If the generato is negative
  1222. drawNegativeCrossing(g2,strand,yPos);
  1223. strand++;
  1224. }
  1225. else{
  1226. drawNoCrossing(g2,strand,yPos);
  1227. }
  1228. }
  1229. changeHandleStrand(generator); //Update handle strand
  1230. yPos+=strandStep; //Update yPos
  1231. }
  1232. if(braid.isEnd()){ //Are we at the end of the braid ?
  1233. stop=1;
  1234. }
  1235. else{
  1236. braid.shift();
  1237. }
  1238. updateXPos(); //Update xPos
  1239. } //Restart with the new generator
  1240. for(int strand=1;strand<strandNumber+1;strand++){
  1241. closeContinuousWay(g2,strand); //Close the continuous way
  1242. }
  1243. if(!handleNormalDraw && handleType==-1){
  1244. //If handleNormalDraw is 0 and hande type is 1 we draw the handle last
  1245. drawHandle(g2);
  1246. }
  1247. }
  1248. // ===================
  1249. //I I
  1250. //I Graphics function I
  1251. //I I
  1252. // ===================
  1253. public void paint(Graphics g){
  1254. if(!isDraw){
  1255. update(g);
  1256. isDraw=true;
  1257. }
  1258. else{
  1259. g.drawImage(offScreenBuffer,0,0,this);
  1260. }
  1261. }
  1262. public void update(Graphics g) {
  1263. // -----------------------------------------------
  1264. //| Graphic update function with double-buffering |
  1265. // -----------------------------------------------
  1266. if(braidWordSet){
  1267. Graphics gr;
  1268. if (offScreenBuffer==null||(!(offScreenBuffer.getWidth(this)==getBounds().width && offScreenBuffer.getHeight(this)==getBounds().height))){
  1269. offScreenBuffer=this.createImage(getBounds().width,getBounds().height);
  1270. }
  1271. gr=offScreenBuffer.getGraphics();
  1272. draw(gr);
  1273. g.drawImage(offScreenBuffer,0,0,this);
  1274. }
  1275. }
  1276. // ====================
  1277. //I I
  1278. //I Animation function I
  1279. //I I
  1280. // ====================
  1281. public boolean reduce(){
  1282. if(!braidWordSet){
  1283. JOptionPane.showMessageDialog(null,"You must enter a braid word first ! ","Error",JOptionPane.ERROR_MESSAGE);
  1284. return true;
  1285. }
  1286. else if(animationStep==0){
  1287. findHandle();
  1288. update(getGraphics());
  1289. if(handleStrand==0){
  1290. //update(getGraphics());
  1291. return true;
  1292. }
  1293. else{
  1294. update(getGraphics());
  1295. insertTrivials();
  1296. trivialHeight=0;
  1297. animationStep=1;
  1298. handleNormalDraw=true;
  1299. if(continuousAnimation){
  1300. return reduce();
  1301. }
  1302. else{
  1303. return false;
  1304. }
  1305. }
  1306. }
  1307. else if(animationStep==1){
  1308. if(trivialHeight>=1){
  1309. trivialHeight=1;
  1310. parameterAnimationStep2=1;
  1311. animationStep=2;
  1312. pause.pause(delayValue);
  1313. return reduce();
  1314. }
  1315. else{
  1316. trivialHeight+=0.1;
  1317. update(getGraphics());
  1318. pause.pause(delayValue);
  1319. return reduce();
  1320. }
  1321. }
  1322. else if(animationStep==2){
  1323. if(handleStrand==0){
  1324. return true;
  1325. }
  1326. else if(parameterAnimationStep2<(float)(1.25)*((float)strandWidth/strandStep)){
  1327. handleNormalDraw=false;
  1328. animationStep=3;
  1329. pause.pause(delayValue);
  1330. return reduce();
  1331. }
  1332. else{
  1333. parameterAnimationStep2-=(float)0.05;
  1334. update(getGraphics());
  1335. pause.pause(delayValue);
  1336. return reduce();
  1337. }
  1338. }
  1339. else if(animationStep==3){
  1340. parameterAnimationStep4=0;
  1341. animationStep=4;
  1342. update(getGraphics());
  1343. pause.pause(delayValue);
  1344. return reduce();
  1345. }
  1346. else if(animationStep==4){
  1347. if(parameterAnimationStep4>=1){
  1348. removeHandle();
  1349. handleNormalDraw=true;
  1350. parameterAnimationStep5=1-(float)(1.25)*((float)strandWidth/strandStep);
  1351. animationStep=5;
  1352. pause.pause(delayValue);
  1353. return reduce();
  1354. }
  1355. else{
  1356. parameterAnimationStep4+=(float)0.05;
  1357. update(getGraphics());
  1358. pause.pause(delayValue);
  1359. return reduce();
  1360. }
  1361. }
  1362. else if(animationStep==5){
  1363. if(parameterAnimationStep5<=(float)0.05){
  1364. parameterAnimationStep5=0;
  1365. animationStep=6;
  1366. pause.pause(delayValue);
  1367. return reduce();
  1368. }
  1369. else{
  1370. parameterAnimationStep5-=(float)0.05;
  1371. update(getGraphics());
  1372. pause.pause(delayValue);
  1373. return reduce();
  1374. }
  1375. }
  1376. else if(animationStep==6){
  1377. if(trivialHeight<=0){
  1378. trivialHeight=0;
  1379. animationStep=7;
  1380. pause.pause(delayValue);
  1381. update(getGraphics());
  1382. return reduce();
  1383. }
  1384. else{
  1385. trivialHeight-=0.1;
  1386. update(getGraphics());
  1387. pause.pause(delayValue);
  1388. return reduce();
  1389. }
  1390. }
  1391. else if(animationStep==7){
  1392. removeTrivials();
  1393. handleStrand=0;
  1394. update(getGraphics());
  1395. animationStep=0;
  1396. updateCurrentBraidWord();
  1397. update(getGraphics());
  1398. pause.pause(delayValue);
  1399. if(continuousAnimation){
  1400. return reduce();
  1401. }
  1402. else{
  1403. return false;
  1404. }
  1405. }
  1406. return false;
  1407. }
  1408. }