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