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