Salome HOME
updated copyright message
[modules/geom.git] / src / GEOMImpl / GEOMImpl_RotateDriver.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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 #include <Standard_Stream.hxx>
24
25 #include <GEOMImpl_RotateDriver.hxx>
26 #include <GEOMImpl_IRotate.hxx>
27 #include <GEOMImpl_Types.hxx>
28
29 #include <GEOM_Function.hxx>
30
31 #include <GEOMUtils.hxx>
32
33 #include <BRepBuilderAPI_Transform.hxx>
34 #include <BRep_Builder.hxx>
35 #include <BRep_Tool.hxx>
36 #include <BRepGProp.hxx>
37
38 #include <TopAbs.hxx>
39 #include <TopExp.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Vertex.hxx>
43 #include <TopoDS_Compound.hxx>
44 #include <TopoDS_Edge.hxx>
45
46 #include <GeomAPI_ProjectPointOnCurve.hxx>
47 #include <Geom_Line.hxx>
48 #include <GProp_GProps.hxx>
49
50 #include <Precision.hxx>
51
52 #include <gp_Trsf.hxx>
53 #include <gp_Pnt.hxx>
54 #include <gp_Vec.hxx>
55 #include <gp_Dir.hxx>
56 #include <gp_Ax1.hxx>
57
58 //=======================================================================
59 //function : GetID
60 //purpose  :
61 //=======================================================================
62 const Standard_GUID& GEOMImpl_RotateDriver::GetID()
63 {
64   static Standard_GUID aRotateDriver("FF1BBB56-5D14-4df2-980B-3A668264EA16");
65   return aRotateDriver;
66 }
67
68
69 //=======================================================================
70 //function : GEOMImpl_RotateDriver
71 //purpose  :
72 //=======================================================================
73
74 GEOMImpl_RotateDriver::GEOMImpl_RotateDriver()
75 {
76 }
77
78 //=======================================================================
79 //function : Execute
80 //purpose  :
81 //=======================================================================
82 Standard_Integer GEOMImpl_RotateDriver::Execute(Handle(TFunction_Logbook)& log) const
83 {
84   if (Label().IsNull()) return 0;
85   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
86
87   if (aFunction.IsNull()) return 0;
88
89   GEOMImpl_IRotate RI(aFunction);
90   gp_Trsf aTrsf;
91   gp_Pnt aCP, aP1, aP2;
92   Standard_Integer aType = aFunction->GetType();
93   Handle(GEOM_Function) anOriginalFunction = RI.GetOriginal();
94   if (anOriginalFunction.IsNull()) return 0;
95   TopoDS_Shape aShape, anOriginal = anOriginalFunction->GetValue();
96   if (anOriginal.IsNull()) return 0;
97
98   if (aType == ROTATE || aType == ROTATE_COPY) {
99     Handle(GEOM_Function) anAxis = RI.GetAxis();
100     if (anAxis.IsNull()) return 0;
101     TopoDS_Shape A = anAxis->GetValue();
102     // do not take into account edge orientation (it is correct)
103     gp_Vec aV = GEOMUtils::GetVector(A, Standard_False);
104     TopoDS_Edge anEdge = TopoDS::Edge(A);
105     gp_Pnt aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge));
106     gp_Dir aDir (aV);
107     gp_Ax1 anAx1 (aP1, aDir);
108
109     Standard_Real anAngle = RI.GetAngle();
110     if (fabs(anAngle) < Precision::Angular()) anAngle += 2.*M_PI; // NPAL19665,19769
111     aTrsf.SetRotation(anAx1, anAngle);
112
113     //NPAL18620: performance problem: multiple locations are accumulated
114     //           in shape and need a great time to process
115     //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False);
116     //aShape = aTransformation.Shape();
117     TopLoc_Location aLocOrig = anOriginal.Location();
118     gp_Trsf aTrsfOrig = aLocOrig.Transformation();
119     //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug
120     aTrsfOrig.PreMultiply(aTrsf);
121     TopLoc_Location aLocRes (aTrsfOrig);
122     aShape = anOriginal.Located(aLocRes);
123   }
124   else if (aType ==  ROTATE_THREE_POINTS || aType == ROTATE_THREE_POINTS_COPY) {
125     Handle(GEOM_Function) aCentPoint = RI.GetCentPoint();
126     Handle(GEOM_Function) aPoint1 = RI.GetPoint1();
127     Handle(GEOM_Function) aPoint2 = RI.GetPoint2();
128     if(aCentPoint.IsNull() || aPoint1.IsNull() || aPoint2.IsNull()) return 0;
129     TopoDS_Shape aCV = aCentPoint->GetValue();
130     TopoDS_Shape aV1 = aPoint1->GetValue();
131     TopoDS_Shape aV2 = aPoint2->GetValue();
132     if(aCV.IsNull() || aCV.ShapeType() != TopAbs_VERTEX) return 0;
133     if(aV1.IsNull() || aV1.ShapeType() != TopAbs_VERTEX) return 0;
134     if(aV2.IsNull() || aV2.ShapeType() != TopAbs_VERTEX) return 0;
135
136     aCP = BRep_Tool::Pnt(TopoDS::Vertex(aCV));
137     aP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1));
138     aP2 = BRep_Tool::Pnt(TopoDS::Vertex(aV2));
139
140     gp_Vec aVec1 (aCP, aP1);
141     gp_Vec aVec2 (aCP, aP2);
142     gp_Dir aDir (aVec1 ^ aVec2);
143     gp_Ax1 anAx1 (aCP, aDir);
144     Standard_Real anAngle = aVec1.Angle(aVec2);
145     if (fabs(anAngle) < Precision::Angular()) anAngle += 2.*M_PI; // NPAL19665
146     aTrsf.SetRotation(anAx1, anAngle);
147     //NPAL18620: performance problem: multiple locations are accumulated
148     //           in shape and need a great time to process
149     //BRepBuilderAPI_Transform aTransformation(anOriginal, aTrsf, Standard_False);
150     //aShape = aTransformation.Shape();
151     TopLoc_Location aLocOrig = anOriginal.Location();
152     gp_Trsf aTrsfOrig = aLocOrig.Transformation();
153     //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug
154     aTrsfOrig.PreMultiply(aTrsf);
155     TopLoc_Location aLocRes (aTrsfOrig);
156     aShape = anOriginal.Located(aLocRes);
157   }
158   else if (aType == ROTATE_1D || aType == ROTATE_1D_STEP) {
159     //Get direction
160     gp_Pnt aP1 = gp::Origin();
161     gp_Dir D = gp::DZ();
162     Handle(GEOM_Function) anAxis = RI.GetAxis();
163     if (!anAxis.IsNull()) {
164       TopoDS_Shape A = anAxis->GetValue();
165       // do not take into account edge orientation (it is correct)
166       gp_Vec aV = GEOMUtils::GetVector(A, Standard_False);
167       TopoDS_Edge anEdge = TopoDS::Edge(A);
168       aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge));
169       D = gp_Dir(aV);
170     }
171     gp_Ax1 AX1 (aP1, D);
172
173     Standard_Integer nbtimes = RI.GetNbIter1();
174     Standard_Real angle = 360. / nbtimes;
175     if (aType == ROTATE_1D_STEP)
176       angle = RI.GetAngle();
177
178     TopoDS_Compound aCompound;
179     BRep_Builder B;
180     B.MakeCompound( aCompound );
181
182     TopLoc_Location aLocOrig = anOriginal.Location();
183     gp_Trsf aTrsfOrig = aLocOrig.Transformation();
184
185     for (int i = 0; i < nbtimes; i++ ) {
186       if (i == 0) { // NPAL19665
187         B.Add(aCompound, anOriginal);
188       }
189       else {
190         aTrsf.SetRotation(AX1, i * angle * M_PI / 180.);
191         //TopLoc_Location aLocRes (aTrsf * aTrsfOrig); // gp_Trsf::Multiply() has a bug
192         gp_Trsf aTrsfNew (aTrsfOrig);
193         aTrsfNew.PreMultiply(aTrsf);
194         TopLoc_Location aLocRes (aTrsfNew);
195         B.Add(aCompound, anOriginal.Located(aLocRes));
196       }
197       //NPAL18620: performance problem: multiple locations are accumulated
198       //           in shape and need a great time to process
199       //BRepBuilderAPI_Transform aBRepTransformation(anOriginal, aTrsf, Standard_False);
200       //B.Add(aCompound, aBRepTransformation.Shape());
201     }
202
203     aShape = aCompound;
204   }
205   else if (aType == ROTATE_2D) {
206     //Get direction
207     gp_Pnt aP1 = gp::Origin();
208     gp_Dir D = gp::DZ();
209     Handle(GEOM_Function) anAxis = RI.GetAxis();
210     if (!anAxis.IsNull()) {
211       TopoDS_Shape A = anAxis->GetValue();
212       // do not take into account edge orientation (it is correct)
213       gp_Vec aV = GEOMUtils::GetVector(A, Standard_False);
214       TopoDS_Edge anEdge = TopoDS::Edge(A);
215       aP1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge));
216       D = gp_Dir(aV);
217     }
218     gp_Ax1 AX1 (aP1, D);
219
220     gp_Trsf aTrsf1;
221     gp_Trsf aTrsf2;
222
223     gp_XYZ aDir2 = RI.GetDir2(); // can be set by previous execution
224     if (aDir2.Modulus() < gp::Resolution()) {
225       // Calculate direction as vector from the axis to the shape's center
226       gp_Pnt P1;
227       GProp_GProps System;
228
229       if (anOriginal.ShapeType() == TopAbs_VERTEX) {
230         P1 = BRep_Tool::Pnt(TopoDS::Vertex( anOriginal ));
231       }
232       else if ( anOriginal.ShapeType() == TopAbs_EDGE || anOriginal.ShapeType() == TopAbs_WIRE ) {
233         BRepGProp::LinearProperties(anOriginal, System);
234         P1 = System.CentreOfMass();
235       }
236       else if ( anOriginal.ShapeType() == TopAbs_FACE || anOriginal.ShapeType() == TopAbs_SHELL ) {
237         BRepGProp::SurfaceProperties(anOriginal, System);
238         P1 = System.CentreOfMass();
239       }
240       else {
241         BRepGProp::VolumeProperties(anOriginal, System);
242         P1 = System.CentreOfMass();
243       }
244
245       Handle(Geom_Line) Line = new Geom_Line(AX1);
246       GeomAPI_ProjectPointOnCurve aPrjTool( P1, Line );
247       gp_Pnt P2 = aPrjTool.NearestPoint();
248
249       if ( P1.IsEqual(P2, Precision::Confusion() ) ) return 0;
250
251       aDir2 = gp_XYZ(P1.X()-P2.X(), P1.Y()-P2.Y(), P1.Z()-P2.Z());
252
253       // Attention: this abnormal action is done for good working of
254       // TransformLikeOther(), used by RestoreSubShapes functionality
255       RI.SetDir2(aDir2);
256     }
257
258     gp_Vec Vec (aDir2);
259     Vec.Normalize();
260
261     Standard_Integer nbtimes2 = RI.GetNbIter2();
262     Standard_Integer nbtimes1 = RI.GetNbIter1();
263     Standard_Real step = RI.GetStep();
264     Standard_Real ang = RI.GetAngle();
265
266     TopLoc_Location aLocOrig = anOriginal.Location();
267     gp_Trsf aTrsfOrig = aLocOrig.Transformation();
268
269     gp_Vec aVec;
270     TopoDS_Compound aCompound;
271     BRep_Builder B;
272     B.MakeCompound( aCompound );
273
274     Standard_Real DX, DY, DZ;
275
276     for (int i = 0; i < nbtimes2; i++ ) {
277       DX = i * step * Vec.X();
278       DY = i * step * Vec.Y();
279       DZ = i * step * Vec.Z();
280       aVec.SetCoord( DX, DY, DZ );
281       aTrsf1.SetTranslation(aVec);
282
283       for (int j = 0; j < nbtimes1; j++ ) {
284         if (j == 0) { // NPAL19665
285           TopLoc_Location aLocRes (aTrsf1 * aTrsfOrig);
286           B.Add(aCompound, anOriginal.Located(aLocRes));
287         }
288         else {
289           aTrsf2.SetRotation(AX1, j * ang * M_PI / 180.);
290           //TopLoc_Location aLocRes (aTrsf2 * aTrsf1 * aTrsfOrig); // gp_Trsf::Multiply() has a bug
291           gp_Trsf aTrsfNew (aTrsfOrig);
292           aTrsfNew.PreMultiply(aTrsf1);
293           aTrsfNew.PreMultiply(aTrsf2);
294           TopLoc_Location aLocRes (aTrsfNew);
295           B.Add(aCompound, anOriginal.Located(aLocRes));
296         }
297         //NPAL18620: performance problem: multiple locations are accumulated
298         //           in shape and need a great time to process
299         //BRepBuilderAPI_Transform aBRepTrsf1 (anOriginal, aTrsf1, Standard_False);
300         //BRepBuilderAPI_Transform aBRepTrsf2 (aBRepTrsf1.Shape(), aTrsf2, Standard_False);
301         //B.Add(aCompound, aBRepTrsf2.Shape());
302       }
303     }
304
305     aShape = aCompound;
306   }
307   else return 0;
308
309
310   if (aShape.IsNull()) return 0;
311
312   aFunction->SetValue(aShape);
313
314   log->SetTouched(Label());
315
316   return 1;
317 }
318
319 //================================================================================
320 /*!
321  * \brief Returns a name of creation operation and names and values of creation parameters
322  */
323 //================================================================================
324
325 bool GEOMImpl_RotateDriver::
326 GetCreationInformation(std::string&             theOperationName,
327                        std::vector<GEOM_Param>& theParams)
328 {
329   if (Label().IsNull()) return 0;
330   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
331
332   GEOMImpl_IRotate aCI( function );
333   Standard_Integer aType = function->GetType();
334
335   switch ( aType ) {
336   case ROTATE:
337   case ROTATE_COPY:
338     theOperationName = "ROTATION";
339     AddParam( theParams, "Object", aCI.GetOriginal() );
340     AddParam( theParams, "Axis", aCI.GetAxis() );
341     AddParam( theParams, "Angle", aCI.GetAngle() );
342     break;
343   case ROTATE_THREE_POINTS:
344   case ROTATE_THREE_POINTS_COPY:
345     theOperationName = "ROTATION";
346     AddParam( theParams, "Object", aCI.GetOriginal() );
347     AddParam( theParams, "Central Point", aCI.GetCentPoint() );
348     AddParam( theParams, "Point 1", aCI.GetPoint1() );
349     AddParam( theParams, "Point 2", aCI.GetPoint2() );
350     break;
351   case ROTATE_1D:
352     theOperationName = "MUL_ROTATION";
353     AddParam( theParams, "Main Object", aCI.GetOriginal() );
354     AddParam( theParams, "Axis", aCI.GetAxis(), "DZ" );
355     AddParam( theParams, "Nb. Times", aCI.GetNbIter1() );
356     break;
357   case ROTATE_1D_STEP:
358     theOperationName = "MUL_ROTATION";
359     AddParam( theParams, "Main Object", aCI.GetOriginal() );
360     AddParam( theParams, "Axis", aCI.GetAxis(), "DZ" );
361     AddParam( theParams, "Angular step", aCI.GetAngle() );
362     AddParam( theParams, "Nb. Times", aCI.GetNbIter1() );
363     break;
364   case ROTATE_2D:
365     theOperationName = "MUL_ROTATION";
366     AddParam( theParams, "Main Object", aCI.GetOriginal() );
367     AddParam( theParams, "Axis", aCI.GetAxis(), "DZ" );
368     AddParam( theParams, "Angular step", aCI.GetAngle() );
369     AddParam( theParams, "Angular Nb. Times", aCI.GetNbIter1() );
370     AddParam( theParams, "Radial step", aCI.GetStep() );
371     AddParam( theParams, "Radial Nb. Times", aCI.GetNbIter2() );
372     break;
373   default:
374     return false;
375   }
376
377   return true;
378 }
379
380 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_RotateDriver,GEOM_BaseDriver)