0025936: Reusable data structure for 2D tesselation (3- and 4-nodal mesh)
[occt.git] / src / NIS / NIS_Surface.cxx
CommitLineData
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
40IMPLEMENT_STANDARD_HANDLE (NIS_Surface, NIS_InteractiveObject)
41IMPLEMENT_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 48inline 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 59NIS_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 79NIS_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
148NIS_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
171void 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
362NIS_Surface::~NIS_Surface ()
ffe2bea7
A
363{
364 Clear();
365}
366
367//=======================================================================
368//function : Clear
369//purpose :
370//=======================================================================
371
372void 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 404NIS_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
419void 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
435void 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
449void 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
463void 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
491NIS_Surface::DisplayMode NIS_Surface::GetDisplayMode () const
492{
493 return myIsWireframe ? Wireframe : Shading;
494}
495
496//=======================================================================
497//function : Clone
7fd59977 498//purpose :
499//=======================================================================
500
857ffd5e 501void 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
548Standard_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 595Standard_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
652Standard_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
721void 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}