Salome HOME
0022661: EDF GEOM: [HYDRO] Integration of the polyline editor in GEOM
[modules/geom.git] / src / SKETCHER / Sketcher_Utils.cxx
1 // Copyright (C) 2007-2014  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   : Sketcher_Utils.cxx
24 //  Author : Sergey KHROMOV
25 //  Module : GEOM
26
27
28 #include "Sketcher_Utils.hxx"
29
30 #include <BRepBuilderAPI_MakeEdge.hxx>
31 #include <BRepBuilderAPI_MakeVertex.hxx>
32 #include <BRepBuilderAPI_MakeWire.hxx>
33 #include <ElSLib.hxx>
34 #include <GeomAPI_Interpolate.hxx>
35 #include <TColgp_HArray1OfPnt.hxx>
36 #include <TopoDS_Wire.hxx>
37
38 const double POINT_CONFUSION_TOLERANCE = 0.0001;
39
40
41 //=======================================================================
42 // function : MakePolyline
43 // purpose  : 
44 //=======================================================================
45 TopoDS_Shape Sketcher_Utils::MakePolyline
46                               (const std::list <double> &theCoords2D,
47                                const Standard_Boolean    IsClosed,
48                                const gp_Ax3             &thePlane)
49 {
50   std::list <gp_Pnt> aPoints;
51   TopoDS_Shape       aResult;
52
53   To3D(theCoords2D, thePlane, aPoints);
54
55   Standard_Integer aNbPnts = aPoints.size();
56
57   if (aNbPnts > 1) {
58     if (IsClosed &&
59         aPoints.front().IsEqual(aPoints.back(), POINT_CONFUSION_TOLERANCE)) {
60       // The polyline should be closed, first and last points are confused.
61       // Remove the last point.
62       aPoints.pop_back();
63       --aNbPnts;
64     }
65   }
66
67   if (aNbPnts == 1) {
68     // The result is vertex.
69     aResult = BRepBuilderAPI_MakeVertex(aPoints.front()).Vertex();
70   } else if (aNbPnts > 1) {
71     // There are several points. Make a polyline.
72     std::list <gp_Pnt>::const_iterator anIter    = aPoints.begin();
73     TopoDS_Vertex                      aVtxFirst =
74                        BRepBuilderAPI_MakeVertex(*anIter).Vertex();
75     TopoDS_Vertex                      aVtx[2];
76     TopoDS_Edge                        aSegment;
77     BRepBuilderAPI_MakeWire            aMkWire;
78
79     aVtx[0] = aVtxFirst;
80
81     for (++anIter; anIter != aPoints.end(); ++anIter) {
82       aVtx[1]  = BRepBuilderAPI_MakeVertex(*anIter).Vertex();
83       aSegment = BRepBuilderAPI_MakeEdge(aVtx[0], aVtx[1]).Edge();
84       aMkWire.Add(aSegment);
85       aVtx[0]  = aVtx[1];
86     }
87
88     if (IsClosed) {
89       // Create a closing segment.
90       aSegment = BRepBuilderAPI_MakeEdge(aVtx[0], aVtxFirst).Edge();
91       aMkWire.Add(aSegment);
92     }
93
94     aResult = aMkWire.Wire();
95   }
96
97   return aResult;
98 }
99
100 //=======================================================================
101 // function : MakeInterpolation
102 // purpose  : 
103 //=======================================================================
104 TopoDS_Shape Sketcher_Utils::MakeInterpolation
105                               (const std::list <double> &theCoords2D,
106                                const Standard_Boolean    IsClosed,
107                                const gp_Ax3             &thePlane)
108 {
109   std::list <gp_Pnt> aPoints;
110   TopoDS_Shape       aResult;
111
112   To3D(theCoords2D, thePlane, aPoints);
113
114   Standard_Integer aNbPnts = aPoints.size();
115
116   if (aNbPnts > 1) {
117     if (IsClosed &&
118         aPoints.front().IsEqual(aPoints.back(), POINT_CONFUSION_TOLERANCE)) {
119       // The polyline should be closed, first and last points are confused.
120       // Remove the last point.
121       aPoints.pop_back();
122       --aNbPnts;
123     }
124   }
125
126   if (aNbPnts == 1) {
127     // The result is vertex.
128     aResult = BRepBuilderAPI_MakeVertex(aPoints.front()).Vertex();
129   } else if (aNbPnts > 1) {
130     std::list <gp_Pnt>::const_iterator anIter        = aPoints.begin();
131     Handle(TColgp_HArray1OfPnt)        aHCurvePoints =
132       new TColgp_HArray1OfPnt(1, aNbPnts);
133     Standard_Integer                   i;
134
135     for (i = 1; anIter != aPoints.end(); ++anIter, ++i) {
136       aHCurvePoints->SetValue(i, *anIter);
137     }
138
139     // Compute BSpline
140     Standard_Real       aTol = Precision::Confusion();
141     GeomAPI_Interpolate aGBC(aHCurvePoints, IsClosed, aTol);
142
143     aGBC.Perform();
144
145     if (aGBC.IsDone()) {
146       TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aGBC.Curve()).Edge();
147       aResult = BRepBuilderAPI_MakeWire(anEdge).Wire();
148     }
149   }
150
151   return aResult;
152 }
153
154 //=======================================================================
155 // function : To3D
156 // purpose  : 
157 //=======================================================================
158 void Sketcher_Utils::To3D(const std::list <double> &theCoords2D,
159                           const gp_Ax3             &thePlane,
160                                 std::list <gp_Pnt> &thePoints)
161 {
162   thePoints.clear();
163
164   if (theCoords2D.empty() || theCoords2D.size() % 2 == 1) {
165     // Odd number of coordinates or empty list. Invalid case.
166     return;
167   }
168
169   std::list <double>::const_iterator anIter = theCoords2D.begin();
170   Standard_Real    aX     = *anIter;
171   Standard_Real    aY     = *(++anIter);
172   gp_Pnt           aPLast = ElSLib::PlaneValue (aX, aY, thePlane);
173   gp_Pnt           aPnt;
174
175   thePoints.push_back(aPLast);
176
177   for (++anIter; anIter != theCoords2D.end(); ++anIter) {
178     aX   = *anIter;
179     aY   = *(++anIter);
180     aPnt =  ElSLib::PlaneValue (aX, aY, thePlane);
181
182     if (!aPLast.IsEqual(aPnt, POINT_CONFUSION_TOLERANCE)) {
183       thePoints.push_back(aPnt);
184       aPLast = aPnt;
185     }
186   }
187 }