package de.lmu.ifi.dbs.elki.data;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.text.NumberFormat;
import java.util.Arrays;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
/**
* HyperBoundingBox represents a hyperrectangle in the multidimensional space.
*
* @author Elke Achtert
*/
public class HyperBoundingBox implements SpatialComparable, Externalizable {
/**
* Serial version.
*/
private static final long serialVersionUID = 1;
/**
* The coordinates of the 'lower left' (= minimum) hyper point.
*/
double[] min;
/**
* The coordinates of the 'upper right' (= maximum) hyper point.
*/
double[] max;
/**
* Empty constructor for Externalizable interface.
*/
public HyperBoundingBox() {
// nothing to do
}
/**
* Creates a HyperBoundingBox for the given hyper points.
*
* @param min - the coordinates of the minimum hyper point
* @param max - the coordinates of the maximum hyper point
*/
public HyperBoundingBox(double[] min, double[] max) {
if(min.length != max.length) {
throw new IllegalArgumentException("min/max need same dimensionality");
}
this.min = min;
this.max = max;
}
/**
* Constructor, cloning an existing spatial object.
*
* @param other Object to clone
*/
public HyperBoundingBox(SpatialComparable other) {
final int dim = other.getDimensionality();
this.min = new double[dim];
this.max = new double[dim];
for(int i = 0; i < dim; i++) {
this.min[i] = other.getMin(i);
this.max[i] = other.getMax(i);
}
}
/**
* Returns the coordinate at the specified dimension of the minimum hyper
* point.
*
* @param dimension the dimension for which the coordinate should be returned,
* where 0 ≤ dimension < this.getDimensionality()
* @return the coordinate at the specified dimension of the minimum hyper
* point
*/
@Override
public double getMin(int dimension) {
return min[dimension];
}
/**
* Returns the coordinate at the specified dimension of the maximum hyper
* point.
*
* @param dimension the dimension for which the coordinate should be returned,
* where 0 ≤ dimension < this.getDimensionality()
* @return the coordinate at the specified dimension of the maximum hyper
* point
*/
@Override
public double getMax(int dimension) {
return max[dimension];
}
/**
* Returns the dimensionality of this HyperBoundingBox.
*
* @return the dimensionality of this HyperBoundingBox
*/
@Override
public int getDimensionality() {
return min.length;
}
/**
* Returns a String representation of the HyperBoundingBox.
*
* @return a string representation of this hyper bounding box
*/
@Override
public String toString() {
return "[Min(" + FormatUtil.format(min, ",", FormatUtil.NF8) + "), Max(" + FormatUtil.format(max, ",", FormatUtil.NF8) + ")]";
}
/**
* Returns a String representation of the HyperBoundingBox.
*
* @param nf number format for output accuracy
* @param pre the prefix of each line
* @return a string representation of this hyper bounding box
*/
public String toString(String pre, NumberFormat nf) {
return pre + "[Min(" + FormatUtil.format(min, ",", nf) + "), Max(" + FormatUtil.format(max, ",", nf) + ")]";
}
@Override
public boolean equals(Object obj) {
HyperBoundingBox box = (HyperBoundingBox) obj;
return Arrays.equals(min, box.min) && Arrays.equals(max, box.max);
}
@Override
public int hashCode() {
return 29 * Arrays.hashCode(min) + Arrays.hashCode(max);
}
/**
* The object implements the writeExternal method to save its contents by
* calling the methods of DataOutput for its primitive values or calling the
* writeObject method of ObjectOutput for objects, strings, and arrays.
*
* @param out the stream to write the object to
* @throws java.io.IOException Includes any I/O exceptions that may occur
* @serialData Overriding methods should use this tag to describe the data
* layout of this Externalizable object. List the sequence of
* element types and, if possible, relate the element to a
* public/protected field and/or method of this Externalizable
* class.
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
int dim = getDimensionality();
out.writeInt(dim);
for(double aMin : min) {
out.writeDouble(aMin);
}
for(double aMax : max) {
out.writeDouble(aMax);
}
}
/**
* The object implements the readExternal method to restore its contents by
* calling the methods of DataInput for primitive types and readObject for
* objects, strings and arrays. The readExternal method must read the values
* in the same sequence and with the same types as were written by
* writeExternal.
*
* @param in the stream to read data from in order to restore the object
* @throws java.io.IOException if I/O errors occur
* @throws ClassNotFoundException If the class for an object being restored
* cannot be found.
*/
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
int dim = in.readInt();
min = new double[dim];
max = new double[dim];
for(int i = 0; i < min.length; i++) {
min[i] = in.readDouble();
}
for(int i = 0; i < max.length; i++) {
max[i] = in.readDouble();
}
}
}