Salome HOME
Merge from V6_main 13/12/2012
[modules/geom.git] / src / GEOMImpl / GEOMImpl_3DSketcherDriver.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
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.
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 #include <Standard_Stream.hxx>
20
21 #include <GEOMImpl_3DSketcherDriver.hxx>
22 #include <GEOMImpl_I3DSketcher.hxx>
23 #include <GEOMImpl_Types.hxx>
24 #include <GEOM_Function.hxx>
25
26 #include <GEOMImpl_IMeasureOperations.hxx>
27
28 #include <Basics_Utils.hxx>
29
30 // OCCT Includes
31 #include <BRepBuilderAPI_MakePolygon.hxx>
32 #include <BRepBuilderAPI_MakeVertex.hxx>
33 #include <BRepBuilderAPI_MakeEdge.hxx>
34 #include <BRepBuilderAPI_MakeWire.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Shape.hxx>
37 #include <TopoDS_Wire.hxx>
38 #include <gp_Pnt.hxx>
39
40 #include <Standard_ConstructionError.hxx>
41
42 #include <utilities.h>
43
44 //=======================================================================
45 //function : GetID
46 //purpose  :
47 //=======================================================================
48 const Standard_GUID& GEOMImpl_3DSketcherDriver::GetID()
49 {
50   static Standard_GUID a3DSketcherDriver("FF2BBB54-5D24-4df3-210B-3A678263EA26");
51   return a3DSketcherDriver;
52 }
53
54
55 //=======================================================================
56 //function : GEOMImpl_3DSketcherDriver
57 //purpose  :
58 //=======================================================================
59 GEOMImpl_3DSketcherDriver::GEOMImpl_3DSketcherDriver()
60 {
61 }
62
63 //=======================================================================
64 //function : Execute
65 //purpose  :
66 //=======================================================================
67 Standard_Integer GEOMImpl_3DSketcherDriver::Execute(TFunction_Logbook& log) const
68 {
69   if (Label().IsNull()) return 0;
70   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
71
72   GEOMImpl_I3DSketcher aCI (aFunction);
73
74   TopoDS_Shape aShape;
75
76   if (aFunction->GetType() == SKETCHER3D_COORDS) {
77     Handle(TColStd_HArray1OfReal) aCoordsArray = aCI.GetCoordinates();
78     int anArrayLength = aCoordsArray->Length();
79
80     std::list<gp_Pnt> points;
81
82     for (int i = 0; i <= (anArrayLength-3); i += 3) {
83       gp_Pnt aPnt = gp_Pnt(aCoordsArray->Value(i+1), aCoordsArray->Value(i+2), aCoordsArray->Value(i+3));
84       if (points.empty() || aPnt.Distance(points.back()) > gp::Resolution())
85         points.push_back(aPnt);
86     }
87
88     if ( points.size() == 1) { // Only Start Point
89       BRepBuilderAPI_MakeVertex mkVertex (points.back());
90       aShape = mkVertex.Shape();
91     }
92     else if ( points.size() > 1) { // Make Wire
93       BRepBuilderAPI_MakePolygon aMakePoly;
94       std::list<gp_Pnt>::iterator it;
95       for (it = points.begin(); it != points.end(); ++it) {
96         aMakePoly.Add(*it);
97       }
98
99       if (points.size() > 2 && 
100           points.back().X() == points.front().X() && 
101           points.back().Y() == points.front().Y() && 
102           points.back().Z() == points.front().Z())
103         aMakePoly.Close();
104
105       if (aMakePoly.IsDone())
106         aShape = aMakePoly.Wire();
107     }
108   }
109   else if (aFunction->GetType() == SKETCHER3D_COMMAND) {
110     Kernel_Utils::Localizer loc;
111
112     TCollection_AsciiString aCommand = aCI.GetCommand();
113     // "3DSketcher:CMD[:CMD[:CMD...]]"
114
115     // Split the command string to separate CMDs
116     int icmd = 2;
117     TColStd_SequenceOfAsciiString aSequence;
118     if (aCommand.Length()) {
119       TCollection_AsciiString aToken = aCommand.Token(":", icmd);
120       while (aToken.Length() > 0) {
121         aSequence.Append(aToken);
122         aToken = aCommand.Token(":", ++icmd);
123       }
124     }
125
126     int nbEdges = 0;
127     bool isFirstPointSet = false;
128     gp_XYZ p = gp::Origin().XYZ();
129     BRepBuilderAPI_MakeVertex MV0 (p);
130     TopoDS_Vertex V = TopoDS::Vertex(MV0.Shape());
131
132     gp_XYZ p0 = p;
133     TopoDS_Vertex V0 = V;
134
135     bool doClose = false;
136     BRepBuilderAPI_MakeWire MW;
137
138     int nbCMDs = aSequence.Length();
139     for (icmd = 1; icmd <= nbCMDs; icmd++) {
140       TCollection_AsciiString aCMD = aSequence.Value(icmd);
141
142       // Split the CMD into string values
143       TColStd_SequenceOfAsciiString aStrVals;
144       int ival = 1;
145       TCollection_AsciiString aToken = aCMD.Token(" ", ival);
146       while (aToken.Length() > 0) {
147         aStrVals.Append(aToken);
148         aToken = aCMD.Token(" ", ++ival);
149       }
150
151       // "TT x y z" : Create segment by point at X & Y or set the first point
152       // "T dx dy dz" : Create segment by point with DX & DY
153       //
154       // "OXY angleX angle2 length" : Create segment by two angles and length
155       // "OYZ angleY angle2 length" : Create segment by two angles and length
156       // "OXZ angleX angle2 length" : Create segment by two angles and length
157       //
158       // "WW" : Close Wire (to finish)
159
160       switch (aStrVals.Value(1).Value(1))
161       {
162       case 'T':
163         {
164           if (aStrVals.Length() != 4)
165             Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command.");
166
167           gp_XYZ vp;
168           vp.SetX(aStrVals.Value(2).RealValue());
169           vp.SetY(aStrVals.Value(3).RealValue());
170           vp.SetZ(aStrVals.Value(4).RealValue());
171
172           if (aStrVals.Value(1) == "TT") { // absolute coordinates
173             if (!isFirstPointSet) {
174               p = vp;
175               BRepBuilderAPI_MakeVertex MV (p);
176               V = TopoDS::Vertex(MV.Shape());
177
178               p0 = p;
179               V0 = V;
180
181               isFirstPointSet = true;
182             }
183             else {
184               if ((vp - p).SquareModulus() > Precision::Confusion()) {
185                 BRepBuilderAPI_MakeVertex MV (vp);
186                 TopoDS_Vertex VV = TopoDS::Vertex(MV.Shape());
187                 BRepBuilderAPI_MakeEdge ME (V, VV);
188                 MW.Add(ME);
189                 nbEdges++;
190
191                 p = vp;
192                 V = VV;
193               }
194             }
195           }
196           else if (aStrVals.Value(1) == "T") { // relative coordinates
197             if (vp.SquareModulus() > Precision::Confusion()) {
198               vp = p + vp;
199
200               BRepBuilderAPI_MakeVertex MV (vp);
201               TopoDS_Vertex VV = TopoDS::Vertex(MV.Shape());
202               BRepBuilderAPI_MakeEdge ME (V, VV);
203               MW.Add(ME);
204               nbEdges++;
205
206               p = vp;
207               V = VV;
208             }
209           }
210           else
211             Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command.");
212         }
213         break;
214       case 'O':
215         {
216           if (aStrVals.Length() != 4)
217             Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command.");
218
219           char type = aStrVals.Value(1).Value(4);
220           char mode = aStrVals.Value(1).Value(5);
221           
222           double anAngle  = aStrVals.Value(2).RealValue() * M_PI/180.0;
223           double anAngle2 = aStrVals.Value(3).RealValue() * M_PI/180.0; 
224           double aLength  = aStrVals.Value(4).RealValue();
225           
226           double aHeight  = aLength * sin(anAngle2);
227           if (type == 'C')
228           {
229             aHeight = aStrVals.Value(3).RealValue();
230             anAngle2 = 0.0;
231           }
232
233           double aProjectedLength = aLength * cos(anAngle2);
234
235           gp_XYZ vp;
236           vp.SetX(aStrVals.Value(2).RealValue());
237           vp.SetY(aStrVals.Value(3).RealValue());
238           vp.SetZ(aStrVals.Value(4).RealValue());
239           
240           gp_XYZ pref = gp::Origin().XYZ();                 
241           if(mode == 'R')
242             pref = p;
243           
244           TCollection_AsciiString aTruncatedCommand = aStrVals.Value(1);
245           aTruncatedCommand.Trunc(3);
246           
247           if (aTruncatedCommand == "OXY") {
248             vp.SetX(pref.X() + aProjectedLength * cos(anAngle));
249             vp.SetY(pref.Y() + aProjectedLength * sin(anAngle));
250             vp.SetZ(pref.Z() + aHeight);
251           }
252           else if (aTruncatedCommand == "OYZ") {
253             vp.SetX(pref.X() + aHeight);
254             vp.SetY(pref.Y() + aProjectedLength * cos(anAngle));
255             vp.SetZ(pref.Z() + aProjectedLength * sin(anAngle));
256           }
257           else if (aTruncatedCommand == "OXZ") {
258             vp.SetX(pref.X() + aProjectedLength * cos(anAngle));
259             vp.SetY(pref.Y() + aHeight);
260             vp.SetZ(pref.Z() + aProjectedLength * sin(anAngle));
261           }
262           else
263             Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command.");
264           
265           if ((vp - p).SquareModulus() > Precision::Confusion()) {
266             BRepBuilderAPI_MakeVertex MV (vp);
267             TopoDS_Vertex VV = TopoDS::Vertex(MV.Shape());
268             BRepBuilderAPI_MakeEdge ME (V, VV);
269             MW.Add(ME);
270             nbEdges++;
271
272             p = vp;
273             V = VV;
274           }
275         }
276         break;
277       case 'W':
278         {
279           if (aStrVals.Length() != 1)
280             Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command.");
281
282           if (aStrVals.Value(1) == "WW")
283             doClose = true;
284           else
285             Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command.");
286         }
287         break;
288       default:
289         {
290           Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command.");
291         }
292       }
293     }
294
295     if (doClose &&
296         nbEdges > 1 && // as 3D sketcher has only straight edges
297         (p - p0).SquareModulus() > Precision::Confusion()) {
298       BRepBuilderAPI_MakeEdge ME (V, V0);
299       MW.Add(ME);
300       nbEdges++;
301     }
302
303     if (nbEdges > 0) {
304       if (!MW.IsDone())
305         Standard_ConstructionError::Raise("3D Sketcher error: Wire construction failed.");
306
307       aShape = MW;
308     }
309     else {
310       if (isFirstPointSet) {
311         aShape = V0;
312       }
313     }
314   }
315   else {
316   }
317  
318   if (aShape.IsNull()) return 0;
319
320   aFunction->SetValue(aShape);
321   log.SetTouched(Label());
322   return 1;
323 }
324
325
326 //=======================================================================
327 //function :  GEOMImpl_3DSketcherDriver_Type_
328 //purpose  :
329 //=======================================================================
330 Standard_EXPORT Handle_Standard_Type& GEOMImpl_3DSketcherDriver_Type_()
331 {
332
333   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
334   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
335   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
336   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
337   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
338   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
339
340
341   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
342   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_3DSketcherDriver",
343                                                          sizeof(GEOMImpl_3DSketcherDriver),
344                                                          1,
345                                                          (Standard_Address)_Ancestors,
346                                                          (Standard_Address)NULL);
347
348   return _aType;
349 }
350
351 //=======================================================================
352 //function : DownCast
353 //purpose  :
354 //=======================================================================
355 const Handle(GEOMImpl_3DSketcherDriver) Handle(GEOMImpl_3DSketcherDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
356 {
357   Handle(GEOMImpl_3DSketcherDriver) _anOtherObject;
358
359   if (!AnObject.IsNull()) {
360      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_3DSketcherDriver))) {
361        _anOtherObject = Handle(GEOMImpl_3DSketcherDriver)((Handle(GEOMImpl_3DSketcherDriver)&)AnObject);
362      }
363   }
364
365   return _anOtherObject ;
366 }