View Javadoc
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  
18  package org.apache.commons.math4.examples.sofm.tsp;
19  
20  import java.util.Arrays;
21  import java.util.Set;
22  import java.util.HashSet;
23  
24  /**
25   * A city, represented by a name and two-dimensional coordinates.
26   */
27  public class City {
28      /** Identifier. */
29      private final String name;
30      /** x-coordinate. */
31      private final double x;
32      /** y-coordinate. */
33      private final double y;
34  
35      /**
36       * @param name Name.
37       * @param x Cartesian x-coordinate.
38       * @param y Cartesian y-coordinate.
39       */
40      public City(String name,
41                  double x,
42                  double y) {
43          this.name = name;
44          this.x = x;
45          this.y = y;
46      }
47  
48      /**
49       * @return the name.
50       */
51      public String getName() {
52          return name;
53      }
54  
55      /**
56       * @return the (x, y) coordinates.
57       */
58      public double[] getCoordinates() {
59          return new double[] {x, y};
60      }
61  
62      /**
63       * Computes the distance between this city and
64       * the given point.
65       *
66       * @param x x-coordinate.
67       * @param y y-coordinate.
68       * @return the distance between {@code (x, y)} and this
69       * city.
70       */
71      public double distance(double x,
72                             double y) {
73          final double xDiff = this.x - x;
74          final double yDiff = this.y - y;
75  
76          return Math.sqrt(xDiff * xDiff + yDiff * yDiff);
77      }
78  
79      /**
80       * @param x x-coordinate.
81       * @param y y-coordinate.
82       * @param cities City list.
83       * @return the city whose coordinates are closest to {@code (x, y)}.
84       */
85      public static City closest(double x,
86                                 double y,
87                                 Set<City> cities) {
88          City closest = null;
89          double min = Double.POSITIVE_INFINITY;
90          for (final City c : cities) {
91              final double d = c.distance(x, y);
92              if (d < min) {
93                  min = d;
94                  closest = c;
95              }
96          }
97          return closest;
98      }
99  
100     /**
101      * Computes the barycentre of all city locations.
102      *
103      * @param cities City list.
104      * @return the barycentre.
105      */
106     public static double[] barycentre(Set<City> cities) {
107         double xB = 0;
108         double yB = 0;
109 
110         int count = 0;
111         for (final City c : cities) {
112             final double[] coord = c.getCoordinates();
113             xB += coord[0];
114             yB += coord[1];
115 
116             ++count;
117         }
118 
119         return new double[] {xB / count, yB / count};
120     }
121 
122     /**
123      * Computes the largest distance between the point at coordinates
124      * {@code (x, y)} and any of the cities.
125      *
126      * @param x x-coordinate.
127      * @param y y-coordinate.
128      * @param cities City list.
129      * @return the largest distance.
130      */
131     public static double largestDistance(double x,
132                                          double y,
133                                          Set<City> cities) {
134         double maxDist = 0;
135         for (final City c : cities) {
136             final double dist = c.distance(x, y);
137             if (dist > maxDist) {
138                 maxDist = dist;
139             }
140         }
141 
142         return maxDist;
143     }
144 
145     /**
146      * @param cities List of cities.
147      * @return a list with no duplicate city.
148      */
149     public static Set<City> unique(City[] cities) {
150         final Set<City> uniqueCities = new HashSet<>();
151         uniqueCities.addAll(Arrays.asList(cities));
152         return uniqueCities;
153     }
154 
155     /** {@inheritDoc} */
156     @Override
157     public boolean equals(Object o) {
158         if (o instanceof City) {
159             final City other = (City) o;
160             return x == other.x &&
161                 y == other.y;
162         }
163         return false;
164     }
165 
166     /** {@inheritDoc} */
167     @Override
168     public int hashCode() {
169         int result = 17;
170 
171         final long c1 = Double.doubleToLongBits(x);
172         result = 31 * result + (int) (c1 ^ (c1 >>> 32));
173 
174         final long c2 = Double.doubleToLongBits(y);
175         result = 31 * result + (int) (c2 ^ (c2 >>> 32));
176 
177         return result;
178     }
179 
180     /** {@inheritDoc} */
181     @Override
182     public String toString() {
183         return getName();
184     }
185 }