PageRenderTime 49ms CodeModel.GetById 12ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/src/contrib/geom-5.1.2.7/src/GEOMImpl/GEOMImpl_RevolutionDriver.cpp

http://pythonocc.googlecode.com/
C++ | 522 lines | 383 code | 81 blank | 58 comment | 68 complexity | c685dc8f16ed3bd3c169b4f9c52ccde8 MD5 | raw file
  1// Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
  2// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
  3// 
  4// This library is free software; you can redistribute it and/or
  5// modify it under the terms of the GNU Lesser General Public
  6// License as published by the Free Software Foundation; either 
  7// version 2.1 of the License.
  8// 
  9// This library is distributed in the hope that it will be useful 
 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 12// Lesser General Public License for more details.
 13//
 14// You should have received a copy of the GNU Lesser General Public  
 15// License along with this library; if not, write to the Free Software 
 16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 17//
 18// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 19//
 20#include "utilities.h"
 21
 22#include <Standard_Stream.hxx>
 23
 24#include <GEOMImpl_RevolutionDriver.hxx>
 25#include <GEOMImpl_IShapesOperations.hxx>
 26#include <GEOMImpl_IRevolution.hxx>
 27#include <GEOMImpl_Types.hxx>
 28#include <GEOM_Function.hxx>
 29
 30#include <BRepPrimAPI_MakeRevol.hxx>
 31#include <BRepBuilderAPI_MakeEdge.hxx>
 32#include <BRepBuilderAPI_MakeWire.hxx>
 33#include <BRepBuilderAPI_Transform.hxx>
 34#include <BRepOffsetAPI_MakePipeShell.hxx>
 35#include <BRep_Tool.hxx>
 36#include <BRepLib.hxx>
 37#include <BRepTools.hxx>
 38#include <BRepLProp_SLProps.hxx>
 39#include <BRepClass3d_SolidClassifier.hxx>
 40#include <TopoDS.hxx>
 41#include <TopoDS_Shape.hxx>
 42#include <TopoDS_Compound.hxx>
 43#include <TopoDS_Solid.hxx>
 44#include <TopoDS_Face.hxx>
 45#include <TopoDS_Wire.hxx>
 46#include <TopoDS_Edge.hxx>
 47#include <TopoDS_Vertex.hxx>
 48#include <TopAbs.hxx>
 49#include <TopExp.hxx>
 50#include <TopTools_ListOfShape.hxx>
 51#include <TopTools_ListIteratorOfListOfShape.hxx>
 52#include <TopExp_Explorer.hxx>
 53#include <GProp_GProps.hxx>
 54#include <BRepGProp.hxx>
 55
 56#include <gp_Pnt.hxx>
 57#include <gp_Lin.hxx>
 58#include <gp_Dir.hxx>
 59#include <gp_Ax2.hxx>
 60#include <Geom_CylindricalSurface.hxx>
 61#include <Geom_ConicalSurface.hxx>
 62#include <Geom_Line.hxx>
 63#include <Geom2d_TrimmedCurve.hxx>
 64#include <GeomAPI_ProjectPointOnCurve.hxx>
 65#include <GCE2d_MakeSegment.hxx>
 66#include <ShHealOper_Sewing.hxx>
 67#include <ShHealOper_FillHoles.hxx>
 68#include <BRepAdaptor_Curve.hxx>
 69
 70#include <Precision.hxx>
 71#include <StdFail_NotDone.hxx>
 72#include <Standard_TypeMismatch.hxx>
 73#include <Standard_ConstructionError.hxx>
 74
 75
 76
 77gp_Pnt GetVertexOnWireNotOnAxis(TopoDS_Wire aWire/*, Standard_Boolean isFirst*/, gp_Ax1 ax)
 78{
 79	//find a subvertex of the wire that isn't on ax
 80	Handle_Geom_Line aLine = new Geom_Line(ax);
 81
 82	TopTools_IndexedMapOfShape	map;
 83	TopExp::MapShapes( aWire, TopAbs_VERTEX, map );
 84	for( int i=1; i<=map.Extent(); i++ )
 85	{
 86		gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( map.FindKey( i ) ) );
 87		GeomAPI_ProjectPointOnCurve proj(p,aLine);
 88		if( proj.NbPoints() > 0 )
 89		{
 90			if( proj.Distance( 1 ) > Precision::Confusion() )
 91				return p;			
 92		}			
 93	}
 94	// if we got here, we haven't found a vertex NOT on ax
 95	// search for a value of an edge NOT on ax
 96	const int nSamples=10;
 97	map.Clear();
 98	TopExp::MapShapes( aWire, TopAbs_EDGE, map );
 99	for( int i=1; i<=map.Extent(); i++ )
100	{
101		BRepAdaptor_Curve curve(TopoDS::Edge( map.FindKey( i ) ));
102		Standard_Real umin = curve.FirstParameter();
103		Standard_Real umax = curve.LastParameter();
104		for( int n = 0; n <= nSamples; n++ )
105		{
106			Standard_Real u = umin + (float(n)/float(nSamples))*( umax - umin );
107			gp_Pnt p = curve.Value(u);
108			GeomAPI_ProjectPointOnCurve proj(p,aLine);
109			if( proj.NbPoints() > 0 )
110			{
111				if( proj.Distance( 1 ) > Precision::Confusion() )
112					return p;			
113			}
114		}			
115	}
116	// if we got here, no appropriate point was found, so throw an exception
117    Standard_ConstructionError::Raise("No point found on wire, that is not on axis");
118    return gp_Pnt(0., 0., 0.);
119}
120
121static TopoDS_Wire getHelicalSpine( gp_Pnt p, gp_Ax1 ax, Standard_Real angle, Standard_Real aConicalAngle, Standard_Real offset )
122{
123	//project the point on the axis
124	Handle_Geom_Line aLine = new Geom_Line(ax);
125	GeomAPI_ProjectPointOnCurve proj(p,aLine);
126	gp_Pnt pOnAx = proj.Point(1);
127	gp_Vec vec(pOnAx,p);
128	gp_Ax2 ax2( pOnAx, ax.Direction(), gp_Dir(vec) );
129
130	// create the surface
131	Handle(Geom_ElementarySurface) aSurf;
132	if (aConicalAngle)
133	  aSurf = new Geom_ConicalSurface ( ax2, aConicalAngle, vec.Magnitude() );
134	else
135	  aSurf = new Geom_CylindricalSurface ( ax2, vec.Magnitude() );
136
137	//create the 2d line on the surface
138	Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(gp_Pnt2d(0.0,0.0), gp_Pnt2d(angle,offset) );
139	TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aSegment , aSurf);
140	TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge);
141	BRepLib::BuildCurves3d(aWire);
142
143	return aWire;
144}
145
146static const TopTools_ListOfShape& getThruSections( TopoDS_Wire w, gp_Ax1 ax, Standard_Real angle, Standard_Real aConicalAngle, Standard_Real offset, int sectionCount )
147{
148	static TopTools_ListOfShape result;
149	result.Clear();
150
151	gp_Trsf tsfTrans;
152	gp_Trsf tsfRot;
153	gp_Trsf tsfCone;
154
155	gp_Vec anOffsetVec = gp_Vec(ax.Direction());
156	Handle_Geom_Line anAxisLine = new Geom_Line(ax);
157
158	for( int i = 1; i <= sectionCount; i++ )
159	{
160		Standard_Real anOffset = offset*double(i)/double(sectionCount);
161		tsfTrans.SetTranslation( anOffset*anOffsetVec );
162		BRepBuilderAPI_Transform trsfTrans(tsfTrans);
163		trsfTrans.Perform(w, Standard_True);
164
165		Standard_Real anAngle = angle*double(i)/double(sectionCount);
166		tsfRot.SetRotation( ax, anAngle );
167		BRepBuilderAPI_Transform trsfRot(tsfRot);
168		trsfRot.Perform(trsfTrans, Standard_False);
169
170		if (aConicalAngle) {
171			gp_Pnt theCurrentPnt = GetVertexOnWireNotOnAxis(TopoDS::Wire(trsfRot), ax);
172
173			GeomAPI_ProjectPointOnCurve proj(theCurrentPnt,anAxisLine);
174			gp_Pnt pOnAx = proj.Point(1);
175			gp_Vec CurrVec(pOnAx,theCurrentPnt);
176			CurrVec.Normalize();
177
178			Standard_Real aConicOffset = anOffset * (Tan(aConicalAngle));
179			tsfCone.SetTranslation(CurrVec*aConicOffset);
180			BRepBuilderAPI_Transform trsfCone(tsfCone);
181			trsfCone.Perform(trsfRot, Standard_False);
182
183			result.Append(trsfCone);
184		}
185		else
186			result.Append(trsfRot);
187	}
188	return result;
189}
190
191
192//=======================================================================
193//function : GetID
194//purpose  :
195//=======================================================================
196const Standard_GUID& GEOMImpl_RevolutionDriver::GetID()
197{
198  static Standard_GUID aRevolutionDriver("FF1BBB18-5D14-4df2-980B-3A668264EA16");
199  return aRevolutionDriver;
200}
201
202//=======================================================================
203//function : GEOMImpl_RevolutionDriver
204//purpose  :
205//=======================================================================
206GEOMImpl_RevolutionDriver::GEOMImpl_RevolutionDriver()
207{
208}
209
210//=======================================================================
211//function : Execute
212//purpose  :
213//======================================================================= 
214Standard_Integer GEOMImpl_RevolutionDriver::Execute(TFunction_Logbook& log) const
215{
216  if (Label().IsNull()) return 0;    
217  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
218
219  GEOMImpl_IRevolution aCI (aFunction);
220  Standard_Integer aType = aFunction->GetType();
221
222  TopoDS_Shape aShape;
223
224  if (aType == REVOLUTION_BASE_AXIS_ANGLE || aType == REVOLUTION_BASE_AXIS_ANGLE_2WAYS) {
225    Handle(GEOM_Function) aRefBase = aCI.GetBase();
226    Handle(GEOM_Function) aRefAxis = aCI.GetAxis();
227    TopoDS_Shape aShapeBase = aRefBase->GetValue();
228    TopoDS_Shape aShapeAxis = aRefAxis->GetValue();
229    if (aShapeAxis.ShapeType() != TopAbs_EDGE) {
230      Standard_TypeMismatch::Raise("Revolution Axis must be an edge");
231    }
232
233    TopoDS_Edge anE = TopoDS::Edge(aShapeAxis);
234    TopoDS_Vertex V1, V2;
235    TopExp::Vertices(anE, V1, V2, Standard_True);
236    if (V1.IsNull() || V2.IsNull()) {
237      Standard_ConstructionError::Raise("Bad edge for the Revolution Axis given");
238    }
239
240    gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
241    if (aV.Magnitude() < Precision::Confusion()) {
242      Standard_ConstructionError::Raise
243        ("End vertices of edge, defining the Revolution Axis, are too close");
244    }
245
246    if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
247      gp_Lin aL(BRep_Tool::Pnt(V1), gp_Dir(aV));
248      Standard_Real d = aL.Distance(BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase)));
249      if (d < Precision::Confusion()) {
250	Standard_ConstructionError::Raise("Vertex to be rotated is too close to Revolution Axis");
251      }
252    }
253    double anAngle = aCI.GetAngle();
254    gp_Ax1 anAxis (BRep_Tool::Pnt(V1), aV);
255    if (aType == REVOLUTION_BASE_AXIS_ANGLE_2WAYS)
256      {
257	gp_Trsf aTrsf;
258	aTrsf.SetRotation(anAxis, ( -anAngle ));
259	BRepBuilderAPI_Transform aTransformation(aShapeBase, aTrsf, Standard_False);
260	aShapeBase = aTransformation.Shape();
261	anAngle = anAngle * 2;
262      }
263    BRepPrimAPI_MakeRevol MR (aShapeBase, anAxis, anAngle, Standard_False);
264    if (!MR.IsDone()) MR.Build();
265    if (!MR.IsDone()) StdFail_NotDone::Raise("Revolution algorithm has failed");
266    aShape = MR.Shape();
267  } else if (aType == REVOLUTION_BASE_AXIS_ANGLE_OFFSET) {
268    /*
269	MakeRevolutionAxisAngleOffset creates a shape by revolving a vertex/edge/wire/face(the "profile") around an axis with an offset along the axis.
270	Depending on the input shape(vertex,edge,wire or face), the result will be an edge,face,shell or solid, in that order.
271  	To keep the order of the result shape low, the function acts per revolution. For each revolution the function creates 
272	- a helix spine beginning at a vertex on the profile, see getHelicalSpine.
273	- 4 thru sections to delimit the result shape
274	Then BRepOffsetAPI_MakePipeShell is used to build each an intermediate result for each revolution.
275	These revolutions are then sewn together to build the result.
276	*/
277    Handle(GEOM_Function) aRefBase = aCI.GetBase();
278	Handle(GEOM_Function) aRefAxis = aCI.GetAxis();
279
280	TopoDS_Shape aShapeBase = aRefBase->GetValue();
281	TopoDS_Shape aShapeAxis = aRefAxis->GetValue();
282
283    if (aShapeAxis.ShapeType() != TopAbs_EDGE) {
284      Standard_TypeMismatch::Raise("Revolution Axis must be an edge");
285    }
286
287    TopoDS_Edge anE = TopoDS::Edge(aShapeAxis);
288    TopoDS_Vertex V1, V2;
289	TopExp::Vertices(anE, V1, V2, Standard_True);
290    if (V1.IsNull() || V2.IsNull()) {
291      Standard_ConstructionError::Raise("Bad edge for the Revolution Axis given");
292    }
293
294    gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
295    if (aV.Magnitude() < Precision::Confusion()) {
296      Standard_ConstructionError::Raise
297        ("End vertices of edge, defining the Revolution Axis, are too close");
298    }
299
300    if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
301      gp_Lin aL(BRep_Tool::Pnt(V1), gp_Dir(aV));
302	  Standard_Real d = aL.Distance(BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase)));
303	  if (d < Precision::Confusion()) {
304		Standard_ConstructionError::Raise("Vertex to be rotated is too close to Revolution Axis");
305      }
306	}
307
308	gp_Ax1 anAxis (BRep_Tool::Pnt(V1), aV);
309	//values from driver
310	Standard_Real theTotalAngleInRAD = aCI.GetAngle();
311	Standard_Real theTotalOffset = aCI.GetOffset();
312	Standard_Real theConeAngle = aCI.GetConeAngle();
313	//constants used below
314	Standard_Real theRevolutionResolution = (PI/2);
315	Standard_Integer theNbWiresPerRevolution = 4;
316
317	//create the basic wire or vertex
318	TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType();
319
320	Standard_Boolean NeedCreateSolid = Standard_False;
321	Standard_Boolean IsVertex = Standard_False;
322
323	TopoDS_Wire   aWireProf;
324	TopoDS_Vertex myVertex;
325
326	if(aTypeBase == TopAbs_WIRE) {
327		aWireProf = TopoDS::Wire(aShapeBase);
328	}
329	else if(aTypeBase == TopAbs_FACE) {
330		NeedCreateSolid = Standard_True;
331		aWireProf = BRepTools::OuterWire(TopoDS::Face(aShapeBase));
332	}
333	else if(aTypeBase == TopAbs_EDGE){
334		TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase);
335		aWireProf = BRepBuilderAPI_MakeWire(anEdge);
336	}
337	else if(aTypeBase == TopAbs_VERTEX){
338		IsVertex = Standard_True;
339		myVertex = TopoDS::Vertex(aShapeBase);
340	}
341	else
342		Standard_ConstructionError::Raise("Construction element is not of the requested type");
343
344	if (!IsVertex)
345	{
346		gp_Pnt theCurrentPnt = GetVertexOnWireNotOnAxis(aWireProf, anAxis);
347
348		TopoDS_Wire theCurrentWire = aWireProf;
349		Standard_Real theCurrAngle = theTotalAngleInRAD;
350		Standard_Boolean isFinished = Standard_False;
351
352		TopTools_ListOfShape listForCompound;
353		while (!isFinished)
354		{
355			if (theCurrAngle > theRevolutionResolution)
356			  theCurrAngle = theCurrAngle-theRevolutionResolution;
357			else
358			{
359			  theRevolutionResolution = theCurrAngle;
360			  isFinished = Standard_True;
361			}
362			Standard_Real theOffset = (theTotalOffset /theTotalAngleInRAD ) * theRevolutionResolution;
363
364			TopoDS_Wire aSpine = getHelicalSpine( theCurrentPnt, anAxis, theRevolutionResolution, theConeAngle, theOffset );
365			TopoDS_Vertex aFirst, aLast;
366			TopExp::Vertices(aSpine, aFirst, aLast);
367			theCurrentPnt = BRep_Tool::Pnt(aLast);
368
369			const TopTools_ListOfShape& listThru = getThruSections( theCurrentWire, anAxis, theRevolutionResolution, theConeAngle, theOffset, theNbWiresPerRevolution );
370			theCurrentWire = TopoDS::Wire(listThru.Last());
371
372			BRepOffsetAPI_MakePipeShell mps(aSpine);
373			TopTools_ListIteratorOfListOfShape it;
374			for( it.Initialize( listThru ); it.More(); it.Next() )
375				mps.Add( it.Value() );
376
377			listForCompound.Append(mps.Shape());
378		}
379
380		TopoDS_Compound CompoundNotSewed;
381		BRep_Builder CompoundBuilder;
382		CompoundBuilder.MakeCompound(CompoundNotSewed);
383		TopTools_ListIteratorOfListOfShape it;
384		for( it.Initialize( listForCompound ); it.More(); it.Next() )
385		  CompoundBuilder.Add(CompoundNotSewed, it.Value());
386
387		if (NeedCreateSolid) {
388			CompoundBuilder.Add  (CompoundNotSewed,  aShapeBase );
389
390			gp_Trsf tsfTrans;
391			gp_Trsf tsfRot;
392			gp_Trsf tsfCone;
393
394			gp_Vec anOffsetVec = gp_Vec(anAxis.Direction());
395
396			tsfTrans.SetTranslation( theTotalOffset*anOffsetVec );
397			BRepBuilderAPI_Transform trsfTrans(tsfTrans);
398			trsfTrans.Perform(aShapeBase, Standard_True);
399
400			tsfRot.SetRotation( anAxis, theTotalAngleInRAD );
401			BRepBuilderAPI_Transform trsfRot(tsfRot);
402			trsfRot.Perform(trsfTrans, Standard_False);
403
404			if (theConeAngle) {
405				Handle_Geom_Line anAxisLine = new Geom_Line(anAxis);
406				Standard_Real aConicOffset = theTotalOffset * (Tan(theConeAngle));
407
408				gp_Pnt theCurrentPnt =  GetVertexOnWireNotOnAxis(BRepTools::OuterWire(TopoDS::Face(trsfRot)), anAxis);
409
410				GeomAPI_ProjectPointOnCurve proj(theCurrentPnt,anAxisLine);
411				gp_Pnt pOnAx = proj.Point(1);
412				gp_Vec CurrVec(pOnAx,theCurrentPnt);
413				CurrVec.Normalize();
414
415				tsfCone.SetTranslation(CurrVec*aConicOffset);
416				BRepBuilderAPI_Transform trsfCone(tsfCone);
417				trsfCone.Perform(trsfRot, Standard_False);
418
419				CompoundBuilder.Add(CompoundNotSewed,  trsfCone );
420			}
421			else
422				CompoundBuilder.Add(CompoundNotSewed,  trsfRot );
423		}
424
425		Standard_Real DefaultSewTolerance = 10.;
426		ShHealOper_Sewing aHealer (CompoundNotSewed, DefaultSewTolerance);
427		TopoDS_Shape CompoundSewed;
428
429		if (aHealer.Perform())
430			CompoundSewed = aHealer.GetResultShape();
431		else
432			CompoundSewed = CompoundNotSewed;
433
434		if (NeedCreateSolid) {
435			TopoDS_Solid aSolid;
436			BRep_Builder aSolidBuilder;
437			aSolidBuilder.MakeSolid(aSolid);
438
439			TopExp_Explorer aExpW(CompoundSewed, TopAbs_SHELL );
440			for( ; aExpW.More(); aExpW.Next())
441				aSolidBuilder.Add(aSolid, aExpW.Current());
442
443			BRepClass3d_SolidClassifier SC(aSolid);
444			SC.PerformInfinitePoint(Precision::Confusion());
445
446			switch (SC.State()) {
447				case TopAbs_IN:
448				  aShape = aSolid.Reversed();
449				  break;
450				case TopAbs_OUT:
451				  aShape = aSolid;
452				  break;
453				default:
454				  aShape = CompoundSewed;
455			}
456		}
457		else {
458			aShape = CompoundSewed;
459		}
460	}
461	else
462	{
463		gp_Pnt theCurrentPnt = BRep_Tool::Pnt(myVertex);
464		aShape = getHelicalSpine( theCurrentPnt, anAxis, theTotalAngleInRAD, theConeAngle, theTotalOffset );
465	}
466  
467  } else {
468  }
469
470  if (aShape.IsNull()) return 0;
471
472  TopoDS_Shape aRes = GEOMImpl_IShapesOperations::CompsolidToCompound(aShape);
473  aFunction->SetValue(aRes);
474
475  log.SetTouched(Label()); 
476
477  return 1;    
478}
479
480
481//=======================================================================
482//function :  GEOMImpl_RevolutionDriver_Type_
483//purpose  :
484//======================================================================= 
485Standard_EXPORT Handle_Standard_Type& GEOMImpl_RevolutionDriver_Type_()
486{
487
488  static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
489  if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
490  static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
491  if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared); 
492  static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
493  if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
494 
495
496  static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
497  static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_RevolutionDriver",
498			                                 sizeof(GEOMImpl_RevolutionDriver),
499			                                 1,
500			                                 (Standard_Address)_Ancestors,
501			                                 (Standard_Address)NULL);
502
503  return _aType;
504}
505
506//=======================================================================
507//function : DownCast
508//purpose  :
509//======================================================================= 
510const Handle(GEOMImpl_RevolutionDriver) Handle(GEOMImpl_RevolutionDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
511{
512  Handle(GEOMImpl_RevolutionDriver) _anOtherObject;
513
514  if (!AnObject.IsNull()) {
515     if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_RevolutionDriver))) {
516       _anOtherObject = Handle(GEOMImpl_RevolutionDriver)((Handle(GEOMImpl_RevolutionDriver)&)AnObject);
517     }
518  }
519
520  return _anOtherObject ;
521}
522