Loading Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +27 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import com.google.common.eventbus.EventBus; import cz.fidentis.analyst.Logger; import cz.fidentis.analyst.face.events.HumanFaceEvent; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.RelationToMesh; import cz.fidentis.analyst.feature.services.FeaturePointImportService; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshModel; Loading @@ -12,6 +13,7 @@ import cz.fidentis.analyst.mesh.io.MeshObjLoader; import cz.fidentis.analyst.octree.Octree; import cz.fidentis.analyst.symmetry.Plane; import cz.fidentis.analyst.visitors.face.HumanFaceVisitor; import cz.fidentis.analyst.visitors.kdtree.KdTreeApproxDistanceToTriangles; import cz.fidentis.analyst.visitors.mesh.BoundingBox; import cz.fidentis.analyst.visitors.mesh.BoundingBox.BBox; import cz.fidentis.analyst.visitors.mesh.CurvatureCalculator; Loading @@ -37,6 +39,7 @@ import java.util.Objects; * * @author Radek Oslejsek * @author Matej Kovar * @author Katerina Zarska */ public class HumanFace implements Serializable { Loading Loading @@ -94,6 +97,7 @@ public class HumanFace implements Serializable { if (landFile != null) { try { loadFeaturePoints(landFile.getAbsoluteFile().getParent(), landFile.getName()); setFeaturePointRelations(); } catch(IOException ex) { Logger.print(ex.toString()); } Loading Loading @@ -444,6 +448,29 @@ public class HumanFace implements Serializable { visitor.visitHumanFace(this); } /** * Sets the feature points relation to the mesh for all feature points */ protected void setFeaturePointRelations() { for (FeaturePoint fp : featurePoints) { if (fp.getRelationToMesh() == null){ fp.setRelationToMesh(computeFeaturePointRelation(fp)); } } } /** * Gets the feature points relation to the mesh - distance, nearest point, feature point position type * @param featurePoint * @return relation */ protected RelationToMesh computeFeaturePointRelation(FeaturePoint featurePoint) { KdTree kdTree = computeKdTree(false); KdTreeApproxDistanceToTriangles visitor = new KdTreeApproxDistanceToTriangles(featurePoint.getPosition(), true); kdTree.accept(visitor); return new RelationToMesh(visitor.getDistance(), visitor.getNearestPoints()); } @Override public int hashCode() { int hash = 7; Loading GUI/src/main/java/cz/fidentis/analyst/core/FaceTab.java +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ import cz.fidentis.analyst.registration.RegistrationAction; import cz.fidentis.analyst.scene.Camera; import cz.fidentis.analyst.symmetry.ProfilesAction; import cz.fidentis.analyst.symmetry.SymmetryAction; import cz.fidentis.analyst.featurepoints.FeaturePointsAction; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; Loading Loading @@ -109,6 +110,7 @@ public class FaceTab extends TopComponent { new CurvatureAction(getCanvas(), controlPanel); new SymmetryAction(getCanvas(), controlPanel); new ProfilesAction(getCanvas(), controlPanel); new FeaturePointsAction(getCanvas(), controlPanel); // Face State Panel for primary face FaceStatePanel facePanel = this.createFacePanelStateForFace(primary, project); Loading GUI/src/main/java/cz/fidentis/analyst/featurepoints/FeaturePointListPanel.java 0 → 100644 +199 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.featurepoints; import cz.fidentis.analyst.core.LoadedActionEvent; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.FeaturePointType; import cz.fidentis.analyst.feature.RelationToMesh; import cz.fidentis.analyst.scene.DrawableFeaturePoints; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.AbstractAction; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; /** * @author Katerina Zarska */ public class FeaturePointListPanel extends JPanel { public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_IN = "highlight hovered FP"; public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_OUT = "set default color of hovered FP"; public static final String ACTION_COMMAND_FEATURE_POINT_SELECT = "highlight feature point with color"; private List<JLabel> colorIndicators; private Map<RelationToMesh, JLabel> featurePointRelations; private List<JCheckBox> featurePointCheckBoxes; /** * Constructor. * * @param action Action listener * @param featurePoints List of all feature points */ public void initComponents(ActionListener action, DrawableFeaturePoints featurePoints) { setLayout(new GridBagLayout()); featurePointRelations = new HashMap<>(featurePoints.getFeaturePoints().size()); featurePointCheckBoxes = new ArrayList<>(featurePoints.getFeaturePoints().size()); colorIndicators = new ArrayList<>(featurePoints.getFeaturePoints().size()); for (int i = 0; i < featurePoints.getFeaturePoints().size(); i++) { //final FeaturePoint featurePoint = featurePoints.get(i); //final FeaturePointType featurePointType = featurePoint.getFeaturePointType(); //final RelationToMesh relation = featurePoint.getRelationToMesh(); //addRow(i, action, featurePointType, relation); addRow(i, action, featurePoints); } } /** * (De)selects feature points * * @param selected {@code true} if all feature point checkboxes are to be selected, * {@code false} otherwise */ public void selectFeaturePoints(List<FeaturePoint> featurePoints, List<FeaturePointType> selectedFeaturePoints, boolean selected) { for (int i = 0; i < featurePoints.size(); i++) { if (selectedFeaturePoints.contains(featurePoints.get(i).getFeaturePointType())) { featurePointCheckBoxes.get(i).setSelected(selected); } else { featurePointCheckBoxes.get(i).setSelected(!selected); } } } /** * (De)selects given feature point * * @param index Index of the feature point * @param selected {@code true} if a feature point checkbox is to be selected, * {@code false} otherwise */ public void selectFeaturePoint(int index, boolean selected) { if (index >= 0 && index < featurePointCheckBoxes.size()) { featurePointCheckBoxes.get(index).setSelected(selected); } } /** * Refreshes the panel * @param action * @param featurePoints */ public void refreshPanel(ActionListener action, DrawableFeaturePoints featurePoints, List<FeaturePointType> selectedFeaturePoints) { removeAll(); initComponents(action, featurePoints); revalidate(); repaint(); selectFeaturePoints(featurePoints.getFeaturePoints(), selectedFeaturePoints, true); } /** * Creates and returns action listener that can be connected with a low-level * GUI element (e.g., a button). Action event of triggered low-level element is * redirected to the given {@code action}. * The listener may also carry additional data as a payload. * * @param action Action listener * @param command Control panel command * @param data Payload data of the action listener * @return Action listener */ protected final ActionListener createListener(ActionListener action, String command, Object data) { return new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { action.actionPerformed(new LoadedActionEvent( e.getSource(), ActionEvent.ACTION_PERFORMED, command, data) ); } }; } protected void addRow(int row, ActionListener action, DrawableFeaturePoints featurePoints) {//FeaturePointType featurePointType, RelationToMesh relation) { FeaturePoint featurePoint = featurePoints.getFeaturePoints().get(row); Color color = DrawableFeaturePoints.OFF_THE_MESH_COLOR; if (featurePoint.getRelationToMesh().getPositionType() == RelationToMesh.FpPositionType.ON_THE_MESH) { color = DrawableFeaturePoints.ON_THE_MESH_COLOR; } else if (featurePoint.getRelationToMesh().getPositionType() == RelationToMesh.FpPositionType.CLOSE_TO_MESH) { color = DrawableFeaturePoints.CLOSE_TO_MESH_COLOR; } GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridx = 0; c.gridy = row; c.anchor = GridBagConstraints.LINE_START; c.fill = GridBagConstraints.NONE; GridBagConstraints c1 = new GridBagConstraints(); c1.insets = new Insets(0, 10, 0, 10); c1.gridwidth = GridBagConstraints.REMAINDER; c1.gridx = 1; c1.gridy = row; c1.anchor = GridBagConstraints.LINE_END; c1.fill = GridBagConstraints.NONE; JLabel label = new JLabel("⚫"); label.setForeground(color); add(label, c1); colorIndicators.add(label); JCheckBox checkBox = new JCheckBox(); checkBox.setText(featurePoint.getFeaturePointType().getName()); add(checkBox, c); featurePointCheckBoxes.add(checkBox); checkBox.addActionListener(createListener(action, ACTION_COMMAND_FEATURE_POINT_SELECT, row)); final int index = row; checkBox.addMouseListener(new MouseAdapter() { // highlight spheres on mouse hover @Override public void mouseEntered(MouseEvent e) { action.actionPerformed(new LoadedActionEvent( e.getSource(), ActionEvent.ACTION_PERFORMED, ACTION_COMMAND_FEATURE_POINT_HOVER_IN, index)); } @Override public void mouseExited(MouseEvent e) { action.actionPerformed(new LoadedActionEvent( e.getSource(), ActionEvent.ACTION_PERFORMED, ACTION_COMMAND_FEATURE_POINT_HOVER_OUT, index)); } }); // GridBagConstraints c2 = new GridBagConstraints(); // c2.gridwidth = GridBagConstraints.REMAINDER; // c2.gridx = 2; // c2.gridy = row; // c2.anchor = GridBagConstraints.LINE_END; // c2.fill = GridBagConstraints.NONE; // c2.insets = new Insets(0, 0, 0, 0); // // JLabel label2 = new JLabel(); // label2.setText(featurePoint.getRelationToMesh().getPositionTypeToString()); // label2.setVisible(true); // add(label2, c2); // featurePointRelations.put(featurePoint.getRelationToMesh(), label2); } } GUI/src/main/java/cz/fidentis/analyst/featurepoints/FeaturePointsAction.java 0 → 100644 +223 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.featurepoints; import cz.fidentis.analyst.canvas.Canvas; import cz.fidentis.analyst.core.ControlPanelAction; import cz.fidentis.analyst.core.DoubleSpinner; import cz.fidentis.analyst.core.LoadedActionEvent; import cz.fidentis.analyst.face.events.HumanFaceEvent; import cz.fidentis.analyst.face.events.HumanFaceListener; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.FeaturePointType; import cz.fidentis.analyst.feature.RelationToMesh; import java.awt.Color; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JTabbedPane; import javax.swing.JToggleButton; /** * * @author Katerina Zarska */ public class FeaturePointsAction extends ControlPanelAction implements HumanFaceListener { /* * GUI elements */ private FeaturePointType hoveredFeaturePoint = null; private final FeaturePointsPanel controlPanel; private List<FeaturePointType> selectedFeaturePoints = new ArrayList<>();; private static final Color FEATURE_POINT_HIGHLIGHT_COLOR = Color.MAGENTA; private static final Color FEATURE_POINT_HOVER_COLOR = Color.CYAN; /** * Constructor * @param canvas OpenGLCanvas * @param topControlPanel Top component for placing control panels */ public FeaturePointsAction(Canvas canvas, JTabbedPane topControlPanel) { super(canvas, topControlPanel); controlPanel = new FeaturePointsPanel(this, getPrimaryFeaturePoints()); // Place control panel to the topControlPanel topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel); topControlPanel.addChangeListener(e -> { // If the FeaturePoints panel is focused... if (((JTabbedPane) e.getSource()).getSelectedComponent() instanceof FeaturePointsPanel) { getCanvas().getScene().setDefaultColors(); } }); // Be informed about changes in faces perfomed by other GUI elements getPrimaryDrawableFace().getHumanFace().registerListener(this); if (getSecondaryDrawableFace() != null) { getSecondaryDrawableFace().getHumanFace().registerListener(this); } } @Override public void actionPerformed(ActionEvent ae) { String action = ae.getActionCommand(); switch (action) { case FeaturePointsPanel.ACTION_COMMAND_ADD_FEATURE_POINT: break; case FeaturePointsPanel.ACTION_COMMAND_REMOVE_FEATURE_POINT: workWithSelectedFp("remove"); controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); break; case FeaturePointsPanel.ACTION_COMMAND_EDIT_FEATURE_POINT: break; case FeaturePointsPanel.ACTION_COMMAND_EXPORT_FEATURE_POINTS: break; case FeaturePointsPanel.ACTION_COMMAND_LOAD_FEATURE_POINTS: break; case FeaturePointListPanel.ACTION_COMMAND_FEATURE_POINT_SELECT: selectFeaturePoint((LoadedActionEvent) ae); highlightSelectedFeaturePoints(); break; case FeaturePointListPanel.ACTION_COMMAND_FEATURE_POINT_HOVER_IN: hoverFeaturePoint((LoadedActionEvent) ae, true); break; case FeaturePointListPanel.ACTION_COMMAND_FEATURE_POINT_HOVER_OUT: hoverFeaturePoint((LoadedActionEvent) ae, false); break; case FeaturePointsPanel.ACTION_CHANGE_DISTANCE_THRESHOLD: changeDistanceThreshold(ae); break; case FeaturePointsPanel.ACTION_PIN_ALL_FEATURE_POINTS: for (FeaturePoint fp : getPrimaryFeaturePoints().getFeaturePoints()) { if (fp.getRelationToMesh().getDistance() != 0) { pinFeaturePointToMesh(fp); } } controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); break; case FeaturePointsPanel.ACTION_PIN_SELECTED_FEATURE_POINTS: workWithSelectedFp("pin"); controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); break; default: // do nothing } renderScene(); } /** * Changes the color of the face's feature point at the given index * and of its weighted representation when the cursor hovers over the feature point's name. * The index is received as the data payload of {@code actionEvent}. * * @param actionEvent Action event with the index of the feature point as its payload data * @param entered {@code true} if the cursor entered the feature point, * {@code false} if the cursor left the feature point */ private void hoverFeaturePoint(LoadedActionEvent actionEvent, boolean entered) { final int index = (int) actionEvent.getData(); if (entered) { // entering a feature point getPrimaryFeaturePoints().setColor(index, FEATURE_POINT_HOVER_COLOR); hoveredFeaturePoint = getTypeOfFeaturePoint(index); } else if (selectedFeaturePoints.contains(hoveredFeaturePoint)) { // leaving highlighted FP getPrimaryFeaturePoints().setColor(index, FEATURE_POINT_HIGHLIGHT_COLOR); } else { // leaving ordinary FP getPrimaryFeaturePoints().resetColorToDefault(index); } } /** * Returns type of the feature point at the given index. * * @param index Index of the feature point * @return Type of the feature point or {@code null} */ private FeaturePointType getTypeOfFeaturePoint(int index) { final List<FeaturePoint> featurePoints = getPrimaryFeaturePoints().getFeaturePoints(); if (index < 0 || index >= featurePoints.size()) { return null; } return featurePoints.get(index).getFeaturePointType(); } /** * Adds a point to selected feature points * * @param actionEvent LoadedActionEvent */ private void selectFeaturePoint(LoadedActionEvent actionEvent) { final int index = (int) actionEvent.getData(); final FeaturePointType fpType = getTypeOfFeaturePoint(index); if (((JToggleButton) actionEvent.getSource()).isSelected()) { selectedFeaturePoints.add(fpType); } else { selectedFeaturePoints.remove(fpType); } } private void highlightSelectedFeaturePoints() { if (selectedFeaturePoints.isEmpty()) { return; } for (int i = 0; i < getPrimaryFeaturePoints().getFeaturePoints().size(); i++) { if (selectedFeaturePoints.contains(getTypeOfFeaturePoint(i))) { getPrimaryFeaturePoints().setColor(i, FEATURE_POINT_HIGHLIGHT_COLOR); } else { getPrimaryFeaturePoints().resetColorToDefault(i); } } } private void workWithSelectedFp(String action) { if (selectedFeaturePoints.isEmpty()) { return; } for (int i = getPrimaryFeaturePoints().getFeaturePoints().size()-1; i >= 0; i--) { if (selectedFeaturePoints.contains(getTypeOfFeaturePoint(i))) { switch(action) { case "remove": getPrimaryFeaturePoints().resetColorToDefault(i); getPrimaryFeaturePoints().getFeaturePoints().remove(i); break; case "pin": pinFeaturePointToMesh(getPrimaryFeaturePoints().getFeaturePoints().get(i)); break; } } } } /** * Changes the distance threshold for categorizing feature points into either ON_THE_MESH or CLOSE_TO_MESH * * @param ae ActionEvent */ private void changeDistanceThreshold(ActionEvent ae) { double sliderVal = (Double) ((DoubleSpinner) ae.getSource()).getValue(); RelationToMesh.setDistanceThreshold(sliderVal); controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); } /** * Changes the feature point's position to the closest point on mesh * * @param fp feature point to be changed */ private void pinFeaturePointToMesh(FeaturePoint fp) { RelationToMesh relation = fp.getRelationToMesh(); if (relation.getPositionType() != RelationToMesh.FpPositionType.OFF_THE_MESH) { fp.setPosition(relation.getNearestPoint()); relation.setDistance(0); } } @Override public void acceptEvent(HumanFaceEvent event) { } } GUI/src/main/java/cz/fidentis/analyst/featurepoints/FeaturePointsPanel.form 0 → 100644 +160 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +27 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import com.google.common.eventbus.EventBus; import cz.fidentis.analyst.Logger; import cz.fidentis.analyst.face.events.HumanFaceEvent; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.RelationToMesh; import cz.fidentis.analyst.feature.services.FeaturePointImportService; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshModel; Loading @@ -12,6 +13,7 @@ import cz.fidentis.analyst.mesh.io.MeshObjLoader; import cz.fidentis.analyst.octree.Octree; import cz.fidentis.analyst.symmetry.Plane; import cz.fidentis.analyst.visitors.face.HumanFaceVisitor; import cz.fidentis.analyst.visitors.kdtree.KdTreeApproxDistanceToTriangles; import cz.fidentis.analyst.visitors.mesh.BoundingBox; import cz.fidentis.analyst.visitors.mesh.BoundingBox.BBox; import cz.fidentis.analyst.visitors.mesh.CurvatureCalculator; Loading @@ -37,6 +39,7 @@ import java.util.Objects; * * @author Radek Oslejsek * @author Matej Kovar * @author Katerina Zarska */ public class HumanFace implements Serializable { Loading Loading @@ -94,6 +97,7 @@ public class HumanFace implements Serializable { if (landFile != null) { try { loadFeaturePoints(landFile.getAbsoluteFile().getParent(), landFile.getName()); setFeaturePointRelations(); } catch(IOException ex) { Logger.print(ex.toString()); } Loading Loading @@ -444,6 +448,29 @@ public class HumanFace implements Serializable { visitor.visitHumanFace(this); } /** * Sets the feature points relation to the mesh for all feature points */ protected void setFeaturePointRelations() { for (FeaturePoint fp : featurePoints) { if (fp.getRelationToMesh() == null){ fp.setRelationToMesh(computeFeaturePointRelation(fp)); } } } /** * Gets the feature points relation to the mesh - distance, nearest point, feature point position type * @param featurePoint * @return relation */ protected RelationToMesh computeFeaturePointRelation(FeaturePoint featurePoint) { KdTree kdTree = computeKdTree(false); KdTreeApproxDistanceToTriangles visitor = new KdTreeApproxDistanceToTriangles(featurePoint.getPosition(), true); kdTree.accept(visitor); return new RelationToMesh(visitor.getDistance(), visitor.getNearestPoints()); } @Override public int hashCode() { int hash = 7; Loading
GUI/src/main/java/cz/fidentis/analyst/core/FaceTab.java +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ import cz.fidentis.analyst.registration.RegistrationAction; import cz.fidentis.analyst.scene.Camera; import cz.fidentis.analyst.symmetry.ProfilesAction; import cz.fidentis.analyst.symmetry.SymmetryAction; import cz.fidentis.analyst.featurepoints.FeaturePointsAction; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; Loading Loading @@ -109,6 +110,7 @@ public class FaceTab extends TopComponent { new CurvatureAction(getCanvas(), controlPanel); new SymmetryAction(getCanvas(), controlPanel); new ProfilesAction(getCanvas(), controlPanel); new FeaturePointsAction(getCanvas(), controlPanel); // Face State Panel for primary face FaceStatePanel facePanel = this.createFacePanelStateForFace(primary, project); Loading
GUI/src/main/java/cz/fidentis/analyst/featurepoints/FeaturePointListPanel.java 0 → 100644 +199 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.featurepoints; import cz.fidentis.analyst.core.LoadedActionEvent; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.FeaturePointType; import cz.fidentis.analyst.feature.RelationToMesh; import cz.fidentis.analyst.scene.DrawableFeaturePoints; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.AbstractAction; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; /** * @author Katerina Zarska */ public class FeaturePointListPanel extends JPanel { public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_IN = "highlight hovered FP"; public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_OUT = "set default color of hovered FP"; public static final String ACTION_COMMAND_FEATURE_POINT_SELECT = "highlight feature point with color"; private List<JLabel> colorIndicators; private Map<RelationToMesh, JLabel> featurePointRelations; private List<JCheckBox> featurePointCheckBoxes; /** * Constructor. * * @param action Action listener * @param featurePoints List of all feature points */ public void initComponents(ActionListener action, DrawableFeaturePoints featurePoints) { setLayout(new GridBagLayout()); featurePointRelations = new HashMap<>(featurePoints.getFeaturePoints().size()); featurePointCheckBoxes = new ArrayList<>(featurePoints.getFeaturePoints().size()); colorIndicators = new ArrayList<>(featurePoints.getFeaturePoints().size()); for (int i = 0; i < featurePoints.getFeaturePoints().size(); i++) { //final FeaturePoint featurePoint = featurePoints.get(i); //final FeaturePointType featurePointType = featurePoint.getFeaturePointType(); //final RelationToMesh relation = featurePoint.getRelationToMesh(); //addRow(i, action, featurePointType, relation); addRow(i, action, featurePoints); } } /** * (De)selects feature points * * @param selected {@code true} if all feature point checkboxes are to be selected, * {@code false} otherwise */ public void selectFeaturePoints(List<FeaturePoint> featurePoints, List<FeaturePointType> selectedFeaturePoints, boolean selected) { for (int i = 0; i < featurePoints.size(); i++) { if (selectedFeaturePoints.contains(featurePoints.get(i).getFeaturePointType())) { featurePointCheckBoxes.get(i).setSelected(selected); } else { featurePointCheckBoxes.get(i).setSelected(!selected); } } } /** * (De)selects given feature point * * @param index Index of the feature point * @param selected {@code true} if a feature point checkbox is to be selected, * {@code false} otherwise */ public void selectFeaturePoint(int index, boolean selected) { if (index >= 0 && index < featurePointCheckBoxes.size()) { featurePointCheckBoxes.get(index).setSelected(selected); } } /** * Refreshes the panel * @param action * @param featurePoints */ public void refreshPanel(ActionListener action, DrawableFeaturePoints featurePoints, List<FeaturePointType> selectedFeaturePoints) { removeAll(); initComponents(action, featurePoints); revalidate(); repaint(); selectFeaturePoints(featurePoints.getFeaturePoints(), selectedFeaturePoints, true); } /** * Creates and returns action listener that can be connected with a low-level * GUI element (e.g., a button). Action event of triggered low-level element is * redirected to the given {@code action}. * The listener may also carry additional data as a payload. * * @param action Action listener * @param command Control panel command * @param data Payload data of the action listener * @return Action listener */ protected final ActionListener createListener(ActionListener action, String command, Object data) { return new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { action.actionPerformed(new LoadedActionEvent( e.getSource(), ActionEvent.ACTION_PERFORMED, command, data) ); } }; } protected void addRow(int row, ActionListener action, DrawableFeaturePoints featurePoints) {//FeaturePointType featurePointType, RelationToMesh relation) { FeaturePoint featurePoint = featurePoints.getFeaturePoints().get(row); Color color = DrawableFeaturePoints.OFF_THE_MESH_COLOR; if (featurePoint.getRelationToMesh().getPositionType() == RelationToMesh.FpPositionType.ON_THE_MESH) { color = DrawableFeaturePoints.ON_THE_MESH_COLOR; } else if (featurePoint.getRelationToMesh().getPositionType() == RelationToMesh.FpPositionType.CLOSE_TO_MESH) { color = DrawableFeaturePoints.CLOSE_TO_MESH_COLOR; } GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridx = 0; c.gridy = row; c.anchor = GridBagConstraints.LINE_START; c.fill = GridBagConstraints.NONE; GridBagConstraints c1 = new GridBagConstraints(); c1.insets = new Insets(0, 10, 0, 10); c1.gridwidth = GridBagConstraints.REMAINDER; c1.gridx = 1; c1.gridy = row; c1.anchor = GridBagConstraints.LINE_END; c1.fill = GridBagConstraints.NONE; JLabel label = new JLabel("⚫"); label.setForeground(color); add(label, c1); colorIndicators.add(label); JCheckBox checkBox = new JCheckBox(); checkBox.setText(featurePoint.getFeaturePointType().getName()); add(checkBox, c); featurePointCheckBoxes.add(checkBox); checkBox.addActionListener(createListener(action, ACTION_COMMAND_FEATURE_POINT_SELECT, row)); final int index = row; checkBox.addMouseListener(new MouseAdapter() { // highlight spheres on mouse hover @Override public void mouseEntered(MouseEvent e) { action.actionPerformed(new LoadedActionEvent( e.getSource(), ActionEvent.ACTION_PERFORMED, ACTION_COMMAND_FEATURE_POINT_HOVER_IN, index)); } @Override public void mouseExited(MouseEvent e) { action.actionPerformed(new LoadedActionEvent( e.getSource(), ActionEvent.ACTION_PERFORMED, ACTION_COMMAND_FEATURE_POINT_HOVER_OUT, index)); } }); // GridBagConstraints c2 = new GridBagConstraints(); // c2.gridwidth = GridBagConstraints.REMAINDER; // c2.gridx = 2; // c2.gridy = row; // c2.anchor = GridBagConstraints.LINE_END; // c2.fill = GridBagConstraints.NONE; // c2.insets = new Insets(0, 0, 0, 0); // // JLabel label2 = new JLabel(); // label2.setText(featurePoint.getRelationToMesh().getPositionTypeToString()); // label2.setVisible(true); // add(label2, c2); // featurePointRelations.put(featurePoint.getRelationToMesh(), label2); } }
GUI/src/main/java/cz/fidentis/analyst/featurepoints/FeaturePointsAction.java 0 → 100644 +223 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.featurepoints; import cz.fidentis.analyst.canvas.Canvas; import cz.fidentis.analyst.core.ControlPanelAction; import cz.fidentis.analyst.core.DoubleSpinner; import cz.fidentis.analyst.core.LoadedActionEvent; import cz.fidentis.analyst.face.events.HumanFaceEvent; import cz.fidentis.analyst.face.events.HumanFaceListener; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.FeaturePointType; import cz.fidentis.analyst.feature.RelationToMesh; import java.awt.Color; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JTabbedPane; import javax.swing.JToggleButton; /** * * @author Katerina Zarska */ public class FeaturePointsAction extends ControlPanelAction implements HumanFaceListener { /* * GUI elements */ private FeaturePointType hoveredFeaturePoint = null; private final FeaturePointsPanel controlPanel; private List<FeaturePointType> selectedFeaturePoints = new ArrayList<>();; private static final Color FEATURE_POINT_HIGHLIGHT_COLOR = Color.MAGENTA; private static final Color FEATURE_POINT_HOVER_COLOR = Color.CYAN; /** * Constructor * @param canvas OpenGLCanvas * @param topControlPanel Top component for placing control panels */ public FeaturePointsAction(Canvas canvas, JTabbedPane topControlPanel) { super(canvas, topControlPanel); controlPanel = new FeaturePointsPanel(this, getPrimaryFeaturePoints()); // Place control panel to the topControlPanel topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel); topControlPanel.addChangeListener(e -> { // If the FeaturePoints panel is focused... if (((JTabbedPane) e.getSource()).getSelectedComponent() instanceof FeaturePointsPanel) { getCanvas().getScene().setDefaultColors(); } }); // Be informed about changes in faces perfomed by other GUI elements getPrimaryDrawableFace().getHumanFace().registerListener(this); if (getSecondaryDrawableFace() != null) { getSecondaryDrawableFace().getHumanFace().registerListener(this); } } @Override public void actionPerformed(ActionEvent ae) { String action = ae.getActionCommand(); switch (action) { case FeaturePointsPanel.ACTION_COMMAND_ADD_FEATURE_POINT: break; case FeaturePointsPanel.ACTION_COMMAND_REMOVE_FEATURE_POINT: workWithSelectedFp("remove"); controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); break; case FeaturePointsPanel.ACTION_COMMAND_EDIT_FEATURE_POINT: break; case FeaturePointsPanel.ACTION_COMMAND_EXPORT_FEATURE_POINTS: break; case FeaturePointsPanel.ACTION_COMMAND_LOAD_FEATURE_POINTS: break; case FeaturePointListPanel.ACTION_COMMAND_FEATURE_POINT_SELECT: selectFeaturePoint((LoadedActionEvent) ae); highlightSelectedFeaturePoints(); break; case FeaturePointListPanel.ACTION_COMMAND_FEATURE_POINT_HOVER_IN: hoverFeaturePoint((LoadedActionEvent) ae, true); break; case FeaturePointListPanel.ACTION_COMMAND_FEATURE_POINT_HOVER_OUT: hoverFeaturePoint((LoadedActionEvent) ae, false); break; case FeaturePointsPanel.ACTION_CHANGE_DISTANCE_THRESHOLD: changeDistanceThreshold(ae); break; case FeaturePointsPanel.ACTION_PIN_ALL_FEATURE_POINTS: for (FeaturePoint fp : getPrimaryFeaturePoints().getFeaturePoints()) { if (fp.getRelationToMesh().getDistance() != 0) { pinFeaturePointToMesh(fp); } } controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); break; case FeaturePointsPanel.ACTION_PIN_SELECTED_FEATURE_POINTS: workWithSelectedFp("pin"); controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); break; default: // do nothing } renderScene(); } /** * Changes the color of the face's feature point at the given index * and of its weighted representation when the cursor hovers over the feature point's name. * The index is received as the data payload of {@code actionEvent}. * * @param actionEvent Action event with the index of the feature point as its payload data * @param entered {@code true} if the cursor entered the feature point, * {@code false} if the cursor left the feature point */ private void hoverFeaturePoint(LoadedActionEvent actionEvent, boolean entered) { final int index = (int) actionEvent.getData(); if (entered) { // entering a feature point getPrimaryFeaturePoints().setColor(index, FEATURE_POINT_HOVER_COLOR); hoveredFeaturePoint = getTypeOfFeaturePoint(index); } else if (selectedFeaturePoints.contains(hoveredFeaturePoint)) { // leaving highlighted FP getPrimaryFeaturePoints().setColor(index, FEATURE_POINT_HIGHLIGHT_COLOR); } else { // leaving ordinary FP getPrimaryFeaturePoints().resetColorToDefault(index); } } /** * Returns type of the feature point at the given index. * * @param index Index of the feature point * @return Type of the feature point or {@code null} */ private FeaturePointType getTypeOfFeaturePoint(int index) { final List<FeaturePoint> featurePoints = getPrimaryFeaturePoints().getFeaturePoints(); if (index < 0 || index >= featurePoints.size()) { return null; } return featurePoints.get(index).getFeaturePointType(); } /** * Adds a point to selected feature points * * @param actionEvent LoadedActionEvent */ private void selectFeaturePoint(LoadedActionEvent actionEvent) { final int index = (int) actionEvent.getData(); final FeaturePointType fpType = getTypeOfFeaturePoint(index); if (((JToggleButton) actionEvent.getSource()).isSelected()) { selectedFeaturePoints.add(fpType); } else { selectedFeaturePoints.remove(fpType); } } private void highlightSelectedFeaturePoints() { if (selectedFeaturePoints.isEmpty()) { return; } for (int i = 0; i < getPrimaryFeaturePoints().getFeaturePoints().size(); i++) { if (selectedFeaturePoints.contains(getTypeOfFeaturePoint(i))) { getPrimaryFeaturePoints().setColor(i, FEATURE_POINT_HIGHLIGHT_COLOR); } else { getPrimaryFeaturePoints().resetColorToDefault(i); } } } private void workWithSelectedFp(String action) { if (selectedFeaturePoints.isEmpty()) { return; } for (int i = getPrimaryFeaturePoints().getFeaturePoints().size()-1; i >= 0; i--) { if (selectedFeaturePoints.contains(getTypeOfFeaturePoint(i))) { switch(action) { case "remove": getPrimaryFeaturePoints().resetColorToDefault(i); getPrimaryFeaturePoints().getFeaturePoints().remove(i); break; case "pin": pinFeaturePointToMesh(getPrimaryFeaturePoints().getFeaturePoints().get(i)); break; } } } } /** * Changes the distance threshold for categorizing feature points into either ON_THE_MESH or CLOSE_TO_MESH * * @param ae ActionEvent */ private void changeDistanceThreshold(ActionEvent ae) { double sliderVal = (Double) ((DoubleSpinner) ae.getSource()).getValue(); RelationToMesh.setDistanceThreshold(sliderVal); controlPanel.getFeaturePointListPanel().refreshPanel(this, getPrimaryFeaturePoints(), selectedFeaturePoints); } /** * Changes the feature point's position to the closest point on mesh * * @param fp feature point to be changed */ private void pinFeaturePointToMesh(FeaturePoint fp) { RelationToMesh relation = fp.getRelationToMesh(); if (relation.getPositionType() != RelationToMesh.FpPositionType.OFF_THE_MESH) { fp.setPosition(relation.getNearestPoint()); relation.setDistance(0); } } @Override public void acceptEvent(HumanFaceEvent event) { } }
GUI/src/main/java/cz/fidentis/analyst/featurepoints/FeaturePointsPanel.form 0 → 100644 +160 −0 File added.Preview size limit exceeded, changes collapsed. Show changes