/** * Calculate "maximum perimeter" constant for a node to be split: 2 times the perimeter of the minimum bounding box * of all bigM + 1 bboxes minus the shortest axis length * * @param boxes */ private double calculatePerimMax( float[][] boxes ) { float[] overfilledBox = mbb( boxes ); double result = 2 * calculatePerimeter( overfilledBox ); double xLength = 2 * ( overfilledBox[2] - overfilledBox[0] ); double yLength = 2 * ( overfilledBox[3] - overfilledBox[1] ); if ( xLength < yLength ) { return result - xLength; } return result - yLength; }
/** * Calculate the value of the goal function when the splitting at position i. * * @param leftSide * @param rightSide */ private double wgFunction( float[][] leftSide, float[][] rightSide ) { double result; try { result = calculatePerimeter( calculateIntersection( mbb( leftSide ), mbb( rightSide ) ) ); } catch ( NoOverlapException e ) { float[][] all = new float[leftSide.length + rightSide.length][]; // Arrays.copyOf does not work for ( int i = 0; i < leftSide.length; i++ ) { all[i] = leftSide[i]; } System.arraycopy( rightSide, 0, all, leftSide.length, rightSide.length ); result = calculatePerimeter( mbb( leftSide ) ) + calculatePerimeter( mbb( rightSide ) ) - calculatePerimMax( all ); } return result; }
for ( int i = smallm - 1; i <= bigM + 1 - smallm; i++ ) { float[][] boxes = copyBoxesFromRange( entries, 0, i + 1 ); perimX += calculatePerimeter( mbb( boxes ) ); perimX += calculatePerimeter( mbb( boxes ) ); for ( int i = smallm; i <= bigM + 1 - smallm; i++ ) { float[][] boxes = copyBoxesFromRange( entries, 0, i + 1 ); perimY += calculatePerimeter( mbb( boxes ) ); perimY += calculatePerimeter( mbb( boxes ) );
parent[parentIndex].bbox = mbb( copyBoxesFromRange( leftEntries, 0, nLeftEntries + 1 ) ); parent[parentIndex].next = leftEntries; newEntry.bbox = mbb( copyBoxesFromRange( rightEntries, 0, nRightEntries + 1 ) ); newEntry.next = rightEntries; parent[parentIndex].bbox = mbb( copyBoxesFromRange( leftEntries, 0, nLeftEntries ) );
/** * Choose the index at which the entries shall be split when inserting insertBox. * * @param entries * @param insertBox * @param object */ private int split( NodeEntry<T>[] entries, float[] insertBox, T object ) { if ( entries[0].next == null ) { // leaf node splitAxis( entries ); } double minValue = Double.MAX_VALUE; int splitIndex = -1; for ( int i = smallm - 1; i < bigM + 1 - smallm; i++ ) { float[][] leftSide = copyBoxesFromRange( entries, 0, i + 1 ); float[][] rightSide = copyBoxesFromRange( entries, i + 1, bigM + 1 ); double currentVal; if ( !intersects( mbb( leftSide ), mbb( rightSide ), 2 ) ) { currentVal = wgFunction( leftSide, rightSide ) * wfFunction( i ); } else { currentVal = wgFunction( leftSide, rightSide ) / wfFunction( i ); } if ( currentVal < minValue ) { minValue = currentVal; splitIndex = i; } } return splitIndex; }
trace[traceIndex].node[entryIndex].bbox = mbb( copyBoxesFromRange( trace[traceIndex - 1].node, 0, trace[traceIndex - 1].node.length ) ); condenseTree( trace, traceIndex + 1, false );