Salome HOME
6327dec360d5b0d4318a054f8d3bc317686793af
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_ShapeInfoFiller_1.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, 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_Cone& aCone)
632 {
633   Standard_Integer aNbV, aNbE, aNbCE, aNbSE, aNbDE, i;
634   Standard_Real aR[3], aHeight, aRmin, aRmax;
635   gp_Pnt aPC[3], aPD, aPc, aPX[3];
636   TopoDS_Vertex aVD;
637   TopoDS_Edge aE;
638   TopoDS_Iterator aIt;
639   TopExp_Explorer aExp;
640   TopTools_MapOfShape aM;
641   GEOMAlgo_KindOfShape aKSE;
642   GEOMAlgo_KindOfName aKNE;
643   GEOMAlgo_KindOfClosed aKCE;
644   //
645   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
646   //
647   aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
648   //
649   aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
650   aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
651   if (aNbV==2 && aNbE==3) {
652     i=0;
653     aNbCE=0;
654     aNbSE=0;
655     aNbDE=0;
656     aExp.Init(aF, TopAbs_EDGE);
657     for (; aExp.More(); aExp.Next()) {
658       aE=TopoDS::Edge(aExp.Current());
659       if(aM.Add(aE)) {
660         const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE);
661         aKNE=aInfoE.KindOfName();
662         aKCE=aInfoE.KindOfClosed();
663         aKSE=aInfoE.KindOfShape();
664         if (aKNE==GEOMAlgo_KN_CIRCLE && aKCE==GEOMAlgo_KC_CLOSED) {
665           aPC[i]=aInfoE.Location();
666           aR[i]=aInfoE.Radius1();
667           //
668           aIt.Initialize(aE);
669           if (aIt.More()) {
670             aVD=*((TopoDS_Vertex*)&aIt.Value());
671           }
672           aPX[i]=BRep_Tool::Pnt(aVD);
673           //
674           ++i;
675           ++aNbCE;
676         }
677         else if (aKNE==GEOMAlgo_KN_SEGMENT) {
678           if (BRep_Tool::IsClosed(aE, aF)) {
679             ++aNbSE;
680           }
681         }
682         else if (aKSE==GEOMAlgo_KS_DEGENERATED) {
683           aIt.Initialize(aE);
684           if (aIt.More()) {
685             aVD=*((TopoDS_Vertex*)&aIt.Value());
686           }
687           //
688           aPD=BRep_Tool::Pnt(aVD);
689           //
690           ++aNbDE;
691         }
692       }
693     }
694     //
695     if ((aNbCE==2 || (aNbCE==1 && aNbDE==1)) && aNbSE==1) {
696       if (aNbDE==1) {
697         aPC[1]=aPD;
698         aR[1]=0.;
699       }
700       //
701       aHeight=aPC[0].Distance(aPC[1]);
702       //
703       
704       gp_Ax2 aAx2new;
705       //
706       if (aR[0]>aR[1]) {
707         aRmin=aR[1];
708         aRmax=aR[0];
709         aPc=aPC[0];
710         gp_Vec aVz(aPC[0], aPC[1]);
711         gp_Vec aVx(aPC[0], aPX[0]);
712         gp_Dir aDz(aVz);
713         gp_Dir aDx(aVx);
714         gp_Ax2 aAx2(aPc, aDz, aDx);
715         aAx2new=aAx2;
716       }
717       else {
718         aRmin=aR[0];
719         aRmax=aR[1];
720         aPc=aPC[1];
721         gp_Vec aVz(aPC[1], aPC[0]);
722         gp_Vec aVx(aPC[1], aPX[1]);
723         gp_Dir aDz(aVz);
724         gp_Dir aDx(aVx);
725         gp_Ax2 aAx2(aPc, aDz, aDx);
726         aAx2new=aAx2;
727       }
728       //
729       gp_Ax3 aAx3(aAx2new);
730       aInfo.SetLocation(aPc);
731       aInfo.SetPosition(aAx3);
732       aInfo.SetRadius1(aRmax);
733       aInfo.SetRadius2(aRmin);
734       aInfo.SetHeight(aHeight);
735       //
736       aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
737       return;
738     }//if ((aNbCE==2 || (aNbCE==1 && aNbDE==1)) && aNbSE==1) {
739   }//if (aNbV==2 && aNbE==3) {
740   //
741   aInfo.SetRadius1 (aCone.RefRadius());
742   //
743   aRmin=0.;   // ZZ
744   aInfo.SetRadius2(aRmin);
745 }
746 //=======================================================================
747 //function : FillDetails
748 //purpose  :
749 //=======================================================================
750 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
751                                            const gp_Torus& )
752 {
753   
754   Standard_Integer aNbV, aNbE, aNbSE;
755   TopoDS_Edge aE;
756   TopExp_Explorer aExp;
757   TopTools_MapOfShape aM;
758   GEOMAlgo_KindOfShape aKS;
759   //
760   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
761   aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
762   //
763   aKS=aInfo.KindOfShape();
764   if (aKS!=GEOMAlgo_KS_TORUS) {
765     return;
766   }
767   
768   aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
769   aNbE=aInfo.NbSubShapes(TopAbs_EDGE); 
770   
771   if (aNbV==1 && aNbE==2) {
772     aNbSE=0;
773     aExp.Init(aF, TopAbs_EDGE);
774     for (; aExp.More(); aExp.Next()) {
775       aE=TopoDS::Edge(aExp.Current());
776       if (aM.Add(aE)) {
777         if (BRep_Tool::IsClosed(aE, aF)) {
778           ++aNbSE;
779         }
780       }
781     }
782     //
783     if (aNbSE==2) {
784       aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
785     }
786   }
787 }
788 //=======================================================================
789 //function : TreatStepSphere
790 //purpose  :
791 //=======================================================================
792 Standard_Boolean  GEOMAlgo_ShapeInfoFiller::TreatStepSphere
793   (const TopoDS_Solid& aSd)
794 {
795   Standard_Boolean bRet, bIsAllowedType, bOnlyClosed, bIsEqual;
796   Standard_Integer j;
797   Standard_Real aTol;
798   Standard_Real aVolume, aVolumeS, dV, aArea, aAreaS, dA;
799   gp_Sphere aSphere[2];
800   GeomAbs_SurfaceType aST;
801   Handle(Geom_Surface) aS;
802   GeomAdaptor_Surface aGAS;
803   TopExp_Explorer aExp;
804   //
805   bRet=Standard_False;
806   aTol=Precision::Confusion();
807   //
808   aExp.Init(aSd, TopAbs_FACE);
809   for (j=0; aExp.More(); aExp.Next(), ++j) {
810     const TopoDS_Face& aF=*((TopoDS_Face*)&aExp.Current());
811     aS=BRep_Tool::Surface(aF);
812     aGAS.Load(aS);
813     aST=aGAS.GetType();
814     bIsAllowedType=GEOMAlgo_ShapeInfoFiller::IsAllowedType(aST);
815     if (!bIsAllowedType) {
816       return bRet;
817     }
818     //
819     if (aST!=GeomAbs_Sphere) {
820       return bRet;
821     }
822     //
823     aSphere[j]=aGAS.Sphere();
824   }
825   //
826   bIsEqual=IsEqual(aSphere[0], aSphere[1], aTol);
827   if (!bIsEqual) {
828     return bRet;
829   }
830   //
831   //--------------------------------
832   GProp_GProps aGProps;
833   //
834   bOnlyClosed=Standard_False;
835   //
836   aVolume=aSphere[0].Volume();
837   //
838   //modified by NIZNHY-PKV Tue Jun 09 08:39:47 2015f
839   BRepGProp::VolumeProperties(aSd, aGProps, aTol,  bOnlyClosed);
840   //BRepGProp::VolumeProperties(aSd, aGProps,  bOnlyClosed);
841   //modified by NIZNHY-PKV Tue Jun 09 08:39:50 2015t
842   aVolumeS=aGProps.Mass();
843   if (aVolumeS<0.) {
844     aVolumeS=-aVolumeS;
845   }
846   //
847   dV=fabs(aVolumeS-aVolume);
848   if (dV>aTol) {
849     return bRet;
850   }
851   //--------------------------------
852   aArea=aSphere[0].Area();
853   //
854   //modified by NIZNHY-PKV Tue Jun 09 08:23:54 2015f
855   BRepGProp::SurfaceProperties(aSd, aGProps, aTol);
856   //BRepGProp::SurfaceProperties(aSd, aGProps);
857   //modified by NIZNHY-PKV Tue Jun 09 08:23:56 2015t
858   aAreaS=aGProps.Mass();
859   //
860   dA=fabs(aAreaS-aArea);
861   if (dA>aTol) {
862     return bRet;
863   }
864   //
865   //--------------------------------
866   gp_Pnt aP0;
867   gp_Ax3 aAx3;
868   Standard_Real aR1;
869   //
870   aP0=aSphere[0].Location();
871   aAx3=aSphere[0].Position();
872   aR1=aSphere[0].Radius();
873   //
874   GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aSd);
875   //
876   aInfo.SetKindOfName(GEOMAlgo_KN_SPHERE);
877   aInfo.SetLocation(aP0);
878   aInfo.SetPosition(aAx3);
879   aInfo.SetRadius1(aR1);
880   //
881   return !bRet;// true
882 }
883 //=======================================================================
884 //function : IsEqual
885 //purpose  :
886 //=======================================================================
887 Standard_Boolean IsEqual(const gp_Sphere& aSp1,
888                          const gp_Sphere& aSp2,
889                          const Standard_Real aTolLin)
890 {
891   Standard_Boolean bRet;
892   Standard_Real aR1, aR2, aD2;
893   //
894   bRet=Standard_False;
895   aR1=aSp1.Radius();
896   aR2=aSp2.Radius();
897   if (fabs(aR1-aR2)>aTolLin) {
898     return bRet;
899   }
900   //
901   const gp_Pnt& aPC1=aSp1.Position().Location();
902   const gp_Pnt& aPC2=aSp2.Position().Location();
903   //
904   aD2=aPC1.SquareDistance(aPC2);
905   bRet=(aD2<aTolLin*aTolLin);
906   //
907   return bRet;
908 }