Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2008-03-20 |
2 | // Created by: Alexander GRIGORIEV | |
3 | // Copyright (c) 2008-2012 OPEN CASCADE SAS | |
4 | // | |
5 | // The content of this file is subject to the Open CASCADE Technology Public | |
6 | // License Version 6.5 (the "License"). You may not use the content of this file | |
7 | // except in compliance with the License. Please obtain a copy of the License | |
8 | // at http://www.opencascade.org and read it completely before using this file. | |
9 | // | |
10 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its | |
11 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. | |
12 | // | |
13 | // The Original Code and all software distributed under the License is | |
14 | // distributed on an "AS IS" basis, without warranty of any kind, and the | |
15 | // Initial Developer hereby disclaims all such warranties, including without | |
16 | // limitation, any warranties of merchantability, fitness for a particular | |
17 | // purpose or non-infringement. Please see the License for the specific terms | |
18 | // and conditions governing the rights and limitations under the License. | |
19 | ||
7fd59977 | 20 | |
21 | #include <NIS_Surface.hxx> | |
22 | #include <NIS_SurfaceDrawer.hxx> | |
23 | #include <NIS_Triangulated.hxx> | |
ffe2bea7 A |
24 | #include <BRepMesh_IncrementalMesh.hxx> |
25 | #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx> | |
26 | #include <BRep_PolygonOnTriangulation.hxx> | |
27 | #include <BRep_TEdge.hxx> | |
7fd59977 | 28 | #include <BRep_Tool.hxx> |
29 | #include <Geom_Surface.hxx> | |
ffe2bea7 A |
30 | #include <NCollection_Map.hxx> |
31 | #include <Poly_PolygonOnTriangulation.hxx> | |
7fd59977 | 32 | #include <Poly_Triangulation.hxx> |
33 | #include <Precision.hxx> | |
34 | #include <TColgp_Array1OfPnt2d.hxx> | |
ffe2bea7 | 35 | #include <TopExp.hxx> |
7fd59977 | 36 | #include <TopExp_Explorer.hxx> |
37 | #include <TopLoc_Location.hxx> | |
ffe2bea7 | 38 | #include <TopTools_MapOfShape.hxx> |
7fd59977 | 39 | #include <TopoDS.hxx> |
40 | #include <TopoDS_Face.hxx> | |
ffe2bea7 A |
41 | #include <TopoDS_Edge.hxx> |
42 | #include <TShort_Array1OfShortReal.hxx> | |
7fd59977 | 43 | #include <gp_Ax1.hxx> |
44 | ||
45 | IMPLEMENT_STANDARD_HANDLE (NIS_Surface, NIS_InteractiveObject) | |
46 | IMPLEMENT_STANDARD_RTTIEXT(NIS_Surface, NIS_InteractiveObject) | |
47 | ||
48 | //======================================================================= | |
ffe2bea7 A |
49 | //function : IsEqual |
50 | //purpose : Compare two triangulations, for NCollection_Map interface. | |
7fd59977 | 51 | //======================================================================= |
52 | ||
ffe2bea7 A |
53 | inline Standard_Boolean IsEqual(const Handle_Poly_Triangulation& theT0, |
54 | const Handle_Poly_Triangulation& theT1) | |
7fd59977 | 55 | { |
ffe2bea7 A |
56 | return (theT0 == theT1); |
57 | } | |
58 | ||
59 | //======================================================================= | |
60 | //function : NIS_Surface | |
61 | //purpose : | |
62 | //======================================================================= | |
63 | ||
64 | NIS_Surface::NIS_Surface(const Handle_NCollection_BaseAllocator& theAlloc) | |
65 | : myAlloc (theAlloc), | |
66 | mypNodes (NULL), | |
67 | mypNormals (NULL), | |
68 | mypTriangles (NULL), | |
69 | mypEdges (NULL), | |
70 | myNNodes (0), | |
71 | myNTriangles (0), | |
72 | myNEdges (0), | |
73 | myIsWireframe(0) | |
74 | { | |
75 | if (myAlloc.IsNull()) | |
76 | myAlloc = NCollection_BaseAllocator::CommonBaseAllocator(); | |
7fd59977 | 77 | } |
78 | ||
79 | //======================================================================= | |
80 | //function : NIS_Surface | |
81 | //purpose : | |
82 | //======================================================================= | |
83 | ||
ffe2bea7 A |
84 | NIS_Surface::NIS_Surface (const Handle(Poly_Triangulation)& theTri, |
85 | const Handle_NCollection_BaseAllocator& theAlloc) | |
86 | : myAlloc (theAlloc), | |
87 | mypNodes (NULL), | |
88 | mypNormals (NULL), | |
89 | mypEdges (NULL), | |
90 | myNNodes (0), | |
91 | myNTriangles (0), | |
92 | myNEdges (0), | |
93 | myIsWireframe(0) | |
7fd59977 | 94 | { |
95 | if (myAlloc.IsNull()) | |
96 | myAlloc = NCollection_BaseAllocator::CommonBaseAllocator(); | |
97 | if (theTri.IsNull() == Standard_False) | |
98 | { | |
99 | // Alocate arrays of entities | |
100 | myNNodes = 3 * theTri->NbTriangles(); | |
101 | myNTriangles = theTri->NbTriangles(); | |
102 | mypNodes = static_cast<Standard_ShortReal*> | |
103 | (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes)); | |
104 | mypNormals = static_cast<Standard_ShortReal *> | |
105 | (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes)); | |
106 | mypTriangles = static_cast<Standard_Integer*> | |
107 | (myAlloc->Allocate(sizeof(Standard_Integer) * 3 * myNTriangles)); | |
108 | ||
109 | // Copy the data from the original triangulation. | |
110 | Standard_Integer i, iN(0), iT(0); | |
111 | const Poly_Array1OfTriangle& arrTri = theTri->Triangles(); | |
112 | const TColgp_Array1OfPnt& arrNodes = theTri->Nodes(); | |
113 | for (i = arrTri.Lower(); i <= arrTri.Upper(); i++) { | |
114 | Standard_Integer iNode[3]; | |
115 | arrTri(i).Get(iNode[0], iNode[1], iNode[2]); | |
116 | gp_XYZ aNorm = ((arrNodes(iNode[1]).XYZ() - arrNodes(iNode[0]).XYZ()) ^ | |
117 | (arrNodes(iNode[2]).XYZ() - arrNodes(iNode[0]).XYZ())); | |
118 | const Standard_Real aMagn = aNorm.Modulus(); | |
119 | if (aMagn > Precision::Confusion()) | |
120 | aNorm /= aMagn; | |
121 | else | |
122 | aNorm.SetCoord(0., 0., 1.); | |
123 | mypNodes[iN+0] = static_cast<Standard_ShortReal>(arrNodes(iNode[0]).X()); | |
124 | mypNodes[iN+1] = static_cast<Standard_ShortReal>(arrNodes(iNode[0]).Y()); | |
125 | mypNodes[iN+2] = static_cast<Standard_ShortReal>(arrNodes(iNode[0]).Z()); | |
126 | mypNodes[iN+3] = static_cast<Standard_ShortReal>(arrNodes(iNode[1]).X()); | |
127 | mypNodes[iN+4] = static_cast<Standard_ShortReal>(arrNodes(iNode[1]).Y()); | |
128 | mypNodes[iN+5] = static_cast<Standard_ShortReal>(arrNodes(iNode[1]).Z()); | |
129 | mypNodes[iN+6] = static_cast<Standard_ShortReal>(arrNodes(iNode[2]).X()); | |
130 | mypNodes[iN+7] = static_cast<Standard_ShortReal>(arrNodes(iNode[2]).Y()); | |
131 | mypNodes[iN+8] = static_cast<Standard_ShortReal>(arrNodes(iNode[2]).Z()); | |
132 | mypNormals[iN+0] = static_cast<Standard_ShortReal>(aNorm.X()); | |
133 | mypNormals[iN+1] = static_cast<Standard_ShortReal>(aNorm.Y()); | |
134 | mypNormals[iN+2] = static_cast<Standard_ShortReal>(aNorm.Z()); | |
135 | mypNormals[iN+3] = static_cast<Standard_ShortReal>(aNorm.X()); | |
136 | mypNormals[iN+4] = static_cast<Standard_ShortReal>(aNorm.Y()); | |
137 | mypNormals[iN+5] = static_cast<Standard_ShortReal>(aNorm.Z()); | |
138 | mypNormals[iN+6] = static_cast<Standard_ShortReal>(aNorm.X()); | |
139 | mypNormals[iN+7] = static_cast<Standard_ShortReal>(aNorm.Y()); | |
140 | mypNormals[iN+8] = static_cast<Standard_ShortReal>(aNorm.Z()); | |
141 | mypTriangles[iT+0] = iT+0; | |
142 | mypTriangles[iT+1] = iT+1; | |
143 | mypTriangles[iT+2] = iT+2; | |
144 | iN += 9; | |
145 | iT += 3; | |
146 | } | |
147 | } | |
148 | } | |
149 | ||
150 | //======================================================================= | |
151 | //function : NIS_Surface | |
152 | //purpose : Constructor | |
153 | //======================================================================= | |
154 | ||
ffe2bea7 A |
155 | NIS_Surface::NIS_Surface (const TopoDS_Shape& theShape, |
156 | const Standard_Real theDeflection, | |
157 | const Handle_NCollection_BaseAllocator& theAlloc) | |
158 | : myAlloc (theAlloc), | |
159 | mypNodes (NULL), | |
7fd59977 | 160 | mypNormals (NULL), |
161 | mypTriangles (NULL), | |
ffe2bea7 | 162 | mypEdges (NULL), |
7fd59977 | 163 | myNNodes (0), |
164 | myNTriangles (0), | |
ffe2bea7 A |
165 | myNEdges (0), |
166 | myIsWireframe (0) | |
7fd59977 | 167 | { |
168 | if (myAlloc.IsNull()) | |
169 | myAlloc = NCollection_BaseAllocator::CommonBaseAllocator(); | |
ffe2bea7 A |
170 | Init (theShape, theDeflection); |
171 | } | |
172 | ||
173 | //======================================================================= | |
174 | //function : Init | |
175 | //purpose : Initialize the instance with a TopoDS_Shape. | |
176 | //======================================================================= | |
177 | ||
178 | void NIS_Surface::Init (const TopoDS_Shape& theShape, | |
179 | const Standard_Real theDeflection) | |
180 | { | |
7fd59977 | 181 | TopLoc_Location aLoc, aLocSurf; |
182 | ||
183 | // Count the nodes and triangles in faces | |
ffe2bea7 | 184 | NCollection_Map<Handle_Poly_Triangulation> mapTri; |
7fd59977 | 185 | TopExp_Explorer fexp (theShape, TopAbs_FACE); |
ffe2bea7 | 186 | for (; fexp.More(); fexp.Next()) |
7fd59977 | 187 | { |
ffe2bea7 | 188 | const TopoDS_Face& aFace = TopoDS::Face(fexp.Current()); |
7fd59977 | 189 | |
190 | const Handle(Poly_Triangulation)& aTriangulation | |
191 | = BRep_Tool::Triangulation (aFace, aLoc); | |
ffe2bea7 A |
192 | |
193 | if (aTriangulation.IsNull()) | |
194 | BRepMesh_IncrementalMesh aMeshTool(aFace, theDeflection); | |
7fd59977 | 195 | |
ffe2bea7 | 196 | if (aTriangulation.IsNull() == Standard_False) |
7fd59977 | 197 | { |
198 | myNNodes += aTriangulation->NbNodes(); | |
199 | myNTriangles += aTriangulation->NbTriangles(); | |
ffe2bea7 | 200 | mapTri.Add(aTriangulation); |
7fd59977 | 201 | } |
202 | } | |
203 | ||
ffe2bea7 A |
204 | // Create map of edges, to build wireframe for all edges. |
205 | TopTools_MapOfShape mapEdges; | |
206 | TopExp_Explorer eexp (theShape, TopAbs_EDGE); | |
207 | for (; eexp.More(); eexp.Next()) | |
208 | { | |
209 | const TopoDS_Shape& anEdge = eexp.Current(); | |
210 | mapEdges.Add(anEdge); | |
211 | } | |
212 | ||
213 | // Allocate arrays of entities | |
7fd59977 | 214 | if (myNNodes && myNTriangles) { |
ffe2bea7 | 215 | mypNodes = static_cast<Standard_ShortReal *> |
7fd59977 | 216 | (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes)); |
217 | mypNormals = static_cast<Standard_ShortReal *> | |
218 | (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes)); | |
ffe2bea7 | 219 | mypTriangles = static_cast<Standard_Integer *> |
7fd59977 | 220 | (myAlloc->Allocate(sizeof(Standard_Integer) * 3 * myNTriangles)); |
ffe2bea7 A |
221 | mypEdges = static_cast<Standard_Integer **> |
222 | (myAlloc->Allocate(sizeof(Standard_Integer *) * mapEdges.Extent())); | |
223 | myNEdges = 0; | |
7fd59977 | 224 | |
225 | // The second loop: copy all nodes and triangles face-by-face | |
226 | const Standard_Real eps2 = Precision::Confusion()*Precision::Confusion(); | |
227 | Standard_Integer nNodes (0), nTriangles (0); | |
228 | for (fexp.ReInit(); fexp.More(); fexp.Next()) | |
229 | { | |
230 | const TopoDS_Face& aFace = TopoDS::Face(fexp.Current()); | |
231 | const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLocSurf); | |
232 | const Handle(Poly_Triangulation)& aTriangulation = | |
233 | BRep_Tool::Triangulation(aFace, aLoc); | |
ffe2bea7 | 234 | if (aTriangulation.IsNull() == Standard_False) |
7fd59977 | 235 | { |
236 | // Prepare transformation | |
237 | Standard_Integer i, aNodeInd(nNodes)/*, aNTriangles = 0*/; | |
238 | const gp_Trsf& aTrf = aLoc.Transformation(); | |
239 | const gp_Trsf& aTrfSurf = aLocSurf.Transformation(); | |
240 | Standard_Boolean isReverse = (aFace.Orientation() == TopAbs_REVERSED); | |
241 | ||
242 | // Store all nodes of the current face in the data model | |
243 | const TColgp_Array1OfPnt& tabNode = aTriangulation->Nodes(); | |
244 | const TColgp_Array1OfPnt2d& tabUV = aTriangulation->UVNodes(); | |
245 | for (i = tabNode.Lower(); i <= tabNode.Upper(); i++) | |
246 | { | |
247 | Standard_Real t[3]; | |
248 | tabNode(i).Transformed(aTrf).Coord (t[0], t[1], t[2]); | |
249 | // write node to mesh data | |
250 | mypNodes[3*aNodeInd + 0] = static_cast<Standard_ShortReal>(t[0]); | |
251 | mypNodes[3*aNodeInd + 1] = static_cast<Standard_ShortReal>(t[1]); | |
252 | mypNodes[3*aNodeInd + 2] = static_cast<Standard_ShortReal>(t[2]); | |
253 | ||
254 | gp_Vec aD1U, aD1V; | |
255 | gp_Pnt aP; | |
ffe2bea7 A |
256 | gp_XYZ aNorm(0., 0., 0.); |
257 | ||
258 | if (aTriangulation->HasNormals()) { | |
259 | // Retrieve the normal direction from the triangulation | |
260 | aNorm.SetCoord(aTriangulation->Normals().Value(3*i-2), | |
261 | aTriangulation->Normals().Value(3*i-1), | |
262 | aTriangulation->Normals().Value(3*i-0)); | |
263 | } else if (aSurf.IsNull() == Standard_False) | |
264 | { | |
265 | // Compute the surface normal at the Node. | |
266 | aSurf->D1(tabUV(i).X(), tabUV(i).Y(), aP, aD1U, aD1V); | |
267 | aNorm = (aD1U.Crossed(aD1V)).XYZ(); | |
268 | } | |
7fd59977 | 269 | |
7fd59977 | 270 | if (isReverse) |
271 | aNorm.Reverse(); | |
272 | const Standard_Real aMod = aNorm.SquareModulus(); | |
273 | if (aMod > eps2) { | |
274 | gp_Dir aDirNorm(aNorm); | |
275 | aDirNorm.Transform(aTrfSurf); | |
276 | aDirNorm.Coord (t[0], t[1], t[2]); | |
277 | } else { | |
278 | t[0] = 0.; | |
279 | t[1] = 0.; | |
280 | t[2] = 1.; | |
281 | } | |
282 | mypNormals[3*aNodeInd + 0] = static_cast<Standard_ShortReal>(t[0]); | |
283 | mypNormals[3*aNodeInd + 1] = static_cast<Standard_ShortReal>(t[1]); | |
284 | mypNormals[3*aNodeInd + 2] = static_cast<Standard_ShortReal>(t[2]); | |
285 | ||
286 | aNodeInd++; | |
287 | } | |
ffe2bea7 | 288 | const Standard_Integer nNodes1 = nNodes - 1; |
7fd59977 | 289 | // Store all triangles of the current face in the data model |
290 | const Poly_Array1OfTriangle& tabTri = aTriangulation->Triangles(); | |
291 | for (i = tabTri.Lower(); i <= tabTri.Upper(); i++) | |
292 | { | |
293 | Standard_Integer aN[3]; | |
294 | tabTri(i).Get (aN[0], aN[1], aN[2]); | |
ffe2bea7 A |
295 | Standard_Integer * pTriangle = &mypTriangles[nTriangles*3]; |
296 | pTriangle[0] = aN[0] + nNodes1; | |
297 | if (isReverse) { | |
298 | pTriangle[1] = aN[2] + nNodes1; | |
299 | pTriangle[2] = aN[1] + nNodes1; | |
300 | } else { | |
301 | pTriangle[1] = aN[1] + nNodes1; | |
302 | pTriangle[2] = aN[2] + nNodes1; | |
303 | } | |
304 | const Standard_ShortReal aVec0[3] = { | |
305 | mypNodes[3*pTriangle[1]+0] - mypNodes[3*pTriangle[0]+0], | |
306 | mypNodes[3*pTriangle[1]+1] - mypNodes[3*pTriangle[0]+1], | |
307 | mypNodes[3*pTriangle[1]+2] - mypNodes[3*pTriangle[0]+2] | |
308 | }; | |
309 | const Standard_ShortReal aVec1[3] = { | |
310 | mypNodes[3*pTriangle[2]+0] - mypNodes[3*pTriangle[0]+0], | |
311 | mypNodes[3*pTriangle[2]+1] - mypNodes[3*pTriangle[0]+1], | |
312 | mypNodes[3*pTriangle[2]+2] - mypNodes[3*pTriangle[0]+2] | |
313 | }; | |
314 | const Standard_ShortReal aVecP[3] = { | |
315 | aVec0[1] * aVec1[2] - aVec0[2] * aVec1[1], | |
316 | aVec0[2] * aVec1[0] - aVec0[0] * aVec1[2], | |
317 | aVec0[0] * aVec1[1] - aVec0[1] * aVec1[0] | |
318 | }; | |
319 | if (aVecP[0]*aVecP[0] + aVecP[1]*aVecP[1] + aVecP[2]*aVecP[2] > eps2) | |
7fd59977 | 320 | nTriangles++; |
ffe2bea7 A |
321 | } |
322 | // Store all edge polygons on the current face. | |
323 | for (eexp.Init(aFace, TopAbs_EDGE); eexp.More(); eexp.Next()) | |
324 | { | |
325 | const TopoDS_Edge& anEdge = TopoDS::Edge(eexp.Current()); | |
326 | if (mapEdges.Remove(anEdge)) { | |
327 | const Handle(Poly_PolygonOnTriangulation)& aPolygon = | |
328 | BRep_Tool::PolygonOnTriangulation(anEdge, aTriangulation, aLoc); | |
329 | if (aPolygon.IsNull() == Standard_False) { | |
330 | const TColStd_Array1OfInteger& arrNode = aPolygon->Nodes(); | |
331 | // Allocate memory to store the current polygon indices. | |
332 | Standard_Integer aLen = arrNode.Length(); | |
333 | Standard_Integer * pEdge = static_cast<Standard_Integer *> | |
334 | (myAlloc->Allocate(sizeof(Standard_Integer) * (aLen + 1))); | |
335 | const gp_Pnt* pLast = &tabNode(arrNode(arrNode.Lower())); | |
336 | pEdge[1] = arrNode(arrNode.Lower()) + nNodes1; | |
337 | Standard_Integer iPNode(arrNode.Lower() + 1), iENode(1); | |
338 | for (; iPNode <= arrNode.Upper(); iPNode++) | |
339 | { | |
340 | const Standard_Integer aN(arrNode(iPNode)); | |
341 | if (pLast->SquareDistance(tabNode(aN)) < eps2) | |
342 | { | |
343 | aLen--; | |
344 | } else { | |
345 | pLast = &tabNode(aN); | |
346 | pEdge[++iENode] = aN + nNodes1; | |
347 | } | |
348 | } | |
349 | // Do not save very short polygons | |
350 | if (aLen > 1) { | |
351 | pEdge[0] = aLen; | |
352 | mypEdges[myNEdges++] = pEdge; | |
353 | } | |
354 | } | |
7fd59977 | 355 | } |
356 | } | |
357 | nNodes += tabNode.Length(); | |
358 | } | |
359 | } | |
360 | myNTriangles = nTriangles; | |
361 | } | |
ffe2bea7 A |
362 | if (GetDrawer().IsNull() == Standard_False) |
363 | { | |
364 | setDrawerUpdate(); | |
365 | } | |
366 | setIsUpdateBox(Standard_True); | |
7fd59977 | 367 | } |
368 | ||
369 | //======================================================================= | |
370 | //function : ~NIS_Surface | |
371 | //purpose : Destructor | |
372 | //======================================================================= | |
373 | ||
374 | NIS_Surface::~NIS_Surface () | |
ffe2bea7 A |
375 | { |
376 | Clear(); | |
377 | } | |
378 | ||
379 | //======================================================================= | |
380 | //function : Clear | |
381 | //purpose : | |
382 | //======================================================================= | |
383 | ||
384 | void NIS_Surface::Clear () | |
7fd59977 | 385 | { |
386 | if (myNNodes) { | |
387 | myNNodes = 0; | |
388 | myAlloc->Free(mypNodes); | |
389 | myAlloc->Free(mypNormals); | |
390 | } | |
391 | if (myNTriangles) { | |
392 | myNTriangles = 0; | |
393 | myAlloc->Free(mypTriangles); | |
394 | } | |
ffe2bea7 A |
395 | if (mypEdges) { |
396 | for (Standard_Integer i = 0; i < myNEdges; i++) { | |
397 | myAlloc->Free(mypEdges[i]); | |
398 | } | |
399 | myNEdges = 0; | |
400 | myAlloc->Free(mypEdges); | |
401 | } | |
402 | if (GetDrawer().IsNull() == Standard_False) { | |
403 | GetDrawer()->SetUpdated(NIS_Drawer::Draw_Normal, | |
404 | NIS_Drawer::Draw_Top, | |
405 | NIS_Drawer::Draw_Transparent, | |
406 | NIS_Drawer::Draw_Hilighted); | |
407 | } | |
408 | myBox.Clear(); | |
7fd59977 | 409 | } |
410 | ||
411 | //======================================================================= | |
412 | //function : DefaultDrawer | |
413 | //purpose : | |
414 | //======================================================================= | |
415 | ||
ffe2bea7 | 416 | NIS_Drawer * NIS_Surface::DefaultDrawer (NIS_Drawer * theDrawer) const |
7fd59977 | 417 | { |
ffe2bea7 A |
418 | NIS_SurfaceDrawer * aDrawer = |
419 | theDrawer ? static_cast<NIS_SurfaceDrawer *>(theDrawer) | |
420 | : new NIS_SurfaceDrawer (Quantity_NOC_SLATEBLUE4); | |
421 | aDrawer->SetBackColor (Quantity_NOC_DARKGREEN); | |
422 | aDrawer->myIsWireframe = myIsWireframe; | |
423 | return aDrawer; | |
7fd59977 | 424 | } |
425 | ||
426 | //======================================================================= | |
427 | //function : SetColor | |
428 | //purpose : Set the normal color for presentation. | |
429 | //======================================================================= | |
430 | ||
431 | void NIS_Surface::SetColor (const Quantity_Color& theColor) | |
432 | { | |
ffe2bea7 A |
433 | const Handle(NIS_SurfaceDrawer) aDrawer = |
434 | static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L)); | |
7fd59977 | 435 | aDrawer->Assign (GetDrawer()); |
436 | aDrawer->myColor[NIS_Drawer::Draw_Normal] = theColor; | |
ffe2bea7 | 437 | aDrawer->myColor[NIS_Drawer::Draw_Top] = theColor; |
7fd59977 | 438 | aDrawer->myColor[NIS_Drawer::Draw_Transparent] = theColor; |
439 | SetDrawer (aDrawer); | |
440 | } | |
441 | ||
442 | //======================================================================= | |
443 | //function : SetBackColor | |
444 | //purpose : Set the normal color for presentation of back side of triangles. | |
445 | //======================================================================= | |
446 | ||
447 | void NIS_Surface::SetBackColor (const Quantity_Color& theColor) | |
448 | { | |
ffe2bea7 A |
449 | const Handle(NIS_SurfaceDrawer) aDrawer = |
450 | static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L)); | |
7fd59977 | 451 | aDrawer->Assign (GetDrawer()); |
452 | aDrawer->myBackColor = theColor; | |
453 | SetDrawer (aDrawer); | |
454 | } | |
455 | ||
456 | //======================================================================= | |
457 | //function : SetPolygonOffset | |
458 | //purpose : | |
459 | //======================================================================= | |
460 | ||
461 | void NIS_Surface::SetPolygonOffset (const Standard_Real theValue) | |
462 | { | |
ffe2bea7 A |
463 | const Handle(NIS_SurfaceDrawer) aDrawer = |
464 | static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L)); | |
7fd59977 | 465 | aDrawer->Assign (GetDrawer()); |
ffe2bea7 | 466 | aDrawer->myPolygonOffset = static_cast<Standard_ShortReal>(theValue); |
7fd59977 | 467 | SetDrawer (aDrawer); |
468 | } | |
469 | ||
470 | //======================================================================= | |
ffe2bea7 A |
471 | //function : SetDisplayMode |
472 | //purpose : Set the display mode: Shading or Wireframe. | |
473 | //======================================================================= | |
474 | ||
475 | void NIS_Surface::SetDisplayMode (const NIS_Surface::DisplayMode theMode) | |
476 | { | |
477 | Standard_Boolean isUpdate(Standard_False); | |
478 | if (myIsWireframe) { | |
479 | if (theMode != Wireframe) { | |
480 | myIsWireframe = Standard_False; | |
481 | isUpdate = Standard_True; | |
482 | } | |
483 | } else { | |
484 | if (theMode == Wireframe) { | |
485 | myIsWireframe = Standard_True; | |
486 | isUpdate = Standard_True; | |
487 | } | |
488 | } | |
9e4c2fbb | 489 | if (isUpdate && !GetDrawer().IsNull()) { |
ffe2bea7 A |
490 | const Handle(NIS_SurfaceDrawer) aDrawer = |
491 | static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L)); | |
492 | aDrawer->Assign (GetDrawer()); | |
493 | aDrawer->myIsWireframe = myIsWireframe; | |
494 | SetDrawer(aDrawer); | |
495 | } | |
496 | } | |
497 | ||
498 | //======================================================================= | |
499 | //function : GetDisplayMode | |
500 | //purpose : Query the current display mode: Shading or Wireframe. | |
501 | //======================================================================= | |
502 | ||
503 | NIS_Surface::DisplayMode NIS_Surface::GetDisplayMode () const | |
504 | { | |
505 | return myIsWireframe ? Wireframe : Shading; | |
506 | } | |
507 | ||
508 | //======================================================================= | |
509 | //function : Clone | |
7fd59977 | 510 | //purpose : |
511 | //======================================================================= | |
512 | ||
ffe2bea7 A |
513 | void NIS_Surface::Clone (const Handle_NCollection_BaseAllocator& theAlloc, |
514 | Handle_NIS_InteractiveObject& theDest) const | |
7fd59977 | 515 | { |
ffe2bea7 A |
516 | Handle(NIS_Surface) aNewObj; |
517 | if (theDest.IsNull()) { | |
518 | aNewObj = new NIS_Surface(theAlloc); | |
519 | theDest = aNewObj; | |
520 | } else { | |
521 | aNewObj = reinterpret_cast<NIS_Surface*> (theDest.operator->()); | |
522 | aNewObj->myAlloc = theAlloc; | |
523 | } | |
524 | NIS_InteractiveObject::Clone(theAlloc, theDest); | |
525 | aNewObj->myNNodes = myNNodes; | |
526 | if (myNNodes > 0) { | |
527 | // copy nodes and normals | |
528 | const Standard_Size nBytes = myNNodes*3*sizeof(Standard_ShortReal); | |
529 | aNewObj->mypNodes = (Standard_ShortReal *)theAlloc->Allocate(nBytes); | |
530 | aNewObj->mypNormals = (Standard_ShortReal *)theAlloc->Allocate(nBytes); | |
531 | memcpy(aNewObj->mypNodes, mypNodes, nBytes); | |
532 | memcpy(aNewObj->mypNormals, mypNormals, nBytes); | |
533 | } | |
534 | aNewObj->myNTriangles = myNTriangles; | |
535 | if (myNTriangles > 0) { | |
536 | const Standard_Size nBytes = sizeof(Standard_Integer) * 3 * myNTriangles; | |
537 | aNewObj->mypTriangles = (Standard_Integer *)theAlloc->Allocate(nBytes); | |
538 | memcpy(aNewObj->mypTriangles, mypTriangles, nBytes); | |
539 | } | |
540 | aNewObj->myNEdges = myNEdges; | |
541 | if (myNEdges > 0) { | |
542 | aNewObj->mypEdges = static_cast<Standard_Integer **> | |
543 | (theAlloc->Allocate(sizeof(Standard_Integer *) * myNEdges)); | |
544 | for (Standard_Integer i = 0; i < myNEdges; i++) { | |
545 | const Standard_Integer * pEdge = mypEdges[i]; | |
546 | const Standard_Size nBytes = sizeof(Standard_Integer) * (pEdge[0] + 1); | |
547 | aNewObj->mypEdges[i] = | |
548 | static_cast<Standard_Integer *> (theAlloc->Allocate(nBytes)); | |
549 | memcpy(aNewObj->mypEdges[i], pEdge, nBytes); | |
550 | } | |
551 | } | |
552 | aNewObj->myIsWireframe = myIsWireframe; | |
7fd59977 | 553 | } |
554 | ||
555 | //======================================================================= | |
556 | //function : Intersect | |
557 | //purpose : | |
558 | //======================================================================= | |
559 | ||
560 | Standard_Real NIS_Surface::Intersect (const gp_Ax1& theAxis, | |
ffe2bea7 | 561 | const Standard_Real theOver) const |
7fd59977 | 562 | { |
563 | Standard_Real aResult (RealLast()); | |
564 | Standard_Real start[3], dir[3]; | |
565 | theAxis.Location().Coord(start[0], start[1], start[2]); | |
566 | theAxis.Direction().Coord(dir[0], dir[1], dir[2]); | |
567 | double anInter; | |
568 | ||
ffe2bea7 A |
569 | if (myIsWireframe == Standard_False) |
570 | for (Standard_Integer i = 0; i < myNTriangles; i++) { | |
571 | const Standard_Integer * pTri = &mypTriangles[3*i]; | |
572 | if (NIS_Triangulated::tri_line_intersect (start, dir, | |
573 | &mypNodes[3*pTri[0]], | |
574 | &mypNodes[3*pTri[1]], | |
575 | &mypNodes[3*pTri[2]], | |
576 | &anInter)) | |
577 | if (anInter < aResult) | |
578 | aResult = anInter; | |
579 | } | |
580 | else { | |
581 | const Standard_Real anOver2 = theOver*theOver; | |
582 | for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) { | |
583 | const Standard_Integer * anEdge = mypEdges[iEdge]; | |
584 | const Standard_Integer nNodes = anEdge[0]; | |
585 | for (Standard_Integer i = 1; i < nNodes; i++) { | |
586 | // Node index is incremented for the head of polygon indice array | |
587 | if (NIS_Triangulated::seg_line_intersect (theAxis.Location().XYZ(), | |
588 | theAxis.Direction().XYZ(), | |
589 | anOver2, | |
590 | &mypNodes[3*anEdge[i+0]], | |
591 | &mypNodes[3*anEdge[i+1]], | |
592 | &anInter)) | |
593 | if (anInter < aResult) | |
594 | aResult = anInter; | |
595 | } | |
596 | } | |
7fd59977 | 597 | } |
598 | ||
599 | return aResult; | |
600 | } | |
601 | ||
602 | //======================================================================= | |
603 | //function : Intersect | |
604 | //purpose : | |
605 | //======================================================================= | |
606 | ||
ffe2bea7 | 607 | Standard_Boolean NIS_Surface::Intersect (const Bnd_B3f& theBox, |
7fd59977 | 608 | const gp_Trsf& theTrf, |
609 | const Standard_Boolean isFullIn) const | |
610 | { | |
611 | Standard_Boolean aResult (isFullIn); | |
612 | ||
ffe2bea7 A |
613 | if (myIsWireframe == Standard_False) { |
614 | if (myNTriangles > 0) { | |
615 | for (Standard_Integer iNode = 0; iNode < myNNodes*3; iNode+=3) { | |
616 | gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]), | |
617 | static_cast<Standard_Real>(mypNodes[iNode+1]), | |
618 | static_cast<Standard_Real>(mypNodes[iNode+2])); | |
619 | theTrf.Transforms(aPnt); | |
620 | if (theBox.IsOut (aPnt) == isFullIn) { | |
621 | aResult = !isFullIn; | |
622 | break; | |
623 | } | |
624 | } | |
625 | } | |
626 | } else { | |
627 | for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) { | |
628 | const Standard_Integer * anEdge = mypEdges[iEdge]; | |
629 | const Standard_Integer nNodes = anEdge[0]; | |
630 | for (Standard_Integer i = 1; i < nNodes; i++) { | |
631 | // index is incremented by 1 for the head number in the array | |
632 | gp_Pnt aPnt[2] = { | |
633 | gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]), | |
634 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]), | |
635 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])), | |
636 | gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]), | |
637 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]), | |
638 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2])) | |
639 | }; | |
640 | aPnt[0].Transform(theTrf); | |
641 | aPnt[1].Transform(theTrf); | |
642 | if (isFullIn) { | |
643 | if (NIS_Triangulated::seg_box_included (theBox, aPnt) == 0) { | |
644 | aResult = Standard_False; | |
645 | break; | |
646 | } | |
647 | } else { | |
648 | if (NIS_Triangulated::seg_box_intersect (theBox, aPnt)) { | |
649 | aResult = Standard_True; | |
650 | break; | |
651 | } | |
652 | } | |
653 | } | |
654 | } | |
655 | } | |
656 | return aResult; | |
657 | } | |
658 | ||
659 | //======================================================================= | |
660 | //function : Intersect | |
661 | //purpose : Selection by polygon | |
662 | //======================================================================= | |
663 | ||
664 | Standard_Boolean NIS_Surface::Intersect | |
665 | (const NCollection_List<gp_XY> &thePolygon, | |
666 | const gp_Trsf &theTrf, | |
667 | const Standard_Boolean isFullIn) const | |
668 | { | |
669 | Standard_Boolean aResult (isFullIn); | |
670 | ||
671 | if (myIsWireframe == Standard_False) { | |
672 | if (myNTriangles > 0) { | |
673 | for (Standard_Integer iNode = 0; iNode < myNNodes*3; iNode+=3) { | |
674 | gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]), | |
675 | static_cast<Standard_Real>(mypNodes[iNode+1]), | |
676 | static_cast<Standard_Real>(mypNodes[iNode+2])); | |
677 | theTrf.Transforms(aPnt); | |
678 | gp_XY aP2d(aPnt.X(), aPnt.Y()); | |
679 | ||
680 | if (!NIS_Triangulated::IsIn(thePolygon, aP2d)) { | |
681 | if (isFullIn) { | |
682 | aResult = Standard_False; | |
683 | break; | |
684 | } | |
685 | } else { | |
686 | if (isFullIn == Standard_False) { | |
687 | aResult = Standard_True; | |
688 | break; | |
689 | } | |
690 | } | |
691 | } | |
692 | } | |
693 | } else { | |
694 | for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) { | |
695 | const Standard_Integer * anEdge = mypEdges[iEdge]; | |
696 | const Standard_Integer nNodes = anEdge[0]; | |
697 | for (Standard_Integer i = 1; i < nNodes; i++) { | |
698 | // index is incremented by 1 for the head number in the array | |
699 | gp_Pnt aPnt[2] = { | |
700 | gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]), | |
701 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]), | |
702 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])), | |
703 | gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]), | |
704 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]), | |
705 | static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2])) | |
706 | }; | |
707 | aPnt[0].Transform(theTrf); | |
708 | aPnt[1].Transform(theTrf); | |
709 | const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()), | |
710 | gp_XY(aPnt[1].X(), aPnt[1].Y()) }; | |
711 | if (isFullIn) { | |
712 | if (NIS_Triangulated::seg_polygon_included (thePolygon, aP2d) == 0) { | |
713 | aResult = Standard_False; | |
714 | break; | |
715 | } | |
716 | } else { | |
717 | if (NIS_Triangulated::seg_polygon_intersect (thePolygon, aP2d)) { | |
718 | aResult = Standard_True; | |
719 | break; | |
720 | } | |
721 | } | |
7fd59977 | 722 | } |
723 | } | |
724 | } | |
725 | return aResult; | |
726 | } | |
727 | ||
728 | //======================================================================= | |
729 | //function : computeBox | |
730 | //purpose : | |
731 | //======================================================================= | |
732 | ||
733 | void NIS_Surface::computeBox () | |
734 | { | |
ffe2bea7 | 735 | NIS_Triangulated::ComputeBox(myBox, myNNodes, mypNodes, 3); |
7fd59977 | 736 | |
737 | const Handle(NIS_SurfaceDrawer)& aDrawer = | |
738 | static_cast<const Handle(NIS_SurfaceDrawer)&> (GetDrawer()); | |
739 | ||
740 | if (aDrawer.IsNull() == Standard_False) { | |
741 | const gp_Trsf& aTrsf = aDrawer->GetTransformation(); | |
742 | myBox = myBox.Transformed(aTrsf); | |
743 | } | |
744 | } |