Salome HOME
ffc2098e98dd20d17badd2422b8a9ab003ac0c79
[modules/gui.git] / src / GLViewer / GLViewer_Tools.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  Author : OPEN CASCADE
23 // File:      GLViewer_Tools.cxx
24 // Created:   April, 2005
25 //
26 #include "GLViewer_Tools.h"
27
28 #include <GL/gl.h>
29
30 #include <iostream>
31 #include <string.h>
32
33 /*!
34   Constructor
35   \param size - size of internal array
36 */
37 GLViewer_LineList::GLViewer_LineList( int size )
38 {
39   myRealSize = 2*size;
40   mySegmentNumber = 0;
41   myMainCoord = 0.0;
42
43   myArray = new double[myRealSize];
44
45   if( !myArray )
46   {
47     std::cout << "Can't allocate memory: " << size << std::endl;
48     myRealSize = 0;
49   }
50   else
51     memset( myArray, 0, myRealSize*sizeof(double) );
52 }
53
54 /*!
55   Destructor
56 */
57 GLViewer_LineList::~GLViewer_LineList()
58 {
59   delete myArray;
60 }
61
62 /*!
63   Adds new line segment to list
64   \param coord1, coord2 - co-ordinates of points
65 */
66 bool GLViewer_LineList::addSegment( double coord1, double coord2 )
67 {
68   if( coord1 > coord2 )
69   {
70     double temp = coord1;
71     coord1 = coord2;
72     coord2 = temp;
73   }
74
75   if( 2*mySegmentNumber == myRealSize || !myArray )
76     return false;
77
78   int index = 0;
79   double c1, c2;
80   while( index < mySegmentNumber)
81   {
82     readSegment( index, c1, c2 );
83     if( coord1 < c1 && coord2 < c1 )
84     {
85       for( int i = mySegmentNumber; i > index - 1; i--)
86       {
87         myArray[2*i] = myArray[2*i-2]; //2*(i-1)
88         myArray[2*i+1] = myArray[2*i-1];//2*(i-1)+1
89       }
90       myArray[0] = coord1;
91       myArray[1] = coord2;
92       // mySegmentNumber; what is means ?
93       return true;
94     }
95     else if( coord1 < c1 && coord2 < c2 )
96     {
97       myArray[index*2] = coord1;
98       return true;
99     }
100     else if( c1 < coord1 && coord2 < c2 )
101     {
102       return true;
103     }
104     else if( coord1 < c2 && c2 < coord2 )
105     {
106       if( c1 > coord1 )
107         myArray[2*index] = coord1;
108
109       if( index != mySegmentNumber - 1 )
110       {
111         for( int i = index+1; i < mySegmentNumber; i++ )
112         {
113           if( coord2 < myArray[2*i] )
114           {
115             myArray[2*index+1] = coord2;
116             if( index+1 != i )
117             {
118               for( int j = 0; i+j < mySegmentNumber;j++ )
119               {
120                 myArray[2*(index+1+j)] = myArray[2*(i+j)];
121                 myArray[2*(index+1+j)+1] = myArray[2*(i+j)+1];
122               }
123               for( int k = 0; k < mySegmentNumber - i; k++ )
124               {
125                 myArray[2*(mySegmentNumber - 1- k)] = 0.0;
126                 myArray[2*(mySegmentNumber - 1- k)+1] = 0.0;
127               }
128               mySegmentNumber -= i - index-1;
129             }            
130             return true;
131           }
132           else if( coord2 < myArray[2*i+1] )
133           {
134             myArray[2*index+1] = myArray[2*i+1];
135             
136             for( int j = index+1; j < mySegmentNumber-1;j++ )
137             {
138               myArray[2*j] = myArray[2*(i+j-index)];
139               myArray[2*j+1] = myArray[2*(i+j-index)+1];
140             }
141             for( int k = 0; k < mySegmentNumber - i-1; k++ )
142             {
143               myArray[2*(mySegmentNumber - 1- k)] = 0.0;
144               myArray[2*(mySegmentNumber - 1- k)+1] = 0.0;
145             }
146             mySegmentNumber -= i - index;
147             return true;
148           }
149         }
150       }
151       else
152       {
153         myArray[2*index+1] = coord2;
154         return true;
155       }
156     }    
157     index++;
158   }
159
160   myArray[mySegmentNumber*2] = coord1;
161   myArray[mySegmentNumber*2+1] = coord2;
162   mySegmentNumber++;
163
164   return true;
165 }
166
167 /*!
168   Gets info about segment
169   \param theIndex - index of segment
170   \param coord1, coord2 - co-ordinates of points
171 */
172 bool GLViewer_LineList::readSegment( int theIndex, double& coord1, double& coord2 )
173 {
174   if( theIndex > mySegmentNumber || !myArray)
175     return false;
176
177   coord1 = myArray[theIndex*2];
178   coord2 = myArray[theIndex*2+1];
179
180   return true;
181 }
182
183 /*!
184   \return true if line list covers point
185   \param thePoint - point co-ordinate
186 */
187 int GLViewer_LineList::contains( double thePoint ) const
188 {
189   if( !myArray || mySegmentNumber == 0 )
190     return -1;
191
192   for( int i = 0; i < mySegmentNumber; i++ )
193     if( myArray[2*i] <= thePoint && thePoint <= myArray[2*i+1] )
194       return i;
195
196   return -1;
197
198 }
199
200 /*!
201   Removes segment
202   \param theIndex - segment index
203 */
204 bool GLViewer_LineList::removeSegment( int theIndex )
205 {
206   if( theIndex > mySegmentNumber || !myArray)
207     return false;
208
209   for( int i = theIndex; i < mySegmentNumber; i++ )
210   {
211     myArray[i*2] = myArray[(i+1)*2];
212     myArray[i*2+1] = myArray[(i+1)*2+1];
213   }
214   mySegmentNumber--;
215   myArray[mySegmentNumber*2] = 0.0;
216   myArray[mySegmentNumber*2+1] = 0.0;
217   return true;
218 }
219
220 /*!
221   Removes segment from line list
222   \param coord1, coord2 - co-ordinates of points
223 */
224 bool GLViewer_LineList::removeSegment( double coord1, double coord2 )
225 {
226   if( coord1 > coord2 )
227   {
228     double temp = coord1;
229     coord1 = coord2;
230     coord2 = temp;
231   }
232
233   if( 2*mySegmentNumber == myRealSize || !myArray )
234     return false;
235
236   int index = 0;
237   double c1, c2;
238   while( index < mySegmentNumber)
239   {
240     readSegment( index, c1, c2 );
241     if( coord1 < c1 && coord2 < c1 )
242     {
243       //nothing
244       return true;
245     }
246     else if( coord1 < c1 && coord2 < c2 )
247     {
248       myArray[index*2] = coord2;
249       return true;
250     }
251     else if( c1 < coord1 && coord2 < c2 )
252     {
253       if( 2*mySegmentNumber == myRealSize )
254         return false;
255       for( int i = mySegmentNumber; i > index + 1; i-- )
256       {
257         myArray[2*i] = myArray[2*(i-1)];
258         myArray[2*i+1] = myArray[2*(i-1)+1];
259       }
260       myArray[2*(index+1)+1] = myArray[2*index+1];
261       myArray[2*(index+1)] = coord2;
262       myArray[2*index+1] = coord1;
263       mySegmentNumber++;
264       return true;
265     }
266     else if( coord1 < c2 && c2 < coord2 )
267     {
268       if( c1 < coord1 )
269       {
270         myArray[2*index+1] = coord1;
271       }
272
273       if( index != mySegmentNumber - 1 )
274       {
275         for( int i = index+1; i < mySegmentNumber; i++ )
276         {
277           if( coord2 < myArray[2*i] )
278           {
279             if( index+1 != i )
280             {
281               for( int j = 1; i+j-1 < mySegmentNumber;j++ )
282               {
283                 myArray[2*(index+j)] = myArray[2*(i+j-1)];
284                 myArray[2*(index+j)+1] = myArray[2*(i+j-1)+1];
285               }
286               for( int k = 0; k < mySegmentNumber - i; k++ )
287               {
288                 myArray[2*(mySegmentNumber - 1- k)] = 0.0;
289                 myArray[2*(mySegmentNumber - 1- k)+1] = 0.0;
290               }
291               mySegmentNumber -= i - index -1;
292             }
293             else
294             {
295               if( !(c1 < coord1) )
296               {
297                 for( int j = 0; index + j + 1 < mySegmentNumber;j++ )
298                 {
299                   myArray[2*(index+j)] = myArray[2*(index+j+1)];
300                   myArray[2*(index+j)+1] = myArray[2*(index+j+1)+1];
301                 }
302                   
303                 myArray[2*(mySegmentNumber - 1)] = 0.0;
304                 myArray[2*(mySegmentNumber - 1)+1] = 0.0;
305                 
306                 mySegmentNumber --;
307               }
308
309             }
310
311             return true;
312
313           }
314           else if( coord2 < myArray[2*i+1] )
315           {
316             if( index+1 != i )
317             {
318               if( c1 < coord1 )
319                 index++;
320
321               myArray[2*index] = coord2;
322               myArray[2*index+1] = myArray[2*i+1];
323             
324               for( int j = 1; i+j < mySegmentNumber;j++ )
325               {
326                 myArray[2*(index+j)] = myArray[2*(i+j)];
327                 myArray[2*(index+j)+1] = myArray[2*(i+j)+1];
328               }
329               for( int k = 0; k < mySegmentNumber - i - 1; k++ )
330               {
331                 myArray[2*(mySegmentNumber - 1- k)] = 0.0;
332                 myArray[2*(mySegmentNumber - 1- k)+1] = 0.0;
333               }
334               mySegmentNumber -= i - index;
335             }
336             else
337             {
338               if( c1 < coord1 )
339               {
340                 myArray[2*(index+1)] = coord2;
341                 return true;
342               }
343               else
344               {
345                 myArray[2*(index)] = coord2;
346                 myArray[2*(index)+1] = myArray[2*(index+1)+1];
347                 for( int j = index+1; j < mySegmentNumber-1; j++ )
348                 {
349                   myArray[2*j] = myArray[2*(j+1)];
350                   myArray[2*j+1] = myArray[2*(j+1)+1];
351                 }
352                 mySegmentNumber--;
353                 myArray[2*mySegmentNumber] = 0.0;
354                 myArray[2*mySegmentNumber+1] = 0.0;
355               }
356             }
357             return true;
358           }
359         }
360       }
361       else
362       {
363         if( !(c1 < coord1) )
364         {
365           mySegmentNumber--;
366           myArray[2*index] = 0.0;
367           myArray[2*index+1] = 0.0;
368         }
369       }
370     }    
371     index++;
372   }
373   return true;
374 }
375
376 /*!
377   Clears line list
378 */
379 void GLViewer_LineList::clear()
380 {
381   if( myArray )
382     memset( myArray, 0, myRealSize*sizeof(double) );
383 }
384
385 /*!
386   Prints debug info about line list
387 */
388 void GLViewer_LineList::print()
389 {
390   std::cout << "MainCoord: " << myMainCoord <<" SIZE: " << myRealSize << " ENum: " << mySegmentNumber << " :::";
391   for( int i = 0; i < mySegmentNumber; i++ )
392     std::cout << "  " << myArray[2*i] << " " << myArray[2*i+1] << " | ";
393
394   std::cout << std::endl;
395 }
396
397 /*!
398   Draws line list with help of OpenGL 
399   \param theDim - dimension
400 */
401 void GLViewer_LineList::show( FieldDim theDim )
402 {
403   if( !myArray )
404     return;
405
406   glColor3f( 1.0, 0.0, 1.0 );
407   if( theDim == FD_X )
408   {
409     glBegin( GL_LINES );
410       for( int i = 0; i < mySegmentNumber; i++ )
411       {
412         glVertex2d( myArray[2*i], myMainCoord );
413         glVertex2d( myArray[2*i+1], myMainCoord );
414       }
415     glEnd();
416   }
417   else if( theDim == FD_Y )
418   {
419     glBegin( GL_LINES );
420       for( int i = 0; i < mySegmentNumber; i++ )
421       {
422         glVertex2d( myMainCoord, myArray[2*i]  );
423         glVertex2d( myMainCoord, myArray[2*i+1] );
424       }
425     glEnd();
426   }
427 }
428
429
430 /*!
431   Constructor
432 */
433 GLViewer_LineField::GLViewer_LineField()
434 {
435   myCurArrayIndex = 0;
436   myGraphArray1 = NULL;
437   myGraphArray2 = NULL;
438
439   myCurCount = 0;
440
441   myXSize = 0;    
442   myYSize = 0;
443   myXLineArray = NULL;
444   myYLineArray = NULL;
445 }
446
447 /*!
448   Constructor
449 */
450 GLViewer_LineField::GLViewer_LineField( const int theMAXSize, const int theXN, const int theYN )
451 {
452   myCurArrayIndex = 0;
453   myGraphArray1 = NULL;
454   myGraphArray2 = NULL;
455
456   myCurCount = 0;
457
458   if( theXN <= 0 || theYN <= 0 )
459   {
460     myXSize = 0;    
461     myYSize = 0;
462     myXLineArray = NULL;
463     myYLineArray = NULL;
464   }
465   else
466   {
467     myXLineArray = new GLViewer_LineList*[theXN];
468     myYLineArray = new GLViewer_LineList*[theYN];
469
470     for( int i = 0; i < theXN; i++ )
471       myXLineArray[i] = new GLViewer_LineList( theMAXSize );
472
473     for( int j = 0; j < theYN; j++ )
474       myYLineArray[j] = new GLViewer_LineList( theMAXSize );
475
476     myXSize = theXN;    
477     myYSize = theYN;
478   }
479 }
480
481 /*!
482   Destructor
483 */
484 GLViewer_LineField::~GLViewer_LineField()
485 {
486   if( myXLineArray )
487   {
488     for( int i = 0; i < myXSize; i++ )
489       delete myXLineArray[i];
490
491     delete myXLineArray;
492   }
493
494   if( myYLineArray )
495   {
496     for( int j = 0; j < myYSize; j++ )
497       delete myYLineArray[j];
498
499     delete myYLineArray;
500   }
501
502   if( myGraphArray1 )
503     delete myGraphArray1;
504
505   if( myGraphArray2 )
506     delete myGraphArray2;
507 }
508
509 /*!
510   Adds line
511 */
512 void GLViewer_LineField::addLine( FieldDim theDim, GLViewer_LineList* )
513 {
514   //not implemented
515 }
516
517 /*!
518   Adds line
519   \param theDim - dimension
520   \param theMC - main co-ordinate
521   \param theBegin - start co-ordinate
522   \param theEnd - end co-ordinate
523 */
524 void GLViewer_LineField:: addLine( FieldDim theDim, double theMC, double theBegin, double theEnd )
525 {
526   GLViewer_LineList* aLL = new GLViewer_LineList( 1 );
527   aLL->addSegment( theBegin, theEnd );
528   aLL->setMainCoord( theMC );
529   addLine( theDim, aLL );
530 }
531
532 /*!
533   Adds line
534   \param theDim - dimension
535   \param theLL - main co-ordinate
536   \param thePosition - index in list
537 */
538 int GLViewer_LineField::insertLine( FieldDim theDim, GLViewer_LineList* theLL, int thePosition )
539 {
540   if( !myXLineArray || !myYLineArray )
541     return -1;
542
543   GLViewer_LineList** anArray = getLLArray( theDim );
544   if( !anArray )
545     return -1;
546
547   int size = getDimSize( theDim ); 
548
549   if( thePosition >= size )
550     return -1;
551   else if( thePosition < 0 )
552   {    
553     if( anArray[size-1]->count() != 0 ) // no more space
554       return -1;
555
556     for( int i = 0; i < size; i++ )
557     {
558       if( anArray[i]->count() == 0 )
559       {
560         delete anArray[i];
561         anArray[i] = theLL;
562         return i;
563       }
564
565       double cur_mc = anArray[i]->mainCoord();
566       if( theLL->mainCoord() < cur_mc )
567       {        
568         for( int j = 0; j+i+1 < size; j++ )
569         {
570           delete anArray[size-j-1];
571           anArray[size-j-1] = anArray[size-j-2];
572         }
573         delete anArray[i];
574         anArray[i] = theLL;
575         return i;
576       }          
577     }
578   }
579   else
580   {
581     delete anArray[thePosition];
582     anArray[thePosition] = theLL;
583     return thePosition;
584   }
585
586   return -1;
587 }
588
589 /*!
590   Adds line
591   \param theDim - dimension
592   \param theMainCoord - main co-ordinate
593   \param theBegin - start co-ordinate
594   \param theEnd - end co-ordinate
595   \param thePosition - index in list
596 */
597 int GLViewer_LineField::insertLine( FieldDim theDim, double theMainCoord, double theBegin, double theEnd, int thePosition )
598 {
599   GLViewer_LineList* aLL = new GLViewer_LineList( 1 );
600   aLL->addSegment( theBegin, theEnd );
601   aLL->setMainCoord( theMainCoord );
602   return insertLine( theDim, aLL, thePosition );
603 }
604
605 /*!
606   \return other dimension
607 */
608 FieldDim GLViewer_LineField::invertDim( FieldDim theFD )
609 {
610   if( theFD == FD_X )
611     return FD_Y;
612   else
613     return FD_X;
614 }
615
616 /*!
617   \return line list
618   \param theIndex - index in list
619   \param tehFD - dimension
620 */
621 GLViewer_LineList* GLViewer_LineField::getLine( int theIndex, FieldDim theFD )
622 {
623   if( !myXLineArray || !myYLineArray )
624     return NULL;
625
626   if( theFD == FD_X )
627   {
628     if( theIndex > myXSize )
629       return NULL;
630     
631     return myXLineArray[theIndex];
632   }
633   else if( theFD == FD_Y )
634   {
635     if( theIndex > myYSize )
636       return NULL;
637     
638     return myYLineArray[theIndex];
639   }
640
641   return NULL;
642 }
643
644 /*!
645   Sets borders of field
646   \param X1, X2 - minimal and maximal abscisses
647   \param Y1, Y2 - minimal and maximal ordinates
648 */
649 void GLViewer_LineField::setBorders( double X1, double X2, double Y1, double Y2 )
650 {
651   if( !myXLineArray || !myYLineArray )
652     return;
653     
654   for( int i = 0; i < myXSize; i++ )
655   {
656     myXLineArray[i]->clear();
657     myXLineArray[i]->addSegment( X1, X2 );
658     myXLineArray[i]->setMainCoord( Y1 + (Y2-Y1)*(double(i)/(myXSize-1)) );
659   }
660
661   for( int j = 0; j < myYSize; j++ )
662   {
663     myYLineArray[j]->clear();
664     myYLineArray[j]->addSegment( Y1, Y2 );
665     myYLineArray[j]->setMainCoord( X1 + (X2-X1)*(double(j)/(myYSize-1)) );
666   }
667
668
669 /*!
670   Adds rectangle
671   \param top, right - a corner of rectangle
672   \param bottom, left - other corner of rectangle
673 */
674 void GLViewer_LineField::addRectangle( double top, double right, double bottom, double left )
675 {
676   if( !myXLineArray || !myYLineArray )
677     return;
678   for( int i = 0; i < myXSize; i++ )
679   {
680     double mainCoord = myXLineArray[i]->mainCoord();
681     if( mainCoord < top && mainCoord > bottom )
682       myXLineArray[i]->removeSegment( left, right );
683   }
684
685   for( int j = 0; j < myYSize; j++ )
686   {
687     double mainCoord = myYLineArray[j]->mainCoord();
688     if( mainCoord < right && mainCoord > left )
689       myYLineArray[j]->removeSegment( bottom, top );
690   }
691 }
692
693 /*!
694   Prints debug info about line field
695 */
696 void GLViewer_LineField::print()
697 {
698   std::cout << "My X matrix Number: " << myXSize << std::endl;
699   for( int i = 0; i < myXSize; i++ )
700     myXLineArray[i]->print();
701
702   std::cout << "My Y matrix Number: " << myYSize << std::endl;
703   for( int j = 0; j < myYSize; j++ )
704     myYLineArray[j]->print();
705 }
706
707 /*!
708   Draws field with help of OpenGL 
709 */
710 void GLViewer_LineField::show()
711 {
712   for( int i = 0; i < myXSize; i++ )
713     getLine( i, FD_X )->show( FD_X );
714
715   for( int j = 0; j < myYSize; j++ )
716     getLine( j, FD_Y )->show( FD_Y );
717   int count = 0;
718   double* anArray = solution( count );
719   glColor3f( 1.0, 0.0, 0.0 );
720   glBegin( GL_LINES );
721   for( int k = 0; k < count; k++ )
722   {
723      glVertex2d( anArray[4*k], anArray[4*k+1] );
724      glVertex2d( anArray[4*k+2], anArray[4*k+3] );
725   }
726   glEnd();
727   delete[] anArray;
728   std::cout << "Show function" << std::endl;
729 }
730
731 /*!
732   \return size
733   \param theDim - dimension
734 */
735 int GLViewer_LineField::getDimSize( FieldDim theDim )
736 {
737   if( theDim == FD_X )
738     return myXSize;
739   else if( theDim == FD_Y )
740     return myYSize;
741
742   return -1;
743 }
744
745 /*!
746   \return array of intersected indexes
747   \param theDim - dimension
748   \param theIndex - index
749   \param theLL - line with that intersection is checked
750   \param theSize - to return value of array size
751 */
752 int* GLViewer_LineField::intersectIndexes( FieldDim theDim, int theIndex, const GLViewer_LineList* theLL, int& theSize )
753 {
754   theSize = 0;
755   if( !myXLineArray || !myYLineArray )
756     return NULL;
757
758   int aDimSize = getDimSize( theDim );
759   int* anArray = new int[aDimSize*2 ];
760
761   for( int i = 0; i < aDimSize; i++ )
762   {
763     GLViewer_LineList* aLL = getLine( i, theDim );      
764     int index = aLL->contains( theLL->mainCoord() );       
765     if( index != -1 && theLL->contains( aLL->mainCoord() ) == theIndex )
766     {
767       anArray[theSize*2] = i;
768       anArray[theSize*2+1] = index;
769       theSize++;
770     }
771   }
772   
773   return anArray;
774 }
775
776 /*!
777   Sets start/end search point
778   \param thePoint - type of point (start: FP_Start; end: FP_End )
779   \param theX, theY - point co-ordinates
780 */
781 bool GLViewer_LineField::setPoint( FieldPoint thePoint, double theX, double theY )
782 {
783   if( !myXLineArray || !myYLineArray )
784     return false;
785
786   int i = -1, j = -1;
787   int xSeg = -1, ySeg = -1;
788   for( i = 0; i < myXSize; i++ )
789   {
790     GLViewer_LineList* aLL = getLine( i, FD_X );
791     if( aLL->mainCoord() == theY )
792     {
793       xSeg = aLL->contains( theX );
794       break;
795     }
796   }
797
798   for( j = 0; j < myYSize; j++ )
799   {
800     GLViewer_LineList* aLL = getLine( j, FD_Y );
801     if( aLL->mainCoord() == theX )
802     {
803       ySeg = aLL->contains( theY );
804       break;
805     }
806   }
807
808   if( xSeg != -1 && ySeg != -1 )
809   {
810     if( thePoint == FP_Start )
811     {
812       myStartPoint.myXLineIndex = i;
813       myStartPoint.myXSegmentIndex = xSeg;
814       myStartPoint.myYLineIndex = j;
815       myStartPoint.myYSegmentIndex = ySeg;
816       myStartPoint.mySolveIndex = -1;
817     }
818     else
819     {
820       myEndPoint.myXLineIndex = i;
821       myEndPoint.myXSegmentIndex = xSeg;
822       myEndPoint.myYLineIndex = j;
823       myEndPoint.myYSegmentIndex = ySeg;
824       myEndPoint.mySolveIndex = -1;
825     }
826     return true;
827   }
828   else
829     return false;
830 }
831
832 /*!
833   \return number of segments
834 */
835 int GLViewer_LineField::segmentNumber()
836 {
837   if( !(myXLineArray || myYLineArray) )
838     return -1;
839
840   int aNumber = 0;
841   for( int aDim = 0; aDim < 2; aDim++ )
842     for( int i = 0, n = getDimSize( (FieldDim)aDim ); i < n; i++ )
843       aNumber += getLine( i, (FieldDim)aDim  )->count();
844
845   return aNumber;
846 }
847
848 /*!
849   Removes all multiple segments
850 */
851 void GLViewer_LineField::optimize()
852 {
853   if( !myXLineArray || !myYLineArray )
854     return;
855
856   for( int aDim = 0; aDim < 2; aDim++ )
857   {
858     for( int i = 0, n = getDimSize( (FieldDim)aDim ); i < n; i++ )
859     {
860       GLViewer_LineList* aLL = getLine( i, (FieldDim)aDim  );
861       for( int k =0, aSegNum = aLL->count(); k < aSegNum; k++ )
862       {
863         // int index = i; unused
864         double a1, a2;
865         aLL->readSegment( k, a1, a2 );
866         for( int l = i+1, m = getDimSize( (FieldDim)aDim ); l < m; l++ )
867         {
868           int end = -1;
869           GLViewer_LineList* aCurLL = getLine( l, (FieldDim)aDim );
870           for( int j = 0, count = aCurLL->count(); j < count; j++  )
871           {
872             double c1, c2;
873             aCurLL->readSegment( j, c1, c2 );
874             if( a1 == c1 && a2 == c2 )
875             {
876               if( !(aDim == 0 && myStartPoint.myXLineIndex == l && myStartPoint.myXSegmentIndex == j) &&
877                   !(aDim == 0 && myEndPoint.myXLineIndex == l && myEndPoint.myXSegmentIndex == j) &&
878                   !(aDim == 1 && myStartPoint.myYLineIndex == l && myStartPoint.myYSegmentIndex == j) &&
879                   !(aDim == 1 && myEndPoint.myYLineIndex == l && myEndPoint.myYSegmentIndex == j) )
880                 aCurLL->removeSegment( j );
881               end = 0;
882               break;
883             }
884             if( a1 < c1 )
885             {
886               end = 1;
887               break;
888             }            
889           }
890           if( end == -1 || end == 1)
891               break;
892         }
893       }
894     }
895   }
896 }
897
898 /*!
899   Some prepare actions
900   Needs call setPoint before
901 */
902 void GLViewer_LineField::initialize()
903 {
904   if( !myXLineArray || !myYLineArray )
905     return;
906
907   int size = segmentNumber();
908
909   myCurArrayIndex = 0;
910   myCurCount = 0;
911
912   myGraphArray1 = new GraphNode[size];
913   myGraphArray2 = new GraphNode[size];
914
915   int index = 0;
916   bool isXSet = false,
917        isYSet = false;
918   for( int aDim = 0; aDim < 2; aDim++ )
919   {
920     for( int i = 0, n = getDimSize( (FieldDim)aDim ); i < n; i++ )
921     {
922       GLViewer_LineList* aLL = getLine( i, (FieldDim)aDim  );
923       for( int k =0, aSegNum = aLL->count(); k < aSegNum; k++ )
924       {
925         myGraphArray1[index].myCount = size;
926         myGraphArray1[index].myDim = (FieldDim)aDim;
927         myGraphArray1[index].myLineIndex = i;
928         myGraphArray1[index].mySegmentindex = k;
929         myGraphArray1[index].prevNodeIndex = -1;
930
931         myGraphArray2[index].myCount = size;
932         myGraphArray2[index].myDim = (FieldDim)aDim;
933         myGraphArray2[index].myLineIndex = i;
934         myGraphArray2[index].mySegmentindex = k;
935         myGraphArray2[index].prevNodeIndex = -1;
936
937         if( !isXSet && aDim == FD_X && myStartPoint.myXLineIndex == i && myStartPoint.myXSegmentIndex == k )
938         {
939           myGraphArray1[index].myCount = 0;
940           isXSet = true;
941         }
942
943         if( aDim == FD_Y && !isYSet && myStartPoint.myYLineIndex == i && myStartPoint.myYSegmentIndex == k )
944         {
945           myGraphArray1[index].myCount = 0;
946           isYSet = true;
947         }
948
949         index++;
950       }
951     }
952   }
953 }
954
955 /*!
956   One iteration of algorithm
957 */
958 void GLViewer_LineField::iteration()
959 {
960   int aParam = myCurCount;
961   myCurCount++;
962
963   int* aNodes = findByCount( aParam );
964   GraphNode* aCurArray = getCurArray();
965
966   for( int i = 0; i < aParam; i++ )
967   {
968     GraphNode aCurNode = aCurArray[aNodes[i]];
969     int aSize = 0;
970     int* aInterNodes = intersectIndexes( invertDim( aCurNode.myDim ), aCurNode.mySegmentindex,
971                                          getLine( aCurNode.myLineIndex, aCurNode.myDim ), aSize );
972     for( int j = 0; j < aSize; j++ )
973     {
974       int index = findBySegment( invertDim( aCurNode.myDim ), aInterNodes[2*j], aInterNodes[2*j+1], false );
975       if( index != -1 )
976         if( aCurArray[index].myCount > myCurCount )
977         {
978           aCurArray[index].myCount = myCurCount;
979           aCurArray[index].prevNodeIndex = aNodes[i];
980         }
981     }
982
983     delete[] aInterNodes;
984   }
985
986   delete[] aNodes;
987 }
988
989 /*!
990   Checks for complete status
991 */
992 GLViewer_LineField::IterationStatus GLViewer_LineField::checkComplete()
993 {
994   if( !myXLineArray || !myYLineArray || !myGraphArray1 || !myGraphArray2 )
995     return IS_ERROR; 
996    
997   int count = 0;
998   GraphNode* aCurArray = getCurArray(),
999            * aSecArray = getSecArray();
1000   
1001   for( int i = 0, n = segmentNumber(); i < n; i++ )
1002   {
1003     if( aCurArray[i].myCount != aSecArray[i].myCount )
1004     {
1005       if( aCurArray[i].myDim == FD_X && 
1006           aCurArray[i].myLineIndex == myEndPoint.myXLineIndex && 
1007           aCurArray[i].mySegmentindex == myEndPoint.myXSegmentIndex )
1008       {
1009         std::cout << "Algorithm complete X!!!!!!!" << std::endl;
1010         myEndPoint.mySolveIndex = i;
1011         return IS_SOLVED;
1012       }
1013       else if( aCurArray[i].myDim == FD_Y && 
1014                aCurArray[i].myLineIndex == myEndPoint.myYLineIndex && 
1015                aCurArray[i].mySegmentindex == myEndPoint.myYSegmentIndex )
1016       {
1017         std::cout << "Algorithm complete Y!!!!!!!" << std::endl;
1018         myEndPoint.mySolveIndex = i;  
1019         return IS_SOLVED;
1020       }
1021       else
1022       {
1023         count++;
1024         aSecArray[i].myCount = aCurArray[i].myCount;
1025         aSecArray[i].prevNodeIndex = aCurArray[i].prevNodeIndex;
1026       }
1027     }
1028   }  
1029   
1030   if( myCurArrayIndex == 0)
1031     myCurArrayIndex = 1;
1032   else
1033     myCurArrayIndex = 0;
1034
1035   std::cout << "Number of ways: " << count << std::endl;
1036   if( count == 0 )
1037     return IS_LOOP;
1038
1039   return IS_NOT_SOLVED;
1040 }
1041
1042 /*!
1043   Finds LineList by counts and returns indexes
1044 */
1045 int* GLViewer_LineField::findByCount( int& theParam )
1046 {
1047   if( !myXLineArray || !myYLineArray || !myGraphArray1 || !myGraphArray2 )
1048     return NULL;
1049
1050   int count = segmentNumber();
1051   int* anArray = new int[count];
1052   int aSize = 0;
1053
1054   GraphNode* aCurArray = getCurArray();  
1055   for( int i = 0; i < count; i++ )
1056   {
1057     GraphNode aCurNode = aCurArray[i];
1058     if( aCurNode.myCount == theParam )
1059     {
1060       anArray[aSize] = i;
1061       aSize++;
1062     }
1063   }
1064
1065   theParam = aSize;
1066   return anArray;
1067 }
1068
1069 /*!
1070   Finds LineList by segment and dimension
1071 */
1072 int GLViewer_LineField::findBySegment( FieldDim theDim, int theLineIndex, int theSegment, bool inCurArray )
1073 {
1074   if( !myXLineArray || !myYLineArray || !myGraphArray1 || !myGraphArray2 || getDimSize( theDim ) <= theLineIndex )
1075     return -1;
1076
1077   GraphNode* aCurArray;
1078   if( inCurArray )
1079     aCurArray = getCurArray();
1080   else
1081     aCurArray = getSecArray();
1082
1083   for( int i = 0, n = segmentNumber(); i < n; i++ )
1084   {
1085     GraphNode aCurNode = aCurArray[i];
1086     if( aCurNode.myDim == theDim && aCurNode.myLineIndex == theLineIndex && aCurNode.mySegmentindex == theSegment )
1087       return i;
1088   }
1089
1090   return -1;
1091 }
1092
1093 /*!
1094   Main method, performs algorithm execution
1095 */
1096 GLViewer_LineField::EndStatus GLViewer_LineField::startAlgorithm()
1097 {
1098   if( !myXLineArray || !myYLineArray || !myGraphArray1 || !myGraphArray2 )
1099     return ES_ERROR;
1100
1101   while( true )
1102   {
1103     std::cout << "-----------Iteration #" << myCurCount << "-------------" << std::endl;
1104     iteration();
1105
1106     IterationStatus is = checkComplete();
1107     if( is == IS_ERROR )
1108       return ES_ERROR;
1109     else if( is == IS_LOOP )
1110       return ES_LOOP;
1111     else if( is == IS_SOLVED )
1112       return ES_SOLVED;
1113   }
1114   return ES_SOLVED;
1115 }
1116
1117 /*!
1118   \return solution and size of solution
1119 */
1120 double* GLViewer_LineField::solution( int& theSize )
1121 {
1122   if( !myXLineArray || !myYLineArray || !myGraphArray1 || !myGraphArray2 )
1123     return NULL;
1124
1125   if( myEndPoint.mySolveIndex == -1 )
1126     return NULL;
1127
1128   theSize = myCurCount+1;
1129   double* anArray = new double[theSize*4];
1130
1131   GraphNode* aCurArray = getCurArray();
1132   
1133   int index = myEndPoint.mySolveIndex;
1134   for( int i = 0; i <= myCurCount; i++  )
1135   {
1136     if( index == -1 )
1137       break;
1138     double c1, c2;
1139     GLViewer_LineList* aLL = getLine( aCurArray[index].myLineIndex, aCurArray[index].myDim );
1140     aLL->readSegment( aCurArray[index].mySegmentindex, c1, c2 );
1141
1142     if( aCurArray[index].myDim == FD_X )
1143     {
1144       anArray[i*4] = c1;
1145       anArray[i*4+1] = aLL->mainCoord();
1146       anArray[i*4+2] = c2;
1147       anArray[i*4+3] = aLL->mainCoord();
1148     }
1149     else
1150     {
1151       anArray[i*4] = aLL->mainCoord();
1152       anArray[i*4+1] = c1;
1153       anArray[i*4+2] = aLL->mainCoord();
1154       anArray[i*4+3] = c2;
1155     }
1156
1157     index = aCurArray[index].prevNodeIndex;    
1158   }
1159
1160   return anArray;
1161 }
1162
1163 /*!
1164   \return current solution array
1165 */
1166 GraphNode* GLViewer_LineField::getCurArray()
1167 {
1168   if( !myGraphArray1 || !myGraphArray2 )
1169     return NULL;
1170
1171   if( myCurArrayIndex == 0)
1172     return myGraphArray1;
1173   else
1174     return myGraphArray2;
1175 }
1176
1177 /*!
1178   \return other solution array
1179 */
1180 GraphNode* GLViewer_LineField::getSecArray()
1181 {
1182   if( !myGraphArray1 || !myGraphArray2 )
1183     return NULL;
1184
1185   if( myCurArrayIndex == 0)
1186     return myGraphArray2;
1187   else
1188     return myGraphArray1;
1189 }
1190
1191 /*!
1192   \return maximum segment number
1193 */
1194 int GLViewer_LineField::maxSegmentNum()
1195 {
1196   if( !myXLineArray || !myYLineArray )
1197     return -1;
1198
1199   int max_num = -1;
1200   for( int aDim = 0; aDim < 2; aDim++ )
1201   {
1202     for( int i = 0, n = getDimSize( (FieldDim)aDim ); i < n; i++ )
1203     {
1204       int count = getLine( i, (FieldDim)aDim  )->count();
1205       if( count > max_num )
1206         max_num = count;
1207     }
1208   }
1209
1210   return max_num;
1211 }
1212
1213 /*!
1214   \return list of LileList by dimension
1215   \param theDim - dimension
1216 */
1217 GLViewer_LineList** GLViewer_LineField::getLLArray( FieldDim theDim )
1218 {
1219   if( theDim == FD_X )
1220     return myXLineArray;
1221   else if( theDim == FD_Y )
1222     return myYLineArray;
1223   else
1224     return NULL;
1225 }