GeneralisedProcrustesAnalysis { public static PointList alignPoints(List<PointList> inputShapes, float threshold, int maxIters) { PointList reference = inputShapes.get(0); List<PointList> workingShapes = new ArrayList<PointList>(inputShapes); workingShapes.remove(reference); ProcrustesAnalysis referencePa = new ProcrustesAnalysis(reference, true); double referenceScaling = referencePa.scaling; Point2d referenceCog = referencePa.referenceCog; if (workingShapes.size() == 0) return reference; PointList mean = alignPointsAndAverage(workingShapes, reference, referenceScaling, referenceCog); while (ProcrustesAnalysis.computeProcrustesDistance(reference, mean) > threshold && maxIters-- >= 0) { reference = mean; mean = alignPointsAndAverage(inputShapes, reference, referenceScaling, referenceCog); } return mean; } GeneralisedProcrustesAnalysis(float threshold, int maxIters);  GeneralisedProcrustesAnalysis(float threshold); PointList align(List<PointList> shapes); static PointList alignPoints(List<PointList> inputShapes, float threshold, int maxIters);  }
@Test public void testAlignment() { Uniform rnd = new Uniform(new MersenneTwister(1)); List<PointList> shapes = new ArrayList<PointList>(); for (int i=0; i<10; i++) { shapes.add(randomTriangle(rnd)); } GeneralisedProcrustesAnalysis.alignPoints(shapes, 10f, 10000); }