0023404: Create SquareConfusion function in Precision package for speed and convenience
[occt.git] / src / NIS / NIS_Surface.cxx
CommitLineData
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
45IMPLEMENT_STANDARD_HANDLE (NIS_Surface, NIS_InteractiveObject)
46IMPLEMENT_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
53inline 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
64NIS_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
84NIS_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
155NIS_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
178void 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
08cd2f6b 226 const Standard_Real eps2 = Precision::SquareConfusion();
7fd59977 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
374NIS_Surface::~NIS_Surface ()
ffe2bea7
A
375{
376 Clear();
377}
378
379//=======================================================================
380//function : Clear
381//purpose :
382//=======================================================================
383
384void 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 416NIS_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
431void 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
447void 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
461void 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
475void 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
503NIS_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
513void 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
560Standard_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 607Standard_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
664Standard_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
733void 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}