Newer
Older
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package cz.fidentis.analyst.procrustes;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.feature.FeaturePoint;
import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.mesh.core.MeshPoint;
import cz.fidentis.analyst.procrustes.utils.ProcrustesAnalysisUtils;
import org.ejml.simple.SimpleMatrix;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Holds important face attributes that are required for procrustes analysis.
*
* @author Jakub Kolman
*/
public class ProcrustesAnalysisFaceModel {
private final HumanFace humanFace;
private HashMap<Integer, FeaturePoint> featurePointsMap; // sorted by feature point type
private List<MeshPoint> vertices;
private SimpleMatrix verticesMatrix;
private MeshModel meshModel;
private final HashMap<Integer, Integer> featurePointTypeCorrespondence;
public ProcrustesAnalysisFaceModel(HumanFace face) {
// getFeaturePoints() returns unmodifiable List. To sort it we need to make copy first
List<FeaturePoint> modifiableFeaturePointList = new ArrayList<>(face.getFeaturePoints());
// To be able to move vertices we have to make a copy of them because getFacets() returns unmodifiable List
List<MeshPoint> modifiableVertices = new ArrayList<>(face.getMeshModel().getFacets().get(0).getVertices());
this.vertices = modifiableVertices;
this.meshModel = face.getMeshModel();
this.featurePointsMap = createFeaturePointMap(
ProcrustesAnalysisUtils.sortListByFeaturePointType(modifiableFeaturePointList));
this.featurePointTypeCorrespondence = createFeaturePointTypeCorrespondence(face.getFeaturePoints());
this.verticesMatrix = ProcrustesAnalysisUtils.createMatrixFromList(modifiableVertices);
// this.featurePointMatrix = ProcrustesAnalysisUtils.createMatrixFromList(modifiableFeaturePointList);
/**
* sets feature points map and also sets feature point on human face for visualisation
*
* @param featurePointsMap
*/
public void setFeaturePointsMap(HashMap<Integer, FeaturePoint> featurePointsMap) {
this.featurePointsMap = featurePointsMap;
this.humanFace.setFeaturePoints(getFeaturePointValues());
public MeshModel getMeshModel() {
return meshModel;
}
public List<FeaturePoint> getFeaturePointValues() {
return new ArrayList<>(this.getFeaturePointsMap().values());
}
public List<MeshPoint> getVertices() {
return vertices;
}
public HashMap<Integer, FeaturePoint> getFeaturePointsMap() {
return featurePointsMap;
}
/**
* sets vertices map and also sets feature point on human face for visualisation
*
* @param verticesMatrix
*/
public void setVerticesMatrix(SimpleMatrix verticesMatrix) {
this.verticesMatrix = verticesMatrix;
changeVerticesValues(verticesMatrix);
}
public SimpleMatrix getVerticesMatrix() {
return verticesMatrix;
}
private void changeVerticesValues(SimpleMatrix matrix) {
for (int i = 0; i < vertices.size(); i++) {
vertices.get(i).getPosition().x = (float) matrix.get(i, 0);
vertices.get(i).getPosition().y = (float) matrix.get(i, 1);
vertices.get(i).getPosition().z = (float) matrix.get(i, 2);
}
}
private HashMap<Integer, FeaturePoint> createFeaturePointMap(List<FeaturePoint> featurePointList) {
HashMap<Integer, FeaturePoint> map = new HashMap<>();
for (FeaturePoint fp: featurePointList) {
map.put(fp.getFeaturePointType().getType(), fp);
}
return map;
}
public HashMap<Integer, Integer> getFeaturePointTypeCorrespondence() {
return featurePointTypeCorrespondence;
}
/**
* Creates corresponding key value pair of matrix row index and a feature point type value.
* It is used in {@link cz.fidentis.analyst.procrustes.utils.ProcrustesAnalysisUtils#createFeaturePointMapFromMatrix}
* so we can get back type of feature point after working with matrices where the type is not stored,
* but instead are used matrix indexes.
*
* @param fpList
* @return
*/
private HashMap<Integer, Integer> createFeaturePointTypeCorrespondence(List<FeaturePoint> fpList) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < fpList.size(); i++) {
map.put(i, fpList.get(i).getFeaturePointType().getType());
}
return map;
}