0031458: Visualization - refine classes across Prs3d and StdPrs packages
[occt.git] / src / SelectMgr / SelectMgr.cxx
1 // Copyright (c) 2020 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <SelectMgr.hxx>
15
16 #include <Graphic3d_ArrayOfPoints.hxx>
17 #include <Graphic3d_AspectMarker3d.hxx>
18 #include <Graphic3d_Group.hxx>
19 #include <Graphic3d_Structure.hxx>
20 #include <Poly_Array1OfTriangle.hxx>
21 #include <Poly_Triangulation.hxx>
22 #include <Prs3d.hxx>
23 #include <Prs3d_LineAspect.hxx>
24 #include <Prs3d_NListOfSequenceOfPnt.hxx>
25 #include <TColgp_HArray1OfPnt.hxx>
26 #include <TColgp_SequenceOfPnt.hxx>
27 #include <Select3D_SensitiveBox.hxx>
28 #include <Select3D_SensitiveEntity.hxx>
29 #include <Select3D_SensitiveFace.hxx>
30 #include <Select3D_SensitivePoint.hxx>
31 #include <Select3D_SensitiveSegment.hxx>
32 #include <Select3D_SensitiveTriangle.hxx>
33 #include <Select3D_SensitiveTriangulation.hxx>
34 #include <Select3D_SensitiveWire.hxx>
35 #include <SelectMgr_Selection.hxx>
36
37 namespace
38 {
39   //! Compute polyline of shrunk triangle.
40   static Handle(TColgp_HSequenceOfPnt) shrunkTriangle (const gp_Pnt* thePnts,
41                                                        const gp_XYZ& theCenter)
42   {
43     const gp_XYZ aV1 = theCenter + (thePnts[0].XYZ() - theCenter) * 0.9;
44     const gp_XYZ aV2 = theCenter + (thePnts[1].XYZ() - theCenter) * 0.9;
45     const gp_XYZ aV3 = theCenter + (thePnts[2].XYZ() - theCenter) * 0.9;
46     Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
47     aPoints->Append (aV1);
48     aPoints->Append (aV2);
49     aPoints->Append (aV3);
50     aPoints->Append (aV1);
51     return aPoints;
52   }
53
54   //! Fill in triangulation polylines.
55   static void addTriangulation (Prs3d_NListOfSequenceOfPnt& theSeqLines,
56                                 Prs3d_NListOfSequenceOfPnt& theSeqFree,
57                                 const Handle(Select3D_SensitiveTriangulation)& theTri,
58                                 const gp_Trsf& theLoc)
59   {
60     gp_Trsf aTrsf = theLoc;
61     if (theTri->HasInitLocation())
62     {
63       aTrsf = theLoc * theTri->GetInitLocation();
64     }
65     const Handle(Poly_Triangulation)& aPolyTri = theTri->Triangulation();
66     for (Standard_Integer aTriIter = 1; aTriIter <= aPolyTri->NbTriangles(); ++aTriIter)
67     {
68       const Poly_Triangle& aTri = aPolyTri->Triangle (aTriIter);
69       const gp_Pnt aPnts[3] =
70       {
71         aPolyTri->Node (aTri (1)).Transformed (aTrsf),
72         aPolyTri->Node (aTri (2)).Transformed (aTrsf),
73         aPolyTri->Node (aTri (3)).Transformed (aTrsf)
74       };
75       const gp_XYZ aCenter = (aPnts[0].XYZ() + aPnts[1].XYZ() + aPnts[2].XYZ()) / 3.0;
76       theSeqLines.Append (shrunkTriangle (aPnts, aCenter));
77     }
78
79     Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
80     Prs3d::AddFreeEdges (*aPoints, aPolyTri, aTrsf);
81     if (!aPoints->IsEmpty())
82     {
83       theSeqFree.Append (aPoints);
84     }
85   }
86
87   //! Fill in bounding box polylines.
88   static void addBoundingBox (Prs3d_NListOfSequenceOfPnt& theSeqLines,
89                               const Handle(Select3D_SensitiveBox)& theSensBox,
90                               const gp_Trsf& theLoc)
91   {
92     Graphic3d_Vec3d aMin, aMax;
93     theSensBox->Box().Get (aMin.x(), aMin.y(), aMin.z(), aMax.x(), aMax.y(), aMax.z());
94     gp_Pnt aPnts[8] =
95     {
96       gp_Pnt(aMin.x(), aMin.y(), aMin.z()),
97       gp_Pnt(aMax.x(), aMin.y(), aMin.z()),
98       gp_Pnt(aMax.x(), aMax.y(), aMin.z()),
99       gp_Pnt(aMin.x(), aMax.y(), aMin.z()),
100       gp_Pnt(aMin.x(), aMin.y(), aMax.z()),
101       gp_Pnt(aMax.x(), aMin.y(), aMax.z()),
102       gp_Pnt(aMax.x(), aMax.y(), aMax.z()),
103       gp_Pnt(aMin.x(), aMax.y(), aMax.z())
104     };
105     for (Standard_Integer aPntIter = 0; aPntIter <= 7; ++aPntIter)
106     {
107       aPnts[aPntIter].Transform (theLoc);
108     }
109
110     {
111       Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
112       for (Standard_Integer i = 0; i < 4; ++i)
113       {
114         aPoints->Append (aPnts[i]);
115       }
116       aPoints->Append (aPnts[0]);
117       theSeqLines.Append (aPoints);
118     }
119     {
120       Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
121       for (Standard_Integer i = 4; i < 8; i++)
122       {
123         aPoints->Append (aPnts[i]);
124       }
125       aPoints->Append (aPnts[4]);
126       theSeqLines.Append (aPoints);
127     }
128     for (Standard_Integer i = 0; i < 4; i++)
129     {
130       Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
131       aPoints->Append (aPnts[i]);
132       aPoints->Append (aPnts[i+4]);
133       theSeqLines.Append (aPoints);
134     }
135   }
136 }
137
138 //=======================================================================
139 //function : ComputeSensitivePrs
140 //purpose  :
141 //=======================================================================
142 void SelectMgr::ComputeSensitivePrs (const Handle(Graphic3d_Structure)& thePrs,
143                                      const Handle(SelectMgr_Selection)& theSel,
144                                      const gp_Trsf& theLoc,
145                                      const Handle(Graphic3d_TransformPers)& theTrsfPers)
146 {
147   thePrs->SetTransformPersistence (theTrsfPers);
148
149   Prs3d_NListOfSequenceOfPnt aSeqLines, aSeqFree;
150   TColgp_SequenceOfPnt aSeqPoints;
151   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
152   {
153     const Handle(Select3D_SensitiveEntity)& anEnt = aSelEntIter.Value()->BaseSensitive();
154     if (Handle(Select3D_SensitiveBox) aSensBox = Handle(Select3D_SensitiveBox)::DownCast (anEnt))
155     {
156       addBoundingBox (aSeqLines, aSensBox, theLoc);
157     }
158     else if (Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(anEnt))
159     {
160       Handle(TColgp_HArray1OfPnt) aSensPnts;
161       aFace->GetPoints (aSensPnts);
162       Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
163       for (TColgp_HArray1OfPnt::Iterator aPntIter (*aSensPnts); aPntIter.More(); aPntIter.Next())
164       {
165         aPoints->Append (aPntIter.Value().Transformed (theLoc));
166       }
167       aSeqLines.Append (aPoints);
168     }
169     else if (Handle(Select3D_SensitivePoly) aSensPoly = Handle(Select3D_SensitivePoly)::DownCast (anEnt))
170     {
171       Standard_Integer aFrom = 0, aTo = 0;
172       aSensPoly->ArrayBounds (aFrom, aTo);
173       Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
174       for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; ++aPntIter)
175       {
176         aPoints->Append (aSensPoly->GetPoint3d (aPntIter).Transformed (theLoc));
177       }
178       aSeqLines.Append (aPoints);
179     }
180     else if (Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast(anEnt))
181     {
182       const NCollection_Vector<Handle(Select3D_SensitiveEntity)>& anEntities = aWire->GetEdges();
183       for (NCollection_Vector<Handle(Select3D_SensitiveEntity)>::Iterator aSubIter (anEntities); aSubIter.More(); aSubIter.Next())
184       {
185         const Handle(Select3D_SensitiveEntity)& aSubEnt = aSubIter.Value();
186         if (Handle(Select3D_SensitiveSegment) aSensSeg = Handle(Select3D_SensitiveSegment)::DownCast (aSubEnt))
187         {
188           Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
189           aPoints->Append (aSensSeg->StartPoint().Transformed (theLoc));
190           aPoints->Append (aSensSeg->EndPoint()  .Transformed (theLoc));
191           aSeqLines.Append (aPoints);
192         }
193         else if (Handle(Select3D_SensitivePoly) aSubSensPoly = Handle(Select3D_SensitivePoly)::DownCast (aSubEnt))
194         {
195           Standard_Integer aFrom = 0, aTo = 0;
196           aSubSensPoly->ArrayBounds (aFrom, aTo);
197           Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
198           for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; ++aPntIter)
199           {
200             aPoints->Append (aSubSensPoly->GetPoint3d (aPntIter).Transformed (theLoc));
201           }
202           aSeqLines.Append (aPoints);
203         }
204       }
205     }
206     else if (Handle(Select3D_SensitiveSegment) aSensSeg = Handle(Select3D_SensitiveSegment)::DownCast(anEnt))
207     {
208       Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
209       aPoints->Append (aSensSeg->StartPoint().Transformed (theLoc));
210       aPoints->Append (aSensSeg->EndPoint()  .Transformed (theLoc));
211       aSeqLines.Append (aPoints);
212     }
213     else if (Handle(Select3D_SensitivePoint) aSensPnt = Handle(Select3D_SensitivePoint)::DownCast(anEnt))
214     {
215       aSeqPoints.Append (aSensPnt->Point().Transformed (theLoc));
216     }
217     else if (Handle(Select3D_SensitiveTriangulation) aSensTri = Handle(Select3D_SensitiveTriangulation)::DownCast (anEnt))
218     {
219       addTriangulation (aSeqLines, aSeqFree, aSensTri, theLoc);
220     }
221     else if (Handle(Select3D_SensitiveTriangle) aSensTri1 = Handle(Select3D_SensitiveTriangle)::DownCast(anEnt))
222     {
223       gp_Pnt aPnts[3];
224       aSensTri1->Points3D (aPnts[0], aPnts[1], aPnts[2]);
225       aPnts[0].Transform (theLoc);
226       aPnts[1].Transform (theLoc);
227       aPnts[2].Transform (theLoc);
228       aSeqLines.Append (shrunkTriangle (aPnts, aSensTri1->Center3D().XYZ()));
229     }
230   }
231
232   if (!aSeqPoints.IsEmpty())
233   {
234     Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (aSeqPoints.Size());
235     for (TColgp_SequenceOfPnt::Iterator aPntIter (aSeqPoints); aPntIter.More(); aPntIter.Next())
236     {
237       anArrayOfPoints->AddVertex (aPntIter.Value());
238     }
239
240     Handle(Graphic3d_Group) aSensPntGroup = thePrs->NewGroup();
241     aSensPntGroup->SetPrimitivesAspect (new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, Quantity_NOC_INDIANRED3, 2.0));
242     aSensPntGroup->AddPrimitiveArray (anArrayOfPoints);
243   }
244   if (!aSeqLines.IsEmpty())
245   {
246     Prs3d::AddPrimitivesGroup (thePrs, new Prs3d_LineAspect (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0), aSeqLines);
247   }
248   if (!aSeqFree.IsEmpty())
249   {
250     Prs3d::AddPrimitivesGroup (thePrs, new Prs3d_LineAspect (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0), aSeqFree);
251   }
252 }