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