3 #include "GEOMImpl_GlueDriver.hxx"
4 #include "GEOMImpl_IGlue.hxx"
5 #include "GEOMImpl_Types.hxx"
6 #include "GEOM_Function.hxx"
8 #include <BRep_Tool.hxx>
9 #include <BRep_Builder.hxx>
10 #include <BRepLib.hxx>
11 #include <BRepBndLib.hxx>
12 #include <BRepTools_Quilt.hxx>
13 #include <BRepClass3d_SolidClassifier.hxx>
16 #include <TopExp_Explorer.hxx>
19 #include <TopoDS_Shape.hxx>
20 #include <TopoDS_Face.hxx>
21 #include <TopoDS_Edge.hxx>
22 #include <TopoDS_Vertex.hxx>
23 #include <TopoDS_Compound.hxx>
24 #include <TopoDS_Shell.hxx>
25 #include <TopoDS_Solid.hxx>
26 #include <TopTools_ListOfShape.hxx>
27 #include <TopTools_ListIteratorOfListOfShape.hxx>
30 #include <Bnd_Box.hxx>
31 #include <Precision.hxx>
32 #include <Standard_NullObject.hxx>
33 #include <Standard_ConstructionError.hxx>
35 //=======================================================================
38 //=======================================================================
39 const Standard_GUID& GEOMImpl_GlueDriver::GetID()
41 static Standard_GUID aGlueDriver("FF1BBB63-5D14-4df2-980B-3A668264EA16");
46 //=======================================================================
47 //function : GEOMImpl_GlueDriver
49 //=======================================================================
50 GEOMImpl_GlueDriver::GEOMImpl_GlueDriver()
54 //=======================================================================
55 //function : FindSameFace
56 //purpose : for GLUE_FACES
57 //=======================================================================
58 static TopoDS_Face FindSameFace (const TopoDS_Shape& aShape,
64 for (TopExp_Explorer exf (aShape, TopAbs_FACE); exf.More(); exf.Next()) {
67 aFace = TopoDS::Face(exf.Current());
68 TopTools_ListOfShape liste1;
69 TopTools_ListOfShape liste2;
70 for (TopExp_Explorer exp (aFace, TopAbs_VERTEX); exp.More(); exp.Next()) {
71 const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
74 for (TopExp_Explorer exp (F, TopAbs_VERTEX); exp.More(); exp.Next()) {
75 const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
79 if (liste1.Extent() == liste2.Extent())
81 TopTools_ListIteratorOfListOfShape it1 (liste1);
83 for (; it1.More(); it1.Next())
85 bool foundSamePoint = false;
86 gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1.Value()));
87 TopTools_ListIteratorOfListOfShape it2 (liste2);
88 for (; it2.More(); it2.Next()) {
89 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2.Value()));
90 double d = P1.Distance(P2);
93 // found Same Point : P1
94 foundSamePoint = true;
98 isSame = isSame && foundSamePoint;
99 if (! isSame) break; // a vertex does not correspond : not same face
104 break; // a face corresponding to F is found
107 if (!isSame) aFace.Nullify(); // return null face
111 //=======================================================================
112 //function : FindSameEdge
113 //purpose : for GLUE_FACES
114 //=======================================================================
115 static TopoDS_Edge FindSameEdge (const TopoDS_Face& nf,
119 TopoDS_Face newFace = TopoDS::Face(nf.Oriented(TopAbs_REVERSED));
120 TopoDS_Vertex VFirst, VLast;
121 TopExp::Vertices(Eold, VFirst, VLast);
122 gp_Pnt Pf = BRep_Tool::Pnt(VFirst);
123 gp_Pnt Pl = BRep_Tool::Pnt(VLast);
125 for (TopExp_Explorer ee (newFace, TopAbs_EDGE); ee.More(); ee.Next()) {
126 const TopoDS_Edge& E = TopoDS::Edge(ee.Current());
127 TopoDS_Vertex VFn, VLn;
128 TopExp::Vertices(E, VFn, VLn);
129 gp_Pnt Pfn = BRep_Tool::Pnt(VFn);
130 gp_Pnt Pln = BRep_Tool::Pnt(VLn);
131 double dff = Pf.Distance(Pfn);
132 double dfl = Pf.Distance(Pln);
133 double dlf = Pl.Distance(Pfn);
134 double dll = Pl.Distance(Pln);
135 if ((dff < tol3d) && (dll <tol3d)) {
136 // edge forward : Pf - Pl
137 Enew = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
138 Eold = TopoDS::Edge(Eold.Oriented(TopAbs_FORWARD));
141 if ((dfl < tol3d) && (dlf <tol3d)) {
142 // edge reversed : Pf - Pl
143 Enew = TopoDS::Edge(E.Oriented(TopAbs_REVERSED));
144 Eold = TopoDS::Edge(Eold.Oriented(TopAbs_FORWARD));
151 //=======================================================================
152 //function : GlueFaces
154 //=======================================================================
155 TopoDS_Shape GEOMImpl_GlueDriver::GlueFaces (const TopoDS_Shape& theShape,
156 const Standard_Real theTolerance)
158 // prendre un premier shell dans la liste des shells
159 // initialiser un compshell avec ce shell
160 // tant qu'il reste des shells dans la liste
161 // chercher un shell qui a des faces en commun avec le compshell
162 // creer un BRepTools_Quilt
163 // recenser les faces communes issues du compshell, les ajouter au quilt
164 // recenser les faces restantes du shell a inclure, les ajouter au quilt
165 // recenser les edges en double, a remplacer
166 // pour chaque paire d'edge
167 // tester l'orientation relative des aretes
168 // bind dans le quilt de Eold.Forward et Enew.Forward (ou reverse)
169 // recuperer le nouveau shell
170 // l'incorporer dans le compshell
171 // appliquer BRepTools_SameParameter au compshell
172 // (rendre parametres 2D des edges identiques aux parametres 3D)
178 bu.MakeCompound(C); // empty compound;
179 TopTools_ListOfShape shellList;
180 for (TopExp_Explorer exp (theShape, TopAbs_SHELL); exp.More(); exp.Next()) {
181 const TopoDS_Shell& S = TopoDS::Shell(exp.Current());
184 TopTools_ListIteratorOfListOfShape its (shellList);
186 Standard_ConstructionError::Raise("Glue aborted : no shell in shape");
189 TopoDS_Shell S = TopoDS::Shell(its.Value());
190 bu.Add(C, S); // add first shell to compound
191 shellList.Remove(its);
192 bool shellAdded = true;
193 bool bigTolerance = false;
195 while ((shellList.Extent() > 0) && shellAdded) {
197 its.Initialize(shellList);
198 for (; its.More(); its.Next()) {
199 S = TopoDS::Shell(its.Value());
201 // compare tolerance with shape's size
203 BRepBndLib::Add(S, aBox);
204 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
205 aBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
206 Standard_Real aTolerance = theTolerance;
207 if (aBox.IsXThin(100. * aTolerance))
208 aTolerance = 0.01 * (Xmax - Xmin);
209 if (aBox.IsYThin(100. * aTolerance))
210 aTolerance = 0.01 * (Ymax - Ymin);
211 if (aBox.IsZThin(100. * aTolerance))
212 aTolerance = 0.01 * (Zmax - Zmin);
213 if (theTolerance > aTolerance)
216 bool isConnected = false;
217 TopTools_ListOfShape newEdges; // common edges from new compound
218 TopTools_ListOfShape oldEdges; // common edges from face to add
221 bu.MakeCompound(CFN); // empty compound for new faces
222 bu.MakeCompound(CFO); // empty compound for old faces
224 for (TopExp_Explorer exp (S, TopAbs_FACE); exp.More(); exp.Next()) {
225 // try to find corresponding face in new compound
226 TopoDS_Face F = TopoDS::Face(exp.Current());
227 TopoDS_Face newFace = FindSameFace(C,F,aTolerance);
228 if (! newFace.IsNull())
232 bu.Add(CFN, newFace); // common faces from new compound
233 for (TopExp_Explorer ee (F, TopAbs_EDGE); ee.More(); ee.Next()) {
235 TopoDS_Edge Eold = TopoDS::Edge(ee.Current());
236 TopoDS_Edge Enew = FindSameEdge(newFace, Eold, aTolerance);
238 Standard_ConstructionError::Raise("Glue aborted : no same edge in same face");
240 oldEdges.Append(Eold);
241 newEdges.Append(Enew);
244 bu.Add(CFO, F); // not common faces from shell to add
250 BRepTools_Quilt glue;
252 TopTools_ListIteratorOfListOfShape ito (oldEdges);
253 TopTools_ListIteratorOfListOfShape itn (newEdges);
254 for (; ito.More(); ito.Next()) {
256 glue.Bind(TopoDS::Edge(ito.Value()), TopoDS::Edge(itn.Value()));
260 TopoDS_Compound newc = TopoDS::Compound(glue.Shells());
261 for (TopExp_Explorer exs (newc, TopAbs_SHELL); exs.More(); exs.Next()) {
262 TopoDS_Shell NS = TopoDS::Shell(exs.Current());
265 shellList.Remove(its);
266 // remove shell from list
272 if (shellList.Extent() > 0) {
273 TCollection_AsciiString aMsg
274 ("Some shapes can not be glued with others, because they are too far from them.");
276 aMsg += "\n\nWarning: The tolerance is too big for some sub-shapes, 1% of sub-shape size is given instead.";
278 Standard_ConstructionError::Raise(aMsg.ToCString());
281 TopExp_Explorer exp (C, TopAbs_SHELL);
282 Standard_Integer ish = 0;
288 for (; exp.More(); exp.Next()) {
289 TopoDS_Shape Sh = exp.Current();
292 BRepClass3d_SolidClassifier SC(Sol);
293 SC.PerformInfinitePoint(1.E-6); // cf. BRepFill_Confusion() - BRepFill_Evolved.cxx
294 if (SC.State() == TopAbs_IN) {
296 B.Add(Sol,Sh.Reversed());
307 BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
311 //=======================================================================
314 //=======================================================================
315 Standard_Integer GEOMImpl_GlueDriver::Execute(TFunction_Logbook& log) const
317 if (Label().IsNull()) return 0;
318 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
320 GEOMImpl_IGlue aCI (aFunction);
321 Standard_Integer aType = aFunction->GetType();
325 if (aType == GLUE_FACES) {
326 Handle(GEOM_Function) aRefBase = aCI.GetBase();
327 TopoDS_Shape aShapeBase = aRefBase->GetValue();
328 if (aShapeBase.IsNull()) {
329 Standard_NullObject::Raise("Shape for gluing is null");
332 Standard_Real tol3d = aCI.GetTolerance();
333 aShape = GlueFaces(aShapeBase, tol3d);
338 if (aShape.IsNull()) return 0;
340 aFunction->SetValue(aShape);
342 log.SetTouched(Label());
348 //=======================================================================
349 //function : GEOMImpl_GlueDriver_Type_
351 //=======================================================================
352 Standard_EXPORT Handle_Standard_Type& GEOMImpl_GlueDriver_Type_()
355 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
356 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
357 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
358 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
359 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
360 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
363 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
364 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_GlueDriver",
365 sizeof(GEOMImpl_GlueDriver),
367 (Standard_Address)_Ancestors,
368 (Standard_Address)NULL);
373 //=======================================================================
374 //function : DownCast
376 //=======================================================================
377 const Handle(GEOMImpl_GlueDriver) Handle(GEOMImpl_GlueDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
379 Handle(GEOMImpl_GlueDriver) _anOtherObject;
381 if (!AnObject.IsNull()) {
382 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_GlueDriver))) {
383 _anOtherObject = Handle(GEOMImpl_GlueDriver)((Handle(GEOMImpl_GlueDriver)&)AnObject);
387 return _anOtherObject ;