/*******************************************************************************
* Copyright (c) 2015 MITRE
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License, Version 2.0 which
* accompanies this distribution and is available at
* http://www.apache.org/licenses/LICENSE-2.0.txt
******************************************************************************/
package org.locationtech.spatial4j.shape.impl;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.shape.Rectangle;
/**
* INTERNAL: A numeric range between a pair of numbers.
* Perhaps this class could become 1st class citizen extending Shape but not now.
* Only public so is accessible from tests in another package.
*/
@Deprecated // See BBoxCalculator
public class Range {
protected final double min, max;
public static Range xRange(Rectangle rect, SpatialContext ctx) {
if (ctx.isGeo())
return new LongitudeRange(rect.getMinX(), rect.getMaxX());
else
return new Range(rect.getMinX(), rect.getMaxX());
}
public static Range yRange(Rectangle rect, SpatialContext ctx) {
return new Range(rect.getMinY(), rect.getMaxY());
}
public Range(double min, double max) {
this.min = min;
this.max = max;
}
public double getMin() {
return min;
}
public double getMax() {
return max;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Range range = (Range) o;
if (Double.compare(range.max, max) != 0) return false;
if (Double.compare(range.min, min) != 0) return false;
return true;
}
@Override
public int hashCode() {
int result;
long temp;
temp = min != +0.0d ? Double.doubleToLongBits(min) : 0L;
result = (int) (temp ^ (temp >>> 32));
temp = max != +0.0d ? Double.doubleToLongBits(max) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public String toString() {
return "Range{" + min + " TO " + max + '}';
}
public double getWidth() {
return max - min;
}
public boolean contains(double v) {
return v >= min && v <= max;
}
public double getCenter() {
return min + getWidth()/2;
}
public Range expandTo(Range other) {
assert this.getClass() == other.getClass();
return new Range(Math.min(min, other.min), Math.max(max, other.max));
}
public double deltaLen(Range other) {
double min3 = Math.max(min, other.min);
double max3 = Math.min(max, other.max);
return max3 - min3;
}
@Deprecated // See BBoxCalculator
public static class LongitudeRange extends Range {
public static final LongitudeRange WORLD_180E180W = new LongitudeRange(-180, 180);
public LongitudeRange(double min, double max) {
super(min, max);
}
public LongitudeRange(Rectangle r) {
super(r.getMinX(), r.getMaxX());
}
@Override
public double getWidth() {
double w = super.getWidth();
if (w < 0)
w += 360;
return w;
}
@Override
public boolean contains(double v) {
if (!crossesDateline())
return super.contains(v);
return v >= min || v <= max;// the OR is the distinction from non-dateline cross
}
public boolean crossesDateline() {
return min > max;
}
public double getCenter() {
double ctr = super.getCenter();
if (ctr > 180)
ctr -= 360;
return ctr;
}
public double compareTo(LongitudeRange b) {
return diff(getCenter(), b.getCenter());
}
/** a - b (compareTo order). < 0 if a < b */
private static double diff(double a, double b) {
double diff = a - b;
if (diff <= 180) {
if (diff >= -180)
return diff;
return diff + 360;
} else {
return diff - 360;
}
}
@Override
public Range expandTo(Range other) {
return expandTo((LongitudeRange) other);
}
public LongitudeRange expandTo(LongitudeRange other) {
LongitudeRange a, b;// a.ctr <= b.ctr
if (this.compareTo(other) <= 0) {
a = this;
b = other;
} else {
a = other;
b = this;
}
LongitudeRange newMin = b.contains(a.min) ? b : a;//usually 'a'
LongitudeRange newMax = a.contains(b.max) ? a : b;//usually 'b'
if (newMin == newMax)
return newMin;
if (newMin == b && newMax == a)
return WORLD_180E180W;
return new LongitudeRange(newMin.min, newMax.max);
}
}
}