Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Graphic2d / Graphic2d_SetOfPolylines.cxx
1 /*=====================================================================
2
3      FONCTION :
4      ----------
5         Classe Graphic2d_SetOfPolylines
6
7      TEST :
8      ------
9
10         Voir TestG2D/TestG21
11
12      REMARQUES:
13      ----------
14
15      HISTORIQUE DES MODIFICATIONS   :
16      --------------------------------
17
18       27-01-98 : GG ; OPTIMISATION LOADER
19                     Transformer les variables static globales en static
20                    locales.
21
22       10-12-97 : GG ; Envoyer plutot des polylines que des segments lorsque
23                 le type de trait n'est pas SOLID de maniere a assurer
24                 la continuite.
25
26 =====================================================================*/
27
28 // PRO13369     //GG_280498
29 //                      Attention sous WNT
30 //                      MapPolylineFromTo() doit etre appele avec le 
31 //                      nombre exacte de points
32
33 #define G002    //GG_140400 Use SetPickedIndex method 
34
35 #include <Graphic2d_SetOfPolylines.ixx>
36 #include <Graphic2d_Vertex.hxx>
37 #include <Graphic2d_HSequenceOfVertex.hxx>
38
39 Graphic2d_SetOfPolylines::Graphic2d_SetOfPolylines (
40         const Handle(Graphic2d_GraphicObject)& aGraphicObject)
41
42   : Graphic2d_Line (aGraphicObject) {
43
44 }
45
46 void Graphic2d_SetOfPolylines::Add( const Standard_Real X, 
47                                     const Standard_Real Y,
48                                         const Standard_Boolean NewPolyline ) {
49   Standard_Integer n = myPolylines.Length();
50   Standard_ShortReal x = Standard_ShortReal( X ),
51                      y = Standard_ShortReal( Y );
52   Graphic2d_Vertex V( x, y );
53
54         if( NewPolyline || (n == 0) ) {
55           Handle(Graphic2d_HSequenceOfVertex) P = 
56                                         new Graphic2d_HSequenceOfVertex();
57           P->Append(V);
58           myPolylines.Append(P);
59         } else {
60           Handle(Graphic2d_HSequenceOfVertex) P = myPolylines.Last();
61           if( !V.IsEqual(P->Value(P->Length())) ) {
62             P->Append(V);
63           }
64         }
65
66         myMinX  = Min(myMinX,x);
67         myMinY  = Min(myMinY,y);
68         myMaxX  = Max(myMaxX,x);
69         myMaxY  = Max(myMaxY,y);
70 }
71
72 void Graphic2d_SetOfPolylines::Add( const Standard_Real X1, 
73                                     const Standard_Real Y1,
74                                         const Standard_Real X2, 
75                                     const Standard_Real Y2 ) {
76
77   Standard_ShortReal x1 = Standard_ShortReal( X1 ),
78                      y1 = Standard_ShortReal( Y1 ),
79                      x2 = Standard_ShortReal( X2 ),
80                      y2 = Standard_ShortReal( Y2 );
81   Graphic2d_Vertex V1( x1, y1 ),
82                    V2( x2, y2 );
83   Standard_Integer np = myPolylines.Length();
84
85         if( !V1.IsEqual(V2) ) {
86           if( np == 0 ) {
87             Handle(Graphic2d_HSequenceOfVertex) P = 
88                                         new Graphic2d_HSequenceOfVertex();
89             if( (x1 > x2) || (y1 > y2) ) {      
90               V1.SetCoord(x2,y2);       // seg orientation
91               V2.SetCoord(x1,y1);
92             }
93             P->Append(V1); P->Append(V2);
94             myPolylines.Append(P);
95           } else {              // Try to build a polyline 
96                                 // Warning,take an aspirine before continue reading...
97             Handle(Graphic2d_HSequenceOfVertex) P,PP;
98             Standard_Integer ip,ipp,lv;
99             for( ip=np ; ip>0 ; ip-- ) {
100               P = myPolylines.Value(ip);//ref line to check
101               lv = P->Length();         //number of vertex in the ref line
102               if( V1.IsEqual(P->Value(lv)) ) {
103                 //first vertex of segment is the same that the last vertex of the
104                 //ref line
105                 if( ip > 1 ) {  //Try to concatenates ref line with others
106                   for( ipp=1 ; ipp<ip ; ipp++ ) {
107                     PP = myPolylines.Value(ipp);        //other polyline 
108                     if( V2.IsEqual(PP->Value(1)) ) {
109                       PP->Prepend(P);           // Move the ref line before this
110                       myPolylines.Remove(ip);   // and destroy the ref line
111                       ip = -1; break;
112                     } else if( V2.IsEqual(PP->Value(PP->Length())) ) {
113                       P->Reverse();
114                       PP->Append(P);            // Reverse & Move the ref line after this
115                       myPolylines.Remove(ip);   // and destroy the ref line
116                       ip = -1; break;
117                     }
118                   }
119                 }
120                 if( ip > 0 ) {
121                   P->Append(V2);                // Append new vertex to ref line
122                   ip = -1;
123                 }
124               } else if( V2.IsEqual(P->Value(lv)) ) {
125                 //second vertex of segment is the same that the last vertex of the
126                 //ref line
127                 if( ip > 1 ) {  //Try to concatenates ref line with others
128                   for( ipp=1 ; ipp<ip ; ipp++ ) {
129                     PP = myPolylines.Value(ipp);        //other polyline 
130                     if( V1.IsEqual(PP->Value(1)) ) {
131                       PP->Prepend(P);           // Move the ref line before this
132                       myPolylines.Remove(ip);   // and destroy the ref line
133                       ip = -1; break;
134                     } else if( V1.IsEqual(PP->Value(PP->Length())) ) {
135                       P->Reverse();
136                       PP->Append(P);            // Reverse & Move the ref line after this
137                       myPolylines.Remove(ip);   // and destroy the ref line
138                       ip = -1; break;
139                     }
140                   }
141                 }
142                 if( ip > 0 ) {
143                   P->Append(V1);                // Append new vertex to ref line
144                   ip = -1;
145                 }
146               } else if( V1.IsEqual(P->Value(1)) ) {
147                 //first vertex of segment is the same that the first vertex of the
148                 //ref line
149                 if( ip > 1 ) {  //Try to concatenates ref line with others
150                   for( ipp=1 ; ipp<ip ; ipp++ ) {
151                     PP = myPolylines.Value(ipp);        //other polyline 
152                     if( V2.IsEqual(PP->Value(PP->Length())) ) {
153                       P->Prepend(PP);           // Move this line before the ref line
154                       myPolylines.Remove(ipp);  // and destroy this line
155                       ip = -1; break;
156                     } else if( V2.IsEqual(PP->Value(1)) ) {
157                       PP->Reverse();
158                       P->Prepend(PP);           // Reverse & Move this line before the ref line 
159                       myPolylines.Remove(ipp);  // and destroy this line
160                       ip = -1; break;
161                     }
162                   }
163                 }
164                 if( ip > 0 ) {
165                   P->Prepend(V2);               // Prepend new vertex to ref line
166                   ip = -1;
167                 }
168               } else if( V2.IsEqual(P->Value(1)) ) {
169                 //second vertex of segment is the same that the first vertex of the
170                 //ref line
171                 if( ip > 1 ) {  //Try to concatenates ref line with others
172                   for( ipp=1 ; ipp<ip ; ipp++ ) {
173                     PP = myPolylines.Value(ipp);        //other polyline 
174                     if( V1.IsEqual(PP->Value(PP->Length())) ) {
175                       P->Prepend(PP);           // Move this line before the ref line
176                       myPolylines.Remove(ipp);  // and destroy this line
177                       ip = -1; break;
178                     } else if( V1.IsEqual(PP->Value(1)) ) {
179                       PP->Reverse();
180                       P->Prepend(PP);           // Reverse & Move this line before the ref line
181                       myPolylines.Remove(ipp);  // and destroy this line
182                       ip = -1; break;
183                     }
184                   }
185                 }
186                 if( ip > 0 ) {
187                   P->Prepend(V1);               // Append new vertex to ref line
188                   ip = -1;
189                 }
190               }
191             }
192                                 //create new line
193             if( ip >= 0 ) {
194               Handle(Graphic2d_HSequenceOfVertex) P = 
195                                         new Graphic2d_HSequenceOfVertex();
196               if( (x1 > x2) || (y1 > y2) ) {    
197                 V1.SetCoord(x2,y2);     // seg orientation
198                 V2.SetCoord(x1,y1);
199               }
200               P->Append(V1);
201               P->Append(V2);
202               myPolylines.Append(P);
203             }
204           }
205
206           myMinX = Min(myMinX,Min(x1,x2));
207           myMinY = Min(myMinY,Min(y1,y2));
208           myMaxX = Max(myMaxX,Max(x1,x2));
209           myMaxY = Max(myMaxY,Max(y1,y2));
210         }
211 }
212
213 Standard_Integer Graphic2d_SetOfPolylines::Length () const {
214    return myPolylines.Length();
215 }
216
217 Standard_Integer Graphic2d_SetOfPolylines::Length (const Standard_Integer aPrank) const {
218     if( aPrank < 1 || aPrank > Length() ) 
219                 Standard_OutOfRange::Raise
220                         ("the polyline rank is out of bounds in the set");
221     return myPolylines.Value(aPrank)->Length();
222 }
223
224 void Graphic2d_SetOfPolylines::Values( const Standard_Integer aPrank,
225                                                        const Standard_Integer aVrank,
226                                                        Standard_Real &X,
227                                        Standard_Real &Y ) const {
228
229     if( aPrank < 1 || aPrank > Length() ) 
230                 Standard_OutOfRange::Raise
231                         ("the polyline rank is out of bounds in the set");
232     if( aVrank < 1 || aVrank > Length(aPrank) ) 
233                 Standard_OutOfRange::Raise
234                         ("the point rank is out of bounds in the polyline");
235
236     Graphic2d_Vertex V = myPolylines.Value(aPrank)->Value(aVrank);
237     X = V.X(); Y = V.Y();
238 }
239
240 void Graphic2d_SetOfPolylines::Draw (const Handle(Graphic2d_Drawer)& aDrawer) {
241 Standard_Integer np = myPolylines.Length();
242 Standard_Boolean IsIn = Standard_False,transform = Standard_False;
243
244   if( np <= 0 ) return;
245
246   if (! myGOPtr->IsTransformed ())
247     IsIn = aDrawer->IsIn (myMinX,myMaxX,myMinY,myMaxY);
248   else {
249     transform = Standard_True;
250     Standard_ShortReal minx, miny, maxx, maxy;
251     MinMax(minx,maxx,miny,maxy);
252     IsIn = aDrawer->IsIn (minx,maxx,miny,maxy);
253   }
254
255   if ( IsIn ) {
256     static gp_GTrsf2d theTrsf;
257     Handle(Graphic2d_HSequenceOfVertex) P;
258     Standard_Real A, B;
259     Standard_ShortReal x1,y1,x2,y2;
260     Standard_Integer ip,lp,iv;
261     DrawLineAttrib(aDrawer);
262     if( transform ) theTrsf = myGOPtr->Transform ();
263     for( ip=1 ; ip<=np ; ip++ ) { 
264       P = myPolylines.Value(ip);
265       lp = P->Length();
266       if( lp > 2 ) {
267         P->Value(1).Coord(A,B);
268         if( transform ) theTrsf.Transforms(A,B); 
269         x1 = Standard_ShortReal( A ); 
270     y1 = Standard_ShortReal( B );
271         aDrawer->MapPolylineFromTo(x1,y1,lp); 
272         for( iv=2 ; iv<lp ; iv++ ) {
273           P->Value(iv).Coord(A,B);
274           if( transform ) theTrsf.Transforms(A,B); 
275           x1 = Standard_ShortReal( A ); 
276       y1 = Standard_ShortReal( B );
277           aDrawer->MapPolylineFromTo(x1,y1,0); 
278         }
279         P->Value(lp).Coord(A,B);
280         if( transform ) theTrsf.Transforms(A,B); 
281         x1 = Standard_ShortReal( A ); 
282     y1 = Standard_ShortReal( B );
283         aDrawer->MapPolylineFromTo(x1,y1,-1); 
284       } else if( lp > 1 ) {
285         P->Value(1).Coord(A,B);
286         if( transform ) theTrsf.Transforms(A,B); 
287         x1 = Standard_ShortReal( A ); 
288     y1 = Standard_ShortReal( B );
289         P->Value(2).Coord(A,B);
290         if( transform ) theTrsf.Transforms(A,B); 
291         x2 = Standard_ShortReal( A ); 
292     y2 = Standard_ShortReal( B );
293     aDrawer->MapSegmentFromTo(x1,y1,x2,y2);
294       }
295     }
296   }
297 }
298
299 Standard_Boolean Graphic2d_SetOfPolylines::Pick (const Standard_ShortReal X,
300                                           const Standard_ShortReal Y,
301                                           const Standard_ShortReal aPrecision,
302                                           const Handle(Graphic2d_Drawer)& aDrawer)
303 {
304 Standard_Integer np = myPolylines.Length();
305 Standard_ShortReal SRX = X, SRY = Y;
306
307     if ( (np > 0) && IsInMinMax (X, Y, aPrecision)) {
308       if (myGOPtr->IsTransformed ()) {
309         gp_GTrsf2d theTrsf((myGOPtr->Transform ()).Inverted ());
310         Standard_Real RX = Standard_Real (SRX), RY = Standard_Real (SRY);
311         theTrsf.Transforms (RX, RY);
312         SRX = Standard_ShortReal (RX); SRY = Standard_ShortReal (RY);
313       }
314
315       Handle(Graphic2d_HSequenceOfVertex) P;
316       Standard_Integer ip,iv=0,lp;
317       Standard_ShortReal x1,y1,x2,y2;
318       Standard_Real A,B;
319       for( ip=1 ; ip<=np ; ip++ ) { 
320         P = myPolylines.Value(ip);
321         lp = P->Length();
322         if( lp > 1 ) {
323              for( iv=1 ; iv<lp ; iv++ ) {
324                P->Value(iv).Coord(A,B);
325                x1 = Standard_ShortReal( A ); 
326            y1 = Standard_ShortReal( B );
327                P->Value(iv+1).Coord(A,B);
328                x2 = Standard_ShortReal( A ); 
329            y2 = Standard_ShortReal( B );
330            if (IsOn (SRX, SRY, x1, y1, x2, y2, aPrecision) ) { 
331 #ifdef G002
332               SetPickedIndex((ip << 16) | iv);
333 #else
334               myPickedIndex = (ip << 16) | iv;
335 #endif
336               return Standard_True;
337             }
338           }
339         }
340       }
341       return Standard_False;
342     } 
343     return Standard_False;
344 }
345
346 void Graphic2d_SetOfPolylines::Save(Aspect_FStream& aFStream) const
347 {
348 }