//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/ogcwebservices/wpvs/util/Attic/QuadTreeSplitter.java,v 1.4 2006/12/04 17:06:43 bezema Exp $
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/exse/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstrasse 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Jens Fitzke
lat/lon GmbH
Aennchenstrasse 19
53177 Bonn
Germany
E-Mail: jens.fitzke@uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.ogcwebservices.wpvs.util;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
import javax.vecmath.Vector3d;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.model.crs.CoordinateSystem;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.GeometryException;
import org.deegree.model.spatialschema.GeometryFactory;
import org.deegree.model.spatialschema.Position;
import org.deegree.model.spatialschema.Surface;
/**
* <p>
* The <code>QuadTreeSplitter</code> class can be used to create x-y axis alligned request quads
* from a qiven List of {@link ResolutionStripe} s. These Stripes depend on the ViewFrustrum and
* it's projection on the x-y plane (the so called footprint). To create an approximation of this
* footprint a Quadtree (a geometric spatial structure, which recursively divides a boundingbox into
* four containing boundingboxes) is built. The leafs of this tree are merged according to their
* resolution and size to create the requeststripes.
* </p>
*
* @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
*
* @author last edited by: $Author: bezema $
*
* @version $Revision: 1.4 $, $Date: 2006/12/04 17:06:43 $
*
*/
public class QuadTreeSplitter {
private static final ILogger LOG = LoggerFactory.getLogger( QuadTreeSplitter.class );
private QuadNode rootNode;
private ArrayList<ResolutionStripe> resolutionStripes;
private double minimalTerrainHeight;
private double minimalResolution;
private CoordinateSystem crs;
private double imageWidth;
private double imageHeight;
private boolean highQuality;
/**
* Creates a new Quadtree, from the given resolutionstripes. The resulting tree can be used to
* generate requeststripes which are (x-y) axis aligned.
* <p>
* The Quality argument is used for the recursive termination criteria, if it is set to true the
* requeststripes will accurately approximate the footprint (=projection of the viewfrustrum
* onto the ground) and the resolutions given in the resolutionstripes this results in a lot of
* requests which can slow down the wpvs. If set to false the footprint and the given
* resolutions will be approximated poorly but only a few requeststripes are created, resulting
* in a faster wpvs.
* </p>
*
* @param resolutionStripes
* the different resolutionstripes.
* @param imageWidth
* the width of the target image, necessary for calculating the width resolution of
* the requeststripe.
* @param imageHeight
* the height of the target image, necessary for calculating the height resolution of
* the requeststripe.
* @param highQuality
* true if accurate (but many) requeststripes should be generated, false if none
* accurate (but only a few) requests should be generated.
* @param g2d
* for debugging -> TODO delete
*/
public QuadTreeSplitter( ArrayList<ResolutionStripe> resolutionStripes, double imageWidth,
double imageHeight, boolean highQuality, Graphics2D g2d ) {
if ( resolutionStripes == null && resolutionStripes.size() <= 0 )
return;
this.resolutionStripes = resolutionStripes;
this.crs = resolutionStripes.get( 0 ).getCRSName() ;
this.minimalTerrainHeight = resolutionStripes.get( 0 ).getMinimalTerrainHeight();
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
this.highQuality = highQuality;
// For the merge, the check is newmin < existing_min therefore -> min large and max small
Position minPos = GeometryFactory.createPosition( 0, 0, 0 );
Position maxPos = GeometryFactory.createPosition( 0, 0, 0 );
Envelope bbox = GeometryFactory.createEnvelope( minPos, maxPos, this.crs );
minimalResolution = Double.MAX_VALUE;
double maxResolution = Double.MIN_VALUE;
// find the highest and loweset maxResolution (which are needed for termination decissions
// and
// find create the axis-alligned bbox of the resolutionstripes which will be the rootnode.
for ( int i = 0; i < resolutionStripes.size(); ++i ) {
try {
bbox = bbox.merge( resolutionStripes.get( i ).getSurface().getEnvelope() );
// minimalResolution is the smallest number
minimalResolution = Math.min( minimalResolution,
resolutionStripes.get( i ).getMinResolution() );
maxResolution = Math.max( maxResolution,
resolutionStripes.get( i ).getMaxResolution() );
} catch ( GeometryException e ) {
e.printStackTrace();
System.out.println( e.getLocalizedMessage() );
}
}
try {
if ( Math.abs( minimalResolution ) < 0.00001 ) // almost null
minimalResolution = Math.pow( maxResolution, 1.0 / resolutionStripes.size() );
Position min = bbox.getMin();
double zValue = min.getZ();
if ( new Double( min.getZ() ).equals( Double.NaN ) )
zValue = 0;
Vector3d leftPoint = new Vector3d( min.getX(), min.getY(), zValue );
Vector3d rightPoint = new Vector3d( min.getX() + ( bbox.getWidth() ),
min.getY() + ( bbox.getHeight() ), zValue );
double currentResolution = StripeFactory.calcScaleOfVector( leftPoint, rightPoint,
imageWidth );
rootNode = new QuadNode( GeometryFactory.createSurface( bbox, crs ), maxResolution,
minimalResolution );
createTree( rootNode, currentResolution, g2d );
} catch ( GeometryException e ) {
e.printStackTrace();
System.out.println( e.getLocalizedMessage() );
}
}
/**
* After instantiating a Quadtree, this method can be called to build the (x-y) axis-alligned
* request stripes.
*
* @param g2d
* TODO just for debugging to be removed.
* @return the (x-y) axis-alligned request squares best fitted the given resolutionstripes.
*/
public ArrayList<ResolutionStripe> getRequestQuads( Graphics2D g2d ) {
ArrayList<ResolutionStripe> resultList = new ArrayList<ResolutionStripe>();
if ( rootNode != null ) {
LinkedHashMap<Integer, ArrayList<QuadNode>> lhm = new LinkedHashMap<Integer, ArrayList<QuadNode>>(
100 );
outputNodes( rootNode, lhm );
Set<Integer> keys = lhm.keySet();
for ( Integer resolution : keys ) {
if ( lhm.containsKey( resolution ) ) {
ArrayList<QuadNode> originalNodes = lhm.get( resolution );
ArrayList<QuadNode> result = new ArrayList<QuadNode>( originalNodes.size() / 2 );
// sorted to x values first.
ArrayList<QuadNode> resultX = new ArrayList<QuadNode>( result.size() );
boolean resort = mergeAndSort( originalNodes, resultX );
while ( resort ) {
result.clear();
result.addAll( resultX );
resultX.clear();
resort = mergeAndSort( result, resultX );
}
// Check if sorting to y results in better values;
for ( QuadNode node : originalNodes ) {
node.compareY();
}
ArrayList<QuadNode> resultY = new ArrayList<QuadNode>();
resort = mergeAndSort( originalNodes, resultY );
while ( resort ) {
result.clear();
result.addAll( resultY );
resultY.clear();
resort = mergeAndSort( result, resultY );
}
result.clear();
// Find the optimal sorting order (lesser quads) and check if the perpendicular
// order results in lesser requeststripes (it usually does)
if ( resultX.size() < resultY.size() ) {
for ( QuadNode node : resultX ) {
node.compareY();
}
while ( mergeAndSort( resultX, result ) ) {
resultX.clear();
resultX.addAll( result );
result.clear();
}
} else {
for ( QuadNode node : resultY ) {
node.compareX();
}
while ( mergeAndSort( resultY, result ) ) {
resultY.clear();
resultY.addAll( result );
result.clear();
}
}
for ( QuadNode quad : result ) {
Position envMin = quad.getBBox().getEnvelope().getMin();
Position envMax = quad.getBBox().getEnvelope().getMax();
Vector3d minVec = new Vector3d( envMin.getX(), envMin.getY(), envMin.getZ() );
Vector3d maxVec = new Vector3d( envMax.getX(), envMin.getY(), envMin.getZ() );
double maxResolution = StripeFactory.calcScaleOfVector( minVec, maxVec,
imageWidth );
double minResolution = maxResolution;
if( maxResolution < 1 ){
maxResolution = 1;
}
ResolutionStripe rs = new ResolutionStripe( quad.getBBox(), maxResolution,
minResolution,
minimalTerrainHeight );
// minVec = new Vector3d( envMin.getX(), envMin.getY(), envMin.getZ() );
// maxVec = new Vector3d( envMin.getX(), envMax.getY(), envMin.getZ() );
// maxResolution = StripeFactory.calcScaleOfVector( minVec, maxVec,
// imageHeight );
//rs.setMaxHeightResolution( maxResolution );
resultList.add( rs );
}
}
}
}
if ( g2d != null ) {
for ( ResolutionStripe stripe : resultList ) {
drawSquare( new QuadNode( stripe.getSurface(), stripe.getMaxResolution(),
stripe.getMinResolution() ), g2d, Color.MAGENTA );
// System.out.println( stripe.toWKT() );
}
}
return resultList;
}
/**
* A little helper function which first sorts the given list of quadnodes according to their
* sorting order and afterwards merges all stripes which are adjacent and have the same
* resolution.
*
* @param toBeMerged the list of Quadnodes which must be sorted and merged.
* @param resultList the list containing the merged quadnodes.
* @return true if the list should be rechecked (that is, if one or more merge(s) took place)
*/
private boolean mergeAndSort( ArrayList<QuadNode> toBeMerged, ArrayList<QuadNode> resultList ) {
Collections.sort( toBeMerged );
Iterator<QuadNode> it = toBeMerged.iterator();
QuadNode first = null;
QuadNode second = null;
boolean needsResort = false;
resultList.clear();
while ( second != null || it.hasNext() ) {
if ( second == null ) {
first = it.next();
} else {
first = second;
second = null;
}
Envelope requestEnvelope = first.getBBox().getEnvelope();
while ( it.hasNext() && second == null ) {
second = it.next();
if ( first.canMerge( second ) ) {
try {
requestEnvelope = requestEnvelope.merge( second.getBBox().getEnvelope() );
} catch ( GeometryException ge ) {
// An error occured, it might be best to not merge these envelopes.
LOG.logError( ge.getLocalizedMessage(), ge );
}
second = null;
needsResort = true;
}
}
Surface resultSurface = null;
try {
resultSurface = GeometryFactory.createSurface( requestEnvelope, crs );
} catch ( GeometryException ge ) {
// An error occured, it might be best not to merge these envelopes.
LOG.logError( ge.getLocalizedMessage(), ge );
}
resultList.add( new QuadNode( resultSurface, first.getMaxResolution(),
first.getMinResolution(), first.isComparingX() ) );
}
return needsResort;
}
/**
* This Method actually builds the tree. The decission of a split is made by evaluating the
* minimal maxResolution of the intersecting ResultionStripe.
*
* @param father
* the Father node which will be splittet into four axis aligned sons
* @param fatherResolution
* the maxResolution of a width axis of the axis-aligned bbox
* @param g2d
* just for debugging-> TODO must be deleted
* @throws GeometryException
* if the Envelope cannot be created
*/
private void createTree( QuadNode father, double fatherResolution, Graphics2D g2d )
throws GeometryException {
Position min = father.getBBox().getEnvelope().getMin();
double widthHalf = 0.5 * father.getBBox().getEnvelope().getWidth();
double heightHalf = 0.5 * father.getBBox().getEnvelope().getHeight();
double lowerLeftX = min.getX();
double lowerLeftY = min.getY();
double currentResolution = 0.5 * fatherResolution;
// no more recursion.
if ( currentResolution < minimalResolution )
return;
checkSon( father, currentResolution, QuadNode.LOWER_LEFT_SON, lowerLeftX, lowerLeftY,
lowerLeftX + widthHalf, lowerLeftY + heightHalf, g2d );
// lowerright
checkSon( father, currentResolution, QuadNode.LOWER_RIGHT_SON, lowerLeftX + widthHalf,
lowerLeftY, lowerLeftX + ( 2 * widthHalf ), lowerLeftY + heightHalf, g2d );
// upperleft
checkSon( father, currentResolution, QuadNode.UPPER_LEFT_SON, lowerLeftX, lowerLeftY
+ heightHalf,
lowerLeftX + widthHalf, lowerLeftY + ( 2 * heightHalf ), g2d );
// upperright
checkSon( father, currentResolution, QuadNode.UPPER_RIGHT_SON, lowerLeftX + widthHalf,
lowerLeftY + heightHalf, lowerLeftX + 2 * widthHalf, lowerLeftY + 2 * heightHalf,
g2d );
}
/**
* Decides if the father quad has to be subdivided into it's sons.
*
* @param father
* the Father quad to divide
* @param maxResolution
* the maxResolution of the fathers son (half the maxResolution of the father)
* @param quadArea
* the area of a son of the son (1/16 of the fathers area)
* @param SON_ID
* the son to check
* @param lowerLeftX
* minx of the bbox of the fathers son
* @param lowerLeftY
* miny of the bbox of the fathers son
* @param upperRightX
* maxx of the bbox of the fathers son
* @param upperRightY
* maxY of the bbox of the fathers son
* @param g2d
* for debugging -> TODO delete
* @throws GeometryException
* if no surface can be created
*/
private void checkSon( QuadNode father, double resolution, final int SON_ID, double lowerLeftX,
double lowerLeftY, double upperRightX, double upperRightY, Graphics2D g2d )
throws GeometryException {
Position min = GeometryFactory.createPosition(
lowerLeftX,
lowerLeftY,
father.getBBox().getEnvelope().getMin().getZ() );
Position max = GeometryFactory.createPosition(
upperRightX,
upperRightY,
father.getBBox().getEnvelope().getMax().getZ() );
Surface bbox = GeometryFactory.createSurface(
GeometryFactory.createEnvelope( min, max, crs ),
crs );
ResolutionStripe intersectedStripe = ( highQuality ) ? getIntersectionForQualityConfiguration( bbox )
: getIntersectionForFastConfiguration( bbox );
if ( intersectedStripe != null ) { // found an intersecting resolutionStripe
QuadNode son = new QuadNode( bbox, intersectedStripe.getMaxResolution(),
intersectedStripe.getMinResolution() );
double sonsResolution = intersectedStripe.getMinResolution();
father.addSon( SON_ID, son );
if ( resolution >= sonsResolution ) {
drawSquare( son, g2d, Color.YELLOW );
createTree( son, resolution, g2d );
}
}
}
/**
* Finds the resolutionstripe with the lowest minResolution which intersects with the given
* bbox. Resulting in a lot of different requests.
*
* @param bbox
* the BoundingBox of the Envelope to check.
* @return the resolutionStripe which intersects the bbox.
*/
private ResolutionStripe getIntersectionForQualityConfiguration( Surface bbox ) {
ResolutionStripe resultStripe = null;
for ( ResolutionStripe stripe : resolutionStripes ) {
if ( bbox.intersects( stripe.getSurface() ) ) {
if ( resultStripe != null ) {
if ( ( stripe.getMinResolution() < resultStripe.getMinResolution() ) ) {
resultStripe = stripe;
}
} else {
resultStripe = stripe;
}
}
}
return resultStripe;
}
/**
* Finds the resolutionstripe with the highest maxResolution which intersects with the given
* bbox. Resulting in only a few different requests.
*
* @param bbox
* the BoundingBox of the Envelope to check.
* @return the resolutionStripe which intersects the bbox.
*/
private ResolutionStripe getIntersectionForFastConfiguration( Surface bbox ) {
ResolutionStripe resultStripe = null;
for ( ResolutionStripe stripe : resolutionStripes ) {
if ( bbox.intersects( stripe.getSurface() ) ) {
if ( resultStripe != null ) {
if ( ( stripe.getMaxResolution() > resultStripe.getMaxResolution() ) ) {
resultStripe = stripe;
}
} else {
resultStripe = stripe;
}
}
}
return resultStripe;
}
/**
* Outputs the tree
*
* @param g2d
* if the quadtree should be drawn.
*/
public void outputTree( Graphics2D g2d ) {
if ( rootNode != null ) {
if ( g2d != null ) {
System.out.println( "number Of leaves-> " + outputNodes( rootNode, g2d ) );
} else {
outputNodes( rootNode, "" );
}
}
}
private int outputNodes( QuadNode father, Graphics2D g2d ) {
if ( father.isLeaf() ) {
drawSquare( father, g2d, Color.BLACK );
return 1;
}
QuadNode[] nodes = father.getSons();
int result = 0;
for ( QuadNode node : nodes ) {
if ( node != null ) {
result += outputNodes( node, g2d );
}
}
return result;
}
private void outputNodes( QuadNode father, String indent ) {
if ( father.isLeaf() ) {
System.out.println( indent + "(father)" + father.getBBox() );
} else {
QuadNode[] nodes = father.getSons();
for ( QuadNode node : nodes ) {
if ( node != null ) {
indent += "-";
outputNodes( node, indent );
}
}
}
}
/**
* Find the leaf nodes and add them according to their maxResolution in a LinkedHashMap.
*
* @param father
* the node to check
* @param outputMap
* the map to output to.
*/
private void outputNodes( QuadNode father, LinkedHashMap<Integer, ArrayList<QuadNode>> outputMap ) {
if ( father.isLeaf() ) {
Integer key = new Integer( (int) Math.floor( father.getMaxResolution() ) );
ArrayList<QuadNode> ts = outputMap.get( key );
if ( ts == null ) { // I know, but I don't put null values so it's ok
ts = new ArrayList<QuadNode>();
outputMap.put( key, ts );
}
if ( ts.add( father ) == false ) {
System.out.println( "quadnode allready in set" );
}
} else {
QuadNode[] nodes = father.getSons();
for ( QuadNode node : nodes ) {
if ( node != null ) {
outputNodes( node, outputMap );
}
}
}
}
private void drawSquare( QuadNode node, Graphics2D g2d, Color c ) {
if ( g2d != null ) {
g2d.setColor( c );
Envelope env = node.getBBox().getEnvelope();
Position min = env.getMin();
int height = (int) env.getHeight();
int width = (int) env.getWidth();
g2d.drawRect( (int) min.getX(), (int) min.getY(), width, height );
Composite co = g2d.getComposite();
g2d.setColor( new Color( c.getRed(), c.getGreen(), c.getBlue(), 64 ) );
g2d.fillRect( (int) min.getX(), (int) min.getY(), width, height );
g2d.setComposite( co );
}
}
/**
*
* The <code>QuadNode</code> class is the bean for every node of the quadtree. It contains a
* axis-aligned BBox and the maxResolution of its associated resolutionStripe. It can have upto
* four sons.
*
* @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
*
* @author last edited by: $Author: bezema $
*
* @version $Revision: 1.4 $, $Date: 2006/12/04 17:06:43 $
*
*/
private class QuadNode implements Comparable<QuadNode> {
private QuadNode[] sons;
private Surface bbox;
private double maxResolution;
private double minResolution;
private double comparePosition;
private double compareLength;
private boolean comparingX;
static final int LOWER_LEFT_SON = 0;
static final int LOWER_RIGHT_SON = 1;
static final int UPPER_LEFT_SON = 2;
static final int UPPER_RIGHT_SON = 3;
private QuadNode( Surface bbox, double maxResolution, double minResolution ) {
this.bbox = bbox;
sons = new QuadNode[4];
this.maxResolution = maxResolution;
this.minResolution = minResolution;
comparePosition = bbox.getEnvelope().getMin().getX();
compareLength = bbox.getEnvelope().getWidth();
comparingX = true;
}
private QuadNode( Surface bbox, double maxResolution, double minResolution,
boolean compareDirection ) {
this( bbox, maxResolution, minResolution );
if ( compareDirection )
compareX();
else
compareY();
}
void addSon( final int sonID, QuadNode son ) {
if ( sonID == LOWER_LEFT_SON || sonID == LOWER_RIGHT_SON || sonID == UPPER_LEFT_SON
|| sonID == UPPER_RIGHT_SON ) {
this.sons[sonID] = son;
}
}
Surface getBBox() {
return bbox;
}
void compareX() {
comparePosition = bbox.getEnvelope().getMin().getX();
compareLength = bbox.getEnvelope().getWidth();
comparingX = true;
}
void compareY() {
comparePosition = bbox.getEnvelope().getMin().getY();
compareLength = bbox.getEnvelope().getHeight();
comparingX = false;
}
/**
* If this Quadnode has no sons it is called a leaf.
*
* @return true if no sons, false otherwhise.
*/
boolean isLeaf() {
return ( sons[0] == null && sons[1] == null && sons[2] == null && sons[3] == null );
}
QuadNode[] getSons() {
return sons;
}
QuadNode getSon( final int sonID ) {
if ( sonID != LOWER_LEFT_SON || sonID != LOWER_RIGHT_SON || sonID != UPPER_LEFT_SON
|| sonID != UPPER_RIGHT_SON )
return null;
return sons[sonID];
}
/**
* @return The max maxResolution of the Stripe.
*/
double getMaxResolution() {
return maxResolution;
}
/**
* @return the minResolution value.
*/
double getMinResolution() {
return minResolution;
}
boolean isComparingX() {
return comparingX;
}
double getComparePosition() {
return comparePosition;
}
double getCompareLength() {
return compareLength;
}
/*
* Attention, the equal result "0" is not really a check for the equality of two Quadnodes,
* it just reflex, that two QuadNodes have the same sorting properties -> the position - (y
* or x) and the length in this direction are equal. It is very plausible that they have
* totally different positions and length in the other (not checked) direction.
*
* @see java.lang.Comparable#compareTo(T)
*/
public int compareTo( QuadNode other ) {
double otherPosition = other.getComparePosition();
if ( Math.abs( comparePosition - otherPosition ) < 0.00001 ) {
double otherLength = other.getCompareLength();
if ( Math.abs( compareLength - otherLength ) < 0.00001 ) {
if ( comparingX ) {
double thisMinY = this.bbox.getEnvelope().getMin().getY();
double otherMinY = other.getBBox().getEnvelope().getMin().getY();
if ( ( Math.abs( thisMinY - otherMinY ) < 0.00001 ) )
return 0;
if ( thisMinY < otherMinY )
return 1;
return -1;
}
double thisMinX = this.bbox.getEnvelope().getMin().getX();
double otherMinX = other.getBBox().getEnvelope().getMin().getX();
if ( ( Math.abs( thisMinX - otherMinX ) < 0.00001 ) )
return 0;
if ( thisMinX < otherMinX )
return 1;
return -1;
}
if ( compareLength < otherLength ) {
return -1;
}
return 1;
}
if ( comparePosition < otherPosition )
return -1;
return 1;
}
/**
* simple check if two quadnodes can be merged, according to their positions, length and if
* they are adjacent.
*
* @param other
* @return true if this QuadNode can be merged with the Other.
*/
boolean canMerge( QuadNode other ) {
double otherPosition = other.getComparePosition();
if ( Math.abs( comparePosition - otherPosition ) < 0.01 ) {
double otherLength = other.getCompareLength();
if ( Math.abs( compareLength - otherLength ) < 0.01 ) {
// the origins and the length are mergable, now check if the Quadnodes are
// adjacent
if ( comparingX ) {
double thisMaxY = this.bbox.getEnvelope().getMax().getY();
double thisMinY = this.bbox.getEnvelope().getMin().getY();
double otherMinY = other.getBBox().getEnvelope().getMin().getY();
double otherMaxY = other.getBBox().getEnvelope().getMax().getY();
if ( ( Math.abs( thisMaxY - otherMinY ) < 0.00001 )
|| ( Math.abs( thisMinY - otherMaxY ) < 0.00001 ) ) {
return true;
}
} else {
double thisMaxX = this.bbox.getEnvelope().getMax().getX();
double thisMinX = this.bbox.getEnvelope().getMin().getX();
double otherMinX = other.getBBox().getEnvelope().getMin().getX();
double otherMaxX = other.getBBox().getEnvelope().getMax().getX();
if ( ( Math.abs( thisMaxX - otherMinX ) < 0.00001 )
|| ( Math.abs( thisMinX - otherMaxX ) < 0.00001 ) ) {
return true;
}
}
}
}
return false;
}
@Override
public String toString() {
return "QuadNode sorted in Direction: " + ( ( comparingX ) ? "x" : "y" )
+ " comparePosition: " + comparePosition + " compareLength: " + compareLength;
}
}
}
/***************************************************************************************************
* Changes to this class. What the people have been up to: $Log: QuadTreeSplitter.java,v $
* Changes to this class. What the people have been up to: Revision 1.4 2006/12/04 17:06:43 bezema
* Changes to this class. What the people have been up to: enhanced dgm from wcs support
* Changes to this class. What the people have been up to:
* Changes to this class. What the people have been up to: Revision 1.3 2006/11/27 15:43:11 bezema
* Changes to this class. What the people have been up to: Updated the coordinatesystem handling
* Changes to this class. What the people have been up to:
* Changes to this class. What the people have been up to: Revision 1.2 2006/11/27 09:07:52 poth
* Changes to this class. What the people have been up to: JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
* Changes to this class. What the people have been up to:
* Changes to this class. What the people have been up to: Revision 1.1 2006/11/23 11:46:40 bezema
* Changes to this class. What the people have been up to: The initial version of the new wpvs
* Changes to this class. What the people have been up to:
**************************************************************************************************/