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