1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.math.stat.clustering;
19
20import java.io.Serializable;
21import java.util.Collection;
22
23import org.apache.commons.math.util.MathUtils;
24
25/**
26 * A simple implementation of {@link Clusterable} for points with integer coordinates.
27 * @version $Revision: 1042376 $ $Date: 2010-12-05 16:54:55 +0100 (dim. 05 déc. 2010) $
28 * @since 2.0
29 */
30public class EuclideanIntegerPoint implements Clusterable<EuclideanIntegerPoint>, Serializable {
31
32    /** Serializable version identifier. */
33    private static final long serialVersionUID = 3946024775784901369L;
34
35    /** Point coordinates. */
36    private final int[] point;
37
38    /**
39     * Build an instance wrapping an integer array.
40     * <p>The wrapped array is referenced, it is <em>not</em> copied.</p>
41     * @param point the n-dimensional point in integer space
42     */
43    public EuclideanIntegerPoint(final int[] point) {
44        this.point = point;
45    }
46
47    /**
48     * Get the n-dimensional point in integer space.
49     * @return a reference (not a copy!) to the wrapped array
50     */
51    public int[] getPoint() {
52        return point;
53    }
54
55    /** {@inheritDoc} */
56    public double distanceFrom(final EuclideanIntegerPoint p) {
57        return MathUtils.distance(point, p.getPoint());
58    }
59
60    /** {@inheritDoc} */
61    public EuclideanIntegerPoint centroidOf(final Collection<EuclideanIntegerPoint> points) {
62        int[] centroid = new int[getPoint().length];
63        for (EuclideanIntegerPoint p : points) {
64            for (int i = 0; i < centroid.length; i++) {
65                centroid[i] += p.getPoint()[i];
66            }
67        }
68        for (int i = 0; i < centroid.length; i++) {
69            centroid[i] /= points.size();
70        }
71        return new EuclideanIntegerPoint(centroid);
72    }
73
74    /** {@inheritDoc} */
75    @Override
76    public boolean equals(final Object other) {
77        if (!(other instanceof EuclideanIntegerPoint)) {
78            return false;
79        }
80        final int[] otherPoint = ((EuclideanIntegerPoint) other).getPoint();
81        if (point.length != otherPoint.length) {
82            return false;
83        }
84        for (int i = 0; i < point.length; i++) {
85            if (point[i] != otherPoint[i]) {
86                return false;
87            }
88        }
89        return true;
90    }
91
92    /** {@inheritDoc} */
93    @Override
94    public int hashCode() {
95        int hashCode = 0;
96        for (Integer i : point) {
97            hashCode += i.hashCode() * 13 + 7;
98        }
99        return hashCode;
100    }
101
102    /**
103     * {@inheritDoc}
104     * @since 2.1
105     */
106    @Override
107    public String toString() {
108        final StringBuilder buff = new StringBuilder("(");
109        final int[] coordinates = getPoint();
110        for (int i = 0; i < coordinates.length; i++) {
111            buff.append(coordinates[i]);
112            if (i < coordinates.length - 1) {
113                buff.append(",");
114            }
115        }
116        buff.append(")");
117        return buff.toString();
118    }
119
120}
121