1 // Created on: 2007-07-17
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2007-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <NIS_Triangulated.hxx>
17 #include <NIS_TriangulatedDrawer.hxx>
18 #include <NIS_InteractiveContext.hxx>
20 #include <Precision.hxx>
22 IMPLEMENT_STANDARD_HANDLE (NIS_Triangulated, NIS_InteractiveObject)
23 IMPLEMENT_STANDARD_RTTIEXT (NIS_Triangulated, NIS_InteractiveObject)
25 static Standard_Real aTolConf = Precision::Confusion() * 0.0001;
28 * Checking the given value if it is considerably greater than zero.
30 static inline Standard_Boolean IsPositive (const Standard_Real theVal)
32 return (theVal > aTolConf);
36 * Compute the size in bytes of an index array.
38 static inline Standard_Size NBytesInd (const Standard_Integer nInd,
39 const unsigned int theIndType)
41 Standard_Size nBytes = static_cast<Standard_Size>(nInd);
50 //=======================================================================
51 //function : NIS_Triangulated()
52 //purpose : Constructor
53 //=======================================================================
55 NIS_Triangulated::NIS_Triangulated
56 (const Standard_Integer nNodes,
57 const Standard_Boolean is2D,
58 const Handle(NCollection_BaseAllocator)& theAlloc)
69 myIsDrawPolygons (Standard_False),
70 myIsCloned (Standard_False),
72 myNodeCoord (is2D ? 2 : 3),
73 myPolygonType (static_cast<unsigned int>(Polygon_Default))
76 if (theAlloc.IsNull())
77 myAlloc = NCollection_BaseAllocator::CommonBaseAllocator().operator->();
79 myAlloc = theAlloc.operator->();
80 allocateNodes (nNodes);
83 //=======================================================================
85 //purpose : Reset all internal data members and structures
86 //=======================================================================
88 void NIS_Triangulated::Clear ()
92 myAlloc->Free(mypNodes);
97 myAlloc->Free(mypTriangles);
102 myAlloc->Free( mypLines);
106 for (unsigned int i = 0; i < myNPolygons; i++)
107 myAlloc->Free(mypPolygons[i]);
108 myAlloc->Free(mypPolygons);
113 myIsDrawPolygons = Standard_False;
114 myPolygonType = static_cast<unsigned int>(Polygon_Default);
115 if (GetDrawer().IsNull() == Standard_False) {
116 GetDrawer()->SetUpdated(NIS_Drawer::Draw_Normal,
117 NIS_Drawer::Draw_Top,
118 NIS_Drawer::Draw_Transparent,
119 NIS_Drawer::Draw_Hilighted);
123 //=======================================================================
124 //function : SetPolygonsPrs
126 //=======================================================================
128 void NIS_Triangulated::SetPolygonsPrs (const Standard_Integer nPolygons,
129 const Standard_Integer nNodes)
132 myType &= ~Type_Polygons;
134 myType |= Type_Polygons;
136 for (unsigned int i = 0; i < myNPolygons; i++)
137 myAlloc->Free(mypPolygons[i]);
138 myAlloc->Free(mypPolygons);
140 myNPolygons = static_cast<unsigned int>(nPolygons);
141 mypPolygons = static_cast<Standard_Integer **>
142 (myAlloc->Allocate(sizeof(Standard_Integer *)*nPolygons));
143 allocateNodes (nNodes);
147 //=======================================================================
148 //function : SetTriangulationPrs
150 //=======================================================================
152 void NIS_Triangulated::SetTriangulationPrs (const Standard_Integer nTri,
153 const Standard_Integer nNodes)
156 myType &= ~Type_Triangulation;
158 myType |= Type_Triangulation;
160 myAlloc->Free(mypTriangles);
161 allocateNodes (nNodes);
164 const Standard_Size nBytes = NBytesInd(3 * nTri, myIndexType);
165 mypTriangles = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
169 //=======================================================================
170 //function : SetLinePrs
172 //=======================================================================
174 void NIS_Triangulated::SetLinePrs (const Standard_Integer nPoints,
175 const Standard_Boolean isClosed,
176 const Standard_Integer nNodes)
179 myType &= ~(Type_Loop | Type_Line);
185 myAlloc->Free(mypLines);
186 myType &= ~Type_Segments;
187 allocateNodes (nNodes);
189 myNLineNodes = nPoints;
190 const Standard_Size nBytes = NBytesInd(nPoints, myIndexType);
191 mypLines = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
195 //=======================================================================
196 //function : SetSegmentPrs
198 //=======================================================================
200 void NIS_Triangulated::SetSegmentPrs (const Standard_Integer nSegments,
201 const Standard_Integer nNodes)
204 myType &= ~(Type_Loop | Type_Segments);
206 myType |= Type_Segments;
208 myAlloc->Free(mypLines);
209 myType &= ~(Type_Line | Type_Loop);
210 allocateNodes (nNodes);
212 myNLineNodes = nSegments*2;
213 const Standard_Size nBytes = NBytesInd(myNLineNodes, myIndexType);
214 mypLines = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
218 //=======================================================================
219 //function : ~NIS_Triangulated
220 //purpose : Destructor
221 //=======================================================================
223 NIS_Triangulated::~NIS_Triangulated ()
228 //=======================================================================
229 //function : DefaultDrawer
231 //=======================================================================
233 NIS_Drawer * NIS_Triangulated::DefaultDrawer (NIS_Drawer * theDrawer) const
235 NIS_TriangulatedDrawer * aDrawer =
236 theDrawer ? static_cast<NIS_TriangulatedDrawer *>(theDrawer)
237 : new NIS_TriangulatedDrawer (Quantity_NOC_RED);
238 aDrawer->myIsDrawPolygons = myIsDrawPolygons;
239 aDrawer->myPolygonType = myPolygonType;
243 //=======================================================================
244 //function : ComputeBox
246 //=======================================================================
248 void NIS_Triangulated::ComputeBox (Bnd_B3f& theBox,
249 const Standard_Integer nNodes,
250 const Standard_ShortReal* pNodes,
251 const Standard_Integer nCoord)
255 Standard_ShortReal aBox[6] = {
256 pNodes[0], pNodes[1], 0.,
257 pNodes[0], pNodes[1], 0.
263 for (Standard_Integer i = 1; i < nNodes; i++) {
264 const Standard_ShortReal * pNode = &pNodes[i * nCoord];
265 if (aBox[0] > pNode[0])
267 else if (aBox[3] < pNode[0])
269 if (aBox[1] > pNode[1])
271 else if (aBox[4] < pNode[1])
274 if (aBox[2] > pNode[2])
276 else if (aBox[5] < pNode[2])
280 theBox.Add (gp_XYZ (Standard_Real(aBox[0]),
281 Standard_Real(aBox[1]),
282 Standard_Real(aBox[2])));
283 theBox.Add (gp_XYZ (Standard_Real(aBox[3]),
284 Standard_Real(aBox[4]),
285 Standard_Real(aBox[5])));
289 //=======================================================================
290 //function : computeBox
292 //=======================================================================
294 void NIS_Triangulated::computeBox ()
296 ComputeBox (myBox, myNNodes, mypNodes, myNodeCoord);
299 //=======================================================================
302 //=======================================================================
304 void NIS_Triangulated::SetNode (const Standard_Integer ind,
305 const gp_XYZ& thePnt)
308 Standard_OutOfRange::Raise ("NIS_Triangulated::SetNode");
309 Standard_ShortReal * pNode = &mypNodes[myNodeCoord * ind];
310 pNode[0] = Standard_ShortReal(thePnt.X());
311 pNode[1] = Standard_ShortReal(thePnt.Y());
313 pNode[2] = Standard_ShortReal(thePnt.Z());
314 setIsUpdateBox(Standard_True);
317 //=======================================================================
320 //=======================================================================
322 void NIS_Triangulated::SetNode (const Standard_Integer ind,
326 Standard_OutOfRange::Raise ("NIS_Triangulated::SetNode");
327 Standard_ShortReal * pNode = &mypNodes[myNodeCoord * ind];
328 pNode[0] = Standard_ShortReal(thePnt.X());
329 pNode[1] = Standard_ShortReal(thePnt.Y());
332 setIsUpdateBox(Standard_True);
335 //=======================================================================
336 //function : SetTriangle
338 //=======================================================================
340 void NIS_Triangulated::SetTriangle (const Standard_Integer ind,
341 const Standard_Integer iNode0,
342 const Standard_Integer iNode1,
343 const Standard_Integer iNode2)
345 if (ind >= myNTriangles)
346 Standard_OutOfRange::Raise ("NIS_Triangulated::SetTriangle");
347 switch (myIndexType) {
350 unsigned char * pTri =
351 reinterpret_cast<unsigned char *>(mypTriangles) + (3 * ind);
352 pTri[0] = static_cast<unsigned char>(iNode0);
353 pTri[1] = static_cast<unsigned char>(iNode1);
354 pTri[2] = static_cast<unsigned char>(iNode2);
359 unsigned short * pTri =
360 reinterpret_cast<unsigned short *>(mypTriangles) + (3 * ind);
361 pTri[0] = static_cast<unsigned short>(iNode0);
362 pTri[1] = static_cast<unsigned short>(iNode1);
363 pTri[2] = static_cast<unsigned short>(iNode2);
368 Standard_Integer * pTri = &mypTriangles[3*ind];
376 //=======================================================================
377 //function : SetLineNode
379 //=======================================================================
381 void NIS_Triangulated::SetLineNode (const Standard_Integer ind,
382 const Standard_Integer iNode)
384 if (ind >= myNLineNodes)
385 Standard_OutOfRange::Raise ("NIS_Triangulated::SetTriangle");
386 switch (myIndexType) {
389 unsigned char * pInd =
390 reinterpret_cast<unsigned char *>(mypLines) + ind;
391 pInd[0] = static_cast<unsigned char>(iNode);
396 unsigned short * pInd =
397 reinterpret_cast<unsigned short *>(mypLines) + ind;
398 pInd[0] = static_cast<unsigned short>(iNode);
402 mypLines[ind] = iNode;
406 //=======================================================================
407 //function : SetPolygonNode
409 //=======================================================================
411 void NIS_Triangulated::SetPolygonNode (const Standard_Integer indPoly,
412 const Standard_Integer ind,
413 const Standard_Integer iNode)
415 if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
416 Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
418 Standard_Integer * aPoly = mypPolygons[indPoly];
419 switch (myIndexType) {
422 unsigned char aNNode = * (reinterpret_cast<unsigned char *>(aPoly));
423 if (static_cast<unsigned char>(ind) >= aNNode)
424 Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
426 unsigned char * pInd =
427 reinterpret_cast<unsigned char *>(aPoly) + ind + 1;
428 pInd[0] = static_cast<unsigned char>(iNode);
433 unsigned short aNNode = * (reinterpret_cast<unsigned short *>(aPoly));
434 if (static_cast<unsigned short>(ind) >= aNNode)
435 Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
437 unsigned short * pInd =
438 reinterpret_cast<unsigned short *>(aPoly) + ind + 1;
439 pInd[0] = static_cast<unsigned short>(iNode);
444 Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
445 aPoly[ind + 1] = iNode;
449 //=======================================================================
450 //function : NPolygonNodes
452 //=======================================================================
453 Standard_Integer NIS_Triangulated::NPolygonNodes
454 (const Standard_Integer indPoly)const
456 Standard_Integer aResult(0);
457 if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
458 Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
459 Standard_Integer * aPoly = mypPolygons[indPoly];
460 switch (myIndexType) {
463 unsigned char aNNode = * (reinterpret_cast<unsigned char *>(aPoly));
464 aResult = static_cast<Standard_Integer>(aNNode);
469 unsigned short aNNode = * (reinterpret_cast<unsigned short *>(aPoly));
470 aResult = static_cast<Standard_Integer>(aNNode);
481 //=======================================================================
482 //function : PolygonNode
484 //=======================================================================
486 Standard_Integer NIS_Triangulated::PolygonNode
487 (const Standard_Integer indPoly,
488 const Standard_Integer ind)const
490 Standard_Integer aResult(-1);
491 if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
492 Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
493 const Standard_Integer * aPoly = mypPolygons[indPoly];
494 switch (myIndexType) {
497 const unsigned char * pInd =
498 reinterpret_cast<const unsigned char *>(aPoly);
499 if (static_cast<unsigned char>(ind) >= pInd[0])
500 Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
502 aResult = static_cast<Standard_Integer>(pInd[ind + 1]);
507 const unsigned short * pInd =
508 reinterpret_cast<const unsigned short *>(aPoly);
509 if (static_cast<unsigned short>(ind) >= pInd[0])
510 Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
512 aResult = static_cast<Standard_Integer>(pInd[ind + 1]);
518 Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
519 aResult = aPoly[ind + 1];
525 //=======================================================================
526 //function : SetPolygon
528 //=======================================================================
530 void NIS_Triangulated::SetPolygon (const Standard_Integer ind,
531 const Standard_Integer theSz)
533 if (ind >= static_cast<Standard_Integer>(myNPolygons))
534 Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygon");
535 switch (myIndexType) {
538 unsigned char * anArray = static_cast <unsigned char *>
539 (myAlloc->Allocate (sizeof(unsigned char) * (theSz+1)));
540 mypPolygons[ind] = reinterpret_cast<Standard_Integer *> (anArray);
541 anArray[0] = static_cast<unsigned char>(theSz);
546 unsigned short * anArray = static_cast <unsigned short *>
547 (myAlloc->Allocate (sizeof(unsigned short) * (theSz+1)));
548 mypPolygons[ind] = reinterpret_cast<Standard_Integer *> (anArray);
549 anArray[0] = static_cast<unsigned short>(theSz);
554 Standard_Integer * anArray = static_cast <Standard_Integer *>
555 (myAlloc->Allocate (sizeof(Standard_Integer) * (theSz+1)));
556 mypPolygons[ind] = anArray;
562 //=======================================================================
563 //function : SetDrawPolygons
565 //=======================================================================
567 void NIS_Triangulated::SetDrawPolygons (const Standard_Boolean isDrawPolygons)
569 if (GetDrawer().IsNull())
570 myIsDrawPolygons = isDrawPolygons;
572 if (myIsDrawPolygons != isDrawPolygons) {
573 const Handle(NIS_TriangulatedDrawer) aDrawer =
574 static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
575 aDrawer->Assign (GetDrawer());
576 aDrawer->myIsDrawPolygons = isDrawPolygons;
578 myIsDrawPolygons = isDrawPolygons;
583 //=======================================================================
584 //function : SetPolygonType
585 //purpose : Set the type of polygon rendering
586 //=======================================================================
588 void NIS_Triangulated::SetPolygonType
589 (const NIS_Triangulated::PolygonType theType)
591 if (GetDrawer().IsNull())
592 myPolygonType = static_cast<unsigned int>(theType);
594 if (myPolygonType != static_cast<unsigned int>(theType)) {
595 const Handle(NIS_TriangulatedDrawer) aDrawer =
596 static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
597 aDrawer->Assign (GetDrawer());
598 aDrawer->myPolygonType = theType;
600 myPolygonType = static_cast<unsigned int>(theType);
605 //=======================================================================
606 //function : SetColor
607 //purpose : Set the normal color for presentation.
608 //=======================================================================
610 void NIS_Triangulated::SetColor (const Quantity_Color& theColor)
612 const Handle(NIS_TriangulatedDrawer) aDrawer =
613 static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
614 aDrawer->Assign (GetDrawer());
615 aDrawer->myColor[NIS_Drawer::Draw_Normal] = theColor;
616 aDrawer->myColor[NIS_Drawer::Draw_Top] = theColor;
617 aDrawer->myColor[NIS_Drawer::Draw_Transparent] = theColor;
621 //=======================================================================
622 //function : GetColor
623 //purpose : Get Normal, Transparent or Hilighted color of the presentation.
624 //=======================================================================
626 Quantity_Color NIS_Triangulated::GetColor
627 (const NIS_Drawer::DrawType theDrawType) const
629 Handle(NIS_TriangulatedDrawer) aDrawer =
630 Handle(NIS_TriangulatedDrawer)::DownCast( GetDrawer() );
631 if (aDrawer.IsNull() == Standard_False)
633 return aDrawer->myColor[theDrawType];
635 return Quantity_Color(); // return null color object
638 //=======================================================================
639 //function : SetHilightColor
640 //purpose : Set the color for hilighted presentation.
641 //=======================================================================
643 void NIS_Triangulated::SetHilightColor (const Quantity_Color& theColor)
645 const Handle(NIS_TriangulatedDrawer) aDrawer =
646 static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
647 aDrawer->Assign (GetDrawer());
648 aDrawer->myColor[NIS_Drawer::Draw_Hilighted] = theColor;
652 //=======================================================================
653 //function : SetDynHilightColor
654 //purpose : Set the color for dynamic hilight presentation.
655 //=======================================================================
657 void NIS_Triangulated::SetDynHilightColor(const Quantity_Color& theColor)
659 const Handle(NIS_TriangulatedDrawer) aDrawer =
660 static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
661 aDrawer->Assign (GetDrawer());
662 aDrawer->myColor[NIS_Drawer::Draw_DynHilighted] = theColor;
666 //=======================================================================
667 //function : SetLineWidth
668 //purpose : Set the width of line presentations in pixels.
669 //=======================================================================
671 void NIS_Triangulated::SetLineWidth (const Standard_Real theWidth)
673 const Handle(NIS_TriangulatedDrawer) aDrawer =
674 static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
675 aDrawer->Assign (GetDrawer());
676 aDrawer->myLineWidth = (Standard_ShortReal) theWidth;
680 //=======================================================================
683 //=======================================================================
685 void NIS_Triangulated::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
686 Handle_NIS_InteractiveObject& theDest) const
688 Handle(NIS_Triangulated) aNewObj;
689 if (theDest.IsNull()) {
690 aNewObj = new (theAlloc) NIS_Triangulated(myNNodes, myNodeCoord == 2,
692 aNewObj->myIsCloned = Standard_True;
695 aNewObj = reinterpret_cast<NIS_Triangulated*> (theDest.operator->());
696 aNewObj->myAlloc = theAlloc.operator->();
697 aNewObj->myNNodes = 0;
698 aNewObj->allocateNodes(myNNodes);
700 NIS_InteractiveObject::Clone(theAlloc, theDest);
704 memcpy(aNewObj->mypNodes, mypNodes,
705 myNNodes * myNodeCoord * sizeof(Standard_ShortReal));
707 aNewObj->myNTriangles = myNTriangles;
709 const Standard_Size nBytes = NBytesInd(3 * myNTriangles, myIndexType);
710 aNewObj->mypTriangles = static_cast<Standard_Integer *>
711 (theAlloc->Allocate(nBytes));
712 memcpy(aNewObj->mypTriangles, mypTriangles, nBytes);
714 // copy lines/segments
715 aNewObj->myNLineNodes = myNLineNodes;
717 const Standard_Size nBytes = NBytesInd(myNLineNodes, myIndexType);
718 aNewObj->mypLines = static_cast<Standard_Integer *>
719 (theAlloc->Allocate(nBytes));
720 memcpy(aNewObj->mypLines, mypLines, nBytes);
723 aNewObj->myNPolygons = myNPolygons;
725 const Standard_Size nBytes = sizeof(Standard_Integer *)*myNPolygons;
726 aNewObj->mypPolygons = static_cast<Standard_Integer **>
727 (theAlloc->Allocate(nBytes));
728 for (unsigned int i = 0; i < myNPolygons; i++) {
729 const Standard_Integer nNodes = NPolygonNodes(i);
730 const Standard_Size nBytes = NBytesInd(nNodes+1, myIndexType);
731 aNewObj->mypPolygons[i] = static_cast <Standard_Integer *>
732 (theAlloc->Allocate (nBytes));
733 memcpy(aNewObj->mypPolygons[i], mypPolygons[i], nBytes);
737 aNewObj->myType = myType;
738 aNewObj->myIsDrawPolygons = myIsDrawPolygons;
739 aNewObj->myIndexType = myIndexType;
740 aNewObj->myPolygonType = myPolygonType;
743 //=======================================================================
746 //=======================================================================
748 void NIS_Triangulated::Delete () const
750 if (myIsCloned == Standard_False)
751 Standard_Transient::Delete();
753 // Call the destructor and then release the memory occupied by the instance.
754 // This is required when the NIS_Triangulated instance is allocated in
755 // the same allocator as its internal arrays.
756 NIS_Triangulated* pThis = const_cast<NIS_Triangulated*>(this);
757 pThis->~NIS_Triangulated();
758 myAlloc->Free(pThis);
762 //=======================================================================
763 //function : Intersect
765 //=======================================================================
767 Standard_Boolean NIS_Triangulated::Intersect
768 (const Bnd_B3f& theBox,
769 const gp_Trsf& theTrf,
770 const Standard_Boolean isFullIn) const
772 Standard_Boolean aResult (isFullIn);
774 if ((myType & Type_Triangulation) && myIsDrawPolygons == Standard_False) {
775 unsigned int iNode = 0;
776 for (; iNode < myNNodes * myNodeCoord; iNode += myNodeCoord)
778 gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
779 static_cast<Standard_Real>(mypNodes[iNode+1]), 0.);
781 aPnt.SetZ (static_cast<Standard_Real>(mypNodes[iNode+2]));
782 theTrf.Transforms (aPnt);
783 if (theBox.IsOut (aPnt)) {
785 aResult = Standard_False;
789 if (isFullIn == Standard_False) {
790 aResult = Standard_True;
796 if (aResult == isFullIn) {
797 if (myType & Type_Segments) {
798 for (Standard_Integer i = 0; i < myNLineNodes; i+=2) {
799 const gp_Pnt aPnt[2] = {
800 nodeAtInd(mypLines, i+0).Transformed(theTrf),
801 nodeAtInd(mypLines, i+1).Transformed(theTrf)
804 if (seg_box_included (theBox, aPnt) == 0) {
805 aResult = Standard_False;
809 if (seg_box_intersect (theBox, aPnt)) {
810 aResult = Standard_True;
815 } else if (myType & Type_Line) {
816 for (Standard_Integer i = 1; i < myNLineNodes; i++) {
817 const gp_Pnt aPnt[2] = {
818 nodeAtInd(mypLines, i-1).Transformed(theTrf),
819 nodeAtInd(mypLines, i+0).Transformed(theTrf)
822 if (seg_box_included (theBox, aPnt) == 0) {
823 aResult = Standard_False;
827 if (seg_box_intersect (theBox, aPnt)) {
828 aResult = Standard_True;
833 if (aResult == isFullIn && (myType & Type_Loop)) {
834 const gp_Pnt aPntLast[2] = {
835 nodeAtInd(mypLines, myNLineNodes-1).Transformed(theTrf),
836 nodeAtInd(mypLines, 0).Transformed(theTrf)
839 if (seg_box_included (theBox, aPntLast) == 0)
840 aResult = Standard_False;
842 if (seg_box_intersect (theBox, aPntLast))
843 aResult = Standard_True;
846 } else if ((myType & Type_Polygons) && myIsDrawPolygons) {
847 for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
848 const Standard_Integer * aPoly = mypPolygons[iPoly];
849 const Standard_Integer nNodes = NPolygonNodes(iPoly);
850 for (Standard_Integer i = 1; i < nNodes; i++) {
851 // index is incremented by 1 for the head number in the array
852 const gp_Pnt aPnt[2] = {
853 nodeAtInd(aPoly, i+0).Transformed(theTrf),
854 nodeAtInd(aPoly, i+1).Transformed(theTrf)
857 if (seg_box_included (theBox, aPnt) == 0) {
858 aResult = Standard_False;
862 if (seg_box_intersect (theBox, aPnt)) {
863 aResult = Standard_True;
868 if (aResult == isFullIn) {
869 const gp_Pnt aPntLast[2] = {
870 nodeAtInd(aPoly, nNodes).Transformed(theTrf),
871 nodeAtInd(aPoly, 1).Transformed(theTrf)
874 if (seg_box_included (theBox, aPntLast) == 0)
875 aResult = Standard_False;
877 if (seg_box_intersect (theBox, aPntLast))
878 aResult = Standard_True;
887 //=======================================================================
888 //function : Intersect
890 //=======================================================================
892 Standard_Real NIS_Triangulated::Intersect (const gp_Ax1& theAxis,
893 const Standard_Real theOver) const
895 Standard_Real aResult (RealLast());
896 Standard_Real start[3], dir[3];
897 theAxis.Location().Coord(start[0], start[1], start[2]);
898 theAxis.Direction().Coord(dir[0], dir[1], dir[2]);
901 if ((myType & Type_Triangulation) && (myIsDrawPolygons == Standard_False))
902 for (Standard_Integer i = 0; i < myNTriangles; i++) {
903 Standard_Boolean isIntersect(Standard_False);
904 if (myIndexType == 0) {
905 const unsigned char * pTri =
906 reinterpret_cast<unsigned char *>(mypTriangles) + (3 * i);
908 isIntersect = tri_line_intersect (start, dir,
909 &mypNodes[myNodeCoord * pTri[0]],
910 &mypNodes[myNodeCoord * pTri[1]],
911 &mypNodes[myNodeCoord * pTri[2]],
914 isIntersect = tri2d_line_intersect (start, dir,
915 &mypNodes[myNodeCoord * pTri[0]],
916 &mypNodes[myNodeCoord * pTri[1]],
917 &mypNodes[myNodeCoord * pTri[2]],
919 } else if (myIndexType == 1) {
920 const unsigned short * pTri =
921 reinterpret_cast<unsigned short *>(mypTriangles) + (3 * i);
923 isIntersect = tri_line_intersect (start, dir,
924 &mypNodes[myNodeCoord * pTri[0]],
925 &mypNodes[myNodeCoord * pTri[1]],
926 &mypNodes[myNodeCoord * pTri[2]],
929 isIntersect = tri2d_line_intersect (start, dir,
930 &mypNodes[myNodeCoord * pTri[0]],
931 &mypNodes[myNodeCoord * pTri[1]],
932 &mypNodes[myNodeCoord * pTri[2]],
935 const Standard_Integer * pTri = &mypTriangles[3 * i];
937 isIntersect = tri_line_intersect (start, dir,
938 &mypNodes[myNodeCoord * pTri[0]],
939 &mypNodes[myNodeCoord * pTri[1]],
940 &mypNodes[myNodeCoord * pTri[2]],
943 isIntersect = tri2d_line_intersect (start, dir,
944 &mypNodes[myNodeCoord * pTri[0]],
945 &mypNodes[myNodeCoord * pTri[1]],
946 &mypNodes[myNodeCoord * pTri[2]],
949 if (isIntersect && anInter < aResult)
953 const Standard_Real anOver2 = theOver*theOver;
954 if (myType & Type_Segments) {
955 Standard_Integer i = 0;
957 for (; i < myNLineNodes; i+=2) {
958 if (seg_line_intersect (theAxis.Location().XYZ(),
959 theAxis.Direction().XYZ(), anOver2,
960 nodeArrAtInd(mypLines, i+0),
961 nodeArrAtInd(mypLines, i+1),
963 if (anInter < aResult)
967 for (; i < myNLineNodes; i+=2) {
968 if (seg2d_line_intersect (theAxis.Location().XYZ(),
969 theAxis.Direction().XYZ(), anOver2,
970 nodeArrAtInd(mypLines, i+0),
971 nodeArrAtInd(mypLines, i+1),
973 if (anInter < aResult)
976 } else if (myType & Type_Line) {
977 Standard_Integer i = 1;
978 if (myNodeCoord > 2) {
979 for (; i < myNLineNodes; i++) {
980 if (seg_line_intersect (theAxis.Location().XYZ(),
981 theAxis.Direction().XYZ(), anOver2,
982 nodeArrAtInd(mypLines, i-1),
983 nodeArrAtInd(mypLines, i-0),
985 if (anInter < aResult)
988 if (myType & Type_Loop)
989 if (seg_line_intersect (theAxis.Location().XYZ(),
990 theAxis.Direction().XYZ(), anOver2,
991 nodeArrAtInd(mypLines, myNLineNodes-1),
992 nodeArrAtInd(mypLines, 0),
994 if (anInter < aResult)
997 for (; i < myNLineNodes; i++) {
998 if (seg2d_line_intersect (theAxis.Location().XYZ(),
999 theAxis.Direction().XYZ(), anOver2,
1000 nodeArrAtInd(mypLines, i-1),
1001 nodeArrAtInd(mypLines, i-0),
1003 if (anInter < aResult)
1006 if (myType & Type_Loop)
1007 if (seg2d_line_intersect (theAxis.Location().XYZ(),
1008 theAxis.Direction().XYZ(), anOver2,
1009 nodeArrAtInd(mypLines, myNLineNodes-1),
1010 nodeArrAtInd(mypLines, 0),
1012 if (anInter < aResult)
1017 if ((myType & Type_Polygons) && myIsDrawPolygons) {
1018 for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
1019 const Standard_Integer * aPoly = mypPolygons[iPoly];
1020 const Standard_Integer nNodes = NPolygonNodes(iPoly);
1021 Standard_Integer i = 1;
1022 if (myNodeCoord > 2) {
1023 for (; i < nNodes; i++) {
1024 // Node index is incremented for the head of polygon indice array
1025 if (seg_line_intersect (theAxis.Location().XYZ(),
1026 theAxis.Direction().XYZ(), anOver2,
1027 nodeArrAtInd(aPoly, i+0),
1028 nodeArrAtInd(aPoly, i+1),
1030 if (anInter < aResult)
1033 if (seg_line_intersect (theAxis.Location().XYZ(),
1034 theAxis.Direction().XYZ(), anOver2,
1035 nodeArrAtInd(aPoly, nNodes),
1036 nodeArrAtInd(aPoly, 1),
1038 if (anInter < aResult)
1041 for (; i < nNodes; i++) {
1042 // Node index is incremented for the head of polygon indice array
1043 if (seg2d_line_intersect (theAxis.Location().XYZ(),
1044 theAxis.Direction().XYZ(), anOver2,
1045 nodeArrAtInd(aPoly, i+0),
1046 nodeArrAtInd(aPoly, i+1),
1048 if (anInter < aResult)
1051 if (seg2d_line_intersect (theAxis.Location().XYZ(),
1052 theAxis.Direction().XYZ(), anOver2,
1053 nodeArrAtInd(aPoly, nNodes),
1054 nodeArrAtInd(aPoly, 1),
1056 if (anInter < aResult)
1064 //=======================================================================
1065 //function : Intersect
1067 //=======================================================================
1068 Standard_Boolean NIS_Triangulated::Intersect
1069 (const NCollection_List<gp_XY> &thePolygon,
1070 const gp_Trsf &theTrf,
1071 const Standard_Boolean isFullIn) const
1073 Standard_Boolean aResult (isFullIn);
1075 if ((myType & Type_Triangulation) && myIsDrawPolygons == Standard_False) {
1076 unsigned int iNode = 0;
1077 for (; iNode < myNNodes * myNodeCoord; iNode += myNodeCoord)
1079 gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
1080 static_cast<Standard_Real>(mypNodes[iNode+1]), 0.);
1081 if (myNodeCoord > 2)
1082 aPnt.SetZ (static_cast<Standard_Real>(mypNodes[iNode+2]));
1083 theTrf.Transforms (aPnt);
1085 gp_XY aP2d(aPnt.X(), aPnt.Y());
1087 if (!NIS_Triangulated::IsIn(thePolygon, aP2d)) {
1089 aResult = Standard_False;
1093 if (isFullIn == Standard_False) {
1094 aResult = Standard_True;
1100 if (aResult == isFullIn) {
1101 if (myType & Type_Segments) {
1102 for (Standard_Integer i = 0; i < myNLineNodes; i+=2) {
1103 const gp_Pnt aPnt[2] = {
1104 nodeAtInd(mypLines, i+0).Transformed(theTrf),
1105 nodeAtInd(mypLines, i+1).Transformed(theTrf)
1107 const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
1108 gp_XY(aPnt[1].X(), aPnt[1].Y()) };
1111 if (seg_polygon_included (thePolygon, aP2d) == 0) {
1112 aResult = Standard_False;
1116 if (seg_polygon_intersect (thePolygon, aP2d)) {
1117 aResult = Standard_True;
1122 } else if (myType & Type_Line) {
1123 for (Standard_Integer i = 1; i < myNLineNodes; i++) {
1124 const gp_Pnt aPnt[2] = {
1125 nodeAtInd(mypLines, i-1).Transformed(theTrf),
1126 nodeAtInd(mypLines, i+0).Transformed(theTrf)
1128 const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
1129 gp_XY(aPnt[1].X(), aPnt[1].Y()) };
1131 if (seg_polygon_included (thePolygon, aP2d) == 0) {
1132 aResult = Standard_False;
1136 if (seg_polygon_intersect (thePolygon, aP2d)) {
1137 aResult = Standard_True;
1142 if (aResult == isFullIn && (myType & Type_Loop)) {
1143 const gp_Pnt aPntLast[2] = {
1144 nodeAtInd(mypLines, myNLineNodes-1).Transformed(theTrf),
1145 nodeAtInd(mypLines, 0).Transformed(theTrf)
1147 const gp_XY aP2dLast[2] = { gp_XY(aPntLast[0].X(), aPntLast[0].Y()),
1148 gp_XY(aPntLast[1].X(), aPntLast[1].Y()) };
1151 if (seg_polygon_included (thePolygon, aP2dLast) == 0)
1152 aResult = Standard_False;
1154 if (seg_polygon_intersect (thePolygon, aP2dLast))
1155 aResult = Standard_True;
1158 } else if ((myType & Type_Polygons) && myIsDrawPolygons) {
1159 for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
1160 const Standard_Integer * aPoly = mypPolygons[iPoly];
1161 const Standard_Integer nNodes = NPolygonNodes(iPoly);
1162 for (Standard_Integer i = 1; i < nNodes; i++) {
1163 const gp_Pnt aPnt[2] = {
1164 nodeAtInd(aPoly, i+0).Transformed(theTrf),
1165 nodeAtInd(aPoly, i+1).Transformed(theTrf)
1167 const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
1168 gp_XY(aPnt[1].X(), aPnt[1].Y()) };
1170 if (seg_polygon_included (thePolygon, aP2d) == 0) {
1171 aResult = Standard_False;
1175 if (seg_polygon_intersect (thePolygon, aP2d)) {
1176 aResult = Standard_True;
1181 if (aResult == isFullIn) {
1182 const gp_Pnt aPntLast[2] = {
1183 nodeAtInd(aPoly, nNodes).Transformed(theTrf),
1184 nodeAtInd(aPoly, 1).Transformed(theTrf)
1186 const gp_XY aP2dLast[2] = { gp_XY(aPntLast[0].X(), aPntLast[0].Y()),
1187 gp_XY(aPntLast[1].X(), aPntLast[1].Y()) };
1189 if (seg_polygon_included (thePolygon, aP2dLast) == 0)
1190 aResult = Standard_False;
1192 if (seg_polygon_intersect (thePolygon, aP2dLast))
1193 aResult = Standard_True;
1202 /* =====================================================================
1203 Function : determinant
1204 Purpose : Calculate the minor of the given matrix, defined by the columns
1205 specified by values c1, c2, c3
1207 Returns : determinant value
1209 ======================================================================== */
1211 static double determinant (const double a[3][4],
1216 return a[0][c1]*a[1][c2]*a[2][c3] +
1217 a[0][c2]*a[1][c3]*a[2][c1] +
1218 a[0][c3]*a[1][c1]*a[2][c2] -
1219 a[0][c3]*a[1][c2]*a[2][c1] -
1220 a[0][c2]*a[1][c1]*a[2][c3] -
1221 a[0][c1]*a[1][c3]*a[2][c2];
1224 /* =====================================================================
1225 Function : tri_line_intersect
1226 Purpose : Intersect a triangle with a line
1227 Parameters : start - coordinates of the origin of the line
1228 dir - coordinates of the direction of the line (normalized)
1229 V0 - first vertex of the triangle
1230 V1 - second vertex of the triangle
1231 V2 - third vertex of the triangle
1232 tInter - output value, contains the parameter of the intersection
1233 point on the line (if found). May be NULL pointer
1234 Returns : int = 1 if intersection found, 0 otherwise
1235 ======================================================================== */
1237 int NIS_Triangulated::tri_line_intersect (const double start[3],
1238 const double dir[3],
1245 const double conf = 1E-15;
1247 const double array[][4] = {
1249 double(V1[0] - V0[0]), double(V2[0] - V0[0]), start[0] - double(V0[0]) },
1251 double(V1[1] - V0[1]), double(V2[1] - V0[1]), start[1] - double(V0[1]) },
1253 double(V1[2] - V0[2]), double(V2[2] - V0[2]), start[2] - double(V0[2]) }
1256 const double d = determinant( array, 0, 1, 2 );
1257 const double dt = determinant( array, 3, 1, 2 );
1260 const double da = determinant( array, 0, 3, 2 );
1262 const double db = determinant( array, 0, 1, 3 );
1263 res = (db > -conf && da+db <= d+conf);
1265 } else if (d < -conf) {
1266 const double da = determinant( array, 0, 3, 2 );
1268 const double db = determinant( array, 0, 1, 3 );
1269 res = (db < conf && da+db >= d-conf);
1278 /* =====================================================================
1279 Function : tri2d_line_intersect
1280 Purpose : Intersect a 2D triangle with a 3D line. Z coordinate of triangle
1282 Parameters : start - coordinates of the origin of the line
1283 dir - coordinates of the direction of the line (normalized)
1284 V0 - first vertex of the triangle
1285 V1 - second vertex of the triangle
1286 V2 - third vertex of the triangle
1287 tInter - output value, contains the parameter of the intersection
1288 point on the line (if found). May be NULL pointer
1289 Returns : int = 1 if intersection found, 0 otherwise
1290 ======================================================================== */
1292 int NIS_Triangulated::tri2d_line_intersect (const double start[3],
1293 const double dir[3],
1300 const double conf = 1E-15;
1302 // Parallel case is excluded
1303 if (dir[2] * dir[2] > conf)
1305 // Find the 2d intersection of (start, dir) with the plane Z = 0.
1306 const double p2d[2] = {
1307 start[0] - dir[0] * start[2] / dir[2],
1308 start[1] - dir[1] * start[2] / dir[2]
1311 // Classify the 2d intersection using barycentric coordinates
1312 // (http://www.blackpawn.com/texts/pointinpoly/)
1313 const double v[][2] = {
1314 { static_cast<double>(V1[0]-V0[0]), static_cast<double>(V1[1]-V0[1]) },
1315 { static_cast<double>(V2[0]-V0[0]), static_cast<double>(V2[1]-V0[1]) },
1316 { static_cast<double>(p2d[0]-V0[0]), static_cast<double>(p2d[1]-V0[1]) }
1318 const double dot00 = v[0][0]*v[0][0] + v[0][1]*v[0][1];
1319 const double dot01 = v[0][0]*v[1][0] + v[0][1]*v[1][1];
1320 const double dot02 = v[0][0]*v[2][0] + v[0][1]*v[2][1];
1321 const double dot11 = v[1][0]*v[1][0] + v[1][1]*v[1][1];
1322 const double dot12 = v[1][0]*v[2][0] + v[1][1]*v[2][1];
1323 const double denom = (dot00 * dot11 - dot01 * dot01);
1324 if (denom * denom < conf) {
1325 // Point on the 1st side of the triangle
1326 res = (dot01 > -conf && dot00 < dot11 + conf);
1328 // Barycentric coordinates of the point
1329 const double u = (dot11 * dot02 - dot01 * dot12) / denom;
1330 const double v = (dot00 * dot12 - dot01 * dot02) / denom;
1331 res = (u > -conf) && (v > -conf) && (u + v < 1. + conf);
1335 *tInter = -start[2] / dir[2];
1340 /* =====================================================================
1341 Function : seg_line_intersect
1342 Purpose : Intersect a segment with a line
1343 Parameters : start - coordinates of the origin of the line
1344 dir - coordinates of the direction of the line (normalized)
1345 over2 - maximal square distance between the line and the segment
1346 for intersection state
1347 V0 - first vertex of the segment
1348 V1 - second vertex of the segment
1349 tInter - output value, contains the parameter of the intersection
1350 point on the line (if found). May be NULL pointer
1351 Returns : int = 1 if intersection found, 0 otherwise
1352 ======================================================================== */
1354 int NIS_Triangulated::seg_line_intersect (const gp_XYZ& aStart,
1362 const gp_XYZ aDirSeg (V1[0]-V0[0], V1[1]-V0[1], V1[2]-V0[2]);
1363 gp_XYZ aDirN = aDirSeg ^ aDir;
1364 Standard_Real aMod2 = aDirN.SquareModulus();
1365 if (aMod2 < Precision::Confusion() * 0.001) {
1366 const gp_XYZ aDelta0 (V0[0]-aStart.X(), V0[1]-aStart.Y(), V0[2]-aStart.Z());
1367 if ((aDelta0 ^ aDir).SquareModulus() < over2) {
1369 const gp_XYZ aDelta1 (V1[0]-aStart.X(),V1[1]-aStart.Y(),V1[2]-aStart.Z());
1371 * tInter = Min (aDelta0 * aDir, aDelta1 * aDir);
1374 // distance between two unlimited lines
1375 const gp_XYZ aPnt0 (V0[0], V0[1], V0[2]);
1376 const Standard_Real aDistL = (aDirN * aPnt0) - aDirN * aStart;
1377 if (aDistL*aDistL < over2 * aMod2) {
1378 const gp_XYZ aPnt1 (V1[0], V1[1], V1[2]);
1379 Standard_Real aDist[3] = {
1380 ((aPnt0 - aStart) ^ aDir).Modulus(),
1381 ((aPnt1 - aStart) ^ aDir).Modulus(),
1384 // Find the intermediate point by interpolation using the distances from
1386 const gp_XYZ aPntI =
1387 (aPnt0 * aDist[1] + aPnt1 * aDist[0]) / (aDist[0] + aDist[1]);
1388 aDist[2] = ((aPntI - aStart) ^ aDir).Modulus();
1389 if (aDist[2] < aDist[0] && aDist[2] < aDist[1]) {
1390 if (aDist[2]*aDist[2] < over2) {
1393 * tInter = (aPntI - aStart) * aDir;
1395 } else if (aDist[0] < aDist[1]) {
1396 if (aDist[0] * aDist[0] < over2) {
1399 * tInter = (aPnt0 - aStart) * aDir;
1402 if (aDist[1] * aDist[1] < over2) {
1405 * tInter = (aPnt1 - aStart) * aDir;
1413 /* =====================================================================
1414 Function : seg2d_line_intersect
1415 Purpose : Intersect a 2D segment with a 3D line
1416 Parameters : start - coordinates of the origin of the line
1417 dir - coordinates of the direction of the line (normalized)
1418 over2 - maximal square distance between the line and the segment
1419 for intersection state
1420 V0 - first vertex of the segment
1421 V1 - second vertex of the segment
1422 tInter - output value, contains the parameter of the intersection
1423 point on the line (if found). May be NULL pointer
1424 Returns : int = 1 if intersection found, 0 otherwise
1425 ======================================================================== */
1427 int NIS_Triangulated::seg2d_line_intersect (const gp_XYZ& aStart,
1435 const gp_XYZ aDirSeg (V1[0]-V0[0], V1[1]-V0[1], 0.);
1436 gp_XYZ aDirN = aDirSeg ^ aDir;
1437 Standard_Real aMod2 = aDirN.SquareModulus();
1438 if (aMod2 < Precision::Confusion() * 0.001) {
1439 const gp_XYZ aDelta0 (V0[0]-aStart.X(), V0[1]-aStart.Y(), -aStart.Z());
1440 if ((aDelta0 ^ aDir).SquareModulus() < over2) {
1442 const gp_XYZ aDelta1 (V1[0]-aStart.X(), V1[1]-aStart.Y(), -aStart.Z());
1444 * tInter = Min (aDelta0 * aDir, aDelta1 * aDir);
1447 // distance between two unlimited lines
1448 const gp_XYZ aPnt0 (V0[0], V0[1], 0.);
1449 const Standard_Real aDistL = (aDirN * aPnt0) - aDirN * aStart;
1450 if (aDistL*aDistL < over2 * aMod2) {
1451 const gp_XYZ aPnt1 (V1[0], V1[1], 0.);
1452 Standard_Real aDist[3] = {
1453 ((aPnt0 - aStart) ^ aDir).Modulus(),
1454 ((aPnt1 - aStart) ^ aDir).Modulus(),
1457 // Find the intermediate point by interpolation using the distances from
1459 const gp_XYZ aPntI =
1460 (aPnt0 * aDist[1] + aPnt1 * aDist[0]) / (aDist[0] + aDist[1]);
1461 aDist[2] = ((aPntI - aStart) ^ aDir).Modulus();
1462 if (aDist[2] < aDist[0] && aDist[2] < aDist[1]) {
1463 if (aDist[2]*aDist[2] < over2) {
1466 * tInter = (aPntI - aStart) * aDir;
1468 } else if (aDist[0] < aDist[1]) {
1469 if (aDist[0] * aDist[0] < over2) {
1472 * tInter = (aPnt0 - aStart) * aDir;
1475 if (aDist[1] * aDist[1] < over2) {
1478 * tInter = (aPnt1 - aStart) * aDir;
1486 //=======================================================================
1487 //function : seg_box_intersect
1489 //=======================================================================
1491 int NIS_Triangulated::seg_box_intersect (const Bnd_B3f& theBox,
1492 const gp_Pnt thePnt[2])
1495 if ((thePnt[1].XYZ() - thePnt[0].XYZ()).SquareModulus()
1496 < Precision::Confusion() * 0.0001)
1499 const gp_Dir aDir (thePnt[1].XYZ() - thePnt[0].XYZ());
1500 if (theBox.IsOut (gp_Ax1(thePnt[0], aDir), Standard_True) ||
1501 theBox.IsOut (gp_Ax1(thePnt[1],-aDir), Standard_True))
1507 //=======================================================================
1508 //function : seg_box_included
1510 //=======================================================================
1512 int NIS_Triangulated::seg_box_included (const Bnd_B3f& theBox,
1513 const gp_Pnt thePnt[2])
1516 if ((thePnt[1].XYZ() - thePnt[0].XYZ()).SquareModulus()
1517 > Precision::Confusion() * 0.0001)
1519 aResult = (theBox.IsOut(thePnt[0].XYZ()) == Standard_False &&
1520 theBox.IsOut(thePnt[1].XYZ()) == Standard_False);
1525 //=======================================================================
1526 //function : seg_polygon_intersect
1528 //=======================================================================
1530 int NIS_Triangulated::seg_polygon_intersect
1531 (const NCollection_List<gp_XY> &thePolygon,
1532 const gp_XY thePnt[2])
1534 Standard_Integer aResult = 0;
1536 if (thePolygon.IsEmpty())
1539 gp_XY aDir(thePnt[1] - thePnt[0]);
1540 Standard_Real aDist = aDir.SquareModulus();
1542 if (aDist > aTolConf) {
1543 aDist = Sqrt(aDist);
1544 aDir.Divide(aDist); // Normalize direction.
1546 // Intersect the line passed through thePnt[0] and thePnt[1] with thePolygon
1547 // Line is presented in form Ax + By + C = 0
1548 Standard_Real aA = aDir.Y();
1549 Standard_Real aB = -aDir.X();
1550 Standard_Real aC = -(aA*thePnt[0].X() + aB*thePnt[0].Y());
1552 Standard_Real aSignedD[2];
1553 Standard_Real aDelta = 0.01;
1555 aSegment[0] = thePolygon.Last();
1556 aSignedD[0] = aA*aSegment[0].X() + aB*aSegment[0].Y() + aC;
1558 NCollection_List<gp_XY>::Iterator anIter(thePolygon);
1560 for (; anIter.More(); anIter.Next()) {
1561 aSegment[1] = anIter.Value();
1562 aSignedD[1] = aA*aSegment[1].X() + aB*aSegment[1].Y() + aC;
1564 // Check if there is an intersection.
1565 if (Abs(aSignedD[0]) <= aTolConf || Abs(aSignedD[1]) <= aTolConf) {
1566 Standard_Integer anIndexVtx =
1567 (Abs(aSignedD[0]) > aTolConf) ? 1 :
1568 (Abs(aSignedD[1]) > aTolConf) ? 0 : -1;
1569 if (anIndexVtx != -1) {
1570 // Check if the point aSegment[1] is inside the segment.
1571 gp_XY aDP(aSegment[anIndexVtx] - thePnt[0]);
1572 Standard_Real aParam = aDP.Dot(aDir);
1574 if (aParam >= -aTolConf && aParam <= aDist + aTolConf) {
1575 // Classify a point on the line that is close to aSegment[1] with
1576 // respect to the polygon.
1579 if (aParam - aDelta >= 0.) {
1580 aPShift = thePnt[0] + aDir.Multiplied(aParam - aDelta);
1581 if (!IsIn(thePolygon, aPShift))
1585 // Try to shift on another direction.
1587 if (aParam + aDelta <= aDist) {
1588 aPShift = thePnt[0] + aDir.Multiplied(aParam + aDelta);
1589 if (!IsIn(thePolygon, aPShift))
1595 } else if (aSignedD[0]*aSignedD[1] < 0.) {
1596 // Compute intersection of the segment with the line.
1597 gp_XY aDSeg(aSegment[1] - aSegment[0]);
1598 Standard_Real aSegLen = aDSeg.Modulus();
1599 Standard_Real aParamOnSeg = aSegLen/(1 + Abs(aSignedD[1]/aSignedD[0]));
1601 (aSegment[0] + aDSeg.Multiplied(aParamOnSeg/aSegLen));
1603 // Check if aPOnLine inside the segment thePnt[1] - thePnt[0]
1604 gp_XY aDP(aPOnLine - thePnt[0]);
1605 Standard_Real aParam = aDP.Dot(aDir);
1607 if (aParam >= -aTolConf && aParam <= aDist + aTolConf) {
1610 if (aParam - aDelta >= 0.) {
1611 aPShift = thePnt[0] + aDir.Multiplied(aParam - aDelta);
1613 if (!IsIn(thePolygon, aPShift))
1617 // Try to shift on another direction.
1619 if (aParam + aDelta <= aDist) {
1620 aPShift = thePnt[0] + aDir.Multiplied(aParam + aDelta);
1622 if (!IsIn(thePolygon, aPShift))
1632 aSegment[0] = aSegment[1];
1633 aSignedD[0] = aSignedD[1];
1640 //=======================================================================
1641 //function : seg_polygon_included
1643 //=======================================================================
1645 int NIS_Triangulated::seg_polygon_included
1646 (const NCollection_List<gp_XY> &thePolygon,
1647 const gp_XY thePnt[2])
1650 int anIntersect = seg_polygon_intersect(thePolygon, thePnt);
1652 if (anIntersect == 0) {
1653 if (IsIn(thePolygon, thePnt[0]) && IsIn(thePolygon, thePnt[1]))
1660 //=======================================================================
1663 //=======================================================================
1665 Standard_Boolean NIS_Triangulated::IsIn
1666 (const NCollection_List<gp_XY> &thePolygon,
1667 const gp_XY &thePoint)
1669 if (thePolygon.IsEmpty())
1670 return Standard_False;
1672 Standard_Integer aCounter = 0; // intersections counter
1675 aSegment[0] = thePolygon.Last();
1677 NCollection_List<gp_XY>::Iterator anIter(thePolygon);
1679 for (; anIter.More(); anIter.Next()) {
1680 aSegment[1] = anIter.Value();
1682 // Compute projection of the point onto the segment.
1683 Standard_Real aParam = 0.;
1684 const gp_XY aDelta = aSegment[1] - aSegment[0];
1685 const gp_XY aDPP0 = thePoint - aSegment[0];
1686 const Standard_Real aLen2 = aDelta.SquareModulus();
1688 if (IsPositive(aLen2)) {
1689 aParam = (aDelta*aDPP0)/aLen2;
1693 else if (aParam > 1.)
1696 // Check if the point lies on the segment
1697 gp_XY aPOnSeg = aSegment[0]*(1. - aParam) + aSegment[1]*aParam;
1698 Standard_Real aSqrDist = (thePoint - aPOnSeg).SquareModulus();
1700 if (aSqrDist < aTolConf) {
1701 // The point is on the contour.
1702 return Standard_True;
1705 // Compute intersection.
1706 const Standard_Real aProd(aDPP0 ^ aDelta);
1708 if (IsPositive(thePoint.X() - aSegment[0].X())) {
1709 if (!IsPositive(thePoint.X() - aSegment[1].X())) {
1714 if (IsPositive(thePoint.X() - aSegment[1].X())) {
1720 aSegment[0] = aSegment[1];
1723 return (aCounter & 0x1);
1726 //=======================================================================
1727 //function : allocateNodes
1729 //=======================================================================
1731 void NIS_Triangulated::allocateNodes (const Standard_Integer nNodes)
1735 myAlloc->Free(mypNodes);
1737 mypNodes = static_cast<Standard_ShortReal*>
1738 (myAlloc->Allocate(sizeof(Standard_ShortReal) * myNodeCoord * nNodes));
1741 else if (nNodes < 65536)
1748 //=======================================================================
1749 //function : NodeAtInd
1750 //purpose : Get the node pointed by the i-th index in the array.
1751 //=======================================================================
1753 gp_Pnt NIS_Triangulated::nodeAtInd (const Standard_Integer * theArray,
1754 const Standard_Integer theInd) const
1756 if (myIndexType == 0) {
1757 const unsigned char * pInd =
1758 reinterpret_cast<const unsigned char *>(theArray);
1759 return gp_Pnt (mypNodes[myNodeCoord * pInd[theInd] + 0],
1760 mypNodes[myNodeCoord * pInd[theInd] + 1],
1761 myNodeCoord < 3 ? 0. :
1762 mypNodes[myNodeCoord * pInd[theInd] + 2]);
1764 if (myIndexType == 1) {
1765 const unsigned short * pInd =
1766 reinterpret_cast<const unsigned short *>(theArray);
1767 return gp_Pnt (mypNodes[myNodeCoord * pInd[theInd] + 0],
1768 mypNodes[myNodeCoord * pInd[theInd] + 1],
1769 myNodeCoord < 3 ? 0. :
1770 mypNodes[myNodeCoord * pInd[theInd] + 2]);
1772 return gp_Pnt (mypNodes[myNodeCoord * theArray[theInd] + 0],
1773 mypNodes[myNodeCoord * theArray[theInd] + 1],
1774 myNodeCoord < 3 ? 0. :
1775 mypNodes[myNodeCoord * theArray[theInd] + 2]);
1778 //=======================================================================
1779 //function : nodeArrAtInd
1780 //purpose : Get the node pointed by the i-th index in the array.
1781 //=======================================================================
1783 float* NIS_Triangulated::nodeArrAtInd (const Standard_Integer * theArray,
1784 const Standard_Integer theInd) const
1786 float* pResult = 0L;
1787 if (myIndexType == 0) {
1788 const unsigned char * pInd =
1789 reinterpret_cast<const unsigned char *>(theArray);
1790 pResult = &mypNodes[myNodeCoord * pInd[theInd]];
1792 else if (myIndexType == 1) {
1793 const unsigned short * pInd =
1794 reinterpret_cast<const unsigned short *>(theArray);
1795 pResult = &mypNodes[myNodeCoord * pInd[theInd]];
1798 pResult = &mypNodes[myNodeCoord * theArray[theInd]];