1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "GEOMImpl_SplineDriver.hxx"
25 #include "GEOMImpl_ISpline.hxx"
26 #include "GEOMImpl_Types.hxx"
27 #include "GEOMImpl_ICurveParametric.hxx"
29 #include "GEOM_Function.hxx"
30 #include "GEOMUtils.hxx"
32 #include <BRepBuilderAPI_MakeEdge.hxx>
33 #include <BRepBuilderAPI_MakeVertex.hxx>
34 #include <BRep_Tool.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Vertex.hxx>
43 #include <Geom_BezierCurve.hxx>
44 #include <GeomAPI_Interpolate.hxx>
48 #include <gp_Circ.hxx>
49 #include <Precision.hxx>
50 #include <TColgp_Array1OfPnt.hxx>
51 #include <TColgp_HArray1OfPnt.hxx>
53 #include <Standard_NullObject.hxx>
55 //=======================================================================
58 //=======================================================================
59 const Standard_GUID& GEOMImpl_SplineDriver::GetID()
61 static Standard_GUID aSplineDriver("FF1BBB33-5D14-4df2-980B-3A668264EA16");
66 //=======================================================================
67 //function : GEOMImpl_SplineDriver
69 //=======================================================================
70 GEOMImpl_SplineDriver::GEOMImpl_SplineDriver()
74 //=======================================================================
77 //=======================================================================
78 Standard_Integer GEOMImpl_SplineDriver::Execute(TFunction_Logbook& log) const
80 if (Label().IsNull()) return 0;
81 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
83 GEOMImpl_ISpline aCI (aFunction);
84 Standard_Integer aType = aFunction->GetType();
88 if (aType == SPLINE_BEZIER ||
89 aType == SPLINE_INTERPOLATION ||
90 aType == SPLINE_INTERPOL_TANGENTS) {
92 bool useCoords = aCI.GetConstructorType() == COORD_CONSTRUCTOR;
94 Handle(TColStd_HArray1OfReal) aCoordsArray; // parametric case
95 Handle(TColStd_HSequenceOfTransient) aPoints; // points case
99 aCoordsArray = aCI.GetCoordinates();
100 aLen = aCoordsArray->Length() / 3;
103 aPoints = aCI.GetPoints();
104 aLen = aPoints->Length();
107 if (aLen < 2) return 0;
109 TColgp_Array1OfPnt points (1, (useCoords ? aLen : 1));
111 int anArrayLength = aCoordsArray->Length();
112 for (int i = 0, j = 1; i <= (anArrayLength-3); i += 3) {
113 gp_Pnt aPnt = gp_Pnt(aCoordsArray->Value(i+1), aCoordsArray->Value(i+2), aCoordsArray->Value(i+3));
114 points.SetValue(j, aPnt);
121 if (aType == SPLINE_BEZIER && aCI.GetIsClosed()) {
124 aV1 = BRepBuilderAPI_MakeVertex(points.Value(1));
127 Handle(GEOM_Function) aFPoint = Handle(GEOM_Function)::DownCast(aPoints->Value(1));
128 TopoDS_Shape aFirstPnt = aFPoint->GetValue();
129 aV1 = TopoDS::Vertex(aFirstPnt);
134 aV2 = BRepBuilderAPI_MakeVertex(points.Value(aLen));
137 Handle(GEOM_Function) aLPoint = Handle(GEOM_Function)::DownCast(aPoints->Value(aLen));
138 TopoDS_Shape aLastPnt = aLPoint->GetValue();
139 aV2 = TopoDS::Vertex(aLastPnt);
142 if (!aV1.IsNull() && !aV2.IsNull() && !aV1.IsSame(aV2)) {
148 Standard_Boolean isSeveral = Standard_False;
151 TColgp_Array1OfPnt CurvePoints (1, aRealLen);
152 for (ind = 1; ind <= aLen; ind++) {
155 aP = points.Value(ind);
156 if (!isSeveral && ind > 1) {
157 if (aP.Distance(aPrevP) > Precision::Confusion()) {
158 isSeveral = Standard_True;
161 CurvePoints.SetValue(ind, aP);
165 Handle(GEOM_Function) aRefPoint = Handle(GEOM_Function)::DownCast(aPoints->Value(ind));
166 TopoDS_Shape aShapePnt = aRefPoint->GetValue();
167 if (aShapePnt.ShapeType() == TopAbs_VERTEX) {
168 aP = BRep_Tool::Pnt(TopoDS::Vertex(aShapePnt));
169 if (!isSeveral && ind > 1) {
170 if (aP.Distance(aPrevP) > Precision::Confusion()) {
171 isSeveral = Standard_True;
174 CurvePoints.SetValue(ind, aP);
180 if (aType == SPLINE_BEZIER) {
182 Standard_ConstructionError::Raise("Points for Bezier Curve are too close");
184 if (aRealLen > aLen) { // set last point equal to first for the closed curve
185 CurvePoints.SetValue(aRealLen, CurvePoints.Value(1));
187 Handle(Geom_BezierCurve) GBC = new Geom_BezierCurve (CurvePoints);
188 aShape = BRepBuilderAPI_MakeEdge(GBC).Edge();
191 //GeomAPI_PointsToBSpline GBC (CurvePoints);
192 //aShape = BRepBuilderAPI_MakeEdge(GBC).Edge();
194 if (aCI.GetDoReordering()) {
195 for (int curInd = 1; curInd < aLen - 1; curInd++) {
196 gp_Pnt curPnt = CurvePoints.Value(curInd);
198 double nearDist = RealLast();
199 for (ind = curInd + 1; ind <= aLen; ind++) {
200 double dist = curPnt.SquareDistance(CurvePoints.Value(ind));
201 if (dist < nearDist && (nearDist - dist) > Precision::Confusion()) {
206 if (nearInd > 0 && nearInd != curInd + 1) {
207 // Keep given order of points to use it in case of equidistant candidates
210 // o o o c o->o->o->o->n o o
212 // curInd curInd+1 nearInd
213 gp_Pnt nearPnt = CurvePoints.Value(nearInd);
214 for (ind = nearInd; ind > curInd + 1; ind--) {
215 CurvePoints.SetValue(ind, CurvePoints.Value(ind - 1));
217 CurvePoints.SetValue(curInd + 1, nearPnt);
222 Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt (1, aLen);
223 for (ind = 1; ind <= aLen; ind++) {
224 aHCurvePoints->SetValue(ind, CurvePoints.Value(ind));
227 bool isClosed = Standard_False;
228 if (aType == SPLINE_INTERPOLATION)
229 isClosed = aCI.GetIsClosed();
231 GeomAPI_Interpolate GBC (aHCurvePoints, isClosed, gp::Resolution());
233 if (aType == SPLINE_INTERPOL_TANGENTS) {
234 Handle(GEOM_Function) aVec1Ref = aCI.GetFirstVector();
235 Handle(GEOM_Function) aVec2Ref = aCI.GetLastVector();
237 if (aVec1Ref.IsNull() || aVec2Ref.IsNull())
238 Standard_NullObject::Raise("Null object is given for a vector");
240 TopoDS_Shape aVec1Sh = aVec1Ref->GetValue();
241 TopoDS_Shape aVec2Sh = aVec2Ref->GetValue();
243 // take orientation of edge into account to avoid regressions, as it was implemented so
244 gp_Vec aV1 = GEOMUtils::GetVector(aVec1Sh, Standard_True);
245 gp_Vec aV2 = GEOMUtils::GetVector(aVec2Sh, Standard_True);
247 GBC.Load(aV1, aV2, /*Scale*/Standard_True);
252 aShape = BRepBuilderAPI_MakeEdge(GBC.Curve()).Edge();
260 if (aShape.IsNull()) return 0;
262 aFunction->SetValue(aShape);
264 log.SetTouched(Label());
269 //================================================================================
271 * \brief Returns a name of creation operation and names and values of creation parameters
273 //================================================================================
275 bool GEOMImpl_SplineDriver::
276 GetCreationInformation(std::string& theOperationName,
277 std::vector<GEOM_Param>& theParams)
279 if (Label().IsNull()) return 0;
280 Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
282 GEOMImpl_ISpline aCI( function );
283 GEOMImpl_ICurveParametric aPI( function );
284 Standard_Integer aType = function->GetType();
286 theOperationName = "CURVE";
290 case SPLINE_INTERPOLATION:
291 case SPLINE_INTERPOL_TANGENTS:
293 AddParam( theParams, "Type", ( aType == SPLINE_BEZIER ? "Bezier" : "Interpolation"));
297 AddParam( theParams, "X(t) equation", aPI.GetExprX() );
298 AddParam( theParams, "Y(t) equation", aPI.GetExprY() );
299 AddParam( theParams, "Z(t) equation", aPI.GetExprZ() );
300 AddParam( theParams, "Min t", aPI.GetParamMin() );
301 AddParam( theParams, "Max t", aPI.GetParamMax() );
302 if ( aPI.GetParamNbStep() )
303 AddParam( theParams, "Number of steps", aPI.GetParamNbStep() );
305 AddParam( theParams, "t step", aPI.GetParamStep() );
309 if ( aCI.GetConstructorType() == COORD_CONSTRUCTOR )
311 Handle(TColStd_HArray1OfReal) coords = aCI.GetCoordinates();
312 GEOM_Param& pntParam = AddParam( theParams, "Points");
313 pntParam << ( coords->Length() ) / 3 << " points: ";
314 for ( int i = coords->Lower(), nb = coords->Upper(); i <= nb; )
315 pntParam << "( " << coords->Value( i++ )
316 << ", " << coords->Value( i++ )
317 << ", " << coords->Value( i++ ) << " ) ";
321 AddParam( theParams, "Points", aCI.GetPoints() );
323 Handle(GEOM_Function) v1 = aCI.GetFirstVector();
324 Handle(GEOM_Function) v2 = aCI.GetLastVector();
325 if ( !v1.IsNull() ) AddParam( theParams, "First tangent vector", v1 );
326 if ( !v2.IsNull() ) AddParam( theParams, "Last tangent vector", v2 );
336 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_SplineDriver,GEOM_BaseDriver);
337 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_SplineDriver,GEOM_BaseDriver);