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