/*- * Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart * * This file is part of CityDoctor2. * * CityDoctor2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CityDoctor2 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with CityDoctor2. If not, see . */ package de.hft.stuttgart.citydoctor2.math; import java.util.List; /** * Utility class for calculating covariance matrices * * @author Matthias Betz * */ public class CovarianceMatrix { private CovarianceMatrix() { } /** * Calculates the covariance matrix of the given points, with the given expected * values. * * @param vertices the vertices for which the matrix is calculated * @param expected the expected values * @return the covariance 3 x 3 matrix */ public static double[][] calculateCovarianceMatrix(List vertices, double[] expected) { if (expected.length != 3) { throw new IllegalArgumentException("for 3D points 3 expected values have to be provided"); } double[][] covValues = new double[3][3]; for (Vector3d v : vertices) { double xdiff = v.getX() - expected[0]; double ydiff = v.getY() - expected[1]; double zdiff = v.getZ() - expected[2]; covValues[0][0] += xdiff * xdiff; covValues[0][1] += xdiff * ydiff; covValues[0][2] += xdiff * zdiff; covValues[1][1] += ydiff * ydiff; covValues[1][2] += ydiff * zdiff; covValues[2][2] += zdiff * zdiff; } covValues[0][0] /= vertices.size(); covValues[0][1] /= vertices.size(); covValues[0][2] /= vertices.size(); covValues[1][1] /= vertices.size(); covValues[1][2] /= vertices.size(); covValues[2][2] /= vertices.size(); // the covariance matrix is symmetric, so we can fill in the remaining values covValues[1][0] = covValues[0][1]; covValues[2][0] = covValues[0][2]; covValues[2][1] = covValues[1][2]; return covValues; } /** * see {@link CovarianceMatrix#calculateCovarianceMatrix(List, double[])} * * @param vertices the vertices for which the matrix is calculated * @param expected the expected values as a vector * @return the covariance 3 x 3 matrix */ public static double[][] calculateCovarianceMatrix(List vertices, Vector3d expected) { return calculateCovarianceMatrix(vertices, expected.getCoordinates()); } public static Vector3d getCentroid(List vertices) { if (vertices.isEmpty()) { throw new IllegalArgumentException("Vertices may not be empty to calculate centroid"); } // Move vertices to origin to avoid numeric instabilities Vector3d start = vertices.get(0); // get the center of all points double meanX = 0.0; double meanY = 0.0; double meanZ = 0.0; for (Vector3d v : vertices) { meanX += v.getX() - start.getX(); meanY += v.getY() - start.getY(); meanZ += v.getZ() - start.getZ(); } meanX = meanX / vertices.size() + start.getX(); meanY = meanY / vertices.size() + start.getY(); meanZ = meanZ / vertices.size() + start.getZ(); return new Vector3d(meanX, meanY, meanZ); } }