//--------------------------------------------------------- size_t CSG_PRQuadTree::_Select_Nearest_Points(CSG_Array &Selection, double x, double y, size_t maxPoints, double Radius, int iQuadrant) const { if( Selection.Get_Value_Size() != sizeof(TLeaf) ) { Selection.Create(sizeof(TLeaf), 0, SG_ARRAY_GROWTH_3); } else { Selection.Set_Array(0, false); } if( m_pRoot ) { double Distance; if( maxPoints < 1 ) { maxPoints = m_nPoints; } if( iQuadrant != 4 ) { _Select_Nearest_Points(Selection, m_pRoot, x, y, Distance = 0.0, Radius, maxPoints, iQuadrant); } else // if( iQuadrant == 4 ) // quadrant-wise search { for(iQuadrant=0; iQuadrant<4; iQuadrant++) { _Select_Nearest_Points(Selection, m_pRoot, x, y, Distance = 0.0, Radius, maxPoints, iQuadrant); } } } return( Selection.Get_Size() ); }
//--------------------------------------------------------- inline bool CSG_PRQuadTree::_Add_Selected(CSG_Array &Selection, CSG_PRQuadTree_Leaf *pLeaf, double Distance) const { if( Selection.Inc_Array() ) { TLeaf *pL = (TLeaf *)Selection.Get_Entry(Selection.Get_Size() - 1); pL->pLeaf = pLeaf; pL->Distance = Distance; return( true ); } return( false ); }
//--------------------------------------------------------- size_t CSG_PRQuadTree::Get_Nearest_Points(CSG_Points_Z &Points, double x, double y, size_t maxPoints, double Radius, int iQuadrant) const { CSG_Array Selection; _Select_Nearest_Points(Selection, x, y, maxPoints, Radius, iQuadrant); Points.Clear(); for(size_t i=0; i<Selection.Get_Size(); i++) { CSG_PRQuadTree_Leaf *pLeaf = _Get_Selected(Selection, i)->pLeaf; Points.Add(pLeaf->Get_X(), pLeaf->Get_Y(), pLeaf->Get_Z()); } return( Points.Get_Count() ); }
//--------------------------------------------------------- void CSG_PRQuadTree::_Select_Nearest_Points(CSG_Array &Selection, CSG_PRQuadTree_Item *pItem, double x, double y, double &Distance, double Radius, size_t maxPoints, int iQuadrant) const { //----------------------------------------------------- if( pItem->is_Leaf() ) { CSG_PRQuadTree_Leaf *pLeaf = (CSG_PRQuadTree_Leaf *)pItem; if( _Quadrant_Contains(x, y, iQuadrant, pLeaf->Get_Point()) == false ) { return; } double d = SG_Get_Distance(x, y, pLeaf->Get_X(), pLeaf->Get_Y(), m_bPolar); if( Radius > 0.0 && Radius < d ) { return; } //------------------------------------------------- if( Selection.Get_Size() < maxPoints ) { if( Distance < d ) { Distance = d; } _Add_Selected(Selection, pLeaf, d); } else if( d < Distance ) { size_t i; for(i=0; i<Selection.Get_Size(); i++) { if( Distance <= _Get_Selected(Selection, i)->Distance ) { _Set_Selected(Selection, i, pLeaf, d); break; } } for(i=0, Distance=d; i<maxPoints; i++) { if( Distance < _Get_Selected(Selection, i)->Distance ) { Distance = _Get_Selected(Selection, i)->Distance; } } } } //----------------------------------------------------- else // if( pItem->is_Node() ) { int i; CSG_PRQuadTree_Item *pChild; for(i=0; i<4; i++) { if( (pChild = ((CSG_PRQuadTree_Node *)pItem)->Get_Child(i)) != NULL && pChild->Contains(x, y) == true ) { _Select_Nearest_Points(Selection, pChild, x, y, Distance, Radius, maxPoints, iQuadrant); } } for(i=0; i<4; i++) { if( (pChild = ((CSG_PRQuadTree_Node *)pItem)->Get_Child(i)) != NULL && pChild->Contains(x, y) == false ) { if( _Radius_Intersects(x, y, Radius, iQuadrant, pChild) ) { if( Get_Selected_Count() < maxPoints || ( Distance > (x < pChild->Get_xCenter() ? pChild->Get_xMin() - x : x - pChild->Get_xMax()) && Distance > (y < pChild->Get_yCenter() ? pChild->Get_yMin() - y : y - pChild->Get_yMax()) ) ) { _Select_Nearest_Points(Selection, pChild, x, y, Distance, Radius, maxPoints, iQuadrant); } } } } } }