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 }