Salome HOME
[bos #41409][FORUM] (2024) kindOfShape() bug for CONE2D
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_ShapeInfoFiller_1.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <GEOMAlgo_ShapeInfoFiller.hxx>
21
22 #include <Precision.hxx>
23 #include <TColStd_MapOfInteger.hxx>
24 #include <TColStd_IndexedMapOfInteger.hxx>
25
26 #include <gp_Lin.hxx>
27 #include <gp_XYZ.hxx>
28 #include <gp_Ax1.hxx>
29 #include <gp_Dir.hxx>
30 #include <gp_Vec.hxx>
31 #include <gp_Ax2.hxx>
32 #include <gp_Ax3.hxx>
33
34 #include <ElCLib.hxx>
35
36 #include <GeomAdaptor_Surface.hxx>
37
38 #include <TopoDS.hxx>
39 #include <TopoDS_Vertex.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Wire.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Iterator.hxx>
44
45 #include <BRep_Tool.hxx>
46
47 #include <TopExp.hxx>
48 #include <TopExp_Explorer.hxx>
49
50 #include <TopTools_MapOfShape.hxx>
51 #include <TopTools_IndexedMapOfShape.hxx>
52
53 #include <BRepTools_WireExplorer.hxx>
54 #include <BRepGProp.hxx>
55 #include <GProp_GProps.hxx>
56
57 #include <GEOMAlgo_ShapeInfo.hxx>
58
59 static
60   Standard_Boolean IsEqual(const gp_Sphere& aSp1,
61                            const gp_Sphere& aSp2,
62                            const Standard_Real aTolDst);
63
64 //=======================================================================
65 //function : FillDetails
66 //purpose  :
67 //=======================================================================
68 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Solid& aSd)
69 {
70   Standard_Boolean bIsStepSphere;
71   Standard_Integer i, aNbF, aNbCyl, aNbCon, aNbPgn, aNbRct;
72   Standard_Integer aNbShells, aNbCrc, aNbX;
73   TopoDS_Shape aFCyl, aFCon;
74   TopTools_IndexedMapOfShape aMF;
75   GEOMAlgo_KindOfName aKNF;
76   GEOMAlgo_KindOfDef aKD;
77   //
78   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aSd);
79   aInfo.SetKindOfName(GEOMAlgo_KN_UNKNOWN);
80   //
81   TopExp::MapShapes(aSd, TopAbs_FACE, aMF);
82   //
83   aNbF=aMF.Extent();
84   if (!aNbF) {
85     return;
86   }
87   //
88   //modified by NIZNHY-PKV Tue Jun 09 08:35:23 2015f
89   if (aNbF==2) {
90     // case requested by the customer
91     // specific solid that should be treated as a sphere
92     bIsStepSphere=TreatStepSphere(aSd);
93     if (bIsStepSphere) {
94       return;
95     }
96   }
97   //modified by NIZNHY-PKV Tue Jun 09 08:35:28 2015t
98   //
99   aKD=GEOMAlgo_KD_SPECIFIED;
100   for (i=1; i<=aNbF && aKD==GEOMAlgo_KD_SPECIFIED; ++i) {
101     const TopoDS_Shape& aF=aMF(i);
102     GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aF);
103     aKD=aInfoF.KindOfDef();
104   }
105   if (aKD!=GEOMAlgo_KD_SPECIFIED) {
106     aInfo.SetKindOfName(GEOMAlgo_KN_SOLID);
107     return;
108   }
109   //
110   aNbShells=GEOMAlgo_ShapeInfoFiller::NbShells(aSd);
111   if (aNbShells>1) {
112     aInfo.SetKindOfName(GEOMAlgo_KN_SOLID);
113     return;
114   }
115   //
116   //
117   if (aNbF==1) {
118     // mb: sphere, torus
119     const TopoDS_Shape& aF=aMF(1);
120     GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aF);
121     aKNF=aInfoF.KindOfName(); // mb: sphere, torus
122     if (aKNF==GEOMAlgo_KN_SPHERE ||
123         aKNF==GEOMAlgo_KN_TORUS) {
124       aInfo.SetKindOfName(aKNF);
125       aInfo.SetLocation(aInfoF.Location());
126       aInfo.SetPosition(aInfoF.Position());
127       aInfo.SetRadius1(aInfoF.Radius1());
128       if(aKNF==GEOMAlgo_KN_TORUS) {
129         aInfo.SetRadius2(aInfoF.Radius2());
130       }
131       return;
132     }
133   }
134   //modified by NIZNHY-PKV Tue Jun 09 08:36:08 2015f
135   /*
136   else if (aNbF==2) {
137     // specific solid that should be treated as a sphere
138     bIsStepSphere=TreatStepSphere(aSd);
139     if (bIsStepSphere) {
140       return;
141     }
142   }
143   */
144   //modified by NIZNHY-PKV Tue Jun 09 08:36:12 2015t
145   //
146   aNbCyl=0;
147   aNbCon=0;
148   aNbPgn=0;
149   aNbRct=0;
150   aNbCrc=0;
151   for (i=1; i<=aNbF; ++i) {
152     const TopoDS_Shape& aF=aMF(i);
153     GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aF);
154     aKNF=aInfoF.KindOfName();
155     if (aKNF==GEOMAlgo_KN_CYLINDER) {
156       aFCyl=aF;
157       ++aNbCyl;
158     }
159     else if (aKNF==GEOMAlgo_KN_CONE) {
160       aFCon=aF;
161       ++aNbCon;
162     }
163     else if (aKNF==GEOMAlgo_KN_DISKCIRCLE) {
164       ++aNbCrc;
165     }
166     else if (aKNF==GEOMAlgo_KN_POLYGON ||
167              aKNF==GEOMAlgo_KN_TRIANGLE ||
168              aKNF==GEOMAlgo_KN_QUADRANGLE) {
169       ++aNbPgn;
170     }
171     else if (aKNF==GEOMAlgo_KN_RECTANGLE) {
172       ++aNbPgn;
173       ++aNbRct;
174     }
175   }
176   //
177   aNbX=aNbCyl+aNbCrc;
178   if (aNbCyl==1 && aNbCrc==2 && aNbX==aNbF) {
179     // cylinder (as they understand it)
180     GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aFCyl);
181     aKNF=aInfoF.KindOfName();
182     aInfo.SetKindOfName(aKNF);
183     aInfo.SetLocation(aInfoF.Location());
184     aInfo.SetPosition(aInfoF.Position());
185     aInfo.SetRadius1(aInfoF.Radius1());
186     aInfo.SetHeight(aInfoF.Height());
187     return;
188   }
189   //
190   aNbX=aNbCon+aNbCrc;
191   if (aNbCon==1 && (aNbCrc==1 || aNbCrc==2) && aNbX==aNbF) {
192     // cone
193     GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aFCon);
194     aKNF=aInfoF.KindOfName();
195     aInfo.SetKindOfName(aKNF);
196     aInfo.SetLocation(aInfoF.Location());
197     aInfo.SetPosition(aInfoF.Position());
198     aInfo.SetRadius1(aInfoF.Radius1());
199     aInfo.SetRadius2(aInfoF.Radius2());
200     aInfo.SetHeight(aInfoF.Height());
201     return;
202   }
203   //
204   if (aNbF!=aNbPgn) {
205     return;// -> GEOMAlgo_KN_UNKNOWN
206   }
207   if (aNbPgn!=6) {
208     aInfo.SetKindOfName(GEOMAlgo_KN_POLYHEDRON);
209     return;
210   }
211   // aNbPgn==6
212   if (aNbPgn!=aNbRct) {
213     aInfo.SetKindOfName(GEOMAlgo_KN_POLYHEDRON);
214     return;
215   }
216   //===================================================
217   // aNbRct=6;
218   // box
219   Standard_Integer j, aNbFi, aNbV, iMax, iMin, iMid;
220   Standard_Real aDot, aLength, aWidth, aHeight, aDist[3];
221   Standard_Real aDistMin, aDistMax;
222   gp_Pnt aPi, aPc;
223   gp_Dir aDir[3];
224   gp_XYZ aXYZc;
225   TColStd_IndexedMapOfInteger aMp;
226   TopTools_IndexedMapOfShape aMV, aMFi;
227   //
228   // barycenter aPc
229   TopExp::MapShapes(aSd, TopAbs_VERTEX, aMV);
230   aNbV=aMV.Extent();
231   if (aNbV!=8) {
232     return;
233   }
234   //
235   aXYZc.SetCoord(0.,0.,0.);
236   for (i=1; i<=aNbV; ++i) {
237     const TopoDS_Vertex& aVi=TopoDS::Vertex(aMV(i));
238     aPi=BRep_Tool::Pnt(aVi);
239     const gp_XYZ& aXYZ=aPi.XYZ();
240     aXYZc=aXYZc+aXYZ;
241   }
242   //
243   aXYZc.Divide(aNbV);
244   aPc.SetXYZ(aXYZc);
245   //
246   // 3 faces
247   for (i=1; i<=aNbF; ++i) {
248     if (aMp.Contains(i)) {
249       continue;
250     }
251     //
252     const TopoDS_Shape& aFi=aMF(i);
253     const GEOMAlgo_ShapeInfo& aIFi=myMapInfo.FindFromKey(aFi);
254     const gp_Dir& aDNi=aIFi.Position().Direction();
255     //
256     for (j=i+1; j<=aNbF; ++j) {
257       if (aMp.Contains(j)) {
258         continue;
259       }
260       //
261       const TopoDS_Shape& aFj=aMF(j);
262       const GEOMAlgo_ShapeInfo& aIFj=myMapInfo.FindFromKey(aFj);
263       const gp_Dir& aDNj=aIFj.Position().Direction();
264       //
265       aDot=aDNi*aDNj;
266       if (aDot<0.) {
267         aDot=-aDot;
268       }
269       if (fabs(1.-aDot)<0.0001) {
270         aMp.Add(i);
271         aMp.Add(j);
272         aMFi.Add(aFi);
273         break;
274       }
275       //
276     }
277   }
278   aNbFi=aMFi.Extent();
279   if (aNbFi!=3) {
280     return;
281   }
282   //
283   iMin=-1;
284   iMax=-1;
285   aDistMin=1.e15;
286   aDistMax=-aDistMin;
287   for (i=0; i<aNbFi; ++i) {
288     const TopoDS_Shape& aFi=aMFi(i+1);
289     const GEOMAlgo_ShapeInfo& aIFi=myMapInfo.FindFromKey(aFi);
290     aPi=aIFi.Location();
291     aDist[i]=aPc.Distance(aPi);
292     if (aDist[i]>aDistMax) {
293       aDistMax=aDist[i];
294       iMax=i;
295     }
296     if (aDist[i]<aDistMin) {
297       aDistMin=aDist[i];
298       iMin=i;
299     }
300     gp_Vec aVi(aPc, aPi);
301     gp_Dir aDi(aVi);
302     aDir[i]=aDi;
303   }
304   //
305   if (iMax==iMin) {
306     iMax=0;
307     iMin=1;
308   }
309   iMid=3-iMax-iMin;
310   //
311   aLength=2.*aDist[iMax];
312   aWidth=2.*aDist[iMid];
313   aHeight=2.*aDist[iMin];
314   //
315   gp_Ax2 aAx2(aPc, aDir[iMin], aDir[iMax]);
316   gp_Ax3 aAx3(aAx2);
317   //
318   aInfo.SetKindOfName(GEOMAlgo_KN_BOX);
319   aInfo.SetLocation(aPc);
320   aInfo.SetLength(aLength);
321   aInfo.SetWidth(aWidth);
322   aInfo.SetHeight(aHeight);
323   aInfo.SetPosition(aAx3);
324 }
325 //=======================================================================
326 //function : FillDetails
327 //purpose  :
328 //=======================================================================
329 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
330                                            const gp_Pln& aPln)
331 {
332   Standard_Integer aNbV, aNbE, i, j;
333   Standard_Real aDot, aD0, aD1, aLength, aWidth;
334   gp_Dir aDx[4], aDX;
335   gp_Pnt aPx[4], aP, aPc;
336   gp_XYZ aXYZc;
337   TopExp_Explorer aExp;
338   TopoDS_Shape aE;
339   TopoDS_Wire aW;
340   TopoDS_Edge aEx;
341   TopoDS_Iterator aIt;
342   TopTools_IndexedMapOfShape aMV;
343   BRepTools_WireExplorer aWExp;
344   GEOMAlgo_KindOfName aKN, aKNE;
345   //
346   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
347   //
348   aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
349   //
350   aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
351   aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
352   //
353   // 1. may be it is circle/ellipse
354   if (aNbV==1 && aNbE==1) {
355     aExp.Init(aF, TopAbs_EDGE);
356     if (aExp.More()) {
357       aE=aExp.Current();
358     }
359     //
360     const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE);
361     aKNE=aInfoE.KindOfName();
362     if (aKNE==GEOMAlgo_KN_CIRCLE) {
363       aKN=GEOMAlgo_KN_DISKCIRCLE;
364       aInfo.SetKindOfName(aKN);
365       aInfo.SetRadius1(aInfoE.Radius1());
366       aInfo.SetLocation(aInfoE.Location());
367       aInfo.SetPosition(aInfoE.Position());
368       aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
369     }
370     if (aKNE==GEOMAlgo_KN_ELLIPSE) {
371       aKN=GEOMAlgo_KN_DISKELLIPSE;
372       aInfo.SetKindOfName(aKN);
373       aInfo.SetRadius1(aInfoE.Radius1());
374       aInfo.SetRadius2(aInfoE.Radius2());
375       aInfo.SetLocation(aInfoE.Location());
376       aInfo.SetPosition(aInfoE.Position());
377       aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
378     }
379     return;
380   }// if (aNbV==1 && aNbE==1) {
381   //
382   //
383   Standard_Boolean bSegment;
384   //
385   bSegment=Standard_True;
386   aExp.Init(aF, TopAbs_EDGE);
387   for (; aExp.More() && bSegment; aExp.Next()) {
388     aE=aExp.Current();
389     const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE);
390     aKNE=aInfoE.KindOfName();
391     if (aKNE!=GEOMAlgo_KN_SEGMENT) {
392       bSegment=!bSegment;
393     }
394   }
395   //
396   if (bSegment) {
397   // 2. may be it is TRIANGLE, POLYGON, QUADRANGLE, RECTANGLE
398     aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
399     aInfo.SetKindOfName(GEOMAlgo_KN_POLYGON);
400     //
401     if (aNbV==3 && aNbE==3) {
402       aInfo.SetKindOfName(GEOMAlgo_KN_TRIANGLE);
403       //
404       aXYZc.SetCoord(0.,0.,0.);
405       TopExp::MapShapes(aF, TopAbs_VERTEX, aMV);
406       for (i=1; i<=aNbV; ++i) {
407         const TopoDS_Vertex& aV=TopoDS::Vertex(aMV(i));
408         aP=BRep_Tool::Pnt(aV);
409         const gp_XYZ& aXYZ=aP.XYZ();
410         aXYZc=aXYZc+aXYZ;
411         aPx[i-1]=aP;
412       }
413       aXYZc.Divide(3.);
414       //
415       aPc.SetXYZ(aXYZc);
416       gp_Vec aVX(aPc, aPx[0]);
417       aVX.Normalize();
418       aDX.SetXYZ(aVX.XYZ());
419       const gp_Dir& aDZ=aPln.Axis().Direction();
420       //
421       gp_Ax2 aAx2(aPc, aDZ, aDX);
422       gp_Ax3 aAx3(aAx2);
423       //
424       aInfo.SetLocation(aPc);
425       aInfo.SetPosition(aAx3);
426     } // if (aNbV==3 && aNbE==3) {
427     //
428     if (aNbV==4 && aNbE==4) {
429       aIt.Initialize(aF);
430       if (aIt.More()) {
431         aW=*((TopoDS_Wire*)&aIt.Value());
432       }
433       //
434       aWExp.Init(aW, aF);
435       for (i=0; aWExp.More(); aWExp.Next(), ++i) {
436         aEx=aWExp.Current();
437         const GEOMAlgo_ShapeInfo& aInfoEx=myMapInfo.FindFromKey(aEx);
438         aDx[i]=aInfoEx.Direction();
439         aPx[i]=aInfoEx.Location();
440       }
441       //
442       Standard_Boolean isRectangle = Standard_True;
443       for (i=0; i<4; ++i) {
444         j=(i==3) ? 0 : i+1;
445         aDot=aDx[i]*aDx[j];
446         if (fabs (aDot) > myTolerance) {
447           isRectangle = Standard_False;
448           break;
449         }
450       }
451       //
452       // rectangle
453       // shift location to the center
454       aXYZc.SetCoord(0.,0.,0.);
455       TopExp::MapShapes(aF, TopAbs_VERTEX, aMV);
456       for (i=1; i<=aNbV; ++i) {
457         const TopoDS_Vertex& aV=TopoDS::Vertex(aMV(i));
458         aP=BRep_Tool::Pnt(aV);
459         const gp_XYZ& aXYZ=aP.XYZ();
460         aXYZc=aXYZc+aXYZ;
461       }
462       //
463       // Location : aPc in center of rectangle
464       // Position : 0z is plane normal
465       //            0x is along the first edge (quadrangle) or
466       //            along length (rectangle)
467       //
468       aXYZc.Divide(4.);
469       aPc.SetXYZ(aXYZc);
470       aDX=aDx[0];
471       aInfo.SetLocation(aPc);
472
473       if (isRectangle) {
474       // Calculate sizes
475         gp_Lin aL0(aPx[0], aDx[0]);
476         gp_Lin aL1(aPx[1], aDx[1]);
477         //
478         aD0=aL0.Distance(aPc);
479         aD1=aL1.Distance(aPc);
480         //
481         aLength=aD1;
482         aWidth =aD0;
483
484         if (aD0>aD1) {
485           aLength=aD0;
486           aWidth =aD1;
487           aDX=aDx[1];
488         }
489         //
490         aLength=2.*aLength;
491         aWidth =2.*aWidth;
492         //
493         aInfo.SetLength(aLength);
494         aInfo.SetWidth(aWidth);
495         aInfo.SetKindOfName(GEOMAlgo_KN_RECTANGLE);
496       } else {
497         aInfo.SetKindOfName(GEOMAlgo_KN_QUADRANGLE);
498       }
499       //
500       const gp_Dir& aDZ=aPln.Axis().Direction();
501       gp_Ax2 aAx2(aPc, aDZ, aDX);
502       gp_Ax3 aAx3(aAx2);
503       aInfo.SetPosition(aAx3);
504       //
505     }// if (aNbV==4 && aNbE==4) {
506     return;
507   }// if (bSegment) {
508   //
509   //aInfo.SetKindOfName(GEOMAlgo_KN_PLANE);
510 }
511 //=======================================================================
512 //function : FillDetails
513 //purpose  :
514 //=======================================================================
515 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
516                                            const gp_Sphere& )//aSph)
517 {
518
519   Standard_Integer aNbV, aNbE, aNbSE, aNbDE;
520   TopoDS_Edge aE;
521   TopExp_Explorer aExp;
522   TopTools_MapOfShape aM;
523   GEOMAlgo_KindOfShape aKSE;//, aKSE;
524   //
525   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
526   //
527   aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
528   aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
529   aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
530   if (aNbV==2 && aNbE==3) {
531     aNbSE=0;
532     aNbDE=0;
533     aExp.Init(aF, TopAbs_EDGE);
534     for (; aExp.More(); aExp.Next()) {
535       aE=TopoDS::Edge(aExp.Current());
536       if(aM.Add(aE)) {
537         const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE);
538         aKSE=aInfoE.KindOfShape();
539         //
540         if (BRep_Tool::IsClosed(aE, aF)) {
541           ++aNbSE;
542         }
543         else if (aKSE==GEOMAlgo_KS_DEGENERATED) {
544           ++aNbDE;
545         }
546       }
547     }
548     //
549     if (aNbSE==1 && aNbDE==2) {
550       aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
551     }
552   }
553 }
554 //=======================================================================
555 //function : FillDetails
556 //purpose  :
557 //=======================================================================
558 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
559                                            const gp_Cylinder& aCyl)
560
561 {
562   Standard_Integer aNbV, aNbE, aNbCE, aNbSE;
563   Standard_Real aT0, aT1, aHeight;
564   gp_Pnt aPC[3], aPc;
565   TopoDS_Edge aE;
566   TopExp_Explorer aExp;
567   TopTools_MapOfShape aM;
568   GEOMAlgo_KindOfName aKNE;
569   GEOMAlgo_KindOfClosed aKCE;
570   //
571   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
572   //
573   aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
574   aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
575   aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
576   if (aNbV==2 && aNbE==3) {
577     const gp_Ax1& aAx1=aCyl.Axis();
578     const gp_Dir& aDir=aAx1.Direction();
579     const gp_Pnt& aPLoc=aAx1.Location();
580     //
581     aNbCE=0;
582     aNbSE=0;
583     aExp.Init(aF, TopAbs_EDGE);
584     for (; aExp.More(); aExp.Next()) {
585       aE=TopoDS::Edge(aExp.Current());
586       if(aM.Add(aE)) {
587         const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE);
588         aKNE=aInfoE.KindOfName();
589         aKCE=aInfoE.KindOfClosed();
590         if (aKNE==GEOMAlgo_KN_CIRCLE && aKCE==GEOMAlgo_KC_CLOSED) {
591           aPC[aNbCE]=aInfoE.Location();
592           ++aNbCE;
593         }
594         else if (aKNE==GEOMAlgo_KN_SEGMENT) {
595           if (BRep_Tool::IsClosed(aE, aF)) {
596             ++aNbSE;
597           }
598         }
599       }
600     }
601     //
602     if (aNbCE==2 && aNbSE==1) {
603       gp_Lin aLin(aPLoc, aDir);
604       //
605       aT0=ElCLib::Parameter(aLin, aPC[0]);
606       aT1=ElCLib::Parameter(aLin, aPC[1]);
607       //
608       aPc=aPC[0];
609       if (aT0>aT1) {
610         aPc=aPC[1];
611       }
612       aHeight=aPC[0].Distance(aPC[1]);
613       //
614       gp_Ax3 aAx3=aCyl.Position();
615       aAx3.SetLocation(aPc);
616       //
617       aInfo.SetPosition(aAx3);
618       aInfo.SetLocation(aPc);
619       aInfo.SetHeight(aHeight);
620       //
621       aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
622       return; // conventional cylinder
623     }//if (aNbCE==2 && aNbSE==1) {
624   }//if (aNbV==2 && aNbE==3) {
625 }
626 //=======================================================================
627 //function : FillDetails
628 //purpose  :
629 //=======================================================================
630 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
631                                            const gp_Torus& )
632 {
633
634   Standard_Integer aNbV, aNbE, aNbSE;
635   TopoDS_Edge aE;
636   TopExp_Explorer aExp;
637   TopTools_MapOfShape aM;
638   GEOMAlgo_KindOfShape aKS;
639   //
640   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
641   aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
642   //
643   aKS=aInfo.KindOfShape();
644   if (aKS!=GEOMAlgo_KS_TORUS) {
645     return;
646   }
647
648   aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
649   aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
650
651   if (aNbV==1 && aNbE==2) {
652     aNbSE=0;
653     aExp.Init(aF, TopAbs_EDGE);
654     for (; aExp.More(); aExp.Next()) {
655       aE=TopoDS::Edge(aExp.Current());
656       if (aM.Add(aE)) {
657         if (BRep_Tool::IsClosed(aE, aF)) {
658           ++aNbSE;
659         }
660       }
661     }
662     //
663     if (aNbSE==2) {
664       aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
665     }
666   }
667 }
668 //=======================================================================
669 //function : TreatStepSphere
670 //purpose  :
671 //=======================================================================
672 Standard_Boolean  GEOMAlgo_ShapeInfoFiller::TreatStepSphere
673   (const TopoDS_Solid& aSd)
674 {
675   Standard_Boolean bRet, bIsAllowedType, bOnlyClosed, bIsEqual;
676   Standard_Integer j;
677   Standard_Real aTol;
678   Standard_Real aVolume, aVolumeS, dV, aArea, aAreaS, dA;
679   gp_Sphere aSphere[2];
680   GeomAbs_SurfaceType aST;
681   Handle(Geom_Surface) aS;
682   GeomAdaptor_Surface aGAS;
683   TopExp_Explorer aExp;
684   //
685   bRet=Standard_False;
686   aTol=Precision::Confusion();
687   //
688   aExp.Init(aSd, TopAbs_FACE);
689   for (j=0; aExp.More(); aExp.Next(), ++j) {
690     const TopoDS_Face& aF=*((TopoDS_Face*)&aExp.Current());
691     aS=BRep_Tool::Surface(aF);
692     aGAS.Load(aS);
693     aST=aGAS.GetType();
694     bIsAllowedType=GEOMAlgo_ShapeInfoFiller::IsAllowedType(aST);
695     if (!bIsAllowedType) {
696       return bRet;
697     }
698     //
699     if (aST!=GeomAbs_Sphere) {
700       return bRet;
701     }
702     //
703     aSphere[j]=aGAS.Sphere();
704   }
705   //
706   bIsEqual=IsEqual(aSphere[0], aSphere[1], aTol);
707   if (!bIsEqual) {
708     return bRet;
709   }
710   //
711   //--------------------------------
712   GProp_GProps aGProps;
713   //
714   bOnlyClosed=Standard_False;
715   //
716   aVolume=aSphere[0].Volume();
717   //
718   //modified by NIZNHY-PKV Tue Jun 09 08:39:47 2015f
719   BRepGProp::VolumeProperties(aSd, aGProps, aTol,  bOnlyClosed);
720   //BRepGProp::VolumeProperties(aSd, aGProps,  bOnlyClosed);
721   //modified by NIZNHY-PKV Tue Jun 09 08:39:50 2015t
722   aVolumeS=aGProps.Mass();
723   if (aVolumeS<0.) {
724     aVolumeS=-aVolumeS;
725   }
726   //
727   dV=fabs(aVolumeS-aVolume);
728   if (dV>aTol) {
729     return bRet;
730   }
731   //--------------------------------
732   aArea=aSphere[0].Area();
733   //
734   //modified by NIZNHY-PKV Tue Jun 09 08:23:54 2015f
735   BRepGProp::SurfaceProperties(aSd, aGProps, aTol);
736   //BRepGProp::SurfaceProperties(aSd, aGProps);
737   //modified by NIZNHY-PKV Tue Jun 09 08:23:56 2015t
738   aAreaS=aGProps.Mass();
739   //
740   dA=fabs(aAreaS-aArea);
741   if (dA>aTol) {
742     return bRet;
743   }
744   //
745   //--------------------------------
746   gp_Pnt aP0;
747   gp_Ax3 aAx3;
748   Standard_Real aR1;
749   //
750   aP0=aSphere[0].Location();
751   aAx3=aSphere[0].Position();
752   aR1=aSphere[0].Radius();
753   //
754   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aSd);
755   //
756   aInfo.SetKindOfName(GEOMAlgo_KN_SPHERE);
757   aInfo.SetLocation(aP0);
758   aInfo.SetPosition(aAx3);
759   aInfo.SetRadius1(aR1);
760   //
761   return !bRet;// true
762 }
763 //=======================================================================
764 //function : IsEqual
765 //purpose  :
766 //=======================================================================
767 Standard_Boolean IsEqual(const gp_Sphere& aSp1,
768                          const gp_Sphere& aSp2,
769                          const Standard_Real aTolLin)
770 {
771   Standard_Boolean bRet;
772   Standard_Real aR1, aR2, aD2;
773   //
774   bRet=Standard_False;
775   aR1=aSp1.Radius();
776   aR2=aSp2.Radius();
777   if (fabs(aR1-aR2)>aTolLin) {
778     return bRet;
779   }
780   //
781   const gp_Pnt& aPC1=aSp1.Position().Location();
782   const gp_Pnt& aPC2=aSp2.Position().Location();
783   //
784   aD2=aPC1.SquareDistance(aPC2);
785   bRet=(aD2<aTolLin*aTolLin);
786   //
787   return bRet;
788 }