Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Scale.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "GeomAlgoAPI_Scale.h"
21
22 #include <BRepBuilderAPI_Transform.hxx>
23 #include <BRepBuilderAPI_GTransform.hxx>
24
25 //=================================================================================================
26 GeomAlgoAPI_Scale::GeomAlgoAPI_Scale(std::shared_ptr<GeomAPI_Shape> theSourceShape,
27                                      std::shared_ptr<GeomAPI_Pnt>   theCenterPoint,
28                                      double theScaleFactor)
29 {
30   myMethodType = BY_FACTOR;
31   mySourceShape = theSourceShape;
32   myCenterPoint = theCenterPoint;
33   myScaleFactor = theScaleFactor;
34 }
35
36 //=================================================================================================
37 GeomAlgoAPI_Scale::GeomAlgoAPI_Scale(std::shared_ptr<GeomAPI_Shape> theSourceShape,
38                                      std::shared_ptr<GeomAPI_Pnt>   theCenterPoint,
39                                      double theScaleFactorX,
40                                      double theScaleFactorY,
41                                      double theScaleFactorZ)
42 {
43   myMethodType = BY_DIMENSIONS;
44   mySourceShape = theSourceShape;
45   myCenterPoint = theCenterPoint;
46   myScaleFactorX = theScaleFactorX;
47   myScaleFactorY = theScaleFactorY;
48   myScaleFactorZ = theScaleFactorZ;
49 }
50
51 //=================================================================================================
52 bool GeomAlgoAPI_Scale::check()
53 {
54   if (!mySourceShape) {
55     myError = "Scale builder :: source shape is not valid.";
56     return false;
57   }
58   if (!myCenterPoint) {
59     myError = "Scale builder :: center point is not valid.";
60     return false;
61   }
62   switch (myMethodType) {
63     case BY_FACTOR: {
64       if (fabs(myScaleFactor) < Precision::Confusion()) {
65         myError = "Scale builder :: the scale factor is null.";
66         return false;
67       }
68       return true;
69     }
70     case BY_DIMENSIONS: {
71       if (fabs(myScaleFactorX) < Precision::Confusion()) {
72         myError = "Scale builder :: the scale factor in X is null.";
73         return false;
74       }
75       if (fabs(myScaleFactorY) < Precision::Confusion()) {
76         myError = "Scale builder :: the scale factor in Y is null.";
77         return false;
78       }
79       if (fabs(myScaleFactorZ) < Precision::Confusion()) {
80         myError = "Scale builder :: the scale factor in Z is null.";
81         return false;
82       }
83       return true;
84     }
85     default: {
86       myError = "Scale builder :: method not implemented.";
87       return false;
88     }
89   }
90 }
91
92 //=================================================================================================
93 void GeomAlgoAPI_Scale::build()
94 {
95   switch (myMethodType) {
96    case BY_FACTOR : {
97      buildByFactor();
98      break;
99    }
100    case BY_DIMENSIONS : {
101      buildByDimensions();
102      break;
103    }
104    default : {
105      myError = "Scale builder :: method not yet implemented";
106      return;
107    }
108   }
109 }
110
111 //=================================================================================================
112 void GeomAlgoAPI_Scale::buildByFactor()
113 {
114   const gp_Pnt& aCenterPoint = myCenterPoint->impl<gp_Pnt>();
115   gp_Trsf* aTrsf = new gp_Trsf();
116   aTrsf->SetScale(aCenterPoint, myScaleFactor);
117
118   const TopoDS_Shape& aSourceShape = mySourceShape->impl<TopoDS_Shape>();
119
120   if(aSourceShape.IsNull()) {
121     myError = "Scale builder :: source shape does not contain any actual shape.";
122     return;
123   }
124
125   // Transform the shape while copying it.
126   BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aSourceShape, *aTrsf, true);
127   if(!aBuilder) {
128     myError = "Scale builder :: transform initialization failed.";
129     return;
130   }
131
132   setImpl(aBuilder);
133   setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
134
135   if(!aBuilder->IsDone()) {
136     myError = "Scale builder :: algorithm failed.";
137     return;
138   }
139
140   TopoDS_Shape aResult = aBuilder->Shape();
141
142   std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
143   aShape->setImpl(new TopoDS_Shape(aResult));
144   setShape(aShape);
145   setDone(true);
146 }
147
148 //=================================================================================================
149 void GeomAlgoAPI_Scale::buildByDimensions()
150 {
151   const gp_Pnt& aCenterPoint = myCenterPoint->impl<gp_Pnt>();
152
153   // Perform the rotation matrix
154   gp_Mat aMatRot(myScaleFactorX, 0., 0.,
155                  0., myScaleFactorY, 0.,
156                  0., 0., myScaleFactorZ);
157
158   // Perform the tranformation
159   gp_Pnt anOriginPnt(0., 0., 0.);
160   gp_GTrsf aGTrsf;
161   gp_GTrsf aGTrsfP0;
162   gp_GTrsf aGTrsf0P;
163   aGTrsfP0.SetTranslationPart(anOriginPnt.XYZ() - aCenterPoint.XYZ());
164   aGTrsf0P.SetTranslationPart(aCenterPoint.XYZ());
165   aGTrsf.SetVectorialPart(aMatRot);
166   aGTrsf = aGTrsf0P.Multiplied(aGTrsf);
167   aGTrsf = aGTrsf.Multiplied(aGTrsfP0);
168
169   const TopoDS_Shape& aSourceShape = mySourceShape->impl<TopoDS_Shape>();
170
171   if(aSourceShape.IsNull()) {
172     myError = "Scale builder :: source shape does not contain any actual shape.";
173     return;
174   }
175
176   // Transform the shape while copying it.
177   BRepBuilderAPI_GTransform* aBuilder = new BRepBuilderAPI_GTransform(aSourceShape, aGTrsf, true);
178   if(!aBuilder) {
179     myError = "Scale builder :: transform initialization failed.";
180     return;
181   }
182
183   setImpl(aBuilder);
184   setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
185
186   if(!aBuilder->IsDone()) {
187     myError = "Scale builder :: algorithm failed.";
188     return;
189   }
190
191   TopoDS_Shape aResult = aBuilder->Shape();
192
193   std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
194   aShape->setImpl(new TopoDS_Shape(aResult));
195   setShape(aShape);
196   setDone(true);
197 }