package cz.fidentis.analyst.icp; import cz.fidentis.analyst.mesh.core.MeshPoint; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * Random undersampling when the mesh vertices to be removed are selected randomly. * * @author Radek Oslejsek */ public class RandomStrategy extends UndersamplingStrategy { /** * Constructor for PERCENTAGE undersampling type. * * @param perc Percentage - a value in (0.0, 1.0> * @throws IllegalArgumentException if the input parameter is wrong */ public RandomStrategy(double perc) { super(perc); } /** * Constructor for PERCENTAGE undersampling type. * * @param max Maximal number of vertices. Must be bigger than zero * @throws IllegalArgumentException if the input parameter is wrong */ public RandomStrategy(int max) { super(max); } @Override public List<MeshPoint> reduceMeshVertices(List<MeshPoint> meshPoints) { if (meshPoints == null) { return null; } int maxVertices = getMaxVertices(meshPoints.size()); if (meshPoints.size() <= maxVertices) { return meshPoints; } // generate randomly ordered indexes: List<Integer> range = IntStream.range(0, meshPoints.size()).boxed().collect(Collectors.toCollection(ArrayList::new)); Collections.shuffle(range); if (maxVertices < meshPoints.size()/2) { // copy indices MeshPoint[] array = new MeshPoint[meshPoints.size()]; range.stream().limit(maxVertices).forEach( i -> array[i] = meshPoints.get(i) ); return Arrays.stream(array).filter( p -> p != null ).collect(Collectors.<MeshPoint>toList()); } else { // remove indices List<MeshPoint> copy = new ArrayList<>(meshPoints); range.stream().limit(meshPoints.size()-maxVertices).forEach( i -> copy.set(i, null) ); return copy.parallelStream().filter( p -> p != null ).collect(Collectors.<MeshPoint>toList()); } } @Override public String toString() { return "random " + super.toString(); } }