CFx SDK Documentation 2024 SP0
Loading...
Searching...
No Matches
GiExtentsSpaceTree.h
Go to the documentation of this file.
1
2// Copyright (C) 2002-2022, Open Design Alliance (the "Alliance").
3// All rights reserved.
4//
5// This software and its documentation and related materials are owned by
6// the Alliance. The software may only be incorporated into application
7// programs owned by members of the Alliance, subject to a signed
8// Membership Agreement and Supplemental Software License Agreement with the
9// Alliance. The structure and organization of this software are the valuable
10// trade secrets of the Alliance and its suppliers. The software is also
11// protected by copyright law and international treaty provisions. Application
12// programs incorporating this software must include the following statement
13// with their copyright notices:
14//
15// This application incorporates Open Design Alliance software pursuant to a license
16// agreement with Open Design Alliance.
17// Open Design Alliance Copyright (C) 2002-2022 by Open Design Alliance.
18// All rights reserved.
19//
20// By use of this software, its documentation or related materials, you
21// acknowledge and accept the above terms.
23
24#ifndef __ODGIEXTENTS3DSPACETREE_H__
25#define __ODGIEXTENTS3DSPACETREE_H__
26
27#include "Ge/GeExtents3d.h"
28#include "Ge/GeExtents2d.h"
29#include "OdVector.h"
30#define STL_USING_SET
31#define STL_USING_MAP
32#include "OdaSTL.h"
33#include "OdList.h"
34
35#ifdef _MSC_VER
36#pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data
37#endif
38
39#include "TD_PackPush.h"
40
49{
50 // unique ID of the object
51 //IMPORTANT: the user is responsible for the uniqueness of the ID
52 OdUInt64 ID;
53
54public:
55
56 // constructor
58 {
59 ID = uniqueID;
60 }
61
62 //set/get ID
63 OdUInt64 getID() const {return ID;}
64 void setID(OdUInt64 uniqueID){ID = uniqueID;}
65
66 // pure virtual members
67 virtual bool isInExtents(OdGeExtents3d& extents) const = 0;
68 virtual bool isInExtents(OdGeExtents2d& extents) const = 0;
69 virtual bool isEqual(OdGiExtentsSpaceObject* pObject, const OdGeTol& tol = OdGeContext::gTol) const = 0;
70};
71
72
80template <class E, class O> class OdGiExtentsSpaceNode //here E should be OdGeExtents3d or OdGeExtents2d
81{
82 template <OdUInt32 NUM_AXIS, OdUInt32 MAX_DEPTH, OdUInt64 MAX_NODE_OBJECT, class EE, class P, class OO> friend class OdGiExtentsSpaceTree;
83
84 // left child node (only link, not need to delete)
85 OdGiExtentsSpaceNode* m_pLeftChild;
86 //right child node (only link, not need to delete)
87 OdGiExtentsSpaceNode* m_pRightChild;
88 //parent node (only link, not need to delete)
89 OdGiExtentsSpaceNode* m_pParent;
90
91 // extents of the node
92 E m_extents;
93
94 // array of vectors with objects in the tree
95 std::map<int, OdVector<O*, OdMemoryAllocator<O*> >* >* m_pObjectPointers;
96 int m_iObjectsTypes;
97
98 // special (the power of 8 or power of 4 ) depth of the node in the tree
99 int m_iDepth;
100public:
101
102 //constructor
103 OdGiExtentsSpaceNode(OdGiExtentsSpaceNode* parent, E& extents, int nDepth, int nTypeOfObjects)
104 {
105 m_pParent = parent;
106 m_extents = extents;
107
108 m_pLeftChild = NULL;
109 m_pRightChild = NULL;
110
111 m_iObjectsTypes = 0;
112 m_pObjectPointers = NULL;
113 if ( nTypeOfObjects > 0 )
114 m_iObjectsTypes = nTypeOfObjects;
115
116 m_iDepth = nDepth;
117 }
118
119 //destructor
121 {
122 releaseObjectsStore();
123 }
124
125 // methods
126 // check that the node is leave
127 bool isLeave()
128 {
129 return (m_pLeftChild == NULL && m_pRightChild == NULL);
130 }
131
132 //get the depth of the ndoe
133 int getDepth() {return m_iDepth;}
134
135
136 // retrieve the pointer the stores objects list
138 {
139 if ( m_pObjectPointers == NULL )
140 return NULL;
141
142 if ( iType < m_iObjectsTypes )
143 {
144 OD_TYPENAME std::map<int, OdVector<O*, OdMemoryAllocator<O*> >* >::iterator it = m_pObjectPointers->find(iType);
145 if ( it != m_pObjectPointers->end() )
146 return it->second;
147 }
148
149 return NULL;
150 }
151
152private:
153
154 // initialize objects list
155 OdVector<O*, OdMemoryAllocator<O*> >* initObjectList(int iType, int iMaxObjectsInNode)
156 {
157 if ( m_pObjectPointers == NULL )
158 m_pObjectPointers = new std::map<int, OdVector<O*, OdMemoryAllocator<O*> >* >;
159
161 (*m_pObjectPointers)[iType] = pNewVector;
162
163 pNewVector->setPhysicalLength(10);
164 pNewVector->setGrowLength(iMaxObjectsInNode);
165
166 return pNewVector;
167 }
168
169 void releaseObjectsStore()
170 {
171 if ( m_pObjectPointers )
172 {
173 OD_TYPENAME std::map<int, OdVector<O*, OdMemoryAllocator<O*> >*>::iterator it = m_pObjectPointers->begin();
174 OD_TYPENAME std::map<int, OdVector<O*, OdMemoryAllocator<O*> >*>::iterator itEnd = m_pObjectPointers->end();
175 while ( it != itEnd )
176 {
177 if ( it->second )
178 delete it->second;
179 ++it;
180 }
181
182 m_pObjectPointers->clear();
183 delete m_pObjectPointers;
184 m_pObjectPointers = NULL;
185 }
186 }
187};
188
189
192
199template <class E, class O>
201{
202 public:
203 virtual bool notifyObjectPlacedAtNode(O* /*pObject*/, int /*objectType*/, OdGiExtentsSpaceNode<E,O>* pNode) = 0;
204};
205
206
207
214template <OdUInt32 NUM_AXIS, OdUInt32 MAX_DEPTH, OdUInt64 MAX_NODE_OBJECT, class E, class P, class O> class OdGiExtentsSpaceTree
215{
216 //root node
217 OdGiExtentsSpaceNode<E, O>* m_pRootNode;
218
219 // list of all nodes
221
222 // list of all leaves
224
225 // pointer to the callback
227
228 //Is addaptive - means that started additioanl splitting when the number of objects starts to be greater than 'm_iMaxNodeObjects'
229 bool m_bIsAdaptive;
230 OdUInt64 m_iMaxNodeObjects;
231
232 // for storing the same objects during processing
233 OdList<O*> m_theSameObjects;
234
235 // for storing the intersected leaves during processing
236 OdList<OdGiExtentsSpaceNode<E, O>*> m_theIntersectedLeaves;
237
238 // for storing the leaves where we should add the object (delayed adding in the case of checking the same)
239 OdList<OdGiExtentsSpaceNode<E, O>*> m_theCandidateLeaves;
240
241public:
242
243 //constructor
245 {
246 m_pRootNode = NULL;
247 m_bIsAdaptive = false;
248 m_iMaxNodeObjects = MAX_NODE_OBJECT;
249 m_pCallback = NULL;
250 }
251
252 //destructor
254
255 //set callback
256 void setCallback(OdGiExtentsSpaceTreeCallback<E, O>* pCallback) {m_pCallback = pCallback;}
257
258 //build the tree (the correctness of the incoming extents should check the caller)
259 void buildTree(E& extents, int nTypeOfObjects, OdInt depth = 2)
260 {
261 if ( depth > MAX_DEPTH )
262 depth = MAX_DEPTH;
263 else if ( depth < 0 )
264 depth = 0;
265
266 if ( m_pRootNode != NULL )
267 reset();
268
269 //1. Create root node
270 m_pRootNode = new OdGiExtentsSpaceNode<E,O>(NULL, extents, 0, nTypeOfObjects);
271 m_Nodes.push_back(m_pRootNode);
272
273 //2. Call recursive method for making the tree
274 constructChilds(m_pRootNode, NUM_AXIS, depth, nTypeOfObjects);
275 }
276
277 // reset the tree
278 void reset()
279 {
280 m_pRootNode = NULL;
281
282 OD_TYPENAME OdList<OdGiExtentsSpaceNode<E,O>*>::iterator it = m_Nodes.begin();
283 OD_TYPENAME OdList<OdGiExtentsSpaceNode<E,O>*>::iterator itEnd = m_Nodes.end();
284 while ( it != itEnd )
285 {
286 OdGiExtentsSpaceNode<E,O>* pNode = *it;
287 delete pNode;
288 ++it;
289 }
290
291 m_Leaves.clear();
292 m_Nodes.clear();
293
294 m_theSameObjects.clear();
295 m_theIntersectedLeaves.clear();
296 m_theCandidateLeaves.clear();
297 }
298
299 // set that the tree should be adaptive or not
300 void setAdaptive(bool bAdaptive) {m_bIsAdaptive = bAdaptive;}
301
302 // set the maximal node objects (used only if 'm_bIsAdaptive' = true)
303 void setMaxNodeObjects(OdUInt64 nObjects) { m_iMaxNodeObjects = nObjects <= 0 ? m_iMaxNodeObjects : nObjects; }
304
305 //process object
306 O* processObject(O* pObject, int iObjectType, bool bCheckTheSame = false, const OdGeTol& tol = OdGeContext::gTol)
307 {
308 m_theSameObjects.clear();
309 m_theCandidateLeaves.clear();
310
311 if ( m_pRootNode == NULL )
312 return NULL;
313
314 nodeProcessObject(m_pRootNode, pObject, iObjectType, bCheckTheSame, tol);
315
316 if ( m_theSameObjects.size() == 0 )
317 {
318 if ( !m_theCandidateLeaves.empty() )
319 {
320 OD_TYPENAME OdList<OdGiExtentsSpaceNode<E,O>*>::iterator itNodes = m_theCandidateLeaves.begin();
321 OD_TYPENAME OdList<OdGiExtentsSpaceNode<E,O>*>::iterator itNodesEnd = m_theCandidateLeaves.end();
322 while ( itNodes != itNodesEnd )
323 {
324 OdGiExtentsSpaceNode<E, O>* pNode = *itNodes;
325 if (pNode)
326 {
327 nodeProcessObject(pNode, pObject, iObjectType, false, tol);
328 }
329 ++itNodes;
330 }
331 }
332 m_theCandidateLeaves.clear();
333 return NULL;
334 }
335
336 m_theCandidateLeaves.clear();
337
338 return m_theSameObjects.front();
339 }
340
341 // retrieve the leaves nodes
343
344 //retrieve the extents of the root node
345 bool getRootExtents(E& exts)
346 {
347 if ( m_pRootNode == NULL )
348 return false;
349
350 if(m_pRootNode->m_extents.isValidExtents())
351 {
352 exts = m_pRootNode->m_extents;
353 return true;
354 }
355 return false;
356 }
357
359 {
360 m_theIntersectedLeaves.clear();
361
362 if ( m_pRootNode == NULL )
363 return NULL;
364
365 nodeProcessExtent(m_pRootNode, ext);
366
367 if ( m_theIntersectedLeaves.size() == 0 )
368 return NULL;
369
370 return &m_theIntersectedLeaves;
371 }
372
374 {
375 m_theIntersectedLeaves.clear();
376
377 nodeProcessPoint(m_pRootNode, pt);
378
379 if ( m_theIntersectedLeaves.size() == 0 )
380 return NULL;
381
382 return &m_theIntersectedLeaves;
383 }
384
385 OdList<OdGiExtentsSpaceNode<E, O>*>* getPointLeaves(const P& pt, double proximityRadius)
386 {
387 m_theIntersectedLeaves.clear();
388
389 nodeProcessPoint(m_pRootNode, pt, proximityRadius);
390
391 if (m_theIntersectedLeaves.size() == 0)
392 return NULL;
393
394 return &m_theIntersectedLeaves;
395 }
396
397private:
398
399 // internal recursive method for building the tree
400 void constructChilds(OdGiExtentsSpaceNode<E,O>* pParentNode, int axislevel, int curDepth, int nTypeOfObjects)
401 {
402 if ( pParentNode == NULL )
403 return;
404
405 if ( curDepth == 0 )
406 {
407 // means we have a leave
408 m_Leaves.push_back(pParentNode);
409 return;
410 }
411
412 //define the left part extents
413 E leftChildExtents;
414
415 P leftBounPoint = pParentNode->m_extents.maxPoint();
416 switch ( axislevel )
417 {
418 case 3:
419 middlez(pParentNode->m_extents.maxPoint(), pParentNode->m_extents.minPoint(), leftBounPoint);
420 break;
421 case 2:
422 leftBounPoint.x = (pParentNode->m_extents.maxPoint().x + pParentNode->m_extents.minPoint().x)/2.;
423 break;
424 case 1:
425 leftBounPoint.y = (pParentNode->m_extents.maxPoint().y + pParentNode->m_extents.minPoint().y)/2.;
426 break;
427 }
428
429 leftChildExtents.set(pParentNode->m_extents.minPoint(), leftBounPoint);
430
431 // create left child
432 pParentNode->m_pLeftChild = new OdGiExtentsSpaceNode<E,O>(pParentNode, leftChildExtents, axislevel > 1 ? pParentNode->m_iDepth : pParentNode->m_iDepth + 1, nTypeOfObjects);
433 m_Nodes.push_back(pParentNode->m_pLeftChild);
434
435 // go deeper
436 if ( axislevel > 1 )
437 constructChilds(pParentNode->m_pLeftChild, axislevel-1, curDepth, nTypeOfObjects);
438 else
439 constructChilds(pParentNode->m_pLeftChild, NUM_AXIS, curDepth-1, nTypeOfObjects);
440
441 //define the right part extents
442 E rightChildExtents;
443
444 P rightBounPoint = pParentNode->m_extents.minPoint();
445 switch ( axislevel )
446 {
447 case 3:
448 middlez(pParentNode->m_extents.maxPoint(), pParentNode->m_extents.minPoint(), rightBounPoint);
449 break;
450 case 2:
451 rightBounPoint.x = (pParentNode->m_extents.maxPoint().x + pParentNode->m_extents.minPoint().x)/2.;
452 break;
453 case 1:
454 rightBounPoint.y = (pParentNode->m_extents.maxPoint().y + pParentNode->m_extents.minPoint().y)/2.;
455 break;
456 }
457
458 rightChildExtents.set(rightBounPoint, pParentNode->m_extents.maxPoint());
459
460 // create right child
461 pParentNode->m_pRightChild = new OdGiExtentsSpaceNode<E,O>(pParentNode, rightChildExtents, axislevel > 1 ? pParentNode->m_iDepth : pParentNode->m_iDepth + 1, nTypeOfObjects);
462 m_Nodes.push_back(pParentNode->m_pRightChild);
463
464 // go deeper
465 if ( axislevel > 1 )
466 constructChilds(pParentNode->m_pRightChild, axislevel-1, curDepth, nTypeOfObjects);
467 else
468 constructChilds(pParentNode->m_pRightChild, NUM_AXIS, curDepth-1, nTypeOfObjects);
469
470 return;
471 }
472
473 // internal recursive method for process objects
474 void nodeProcessObject(OdGiExtentsSpaceNode<E,O>* pNode, O* pObject, int iObjectType, bool bCheckTheSame, const OdGeTol& tol = OdGeContext::gTol)
475 {
476 if ( pNode == NULL || pObject == NULL )
477 return;
478
479 bool bIntersect = pObject->isInExtents(pNode->m_extents);
480
481 if ( bIntersect )
482 {
483 if ( pNode->isLeave() )
484 {
485 if ( m_pCallback )
486 {
487 if ( !m_pCallback->notifyObjectPlacedAtNode(pObject, iObjectType, pNode) )
488 return;
489 }
490
491 OdVector<O*, OdMemoryAllocator<O*> >* pNodeObjects = pNode->getObjectPointersPtr(iObjectType);
492 if ( pNodeObjects == NULL ) // initialize object list if need
493 {
494 if ( m_iMaxNodeObjects > 0 )
495 pNodeObjects = pNode->initObjectList(iObjectType, m_iMaxNodeObjects+1);
496 else
497 pNodeObjects = pNode->initObjectList(iObjectType, 50);
498 }
499
500 if ( pNodeObjects )
501 {
502 if ( bCheckTheSame ) // check that we already have the same object
503 {
504 OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator itNodes = pNodeObjects->begin();
505 OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator itNodesEnd = pNodeObjects->end();
506 while ( itNodes != itNodesEnd )
507 {
508 O* pObjectInList = *itNodes;
509 if ( pObjectInList )
510 {
511 if ( pObjectInList->isEqual(pObject, tol) )
512 {
513 m_theSameObjects.push_back(pObjectInList);
514 return;
515 }
516 }
517 ++itNodes;
518 }
519 m_theCandidateLeaves.push_back(pNode);
520 }
521 else // simply add
522 {
523 pNodeObjects->push_back( pObject );
524 }
525 }
526
527 //adaptive case
528 if ( m_bIsAdaptive && pNodeObjects->size() > m_iMaxNodeObjects && pNode->m_iDepth <= MAX_DEPTH )
529 {
530 // remove current node from leaves
531 m_Leaves.remove(pNode);
532
533 //try to make additional split
534 constructChilds(pNode, NUM_AXIS, 1/*one step deeper*/, pNode->m_iObjectsTypes);
535
536 //put down the objects
537 for ( int i = 0; i < pNode->m_iObjectsTypes; i++)
538 {
539 pNodeObjects = pNode->getObjectPointersPtr(i);
540 if ( pNodeObjects )
541 {
542 OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator it = pNodeObjects->begin();
543 OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator itEnd = pNodeObjects->end();
544 while ( it != itEnd )
545 {
546 O* pObjectInList = *it;
547
548 if ( pObjectInList )
549 {
550 nodeProcessObject(pNode->m_pLeftChild, pObjectInList, i, false, tol);
551 nodeProcessObject(pNode->m_pRightChild, pObjectInList, i, false, tol);
552 }
553
554 ++it;
555 }
556 }
557 } //eo for...
558 //remove information about the objects in the nodes
559 pNode->releaseObjectsStore();
560 }
561 }
562 else
563 {
564 nodeProcessObject(pNode->m_pLeftChild, pObject, iObjectType, bCheckTheSame, tol);
565 nodeProcessObject(pNode->m_pRightChild, pObject, iObjectType, bCheckTheSame, tol);
566 }
567 }
568
569 return;
570 }
571
572 // internal recursive method for process extents
573 void nodeProcessExtent(OdGiExtentsSpaceNode<E,O>* pNode, E& ext)
574 {
575 if ( pNode == NULL || !ext.isValidExtents() )
576 return;
577
578 E isect;
579 ext.intersectWith(pNode->m_extents, &isect);
580
581 if ( isect.isValidExtents() )
582 {
583 if ( pNode->isLeave() )
584 {
585 m_theIntersectedLeaves.push_back(pNode);
586 }
587 else
588 {
589 nodeProcessExtent(pNode->m_pLeftChild, ext);
590 nodeProcessExtent(pNode->m_pRightChild, ext);
591 }
592 }
593
594 return;
595 }
596
597 // internal recursive method for process point
598 void nodeProcessPoint(OdGiExtentsSpaceNode<E,O>* pNode, const P& pt)
599 {
600 if ( pNode == NULL )
601 return;
602
603 if ( pNode->m_extents.contains(pt) )
604 {
605 if ( pNode->isLeave() )
606 {
607 m_theIntersectedLeaves.push_back(pNode);
608 }
609 else
610 {
611 nodeProcessPoint(pNode->m_pLeftChild, pt);
612 nodeProcessPoint(pNode->m_pRightChild, pt);
613 }
614 }
615
616 return;
617 }
618
619 void nodeProcessPoint(OdGiExtentsSpaceNode<E, O>* pNode, const P& pt, double r)
620 {
621 if (pNode == NULL)
622 return;
623
624 if (pNode->m_extents.isWithinRange(pt, r))
625 {
626 if (pNode->isLeave())
627 {
628 m_theIntersectedLeaves.push_back(pNode);
629 }
630 else
631 {
632 nodeProcessPoint(pNode->m_pLeftChild, pt, r);
633 nodeProcessPoint(pNode->m_pRightChild, pt, r);
634 }
635 }
636
637 return;
638 }
639
640 void middlez(const OdGePoint2d& pt1, const OdGePoint2d& pt2, OdGePoint2d& ptRes)
641 {
642 return;
643 }
644
645
646 void middlez(const OdGePoint3d& pt1, const OdGePoint3d& pt2, OdGePoint3d& ptRes)
647 {
648 ptRes.z = (pt1.z + pt2.z)/2.;
649 return;
650 }
651};
652
655
656
665{
667
668 // set of the IDs of edges which have this vertex
669 std::set<OdUInt64> m_edges;
670
671 // set of the IDs of invisible edges which have this vertex
672 std::set<OdUInt64> m_invisibleedges;
673
674 // need for constructing the chain polylines
675 bool m_bVisited;
676
677public:
678
679 //point
681
682 //constructor
684 {
685 m_pt.set(pt.x, pt.y, pt.z);
686 m_bVisited = false;
687 }
688
690 {
691 m_edges.clear();
692 m_invisibleedges.clear();
693 }
694
696 {
697 m_edges.insert(ID);
698 }
699
701 {
702 m_invisibleedges.insert(ID);
703 }
704
706 {
707 m_invisibleedges.erase(ID);
708 }
709
710 // check that the edge is in extents (currently not used)
711 bool isInExtents(OdGeExtents3d& extents) const
712 {
713 OdGeTol tol;
714 if (extents.contains( m_pt, tol ) )
715 return true;
716
717 return false;
718 }
719
720 bool isInExtents(OdGeExtents2d& extents) const {return false;}
721
722 // check that objects are equal
724 {
725 OdGiExtents3dSpacePoint* pObjectVertex = dynamic_cast<OdGiExtents3dSpacePoint*>(pObject);
726
727 if ( pObjectVertex == NULL )
728 return false;
729
730 if ( pObjectVertex->m_pt.isEqualTo(m_pt, tol) )
731 return true;
732
733 return false;
734 }
735
737 {
738 return m_edges.size();
739 }
740
741 const std::set<OdUInt64>* getEdges(){return &m_edges;}
742 const std::set<OdUInt64>* getInvisilbeEdges(){return & m_invisibleedges;}
743
744 void setVisited(bool bVisit){m_bVisited = bVisit;}
745 bool isVisited(){return m_bVisited;}
746
747};
748
757{
758
759public:
760 //two vertices
763 bool m_bVisited; // need for constructing the pathes
764 bool m_bIsVisible; // means that the edge is not visible
765
766 //constructor
768 {
769 m_iVert1 = pt1.getID();
770 m_iVert2 = pt2.getID();
771
772 if ( uniqueID >= 0 )
773 {
774 pt1.m_edges.insert(uniqueID);
775 pt2.m_edges.insert(uniqueID);
776 }
777
778 m_bVisited = false;
779 m_bIsVisible = true;
780 }
781
782 void setVisited(bool bVisit){m_bVisited = bVisit;}
783 bool isVisited(){return m_bVisited;}
784
786 {
787 if ( iDfirst == m_iVert1 )
788 return m_iVert2;
789
790 return m_iVert1;
791 }
792
793 bool isInExtents(OdGeExtents3d& extents) const {return false;}
794 bool isInExtents(OdGeExtents2d& extents) const {return false;}
795 bool isEqual(OdGiExtentsSpaceObject* pObject, const OdGeTol& tol = OdGeContext::gTol) const{return false;}
796};
797
806{
807protected:
808
810
811public:
812
813 //constructor
815
817
818 virtual void addVertex(OdGiExtents3dSpacePoint* pVertex)
819 {
820 vertices.push_back(pVertex);
821 }
822
825 {
826 OdGiExtents3dSpacePoint* ptFirst = vertices.front();
827 OdGiExtents3dSpacePoint* ptSecond = vertices.back();
828 if ( ptFirst == ptSecond && vertices.size() > 1)
829 return vertices.size()-1;
830
831 return vertices.size();
832 }
833
834 void getPoints(OdGePoint3d *pPoints)
835 {
836 if ( pPoints == NULL )
837 return;
838
841 OdUInt32 ind = 0;
842 while ( it != itEnd )
843 {
844 OdGiExtents3dSpacePoint* pVertex = *it;
845 if ( pVertex )
846 {
847 pPoints[ind].set(pVertex->m_pt.x, pVertex->m_pt.y, pVertex->m_pt.z);
848 ind++;
849 }
850 ++it;
851 }
852 }
853
855 {
856 if ( pPoints == NULL )
857 return;
858
861
862 OdGiExtents3dSpacePoint* ptFirst = vertices.front();
863 OdGiExtents3dSpacePoint* ptSecond = vertices.back();
864 if ( ptFirst == ptSecond && vertices.size() > 1 )
865 --itEnd;
866
867 OdUInt32 ind = 0;
868 while ( it != itEnd )
869 {
870 OdGiExtents3dSpacePoint* pVertex = *it;
871 if ( pVertex )
872 {
873 pPoints[ind].set(pVertex->m_pt.x, pVertex->m_pt.y, pVertex->m_pt.z);
874 ind++;
875 }
876 ++it;
877 }
878 }
879
880 void getPoints(OdGePoint3dVector& pts)
881 {
882 getPoints(pts.asArrayPtr());
883 }
884
885 void getPoints_closed(OdGePoint3dVector& pts)
886 {
887 getPoints_closed(pts.asArrayPtr());
888 }
889
890 bool isInExtents(OdGeExtents3d& extents) const {return false;}
891 bool isInExtents(OdGeExtents2d& extents) const {return false;}
892 bool isEqual(OdGiExtentsSpaceObject* pObject, const OdGeTol& tol = OdGeContext::gTol) const{return false;}
893};
894
895
897{
898 // next start vertex for finding the path
900 {
901 OdGiExtents3dSpacePoint* pStartVertex = NULL;
902
903 //1. Try to find leafs
904 if ( leafs.size() > 0 )
905 {
906 OdList<OdGiExtents3dSpacePoint*>::iterator itLeafs = leafs.begin();
907 OdList<OdGiExtents3dSpacePoint*>::iterator itLeafsEnd = leafs.end();
908 while ( itLeafs != itLeafsEnd )
909 {
910 OdGiExtents3dSpacePoint* pLeaf = *itLeafs;
911 if ( pLeaf && !pLeaf->isVisited() )
912 {
913 pStartVertex = pLeaf;
914 break;
915 }
916 ++itLeafs;
917 }
918 }
919
920 //2. Try to find first not visited vertex
921 if ( pStartVertex == NULL )
922 {
923 int iVertNumber = points.size();
924 for (OdUInt64 i = 0; i < iVertNumber; i++)
925 {
926 OdGiExtents3dSpacePoint* pVert = points[i];
927 if ( pVert && !pVert->isVisited() )
928 {
929 pStartVertex = pVert;
930 break;
931 }
932 }
933 }
934
935 return pStartVertex;
936 }
937
938template <class E>
939static OdGiExtents3dSpaceEdge* getFirstUnvisitedEdge(OdGiExtents3dSpacePoint* pVertex, OdArray<E*>& edges)
940{
941 if ( pVertex == NULL )
942 return NULL;
943
944 const std::set<OdUInt64>* pEdges = pVertex->getEdges();
945 if ( pEdges == NULL )
946 return NULL;
947
948 std::set<OdUInt64>::const_iterator itEdge = pEdges->begin();
949 std::set<OdUInt64>::const_iterator itEdgeEnd = pEdges->end();
950 while ( itEdge != itEdgeEnd )
951 {
952 OdUInt64 edgeID = *itEdge;
953 if ( edgeID < edges.size() )
954 {
955 OdGiExtents3dSpaceEdge* pEdge = dynamic_cast<OdGiExtents3dSpaceEdge*>(edges[edgeID]);
956 if ( pEdge && !pEdge->isVisited() && pEdge->m_bIsVisible )
957 return pEdge;
958 }
959
960 ++itEdge;
961 }
962
963 return NULL;
964}
965
966 // construct a path from start vertex
967template <class T, class E>
968static void constructPath(OdGiExtents3dSpacePoint* pStartVertex, OdArray<OdGiExtents3dSpacePoint*>& points,
969 OdArray<E*>& edges, OdList<T*>& polylines)
970{
971 if ( pStartVertex == NULL )
972 return;
973
974 OdGiExtents3dSpacePoint* pFirstVertex = pStartVertex;
975
976 T *pPath = NULL;
977 //loop
978 while(pFirstVertex)
979 {
980 //get unvisited edge
981 OdGiExtents3dSpaceEdge* pFirstEdge = getFirstUnvisitedEdge(pFirstVertex, edges);
982 if ( pFirstEdge == NULL )
983 {
984 pFirstVertex->setVisited(true);
985 break;
986 }
987
988 // get the second vertex of the edge
989 OdGiExtents3dSpacePoint* pNextVertex = points[pFirstEdge->getSecondVertex(pFirstVertex->getID())];
990
991 //init the path
992 if ( pPath == NULL )
993 {
994 pPath = new T(0);
995 pPath->addVertex(pFirstVertex);
996 }
997 pPath->addVertex(pNextVertex);
998
999 pFirstVertex->setVisited(true);
1000 pNextVertex->setVisited(true);
1001 pFirstEdge->setVisited(true);
1002
1003 pFirstVertex = pNextVertex;
1004 }
1005
1006 if ( pPath )
1007 polylines.push_back(pPath);
1008
1009 return;
1010}
1011
1012public:
1013template <class T, class E>
1015{
1016 //1. Find the vertices with power 1 if exists
1018 int iVertNumber = points.size();
1019 for (OdUInt64 i = 0; i < iVertNumber; i++)
1020 {
1021 OdGiExtents3dSpacePoint* pVert = points[i];
1022 if ( pVert )
1023 {
1024 OdUInt64 vPower = pVert->getPower();
1025 if ( vPower == 1 )
1026 leafVertices.push_back(pVert);
1027 else if ( vPower == 0 )
1028 pVert->setVisited(true);
1029 }
1030 }
1031
1032 //2. run loop for construction the pathes
1033 OdGiExtents3dSpacePoint* pStartVertex = getNextStartVertex(points, leafVertices);
1034 while ( pStartVertex )
1035 {
1036 constructPath(pStartVertex, points, edges, polylines);
1037 pStartVertex = getNextStartVertex(points, leafVertices);
1038 }
1039
1040 return polylines.size();
1041}
1042};
1043
1044#include "TD_PackPop.h"
1045
1046#endif //#ifndef __ODGIEXTENTS3DSPACETREE_H__
tol
Definition: DimVarDefs.h:2287
OdGiExtentsSpaceTree< 3, 5, 20, OdGeExtents3d, OdGePoint3d, OdGiExtentsSpaceObject > OdGiExtents3dSpaceTree
OdGiExtentsSpaceTree< 2, 10, 10, OdGeExtents2d, OdGePoint2d, OdGiExtentsSpaceObject > OdGiExtents2dSpaceTree
OdGiExtentsSpaceNode< OdGeExtents3d, OdGiExtentsSpaceObject > OdGiExtents3dSpaceNode
OdGiExtentsSpaceNode< OdGeExtents2d, OdGiExtentsSpaceObject > OdGiExtents2dSpaceNode
#define OD_TYPENAME
Definition: OdPlatform.h:631
unsigned int OdUInt32
int OdInt
E
Definition: SysVarDefs.h:422
size_type size() const
Definition: OdArray.h:1247
bool contains(const OdGePoint3d &point, const OdGeTol &tol=OdGeContext::gTol) const
Definition: GeExtents3d.h:521
bool isEqualTo(const OdGePoint3d &point, const OdGeTol &tol=OdGeContext::gTol) const
double z
Definition: GePoint3d.h:497
double y
Definition: GePoint3d.h:496
double x
Definition: GePoint3d.h:495
OdGePoint3d & set(double xx, double yy, double zz)
Definition: GePoint3d.h:455
Definition: GeTol.h:49
virtual void addVertex(OdGiExtents3dSpacePoint *pVertex)
bool isInExtents(OdGeExtents2d &extents) const
void getPoints(OdGePoint3dVector &pts)
bool isInExtents(OdGeExtents3d &extents) const
void getPoints(OdGePoint3d *pPoints)
void getPoints_closed(OdGePoint3dVector &pts)
OdGiExtents3dSpaceChainPolyline(OdInt64 uniqueID)
void getPoints_closed(OdGePoint3d *pPoints)
bool isEqual(OdGiExtentsSpaceObject *pObject, const OdGeTol &tol=OdGeContext::gTol) const
OdList< OdGiExtents3dSpacePoint * > vertices
void setVisited(bool bVisit)
OdGiExtents3dSpaceEdge(OdGiExtents3dSpacePoint &pt1, OdGiExtents3dSpacePoint &pt2, OdInt64 uniqueID)
bool isEqual(OdGiExtentsSpaceObject *pObject, const OdGeTol &tol=OdGeContext::gTol) const
bool isInExtents(OdGeExtents3d &extents) const
bool isInExtents(OdGeExtents2d &extents) const
OdUInt64 getSecondVertex(OdUInt64 iDfirst)
bool isInExtents(OdGeExtents2d &extents) const
OdGiExtents3dSpacePoint(const OdGePoint3d &pt, OdUInt64 uniqueID)
bool isEqual(OdGiExtentsSpaceObject *pObject, const OdGeTol &tol=OdGeContext::gTol) const
const std::set< OdUInt64 > * getInvisilbeEdges()
void removeInvisible(OdUInt64 ID)
const std::set< OdUInt64 > * getEdges()
void addInvisible(OdUInt64 ID)
bool isInExtents(OdGeExtents3d &extents) const
void setVisited(bool bVisit)
static OdInt64 calculateChainPolylinesFromEdges(OdArray< OdGiExtents3dSpacePoint * > &points, OdArray< E * > &edges, OdList< T * > &polylines)
OdGiExtentsSpaceNode(OdGiExtentsSpaceNode *parent, E &extents, int nDepth, int nTypeOfObjects)
OdVector< O *, OdMemoryAllocator< O * > > * getObjectPointersPtr(int iType)
virtual bool isEqual(OdGiExtentsSpaceObject *pObject, const OdGeTol &tol=OdGeContext::gTol) const =0
virtual bool isInExtents(OdGeExtents3d &extents) const =0
OdGiExtentsSpaceObject(OdUInt64 uniqueID)
virtual bool isInExtents(OdGeExtents2d &extents) const =0
void setID(OdUInt64 uniqueID)
virtual bool notifyObjectPlacedAtNode(O *, int, OdGiExtentsSpaceNode< E, O > *pNode)=0
O * processObject(O *pObject, int iObjectType, bool bCheckTheSame=false, const OdGeTol &tol=OdGeContext::gTol)
void setCallback(OdGiExtentsSpaceTreeCallback< E, O > *pCallback)
OdList< OdGiExtentsSpaceNode< E, O > * > * getPointLeaves(const P &pt, double proximityRadius)
OdList< OdGiExtentsSpaceNode< E, O > * > * getExtentsLeaves(E &ext)
OdList< OdGiExtentsSpaceNode< E, O > * > * retrieveLeaves()
bool getRootExtents(E &exts)
void setAdaptive(bool bAdaptive)
OdList< OdGiExtentsSpaceNode< E, O > * > * getPointLeaves(const P &pt)
void buildTree(E &extents, int nTypeOfObjects, OdInt depth=2)
void setMaxNodeObjects(OdUInt64 nObjects)
Definition: Int64.h:43
Definition: OdList.h:50
std::list< T, A >::iterator iterator
Definition: OdList.h:52
OdVector & setGrowLength(int growLength)
Definition: OdVector.h:1559
iterator begin()
Definition: OdVector.h:861
void push_back(const T &value)
Definition: OdVector.h:1280
size_type size() const
Definition: OdVector.h:1204
OdVector & setPhysicalLength(size_type physicalLength)
Definition: OdVector.h:1540
iterator end()
Definition: OdVector.h:873
static GE_STATIC_EXPORT OdGeTol gTol
Definition: GeGbl.h:65