1 // File: NIS_Surface.cpp
2 // Created: 20.03.08 08:27
3 // Author: Alexander GRIGORIEV
4 // Copyright: Open Cascade S.A. 2008
6 #include <NIS_Surface.hxx>
7 #include <NIS_SurfaceDrawer.hxx>
8 #include <NIS_Triangulated.hxx>
9 #include <BRep_Tool.hxx>
10 #include <Geom_Surface.hxx>
11 #include <Poly_Triangulation.hxx>
12 #include <Precision.hxx>
13 #include <TColgp_Array1OfPnt2d.hxx>
14 #include <TopExp_Explorer.hxx>
15 #include <TopLoc_Location.hxx>
17 #include <TopoDS_Face.hxx>
20 IMPLEMENT_STANDARD_HANDLE (NIS_Surface, NIS_InteractiveObject)
21 IMPLEMENT_STANDARD_RTTIEXT(NIS_Surface, NIS_InteractiveObject)
23 //=======================================================================
24 //function : defaultDrawer
25 //purpose : internal method (static)
26 //=======================================================================
28 inline Handle(NIS_SurfaceDrawer) defaultDrawer()
30 const Handle(NIS_SurfaceDrawer) aDrawer =
31 new NIS_SurfaceDrawer(Quantity_NOC_SLATEBLUE4);
32 aDrawer->SetBackColor (Quantity_NOC_DARKGREEN);
36 //=======================================================================
37 //function : NIS_Surface
39 //=======================================================================
41 NIS_Surface::NIS_Surface
42 (const Handle(Poly_Triangulation)& theTri,
43 const Handle_NCollection_BaseAllocator& theAlloc)
51 myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
52 if (theTri.IsNull() == Standard_False)
54 // Alocate arrays of entities
55 myNNodes = 3 * theTri->NbTriangles();
56 myNTriangles = theTri->NbTriangles();
57 mypNodes = static_cast<Standard_ShortReal*>
58 (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes));
59 mypNormals = static_cast<Standard_ShortReal *>
60 (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes));
61 mypTriangles = static_cast<Standard_Integer*>
62 (myAlloc->Allocate(sizeof(Standard_Integer) * 3 * myNTriangles));
64 // Copy the data from the original triangulation.
65 Standard_Integer i, iN(0), iT(0);
66 const Poly_Array1OfTriangle& arrTri = theTri->Triangles();
67 const TColgp_Array1OfPnt& arrNodes = theTri->Nodes();
68 for (i = arrTri.Lower(); i <= arrTri.Upper(); i++) {
69 Standard_Integer iNode[3];
70 arrTri(i).Get(iNode[0], iNode[1], iNode[2]);
71 gp_XYZ aNorm = ((arrNodes(iNode[1]).XYZ() - arrNodes(iNode[0]).XYZ()) ^
72 (arrNodes(iNode[2]).XYZ() - arrNodes(iNode[0]).XYZ()));
73 const Standard_Real aMagn = aNorm.Modulus();
74 if (aMagn > Precision::Confusion())
77 aNorm.SetCoord(0., 0., 1.);
78 mypNodes[iN+0] = static_cast<Standard_ShortReal>(arrNodes(iNode[0]).X());
79 mypNodes[iN+1] = static_cast<Standard_ShortReal>(arrNodes(iNode[0]).Y());
80 mypNodes[iN+2] = static_cast<Standard_ShortReal>(arrNodes(iNode[0]).Z());
81 mypNodes[iN+3] = static_cast<Standard_ShortReal>(arrNodes(iNode[1]).X());
82 mypNodes[iN+4] = static_cast<Standard_ShortReal>(arrNodes(iNode[1]).Y());
83 mypNodes[iN+5] = static_cast<Standard_ShortReal>(arrNodes(iNode[1]).Z());
84 mypNodes[iN+6] = static_cast<Standard_ShortReal>(arrNodes(iNode[2]).X());
85 mypNodes[iN+7] = static_cast<Standard_ShortReal>(arrNodes(iNode[2]).Y());
86 mypNodes[iN+8] = static_cast<Standard_ShortReal>(arrNodes(iNode[2]).Z());
87 mypNormals[iN+0] = static_cast<Standard_ShortReal>(aNorm.X());
88 mypNormals[iN+1] = static_cast<Standard_ShortReal>(aNorm.Y());
89 mypNormals[iN+2] = static_cast<Standard_ShortReal>(aNorm.Z());
90 mypNormals[iN+3] = static_cast<Standard_ShortReal>(aNorm.X());
91 mypNormals[iN+4] = static_cast<Standard_ShortReal>(aNorm.Y());
92 mypNormals[iN+5] = static_cast<Standard_ShortReal>(aNorm.Z());
93 mypNormals[iN+6] = static_cast<Standard_ShortReal>(aNorm.X());
94 mypNormals[iN+7] = static_cast<Standard_ShortReal>(aNorm.Y());
95 mypNormals[iN+8] = static_cast<Standard_ShortReal>(aNorm.Z());
96 mypTriangles[iT+0] = iT+0;
97 mypTriangles[iT+1] = iT+1;
98 mypTriangles[iT+2] = iT+2;
105 //=======================================================================
106 //function : NIS_Surface
107 //purpose : Constructor
108 //=======================================================================
110 NIS_Surface::NIS_Surface
111 (const TopoDS_Shape& theShape,
112 // const Standard_Real theDeflection,
113 const Handle_NCollection_BaseAllocator& theAlloc)
121 if (myAlloc.IsNull())
122 myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
123 TopLoc_Location aLoc, aLocSurf;
125 // Count the nodes and triangles in faces
126 TopExp_Explorer fexp (theShape, TopAbs_FACE);
127 for ( ; fexp.More(); fexp.Next() )
129 TopoDS_Face aFace = TopoDS::Face(fexp.Current());
131 const Handle(Poly_Triangulation)& aTriangulation
132 = BRep_Tool::Triangulation (aFace, aLoc);
133 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLoc);
135 if (aTriangulation.IsNull() == Standard_False &&
136 aSurf.IsNull() == Standard_False)
138 myNNodes += aTriangulation->NbNodes();
139 myNTriangles += aTriangulation->NbTriangles();
143 // Alocate arrays of entities
144 if (myNNodes && myNTriangles) {
145 mypNodes = static_cast<Standard_ShortReal*>
146 (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes));
147 mypNormals = static_cast<Standard_ShortReal *>
148 (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes));
149 mypTriangles = static_cast<Standard_Integer*>
150 (myAlloc->Allocate(sizeof(Standard_Integer) * 3 * myNTriangles));
152 // The second loop: copy all nodes and triangles face-by-face
153 const Standard_Real eps2 = Precision::Confusion()*Precision::Confusion();
154 Standard_Integer nNodes (0), nTriangles (0);
155 for (fexp.ReInit(); fexp.More(); fexp.Next())
157 const TopoDS_Face& aFace = TopoDS::Face(fexp.Current());
158 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLocSurf);
159 const Handle(Poly_Triangulation)& aTriangulation =
160 BRep_Tool::Triangulation(aFace, aLoc);
161 if (aTriangulation.IsNull() == Standard_False &&
162 aSurf.IsNull() == Standard_False)
164 // Prepare transformation
165 Standard_Integer i, aNodeInd(nNodes)/*, aNTriangles = 0*/;
166 const gp_Trsf& aTrf = aLoc.Transformation();
167 const gp_Trsf& aTrfSurf = aLocSurf.Transformation();
168 Standard_Boolean isReverse = (aFace.Orientation() == TopAbs_REVERSED);
170 // Store all nodes of the current face in the data model
171 const TColgp_Array1OfPnt& tabNode = aTriangulation->Nodes();
172 const TColgp_Array1OfPnt2d& tabUV = aTriangulation->UVNodes();
173 for (i = tabNode.Lower(); i <= tabNode.Upper(); i++)
176 tabNode(i).Transformed(aTrf).Coord (t[0], t[1], t[2]);
177 // write node to mesh data
178 mypNodes[3*aNodeInd + 0] = static_cast<Standard_ShortReal>(t[0]);
179 mypNodes[3*aNodeInd + 1] = static_cast<Standard_ShortReal>(t[1]);
180 mypNodes[3*aNodeInd + 2] = static_cast<Standard_ShortReal>(t[2]);
185 // Compute the surface normal at the Node.
186 aSurf->D1(tabUV(i).X(), tabUV(i).Y(), aP, aD1U, aD1V);
187 gp_XYZ aNorm = (aD1U.Crossed(aD1V)).XYZ();
190 const Standard_Real aMod = aNorm.SquareModulus();
192 gp_Dir aDirNorm(aNorm);
193 aDirNorm.Transform(aTrfSurf);
194 aDirNorm.Coord (t[0], t[1], t[2]);
200 mypNormals[3*aNodeInd + 0] = static_cast<Standard_ShortReal>(t[0]);
201 mypNormals[3*aNodeInd + 1] = static_cast<Standard_ShortReal>(t[1]);
202 mypNormals[3*aNodeInd + 2] = static_cast<Standard_ShortReal>(t[2]);
206 // Store all triangles of the current face in the data model
207 const Poly_Array1OfTriangle& tabTri = aTriangulation->Triangles();
208 for (i = tabTri.Lower(); i <= tabTri.Upper(); i++)
210 Standard_Integer aN[3];
211 tabTri(i).Get (aN[0], aN[1], aN[2]);
212 if (((tabNode(aN[2]).XYZ() -
213 tabNode(aN[0]).XYZ()) ^
214 (tabNode(aN[1]).XYZ() -
215 tabNode(aN[0]).XYZ())).SquareModulus() > eps2)
217 aN[0] += (nNodes - 1);
218 aN[1] += (nNodes - 1);
219 aN[2] += (nNodes - 1);
220 mypTriangles[nTriangles*3 + 0] = aN[0];
222 mypTriangles[nTriangles*3 + 1] = aN[2];
223 mypTriangles[nTriangles*3 + 2] = aN[1];
225 mypTriangles[nTriangles*3 + 1] = aN[1];
226 mypTriangles[nTriangles*3 + 2] = aN[2];
231 nNodes += tabNode.Length();
234 myNTriangles = nTriangles;
238 //=======================================================================
239 //function : ~NIS_Surface
240 //purpose : Destructor
241 //=======================================================================
243 NIS_Surface::~NIS_Surface ()
247 myAlloc->Free(mypNodes);
248 myAlloc->Free(mypNormals);
252 myAlloc->Free(mypTriangles);
256 //=======================================================================
257 //function : DefaultDrawer
259 //=======================================================================
261 Handle(NIS_Drawer) NIS_Surface::DefaultDrawer () const
263 return defaultDrawer();
266 //=======================================================================
267 //function : SetColor
268 //purpose : Set the normal color for presentation.
269 //=======================================================================
271 void NIS_Surface::SetColor (const Quantity_Color& theColor)
273 Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
274 aDrawer->Assign (GetDrawer());
275 aDrawer->myColor[NIS_Drawer::Draw_Normal] = theColor;
276 aDrawer->myColor[NIS_Drawer::Draw_Transparent] = theColor;
280 //=======================================================================
281 //function : SetBackColor
282 //purpose : Set the normal color for presentation of back side of triangles.
283 //=======================================================================
285 void NIS_Surface::SetBackColor (const Quantity_Color& theColor)
287 Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
288 aDrawer->Assign (GetDrawer());
289 aDrawer->myBackColor = theColor;
293 //=======================================================================
294 //function : SetPolygonOffset
296 //=======================================================================
298 void NIS_Surface::SetPolygonOffset (const Standard_Real theValue)
300 Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
301 aDrawer->Assign (GetDrawer());
302 aDrawer->myPolygonOffset = theValue;
306 //=======================================================================
307 //function : SetTransparency
309 //=======================================================================
311 void NIS_Surface::SetTransparency (const Standard_Real theValue)
313 Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
314 aDrawer->Assign (GetDrawer());
315 aDrawer->myTransparency = theValue;
319 //=======================================================================
320 //function : Intersect
322 //=======================================================================
324 Standard_Real NIS_Surface::Intersect (const gp_Ax1& theAxis,
325 const Standard_Real /*over*/) const
327 Standard_Real aResult (RealLast());
328 Standard_Real start[3], dir[3];
329 theAxis.Location().Coord(start[0], start[1], start[2]);
330 theAxis.Direction().Coord(dir[0], dir[1], dir[2]);
333 for (Standard_Integer i = 0; i < myNTriangles; i++) {
334 const Standard_Integer * pTri = &mypTriangles[3*i];
335 if (NIS_Triangulated::tri_line_intersect (start, dir,
336 &mypNodes[3*pTri[0]],
337 &mypNodes[3*pTri[1]],
338 &mypNodes[3*pTri[2]],
340 if (anInter < aResult)
347 //=======================================================================
348 //function : Intersect
350 //=======================================================================
352 Standard_Boolean NIS_Surface::Intersect
353 (const Bnd_B3f& theBox,
354 const gp_Trsf& theTrf,
355 const Standard_Boolean isFullIn) const
357 Standard_Boolean aResult (isFullIn);
359 if (myNTriangles > 0) {
360 for (Standard_Integer iNode = 0; iNode < myNNodes*3; iNode+=3) {
361 gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
362 static_cast<Standard_Real>(mypNodes[iNode+1]),
363 static_cast<Standard_Real>(mypNodes[iNode+2]));
364 theTrf.Transforms(aPnt);
365 if (theBox.IsOut (aPnt) == isFullIn) {
374 //=======================================================================
375 //function : computeBox
377 //=======================================================================
379 void NIS_Surface::computeBox ()
381 NIS_Triangulated::ComputeBox(myBox, myNNodes, mypNodes);
383 const Handle(NIS_SurfaceDrawer)& aDrawer =
384 static_cast<const Handle(NIS_SurfaceDrawer)&> (GetDrawer());
386 if (aDrawer.IsNull() == Standard_False) {
387 const gp_Trsf& aTrsf = aDrawer->GetTransformation();
388 myBox = myBox.Transformed(aTrsf);