CFx SDK Documentation  2023 SP0
GiExtentsSpaceTree.h
Go to the documentation of this file.
1 // Copyright (C) 2002-2017, 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 Teigha(R) software pursuant to a license
16 // agreement with Open Design Alliance.
17 // Teigha(R) Copyright (C) 2002-2017 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 
54 public:
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 
80 template <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;
100 public:
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 
152 private:
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 
199 template <class E, class O>
201 {
202  public:
203  virtual bool notifyObjectPlacedAtNode(O* /*pObject*/, int /*objectType*/, OdGiExtentsSpaceNode<E,O>* pNode) = 0;
204 };
205 
206 
207 
214 template <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 public:
239 
240  //constructor
242  {
243  m_pRootNode = NULL;
244  m_bIsAdaptive = false;
245  m_iMaxNodeObjects = MAX_NODE_OBJECT;
246  m_pCallback = NULL;
247  }
248 
249  //destructor
251 
252  //set callback
253  void setCallback(OdGiExtentsSpaceTreeCallback<E, O>* pCallback) {m_pCallback = pCallback;}
254 
255  //build the tree (the correctness of the incoming extents should check the caller)
256  void buildTree(E& extents, int nTypeOfObjects, OdInt depth = 2)
257  {
258  if ( depth > MAX_DEPTH )
259  depth = MAX_DEPTH;
260  else if ( depth < 0 )
261  depth = 0;
262 
263  if ( m_pRootNode != NULL )
264  reset();
265 
266  //1. Create root node
267  m_pRootNode = new OdGiExtentsSpaceNode<E,O>(NULL, extents, 0, nTypeOfObjects);
268  m_Nodes.push_back(m_pRootNode);
269 
270  //2. Call recursive method for making the tree
271  constructChilds(m_pRootNode, NUM_AXIS, depth, nTypeOfObjects);
272  }
273 
274  // reset the tree
275  void reset()
276  {
277  m_pRootNode = NULL;
278 
279  OD_TYPENAME OdList<OdGiExtentsSpaceNode<E,O>*>::iterator it = m_Nodes.begin();
280  OD_TYPENAME OdList<OdGiExtentsSpaceNode<E,O>*>::iterator itEnd = m_Nodes.end();
281  while ( it != itEnd )
282  {
283  OdGiExtentsSpaceNode<E,O>* pNode = *it;
284  delete pNode;
285  ++it;
286  }
287 
288  m_Leaves.clear();
289  m_Nodes.clear();
290 
291  m_theSameObjects.clear();
292  m_theIntersectedLeaves.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(OdUInt64 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 
306  if ( m_pRootNode == NULL )
307  return NULL;
308 
309  nodeProcessObject(m_pRootNode, pObject, iObjectType, bCheckTheSame, tol);
310 
311  if ( m_theSameObjects.size() == 0 )
312  return NULL;
313 
314  return m_theSameObjects.front();
315  }
316 
317  // retrieve the leaves nodes
319 
320  //retrieve the extents of the root node
321  bool getRootExtents(E& exts)
322  {
323  if ( m_pRootNode == NULL )
324  return false;
325 
326  if(m_pRootNode->m_extents.isValidExtents())
327  {
328  exts = m_pRootNode->m_extents;
329  return true;
330  }
331  return false;
332  }
333 
335  {
336  m_theIntersectedLeaves.clear();
337 
338  if ( m_pRootNode == NULL )
339  return NULL;
340 
341  nodeProcessExtent(m_pRootNode, ext);
342 
343  if ( m_theIntersectedLeaves.size() == 0 )
344  return NULL;
345 
346  return &m_theIntersectedLeaves;
347  }
348 
350  {
351  m_theIntersectedLeaves.clear();
352 
353  if ( m_pRootNode == NULL )
354  return NULL;
355 
356  nodeProcessPoint(m_pRootNode, pt);
357 
358  if ( m_theIntersectedLeaves.size() == 0 )
359  return NULL;
360 
361  return &m_theIntersectedLeaves;
362  }
363 
364 private:
365 
366  // internal recursive method for building the tree
367  void constructChilds(OdGiExtentsSpaceNode<E,O>* pParentNode, int axislevel, int curDepth, int nTypeOfObjects)
368  {
369  if ( pParentNode == NULL )
370  return;
371 
372  if ( curDepth == 0 )
373  {
374  // means we have a leave
375  m_Leaves.push_back(pParentNode);
376  return;
377  }
378 
379  //define the left part extents
380  E leftChildExtents;
381 
382  P leftBounPoint = pParentNode->m_extents.maxPoint();
383  switch ( axislevel )
384  {
385  case 3:
386  middlez(pParentNode->m_extents.maxPoint(), pParentNode->m_extents.minPoint(), leftBounPoint);
387  break;
388  case 2:
389  leftBounPoint.x = (pParentNode->m_extents.maxPoint().x + pParentNode->m_extents.minPoint().x)/2.;
390  break;
391  case 1:
392  leftBounPoint.y = (pParentNode->m_extents.maxPoint().y + pParentNode->m_extents.minPoint().y)/2.;
393  break;
394  }
395 
396  leftChildExtents.set(pParentNode->m_extents.minPoint(), leftBounPoint);
397 
398  // create left child
399  pParentNode->m_pLeftChild = new OdGiExtentsSpaceNode<E,O>(pParentNode, leftChildExtents, axislevel > 1 ? pParentNode->m_iDepth : pParentNode->m_iDepth + 1, nTypeOfObjects);
400  m_Nodes.push_back(pParentNode->m_pLeftChild);
401 
402  // go deeper
403  if ( axislevel > 1 )
404  constructChilds(pParentNode->m_pLeftChild, axislevel-1, curDepth, nTypeOfObjects);
405  else
406  constructChilds(pParentNode->m_pLeftChild, NUM_AXIS, curDepth-1, nTypeOfObjects);
407 
408  //define the right part extents
409  E rightChildExtents;
410 
411  P rightBounPoint = pParentNode->m_extents.minPoint();
412  switch ( axislevel )
413  {
414  case 3:
415  middlez(pParentNode->m_extents.maxPoint(), pParentNode->m_extents.minPoint(), rightBounPoint);
416  break;
417  case 2:
418  rightBounPoint.x = (pParentNode->m_extents.maxPoint().x + pParentNode->m_extents.minPoint().x)/2.;
419  break;
420  case 1:
421  rightBounPoint.y = (pParentNode->m_extents.maxPoint().y + pParentNode->m_extents.minPoint().y)/2.;
422  break;
423  }
424 
425  rightChildExtents.set(rightBounPoint, pParentNode->m_extents.maxPoint());
426 
427  // create right child
428  pParentNode->m_pRightChild = new OdGiExtentsSpaceNode<E,O>(pParentNode, rightChildExtents, axislevel > 1 ? pParentNode->m_iDepth : pParentNode->m_iDepth + 1, nTypeOfObjects);
429  m_Nodes.push_back(pParentNode->m_pRightChild);
430 
431  // go deeper
432  if ( axislevel > 1 )
433  constructChilds(pParentNode->m_pRightChild, axislevel-1, curDepth, nTypeOfObjects);
434  else
435  constructChilds(pParentNode->m_pRightChild, NUM_AXIS, curDepth-1, nTypeOfObjects);
436 
437  return;
438  }
439 
440  // internal recursive method for process objects
441  void nodeProcessObject(OdGiExtentsSpaceNode<E,O>* pNode, O* pObject, int iObjectType, bool bCheckTheSame, const OdGeTol& tol = OdGeContext::gTol)
442  {
443  if ( pNode == NULL || pObject == NULL )
444  return;
445 
446  bool bIntersect = pObject->isInExtents(pNode->m_extents);
447 
448  if ( bIntersect )
449  {
450  if ( pNode->isLeave() )
451  {
452  if ( m_pCallback )
453  {
454  if ( !m_pCallback->notifyObjectPlacedAtNode(pObject, iObjectType, pNode) )
455  return;
456  }
457 
458  OdVector<O*, OdMemoryAllocator<O*> >* pNodeObjects = pNode->getObjectPointersPtr(iObjectType);
459  if ( pNodeObjects == NULL ) // initialize object list if need
460  {
461  if ( m_iMaxNodeObjects > 0 )
462  pNodeObjects = pNode->initObjectList(iObjectType, m_iMaxNodeObjects+1);
463  else
464  pNodeObjects = pNode->initObjectList(iObjectType, 50);
465  }
466 
467  if ( pNodeObjects )
468  {
469  if ( bCheckTheSame ) // check that we already have the same object
470  {
471  OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator itNodes = pNodeObjects->begin();
472  OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator itNodesEnd = pNodeObjects->end();
473  while ( itNodes != itNodesEnd )
474  {
475  O* pObjectInList = *itNodes;
476  if ( pObjectInList )
477  {
478  if ( pObjectInList->isEqual(pObject, tol) )
479  {
480  m_theSameObjects.push_back(pObjectInList);
481  return;
482  }
483  }
484  ++itNodes;
485  }
486  pNodeObjects->push_back( pObject );
487  }
488  else // simply add
489  {
490  pNodeObjects->push_back( pObject );
491  }
492  }
493 
494  //adaptive case
495  if ( m_bIsAdaptive && pNodeObjects->size() > m_iMaxNodeObjects && pNode->m_iDepth <= MAX_DEPTH )
496  {
497  // remove current node from leaves
498  m_Leaves.remove(pNode);
499 
500  //try to make additional split
501  constructChilds(pNode, NUM_AXIS, 1/*one step deeper*/, pNode->m_iObjectsTypes);
502 
503  //put down the objects
504  for ( int i = 0; i < pNode->m_iObjectsTypes; i++)
505  {
506  pNodeObjects = pNode->getObjectPointersPtr(i);
507  if ( pNodeObjects )
508  {
509  OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator it = pNodeObjects->begin();
510  OD_TYPENAME OdVector<O*, OdMemoryAllocator<O*> >::iterator itEnd = pNodeObjects->end();
511  while ( it != itEnd )
512  {
513  O* pObjectInList = *it;
514 
515  if ( pObjectInList )
516  {
517  nodeProcessObject(pNode->m_pLeftChild, pObjectInList, i, false, tol);
518  nodeProcessObject(pNode->m_pRightChild, pObjectInList, i, false, tol);
519  }
520 
521  ++it;
522  }
523  }
524  } //eo for...
525  //remove information about the objects in the nodes
526  pNode->releaseObjectsStore();
527  }
528  }
529  else
530  {
531  nodeProcessObject(pNode->m_pLeftChild, pObject, iObjectType, bCheckTheSame, tol);
532  nodeProcessObject(pNode->m_pRightChild, pObject, iObjectType, bCheckTheSame, tol);
533  }
534  }
535 
536  return;
537  }
538 
539  // internal recursive method for process extents
540  void nodeProcessExtent(OdGiExtentsSpaceNode<E,O>* pNode, E& ext)
541  {
542  if ( pNode == NULL || !ext.isValidExtents() )
543  return;
544 
545  E isect;
546  ext.intersectWith(pNode->m_extents, &isect);
547 
548  if ( isect.isValidExtents() )
549  {
550  if ( pNode->isLeave() )
551  {
552  m_theIntersectedLeaves.push_back(pNode);
553  }
554  else
555  {
556  nodeProcessExtent(pNode->m_pLeftChild, ext);
557  nodeProcessExtent(pNode->m_pRightChild, ext);
558  }
559  }
560 
561  return;
562  }
563 
564  // internal recursive method for process point
565  void nodeProcessPoint(OdGiExtentsSpaceNode<E,O>* pNode, const P& pt)
566  {
567  if ( pNode == NULL )
568  return;
569 
570  if ( pNode->m_extents.contains(pt) )
571  {
572  if ( pNode->isLeave() )
573  {
574  m_theIntersectedLeaves.push_back(pNode);
575  }
576  else
577  {
578  nodeProcessPoint(pNode->m_pLeftChild, pt);
579  nodeProcessPoint(pNode->m_pRightChild, pt);
580  }
581  }
582 
583  return;
584  }
585 
586  void middlez(const OdGePoint2d& pt1, const OdGePoint2d& pt2, OdGePoint2d& ptRes)
587  {
588  return;
589  }
590 
591 
592  void middlez(const OdGePoint3d& pt1, const OdGePoint3d& pt2, OdGePoint3d& ptRes)
593  {
594  ptRes.z = (pt1.z + pt2.z)/2.;
595  return;
596  }
597 };
598 
601 
602 
611 {
613 
614  // set of the IDs of edges which have this vertex
615  std::set<OdUInt64> m_edges;
616 
617  // set of the IDs of invisible edges which have this vertex
618  std::set<OdUInt64> m_invisibleedges;
619 
620  // need for constructing the chain polylines
621  bool m_bVisited;
622 
623 public:
624 
625  //point
627 
628  //constructor
630  {
631  m_pt.set(pt.x, pt.y, pt.z);
632  m_bVisited = false;
633  }
634 
636  {
637  m_edges.clear();
638  m_invisibleedges.clear();
639  }
640 
641  void addEdge(OdUInt64 ID)
642  {
643  m_edges.insert(ID);
644  }
645 
647  {
648  m_invisibleedges.insert(ID);
649  }
650 
652  {
653  m_invisibleedges.erase(ID);
654  }
655 
656  // check that the edge is in extents (currently not used)
657  bool isInExtents(OdGeExtents3d& extents) const
658  {
659  OdGeTol tol;
660  if (extents.contains( m_pt, tol ) )
661  return true;
662 
663  return false;
664  }
665 
666  bool isInExtents(OdGeExtents2d& extents) const {return false;}
667 
668  // check that objects are equal
670  {
671  OdGiExtents3dSpacePoint* pObjectVertex = dynamic_cast<OdGiExtents3dSpacePoint*>(pObject);
672 
673  if ( pObjectVertex == NULL )
674  return false;
675 
676  if ( pObjectVertex->m_pt.isEqualTo(m_pt, tol) )
677  return true;
678 
679  return false;
680  }
681 
683  {
684  return m_edges.size();
685  }
686 
687  const std::set<OdUInt64>* getEdges(){return &m_edges;}
688  const std::set<OdUInt64>* getInvisilbeEdges(){return & m_invisibleedges;}
689 
690  void setVisited(bool bVisit){m_bVisited = bVisit;}
691  bool isVisited(){return m_bVisited;}
692 
693 };
694 
703 {
704 
705 public:
706  //two vertices
709  bool m_bVisited; // need for constructing the pathes
710  bool m_bIsVisible; // means that the edge is not visible
711 
712  //constructor
714  {
715  m_iVert1 = pt1.getID();
716  m_iVert2 = pt2.getID();
717 
718  if ( uniqueID >= 0 )
719  {
720  pt1.m_edges.insert(uniqueID);
721  pt2.m_edges.insert(uniqueID);
722  }
723 
724  m_bVisited = false;
725  m_bIsVisible = true;
726  }
727 
728  void setVisited(bool bVisit){m_bVisited = bVisit;}
729  bool isVisited(){return m_bVisited;}
730 
732  {
733  if ( iDfirst == m_iVert1 )
734  return m_iVert2;
735 
736  return m_iVert1;
737  }
738 
739  bool isInExtents(OdGeExtents3d& extents) const {return false;}
740  bool isInExtents(OdGeExtents2d& extents) const {return false;}
741  bool isEqual(OdGiExtentsSpaceObject* pObject, const OdGeTol& tol = OdGeContext::gTol) const{return false;}
742 };
743 
752 {
753 protected:
754 
756 
757 public:
758 
759  //constructor
761 
763 
764  virtual void addVertex(OdGiExtents3dSpacePoint* pVertex)
765  {
766  vertices.push_back(pVertex);
767  }
768 
771  {
772  OdGiExtents3dSpacePoint* ptFirst = vertices.front();
773  OdGiExtents3dSpacePoint* ptSecond = vertices.back();
774  if ( ptFirst == ptSecond && vertices.size() > 1)
775  return vertices.size()-1;
776 
777  return vertices.size();
778  }
779 
780  void getPoints(OdGePoint3d *pPoints)
781  {
782  if ( pPoints == NULL )
783  return;
784 
787  OdUInt32 ind = 0;
788  while ( it != itEnd )
789  {
790  OdGiExtents3dSpacePoint* pVertex = *it;
791  if ( pVertex )
792  {
793  pPoints[ind].set(pVertex->m_pt.x, pVertex->m_pt.y, pVertex->m_pt.z);
794  ind++;
795  }
796  ++it;
797  }
798  }
799 
801  {
802  if ( pPoints == NULL )
803  return;
804 
807 
808  OdGiExtents3dSpacePoint* ptFirst = vertices.front();
809  OdGiExtents3dSpacePoint* ptSecond = vertices.back();
810  if ( ptFirst == ptSecond && vertices.size() > 1 )
811  --itEnd;
812 
813  OdUInt32 ind = 0;
814  while ( it != itEnd )
815  {
816  OdGiExtents3dSpacePoint* pVertex = *it;
817  if ( pVertex )
818  {
819  pPoints[ind].set(pVertex->m_pt.x, pVertex->m_pt.y, pVertex->m_pt.z);
820  ind++;
821  }
822  ++it;
823  }
824  }
825 
826  void getPoints(OdGePoint3dVector& pts)
827  {
828  getPoints(pts.asArrayPtr());
829  }
830 
831  void getPoints_closed(OdGePoint3dVector& pts)
832  {
833  getPoints_closed(pts.asArrayPtr());
834  }
835 
836  bool isInExtents(OdGeExtents3d& extents) const {return false;}
837  bool isInExtents(OdGeExtents2d& extents) const {return false;}
838  bool isEqual(OdGiExtentsSpaceObject* pObject, const OdGeTol& tol = OdGeContext::gTol) const{return false;}
839 };
840 
841 
843 {
844  // next start vertex for finding the path
846  {
847  OdGiExtents3dSpacePoint* pStartVertex = NULL;
848 
849  //1. Try to find leafs
850  if ( leafs.size() > 0 )
851  {
852  OdList<OdGiExtents3dSpacePoint*>::iterator itLeafs = leafs.begin();
853  OdList<OdGiExtents3dSpacePoint*>::iterator itLeafsEnd = leafs.end();
854  while ( itLeafs != itLeafsEnd )
855  {
856  OdGiExtents3dSpacePoint* pLeaf = *itLeafs;
857  if ( pLeaf && !pLeaf->isVisited() )
858  {
859  pStartVertex = pLeaf;
860  break;
861  }
862  ++itLeafs;
863  }
864  }
865 
866  //2. Try to find first not visited vertex
867  if ( pStartVertex == NULL )
868  {
869  int iVertNumber = points.size();
870  for (OdUInt64 i = 0; i < iVertNumber; i++)
871  {
872  OdGiExtents3dSpacePoint* pVert = points[i];
873  if ( pVert && !pVert->isVisited() )
874  {
875  pStartVertex = pVert;
876  break;
877  }
878  }
879  }
880 
881  return pStartVertex;
882  }
883 
884 template <class E>
885 static OdGiExtents3dSpaceEdge* getFirstUnvisitedEdge(OdGiExtents3dSpacePoint* pVertex, OdArray<E*>& edges)
886 {
887  if ( pVertex == NULL )
888  return NULL;
889 
890  const std::set<OdUInt64>* pEdges = pVertex->getEdges();
891  if ( pEdges == NULL )
892  return NULL;
893 
894  std::set<OdUInt64>::const_iterator itEdge = pEdges->begin();
895  std::set<OdUInt64>::const_iterator itEdgeEnd = pEdges->end();
896  while ( itEdge != itEdgeEnd )
897  {
898  OdUInt64 edgeID = *itEdge;
899  if ( edgeID < edges.size() )
900  {
901  OdGiExtents3dSpaceEdge* pEdge = dynamic_cast<OdGiExtents3dSpaceEdge*>(edges[edgeID]);
902  if ( pEdge && !pEdge->isVisited() && pEdge->m_bIsVisible )
903  return pEdge;
904  }
905 
906  ++itEdge;
907  }
908 
909  return NULL;
910 }
911 
912  // construct a path from start vertex
913 template <class T, class E>
914 static void constructPath(OdGiExtents3dSpacePoint* pStartVertex, OdArray<OdGiExtents3dSpacePoint*>& points,
915  OdArray<E*>& edges, OdList<T*>& polylines)
916 {
917  if ( pStartVertex == NULL )
918  return;
919 
920  OdGiExtents3dSpacePoint* pFirstVertex = pStartVertex;
921 
922  T *pPath = NULL;
923  //loop
924  while(pFirstVertex)
925  {
926  //get unvisited edge
927  OdGiExtents3dSpaceEdge* pFirstEdge = getFirstUnvisitedEdge(pFirstVertex, edges);
928  if ( pFirstEdge == NULL )
929  {
930  pFirstVertex->setVisited(true);
931  break;
932  }
933 
934  // get the second vertex of the edge
935  OdGiExtents3dSpacePoint* pNextVertex = points[pFirstEdge->getSecondVertex(pFirstVertex->getID())];
936 
937  //init the path
938  if ( pPath == NULL )
939  {
940  pPath = new T(0);
941  pPath->addVertex(pFirstVertex);
942  }
943  pPath->addVertex(pNextVertex);
944 
945  pFirstVertex->setVisited(true);
946  pNextVertex->setVisited(true);
947  pFirstEdge->setVisited(true);
948 
949  pFirstVertex = pNextVertex;
950  }
951 
952  if ( pPath )
953  polylines.push_back(pPath);
954 
955  return;
956 }
957 
958 public:
959 template <class T, class E>
961 {
962  //1. Find the vertices with power 1 if exists
964  int iVertNumber = points.size();
965  for (OdUInt64 i = 0; i < iVertNumber; i++)
966  {
967  OdGiExtents3dSpacePoint* pVert = points[i];
968  if ( pVert )
969  {
970  OdUInt64 vPower = pVert->getPower();
971  if ( vPower == 1 )
972  leafVertices.push_back(pVert);
973  else if ( vPower == 0 )
974  pVert->setVisited(true);
975  }
976  }
977 
978  //2. run loop for construction the pathes
979  OdGiExtents3dSpacePoint* pStartVertex = getNextStartVertex(points, leafVertices);
980  while ( pStartVertex )
981  {
982  constructPath(pStartVertex, points, edges, polylines);
983  pStartVertex = getNextStartVertex(points, leafVertices);
984  }
985 
986  return polylines.size();
987 }
988 };
989 
990 #include "TD_PackPop.h"
991 
992 #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 NULL
Definition: GsProperties.h:177
#define OD_TYPENAME
Definition: OdPlatform.h:581
unsigned int OdUInt32
int OdInt
E
Definition: SysVarDefs.h:422
size_type size() const
Definition: OdArray.h:893
bool contains(const OdGePoint3d &point, const OdGeTol &tol=OdGeContext::gTol) const
Definition: GeExtents3d.h:375
OdGePoint3d & set(double xx, double yy, double zz)
Definition: GePoint3d.h:337
bool isEqualTo(const OdGePoint3d &point, const OdGeTol &tol=OdGeContext::gTol) const
double z
Definition: GePoint3d.h:369
double y
Definition: GePoint3d.h:368
double x
Definition: GePoint3d.h:367
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)
const std::set< OdUInt64 > * getEdges()
bool isInExtents(OdGeExtents2d &extents) const
OdGiExtents3dSpacePoint(const OdGePoint3d &pt, OdUInt64 uniqueID)
bool isEqual(OdGiExtentsSpaceObject *pObject, const OdGeTol &tol=OdGeContext::gTol) const
void removeInvisible(OdUInt64 ID)
void addInvisible(OdUInt64 ID)
bool isInExtents(OdGeExtents3d &extents) const
void setVisited(bool bVisit)
const std::set< OdUInt64 > * getInvisilbeEdges()
static OdInt64 calculateChainPolylinesFromEdges(OdArray< OdGiExtents3dSpacePoint * > &points, OdArray< E * > &edges, OdList< T * > &polylines)
OdVector< O *, OdMemoryAllocator< O * > > * getObjectPointersPtr(int iType)
OdGiExtentsSpaceNode(OdGiExtentsSpaceNode *parent, E &extents, int nDepth, int nTypeOfObjects)
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
void setCallback(OdGiExtentsSpaceTreeCallback< E, O > *pCallback)
OdList< OdGiExtentsSpaceNode< E, O > * > * retrieveLeaves()
OdList< OdGiExtentsSpaceNode< E, O > * > * getExtentsLeaves(E &ext)
bool getRootExtents(E &exts)
O * processObject(O *pObject, int iObjectType, bool bCheckTheSame=false, const OdGeTol &tol=OdGeContext::gTol)
OdList< OdGiExtentsSpaceNode< E, O > * > * getPointLeaves(const P &pt)
void setAdaptive(bool bAdaptive)
void buildTree(E &extents, int nTypeOfObjects, OdInt depth=2)
void setMaxNodeObjects(OdUInt64 nObjects)
Definition: Int64.h:43
Definition: OdList.h:45
OdVector & setGrowLength(int growLength)
Definition: OdVector.h:1160
iterator begin()
Definition: OdVector.h:659
void push_back(const T &value)
Definition: OdVector.h:926
size_type size() const
Definition: OdVector.h:866
OdVector & setPhysicalLength(size_type physicalLength)
Definition: OdVector.h:1141
iterator end()
Definition: OdVector.h:671
static GE_STATIC_EXPORT OdGeTol gTol
Definition: GeGbl.h:60