1 // Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <GEOMAlgo_ShapeInfoFiller.hxx>
22 #include <Precision.hxx>
23 #include <TColStd_MapOfInteger.hxx>
24 #include <TColStd_IndexedMapOfInteger.hxx>
36 #include <GeomAdaptor_Surface.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>
45 #include <BRep_Tool.hxx>
48 #include <TopExp_Explorer.hxx>
50 #include <TopTools_MapOfShape.hxx>
51 #include <TopTools_IndexedMapOfShape.hxx>
53 #include <BRepTools_WireExplorer.hxx>
54 #include <BRepGProp.hxx>
55 #include <GProp_GProps.hxx>
57 #include <GEOMAlgo_ShapeInfo.hxx>
60 Standard_Boolean IsEqual(const gp_Sphere& aSp1,
61 const gp_Sphere& aSp2,
62 const Standard_Real aTolDst);
64 //=======================================================================
65 //function : FillDetails
67 //=======================================================================
68 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Solid& aSd)
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;
78 GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aSd);
79 aInfo.SetKindOfName(GEOMAlgo_KN_UNKNOWN);
81 TopExp::MapShapes(aSd, TopAbs_FACE, aMF);
88 //modified by NIZNHY-PKV Tue Jun 09 08:35:23 2015f
90 // case requested by the customer
91 // specific solid that should be treated as a sphere
92 bIsStepSphere=TreatStepSphere(aSd);
97 //modified by NIZNHY-PKV Tue Jun 09 08:35:28 2015t
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();
105 if (aKD!=GEOMAlgo_KD_SPECIFIED) {
106 aInfo.SetKindOfName(GEOMAlgo_KN_SOLID);
110 aNbShells=GEOMAlgo_ShapeInfoFiller::NbShells(aSd);
112 aInfo.SetKindOfName(GEOMAlgo_KN_SOLID);
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());
134 //modified by NIZNHY-PKV Tue Jun 09 08:36:08 2015f
137 // specific solid that should be treated as a sphere
138 bIsStepSphere=TreatStepSphere(aSd);
144 //modified by NIZNHY-PKV Tue Jun 09 08:36:12 2015t
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) {
159 else if (aKNF==GEOMAlgo_KN_CONE) {
163 else if (aKNF==GEOMAlgo_KN_DISKCIRCLE) {
166 else if (aKNF==GEOMAlgo_KN_POLYGON ||
167 aKNF==GEOMAlgo_KN_TRIANGLE ||
168 aKNF==GEOMAlgo_KN_QUADRANGLE) {
171 else if (aKNF==GEOMAlgo_KN_RECTANGLE) {
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());
191 if (aNbCon==1 && (aNbCrc==1 || aNbCrc==2) && aNbX==aNbF) {
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());
205 return;// -> GEOMAlgo_KN_UNKNOWN
208 aInfo.SetKindOfName(GEOMAlgo_KN_POLYHEDRON);
212 if (aNbPgn!=aNbRct) {
213 aInfo.SetKindOfName(GEOMAlgo_KN_POLYHEDRON);
216 //===================================================
219 Standard_Integer j, aNbFi, aNbV, iMax, iMin, iMid;
220 Standard_Real aDot, aLength, aWidth, aHeight, aDist[3];
221 Standard_Real aDistMin, aDistMax;
225 TColStd_IndexedMapOfInteger aMp;
226 TopTools_IndexedMapOfShape aMV, aMFi;
229 TopExp::MapShapes(aSd, TopAbs_VERTEX, aMV);
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();
247 for (i=1; i<=aNbF; ++i) {
248 if (aMp.Contains(i)) {
252 const TopoDS_Shape& aFi=aMF(i);
253 const GEOMAlgo_ShapeInfo& aIFi=myMapInfo.FindFromKey(aFi);
254 const gp_Dir& aDNi=aIFi.Position().Direction();
256 for (j=i+1; j<=aNbF; ++j) {
257 if (aMp.Contains(j)) {
261 const TopoDS_Shape& aFj=aMF(j);
262 const GEOMAlgo_ShapeInfo& aIFj=myMapInfo.FindFromKey(aFj);
263 const gp_Dir& aDNj=aIFj.Position().Direction();
269 if (fabs(1.-aDot)<0.0001) {
287 for (i=0; i<aNbFi; ++i) {
288 const TopoDS_Shape& aFi=aMFi(i+1);
289 const GEOMAlgo_ShapeInfo& aIFi=myMapInfo.FindFromKey(aFi);
291 aDist[i]=aPc.Distance(aPi);
292 if (aDist[i]>aDistMax) {
296 if (aDist[i]<aDistMin) {
300 gp_Vec aVi(aPc, aPi);
311 aLength=2.*aDist[iMax];
312 aWidth=2.*aDist[iMid];
313 aHeight=2.*aDist[iMin];
315 gp_Ax2 aAx2(aPc, aDir[iMin], aDir[iMax]);
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);
325 //=======================================================================
326 //function : FillDetails
328 //=======================================================================
329 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
332 Standard_Integer aNbV, aNbE, i, j;
333 Standard_Real aDot, aD0, aD1, aLength, aWidth;
335 gp_Pnt aPx[4], aP, aPc;
337 TopExp_Explorer aExp;
342 TopTools_IndexedMapOfShape aMV;
343 BRepTools_WireExplorer aWExp;
344 GEOMAlgo_KindOfName aKN, aKNE;
346 GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
348 aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
350 aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
351 aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
353 // 1. may be it is circle/ellipse
354 if (aNbV==1 && aNbE==1) {
355 aExp.Init(aF, TopAbs_EDGE);
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);
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);
380 }// if (aNbV==1 && aNbE==1) {
383 Standard_Boolean bSegment;
385 bSegment=Standard_True;
386 aExp.Init(aF, TopAbs_EDGE);
387 for (; aExp.More() && bSegment; aExp.Next()) {
389 const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE);
390 aKNE=aInfoE.KindOfName();
391 if (aKNE!=GEOMAlgo_KN_SEGMENT) {
397 // 2. may be it is TRIANGLE, POLYGON, QUADRANGLE, RECTANGLE
398 aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
399 aInfo.SetKindOfName(GEOMAlgo_KN_POLYGON);
401 if (aNbV==3 && aNbE==3) {
402 aInfo.SetKindOfName(GEOMAlgo_KN_TRIANGLE);
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();
416 gp_Vec aVX(aPc, aPx[0]);
418 aDX.SetXYZ(aVX.XYZ());
419 const gp_Dir& aDZ=aPln.Axis().Direction();
421 gp_Ax2 aAx2(aPc, aDZ, aDX);
424 aInfo.SetLocation(aPc);
425 aInfo.SetPosition(aAx3);
426 } // if (aNbV==3 && aNbE==3) {
428 if (aNbV==4 && aNbE==4) {
431 aW=*((TopoDS_Wire*)&aIt.Value());
435 for (i=0; aWExp.More(); aWExp.Next(), ++i) {
437 const GEOMAlgo_ShapeInfo& aInfoEx=myMapInfo.FindFromKey(aEx);
438 aDx[i]=aInfoEx.Direction();
439 aPx[i]=aInfoEx.Location();
442 Standard_Boolean isRectangle = Standard_True;
443 for (i=0; i<4; ++i) {
446 if (fabs (aDot) > myTolerance) {
447 isRectangle = Standard_False;
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();
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)
471 aInfo.SetLocation(aPc);
475 gp_Lin aL0(aPx[0], aDx[0]);
476 gp_Lin aL1(aPx[1], aDx[1]);
478 aD0=aL0.Distance(aPc);
479 aD1=aL1.Distance(aPc);
493 aInfo.SetLength(aLength);
494 aInfo.SetWidth(aWidth);
495 aInfo.SetKindOfName(GEOMAlgo_KN_RECTANGLE);
497 aInfo.SetKindOfName(GEOMAlgo_KN_QUADRANGLE);
500 const gp_Dir& aDZ=aPln.Axis().Direction();
501 gp_Ax2 aAx2(aPc, aDZ, aDX);
503 aInfo.SetPosition(aAx3);
505 }// if (aNbV==4 && aNbE==4) {
509 //aInfo.SetKindOfName(GEOMAlgo_KN_PLANE);
511 //=======================================================================
512 //function : FillDetails
514 //=======================================================================
515 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
516 const gp_Sphere& )//aSph)
519 Standard_Integer aNbV, aNbE, aNbSE, aNbDE;
521 TopExp_Explorer aExp;
522 TopTools_MapOfShape aM;
523 GEOMAlgo_KindOfShape aKSE;//, aKSE;
525 GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
527 aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
528 aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
529 aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
530 if (aNbV==2 && aNbE==3) {
533 aExp.Init(aF, TopAbs_EDGE);
534 for (; aExp.More(); aExp.Next()) {
535 aE=TopoDS::Edge(aExp.Current());
537 const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE);
538 aKSE=aInfoE.KindOfShape();
540 if (BRep_Tool::IsClosed(aE, aF)) {
543 else if (aKSE==GEOMAlgo_KS_DEGENERATED) {
549 if (aNbSE==1 && aNbDE==2) {
550 aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
554 //=======================================================================
555 //function : FillDetails
557 //=======================================================================
558 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
559 const gp_Cylinder& aCyl)
562 Standard_Integer aNbV, aNbE, aNbCE, aNbSE;
563 Standard_Real aT0, aT1, aHeight;
566 TopExp_Explorer aExp;
567 TopTools_MapOfShape aM;
568 GEOMAlgo_KindOfName aKNE;
569 GEOMAlgo_KindOfClosed aKCE;
571 GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
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();
583 aExp.Init(aF, TopAbs_EDGE);
584 for (; aExp.More(); aExp.Next()) {
585 aE=TopoDS::Edge(aExp.Current());
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();
594 else if (aKNE==GEOMAlgo_KN_SEGMENT) {
595 if (BRep_Tool::IsClosed(aE, aF)) {
602 if (aNbCE==2 && aNbSE==1) {
603 gp_Lin aLin(aPLoc, aDir);
605 aT0=ElCLib::Parameter(aLin, aPC[0]);
606 aT1=ElCLib::Parameter(aLin, aPC[1]);
612 aHeight=aPC[0].Distance(aPC[1]);
614 gp_Ax3 aAx3=aCyl.Position();
615 aAx3.SetLocation(aPc);
617 aInfo.SetPosition(aAx3);
618 aInfo.SetLocation(aPc);
619 aInfo.SetHeight(aHeight);
621 aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
622 return; // conventional cylinder
623 }//if (aNbCE==2 && aNbSE==1) {
624 }//if (aNbV==2 && aNbE==3) {
626 //=======================================================================
627 //function : FillDetails
629 //=======================================================================
630 void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF,
634 Standard_Integer aNbV, aNbE, aNbSE;
636 TopExp_Explorer aExp;
637 TopTools_MapOfShape aM;
638 GEOMAlgo_KindOfShape aKS;
640 GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF);
641 aInfo.SetKindOfDef(GEOMAlgo_KD_ARBITRARY);
643 aKS=aInfo.KindOfShape();
644 if (aKS!=GEOMAlgo_KS_TORUS) {
648 aNbV=aInfo.NbSubShapes(TopAbs_VERTEX);
649 aNbE=aInfo.NbSubShapes(TopAbs_EDGE);
651 if (aNbV==1 && aNbE==2) {
653 aExp.Init(aF, TopAbs_EDGE);
654 for (; aExp.More(); aExp.Next()) {
655 aE=TopoDS::Edge(aExp.Current());
657 if (BRep_Tool::IsClosed(aE, aF)) {
664 aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
668 //=======================================================================
669 //function : TreatStepSphere
671 //=======================================================================
672 Standard_Boolean GEOMAlgo_ShapeInfoFiller::TreatStepSphere
673 (const TopoDS_Solid& aSd)
675 Standard_Boolean bRet, bIsAllowedType, bOnlyClosed, bIsEqual;
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;
686 aTol=Precision::Confusion();
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);
694 bIsAllowedType=GEOMAlgo_ShapeInfoFiller::IsAllowedType(aST);
695 if (!bIsAllowedType) {
699 if (aST!=GeomAbs_Sphere) {
703 aSphere[j]=aGAS.Sphere();
706 bIsEqual=IsEqual(aSphere[0], aSphere[1], aTol);
711 //--------------------------------
712 GProp_GProps aGProps;
714 bOnlyClosed=Standard_False;
716 aVolume=aSphere[0].Volume();
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();
727 dV=fabs(aVolumeS-aVolume);
731 //--------------------------------
732 aArea=aSphere[0].Area();
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();
740 dA=fabs(aAreaS-aArea);
745 //--------------------------------
750 aP0=aSphere[0].Location();
751 aAx3=aSphere[0].Position();
752 aR1=aSphere[0].Radius();
754 GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aSd);
756 aInfo.SetKindOfName(GEOMAlgo_KN_SPHERE);
757 aInfo.SetLocation(aP0);
758 aInfo.SetPosition(aAx3);
759 aInfo.SetRadius1(aR1);
763 //=======================================================================
766 //=======================================================================
767 Standard_Boolean IsEqual(const gp_Sphere& aSp1,
768 const gp_Sphere& aSp2,
769 const Standard_Real aTolLin)
771 Standard_Boolean bRet;
772 Standard_Real aR1, aR2, aD2;
777 if (fabs(aR1-aR2)>aTolLin) {
781 const gp_Pnt& aPC1=aSp1.Position().Location();
782 const gp_Pnt& aPC2=aSp2.Position().Location();
784 aD2=aPC1.SquareDistance(aPC2);
785 bRet=(aD2<aTolLin*aTolLin);