Salome HOME
Merge master branch into V9_dev.
[modules/geom.git] / src / GEOMGUI / GEOMGUI_DimensionProperty.cxx
1 // Copyright (C) 2007-2016  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 // File   : GEOMGUI_DimensionProperty.cxx
24 // Author : Anton POLETAEV, Open CASCADE S.A.S.
25 //
26
27 #include "GEOMGUI_DimensionProperty.h"
28
29 // OCCT includes
30 #include <Standard_ProgramError.hxx>
31 #include <gp_Trsf.hxx>
32
33 #include <SalomeApp_Application.h>
34
35 // Static patterns for casting value-to-string & value-from-string. The patterns are:
36 //  ITEM: { name[string] : visibility : type : values[composite] };
37 //  PLANE: a[float] : b[float] : c[float] : d[float]
38 //  PROPS: flyout[float] : text h pos[int] : text v pos[int] : arrow pos[int]
39 //  XYZ: x [float] : y[float] : z[float]
40 //  FLOAT: value [float]
41 namespace
42 {
43   static const QString PATTERN_ITEM_GROUP = "\\{ (Name=(?::{2,}|.)*:(?!:)Visible=.*:Type=.*:.*) \\}";
44   static const QString PATTERN_ITEM  = "Name=((?::{2,}|.)*):(?!:)Visible=(\\d{1}):Type=(\\d{1}):(.*)";
45   static const QString PATTERN_PLANE = "Plane=\\{(.*):(.*):(.*):(.*)\\}";
46   static const QString PATTERN_PROPS = "Flyout=(.*):TextH=(.*):TextV=(.*):Arrow=(.*)";
47   static const QString PATTERN_XYZ   = "%1=\\{(.*):(.*):(.*)\\}";
48   static const QString PATTERN_FLOAT = "%1=(.*)";
49
50   static const QString PATTERN_LENGTH =
51     PATTERN_PLANE + ":" +
52     PATTERN_PROPS + ":" +
53     PATTERN_XYZ.arg( "Point1" ) + ":" +
54     PATTERN_XYZ.arg( "Point2" );
55
56   static const QString PATTERN_DIAMETER =
57     PATTERN_PLANE + ":" +
58     PATTERN_PROPS + ":" +
59     PATTERN_XYZ.arg( "Position" ) + ":" +
60     PATTERN_XYZ.arg( "NDir" ) + ":" +
61     PATTERN_XYZ.arg( "XDir" ) + ":" +
62     PATTERN_FLOAT.arg( "Radius" );
63
64   static const QString PATTERN_ANGLE =
65     PATTERN_PROPS + ":" +
66     PATTERN_XYZ.arg( "Point1" ) + ":" +
67     PATTERN_XYZ.arg( "Point2" ) + ":" +
68     PATTERN_XYZ.arg( "Point3" );
69 };
70
71 //=================================================================================
72 // function : Length::Init
73 // purpose  : 
74 //=================================================================================
75 void GEOMGUI_DimensionProperty::Length::Init( const Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS )
76 {
77   gp_Trsf aFromLCS;
78   aFromLCS.SetTransformation( gp_Ax3(), theLCS );
79
80   FirstPoint  = theIO->FirstPoint().Transformed( aFromLCS );
81   SecondPoint = theIO->SecondPoint().Transformed( aFromLCS );
82   Plane       = theIO->GetPlane().Transformed( aFromLCS );
83   Flyout      = theIO->GetFlyout();
84   TextHPos    = theIO->DimensionAspect()->TextHorizontalPosition();
85   TextVPos    = theIO->DimensionAspect()->TextVerticalPosition();
86   ArrowPos    = theIO->DimensionAspect()->ArrowOrientation();
87 }
88
89 //=================================================================================
90 // function : Length::Update
91 // purpose  : 
92 //=================================================================================
93 void GEOMGUI_DimensionProperty::Length::Update( Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS )
94 {
95   gp_Trsf aToLCS;
96   aToLCS.SetTransformation( theLCS, gp_Ax3() );
97
98   gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS );
99   gp_Pnt aPoint2 = SecondPoint.Transformed( aToLCS );
100   gp_Pln aPlane  = Plane.Transformed( aToLCS );
101
102   theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPlane );
103   theIO->SetFlyout( Flyout );
104
105   Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
106   aStyle->SetTextHorizontalPosition( TextHPos );
107   aStyle->SetTextVerticalPosition( TextVPos );
108   aStyle->SetArrowOrientation( ArrowPos );
109   theIO->SetDimensionAspect( aStyle );
110 }
111
112 //=================================================================================
113 // function : Length::ToValues
114 // purpose  : 
115 //=================================================================================
116 void GEOMGUI_DimensionProperty::Length::ToValues(std::vector<double>& theValues) const
117 {
118   // custom plane [2,3,4,5]
119   Standard_Real A, B, C, D;
120   Plane.Coefficients( A, B, C, D );
121   theValues.push_back( (double) A );
122   theValues.push_back( (double) B );
123   theValues.push_back( (double) C );
124   theValues.push_back( (double) D );
125
126   // flyout size [6]
127   theValues.push_back( (double) Flyout );
128
129   // text flags [7,8]
130   theValues.push_back( (double) TextHPos );
131   theValues.push_back( (double) TextVPos );
132
133   // arrow flags [9]
134   theValues.push_back( (double) ArrowPos );
135
136   // point 1 [10,11,12]
137   theValues.push_back( (double) FirstPoint.X() );
138   theValues.push_back( (double) FirstPoint.Y() );
139   theValues.push_back( (double) FirstPoint.Z() );
140
141   // point 2 [13,14,15]
142   theValues.push_back( (double) SecondPoint.X() );
143   theValues.push_back( (double) SecondPoint.Y() );
144   theValues.push_back( (double) SecondPoint.Z() );
145 }
146
147 //=================================================================================
148 // function : Length::FromValues
149 // purpose  : 
150 //=================================================================================
151 void GEOMGUI_DimensionProperty::Length::FromValues(int& theIt, const std::vector<double>& theValues)
152 {
153   // custom plane [2,3,4,5]
154   Standard_Real A = (Standard_Real) theValues[theIt++];
155   Standard_Real B = (Standard_Real) theValues[theIt++];
156   Standard_Real C = (Standard_Real) theValues[theIt++];
157   Standard_Real D = (Standard_Real) theValues[theIt++];
158   Plane = gp_Pln( A, B, C, D );
159
160   // flyout size [6]
161   Flyout = (Standard_Real) theValues[theIt++];
162
163   // text flags [7,8]
164   TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)theValues[theIt++];
165   TextVPos = (Prs3d_DimensionTextVerticalPosition)  (int)theValues[theIt++];
166
167   // arrow flags [9]
168   ArrowPos = (Prs3d_DimensionArrowOrientation) (int)theValues[theIt++];
169
170   // point 1 [10,11,12]
171   Standard_Real aFirstX = theValues[theIt++];
172   Standard_Real aFirstY = theValues[theIt++];
173   Standard_Real aFirstZ = theValues[theIt++];
174   FirstPoint = gp_Pnt( aFirstX, aFirstY, aFirstZ );
175
176   // point 2 [13,14,15]
177   Standard_Real aSecondX = theValues[theIt++];
178   Standard_Real aSecondY = theValues[theIt++];
179   Standard_Real aSecondZ = theValues[theIt++];
180   SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ );
181 }
182
183 //=================================================================================
184 // function : Length::operator == 
185 // purpose  : 
186 //=================================================================================
187 bool GEOMGUI_DimensionProperty::Length::operator == (const Length& theOther) const
188 {
189   if ( FirstPoint.X()  != theOther.FirstPoint.X()
190     || FirstPoint.Y()  != theOther.FirstPoint.Y()
191     || FirstPoint.Z()  != theOther.FirstPoint.Z()
192     || SecondPoint.X() != theOther.SecondPoint.X()
193     || SecondPoint.Y() != theOther.SecondPoint.Y()
194     || SecondPoint.Z() != theOther.SecondPoint.Z() )
195   {
196     return false;
197   }
198
199   if ( Plane.Location().X() != theOther.Plane.Location().X()
200     || Plane.Location().Y() != theOther.Plane.Location().Y()
201     || Plane.Location().Z() != theOther.Plane.Location().Z()
202     || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X()
203     || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y()
204     || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() )
205   {
206     return false;
207   }
208
209   if ( Flyout   != theOther.Flyout 
210     || TextHPos != theOther.TextHPos 
211     || TextVPos != theOther.TextVPos
212     || ArrowPos != theOther.ArrowPos )
213   {
214     return false;
215   }
216
217   return true;
218 }
219
220 //=================================================================================
221 // function : Diameter::Init
222 // purpose  : 
223 //=================================================================================
224 void GEOMGUI_DimensionProperty::Diameter::Init( const Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS )
225 {
226   gp_Trsf aFromLCS;
227   aFromLCS.SetTransformation( gp_Ax3(), theLCS );
228
229   Circle   = theIO->Circle().Transformed( aFromLCS );
230   Plane    = theIO->GetPlane().Transformed( aFromLCS );
231   Flyout   = theIO->GetFlyout();
232   TextHPos = theIO->DimensionAspect()->TextHorizontalPosition();
233   TextVPos = theIO->DimensionAspect()->TextVerticalPosition();
234   ArrowPos = theIO->DimensionAspect()->ArrowOrientation();
235 }
236
237 //=================================================================================
238 // function : Diameter::Update
239 // purpose  : 
240 //=================================================================================
241 void GEOMGUI_DimensionProperty::Diameter::Update( Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS )
242 {
243   gp_Trsf aToLCS;
244   aToLCS.SetTransformation( theLCS, gp_Ax3() );
245
246   gp_Circ aCircle = Circle.Transformed( aToLCS );
247   gp_Pln  aPlane  = Plane.Transformed( aToLCS );
248
249   Standard_Boolean isParallel = 
250     aCircle.Axis().Direction().IsParallel( aPlane.Axis().Direction(), Precision::Angular() );
251
252   if ( isParallel )
253   {
254     theIO->UnsetCustomPlane();
255     theIO->SetMeasuredGeometry( aCircle );
256   }
257   else
258   {
259     theIO->SetCustomPlane( aPlane );
260     theIO->SetMeasuredGeometry( aCircle );
261   }
262
263   theIO->SetFlyout( Flyout );
264
265   Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
266   aStyle->SetTextHorizontalPosition( TextHPos );
267   aStyle->SetTextVerticalPosition( TextVPos );
268   aStyle->SetArrowOrientation( ArrowPos );
269   theIO->SetDimensionAspect( aStyle );
270 }
271
272 //=================================================================================
273 // function : Diameter::ToValues
274 // purpose  : 
275 //=================================================================================
276 void GEOMGUI_DimensionProperty::Diameter::ToValues(std::vector<double>& theValues) const
277 {
278   // custom plane [2,3,4,5]
279   Standard_Real A, B, C, D;
280   Plane.Coefficients( A, B, C, D );
281   theValues.push_back( (double) A );
282   theValues.push_back( (double) B );
283   theValues.push_back( (double) C );
284   theValues.push_back( (double) D );
285
286   // flyout size [6]
287   theValues.push_back( (double) Flyout );
288
289   // text flags [7,8]
290   theValues.push_back( (double) TextHPos );
291   theValues.push_back( (double) TextVPos );
292
293   // arrow flags [9]
294   theValues.push_back( (double) ArrowPos );
295
296   // circle location [10,11,12]
297   theValues.push_back( (double) Circle.Location().X() );
298   theValues.push_back( (double) Circle.Location().Y() );
299   theValues.push_back( (double) Circle.Location().Z() );
300
301   // circle normal [13,14,15]
302   theValues.push_back( (double) Circle.Axis().Direction().X() );
303   theValues.push_back( (double) Circle.Axis().Direction().Y() );
304   theValues.push_back( (double) Circle.Axis().Direction().Z() );
305
306   // x-direction [16,17,18]
307   theValues.push_back( (double) Circle.XAxis().Direction().X() );
308   theValues.push_back( (double) Circle.XAxis().Direction().Y() );
309   theValues.push_back( (double) Circle.XAxis().Direction().Z() );
310
311   // radius [19]
312   theValues.push_back( (double) Circle.Radius() );
313 }
314
315 //=================================================================================
316 // function : Diameter::FromValues
317 // purpose  : 
318 //=================================================================================
319 void GEOMGUI_DimensionProperty::Diameter::FromValues(int& theIt, const std::vector<double>& theValues)
320 {
321   // custom plane [2,3,4,5]
322   Standard_Real A = (Standard_Real) theValues[theIt++];
323   Standard_Real B = (Standard_Real) theValues[theIt++];
324   Standard_Real C = (Standard_Real) theValues[theIt++];
325   Standard_Real D = (Standard_Real) theValues[theIt++];
326   Plane = gp_Pln( A, B, C, D );
327
328   // flyout size [6]
329   Flyout = (Standard_Real) theValues[theIt++];
330
331   // text flags [7,8]
332   TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)theValues[theIt++];
333   TextVPos = (Prs3d_DimensionTextVerticalPosition)  (int)theValues[theIt++];
334
335   // arrow flags [9]
336   ArrowPos = (Prs3d_DimensionArrowOrientation) (int)theValues[theIt++];
337
338   // circle location [10,11,12]
339   Standard_Real aLocX = (Standard_Real) theValues[theIt++];
340   Standard_Real aLocY = (Standard_Real) theValues[theIt++];
341   Standard_Real aLocZ = (Standard_Real) theValues[theIt++];
342
343   // circle normal [13,14,15]
344   Standard_Real aNormX = (Standard_Real) theValues[theIt++];
345   Standard_Real aNormY = (Standard_Real) theValues[theIt++];
346   Standard_Real aNormZ = (Standard_Real) theValues[theIt++];
347
348   // x-direction [16,17,18]
349   Standard_Real aXDirX = (Standard_Real) theValues[theIt++];
350   Standard_Real aXDirY = (Standard_Real) theValues[theIt++];
351   Standard_Real aXDirZ = (Standard_Real) theValues[theIt++];
352
353   // radius [19]
354   Standard_Real aRadius = (Standard_Real) theValues[theIt++];
355
356   gp_Ax2 anAx( gp_Pnt( aLocX, aLocY, aLocZ ),
357                gp_Dir( aNormX, aNormY, aNormZ ),
358                gp_Dir( aXDirX, aXDirY, aXDirZ ) );
359
360   Circle = gp_Circ( anAx, aRadius );
361 }
362
363 //=================================================================================
364 // function : Diameter::operator == 
365 // purpose  : 
366 //=================================================================================
367 bool GEOMGUI_DimensionProperty::Diameter::operator == (const Diameter& theOther) const
368 {
369   if ( Circle.Location().X()  != theOther.Circle.Location().X()
370     || Circle.Location().Y()  != theOther.Circle.Location().Y()
371     || Circle.Location().Z()  != theOther.Circle.Location().Z()
372     || Circle.Axis().Direction().X() != theOther.Circle.Axis().Direction().X()
373     || Circle.Axis().Direction().Y() != theOther.Circle.Axis().Direction().Y()
374     || Circle.Axis().Direction().Z() != theOther.Circle.Axis().Direction().Z()
375     || Circle.XAxis().Direction().X() != theOther.Circle.XAxis().Direction().X()
376     || Circle.XAxis().Direction().Y() != theOther.Circle.XAxis().Direction().Y()
377     || Circle.XAxis().Direction().Z() != theOther.Circle.XAxis().Direction().Z() 
378     || Circle.Radius() != theOther.Circle.Radius() )
379   {
380     return false;
381   }
382
383   if ( Plane.Location().X() != theOther.Plane.Location().X()
384     || Plane.Location().Y() != theOther.Plane.Location().Y()
385     || Plane.Location().Z() != theOther.Plane.Location().Z()
386     || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X()
387     || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y()
388     || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() )
389   {
390     return false;
391   }
392
393   if ( Flyout   != theOther.Flyout 
394     || TextHPos != theOther.TextHPos 
395     || TextVPos != theOther.TextVPos 
396     || ArrowPos != theOther.ArrowPos )
397   {
398     return false;
399   }
400
401   return true;
402 }
403
404 //=================================================================================
405 // function : Angle::Init
406 // purpose  : 
407 //=================================================================================
408 void GEOMGUI_DimensionProperty::Angle::Init( const Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS )
409 {
410   gp_Trsf aFromLCS;
411   aFromLCS.SetTransformation( gp_Ax3(), theLCS );
412
413   FirstPoint  = theIO->FirstPoint().Transformed( aFromLCS );
414   SecondPoint = theIO->SecondPoint().Transformed( aFromLCS );
415   CenterPoint = theIO->CenterPoint().Transformed( aFromLCS );
416   Flyout      = theIO->GetFlyout();
417   TextHPos    = theIO->DimensionAspect()->TextHorizontalPosition();
418   TextVPos    = theIO->DimensionAspect()->TextVerticalPosition();
419   ArrowPos    = theIO->DimensionAspect()->ArrowOrientation();
420 }
421
422 //=================================================================================
423 // function : Angle::Update
424 // purpose  : 
425 //=================================================================================
426 void GEOMGUI_DimensionProperty::Angle::Update( Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS )
427 {
428   gp_Trsf aToLCS;
429   aToLCS.SetTransformation( theLCS, gp_Ax3() );
430
431   gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS );
432   gp_Pnt aPoint2 = CenterPoint.Transformed( aToLCS );
433   gp_Pnt aPoint3 = SecondPoint.Transformed( aToLCS );
434
435   theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPoint3 );
436   theIO->SetFlyout( Flyout );
437
438   Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
439   aStyle->SetTextHorizontalPosition( TextHPos );
440   aStyle->SetTextVerticalPosition( TextVPos );
441   aStyle->SetArrowOrientation( ArrowPos );
442   theIO->SetDimensionAspect( aStyle );
443 }
444
445 //=================================================================================
446 // function : Angle::ToValues
447 // purpose  : 
448 //=================================================================================
449 void GEOMGUI_DimensionProperty::Angle::ToValues(std::vector<double>& theValues) const
450 {
451   // flyout [2]
452   theValues.push_back( (double) Flyout );
453
454   // text flags [3,4]
455   theValues.push_back( (double) TextHPos );
456   theValues.push_back( (double) TextVPos );
457
458   // arrow flags [5]
459   theValues.push_back( (double) ArrowPos );
460
461   // point 1 [6,7,8]
462   theValues.push_back( (double) FirstPoint.X() );
463   theValues.push_back( (double) FirstPoint.Y() );
464   theValues.push_back( (double) FirstPoint.Z() );
465
466   // point 2 [9,10,11]
467   theValues.push_back( (double) SecondPoint.X() );
468   theValues.push_back( (double) SecondPoint.Y() );
469   theValues.push_back( (double) SecondPoint.Z() );
470
471   // center [12,13,14]
472   theValues.push_back( (double) CenterPoint.X() );
473   theValues.push_back( (double) CenterPoint.Y() );
474   theValues.push_back( (double) CenterPoint.Z() );
475 }
476
477 //=================================================================================
478 // function : Angle::FromValues
479 // purpose  : 
480 //=================================================================================
481 void GEOMGUI_DimensionProperty::Angle::FromValues(int& theIt, const std::vector<double>& theValues)
482 {
483   // flyout [2]
484   Flyout = (Standard_Real) theValues[theIt++];
485
486   // text flags [3,4]
487   TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)theValues[theIt++];
488   TextVPos = (Prs3d_DimensionTextVerticalPosition)  (int)theValues[theIt++];
489
490   // arrow flags [5]
491   ArrowPos = (Prs3d_DimensionArrowOrientation) (int)theValues[theIt++];
492
493   // point 1 [6,7,8]
494   Standard_Real aFirstX = (Standard_Real) theValues[theIt++];
495   Standard_Real aFirstY = (Standard_Real) theValues[theIt++];
496   Standard_Real aFirstZ = (Standard_Real) theValues[theIt++];
497
498   // point 2 [9,10,11]
499   Standard_Real aSecondX = (Standard_Real) theValues[theIt++];
500   Standard_Real aSecondY = (Standard_Real) theValues[theIt++];
501   Standard_Real aSecondZ = (Standard_Real) theValues[theIt++];
502
503   // center [12,13,14]
504   Standard_Real aCenterX = (Standard_Real) theValues[theIt++];
505   Standard_Real aCenterY = (Standard_Real) theValues[theIt++];
506   Standard_Real aCenterZ = (Standard_Real) theValues[theIt++];
507
508   FirstPoint  = gp_Pnt( aFirstX, aFirstY, aFirstZ );
509   SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ );
510   CenterPoint = gp_Pnt( aCenterX, aCenterY, aCenterZ );
511 }
512
513 //=================================================================================
514 // function : Angle::operator == 
515 // purpose  : 
516 //=================================================================================
517 bool GEOMGUI_DimensionProperty::Angle::operator == (const Angle& theOther) const
518 {
519   if ( FirstPoint.X()  != theOther.FirstPoint.X()
520     || FirstPoint.Y()  != theOther.FirstPoint.Y()
521     || FirstPoint.Z()  != theOther.FirstPoint.Z()
522     || SecondPoint.X() != theOther.SecondPoint.X()
523     || SecondPoint.Y() != theOther.SecondPoint.Y()
524     || SecondPoint.Z() != theOther.SecondPoint.Z()
525     || CenterPoint.X() != theOther.CenterPoint.X()
526     || CenterPoint.Y() != theOther.CenterPoint.Y()
527     || CenterPoint.Z() != theOther.CenterPoint.Z() )
528   {
529     return false;
530   }
531
532   if ( Flyout   != theOther.Flyout 
533     || TextHPos != theOther.TextHPos 
534     || TextVPos != theOther.TextVPos 
535     || ArrowPos != theOther.ArrowPos )
536   {
537     return false;
538   }
539
540   return true;
541 }
542
543 //=================================================================================
544 // function : Constructor
545 // purpose  : 
546 //=================================================================================
547 GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty()
548 {
549 }
550
551 //=================================================================================
552 // function : Copy constructor
553 // purpose  : 
554 //=================================================================================
555 GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty( const GEOMGUI_DimensionProperty& theOther )
556 {
557   const VectorOfVisibility& aOtherVis   = theOther.myVisibility;
558   const VectorOfNames& aOtherNames      = theOther.myNames;
559   const VectorOfRecords& aOtherRecords  = theOther.myRecords;
560
561   VectorOfVisibility::const_iterator aVisIt = aOtherVis.constBegin();
562   VectorOfNames::const_iterator   aNamesIt  = aOtherNames.constBegin();
563   VectorOfRecords::const_iterator aRecordIt = aOtherRecords.constBegin();
564   for ( ; aRecordIt != aOtherRecords.constEnd(); ++aVisIt, ++aNamesIt, ++aRecordIt )
565   {
566     RecordPtr aNewRecord;
567     const RecordPtr& aRecord = *aRecordIt;
568     switch( aRecord->Type() )
569     {
570       case DimensionType_Length :
571         aNewRecord = RecordPtr( new Length( *aRecord->AsLength() ) );
572         break;
573
574       case DimensionType_Diameter :
575         aNewRecord = RecordPtr( new Diameter( *aRecord->AsDiameter() ) );
576         break;
577
578       case DimensionType_Angle :
579         aNewRecord = RecordPtr( new Angle( *aRecord->AsAngle() ) );
580         break;
581     }
582
583     myVisibility.append( *aVisIt );
584     myNames.append( *aNamesIt );
585     myRecords.append( aNewRecord );
586   }
587 }
588
589 //=================================================================================
590 // function : Init constructor
591 // purpose  : 
592 //=================================================================================
593 GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty( const std::string& theEntry )
594 {
595   LoadFromAttribute( theEntry );
596 }
597
598 //=================================================================================
599 // function : Init constructor
600 // purpose  : 
601 //=================================================================================
602 GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty( const QString& theProperty )
603 {
604   QRegExp aRegExpItemGroups( PATTERN_ITEM_GROUP );
605   QRegExp aRegExpItem( "^" + PATTERN_ITEM + "$" );
606   aRegExpItemGroups.setMinimal( true );
607   aRegExpItem.setMinimal( true );
608
609   int aPos = 0;
610   while ( ( aPos = aRegExpItemGroups.indexIn( theProperty, aPos ) ) != -1 )
611   {
612     aPos += aRegExpItemGroups.matchedLength();
613
614     QString aStrItem = aRegExpItemGroups.cap(1);
615
616     if ( aRegExpItem.indexIn( aStrItem ) < 0 )
617     {
618       continue;
619     }
620
621     // extract name
622     QString aStrName    = aRegExpItem.cap( 1 );
623     QString aStrVisible = aRegExpItem.cap( 2 );
624     QString aStrType    = aRegExpItem.cap( 3 );
625     QString aStrValues  = aRegExpItem.cap( 4 );
626
627     // extract values
628     aStrName.replace( "::", ":" );
629     bool isVisible = aStrVisible.toInt() != 0;
630     int aType = aStrType.toInt();
631     
632     RecordPtr aRecord;
633     switch ( aType )
634     {
635       case DimensionType_Length   : aRecord = RecordPtr( new Length ); break;
636       case DimensionType_Diameter : aRecord = RecordPtr( new Diameter ); break;
637       case DimensionType_Angle    : aRecord = RecordPtr( new Angle ); break;
638       default:
639         continue;
640     }
641     
642     QRegExp aRegExpValues;
643     switch ( aType )
644     {
645       case DimensionType_Length   : aRegExpValues = QRegExp( "^" + PATTERN_LENGTH + "$" ); break;
646       case DimensionType_Diameter : aRegExpValues = QRegExp( "^" + PATTERN_DIAMETER + "$" ); break;
647       case DimensionType_Angle    : aRegExpValues = QRegExp( "^" + PATTERN_ANGLE + "$" ); break;
648     }
649
650     aRegExpValues.setMinimal(true);
651
652     if ( aRegExpValues.indexIn( aStrValues ) < 0 )
653     {
654       continue;
655     }
656
657     std::vector<double> aValues;
658
659     QStringList aStrListOfValues = aRegExpValues.capturedTexts();
660     QStringList::Iterator aStrListOfValuesIt = aStrListOfValues.begin();
661     ++aStrListOfValuesIt; // skip first capture
662     for ( ; aStrListOfValuesIt != aStrListOfValues.end(); ++aStrListOfValuesIt )
663     {
664       aValues.push_back( (*aStrListOfValuesIt).toDouble() );
665     }
666
667     int aValueIt = 0;
668
669     aRecord->FromValues( aValueIt, aValues );
670
671     myVisibility.append( isVisible );
672     myNames.append( aStrName );
673     myRecords.append( aRecord );
674   }
675 }
676
677 //=================================================================================
678 // function : Destructor
679 // purpose  : 
680 //=================================================================================
681 GEOMGUI_DimensionProperty::~GEOMGUI_DimensionProperty()
682 {
683 }
684
685 //=================================================================================
686 // function : operator QVariant()
687 // purpose  : 
688 //=================================================================================
689 GEOMGUI_DimensionProperty::operator QVariant() const
690 {
691   QVariant aQVariant;
692   aQVariant.setValue( *this );
693   return aQVariant;
694 }
695
696 //=================================================================================
697 // function : operator QString()
698 // purpose  : 
699 //=================================================================================
700 GEOMGUI_DimensionProperty::operator QString() const
701 {
702   QStringList anItems;
703
704   VectorOfVisibility::ConstIterator aVisibilityIt = myVisibility.constBegin();
705   VectorOfRecords::ConstIterator aRecordIt        = myRecords.constBegin();
706   VectorOfNames::ConstIterator aNameIt            = myNames.constBegin();
707   for ( ; aRecordIt != myRecords.constEnd(); ++aRecordIt, ++aNameIt, ++aVisibilityIt )
708   {
709     QString aName            = *aNameIt;
710     const bool& isVisible    = *aVisibilityIt;
711     const RecordPtr& aRecord = *aRecordIt;
712
713     // pack values
714     std::vector<double> aPacked;
715     aRecord->ToValues( aPacked );
716
717     // put values into pattern
718     QString aStringValues;
719     switch ( aRecord->Type() )
720     {
721       case DimensionType_Length   : aStringValues = PATTERN_LENGTH; break;
722       case DimensionType_Diameter : aStringValues = PATTERN_DIAMETER; break;
723       case DimensionType_Angle    : aStringValues = PATTERN_ANGLE; break;
724       default:
725         continue;
726     }
727
728     aStringValues.remove("\\");
729
730     size_t it = 0;
731     for ( ; it < aPacked.size(); ++it )
732     {
733       int aNextPos = aStringValues.indexOf("(.*)");
734       if ( aNextPos < 0 )
735       {
736         break; // invalid pattern
737       }
738
739       aStringValues.replace( aNextPos, 4, QString::number( aPacked.at(it) ) );
740     }
741
742     if ( it < aPacked.size() )
743     {
744       continue; // invalid pattern
745     }
746
747     // replace all ':' to '::' for pattern matching
748     aName.replace(":", "::");
749
750     anItems.append( 
751       QString("{ Name=") + aName +
752       QString(":") + QString("Visible=") + QString::number( isVisible ? 1 : 0 ) +
753       QString(":") + QString("Type=") + QString::number( (int) aRecord->Type() ) +
754       QString(":") + aStringValues + QString(" }") );
755   }
756
757   return anItems.join( ":" );
758 }
759
760 //=================================================================================
761 // function : operator ==
762 // purpose  : 
763 //=================================================================================
764 bool GEOMGUI_DimensionProperty::operator == (const GEOMGUI_DimensionProperty& theOther) const
765 {
766   if ( myVisibility.size() != theOther.myVisibility.size()
767     || myNames.size() != theOther.myNames.size()
768     || myRecords.size() != theOther.myRecords.size() )
769   {
770     return false;
771   }
772
773   for ( int it = 0; it < myRecords.size(); ++it )
774   {
775     if ( myVisibility[it] != theOther.myVisibility[it] )
776     {
777       return false;
778     }
779
780     if ( myNames[it] != theOther.myNames[it] )
781     {
782       return false;
783     }
784
785     const RecordPtr& aRecord = myRecords[it];
786     const RecordPtr& aOtherRecord = theOther.myRecords[it];
787     if ( aRecord->Type() != aOtherRecord->Type() )
788     {
789       return false;
790     }
791
792     switch ( aRecord->Type() )
793     {
794       case DimensionType_Length:
795         if ( (*aRecord->AsLength()) != (*aOtherRecord->AsLength()) )
796         {
797           return false;
798         }
799         break;
800
801       case DimensionType_Diameter:
802         if ( (*aRecord->AsDiameter()) != (*aOtherRecord->AsDiameter()) )
803         {
804           return false;
805         }
806         break;
807
808       case DimensionType_Angle:
809         if ( (*aRecord->AsAngle()) != (*aOtherRecord->AsAngle()) )
810         {
811           return false;
812         }
813         break;
814     }
815   }
816
817   return true;
818 }
819
820 //=================================================================================
821 // function : GetNumber
822 // purpose  : 
823 //=================================================================================
824 int GEOMGUI_DimensionProperty::GetNumber() const
825 {
826   return myRecords.size();
827 }
828
829 //=================================================================================
830 // function : AddRecord
831 // purpose  : 
832 //=================================================================================
833 void GEOMGUI_DimensionProperty::AddRecord( const Handle(AIS_Dimension)& theIO, const gp_Ax3& theLCS )
834 {
835   RecordPtr aNewRecord;
836
837   int aType = TypeFromIO( theIO );
838
839   switch ( aType )
840   {
841     case DimensionType_Length :
842     {
843       Handle(AIS_LengthDimension) aLength = 
844         Handle(AIS_LengthDimension)::DownCast( theIO );
845
846       aNewRecord = RecordPtr( new Length() );
847       aNewRecord->AsLength()->Init( aLength, theLCS );
848       break;
849     }
850
851     case DimensionType_Diameter :
852     {
853       Handle(AIS_DiameterDimension) aDiam =
854         Handle(AIS_DiameterDimension)::DownCast( theIO );
855
856       aNewRecord = RecordPtr( new Diameter() );
857       aNewRecord->AsDiameter()->Init( aDiam, theLCS );
858       break;
859     }
860
861     case DimensionType_Angle :
862     {
863       Handle(AIS_AngleDimension) anAngle =
864         Handle(AIS_AngleDimension)::DownCast( theIO );
865
866       aNewRecord = RecordPtr( new Angle() );
867       aNewRecord->AsAngle()->Init( anAngle, theLCS );
868     }
869   }
870
871   myVisibility.append( true );
872   myNames.append( QString() );
873   myRecords.append( aNewRecord );
874 }
875
876 //=================================================================================
877 // function : AddRecord
878 // purpose  : 
879 //=================================================================================
880 void GEOMGUI_DimensionProperty::AddRecord( const RecordPtr& theRecord )
881 {
882   myVisibility.append( true );
883   myNames.append( QString() );
884   myRecords.append( theRecord );
885 }
886
887 //=================================================================================
888 // function : RemoveRecord
889 // purpose  : 
890 //=================================================================================
891 void GEOMGUI_DimensionProperty::RemoveRecord( const int theIndex )
892 {
893   myNames.remove( theIndex );
894   myVisibility.remove( theIndex );
895   myRecords.remove( theIndex );
896 }
897
898 //=================================================================================
899 // function : Clear
900 // purpose  : 
901 //=================================================================================
902 void GEOMGUI_DimensionProperty::Clear()
903 {
904   myNames.clear();
905   myVisibility.clear();
906   myRecords.clear();
907 }
908
909 //=================================================================================
910 // function : SetRecord
911 // purpose  : 
912 //=================================================================================
913 void GEOMGUI_DimensionProperty::SetRecord( const int theIndex,
914                                            const Handle(AIS_Dimension)& theIO,
915                                            const gp_Ax3& theLCS )
916 {
917   int aType = TypeFromIO( theIO );
918
919   RecordPtr& aChangeRecord = myRecords[theIndex];
920
921   switch ( aType )
922   {
923     case DimensionType_Length :
924     {
925       Handle(AIS_LengthDimension) aLength = 
926         Handle(AIS_LengthDimension)::DownCast( theIO );
927
928       aChangeRecord = RecordPtr( new Length() );
929       aChangeRecord->AsLength()->Init( aLength, theLCS );
930       break;
931     }
932
933     case DimensionType_Diameter :
934     {
935       Handle(AIS_DiameterDimension) aDiam =
936         Handle(AIS_DiameterDimension)::DownCast( theIO );
937
938       aChangeRecord = RecordPtr( new Diameter() );
939       aChangeRecord->AsDiameter()->Init( aDiam, theLCS );
940       break;
941     }
942
943     case DimensionType_Angle :
944     {
945       Handle(AIS_AngleDimension) anAngle =
946         Handle(AIS_AngleDimension)::DownCast( theIO );
947
948       aChangeRecord = RecordPtr( new Angle() );
949       aChangeRecord->AsAngle()->Init( anAngle, theLCS );
950     }
951   }
952 }
953
954 //=================================================================================
955 // function : SetRecord
956 // purpose  : 
957 //=================================================================================
958 void GEOMGUI_DimensionProperty::SetRecord( const int theIndex, const RecordPtr& theRecord )
959 {
960   myRecords[theIndex] = theRecord;
961 }
962
963 //=================================================================================
964 // function : GetRecord
965 // purpose  : 
966 //=================================================================================
967 const GEOMGUI_DimensionProperty::RecordPtr& GEOMGUI_DimensionProperty::GetRecord( const int theIndex ) const
968 {
969   return myRecords[theIndex];
970 }
971
972 //=================================================================================
973 // function : IsVisible
974 // purpose  : 
975 //=================================================================================
976 bool GEOMGUI_DimensionProperty::IsVisible( const int theIndex ) const
977 {
978   return myVisibility[theIndex];
979 }
980
981 //=================================================================================
982 // function : SetVisible
983 // purpose  : 
984 //=================================================================================
985 void GEOMGUI_DimensionProperty::SetVisible( const int theIndex, const bool theIsVisible )
986 {
987   myVisibility[theIndex] = theIsVisible;
988 }
989
990 //=================================================================================
991 // function : GetName
992 // purpose  : 
993 //=================================================================================
994 QString GEOMGUI_DimensionProperty::GetName( const int theIndex ) const
995 {
996   return myNames[theIndex];
997 }
998
999 //=================================================================================
1000 // function : SetName
1001 // purpose  : 
1002 //=================================================================================
1003 void GEOMGUI_DimensionProperty::SetName( const int theIndex, const QString &theName )
1004 {
1005   myNames[theIndex] = theName;
1006 }
1007
1008 //=================================================================================
1009 // function : GetType
1010 // purpose  : 
1011 //=================================================================================
1012 int GEOMGUI_DimensionProperty::GetType( const int theIndex ) const
1013 {
1014   return myRecords[theIndex]->Type();
1015 }
1016
1017 //=================================================================================
1018 // function : LoadFromAttribute
1019 // purpose  : 
1020 //=================================================================================
1021 void GEOMGUI_DimensionProperty::LoadFromAttribute( const std::string& theEntry )
1022 {
1023   Clear();
1024
1025   _PTR(SObject) aSObj = SalomeApp_Application::getStudy()->FindObjectID( theEntry );
1026   if ( !aSObj )
1027   {
1028     return;
1029   }
1030
1031   _PTR(StudyBuilder) aBuilder = SalomeApp_Application::getStudy()->NewBuilder();
1032
1033   _PTR(GenericAttribute) aSeekAtt;
1034   _PTR(AttributeTableOfReal) aRecordsAtt;
1035
1036   if ( !aSObj->FindAttribute( aSeekAtt, "AttributeTableOfReal" ) )
1037   {
1038     return;
1039   }
1040
1041   aRecordsAtt = aSeekAtt;
1042
1043   for ( int aRecordIt = 1; aRecordIt <= aRecordsAtt->GetNbColumns(); ++aRecordIt )
1044   {
1045     std::vector<double> aPacked = aRecordsAtt->GetColumn( aRecordIt );
1046
1047     RecordPtr aRecord;
1048
1049     QString aName( aRecordsAtt->GetColumnTitle( aRecordIt ).c_str() );
1050
1051     // unpack records
1052     int it = 0;
1053
1054     // visibility [0]
1055     bool isVisible = (bool) aPacked[it++];
1056
1057     // type [1]
1058     int aType = (int) aPacked[it++];
1059
1060     switch (aType)
1061     {
1062       case DimensionType_Length   : aRecord = RecordPtr( new Length ); break;
1063       case DimensionType_Diameter : aRecord = RecordPtr( new Diameter ); break;
1064       case DimensionType_Angle    : aRecord = RecordPtr( new Angle ); break;
1065     }
1066     aRecord->FromValues(it, aPacked);
1067
1068     myVisibility.append( isVisible );
1069     myNames.append( aName );
1070     myRecords.append( aRecord );
1071   }
1072 }
1073
1074 //=================================================================================
1075 // function : SaveToAttribute
1076 // purpose  : 
1077 //=================================================================================
1078 void GEOMGUI_DimensionProperty::SaveToAttribute( const std::string &theEntry )
1079 {
1080   _PTR(SObject) aSObj = SalomeApp_Application::getStudy()->FindObjectID( theEntry );
1081   if ( !aSObj )
1082   {
1083     return;
1084   }
1085
1086   _PTR(StudyBuilder) aBuilder = SalomeApp_Application::getStudy()->NewBuilder();
1087
1088   _PTR(AttributeTableOfReal) aRecordsAtt;
1089
1090   aRecordsAtt = aBuilder->FindOrCreateAttribute( aSObj, "AttributeTableOfReal" );
1091   aRecordsAtt->SetNbColumns( 0 );
1092
1093   for ( int it = 0; it < myRecords.size(); ++it )
1094   {
1095     bool aVisibility   = myVisibility[it];
1096     QString& aName     = myNames[it];
1097     RecordPtr& aRecord = myRecords[it];
1098
1099     std::vector<double> aPacked;
1100
1101     // visibility [0]
1102     aPacked.push_back( (double) aVisibility );
1103
1104     // type [1]
1105     aPacked.push_back( (double) aRecord->Type() );
1106
1107     // values
1108     aRecord->ToValues( aPacked );
1109
1110     aRecordsAtt->AddColumn( aPacked );
1111     aRecordsAtt->SetColumnTitle( it + 1, aName.toStdString() );
1112   }
1113 }
1114
1115 //=================================================================================
1116 // function : TypeFromIO
1117 // purpose  : 
1118 //=================================================================================
1119 int GEOMGUI_DimensionProperty::TypeFromIO( const Handle(AIS_Dimension)& theIO ) const
1120 {
1121   if ( theIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) )
1122   {
1123     return DimensionType_Length;
1124   }
1125
1126   if ( theIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
1127   {
1128     return DimensionType_Diameter;
1129   }
1130
1131   if ( theIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
1132   {
1133     return DimensionType_Angle;
1134   }
1135
1136   Standard_ProgramError::Raise( "unsupported dimension type" );
1137
1138   return 0;
1139 }