0023024: Update headers of OCCT files
[occt.git] / src / Graphic2d / Graphic2d_SetOfPolylines.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 /*=====================================================================
20
21      FONCTION :
22      ----------
23         Classe Graphic2d_SetOfPolylines
24
25      TEST :
26      ------
27
28         Voir TestG2D/TestG21
29
30
31
32 =====================================================================*/
33
34 // PRO13369     //GG_280498
35 //                      MapPolylineFromTo() should be called with exact number of points
36
37 #define G002    //GG_140400 Use SetPickedIndex method 
38
39 #include <Graphic2d_SetOfPolylines.ixx>
40 #include <Graphic2d_Vertex.hxx>
41 #include <Graphic2d_HSequenceOfVertex.hxx>
42
43 Graphic2d_SetOfPolylines::Graphic2d_SetOfPolylines (
44         const Handle(Graphic2d_GraphicObject)& aGraphicObject)
45
46   : Graphic2d_Line (aGraphicObject) {
47
48 }
49
50 void Graphic2d_SetOfPolylines::Add( const Standard_Real X, 
51                                     const Standard_Real Y,
52                                         const Standard_Boolean NewPolyline ) {
53   Standard_Integer n = myPolylines.Length();
54   Standard_ShortReal x = Standard_ShortReal( X ),
55                      y = Standard_ShortReal( Y );
56   Graphic2d_Vertex V( x, y );
57
58         if( NewPolyline || (n == 0) ) {
59           Handle(Graphic2d_HSequenceOfVertex) P = 
60                                         new Graphic2d_HSequenceOfVertex();
61           P->Append(V);
62           myPolylines.Append(P);
63         } else {
64           Handle(Graphic2d_HSequenceOfVertex) P = myPolylines.Last();
65           if( !V.IsEqual(P->Value(P->Length())) ) {
66             P->Append(V);
67           }
68         }
69
70         myMinX  = Min(myMinX,x);
71         myMinY  = Min(myMinY,y);
72         myMaxX  = Max(myMaxX,x);
73         myMaxY  = Max(myMaxY,y);
74 }
75
76 void Graphic2d_SetOfPolylines::Add( const Standard_Real X1, 
77                                     const Standard_Real Y1,
78                                         const Standard_Real X2, 
79                                     const Standard_Real Y2 ) {
80
81   Standard_ShortReal x1 = Standard_ShortReal( X1 ),
82                      y1 = Standard_ShortReal( Y1 ),
83                      x2 = Standard_ShortReal( X2 ),
84                      y2 = Standard_ShortReal( Y2 );
85   Graphic2d_Vertex V1( x1, y1 ),
86                    V2( x2, y2 );
87   Standard_Integer np = myPolylines.Length();
88
89         if( !V1.IsEqual(V2) ) {
90           if( np == 0 ) {
91             Handle(Graphic2d_HSequenceOfVertex) P = 
92                                         new Graphic2d_HSequenceOfVertex();
93             if( (x1 > x2) || (y1 > y2) ) {      
94               V1.SetCoord(x2,y2);       // seg orientation
95               V2.SetCoord(x1,y1);
96             }
97             P->Append(V1); P->Append(V2);
98             myPolylines.Append(P);
99           } else {              // Try to build a polyline 
100                                 // Warning,take an aspirine before continue reading...
101             Handle(Graphic2d_HSequenceOfVertex) P,PP;
102             Standard_Integer ip,ipp,lv;
103             for( ip=np ; ip>0 ; ip-- ) {
104               P = myPolylines.Value(ip);//ref line to check
105               lv = P->Length();         //number of vertex in the ref line
106               if( V1.IsEqual(P->Value(lv)) ) {
107                 //first vertex of segment is the same that the last vertex of the
108                 //ref line
109                 if( ip > 1 ) {  //Try to concatenate ref line with others
110                   for( ipp=1 ; ipp<ip ; ipp++ ) {
111                     PP = myPolylines.Value(ipp);        //other polyline 
112                     if( V2.IsEqual(PP->Value(1)) ) {
113                       PP->Prepend(P);           // Move the ref line before this
114                       myPolylines.Remove(ip);   // and destroy the ref line
115                       ip = -1; break;
116                     } else if( V2.IsEqual(PP->Value(PP->Length())) ) {
117                       P->Reverse();
118                       PP->Append(P);            // Reverse & Move the ref line after this
119                       myPolylines.Remove(ip);   // and destroy the ref line
120                       ip = -1; break;
121                     }
122                   }
123                 }
124                 if( ip > 0 ) {
125                   P->Append(V2);                // Append new vertex to ref line
126                   ip = -1;
127                 }
128               } else if( V2.IsEqual(P->Value(lv)) ) {
129                 //second vertex of segment is the same that the last vertex of the
130                 //ref line
131                 if( ip > 1 ) {  //Try to concatenate ref line with others
132                   for( ipp=1 ; ipp<ip ; ipp++ ) {
133                     PP = myPolylines.Value(ipp);        //other polyline 
134                     if( V1.IsEqual(PP->Value(1)) ) {
135                       PP->Prepend(P);           // Move the ref line before this
136                       myPolylines.Remove(ip);   // and destroy the ref line
137                       ip = -1; break;
138                     } else if( V1.IsEqual(PP->Value(PP->Length())) ) {
139                       P->Reverse();
140                       PP->Append(P);            // Reverse & Move the ref line after this
141                       myPolylines.Remove(ip);   // and destroy the ref line
142                       ip = -1; break;
143                     }
144                   }
145                 }
146                 if( ip > 0 ) {
147                   P->Append(V1);                // Append new vertex to ref line
148                   ip = -1;
149                 }
150               } else if( V1.IsEqual(P->Value(1)) ) {
151                 //first vertex of segment is the same that the first vertex of the
152                 //ref line
153                 if( ip > 1 ) {  //Try to concatenate ref line with others
154                   for( ipp=1 ; ipp<ip ; ipp++ ) {
155                     PP = myPolylines.Value(ipp);        //other polyline 
156                     if( V2.IsEqual(PP->Value(PP->Length())) ) {
157                       P->Prepend(PP);           // Move this line before the ref line
158                       myPolylines.Remove(ipp);  // and destroy this line
159                       ip = -1; break;
160                     } else if( V2.IsEqual(PP->Value(1)) ) {
161                       PP->Reverse();
162                       P->Prepend(PP);           // Reverse & Move this line before the ref line 
163                       myPolylines.Remove(ipp);  // and destroy this line
164                       ip = -1; break;
165                     }
166                   }
167                 }
168                 if( ip > 0 ) {
169                   P->Prepend(V2);               // Prepend new vertex to ref line
170                   ip = -1;
171                 }
172               } else if( V2.IsEqual(P->Value(1)) ) {
173                 //second vertex of segment is the same that the first vertex of the
174                 //ref line
175                 if( ip > 1 ) {  //Try to concatenate ref line with others
176                   for( ipp=1 ; ipp<ip ; ipp++ ) {
177                     PP = myPolylines.Value(ipp);        //other polyline 
178                     if( V1.IsEqual(PP->Value(PP->Length())) ) {
179                       P->Prepend(PP);           // Move this line before the ref line
180                       myPolylines.Remove(ipp);  // and destroy this line
181                       ip = -1; break;
182                     } else if( V1.IsEqual(PP->Value(1)) ) {
183                       PP->Reverse();
184                       P->Prepend(PP);           // Reverse & Move this line before the ref line
185                       myPolylines.Remove(ipp);  // and destroy this line
186                       ip = -1; break;
187                     }
188                   }
189                 }
190                 if( ip > 0 ) {
191                   P->Prepend(V1);               // Append new vertex to ref line
192                   ip = -1;
193                 }
194               }
195             }
196                                 //create new line
197             if( ip >= 0 ) {
198               Handle(Graphic2d_HSequenceOfVertex) P = 
199                                         new Graphic2d_HSequenceOfVertex();
200               if( (x1 > x2) || (y1 > y2) ) {    
201                 V1.SetCoord(x2,y2);     // seg orientation
202                 V2.SetCoord(x1,y1);
203               }
204               P->Append(V1);
205               P->Append(V2);
206               myPolylines.Append(P);
207             }
208           }
209
210           myMinX = Min(myMinX,Min(x1,x2));
211           myMinY = Min(myMinY,Min(y1,y2));
212           myMaxX = Max(myMaxX,Max(x1,x2));
213           myMaxY = Max(myMaxY,Max(y1,y2));
214         }
215 }
216
217 Standard_Integer Graphic2d_SetOfPolylines::Length () const {
218    return myPolylines.Length();
219 }
220
221 Standard_Integer Graphic2d_SetOfPolylines::Length (const Standard_Integer aPrank) const {
222     if( aPrank < 1 || aPrank > Length() ) 
223                 Standard_OutOfRange::Raise
224                         ("the polyline rank is out of bounds in the set");
225     return myPolylines.Value(aPrank)->Length();
226 }
227
228 void Graphic2d_SetOfPolylines::Values( const Standard_Integer aPrank,
229                                                        const Standard_Integer aVrank,
230                                                        Standard_Real &X,
231                                        Standard_Real &Y ) const {
232
233     if( aPrank < 1 || aPrank > Length() ) 
234                 Standard_OutOfRange::Raise
235                         ("the polyline rank is out of bounds in the set");
236     if( aVrank < 1 || aVrank > Length(aPrank) ) 
237                 Standard_OutOfRange::Raise
238                         ("the point rank is out of bounds in the polyline");
239
240     Graphic2d_Vertex V = myPolylines.Value(aPrank)->Value(aVrank);
241     X = V.X(); Y = V.Y();
242 }
243
244 void Graphic2d_SetOfPolylines::Draw (const Handle(Graphic2d_Drawer)& aDrawer) {
245 Standard_Integer np = myPolylines.Length();
246 Standard_Boolean IsIn = Standard_False,transform = Standard_False;
247
248   if( np <= 0 ) return;
249
250   if (! myGOPtr->IsTransformed ())
251     IsIn = aDrawer->IsIn (myMinX,myMaxX,myMinY,myMaxY);
252   else {
253     transform = Standard_True;
254     Standard_ShortReal minx, miny, maxx, maxy;
255     MinMax(minx,maxx,miny,maxy);
256     IsIn = aDrawer->IsIn (minx,maxx,miny,maxy);
257   }
258
259   if ( IsIn ) {
260     static gp_GTrsf2d theTrsf;
261     Handle(Graphic2d_HSequenceOfVertex) P;
262     Standard_Real A, B;
263     Standard_ShortReal x1,y1,x2,y2;
264     Standard_Integer ip,lp,iv;
265     DrawLineAttrib(aDrawer);
266     if( transform ) theTrsf = myGOPtr->Transform ();
267     for( ip=1 ; ip<=np ; ip++ ) { 
268       P = myPolylines.Value(ip);
269       lp = P->Length();
270       if( lp > 2 ) {
271         P->Value(1).Coord(A,B);
272         if( transform ) theTrsf.Transforms(A,B); 
273         x1 = Standard_ShortReal( A ); 
274     y1 = Standard_ShortReal( B );
275         aDrawer->MapPolylineFromTo(x1,y1,lp); 
276         for( iv=2 ; iv<lp ; iv++ ) {
277           P->Value(iv).Coord(A,B);
278           if( transform ) theTrsf.Transforms(A,B); 
279           x1 = Standard_ShortReal( A ); 
280       y1 = Standard_ShortReal( B );
281           aDrawer->MapPolylineFromTo(x1,y1,0); 
282         }
283         P->Value(lp).Coord(A,B);
284         if( transform ) theTrsf.Transforms(A,B); 
285         x1 = Standard_ShortReal( A ); 
286     y1 = Standard_ShortReal( B );
287         aDrawer->MapPolylineFromTo(x1,y1,-1); 
288       } else if( lp > 1 ) {
289         P->Value(1).Coord(A,B);
290         if( transform ) theTrsf.Transforms(A,B); 
291         x1 = Standard_ShortReal( A ); 
292     y1 = Standard_ShortReal( B );
293         P->Value(2).Coord(A,B);
294         if( transform ) theTrsf.Transforms(A,B); 
295         x2 = Standard_ShortReal( A ); 
296     y2 = Standard_ShortReal( B );
297     aDrawer->MapSegmentFromTo(x1,y1,x2,y2);
298       }
299     }
300   }
301 }
302
303 Standard_Boolean Graphic2d_SetOfPolylines::Pick (const Standard_ShortReal X,
304                                           const Standard_ShortReal Y,
305                                           const Standard_ShortReal aPrecision,
306                                           const Handle(Graphic2d_Drawer)& aDrawer)
307 {
308 Standard_Integer np = myPolylines.Length();
309 Standard_ShortReal SRX = X, SRY = Y;
310
311     if ( (np > 0) && IsInMinMax (X, Y, aPrecision)) {
312       if (myGOPtr->IsTransformed ()) {
313         gp_GTrsf2d theTrsf((myGOPtr->Transform ()).Inverted ());
314         Standard_Real RX = Standard_Real (SRX), RY = Standard_Real (SRY);
315         theTrsf.Transforms (RX, RY);
316         SRX = Standard_ShortReal (RX); SRY = Standard_ShortReal (RY);
317       }
318
319       Handle(Graphic2d_HSequenceOfVertex) P;
320       Standard_Integer ip,iv=0,lp;
321       Standard_ShortReal x1,y1,x2,y2;
322       Standard_Real A,B;
323       for( ip=1 ; ip<=np ; ip++ ) { 
324         P = myPolylines.Value(ip);
325         lp = P->Length();
326         if( lp > 1 ) {
327              for( iv=1 ; iv<lp ; iv++ ) {
328                P->Value(iv).Coord(A,B);
329                x1 = Standard_ShortReal( A ); 
330            y1 = Standard_ShortReal( B );
331                P->Value(iv+1).Coord(A,B);
332                x2 = Standard_ShortReal( A ); 
333            y2 = Standard_ShortReal( B );
334            if (IsOn (SRX, SRY, x1, y1, x2, y2, aPrecision) ) { 
335 #ifdef G002
336               SetPickedIndex((ip << 16) | iv);
337 #else
338               myPickedIndex = (ip << 16) | iv;
339 #endif
340               return Standard_True;
341             }
342           }
343         }
344       }
345       return Standard_False;
346     } 
347     return Standard_False;
348 }
349
350 void Graphic2d_SetOfPolylines::Save(Aspect_FStream& aFStream) const
351 {
352 }