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