1 // Copyright (C) 2007-2008 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.
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
22 //#include <Standard_Stream.hxx>
24 #include <GEOMImpl_PositionDriver.hxx>
25 #include <GEOMImpl_IPosition.hxx>
26 #include <GEOMImpl_Types.hxx>
27 #include <GEOM_Function.hxx>
29 #include <GEOMImpl_IMeasureOperations.hxx>
32 #include <BRepBuilderAPI_Transform.hxx>
33 #include <GCPnts_AbscissaPoint.hxx>
34 #include <ShHealOper_EdgeDivide.hxx>
35 #include <BRep_Tool.hxx>
36 #include <BRepTools.hxx>
37 #include <BRepTools_WireExplorer.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopoDS_Vertex.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Wire.hxx>
45 #include <TopExp_Explorer.hxx>
47 #include <Geom_Plane.hxx>
48 #include <Geom_Curve.hxx>
49 #include <GProp_GProps.hxx>
50 #include <BRepGProp.hxx>
51 #include <ShapeAnalysis_Edge.hxx>
52 #include <GeomAdaptor_Curve.hxx>
53 #include <BRepGProp.hxx>
54 #include <ShapeFix_Wire.hxx>
56 #include <Precision.hxx>
61 //=======================================================================
64 //=======================================================================
65 const Standard_GUID& GEOMImpl_PositionDriver::GetID()
67 static Standard_GUID aPositionDriver("FF1BBB69-5D14-4df2-980B-3A668264EA16");
68 return aPositionDriver;
72 //=======================================================================
73 //function : GEOMImpl_PositionDriver
75 //=======================================================================
76 GEOMImpl_PositionDriver::GEOMImpl_PositionDriver()
80 //=======================================================================
83 //=======================================================================
84 Standard_Integer GEOMImpl_PositionDriver::Execute(TFunction_Logbook& log) const
86 if (Label().IsNull()) return 0;
87 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
89 GEOMImpl_IPosition aCI (aFunction);
90 Standard_Integer aType = aFunction->GetType();
94 if (aType == POSITION_SHAPE || aType == POSITION_SHAPE_COPY) {
95 Handle(GEOM_Function) aRefShape = aCI.GetShape();
96 Handle(GEOM_Function) aRefStartLCS = aCI.GetStartLCS();
97 Handle(GEOM_Function) aRefEndLCS = aCI.GetEndLCS();
99 TopoDS_Shape aShapeBase = aRefShape->GetValue();
100 TopoDS_Shape aShapeStartLCS = aRefStartLCS->GetValue();
101 TopoDS_Shape aShapeEndLCS = aRefEndLCS->GetValue();
103 if (aShapeBase.IsNull() || aShapeStartLCS.IsNull() ||
104 aShapeEndLCS.IsNull() || aShapeEndLCS.ShapeType() != TopAbs_FACE)
108 gp_Ax3 aStartAx3, aDestAx3;
111 aDestAx3 = GEOMImpl_IMeasureOperations::GetPosition(aShapeEndLCS);
114 aStartAx3 = GEOMImpl_IMeasureOperations::GetPosition(aShapeStartLCS);
116 // Set transformation
117 aTrsf.SetDisplacement(aStartAx3, aDestAx3);
119 // Perform transformation
120 BRepBuilderAPI_Transform aBRepTrsf (aShapeBase, aTrsf, Standard_False);
121 aShape = aBRepTrsf.Shape();
123 else if (aType == POSITION_SHAPE_FROM_GLOBAL ||
124 aType == POSITION_SHAPE_FROM_GLOBAL_COPY) {
125 Handle(GEOM_Function) aRefShape = aCI.GetShape();
126 Handle(GEOM_Function) aRefEndLCS = aCI.GetEndLCS();
128 TopoDS_Shape aShapeBase = aRefShape->GetValue();
129 TopoDS_Shape aShapeEndLCS = aRefEndLCS->GetValue();
131 if (aShapeBase.IsNull() || aShapeEndLCS.IsNull() ||
132 aShapeEndLCS.ShapeType() != TopAbs_FACE)
136 gp_Ax3 aStartAx3, aDestAx3;
139 aDestAx3 = GEOMImpl_IMeasureOperations::GetPosition(aShapeEndLCS);
141 // Set transformation
142 aTrsf.SetDisplacement(aStartAx3, aDestAx3);
144 // Perform transformation
145 BRepBuilderAPI_Transform aBRepTrsf (aShapeBase, aTrsf, Standard_False);
146 aShape = aBRepTrsf.Shape();
148 else if (aType == POSITION_ALONG_PATH) {
149 Handle(GEOM_Function) aRefShape = aCI.GetShape();
150 Handle(GEOM_Function) aPathShape = aCI.GetPath();
151 double aValue = aCI.GetDistance();
152 bool aReversed = aCI.GetReverse();
154 TopoDS_Shape aShapeBase = aRefShape->GetValue();
155 TopoDS_Shape aPath = aPathShape->GetValue();
157 if (aShapeBase.IsNull() || aPath.IsNull())
160 //Get a Center Of Mass Of Base Object
161 GProp_GProps aSystem;
163 if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
164 aCenterMass = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase));
165 } else if (aShapeBase.ShapeType() == TopAbs_EDGE || aShapeBase.ShapeType() == TopAbs_WIRE) {
166 BRepGProp::LinearProperties(aShapeBase, aSystem);
167 aCenterMass = aSystem.CentreOfMass();
168 } else if (aShapeBase.ShapeType() == TopAbs_FACE || aShapeBase.ShapeType() == TopAbs_SHELL) {
169 BRepGProp::SurfaceProperties(aShapeBase, aSystem);
170 aCenterMass = aSystem.CentreOfMass();
172 BRepGProp::VolumeProperties(aShapeBase, aSystem);
173 aCenterMass = aSystem.CentreOfMass();
176 TopoDS_Shape aTrimmedPath;
178 Handle(Geom_Curve) aCurve;
179 Standard_Real aFirst =0.,aLast=0.;
180 Standard_Real aParam = 0.;
181 Standard_Real aLength = 0.;
183 gp_Pnt aPFirst, aPLast;
185 if ( aPath.ShapeType() == TopAbs_EDGE ) { // The Path is Edge
186 TopoDS_Edge anEdge = TopoDS::Edge(aPath);
188 BRep_Tool::Range(anEdge,aFirst,aLast);
189 aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
191 aCurve = aCurve->Reversed();
193 aCurve->D0(aFirst, aPFirst);
194 aCurve->D0(aLast, aPLast);
196 // Translate a CenterMass of Base Shape to the start of the path
197 if ( !aPFirst.IsEqual(aCenterMass, gp::Resolution()) ) {
199 aCurTrsf.SetTranslation(aCenterMass, aPFirst);
200 aTrsf.PreMultiply(aCurTrsf);
202 aParam = aFirst + aValue*(aLast - aFirst); // Calculate parameter
203 } else if ( aPath.ShapeType() == TopAbs_WIRE ) { // The path Shape is Wire
204 TopoDS_Wire aWire = TopoDS::Wire(aPath);
207 Handle(ShapeFix_Wire) aFixWire = new ShapeFix_Wire;
208 aFixWire->Load(aWire);
209 aFixWire->FixReorder();
210 aWire = aFixWire->Wire();
213 TopTools_SequenceOfShape Edges;
214 Standard_Real nbEdges = 0.;
215 BRepTools_WireExplorer aWE (aWire);
216 for (; aWE.More(); aWE.Next(), nbEdges++) // Explore a Wire on Edges
217 Edges.Append(aWE.Current());
219 Standard_Real aSummOfLen =0.;
220 Standard_Real aCurLen =0.;
221 GeomAdaptor_Curve aAdC;
223 for(int i=1; i<=Edges.Length(); i++) { // Calculate summary Lenght of edges
224 TopoDS_Edge anEdge = TopoDS::Edge(Edges.Value(i));
225 BRep_Tool::Range(anEdge,aFirst,aLast);
226 aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
227 aAdC.Load(aCurve,aFirst,aLast);
228 aCurLen = GCPnts_AbscissaPoint::Length(aAdC,aFirst,aLast);
229 aSummOfLen += aCurLen;
232 // Move BaseShape to the Start Of the Curve
235 anEdge = TopoDS::Edge(Edges.Value(1));
237 anEdge = TopoDS::Edge(Edges.Value(Edges.Length()));
239 BRep_Tool::Range(anEdge,aFirst,aLast);
240 aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
241 aCurve->D0(aFirst, aPFirst);
242 aCurve->D0(aLast, aPLast);
243 if ( !aPFirst.IsEqual(aCenterMass, gp::Resolution()) ) {
245 if (aReversed && anEdge.Orientation() == TopAbs_FORWARD)
248 aCurTrsf.SetTranslation(aCenterMass, aPFirst);
249 aTrsf.PreMultiply(aCurTrsf);
252 Standard_Real aWireLen = aSummOfLen*aValue;
254 for(int i=1; i<=Edges.Length(); i++) {
257 anEdge = TopoDS::Edge(Edges.Value(i));
259 anEdge = TopoDS::Edge(Edges.Value(Edges.Length() - i + 1));
261 aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
262 BRep_Tool::Range(anEdge,aFirst,aLast);
264 if (!aReversed && anEdge.Orientation() == TopAbs_REVERSED)
265 aCurve = aCurve->Reversed();
267 if (aReversed && anEdge.Orientation() == TopAbs_FORWARD)
268 aCurve = aCurve->Reversed();
270 aAdC.Load(aCurve,aFirst,aLast);
271 aCurLen = GCPnts_AbscissaPoint::Length(aAdC,aFirst,aLast);
273 if ( aWireLen > (aSummOfLen + aCurLen) ) { // Transform a Base object along this Edge
274 aSummOfLen += aCurLen;
276 gp_Vec aStartVec1, aStartVec2, aDestVec1, aDestVec2;
277 aCurve->D2(aFirst, aP1, aStartVec1, aStartVec2 );
278 aCurve->D2(aLast, aP2, aDestVec1, aDestVec2 );
280 if (aStartVec2.Magnitude() > gp::Resolution() && aDestVec2.Magnitude() > gp::Resolution()) {
281 gp_Ax3 aStartAx3(aP1, aStartVec1, aStartVec2);
282 gp_Ax3 aDestAx3(aP2, aDestVec1, aDestVec2);
283 aCurTrsf.SetDisplacement(aStartAx3, aDestAx3);
285 aCurTrsf.SetTranslation(aP1, aP2);
287 aTrsf.PreMultiply(aCurTrsf);
290 aLength = aWireLen - aSummOfLen;
291 GCPnts_AbscissaPoint anAbsc(aAdC,aLength,aFirst);
293 aParam = anAbsc.Parameter();
298 return 0; // Unknown Type
302 gp_Vec aStartVec1, aStartVec2, aDestVec1, aDestVec2;
303 aCurve->D2(aFirst, aP1, aStartVec1, aStartVec2 );
304 aCurve->D2(aParam, aP2, aDestVec1, aDestVec2 );
306 if (aStartVec2.Magnitude() > gp::Resolution() && aDestVec2.Magnitude() > gp::Resolution()) {
307 gp_Ax3 aStartAx3(aP1, aStartVec1, aStartVec2);
308 gp_Ax3 aDestAx3(aP2, aDestVec1, aDestVec2);
309 aCurTrsf.SetDisplacement(aStartAx3, aDestAx3);
311 aCurTrsf.SetTranslation(aP1, aP2);
313 aTrsf.PreMultiply(aCurTrsf);
315 if ( !aPFirst.IsEqual(aCenterMass, gp::Resolution()) ) {
317 aCurTrsf.SetTranslation(aPFirst, aCenterMass);
318 aTrsf.PreMultiply(aCurTrsf);
321 // Perform transformation
322 BRepBuilderAPI_Transform aBRepTrsf (aShapeBase, aTrsf, Standard_False);
323 aShape = aBRepTrsf.Shape();
328 if (aShape.IsNull()) return 0;
330 aFunction->SetValue(aShape);
332 log.SetTouched(Label());
338 //=======================================================================
339 //function : GEOMImpl_PositionDriver_Type_
341 //=======================================================================
342 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PositionDriver_Type_()
345 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
346 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
347 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
348 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
349 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
350 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
353 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
354 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PositionDriver",
355 sizeof(GEOMImpl_PositionDriver),
357 (Standard_Address)_Ancestors,
358 (Standard_Address)NULL);
363 //=======================================================================
364 //function : DownCast
366 //=======================================================================
367 const Handle(GEOMImpl_PositionDriver) Handle(GEOMImpl_PositionDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
369 Handle(GEOMImpl_PositionDriver) _anOtherObject;
371 if (!AnObject.IsNull()) {
372 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PositionDriver))) {
373 _anOtherObject = Handle(GEOMImpl_PositionDriver)((Handle(GEOMImpl_PositionDriver)&)AnObject);
377 return _anOtherObject ;