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