1
// Spatial Index Library
3
// Copyright (C) 2002 Navel Ltd.
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
#include "../spatialindex/SpatialIndexImpl.h"
30
using namespace SpatialIndex::RTree;
33
// Tools::IObject interface
35
Tools::IObject* Node::clone()
37
throw Tools::NotSupportedException( "IObject::clone should never be called." );
41
// Tools::ISerializable interface
43
unsigned long Node::getByteArraySize()
49
( m_children *( m_pTree->m_dimension * sizeof( double ) * 2 + sizeof( long ) + sizeof( unsigned long ) ) ) +
51
( 2 * m_pTree->m_dimension * sizeof( double ) ) );
54
void Node::loadFromByteArray( const byte* ptr )
56
m_nodeMBR = m_pTree->m_infiniteRegion;
58
// skip the node type information, it is not needed.
59
ptr += sizeof( long );
61
memcpy( &m_level, ptr, sizeof( long ) );
62
ptr += sizeof( long );
64
memcpy( &m_children, ptr, sizeof( long ) );
65
ptr += sizeof( long );
67
for ( unsigned long cChild = 0; cChild < m_children; cChild++ )
69
m_ptrMBR[cChild] = m_pTree->m_regionPool.acquire();
70
*( m_ptrMBR[cChild] ) = m_pTree->m_infiniteRegion;
72
memcpy( m_ptrMBR[cChild]->m_pLow, ptr, m_pTree->m_dimension * sizeof( double ) );
73
ptr += m_pTree->m_dimension * sizeof( double );
74
memcpy( m_ptrMBR[cChild]->m_pHigh, ptr, m_pTree->m_dimension * sizeof( double ) );
75
ptr += m_pTree->m_dimension * sizeof( double );
76
memcpy( &( m_pIdentifier[cChild] ), ptr, sizeof( long ) );
77
ptr += sizeof( long );
79
memcpy( &( m_pDataLength[cChild] ), ptr, sizeof( unsigned long ) );
80
ptr += sizeof( unsigned long );
82
if ( m_pDataLength[cChild] > 0 )
84
m_totalDataLength += m_pDataLength[cChild];
85
m_pData[cChild] = new byte[m_pDataLength[cChild]];
86
memcpy( m_pData[cChild], ptr, m_pDataLength[cChild] );
87
ptr += m_pDataLength[cChild];
94
//m_nodeMBR.combineRegion(*(m_ptrMBR[cChild]));
97
memcpy( m_nodeMBR.m_pLow, ptr, m_pTree->m_dimension * sizeof( double ) );
98
ptr += m_pTree->m_dimension * sizeof( double );
99
memcpy( m_nodeMBR.m_pHigh, ptr, m_pTree->m_dimension * sizeof( double ) );
100
//ptr += m_pTree->m_dimension * sizeof(double);
103
void Node::storeToByteArray( byte** data, unsigned long& len )
105
len = getByteArraySize();
107
*data = new byte[len];
112
if ( m_level == 0 ) type = PersistentLeaf;
113
else type = PersistentIndex;
115
memcpy( ptr, &type, sizeof( long ) );
116
ptr += sizeof( long );
118
memcpy( ptr, &m_level, sizeof( long ) );
119
ptr += sizeof( long );
121
memcpy( ptr, &m_children, sizeof( long ) );
122
ptr += sizeof( long );
124
for ( unsigned long cChild = 0; cChild < m_children; cChild++ )
126
memcpy( ptr, m_ptrMBR[cChild]->m_pLow, m_pTree->m_dimension * sizeof( double ) );
127
ptr += m_pTree->m_dimension * sizeof( double );
128
memcpy( ptr, m_ptrMBR[cChild]->m_pHigh, m_pTree->m_dimension * sizeof( double ) );
129
ptr += m_pTree->m_dimension * sizeof( double );
130
memcpy( ptr, &( m_pIdentifier[cChild] ), sizeof( long ) );
131
ptr += sizeof( long );
133
memcpy( ptr, &( m_pDataLength[cChild] ), sizeof( unsigned long ) );
134
ptr += sizeof( unsigned long );
136
if ( m_pDataLength[cChild] > 0 )
138
memcpy( ptr, m_pData[cChild], m_pDataLength[cChild] );
139
ptr += m_pDataLength[cChild];
143
// store the node MBR for efficiency. This increases the node size a little bit.
144
memcpy( ptr, m_nodeMBR.m_pLow, m_pTree->m_dimension * sizeof( double ) );
145
ptr += m_pTree->m_dimension * sizeof( double );
146
memcpy( ptr, m_nodeMBR.m_pHigh, m_pTree->m_dimension * sizeof( double ) );
147
//ptr += m_pTree->m_dimension * sizeof(double);
149
assert( len == ( ptr - *data ) + m_pTree->m_dimension * sizeof( double ) );
153
// SpatialIndex::IEntry interface
155
long Node::getIdentifier() const
160
void Node::getShape( IShape** out ) const
162
*out = new Region( m_nodeMBR );
166
// SpatialIndex::INode interface
168
unsigned long Node::getChildrenCount() const
173
long Node::getChildIdentifier( unsigned long index ) const
175
if ( index < 0 || index >= m_children ) throw Tools::IndexOutOfBoundsException( index );
177
return m_pIdentifier[index];
180
void Node::getChildShape( unsigned long index, IShape** out ) const
182
if ( index < 0 || index >= m_children ) throw Tools::IndexOutOfBoundsException( index );
184
*out = new Region( *( m_ptrMBR[index] ) );
187
unsigned long Node::getLevel() const
192
bool Node::isLeaf() const
194
return ( m_level == 0 );
197
bool Node::isIndex() const
199
return ( m_level != 0 );
216
m_totalDataLength( 0 )
221
// MSVC seems to find RTree* pTree ambiguous
222
Node::Node( SpatialIndex::RTree::RTree* pTree, long id, unsigned long level, unsigned long capacity ) :
224
Node::Node( RTree* pTree, long id, unsigned long level, unsigned long capacity ) :
230
m_capacity( capacity ),
235
m_totalDataLength( 0 )
237
m_nodeMBR.makeInfinite( m_pTree->m_dimension );
241
m_pDataLength = new unsigned long[m_capacity + 1];
242
m_pData = new byte*[m_capacity + 1];
243
m_ptrMBR = new RegionPtr[m_capacity + 1];
244
m_pIdentifier = new long[m_capacity + 1];
248
delete[] m_pDataLength;
251
delete[] m_pIdentifier;
260
for ( unsigned long cChild = 0; cChild < m_children; cChild++ )
262
if ( m_pData[cChild] != 0 ) delete[] m_pData[cChild];
268
delete[] m_pDataLength;
270
delete[] m_pIdentifier;
273
Node& Node::operator=( const Node & n )
275
throw Tools::IllegalStateException( "operator =: This should never be called." );
278
void Node::insertEntry( unsigned long dataLength, byte* pData, Region& mbr, long id )
280
assert( m_children < m_capacity );
282
m_pDataLength[m_children] = dataLength;
283
m_pData[m_children] = pData;
284
m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire();
285
*( m_ptrMBR[m_children] ) = mbr;
286
m_pIdentifier[m_children] = id;
288
m_totalDataLength += dataLength;
291
m_nodeMBR.combineRegion( mbr );
294
void Node::deleteEntry( unsigned long index )
296
assert( index >= 0 && index < m_children );
298
// cache it, since I might need it for "touches" later.
299
RegionPtr ptrR = m_ptrMBR[index];
301
m_totalDataLength -= m_pDataLength[index];
302
if ( m_pData[index] != 0 ) delete[] m_pData[index];
304
if ( m_children > 1 && index != m_children - 1 )
306
m_pDataLength[index] = m_pDataLength[m_children - 1];
307
m_pData[index] = m_pData[m_children - 1];
308
m_ptrMBR[index] = m_ptrMBR[m_children - 1];
309
m_pIdentifier[index] = m_pIdentifier[m_children - 1];
314
// WARNING: index has now changed. Do not use it below here.
316
if ( m_children == 0 )
318
m_nodeMBR = m_pTree->m_infiniteRegion;
320
else if ( m_pTree->m_bTightMBRs && m_nodeMBR.touchesRegion( *ptrR ) )
322
for ( unsigned long cDim = 0; cDim < m_nodeMBR.m_dimension; cDim++ )
324
m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max();
325
m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max();
327
for ( unsigned long cChild = 0; cChild < m_children; cChild++ )
329
m_nodeMBR.m_pLow[cDim] = std::min( m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim] );
330
m_nodeMBR.m_pHigh[cDim] = std::max( m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim] );
336
bool Node::insertData( unsigned long dataLength, byte* pData, Region& mbr, long id, stack<long>& pathBuffer, byte* overflowTable )
338
if ( m_children < m_capacity )
340
bool adjusted = false;
342
// this has to happen before insertEntry modifies m_nodeMBR.
343
bool b = m_nodeMBR.containsRegion( mbr );
345
insertEntry( dataLength, pData, mbr, id );
346
m_pTree->writeNode( this );
348
if (( ! b ) && ( ! pathBuffer.empty() ) )
350
long cParent = pathBuffer.top(); pathBuffer.pop();
351
NodePtr ptrN = m_pTree->readNode( cParent );
352
Index* p = static_cast<Index*>( ptrN.get() );
353
p->adjustTree( this, pathBuffer );
359
else if ( m_pTree->m_treeVariant == RV_RSTAR && ( ! pathBuffer.empty() ) && overflowTable[m_level] == 0 )
361
overflowTable[m_level] = 1;
363
vector<long> vReinsert, vKeep;
364
reinsertData( dataLength, pData, mbr, id, vReinsert, vKeep );
366
unsigned long lReinsert = vReinsert.size();
367
unsigned long lKeep = vKeep.size();
369
byte** reinsertdata = 0;
370
RegionPtr* reinsertmbr = 0;
371
long* reinsertid = 0;
372
unsigned long* reinsertlen = 0;
374
RegionPtr* keepmbr = 0;
376
unsigned long* keeplen = 0;
380
reinsertdata = new byte*[lReinsert];
381
reinsertmbr = new RegionPtr[lReinsert];
382
reinsertid = new long[lReinsert];
383
reinsertlen = new unsigned long[lReinsert];
385
keepdata = new byte*[m_capacity + 1];
386
keepmbr = new RegionPtr[m_capacity + 1];
387
keepid = new long[m_capacity + 1];
388
keeplen = new unsigned long[m_capacity + 1];
392
delete[] reinsertdata;
393
delete[] reinsertmbr;
395
delete[] reinsertlen;
403
unsigned long cIndex;
405
for ( cIndex = 0; cIndex < lReinsert; cIndex++ )
407
reinsertlen[cIndex] = m_pDataLength[vReinsert[cIndex]];
408
reinsertdata[cIndex] = m_pData[vReinsert[cIndex]];
409
reinsertmbr[cIndex] = m_ptrMBR[vReinsert[cIndex]];
410
reinsertid[cIndex] = m_pIdentifier[vReinsert[cIndex]];
413
for ( cIndex = 0; cIndex < lKeep; cIndex++ )
415
keeplen[cIndex] = m_pDataLength[vKeep[cIndex]];
416
keepdata[cIndex] = m_pData[vKeep[cIndex]];
417
keepmbr[cIndex] = m_ptrMBR[vKeep[cIndex]];
418
keepid[cIndex] = m_pIdentifier[vKeep[cIndex]];
421
delete[] m_pDataLength;
424
delete[] m_pIdentifier;
426
m_pDataLength = keeplen;
429
m_pIdentifier = keepid;
431
m_totalDataLength = 0;
433
for ( unsigned long cChild = 0; cChild < m_children; cChild++ ) m_totalDataLength += m_pDataLength[cChild];
435
for ( unsigned long cDim = 0; cDim < m_nodeMBR.m_dimension; cDim++ )
437
m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max();
438
m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max();
440
for ( unsigned long cChild = 0; cChild < m_children; cChild++ )
442
m_nodeMBR.m_pLow[cDim] = std::min( m_nodeMBR.m_pLow[cDim], m_ptrMBR[cChild]->m_pLow[cDim] );
443
m_nodeMBR.m_pHigh[cDim] = std::max( m_nodeMBR.m_pHigh[cDim], m_ptrMBR[cChild]->m_pHigh[cDim] );
447
m_pTree->writeNode( this );
449
// Divertion from R*-Tree algorithm here. First adjust
450
// the path to the root, then start reinserts, to avoid complicated handling
451
// of changes to the same node from multiple insertions.
452
long cParent = pathBuffer.top(); pathBuffer.pop();
453
NodePtr ptrN = m_pTree->readNode( cParent );
454
Index* p = static_cast<Index*>( ptrN.get() );
455
p->adjustTree( this, pathBuffer );
457
for ( cIndex = 0; cIndex < lReinsert; cIndex++ )
459
m_pTree->insertData_impl(
460
reinsertlen[cIndex], reinsertdata[cIndex],
461
*( reinsertmbr[cIndex] ), reinsertid[cIndex],
462
m_level, overflowTable );
465
delete[] reinsertdata;
466
delete[] reinsertmbr;
468
delete[] reinsertlen;
476
split( dataLength, pData, mbr, id, n, nn );
478
if ( pathBuffer.empty() )
480
n->m_level = m_level;
481
nn->m_level = m_level;
482
n->m_identifier = -1;
483
nn->m_identifier = -1;
484
m_pTree->writeNode( n.get() );
485
m_pTree->writeNode( nn.get() );
487
NodePtr ptrR = m_pTree->m_indexPool.acquire();
488
if ( ptrR.get() == 0 )
490
ptrR = NodePtr( new Index( m_pTree, m_pTree->m_rootID, m_level + 1 ), &( m_pTree->m_indexPool ) );
494
//ptrR->m_pTree = m_pTree;
495
ptrR->m_identifier = m_pTree->m_rootID;
496
ptrR->m_level = m_level + 1;
497
ptrR->m_nodeMBR = m_pTree->m_infiniteRegion;
500
ptrR->insertEntry( 0, 0, n->m_nodeMBR, n->m_identifier );
501
ptrR->insertEntry( 0, 0, nn->m_nodeMBR, nn->m_identifier );
503
m_pTree->writeNode( ptrR.get() );
505
m_pTree->m_stats.m_nodesInLevel[m_level] = 2;
506
m_pTree->m_stats.m_nodesInLevel.push_back( 1 );
507
m_pTree->m_stats.m_treeHeight = m_level + 2;
511
n->m_level = m_level;
512
nn->m_level = m_level;
513
n->m_identifier = m_identifier;
514
nn->m_identifier = -1;
516
m_pTree->writeNode( n.get() );
517
m_pTree->writeNode( nn.get() );
519
long cParent = pathBuffer.top(); pathBuffer.pop();
520
NodePtr ptrN = m_pTree->readNode( cParent );
521
Index* p = static_cast<Index*>( ptrN.get() );
522
p->adjustTree( n.get(), nn.get(), pathBuffer, overflowTable );
529
void Node::reinsertData( unsigned long dataLength, byte* pData, Region& mbr, long id, vector<long>& reinsert, vector<long>& keep )
531
ReinsertEntry** v = new ReinsertEntry*[m_capacity + 1];
533
m_pDataLength[m_children] = dataLength;
534
m_pData[m_children] = pData;
535
m_ptrMBR[m_children] = m_pTree->m_regionPool.acquire();
536
*( m_ptrMBR[m_children] ) = mbr;
537
m_pIdentifier[m_children] = id;
539
PointPtr nc = m_pTree->m_pointPool.acquire();
540
m_nodeMBR.getCenter( *nc );
541
PointPtr c = m_pTree->m_pointPool.acquire();
543
for ( unsigned long cChild = 0; cChild < m_capacity + 1; cChild++ )
547
v[cChild] = new ReinsertEntry( cChild, 0.0 );
551
for ( unsigned long i = 0; i < cChild; i++ ) delete v[i];
556
m_ptrMBR[cChild]->getCenter( *c );
558
// calculate relative distance of every entry from the node MBR (ignore square root.)
559
for ( unsigned long cDim = 0; cDim < m_nodeMBR.m_dimension; cDim++ )
561
double d = nc->m_pCoords[cDim] - c->m_pCoords[cDim];
562
v[cChild]->m_dist += d * d;
566
// sort by increasing order of distances.
567
::qsort( v, m_capacity + 1, sizeof( ReinsertEntry* ), ReinsertEntry::compareReinsertEntry );
569
unsigned long cReinsert = ( unsigned long ) std::floor(( m_capacity + 1 ) * m_pTree->m_reinsertFactor );
571
unsigned long cCount;
573
for ( cCount = 0; cCount < cReinsert; cCount++ )
575
reinsert.push_back( v[cCount]->m_id );
579
for ( cCount = cReinsert; cCount < m_capacity + 1; cCount++ )
581
keep.push_back( v[cCount]->m_id );
588
void Node::rtreeSplit( unsigned long dataLength, byte* pData, Region& mbr, long id, vector<long>& group1, vector<long>& group2 )
590
unsigned long cChild;
591
unsigned long minimumLoad = static_cast<unsigned long>( std::floor( m_capacity * m_pTree->m_fillFactor ) );
593
// use this mask array for marking visited entries.
594
byte* mask = new byte[m_capacity + 1];
595
memset( mask, 0, m_capacity + 1 );
597
// insert new data in the node for easier manipulation. Data arrays are always
598
// by one larger than node capacity.
599
m_pDataLength[m_capacity] = dataLength;
600
m_pData[m_capacity] = pData;
601
m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire();
602
*( m_ptrMBR[m_capacity] ) = mbr;
603
m_pIdentifier[m_capacity] = id;
604
// m_totalDataLength does not need to be increased here.
606
// initialize each group with the seed entries.
607
unsigned long seed1, seed2;
608
pickSeeds( seed1, seed2 );
610
group1.push_back( seed1 );
611
group2.push_back( seed2 );
616
// find MBR of each group.
617
RegionPtr mbr1 = m_pTree->m_regionPool.acquire();
618
*mbr1 = *( m_ptrMBR[seed1] );
619
RegionPtr mbr2 = m_pTree->m_regionPool.acquire();
620
*mbr2 = *( m_ptrMBR[seed2] );
622
// count how many entries are left unchecked (exclude the seeds here.)
623
unsigned long cRemaining = m_capacity + 1 - 2;
625
while ( cRemaining > 0 )
627
if ( minimumLoad - group1.size() == cRemaining )
629
// all remaining entries must be assigned to group1 to comply with minimun load requirement.
630
for ( cChild = 0; cChild < m_capacity + 1; cChild++ )
632
if ( mask[cChild] == 0 )
634
group1.push_back( cChild );
640
else if ( minimumLoad - group2.size() == cRemaining )
642
// all remaining entries must be assigned to group2 to comply with minimun load requirement.
643
for ( cChild = 0; cChild < m_capacity + 1; cChild++ )
645
if ( mask[cChild] == 0 )
647
group2.push_back( cChild );
655
// For all remaining entries compute the difference of the cost of grouping an
656
// entry in either group. When done, choose the entry that yielded the maximum
657
// difference. In case of linear split, select any entry (e.g. the first one.)
659
double md1 = 0.0, md2 = 0.0;
660
double m = -std::numeric_limits<double>::max();
662
double a1 = mbr1->getArea();
663
double a2 = mbr2->getArea();
665
RegionPtr a = m_pTree->m_regionPool.acquire();
666
RegionPtr b = m_pTree->m_regionPool.acquire();
668
for ( cChild = 0; cChild < m_capacity + 1; cChild++ )
670
if ( mask[cChild] == 0 )
672
mbr1->getCombinedRegion( *a, *( m_ptrMBR[cChild] ) );
673
d1 = a->getArea() - a1;
674
mbr2->getCombinedRegion( *b, *( m_ptrMBR[cChild] ) );
675
d2 = b->getArea() - a2;
676
d = std::abs( d1 - d2 );
683
if ( m_pTree->m_treeVariant == RV_LINEAR || m_pTree->m_treeVariant == RV_RSTAR ) break;
688
// determine the group where we should add the new entry.
693
group1.push_back( sel );
696
else if ( md2 < md1 )
698
group2.push_back( sel );
703
group1.push_back( sel );
708
group2.push_back( sel );
711
else if ( group1.size() < group2.size() )
713
group1.push_back( sel );
716
else if ( group2.size() < group1.size() )
718
group2.push_back( sel );
723
group1.push_back( sel );
730
mbr1->combineRegion( *( m_ptrMBR[sel] ) );
734
mbr2->combineRegion( *( m_ptrMBR[sel] ) );
742
void Node::rstarSplit( unsigned long dataLength, byte* pData, Region& mbr, long id, std::vector<long>& group1, std::vector<long>& group2 )
744
RstarSplitEntry** dataLow = 0;
745
RstarSplitEntry** dataHigh = 0;
749
dataLow = new RstarSplitEntry*[m_capacity + 1];
750
dataHigh = new RstarSplitEntry*[m_capacity + 1];
758
m_pDataLength[m_capacity] = dataLength;
759
m_pData[m_capacity] = pData;
760
m_ptrMBR[m_capacity] = m_pTree->m_regionPool.acquire();
761
*( m_ptrMBR[m_capacity] ) = mbr;
762
m_pIdentifier[m_capacity] = id;
763
// m_totalDataLength does not need to be increased here.
765
unsigned long nodeSPF = static_cast<unsigned long>( std::floor(( m_capacity + 1 ) * m_pTree->m_splitDistributionFactor ) );
766
unsigned long splitDistribution = ( m_capacity + 1 ) - ( 2 * nodeSPF ) + 2;
768
unsigned long cChild = 0, cDim, cIndex;
770
for ( cChild = 0; cChild <= m_capacity; cChild++ )
774
dataLow[cChild] = new RstarSplitEntry( m_ptrMBR[cChild].get(), cChild, 0 );
778
for ( unsigned long i = 0; i < cChild; i++ ) delete dataLow[i];
784
dataHigh[cChild] = dataLow[cChild];
787
double minimumMargin = std::numeric_limits<double>::max();
792
for ( cDim = 0; cDim < m_pTree->m_dimension; cDim++ )
794
::qsort( dataLow, m_capacity + 1, sizeof( RstarSplitEntry* ), RstarSplitEntry::compareLow );
795
::qsort( dataHigh, m_capacity + 1, sizeof( RstarSplitEntry* ), RstarSplitEntry::compareHigh );
797
// calculate sum of margins and overlap for all distributions.
798
double marginl = 0.0;
799
double marginh = 0.0;
801
Region bbl1, bbl2, bbh1, bbh2;
803
for ( cChild = 1; cChild <= splitDistribution; cChild++ )
805
unsigned long l = nodeSPF - 1 + cChild;
807
bbl1 = *( dataLow[0]->m_pRegion );
808
bbh1 = *( dataHigh[0]->m_pRegion );
810
for ( cIndex = 1; cIndex < l; cIndex++ )
812
bbl1.combineRegion( *( dataLow[cIndex]->m_pRegion ) );
813
bbh1.combineRegion( *( dataHigh[cIndex]->m_pRegion ) );
816
bbl2 = *( dataLow[l]->m_pRegion );
817
bbh2 = *( dataHigh[l]->m_pRegion );
819
for ( cIndex = l + 1; cIndex <= m_capacity; cIndex++ )
821
bbl2.combineRegion( *( dataLow[cIndex]->m_pRegion ) );
822
bbh2.combineRegion( *( dataHigh[cIndex]->m_pRegion ) );
825
marginl += bbl1.getMargin() + bbl2.getMargin();
826
marginh += bbh1.getMargin() + bbh2.getMargin();
829
double margin = std::min( marginl, marginh );
831
// keep minimum margin as split axis.
832
if ( margin < minimumMargin )
834
minimumMargin = margin;
836
sortOrder = ( marginl < marginh ) ? 0 : 1;
839
// increase the dimension according to which the data entries should be sorted.
840
for ( cChild = 0; cChild <= m_capacity; cChild++ )
842
dataLow[cChild]->m_sortDim = cDim + 1;
846
for ( cChild = 0; cChild <= m_capacity; cChild++ )
848
dataLow[cChild]->m_sortDim = splitAxis;
851
::qsort( dataLow, m_capacity + 1, sizeof( RstarSplitEntry* ), ( sortOrder == 0 ) ? RstarSplitEntry::compareLow : RstarSplitEntry::compareHigh );
853
double ma = std::numeric_limits<double>::max();
854
double mo = std::numeric_limits<double>::max();
855
long splitPoint = -1;
859
for ( cChild = 1; cChild <= splitDistribution; cChild++ )
861
unsigned long l = nodeSPF - 1 + cChild;
863
bb1 = *( dataLow[0]->m_pRegion );
865
for ( cIndex = 1; cIndex < l; cIndex++ )
867
bb1.combineRegion( *( dataLow[cIndex]->m_pRegion ) );
870
bb2 = *( dataLow[l]->m_pRegion );
872
for ( cIndex = l + 1; cIndex <= m_capacity; cIndex++ )
874
bb2.combineRegion( *( dataLow[cIndex]->m_pRegion ) );
877
double o = bb1.getIntersectingArea( bb2 );
883
ma = bb1.getArea() + bb2.getArea();
887
double a = bb1.getArea() + bb2.getArea();
897
unsigned long l1 = nodeSPF - 1 + splitPoint;
899
for ( cIndex = 0; cIndex < l1; cIndex++ )
901
group1.push_back( dataLow[cIndex]->m_id );
902
delete dataLow[cIndex];
905
for ( cIndex = l1; cIndex <= m_capacity; cIndex++ )
907
group2.push_back( dataLow[cIndex]->m_id );
908
delete dataLow[cIndex];
915
void Node::pickSeeds( unsigned long& index1, unsigned long& index2 )
917
double separation = -std::numeric_limits<double>::max();
918
double inefficiency = -std::numeric_limits<double>::max();
919
unsigned long cDim, cChild, cIndex;
921
switch ( m_pTree->m_treeVariant )
925
for ( cDim = 0; cDim < m_pTree->m_dimension; cDim++ )
927
double leastLower = m_ptrMBR[0]->m_pLow[cDim];
928
double greatestUpper = m_ptrMBR[0]->m_pHigh[cDim];
929
unsigned long greatestLower = 0;
930
unsigned long leastUpper = 0;
933
for ( cChild = 1; cChild <= m_capacity; cChild++ )
935
if ( m_ptrMBR[cChild]->m_pLow[cDim] > m_ptrMBR[greatestLower]->m_pLow[cDim] ) greatestLower = cChild;
936
if ( m_ptrMBR[cChild]->m_pHigh[cDim] < m_ptrMBR[leastUpper]->m_pHigh[cDim] ) leastUpper = cChild;
938
leastLower = std::min( m_ptrMBR[cChild]->m_pLow[cDim], leastLower );
939
greatestUpper = std::max( m_ptrMBR[cChild]->m_pHigh[cDim], greatestUpper );
942
width = greatestUpper - leastLower;
943
if ( width <= 0 ) width = 1;
945
double f = ( m_ptrMBR[greatestLower]->m_pLow[cDim] - m_ptrMBR[leastUpper]->m_pHigh[cDim] ) / width;
947
if ( f > separation )
950
index2 = greatestLower;
955
if ( index1 == index2 )
957
if ( index2 == 0 ) index2++;
963
// for each pair of Regions (account for overflow Region too!)
964
for ( cChild = 0; cChild < m_capacity; cChild++ )
966
double a = m_ptrMBR[cChild]->getArea();
968
for ( cIndex = cChild + 1; cIndex <= m_capacity; cIndex++ )
970
// get the combined MBR of those two entries.
972
m_ptrMBR[cChild]->getCombinedRegion( r, *( m_ptrMBR[cIndex] ) );
974
// find the inefficiency of grouping these entries together.
975
double d = r.getArea() - a - m_ptrMBR[cIndex]->getArea();
977
if ( d > inefficiency )
988
throw Tools::NotSupportedException( "Node::pickSeeds: Tree variant not supported." );
992
void Node::condenseTree( stack<NodePtr>& toReinsert, stack<long>& pathBuffer, NodePtr& ptrThis )
994
unsigned long minimumLoad = static_cast<unsigned long>( std::floor( m_capacity * m_pTree->m_fillFactor ) );
996
if ( pathBuffer.empty() )
998
// eliminate root if it has only one child.
999
if ( m_level != 0 && m_children == 1 )
1001
NodePtr ptrN = m_pTree->readNode( m_pIdentifier[0] );
1002
m_pTree->deleteNode( ptrN.get() );
1003
ptrN->m_identifier = m_pTree->m_rootID;
1004
m_pTree->writeNode( ptrN.get() );
1006
m_pTree->m_stats.m_nodesInLevel.pop_back();
1007
m_pTree->m_stats.m_treeHeight -= 1;
1008
// HACK: pending deleteNode for deleted child will decrease nodesInLevel, later on.
1009
m_pTree->m_stats.m_nodesInLevel[m_pTree->m_stats.m_treeHeight - 1] = 2;
1014
long cParent = pathBuffer.top(); pathBuffer.pop();
1015
NodePtr ptrParent = m_pTree->readNode( cParent );
1016
Index* p = static_cast<Index*>( ptrParent.get() );
1018
// find the entry in the parent, that points to this node.
1019
unsigned long child;
1021
for ( child = 0; child != p->m_children; child++ )
1023
if ( p->m_pIdentifier[child] == m_identifier ) break;
1026
if ( m_children < minimumLoad )
1028
// used space less than the minimum
1029
// 1. eliminate node entry from the parent. deleteEntry will fix the parent's MBR.
1030
p->deleteEntry( child );
1031
// 2. add this node to the stack in order to reinsert its entries.
1032
toReinsert.push( ptrThis );
1036
// adjust the entry in 'p' to contain the new bounding region of this node.
1037
*( p->m_ptrMBR[child] ) = m_nodeMBR;
1039
// global recalculation necessary since the MBR can only shrink in size,
1040
// due to data removal.
1041
if ( m_pTree->m_bTightMBRs )
1043
for ( unsigned long cDim = 0; cDim < p->m_nodeMBR.m_dimension; cDim++ )
1045
p->m_nodeMBR.m_pLow[cDim] = std::numeric_limits<double>::max();
1046
p->m_nodeMBR.m_pHigh[cDim] = -std::numeric_limits<double>::max();
1048
for ( unsigned long cChild = 0; cChild < p->m_children; cChild++ )
1050
p->m_nodeMBR.m_pLow[cDim] = std::min( p->m_nodeMBR.m_pLow[cDim], p->m_ptrMBR[cChild]->m_pLow[cDim] );
1051
p->m_nodeMBR.m_pHigh[cDim] = std::max( p->m_nodeMBR.m_pHigh[cDim], p->m_ptrMBR[cChild]->m_pHigh[cDim] );
1057
// write parent node back to storage.
1058
m_pTree->writeNode( p );
1060
p->condenseTree( toReinsert, pathBuffer, ptrParent );